]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #7521 from donaldsharp/set_src_future_us
[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[];
36235319 99const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json);
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
DS
210 e = *extra;
211 if (e->damp_info)
a935f597
DA
212 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
213 e->damp_info->safi);
d62a17ae 214
c93a3b77
DS
215 e->damp_info = NULL;
216 if (e->parent) {
40381db7 217 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 218
40381db7 219 if (bpi->net) {
0e70e6c8
DL
220 /* FIXME: since multiple e may have the same e->parent
221 * and e->parent->net is holding a refcount for each
222 * of them, we need to do some fudging here.
223 *
40381db7
DS
224 * WARNING: if bpi->net->lock drops to 0, bpi may be
225 * freed as well (because bpi->net was holding the
226 * last reference to bpi) => write after free!
0e70e6c8
DL
227 */
228 unsigned refcount;
229
40381db7 230 bpi = bgp_path_info_lock(bpi);
c10e14e9 231 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 232 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 233 if (!refcount)
40381db7
DS
234 bpi->net = NULL;
235 bgp_path_info_unlock(bpi);
0e70e6c8 236 }
18ee8310 237 bgp_path_info_unlock(e->parent);
c93a3b77 238 e->parent = NULL;
d62a17ae 239 }
c93a3b77
DS
240
241 if (e->bgp_orig)
242 bgp_unlock(e->bgp_orig);
c26edcda 243
ff3bf9a4
DS
244 if (e->aggr_suppressors)
245 list_delete(&e->aggr_suppressors);
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. */
40381db7 1507 ret = route_map_apply(rmap, p, RMAP_BGP, &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. */
40381db7 1558 ret = route_map_apply(rmap, p, RMAP_BGP, &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))
1839 zlog_debug(
1840 "subgrpannouncecheck: community filter check fail");
3dc339cd 1841 return false;
d62a17ae 1842 }
3f9c7369 1843
d62a17ae 1844 /* If the attribute has originator-id and it is same as remote
1845 peer's id. */
40381db7
DS
1846 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1847 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1848 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1849 zlog_debug(
8228a9a7
DS
1850 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1851 onlypeer->host, p);
3dc339cd 1852 return false;
d62a17ae 1853 }
3f9c7369 1854
d62a17ae 1855 /* ORF prefix-list filter check */
1856 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1857 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1858 || CHECK_FLAG(peer->af_cap[afi][safi],
1859 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1860 if (peer->orf_plist[afi][safi]) {
1861 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1862 == PREFIX_DENY) {
1863 if (bgp_debug_update(NULL, p,
1864 subgrp->update_group, 0))
1865 zlog_debug(
8228a9a7
DS
1866 "%s [Update:SEND] %pFX is filtered via ORF",
1867 peer->host, p);
3dc339cd 1868 return false;
d62a17ae 1869 }
1870 }
1871
1872 /* Output filter check. */
40381db7 1873 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1874 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1875 zlog_debug("%s [Update:SEND] %pFX is filtered",
1876 peer->host, p);
3dc339cd 1877 return false;
d62a17ae 1878 }
3f9c7369 1879
d62a17ae 1880 /* AS path loop check. */
2b31007c
RZ
1881 if (onlypeer && onlypeer->as_path_loop_detection
1882 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1883 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1884 zlog_debug(
3efd0893 1885 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 1886 onlypeer->host, onlypeer->as);
3dc339cd 1887 return false;
d62a17ae 1888 }
3f9c7369 1889
d62a17ae 1890 /* If we're a CONFED we need to loop check the CONFED ID too */
1891 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1892 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1893 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1894 zlog_debug(
3efd0893 1895 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 1896 peer->host, bgp->confed_id);
3dc339cd 1897 return false;
d62a17ae 1898 }
3f9c7369 1899 }
3f9c7369 1900
d62a17ae 1901 /* Route-Reflect check. */
1902 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1903 reflect = 1;
1904 else
1905 reflect = 0;
1906
1907 /* IBGP reflection check. */
1908 if (reflect && !samepeer_safe) {
1909 /* A route from a Client peer. */
1910 if (CHECK_FLAG(from->af_flags[afi][safi],
1911 PEER_FLAG_REFLECTOR_CLIENT)) {
1912 /* Reflect to all the Non-Client peers and also to the
1913 Client peers other than the originator. Originator
1914 check
1915 is already done. So there is noting to do. */
1916 /* no bgp client-to-client reflection check. */
892fedb6
DA
1917 if (CHECK_FLAG(bgp->flags,
1918 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 1919 if (CHECK_FLAG(peer->af_flags[afi][safi],
1920 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1921 return false;
d62a17ae 1922 } else {
1923 /* A route from a Non-client peer. Reflect to all other
1924 clients. */
1925 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1926 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1927 return false;
d62a17ae 1928 }
1929 }
3f9c7369 1930
d62a17ae 1931 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1932 *attr = *piattr;
d62a17ae 1933
1934 /* If local-preference is not set. */
1935 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1936 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1937 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1938 attr->local_pref = bgp->default_local_pref;
3f9c7369 1939 }
3f9c7369 1940
d62a17ae 1941 /* If originator-id is not set and the route is to be reflected,
1942 set the originator id */
1943 if (reflect
1944 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1945 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1946 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1947 }
3f9c7369 1948
d62a17ae 1949 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1950 */
1951 if (peer->sort == BGP_PEER_EBGP
1952 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1953 if (from != bgp->peer_self && !transparent
1954 && !CHECK_FLAG(peer->af_flags[afi][safi],
1955 PEER_FLAG_MED_UNCHANGED))
1956 attr->flag &=
1957 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1958 }
3f9c7369 1959
d62a17ae 1960 /* Since the nexthop attribute can vary per peer, it is not explicitly
1961 * set
1962 * in announce check, only certain flags and length (or number of
1963 * nexthops
1964 * -- for IPv6/MP_REACH) are set here in order to guide the update
1965 * formation
1966 * code in setting the nexthop(s) on a per peer basis in
1967 * reformat_peer().
1968 * Typically, the source nexthop in the attribute is preserved but in
1969 * the
1970 * scenarios where we know it will always be overwritten, we reset the
1971 * nexthop to "0" in an attempt to achieve better Update packing. An
1972 * example of this is when a prefix from each of 2 IBGP peers needs to
1973 * be
1974 * announced to an EBGP peer (and they have the same attributes barring
1975 * their nexthop).
1976 */
1977 if (reflect)
1978 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1979
1980#define NEXTHOP_IS_V6 \
1981 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1982 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1983 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1984 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1985
1986 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1987 * if
1988 * the peer (group) is configured to receive link-local nexthop
1989 * unchanged
c728d027
DA
1990 * and it is available in the prefix OR we're not reflecting the route,
1991 * link-local nexthop address is valid and
d62a17ae 1992 * the peer (group) to whom we're going to announce is on a shared
1993 * network
1994 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
1995 * By checking if nexthop LL address is valid we are sure that
1996 * we do not announce LL address as `::`.
d62a17ae 1997 */
1998 if (NEXTHOP_IS_V6) {
1999 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2000 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2001 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2002 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
2003 || (!reflect
2004 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2005 && peer->shared_network
d62a17ae 2006 && (from == bgp->peer_self
2007 || peer->sort == BGP_PEER_EBGP))) {
2008 attr->mp_nexthop_len =
2009 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2010 }
3f9c7369 2011
d62a17ae 2012 /* Clear off link-local nexthop in source, whenever it is not
2013 * needed to
2014 * ensure more prefixes share the same attribute for
2015 * announcement.
2016 */
2017 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2018 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2019 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2020 }
3f9c7369 2021
d62a17ae 2022 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2023 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2024
2025 /* Route map & unsuppress-map apply. */
7f7940e6 2026 if (!skip_rmap_check
e73c112e 2027 && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2028 struct bgp_path_info rmap_path = {0};
2029 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2030 struct attr dummy_attr = {0};
d62a17ae 2031
e34291b8 2032 /* Fill temp path_info */
9bcb3eef
DS
2033 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2034 pi, peer, attr);
16f7ce2b 2035
d62a17ae 2036 /* don't confuse inbound and outbound setting */
2037 RESET_FLAG(attr->rmap_change_flags);
2038
2039 /*
2040 * The route reflector is not allowed to modify the attributes
2041 * of the reflected IBGP routes unless explicitly allowed.
2042 */
2043 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2044 && !CHECK_FLAG(bgp->flags,
2045 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2046 dummy_attr = *attr;
40381db7 2047 rmap_path.attr = &dummy_attr;
d62a17ae 2048 }
3f9c7369 2049
d62a17ae 2050 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2051
4056a5f6 2052 if (bgp_path_suppressed(pi))
d62a17ae 2053 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
40381db7 2054 RMAP_BGP, &rmap_path);
d62a17ae 2055 else
2056 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
40381db7 2057 RMAP_BGP, &rmap_path);
d62a17ae 2058
2059 peer->rmap_type = 0;
2060
2061 if (ret == RMAP_DENYMATCH) {
778048bf 2062 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2063 zlog_debug(
2064 "%s [Update:SEND] %pFX is filtered by route-map",
2065 peer->host, p);
778048bf 2066
d62a17ae 2067 bgp_attr_flush(attr);
3dc339cd 2068 return false;
d62a17ae 2069 }
3f9c7369 2070 }
3f9c7369 2071
9dac9fc8
DA
2072 /* RFC 8212 to prevent route leaks.
2073 * This specification intends to improve this situation by requiring the
2074 * explicit configuration of both BGP Import and Export Policies for any
2075 * External BGP (EBGP) session such as customers, peers, or
2076 * confederation boundaries for all enabled address families. Through
2077 * codification of the aforementioned requirement, operators will
2078 * benefit from consistent behavior across different BGP
2079 * implementations.
2080 */
1d3fdccf 2081 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
9dac9fc8 2082 if (!bgp_outbound_policy_exists(peer, filter))
3dc339cd 2083 return false;
9dac9fc8 2084
fb29348a
DA
2085 /* draft-ietf-idr-deprecate-as-set-confed-set
2086 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2087 * Eventually, This document (if approved) updates RFC 4271
2088 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2089 * and obsoletes RFC 6472.
2090 */
7f972cd8 2091 if (peer->bgp->reject_as_sets)
fb29348a 2092 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2093 return false;
fb29348a 2094
33d022bc
DA
2095 /* Codification of AS 0 Processing */
2096 if (aspath_check_as_zero(attr->aspath))
e2369003 2097 return false;
33d022bc 2098
637e5ba4 2099 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2100 if (peer->sort == BGP_PEER_IBGP
2101 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2102 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2103 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2104 } else {
2105 bgp_attr_add_gshut_community(attr);
2106 }
2107 }
2108
d62a17ae 2109 /* After route-map has been applied, we check to see if the nexthop to
2110 * be carried in the attribute (that is used for the announcement) can
2111 * be cleared off or not. We do this in all cases where we would be
2112 * setting the nexthop to "ourselves". For IPv6, we only need to
2113 * consider
2114 * the global nexthop here; the link-local nexthop would have been
2115 * cleared
2116 * already, and if not, it is required by the update formation code.
2117 * Also see earlier comments in this function.
2118 */
2119 /*
2120 * If route-map has performed some operation on the nexthop or the peer
2121 * configuration says to pass it unchanged, we cannot reset the nexthop
2122 * here, so only attempt to do it if these aren't true. Note that the
2123 * route-map handler itself might have cleared the nexthop, if for
2124 * example,
2125 * it is configured as 'peer-address'.
2126 */
2127 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2128 piattr->rmap_change_flags)
d62a17ae 2129 && !transparent
2130 && !CHECK_FLAG(peer->af_flags[afi][safi],
2131 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2132 /* We can reset the nexthop, if setting (or forcing) it to
2133 * 'self' */
2134 if (CHECK_FLAG(peer->af_flags[afi][safi],
2135 PEER_FLAG_NEXTHOP_SELF)
2136 || CHECK_FLAG(peer->af_flags[afi][safi],
2137 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2138 if (!reflect
2139 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2140 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2141 subgroup_announce_reset_nhop(
2142 (peer_cap_enhe(peer, afi, safi)
2143 ? AF_INET6
2144 : p->family),
2145 attr);
7b651a32 2146 nh_reset = true;
2147 }
d62a17ae 2148 } else if (peer->sort == BGP_PEER_EBGP) {
2149 /* Can also reset the nexthop if announcing to EBGP, but
2150 * only if
2151 * no peer in the subgroup is on a shared subnet.
2152 * Note: 3rd party nexthop currently implemented for
2153 * IPv4 only.
2154 */
737af885
BS
2155 if ((p->family == AF_INET) &&
2156 (!bgp_subgrp_multiaccess_check_v4(
2157 piattr->nexthop,
7b651a32 2158 subgrp, from))) {
d62a17ae 2159 subgroup_announce_reset_nhop(
2160 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2161 ? AF_INET6
2162 : p->family),
737af885 2163 attr);
7b651a32 2164 nh_reset = true;
2165 }
737af885
BS
2166
2167 if ((p->family == AF_INET6) &&
2168 (!bgp_subgrp_multiaccess_check_v6(
2169 piattr->mp_nexthop_global,
7b651a32 2170 subgrp, from))) {
737af885
BS
2171 subgroup_announce_reset_nhop(
2172 (peer_cap_enhe(peer, afi, safi)
2173 ? AF_INET6
2174 : p->family),
2175 attr);
7b651a32 2176 nh_reset = true;
2177 }
737af885
BS
2178
2179
2180
40381db7 2181 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2182 /*
2183 * This flag is used for leaked vpn-vrf routes
2184 */
2185 int family = p->family;
2186
2187 if (peer_cap_enhe(peer, afi, safi))
2188 family = AF_INET6;
2189
2190 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2191 zlog_debug(
1defdda8 2192 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2193 __func__, family2str(family));
2194 subgroup_announce_reset_nhop(family, attr);
7b651a32 2195 nh_reset = true;
d62a17ae 2196 }
63696f1d 2197 }
960035b2 2198
63696f1d 2199 /* If IPv6/MP and nexthop does not have any override and happens
2200 * to
2201 * be a link-local address, reset it so that we don't pass along
2202 * the
2203 * source's link-local IPv6 address to recipients who may not be
2204 * on
2205 * the same interface.
2206 */
2207 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2208 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2209 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2210 nh_reset = true;
2211 }
d62a17ae 2212 }
3f9c7369 2213
7b651a32 2214 /*
2215 * When the next hop is set to ourselves, if all multipaths have
2216 * link-bandwidth announce the cumulative bandwidth as that makes
2217 * the most sense. However, don't modify if the link-bandwidth has
2218 * been explicitly set by user policy.
2219 */
2220 if (nh_reset &&
f7e1c681 2221 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2222 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2223 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2224 attr->ecommunity = ecommunity_replace_linkbw(
2225 bgp->as, attr->ecommunity, cum_bw);
2226
3dc339cd 2227 return true;
3f9c7369
DS
2228}
2229
f009ff26 2230static int bgp_route_select_timer_expire(struct thread *thread)
2231{
2232 struct afi_safi_info *info;
2233 afi_t afi;
2234 safi_t safi;
2235 struct bgp *bgp;
2236
2237 info = THREAD_ARG(thread);
2238 afi = info->afi;
2239 safi = info->safi;
2240 bgp = info->bgp;
2241
2242 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2243 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2244 safi);
f009ff26 2245
2246 bgp->gr_info[afi][safi].t_route_select = NULL;
2247
2248 XFREE(MTYPE_TMP, info);
2249
2250 /* Best path selection */
2251 return bgp_best_path_select_defer(bgp, afi, safi);
2252}
2253
9bcb3eef 2254void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2255 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2256 struct bgp_path_info_pair *result, afi_t afi,
2257 safi_t safi)
2258{
2259 struct bgp_path_info *new_select;
2260 struct bgp_path_info *old_select;
40381db7
DS
2261 struct bgp_path_info *pi;
2262 struct bgp_path_info *pi1;
2263 struct bgp_path_info *pi2;
2264 struct bgp_path_info *nextpi = NULL;
d62a17ae 2265 int paths_eq, do_mpath, debug;
2266 struct list mp_list;
2267 char pfx_buf[PREFIX2STR_BUFFER];
2268 char path_buf[PATH_ADDPATH_STR_BUFFER];
2269
2270 bgp_mp_list_init(&mp_list);
2271 do_mpath =
2272 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2273
9bcb3eef 2274 debug = bgp_debug_bestpath(dest);
d62a17ae 2275
2276 if (debug)
9bcb3eef 2277 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2278
9bcb3eef 2279 dest->reason = bgp_path_selection_none;
d62a17ae 2280 /* bgp deterministic-med */
2281 new_select = NULL;
892fedb6 2282 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2283
1defdda8 2284 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2285 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2286 pi1 = pi1->next)
9bcb3eef 2287 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2288 BGP_PATH_DMED_SELECTED);
d62a17ae 2289
9bcb3eef 2290 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2291 pi1 = pi1->next) {
40381db7 2292 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2293 continue;
40381db7 2294 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2295 continue;
ea8b2282 2296 if (pi1->peer != bgp->peer_self)
40381db7 2297 if (pi1->peer->status != Established)
d62a17ae 2298 continue;
2299
40381db7
DS
2300 new_select = pi1;
2301 if (pi1->next) {
2302 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2303 if (CHECK_FLAG(pi2->flags,
1defdda8 2304 BGP_PATH_DMED_CHECK))
d62a17ae 2305 continue;
40381db7 2306 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2307 continue;
ea8b2282 2308 if (pi2->peer != bgp->peer_self
d62a17ae 2309 && !CHECK_FLAG(
ea8b2282
DS
2310 pi2->peer->sflags,
2311 PEER_STATUS_NSF_WAIT))
40381db7 2312 if (pi2->peer->status
d62a17ae 2313 != Established)
2314 continue;
2315
121e245d
DS
2316 if (!aspath_cmp_left(pi1->attr->aspath,
2317 pi2->attr->aspath)
2318 && !aspath_cmp_left_confed(
40381db7 2319 pi1->attr->aspath,
121e245d
DS
2320 pi2->attr->aspath))
2321 continue;
d62a17ae 2322
121e245d
DS
2323 if (bgp_path_info_cmp(
2324 bgp, pi2, new_select,
2325 &paths_eq, mpath_cfg, debug,
fdf81fa0 2326 pfx_buf, afi, safi,
9bcb3eef 2327 &dest->reason)) {
121e245d 2328 bgp_path_info_unset_flag(
9bcb3eef 2329 dest, new_select,
121e245d
DS
2330 BGP_PATH_DMED_SELECTED);
2331 new_select = pi2;
d62a17ae 2332 }
121e245d
DS
2333
2334 bgp_path_info_set_flag(
9bcb3eef 2335 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2336 }
2337 }
9bcb3eef 2338 bgp_path_info_set_flag(dest, new_select,
18ee8310 2339 BGP_PATH_DMED_CHECK);
9bcb3eef 2340 bgp_path_info_set_flag(dest, new_select,
18ee8310 2341 BGP_PATH_DMED_SELECTED);
d62a17ae 2342
2343 if (debug) {
18ee8310
DS
2344 bgp_path_info_path_with_addpath_rx_str(
2345 new_select, path_buf);
8228a9a7
DS
2346 zlog_debug(
2347 "%pBD: %s is the bestpath from AS %u",
2348 dest, path_buf,
2349 aspath_get_first_as(
2350 new_select->attr->aspath));
d62a17ae 2351 }
2352 }
2353 }
96450faf 2354
d62a17ae 2355 /* Check old selected route and new selected route. */
2356 old_select = NULL;
2357 new_select = NULL;
9bcb3eef 2358 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2359 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2360 enum bgp_path_selection_reason reason;
2361
40381db7
DS
2362 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2363 old_select = pi;
d62a17ae 2364
40381db7 2365 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2366 /* reap REMOVED routes, if needs be
2367 * selected route must stay for a while longer though
2368 */
40381db7
DS
2369 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2370 && (pi != old_select))
9bcb3eef 2371 bgp_path_info_reap(dest, pi);
d62a17ae 2372
ddb5b488 2373 if (debug)
40381db7
DS
2374 zlog_debug("%s: pi %p in holddown", __func__,
2375 pi);
ddb5b488 2376
d62a17ae 2377 continue;
2378 }
96450faf 2379
40381db7
DS
2380 if (pi->peer && pi->peer != bgp->peer_self
2381 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2382 if (pi->peer->status != Established) {
ddb5b488
PZ
2383
2384 if (debug)
2385 zlog_debug(
40381db7
DS
2386 "%s: pi %p non self peer %s not estab state",
2387 __func__, pi, pi->peer->host);
ddb5b488 2388
d62a17ae 2389 continue;
ddb5b488 2390 }
9fbdd100 2391
892fedb6 2392 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2393 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2394 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2395 if (debug)
40381db7 2396 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2397 continue;
2398 }
9fbdd100 2399
9bcb3eef 2400 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2401
9bcb3eef 2402 reason = dest->reason;
40381db7 2403 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2404 debug, pfx_buf, afi, safi,
2405 &dest->reason)) {
19ea4cec
DS
2406 if (new_select == NULL &&
2407 reason != bgp_path_selection_none)
9bcb3eef 2408 dest->reason = reason;
40381db7 2409 new_select = pi;
d62a17ae 2410 }
2411 }
718e3744 2412
d62a17ae 2413 /* Now that we know which path is the bestpath see if any of the other
2414 * paths
2415 * qualify as multipaths
2416 */
2417 if (debug) {
2418 if (new_select)
18ee8310
DS
2419 bgp_path_info_path_with_addpath_rx_str(new_select,
2420 path_buf);
d62a17ae 2421 else
772270f3 2422 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2423 zlog_debug(
8228a9a7
DS
2424 "%pBD: After path selection, newbest is %s oldbest was %s",
2425 dest, path_buf,
d62a17ae 2426 old_select ? old_select->peer->host : "NONE");
96450faf 2427 }
9fbdd100 2428
d62a17ae 2429 if (do_mpath && new_select) {
9bcb3eef 2430 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2431 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2432
2433 if (debug)
18ee8310 2434 bgp_path_info_path_with_addpath_rx_str(
40381db7 2435 pi, path_buf);
d62a17ae 2436
40381db7 2437 if (pi == new_select) {
d62a17ae 2438 if (debug)
2439 zlog_debug(
8228a9a7
DS
2440 "%pBD: %s is the bestpath, add to the multipath list",
2441 dest, path_buf);
40381db7 2442 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2443 continue;
2444 }
2445
40381db7 2446 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2447 continue;
2448
40381db7
DS
2449 if (pi->peer && pi->peer != bgp->peer_self
2450 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2451 PEER_STATUS_NSF_WAIT))
40381db7 2452 if (pi->peer->status != Established)
d62a17ae 2453 continue;
2454
40381db7 2455 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2456 if (debug)
2457 zlog_debug(
8228a9a7
DS
2458 "%pBD: %s has the same nexthop as the bestpath, skip it",
2459 dest, path_buf);
d62a17ae 2460 continue;
2461 }
2462
40381db7 2463 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2464 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2465 &dest->reason);
d62a17ae 2466
2467 if (paths_eq) {
2468 if (debug)
2469 zlog_debug(
8228a9a7
DS
2470 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2471 dest, path_buf);
40381db7 2472 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2473 }
2474 }
2475 }
fee0f4c6 2476
9bcb3eef 2477 bgp_path_info_mpath_update(dest, new_select, old_select, &mp_list,
18ee8310
DS
2478 mpath_cfg);
2479 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2480 bgp_mp_list_clear(&mp_list);
96450faf 2481
9bcb3eef 2482 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2483
d62a17ae 2484 result->old = old_select;
2485 result->new = new_select;
96450faf 2486
d62a17ae 2487 return;
fee0f4c6 2488}
2489
3f9c7369
DS
2490/*
2491 * A new route/change in bestpath of an existing route. Evaluate the path
2492 * for advertisement to the subgroup.
2493 */
3dc339cd
DA
2494void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2495 struct bgp_path_info *selected,
9bcb3eef 2496 struct bgp_dest *dest,
3dc339cd 2497 uint32_t addpath_tx_id)
d62a17ae 2498{
b54892e0 2499 const struct prefix *p;
d62a17ae 2500 struct peer *onlypeer;
2501 struct attr attr;
2502 afi_t afi;
2503 safi_t safi;
a77e2f4b
S
2504 struct bgp *bgp;
2505 bool advertise;
adbac85e 2506
9bcb3eef 2507 p = bgp_dest_get_prefix(dest);
d62a17ae 2508 afi = SUBGRP_AFI(subgrp);
2509 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2510 bgp = SUBGRP_INST(subgrp);
d62a17ae 2511 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2512 : NULL);
2513
2dbe669b
DA
2514 if (BGP_DEBUG(update, UPDATE_OUT))
2515 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2516
d62a17ae 2517 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2518 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2519 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2520 return;
d62a17ae 2521
2522 memset(&attr, 0, sizeof(struct attr));
2523 /* It's initialized in bgp_announce_check() */
2524
a77e2f4b
S
2525 /* Announcement to the subgroup. If the route is filtered withdraw it.
2526 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2527 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2528 * route
d62a17ae 2529 */
a77e2f4b
S
2530 advertise = bgp_check_advertise(bgp, dest);
2531
d62a17ae 2532 if (selected) {
7f7940e6 2533 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
a77e2f4b
S
2534 false)) {
2535 /* Route is selected, if the route is already installed
2536 * in FIB, then it is advertised
2537 */
2538 if (advertise)
2539 bgp_adj_out_set_subgroup(dest, subgrp, &attr,
2540 selected);
2541 } else
9bcb3eef 2542 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2543 addpath_tx_id);
d62a17ae 2544 }
2545
2546 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2547 else {
9bcb3eef 2548 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2549 }
200df115 2550}
fee0f4c6 2551
3064bf43 2552/*
e1072051 2553 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2554 * This is called at the end of route processing.
3064bf43 2555 */
9bcb3eef 2556void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2557{
40381db7 2558 struct bgp_path_info *pi;
3064bf43 2559
9bcb3eef 2560 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2561 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2562 continue;
40381db7
DS
2563 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2564 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2565 }
3064bf43 2566}
2567
2568/*
2569 * Has the route changed from the RIB's perspective? This is invoked only
2570 * if the route selection returns the same best route as earlier - to
2571 * determine if we need to update zebra or not.
2572 */
9bcb3eef 2573bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2574{
4b7e6066 2575 struct bgp_path_info *mpinfo;
d62a17ae 2576
2bb9eff4
DS
2577 /* If this is multipath, check all selected paths for any nexthop
2578 * change or attribute change. Some attribute changes (e.g., community)
2579 * aren't of relevance to the RIB, but we'll update zebra to ensure
2580 * we handle the case of BGP nexthop change. This is the behavior
2581 * when the best path has an attribute change anyway.
d62a17ae 2582 */
1defdda8 2583 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2584 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2585 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2586 return true;
d62a17ae 2587
2bb9eff4
DS
2588 /*
2589 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2590 */
18ee8310
DS
2591 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2592 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2593 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2594 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2595 return true;
d62a17ae 2596 }
3064bf43 2597
d62a17ae 2598 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2599 return false;
3064bf43 2600}
2601
d62a17ae 2602struct bgp_process_queue {
2603 struct bgp *bgp;
9bcb3eef 2604 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2605#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2606 unsigned int flags;
2607 unsigned int queued;
200df115 2608};
2609
3b0c17e1 2610static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2611 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2612 struct bgp_path_info *new_select,
2613 struct bgp_path_info *old_select)
2614{
9bcb3eef 2615 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2616
2617 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2618 return;
2619
2620 if (advertise_type5_routes(bgp, afi) && new_select
2621 && is_route_injectable_into_evpn(new_select)) {
2622
2623 /* apply the route-map */
2624 if (bgp->adv_cmd_rmap[afi][safi].map) {
2625 route_map_result_t ret;
2626 struct bgp_path_info rmap_path;
2627 struct bgp_path_info_extra rmap_path_extra;
2628 struct attr dummy_attr;
2629
2630 dummy_attr = *new_select->attr;
2631
2632 /* Fill temp path_info */
9bcb3eef 2633 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2634 new_select, new_select->peer,
2635 &dummy_attr);
2636
2637 RESET_FLAG(dummy_attr.rmap_change_flags);
2638
2639 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
2640 p, RMAP_BGP, &rmap_path);
2641
2642 if (ret == RMAP_DENYMATCH) {
2643 bgp_attr_flush(&dummy_attr);
2644 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2645 safi);
2646 } else
2647 bgp_evpn_advertise_type5_route(
2648 bgp, p, &dummy_attr, afi, safi);
2649 } else {
2650 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2651 afi, safi);
2652 }
2653 } else if (advertise_type5_routes(bgp, afi) && old_select
2654 && is_route_injectable_into_evpn(old_select))
2655 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2656}
2657
3103e8d2
DS
2658/*
2659 * old_select = The old best path
2660 * new_select = the new best path
2661 *
2662 * if (!old_select && new_select)
2663 * We are sending new information on.
2664 *
2665 * if (old_select && new_select) {
2666 * if (new_select != old_select)
2667 * We have a new best path send a change
2668 * else
2669 * We've received a update with new attributes that needs
2670 * to be passed on.
2671 * }
2672 *
2673 * if (old_select && !new_select)
2674 * We have no eligible route that we can announce or the rn
2675 * is being removed.
2676 */
9bcb3eef 2677static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2678 afi_t afi, safi_t safi)
d62a17ae 2679{
4b7e6066
DS
2680 struct bgp_path_info *new_select;
2681 struct bgp_path_info *old_select;
2682 struct bgp_path_info_pair old_and_new;
ddb5b488 2683 int debug = 0;
d62a17ae 2684
892fedb6 2685 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2686 if (dest)
2687 debug = bgp_debug_bestpath(dest);
b54892e0 2688 if (debug)
f4c713ae 2689 zlog_debug(
56ca3b5b 2690 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2691 __func__, dest);
f4c713ae
LB
2692 return;
2693 }
d62a17ae 2694 /* Is it end of initial update? (after startup) */
9bcb3eef 2695 if (!dest) {
d62a17ae 2696 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2697 sizeof(bgp->update_delay_zebra_resume_time));
2698
2699 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2700 FOREACH_AFI_SAFI (afi, safi) {
2701 if (bgp_fibupd_safi(safi))
2702 bgp_zebra_announce_table(bgp, afi, safi);
2703 }
d62a17ae 2704 bgp->main_peers_update_hold = 0;
2705
2706 bgp_start_routeadv(bgp);
aac24838 2707 return;
d62a17ae 2708 }
cb1faec9 2709
9bcb3eef 2710 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2711
9bcb3eef 2712 debug = bgp_debug_bestpath(dest);
b54892e0 2713 if (debug)
56ca3b5b 2714 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__, dest,
ddb5b488 2715 afi2str(afi), safi2str(safi));
ddb5b488 2716
f009ff26 2717 /* The best path calculation for the route is deferred if
2718 * BGP_NODE_SELECT_DEFER is set
2719 */
9bcb3eef 2720 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2721 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2722 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2723 return;
2724 }
2725
d62a17ae 2726 /* Best path selection. */
9bcb3eef 2727 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2728 afi, safi);
2729 old_select = old_and_new.old;
2730 new_select = old_and_new.new;
2731
2732 /* Do we need to allocate or free labels?
2733 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2734 * necessary to do this upon changes to best path. Exceptions:
2735 * - label index has changed -> recalculate resulting label
2736 * - path_info sub_type changed -> switch to/from implicit-null
2737 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2738 */
318cac96 2739 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2740 if (new_select) {
2741 if (!old_select
2742 || bgp_label_index_differs(new_select, old_select)
57592a53 2743 || new_select->sub_type != old_select->sub_type
9bcb3eef 2744 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2745 /* Enforced penultimate hop popping:
2746 * implicit-null for local routes, aggregate
2747 * and redistributed routes
2748 */
d62a17ae 2749 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2750 || new_select->sub_type
2751 == BGP_ROUTE_AGGREGATE
2752 || new_select->sub_type
2753 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2754 if (CHECK_FLAG(
9bcb3eef 2755 dest->flags,
d62a17ae 2756 BGP_NODE_REGISTERED_FOR_LABEL))
9bcb3eef 2757 bgp_unregister_for_label(dest);
70e98a7f 2758 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2759 &dest->local_label);
2760 bgp_set_valid_label(&dest->local_label);
d62a17ae 2761 } else
9bcb3eef
DS
2762 bgp_register_for_label(dest,
2763 new_select);
d62a17ae 2764 }
9bcb3eef 2765 } else if (CHECK_FLAG(dest->flags,
a4d82a8a 2766 BGP_NODE_REGISTERED_FOR_LABEL)) {
9bcb3eef 2767 bgp_unregister_for_label(dest);
318cac96 2768 }
9bcb3eef
DS
2769 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
2770 bgp_unregister_for_label(dest);
d62a17ae 2771 }
cd1964ff 2772
b54892e0 2773 if (debug)
ddb5b488 2774 zlog_debug(
56ca3b5b 2775 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
9bcb3eef 2776 __func__, dest, afi2str(afi), safi2str(safi),
ddb5b488 2777 old_select, new_select);
ddb5b488 2778
d62a17ae 2779 /* If best route remains the same and this is not due to user-initiated
2780 * clear, see exactly what needs to be done.
2781 */
d62a17ae 2782 if (old_select && old_select == new_select
9bcb3eef 2783 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2784 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2785 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2786 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2787#ifdef ENABLE_BGP_VNC
d62a17ae 2788 vnc_import_bgp_add_route(bgp, p, old_select);
2789 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2790#endif
bb744275 2791 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2792 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2793
2794 if (new_select->type == ZEBRA_ROUTE_BGP
2795 && (new_select->sub_type == BGP_ROUTE_NORMAL
2796 || new_select->sub_type
2797 == BGP_ROUTE_IMPORTED))
2798
9bcb3eef 2799 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
2800 bgp, afi, safi);
2801 }
d62a17ae 2802 }
d62a17ae 2803
2804 /* If there is a change of interest to peers, reannounce the
2805 * route. */
1defdda8 2806 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 2807 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
2808 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2809 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2810
2811 /* unicast routes must also be annouced to
2812 * labeled-unicast update-groups */
2813 if (safi == SAFI_UNICAST)
2814 group_announce_route(bgp, afi,
9bcb3eef 2815 SAFI_LABELED_UNICAST, dest,
d62a17ae 2816 new_select);
2817
1defdda8 2818 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 2819 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 2820 }
fee0f4c6 2821
3b0c17e1 2822 /* advertise/withdraw type-5 routes */
2823 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2824 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2825 bgp_process_evpn_route_injection(
9bcb3eef 2826 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 2827
b1875e65 2828 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2829 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
2830 bgp_zebra_clear_route_change_flags(dest);
2831 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2832 return;
d62a17ae 2833 }
8ad7271d 2834
d62a17ae 2835 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2836 */
9bcb3eef 2837 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 2838
2839 /* bestpath has changed; bump version */
2840 if (old_select || new_select) {
9bcb3eef 2841 bgp_bump_version(dest);
d62a17ae 2842
2843 if (!bgp->t_rmap_def_originate_eval) {
2844 bgp_lock(bgp);
2845 thread_add_timer(
2846 bm->master,
2847 update_group_refresh_default_originate_route_map,
2848 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2849 &bgp->t_rmap_def_originate_eval);
2850 }
2851 }
3f9c7369 2852
d62a17ae 2853 if (old_select)
9bcb3eef 2854 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 2855 if (new_select) {
ddb5b488
PZ
2856 if (debug)
2857 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
2858 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2859 bgp_path_info_unset_flag(dest, new_select,
2860 BGP_PATH_ATTR_CHANGED);
1defdda8 2861 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 2862 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 2863 }
338b3424 2864
49e5a4a0 2865#ifdef ENABLE_BGP_VNC
d62a17ae 2866 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2867 if (old_select != new_select) {
2868 if (old_select) {
2869 vnc_import_bgp_exterior_del_route(bgp, p,
2870 old_select);
2871 vnc_import_bgp_del_route(bgp, p, old_select);
2872 }
2873 if (new_select) {
2874 vnc_import_bgp_exterior_add_route(bgp, p,
2875 new_select);
2876 vnc_import_bgp_add_route(bgp, p, new_select);
2877 }
2878 }
2879 }
65efcfce
LB
2880#endif
2881
9bcb3eef 2882 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2883
2884 /* unicast routes must also be annouced to labeled-unicast update-groups
2885 */
2886 if (safi == SAFI_UNICAST)
9bcb3eef 2887 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 2888 new_select);
2889
2890 /* FIB update. */
2891 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2892 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2893 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2894 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2895 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2896 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2897
2898 /* if this is an evpn imported type-5 prefix,
2899 * we need to withdraw the route first to clear
2900 * the nh neigh and the RMAC entry.
2901 */
2902 if (old_select &&
2903 is_route_parent_evpn(old_select))
2904 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2905
9bcb3eef 2906 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 2907 } else {
d62a17ae 2908 /* Withdraw the route from the kernel. */
2909 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2910 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2911 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2912 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2913
568e10ca 2914 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2915 }
718e3744 2916 }
3064bf43 2917
9bcb3eef 2918 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 2919 old_select);
5424b7ba 2920
d62a17ae 2921 /* Clear any route change flags. */
9bcb3eef 2922 bgp_zebra_clear_route_change_flags(dest);
3064bf43 2923
18ee8310 2924 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2925 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 2926 bgp_path_info_reap(dest, old_select);
d62a17ae 2927
9bcb3eef 2928 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2929 return;
718e3744 2930}
2931
f009ff26 2932/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2933int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2934{
9bcb3eef 2935 struct bgp_dest *dest;
f009ff26 2936 int cnt = 0;
2937 struct afi_safi_info *thread_info;
f009ff26 2938
56c226e7
DS
2939 if (bgp->gr_info[afi][safi].t_route_select) {
2940 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
2941
2942 thread_info = THREAD_ARG(t);
2943 XFREE(MTYPE_TMP, thread_info);
f009ff26 2944 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 2945 }
f009ff26 2946
2947 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
2948 zlog_debug("%s: processing route for %s : cnt %d", __func__,
2949 get_afi_safi_str(afi, safi, false),
26742171 2950 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 2951 }
2952
2953 /* Process the route list */
6338d242
DS
2954 for (dest = bgp_table_top(bgp->rib[afi][safi]);
2955 dest && bgp->gr_info[afi][safi].gr_deferred != 0;
26742171
DS
2956 dest = bgp_route_next(dest)) {
2957 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
2958 continue;
2959
2960 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
2961 bgp->gr_info[afi][safi].gr_deferred--;
2962 bgp_process_main_one(bgp, dest, afi, safi);
2963 cnt++;
2964 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT) {
2965 bgp_dest_unlock_node(dest);
2966 break;
f009ff26 2967 }
f009ff26 2968 }
2969
9e3b51a7 2970 /* Send EOR message when all routes are processed */
6338d242 2971 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 2972 bgp_send_delayed_eor(bgp);
8c48b3b6 2973 /* Send route processing complete message to RIB */
2974 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 2975 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 2976 return 0;
9e3b51a7 2977 }
f009ff26 2978
2979 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 2980
2981 thread_info->afi = afi;
2982 thread_info->safi = safi;
2983 thread_info->bgp = bgp;
2984
2985 /* If there are more routes to be processed, start the
2986 * selection timer
2987 */
2988 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
2989 BGP_ROUTE_SELECT_DELAY,
2990 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 2991 return 0;
2992}
2993
aac24838 2994static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 2995{
aac24838
JB
2996 struct bgp_process_queue *pqnode = data;
2997 struct bgp *bgp = pqnode->bgp;
d62a17ae 2998 struct bgp_table *table;
9bcb3eef 2999 struct bgp_dest *dest;
aac24838
JB
3000
3001 /* eoiu marker */
3002 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3003 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3004 /* should always have dedicated wq call */
3005 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3006 return WQ_SUCCESS;
3007 }
3008
ac021f40 3009 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3010 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3011 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3012 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3013 table = bgp_dest_table(dest);
3014 /* note, new DESTs may be added as part of processing */
3015 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3016
9bcb3eef 3017 bgp_dest_unlock_node(dest);
d62a17ae 3018 bgp_table_unlock(table);
3019 }
aac24838
JB
3020
3021 return WQ_SUCCESS;
3022}
3023
3024static void bgp_processq_del(struct work_queue *wq, void *data)
3025{
3026 struct bgp_process_queue *pqnode = data;
3027
3028 bgp_unlock(pqnode->bgp);
3029
3030 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3031}
3032
b6c386bb 3033void bgp_process_queue_init(struct bgp *bgp)
200df115 3034{
b6c386bb
DS
3035 if (!bgp->process_queue) {
3036 char name[BUFSIZ];
3037
3038 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3039 bgp->process_queue = work_queue_new(bm->master, name);
3040 }
3041
3042 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3043 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3044 bgp->process_queue->spec.max_retries = 0;
3045 bgp->process_queue->spec.hold = 50;
d62a17ae 3046 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3047 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3048}
3049
cfe8d15a 3050static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3051{
3052 struct bgp_process_queue *pqnode;
3053
a4d82a8a
PZ
3054 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3055 sizeof(struct bgp_process_queue));
aac24838
JB
3056
3057 /* unlocked in bgp_processq_del */
3058 pqnode->bgp = bgp_lock(bgp);
3059 STAILQ_INIT(&pqnode->pqueue);
3060
aac24838
JB
3061 return pqnode;
3062}
3063
9bcb3eef 3064void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3065{
aac24838 3066#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3067 struct work_queue *wq = bgp->process_queue;
d62a17ae 3068 struct bgp_process_queue *pqnode;
cfe8d15a 3069 int pqnode_reuse = 0;
495f0b13 3070
d62a17ae 3071 /* already scheduled for processing? */
9bcb3eef 3072 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3073 return;
2e02b9b2 3074
f009ff26 3075 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3076 * the workqueue
3077 */
9bcb3eef 3078 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3079 if (BGP_DEBUG(update, UPDATE_OUT))
3080 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3081 dest);
f009ff26 3082 return;
3083 }
3084
aac24838 3085 if (wq == NULL)
d62a17ae 3086 return;
3087
aac24838 3088 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3089 limit only if is from the same BGP view and it's not an EOIU marker
3090 */
aac24838
JB
3091 if (work_queue_item_count(wq)) {
3092 struct work_queue_item *item = work_queue_last_item(wq);
3093 pqnode = item->data;
228da428 3094
a4d82a8a
PZ
3095 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3096 || pqnode->bgp != bgp
3097 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3098 pqnode = bgp_processq_alloc(bgp);
3099 else
3100 pqnode_reuse = 1;
aac24838 3101 } else
cfe8d15a 3102 pqnode = bgp_processq_alloc(bgp);
aac24838 3103 /* all unlocked in bgp_process_wq */
9bcb3eef 3104 bgp_table_lock(bgp_dest_table(dest));
aac24838 3105
9bcb3eef
DS
3106 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3107 bgp_dest_lock_node(dest);
aac24838 3108
60466a63 3109 /* can't be enqueued twice */
9bcb3eef
DS
3110 assert(STAILQ_NEXT(dest, pq) == NULL);
3111 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3112 pqnode->queued++;
3113
cfe8d15a
LB
3114 if (!pqnode_reuse)
3115 work_queue_add(wq, pqnode);
3116
d62a17ae 3117 return;
fee0f4c6 3118}
0a486e5f 3119
d62a17ae 3120void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3121{
d62a17ae 3122 struct bgp_process_queue *pqnode;
cb1faec9 3123
b6c386bb 3124 if (bgp->process_queue == NULL)
d62a17ae 3125 return;
2e02b9b2 3126
cfe8d15a 3127 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3128
aac24838 3129 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3130 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3131}
3132
d62a17ae 3133static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3134{
d62a17ae 3135 struct peer *peer;
0a486e5f 3136
d62a17ae 3137 peer = THREAD_ARG(thread);
3138 peer->t_pmax_restart = NULL;
0a486e5f 3139
d62a17ae 3140 if (bgp_debug_neighbor_events(peer))
3141 zlog_debug(
3142 "%s Maximum-prefix restart timer expired, restore peering",
3143 peer->host);
0a486e5f 3144
a9bafa95 3145 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3146 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3147
d62a17ae 3148 return 0;
0a486e5f 3149}
3150
9cbd06e0
DA
3151static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3152 safi_t safi)
3153{
3154 uint32_t count = 0;
f41b0459 3155 bool filtered = false;
9cbd06e0
DA
3156 struct bgp_dest *dest;
3157 struct bgp_adj_in *ain;
40bb2ccf 3158 struct attr attr = {};
9cbd06e0
DA
3159 struct bgp_table *table = peer->bgp->rib[afi][safi];
3160
3161 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3162 for (ain = dest->adj_in; ain; ain = ain->next) {
3163 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3164
3165 attr = *ain->attr;
9cbd06e0
DA
3166
3167 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3168 == FILTER_DENY)
f41b0459
DA
3169 filtered = true;
3170
3171 if (bgp_input_modifier(
3172 peer, rn_p, &attr, afi, safi,
3173 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3174 NULL, 0, NULL)
3175 == RMAP_DENY)
3176 filtered = true;
3177
3178 if (filtered)
9cbd06e0 3179 count++;
f41b0459
DA
3180
3181 bgp_attr_undup(&attr, ain->attr);
9cbd06e0
DA
3182 }
3183 }
3184
3185 return count;
3186}
3187
3dc339cd
DA
3188bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3189 int always)
718e3744 3190{
d62a17ae 3191 iana_afi_t pkt_afi;
5c525538 3192 iana_safi_t pkt_safi;
9cbd06e0
DA
3193 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3194 PEER_FLAG_MAX_PREFIX_FORCE))
3195 ? bgp_filtered_routes_count(peer, afi, safi)
3196 + peer->pcount[afi][safi]
3197 : peer->pcount[afi][safi];
9cabb64b 3198
d62a17ae 3199 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3200 return false;
e0701b79 3201
9cbd06e0 3202 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3203 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3204 PEER_STATUS_PREFIX_LIMIT)
3205 && !always)
3dc339cd 3206 return false;
e0701b79 3207
d62a17ae 3208 zlog_info(
6cde4b45 3209 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
9cbd06e0
DA
3210 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3211 peer->pmax[afi][safi]);
d62a17ae 3212 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3213
3214 if (CHECK_FLAG(peer->af_flags[afi][safi],
3215 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3216 return false;
d62a17ae 3217
3218 /* Convert AFI, SAFI to values for packet. */
3219 pkt_afi = afi_int2iana(afi);
3220 pkt_safi = safi_int2iana(safi);
3221 {
d7c0a89a 3222 uint8_t ndata[7];
d62a17ae 3223
3224 ndata[0] = (pkt_afi >> 8);
3225 ndata[1] = pkt_afi;
3226 ndata[2] = pkt_safi;
3227 ndata[3] = (peer->pmax[afi][safi] >> 24);
3228 ndata[4] = (peer->pmax[afi][safi] >> 16);
3229 ndata[5] = (peer->pmax[afi][safi] >> 8);
3230 ndata[6] = (peer->pmax[afi][safi]);
3231
3232 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3233 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3234 BGP_NOTIFY_CEASE_MAX_PREFIX,
3235 ndata, 7);
3236 }
3237
3238 /* Dynamic peers will just close their connection. */
3239 if (peer_dynamic_neighbor(peer))
3dc339cd 3240 return true;
d62a17ae 3241
3242 /* restart timer start */
3243 if (peer->pmax_restart[afi][safi]) {
3244 peer->v_pmax_restart =
3245 peer->pmax_restart[afi][safi] * 60;
3246
3247 if (bgp_debug_neighbor_events(peer))
3248 zlog_debug(
3249 "%s Maximum-prefix restart timer started for %d secs",
3250 peer->host, peer->v_pmax_restart);
3251
3252 BGP_TIMER_ON(peer->t_pmax_restart,
3253 bgp_maximum_prefix_restart_timer,
3254 peer->v_pmax_restart);
3255 }
3256
3dc339cd 3257 return true;
d62a17ae 3258 } else
3259 UNSET_FLAG(peer->af_sflags[afi][safi],
3260 PEER_STATUS_PREFIX_LIMIT);
3261
b1823b69
DS
3262 if (pcount
3263 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3264 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3265 PEER_STATUS_PREFIX_THRESHOLD)
3266 && !always)
3dc339cd 3267 return false;
d62a17ae 3268
3269 zlog_info(
6cde4b45 3270 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
9cbd06e0
DA
3271 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3272 peer->pmax[afi][safi]);
d62a17ae 3273 SET_FLAG(peer->af_sflags[afi][safi],
3274 PEER_STATUS_PREFIX_THRESHOLD);
3275 } else
3276 UNSET_FLAG(peer->af_sflags[afi][safi],
3277 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3278 return false;
718e3744 3279}
3280
b40d939b 3281/* Unconditionally remove the route from the RIB, without taking
3282 * damping into consideration (eg, because the session went down)
3283 */
9bcb3eef 3284void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3285 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3286{
f009ff26 3287
3288 struct bgp *bgp = NULL;
3289 bool delete_route = false;
3290
9bcb3eef
DS
3291 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3292 safi);
d62a17ae 3293
f009ff26 3294 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3295 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3296
f009ff26 3297 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3298 * flag
3299 */
3300 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3301 delete_route = true;
9bcb3eef 3302 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3303 delete_route = true;
f009ff26 3304 if (delete_route) {
9bcb3eef
DS
3305 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3306 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3307 bgp = pi->peer->bgp;
26742171 3308 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3309 }
3310 }
3311 }
4a11bf2c 3312
9bcb3eef
DS
3313 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3314 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3315}
3316
9bcb3eef 3317static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3318 struct peer *peer, afi_t afi, safi_t safi,
3319 struct prefix_rd *prd)
3320{
9bcb3eef 3321 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3322
d62a17ae 3323 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3324 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3325 */
3326 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3327 && peer->sort == BGP_PEER_EBGP)
9bcb3eef 3328 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
d62a17ae 3329 == BGP_DAMP_SUPPRESSED) {
b54892e0 3330 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
d62a17ae 3331 safi);
3332 return;
3333 }
3334
49e5a4a0 3335#ifdef ENABLE_BGP_VNC
d62a17ae 3336 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3337 struct bgp_dest *pdest = NULL;
d62a17ae 3338 struct bgp_table *table = NULL;
3339
9bcb3eef
DS
3340 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3341 (struct prefix *)prd);
3342 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3343 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3344
3345 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3346 peer->bgp, prd, table, p, pi);
d62a17ae 3347 }
9bcb3eef 3348 bgp_dest_unlock_node(pdest);
d62a17ae 3349 }
3350 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3351 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3352
b54892e0
DS
3353 vnc_import_bgp_del_route(peer->bgp, p, pi);
3354 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3355 }
65efcfce 3356 }
d62a17ae 3357#endif
128ea8ab 3358
d62a17ae 3359 /* If this is an EVPN route, process for un-import. */
3360 if (safi == SAFI_EVPN)
b54892e0 3361 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3362
9bcb3eef 3363 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3364}
3365
4b7e6066
DS
3366struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3367 struct peer *peer, struct attr *attr,
9bcb3eef 3368 struct bgp_dest *dest)
fb018d25 3369{
4b7e6066 3370 struct bgp_path_info *new;
fb018d25 3371
d62a17ae 3372 /* Make new BGP info. */
4b7e6066 3373 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3374 new->type = type;
3375 new->instance = instance;
3376 new->sub_type = sub_type;
3377 new->peer = peer;
3378 new->attr = attr;
3379 new->uptime = bgp_clock();
9bcb3eef 3380 new->net = dest;
d62a17ae 3381 return new;
fb018d25
DS
3382}
3383
d62a17ae 3384static void overlay_index_update(struct attr *attr,
d62a17ae 3385 union gw_addr *gw_ip)
684a7227 3386{
d62a17ae 3387 if (!attr)
3388 return;
d62a17ae 3389 if (gw_ip == NULL) {
6c924775
DS
3390 struct bgp_route_evpn eo;
3391
3392 memset(&eo, 0, sizeof(eo));
3393 bgp_attr_set_evpn_overlay(attr, &eo);
d62a17ae 3394 } else {
6c924775
DS
3395 struct bgp_route_evpn eo = {.gw_ip = *gw_ip};
3396
3397 bgp_attr_set_evpn_overlay(attr, &eo);
d62a17ae 3398 }
684a7227
PG
3399}
3400
40381db7 3401static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3402 union gw_addr *gw_ip)
3403{
6c924775
DS
3404 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(path->attr);
3405 union gw_addr path_gw_ip, *path_gw_ip_remote;
11ebf4ed 3406 union {
0a50c248 3407 esi_t esi;
11ebf4ed
DS
3408 union gw_addr ip;
3409 } temp;
d62a17ae 3410
3411 if (afi != AFI_L2VPN)
3412 return true;
11ebf4ed 3413
6c924775 3414 path_gw_ip = eo->gw_ip;
11ebf4ed
DS
3415
3416 if (gw_ip == NULL) {
3417 memset(&temp, 0, sizeof(temp));
40381db7 3418 path_gw_ip_remote = &temp.ip;
11ebf4ed 3419 } else
40381db7 3420 path_gw_ip_remote = gw_ip;
11ebf4ed 3421
6c924775 3422 return !!memcmp(&path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
684a7227
PG
3423}
3424
c265ee22 3425/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3426bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3427 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3428 struct bgp_dest *dest)
d62a17ae 3429{
2dbe3fa9 3430 bool ret = false;
b099a5c8
DA
3431 bool is_bgp_static_route =
3432 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3433 : false;
d62a17ae 3434
e8442016
DS
3435 /*
3436 * Only validated for unicast and multicast currently.
3437 * Also valid for EVPN where the nexthop is an IP address.
3438 * If we are a bgp static route being checked then there is
3439 * no need to check to see if the nexthop is martian as
3440 * that it should be ok.
3441 */
3442 if (is_bgp_static_route ||
3443 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3444 return false;
d62a17ae 3445
3446 /* If NEXT_HOP is present, validate it. */
3447 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e8442016 3448 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3449 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3450 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3451 return true;
d62a17ae 3452 }
c265ee22 3453
d62a17ae 3454 /* If MP_NEXTHOP is present, validate it. */
3455 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3456 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3457 * it is not an IPv6 link-local address.
0355b41d
DA
3458 *
3459 * If we receive an UPDATE with nexthop length set to 32 bytes
3460 * we shouldn't discard an UPDATE if it's set to (::).
3461 * The link-local (2st) is validated along the code path later.
d62a17ae 3462 */
3463 if (attr->mp_nexthop_len) {
3464 switch (attr->mp_nexthop_len) {
3465 case BGP_ATTR_NHLEN_IPV4:
3466 case BGP_ATTR_NHLEN_VPNV4:
e8442016 3467 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
975a328e
DA
3468 || IPV4_CLASS_DE(
3469 ntohl(attr->mp_nexthop_global_in.s_addr))
3470 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3471 dest));
d62a17ae 3472 break;
3473
3474 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3475 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3476 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3477 &attr->mp_nexthop_global)
d62a17ae 3478 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3479 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3480 &attr->mp_nexthop_global)
3481 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3482 dest));
d62a17ae 3483 break;
0355b41d
DA
3484 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3485 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3486 || IN6_IS_ADDR_MULTICAST(
3487 &attr->mp_nexthop_global)
3488 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3489 dest));
0355b41d 3490 break;
d62a17ae 3491
3492 default:
3dc339cd 3493 ret = true;
d62a17ae 3494 break;
3495 }
3496 }
c265ee22 3497
d62a17ae 3498 return ret;
3499}
3500
5a1ae2c2 3501int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3502 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3503 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3504 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3505 struct bgp_route_evpn *evpn)
d62a17ae 3506{
3507 int ret;
3508 int aspath_loop_count = 0;
9bcb3eef 3509 struct bgp_dest *dest;
d62a17ae 3510 struct bgp *bgp;
3511 struct attr new_attr;
3512 struct attr *attr_new;
40381db7 3513 struct bgp_path_info *pi;
4b7e6066
DS
3514 struct bgp_path_info *new;
3515 struct bgp_path_info_extra *extra;
d62a17ae 3516 const char *reason;
3517 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3518 int connected = 0;
3519 int do_loop_check = 1;
3520 int has_valid_label = 0;
7c312383 3521 afi_t nh_afi;
949b0f24 3522 uint8_t pi_type = 0;
3523 uint8_t pi_sub_type = 0;
3524
c7bb4f00 3525 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3526 char pfxprint[PREFIX2STR_BUFFER];
3527
3528 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3529 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3530 afi, safi, attr);
6401252f
QY
3531 }
3532
49e5a4a0 3533#ifdef ENABLE_BGP_VNC
d62a17ae 3534 int vnc_implicit_withdraw = 0;
65efcfce 3535#endif
d62a17ae 3536 int same_attr = 0;
718e3744 3537
d62a17ae 3538 memset(&new_attr, 0, sizeof(struct attr));
3539 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3540 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3541
d62a17ae 3542 bgp = peer->bgp;
9bcb3eef 3543 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3544 /* TODO: Check to see if we can get rid of "is_valid_label" */
3545 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3546 has_valid_label = (num_labels > 0) ? 1 : 0;
3547 else
3548 has_valid_label = bgp_is_valid_label(label);
718e3744 3549
28f66de2
MS
3550 if (has_valid_label)
3551 assert(label != NULL);
3552
a77e2f4b
S
3553 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3554 * condition :
3555 * Suppress fib is enabled
3556 * BGP_OPT_NO_FIB is not enabled
3557 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3558 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3559 */
3560 if (BGP_SUPPRESS_FIB_ENABLED(bgp) &&
3561 (sub_type == BGP_ROUTE_NORMAL) &&
3562 (!bgp_option_check(BGP_OPT_NO_FIB)) &&
3563 (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3564 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3565
d62a17ae 3566 /* When peer's soft reconfiguration enabled. Record input packet in
3567 Adj-RIBs-In. */
3568 if (!soft_reconfig
3569 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3570 && peer != bgp->peer_self)
9bcb3eef 3571 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3572
3573 /* Check previously received route. */
9bcb3eef 3574 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3575 if (pi->peer == peer && pi->type == type
3576 && pi->sub_type == sub_type
3577 && pi->addpath_rx_id == addpath_id)
d62a17ae 3578 break;
3579
3580 /* AS path local-as loop check. */
3581 if (peer->change_local_as) {
c4368918
DW
3582 if (peer->allowas_in[afi][safi])
3583 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3584 else if (!CHECK_FLAG(peer->flags,
3585 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3586 aspath_loop_count = 1;
3587
3588 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3589 > aspath_loop_count) {
b4d46cc9 3590 peer->stat_pfx_aspath_loop++;
9bcb3eef 3591 reason = "as-path contains our own AS A;";
d62a17ae 3592 goto filtered;
3593 }
718e3744 3594 }
718e3744 3595
d62a17ae 3596 /* If the peer is configured for "allowas-in origin" and the last ASN in
3597 * the
3598 * as-path is our ASN then we do not need to call aspath_loop_check
3599 */
3600 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3601 if (aspath_get_last_as(attr->aspath) == bgp->as)
3602 do_loop_check = 0;
3603
3604 /* AS path loop check. */
3605 if (do_loop_check) {
3606 if (aspath_loop_check(attr->aspath, bgp->as)
3607 > peer->allowas_in[afi][safi]
3608 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3609 && aspath_loop_check(attr->aspath, bgp->confed_id)
3610 > peer->allowas_in[afi][safi])) {
b4d46cc9 3611 peer->stat_pfx_aspath_loop++;
d62a17ae 3612 reason = "as-path contains our own AS;";
3613 goto filtered;
3614 }
3615 }
aac9ef6c 3616
d62a17ae 3617 /* Route reflector originator ID check. */
3618 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3619 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3620 peer->stat_pfx_originator_loop++;
d62a17ae 3621 reason = "originator is us;";
3622 goto filtered;
3623 }
718e3744 3624
d62a17ae 3625 /* Route reflector cluster ID check. */
3626 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3627 peer->stat_pfx_cluster_loop++;
d62a17ae 3628 reason = "reflected from the same cluster;";
3629 goto filtered;
3630 }
718e3744 3631
d62a17ae 3632 /* Apply incoming filter. */
3633 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3634 peer->stat_pfx_filter++;
d62a17ae 3635 reason = "filter;";
3636 goto filtered;
3637 }
718e3744 3638
a8b72dc6
DA
3639 /* RFC 8212 to prevent route leaks.
3640 * This specification intends to improve this situation by requiring the
3641 * explicit configuration of both BGP Import and Export Policies for any
3642 * External BGP (EBGP) session such as customers, peers, or
3643 * confederation boundaries for all enabled address families. Through
3644 * codification of the aforementioned requirement, operators will
3645 * benefit from consistent behavior across different BGP
3646 * implementations.
3647 */
1d3fdccf 3648 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3649 if (!bgp_inbound_policy_exists(peer,
3650 &peer->filter[afi][safi])) {
3651 reason = "inbound policy missing";
3652 goto filtered;
3653 }
3654
fb29348a
DA
3655 /* draft-ietf-idr-deprecate-as-set-confed-set
3656 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3657 * Eventually, This document (if approved) updates RFC 4271
3658 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3659 * and obsoletes RFC 6472.
3660 */
7f972cd8 3661 if (peer->bgp->reject_as_sets)
fb29348a
DA
3662 if (aspath_check_as_sets(attr->aspath)) {
3663 reason =
3664 "as-path contains AS_SET or AS_CONFED_SET type;";
3665 goto filtered;
3666 }
3667
6f4f49b2 3668 new_attr = *attr;
d62a17ae 3669
3670 /* Apply incoming route-map.
3671 * NB: new_attr may now contain newly allocated values from route-map
3672 * "set"
3673 * commands, so we need bgp_attr_flush in the error paths, until we
3674 * intern
3675 * the attr (which takes over the memory references) */
9bcb3eef
DS
3676 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3677 num_labels, dest)
3678 == RMAP_DENY) {
b4d46cc9 3679 peer->stat_pfx_filter++;
d62a17ae 3680 reason = "route-map;";
3681 bgp_attr_flush(&new_attr);
3682 goto filtered;
3683 }
718e3744 3684
05864da7 3685 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3686 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3687 /* remove from RIB previous entry */
3688 bgp_zebra_withdraw(p, pi, bgp, safi);
3689 }
3690
7f323236
DW
3691 if (peer->sort == BGP_PEER_EBGP) {
3692
a4d82a8a
PZ
3693 /* If we receive the graceful-shutdown community from an eBGP
3694 * peer we must lower local-preference */
3695 if (new_attr.community
3696 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3697 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3698 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3699
a4d82a8a
PZ
3700 /* If graceful-shutdown is configured then add the GSHUT
3701 * community to all paths received from eBGP peers */
637e5ba4 3702 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3703 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3704 }
3705
949b0f24 3706 if (pi) {
3707 pi_type = pi->type;
3708 pi_sub_type = pi->sub_type;
3709 }
3710
d62a17ae 3711 /* next hop check. */
a4d82a8a 3712 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3713 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3714 &new_attr, dest)) {
b4d46cc9 3715 peer->stat_pfx_nh_invalid++;
d62a17ae 3716 reason = "martian or self next-hop;";
3717 bgp_attr_flush(&new_attr);
3718 goto filtered;
3719 }
718e3744 3720
5c14a191 3721 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3722 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3723 reason = "self mac;";
3724 goto filtered;
3725 }
3726
1e9be514
QY
3727 /* Update Overlay Index */
3728 if (afi == AFI_L2VPN) {
3729 overlay_index_update(&new_attr,
3730 evpn == NULL ? NULL : &evpn->gw_ip);
3731 }
3732
d62a17ae 3733 attr_new = bgp_attr_intern(&new_attr);
3734
9cbd06e0
DA
3735 /* If maximum prefix count is configured and current prefix
3736 * count exeed it.
3737 */
3738 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3739 return -1;
3740
d62a17ae 3741 /* If the update is implicit withdraw. */
40381db7
DS
3742 if (pi) {
3743 pi->uptime = bgp_clock();
3744 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3745
9bcb3eef 3746 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3747
d62a17ae 3748 /* Same attribute comes in. */
40381db7
DS
3749 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3750 && attrhash_cmp(pi->attr, attr_new)
d62a17ae 3751 && (!has_valid_label
40381db7 3752 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3753 num_labels * sizeof(mpls_label_t))
d62a17ae 3754 == 0)
3755 && (overlay_index_equal(
0a50c248 3756 afi, pi,
d62a17ae 3757 evpn == NULL ? NULL : &evpn->gw_ip))) {
3758 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3759 BGP_CONFIG_DAMPENING)
3760 && peer->sort == BGP_PEER_EBGP
40381db7 3761 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3762 if (bgp_debug_update(peer, p, NULL, 1)) {
3763 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3764 afi, safi, prd, p, label,
3765 num_labels, addpath_id ? 1 : 0,
3766 addpath_id, pfx_buf,
3767 sizeof(pfx_buf));
d62a17ae 3768 zlog_debug("%s rcvd %s", peer->host,
3769 pfx_buf);
3770 }
3771
9bcb3eef 3772 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 3773 != BGP_DAMP_SUPPRESSED) {
40381db7 3774 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3775 safi);
9bcb3eef 3776 bgp_process(bgp, dest, afi, safi);
d62a17ae 3777 }
3778 } else /* Duplicate - odd */
3779 {
3780 if (bgp_debug_update(peer, p, NULL, 1)) {
3781 if (!peer->rcvd_attr_printed) {
3782 zlog_debug(
3783 "%s rcvd UPDATE w/ attr: %s",
3784 peer->host,
3785 peer->rcvd_attr_str);
3786 peer->rcvd_attr_printed = 1;
3787 }
3788
3789 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3790 afi, safi, prd, p, label,
3791 num_labels, addpath_id ? 1 : 0,
3792 addpath_id, pfx_buf,
3793 sizeof(pfx_buf));
d62a17ae 3794 zlog_debug(
3795 "%s rcvd %s...duplicate ignored",
3796 peer->host, pfx_buf);
3797 }
3798
3799 /* graceful restart STALE flag unset. */
40381db7 3800 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3801 bgp_path_info_unset_flag(
9bcb3eef
DS
3802 dest, pi, BGP_PATH_STALE);
3803 bgp_dest_set_defer_flag(dest, false);
3804 bgp_process(bgp, dest, afi, safi);
d62a17ae 3805 }
3806 }
3807
9bcb3eef 3808 bgp_dest_unlock_node(dest);
d62a17ae 3809 bgp_attr_unintern(&attr_new);
3810
3811 return 0;
3812 }
718e3744 3813
d62a17ae 3814 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3815 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3816 if (bgp_debug_update(peer, p, NULL, 1)) {
3817 bgp_debug_rdpfxpath2str(
a4d82a8a 3818 afi, safi, prd, p, label, num_labels,
d62a17ae 3819 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3820 sizeof(pfx_buf));
3821 zlog_debug(
3822 "%s rcvd %s, flapped quicker than processing",
3823 peer->host, pfx_buf);
3824 }
3825
9bcb3eef 3826 bgp_path_info_restore(dest, pi);
d62a17ae 3827 }
718e3744 3828
d62a17ae 3829 /* Received Logging. */
3830 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3831 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3832 num_labels, addpath_id ? 1 : 0,
3833 addpath_id, pfx_buf,
3834 sizeof(pfx_buf));
d62a17ae 3835 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3836 }
718e3744 3837
d62a17ae 3838 /* graceful restart STALE flag unset. */
f009ff26 3839 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
3840 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3841 bgp_dest_set_defer_flag(dest, false);
f009ff26 3842 }
d62a17ae 3843
3844 /* The attribute is changed. */
9bcb3eef 3845 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3846
3847 /* implicit withdraw, decrement aggregate and pcount here.
3848 * only if update is accepted, they'll increment below.
3849 */
40381db7 3850 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3851
3852 /* Update bgp route dampening information. */
3853 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3854 && peer->sort == BGP_PEER_EBGP) {
3855 /* This is implicit withdraw so we should update
3856 dampening
3857 information. */
40381db7 3858 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 3859 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 3860 }
49e5a4a0 3861#ifdef ENABLE_BGP_VNC
d62a17ae 3862 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3863 struct bgp_dest *pdest = NULL;
d62a17ae 3864 struct bgp_table *table = NULL;
3865
9bcb3eef
DS
3866 pdest = bgp_node_get(bgp->rib[afi][safi],
3867 (struct prefix *)prd);
3868 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3869 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3870
3871 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3872 bgp, prd, table, p, pi);
d62a17ae 3873 }
9bcb3eef 3874 bgp_dest_unlock_node(pdest);
d62a17ae 3875 }
3876 if ((afi == AFI_IP || afi == AFI_IP6)
3877 && (safi == SAFI_UNICAST)) {
40381db7 3878 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3879 /*
3880 * Implicit withdraw case.
3881 */
3882 ++vnc_implicit_withdraw;
40381db7
DS
3883 vnc_import_bgp_del_route(bgp, p, pi);
3884 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3885 }
3886 }
65efcfce 3887#endif
128ea8ab 3888
d62a17ae 3889 /* Special handling for EVPN update of an existing route. If the
3890 * extended community attribute has changed, we need to
3891 * un-import
3892 * the route using its existing extended community. It will be
3893 * subsequently processed for import with the new extended
3894 * community.
3895 */
6f8c9c11
PR
3896 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
3897 && !same_attr) {
40381db7 3898 if ((pi->attr->flag
d62a17ae 3899 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3900 && (attr_new->flag
3901 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3902 int cmp;
3903
40381db7 3904 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3905 attr_new->ecommunity);
3906 if (!cmp) {
3907 if (bgp_debug_update(peer, p, NULL, 1))
3908 zlog_debug(
3909 "Change in EXT-COMM, existing %s new %s",
3910 ecommunity_str(
40381db7 3911 pi->attr->ecommunity),
d62a17ae 3912 ecommunity_str(
3913 attr_new->ecommunity));
6f8c9c11
PR
3914 if (safi == SAFI_EVPN)
3915 bgp_evpn_unimport_route(
3916 bgp, afi, safi, p, pi);
3917 else /* SAFI_MPLS_VPN */
3918 vpn_leak_to_vrf_withdraw(bgp,
3919 pi);
d62a17ae 3920 }
3921 }
3922 }
718e3744 3923
d62a17ae 3924 /* Update to new attribute. */
40381db7
DS
3925 bgp_attr_unintern(&pi->attr);
3926 pi->attr = attr_new;
d62a17ae 3927
3928 /* Update MPLS label */
3929 if (has_valid_label) {
40381db7 3930 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3931 if (extra->label != label) {
3932 memcpy(&extra->label, label,
dbd587da 3933 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3934 extra->num_labels = num_labels;
3935 }
b57ba6d2
MK
3936 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3937 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3938 }
718e3744 3939
e496b420
HS
3940 /* Update SRv6 SID */
3941 if (attr->srv6_l3vpn) {
3942 extra = bgp_path_info_extra_get(pi);
3943 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
3944 sid_copy(&extra->sid[0],
3945 &attr->srv6_l3vpn->sid);
3946 extra->num_sids = 1;
3947 }
3948 } else if (attr->srv6_vpn) {
3949 extra = bgp_path_info_extra_get(pi);
3950 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
3951 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3952 extra->num_sids = 1;
3953 }
3954 }
3955
49e5a4a0 3956#ifdef ENABLE_BGP_VNC
d62a17ae 3957 if ((afi == AFI_IP || afi == AFI_IP6)
3958 && (safi == SAFI_UNICAST)) {
3959 if (vnc_implicit_withdraw) {
3960 /*
3961 * Add back the route with its new attributes
3962 * (e.g., nexthop).
3963 * The route is still selected, until the route
3964 * selection
3965 * queued by bgp_process actually runs. We have
3966 * to make this
3967 * update to the VNC side immediately to avoid
3968 * racing against
3969 * configuration changes (e.g., route-map
3970 * changes) which
3971 * trigger re-importation of the entire RIB.
3972 */
40381db7
DS
3973 vnc_import_bgp_add_route(bgp, p, pi);
3974 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 3975 }
3976 }
65efcfce
LB
3977#endif
3978
d62a17ae 3979 /* Update bgp route dampening information. */
3980 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3981 && peer->sort == BGP_PEER_EBGP) {
3982 /* Now we do normal update dampening. */
9bcb3eef 3983 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 3984 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 3985 bgp_dest_unlock_node(dest);
d62a17ae 3986 return 0;
3987 }
3988 }
128ea8ab 3989
d62a17ae 3990 /* Nexthop reachability check - for unicast and
3991 * labeled-unicast.. */
7c312383
AD
3992 if (((afi == AFI_IP || afi == AFI_IP6)
3993 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3994 || (safi == SAFI_EVPN &&
3995 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
3996 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
3997 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 3998 && !CHECK_FLAG(peer->flags,
3999 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4000 && !CHECK_FLAG(bgp->flags,
4001 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4002 connected = 1;
4003 else
4004 connected = 0;
4005
960035b2
PZ
4006 struct bgp *bgp_nexthop = bgp;
4007
40381db7
DS
4008 if (pi->extra && pi->extra->bgp_orig)
4009 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4010
7c312383
AD
4011 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4012
4013 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
4014 pi, NULL, connected)
a4d82a8a 4015 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4016 bgp_path_info_set_flag(dest, pi,
4017 BGP_PATH_VALID);
d62a17ae 4018 else {
4019 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4020 zlog_debug("%s(%pI4): NH unresolved",
4021 __func__,
4022 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4023 }
9bcb3eef 4024 bgp_path_info_unset_flag(dest, pi,
18ee8310 4025 BGP_PATH_VALID);
d62a17ae 4026 }
4027 } else
9bcb3eef 4028 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4029
49e5a4a0 4030#ifdef ENABLE_BGP_VNC
d62a17ae 4031 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4032 struct bgp_dest *pdest = NULL;
d62a17ae 4033 struct bgp_table *table = NULL;
4034
9bcb3eef
DS
4035 pdest = bgp_node_get(bgp->rib[afi][safi],
4036 (struct prefix *)prd);
4037 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4038 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4039
4040 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4041 bgp, prd, table, p, pi);
d62a17ae 4042 }
9bcb3eef 4043 bgp_dest_unlock_node(pdest);
d62a17ae 4044 }
4045#endif
718e3744 4046
d62a17ae 4047 /* If this is an EVPN route and some attribute has changed,
4048 * process
4049 * route for import. If the extended community has changed, we
4050 * would
4051 * have done the un-import earlier and the import would result
4052 * in the
4053 * route getting injected into appropriate L2 VNIs. If it is
4054 * just
4055 * some other attribute change, the import will result in
4056 * updating
4057 * the attributes for the route in the VNI(s).
4058 */
7c312383
AD
4059 if (safi == SAFI_EVPN && !same_attr &&
4060 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4061 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4062
4063 /* Process change. */
40381db7 4064 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4065
9bcb3eef
DS
4066 bgp_process(bgp, dest, afi, safi);
4067 bgp_dest_unlock_node(dest);
558d1fec 4068
ddb5b488
PZ
4069 if (SAFI_UNICAST == safi
4070 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4071 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4072
40381db7 4073 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4074 }
4075 if ((SAFI_MPLS_VPN == safi)
4076 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4077
40381db7 4078 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4079 }
4080
49e5a4a0 4081#ifdef ENABLE_BGP_VNC
d62a17ae 4082 if (SAFI_MPLS_VPN == safi) {
4083 mpls_label_t label_decoded = decode_label(label);
28070ee3 4084
d62a17ae 4085 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4086 type, sub_type, &label_decoded);
4087 }
4088 if (SAFI_ENCAP == safi) {
4089 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4090 type, sub_type, NULL);
4091 }
28070ee3
PZ
4092#endif
4093
d62a17ae 4094 return 0;
4095 } // End of implicit withdraw
718e3744 4096
d62a17ae 4097 /* Received Logging. */
4098 if (bgp_debug_update(peer, p, NULL, 1)) {
4099 if (!peer->rcvd_attr_printed) {
4100 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4101 peer->rcvd_attr_str);
4102 peer->rcvd_attr_printed = 1;
4103 }
718e3744 4104
a4d82a8a 4105 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4106 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4107 sizeof(pfx_buf));
4108 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4109 }
718e3744 4110
d62a17ae 4111 /* Make new BGP info. */
9bcb3eef 4112 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4113
d62a17ae 4114 /* Update MPLS label */
4115 if (has_valid_label) {
18ee8310 4116 extra = bgp_path_info_extra_get(new);
8ba71050 4117 if (extra->label != label) {
dbd587da
QY
4118 memcpy(&extra->label, label,
4119 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4120 extra->num_labels = num_labels;
4121 }
b57ba6d2
MK
4122 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4123 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4124 }
718e3744 4125
e496b420
HS
4126 /* Update SRv6 SID */
4127 if (safi == SAFI_MPLS_VPN) {
4128 extra = bgp_path_info_extra_get(new);
4129 if (attr->srv6_l3vpn) {
4130 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
4131 extra->num_sids = 1;
4132 } else if (attr->srv6_vpn) {
4133 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4134 extra->num_sids = 1;
4135 }
4136 }
4137
d62a17ae 4138 /* Update Overlay Index */
4139 if (afi == AFI_L2VPN) {
4140 overlay_index_update(new->attr,
d62a17ae 4141 evpn == NULL ? NULL : &evpn->gw_ip);
4142 }
4143 /* Nexthop reachability check. */
7c312383
AD
4144 if (((afi == AFI_IP || afi == AFI_IP6)
4145 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4146 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4147 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4148 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4149 && !CHECK_FLAG(peer->flags,
4150 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4151 && !CHECK_FLAG(bgp->flags,
4152 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4153 connected = 1;
4154 else
4155 connected = 0;
4156
7c312383
AD
4157 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4158
4159 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, new, NULL,
4160 connected)
a4d82a8a 4161 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4162 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4163 else {
4164 if (BGP_DEBUG(nht, NHT)) {
4165 char buf1[INET6_ADDRSTRLEN];
4166 inet_ntop(AF_INET,
4167 (const void *)&attr_new->nexthop,
4168 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4169 zlog_debug("%s(%s): NH unresolved", __func__,
4170 buf1);
d62a17ae 4171 }
9bcb3eef 4172 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4173 }
4174 } else
9bcb3eef 4175 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4176
d62a17ae 4177 /* Addpath ID */
4178 new->addpath_rx_id = addpath_id;
4179
4180 /* Increment prefix */
4181 bgp_aggregate_increment(bgp, p, new, afi, safi);
4182
4183 /* Register new BGP information. */
9bcb3eef 4184 bgp_path_info_add(dest, new);
d62a17ae 4185
4186 /* route_node_get lock */
9bcb3eef 4187 bgp_dest_unlock_node(dest);
558d1fec 4188
49e5a4a0 4189#ifdef ENABLE_BGP_VNC
d62a17ae 4190 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4191 struct bgp_dest *pdest = NULL;
d62a17ae 4192 struct bgp_table *table = NULL;
4193
9bcb3eef
DS
4194 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4195 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4196 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4197
4198 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4199 bgp, prd, table, p, new);
4200 }
9bcb3eef 4201 bgp_dest_unlock_node(pdest);
d62a17ae 4202 }
65efcfce
LB
4203#endif
4204
d62a17ae 4205 /* If this is an EVPN route, process for import. */
7c312383 4206 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4207 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4208
9bcb3eef 4209 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4210
d62a17ae 4211 /* Process change. */
9bcb3eef 4212 bgp_process(bgp, dest, afi, safi);
718e3744 4213
ddb5b488
PZ
4214 if (SAFI_UNICAST == safi
4215 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4216 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4217 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4218 }
4219 if ((SAFI_MPLS_VPN == safi)
4220 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4221
4222 vpn_leak_to_vrf_update(bgp, new);
4223 }
49e5a4a0 4224#ifdef ENABLE_BGP_VNC
d62a17ae 4225 if (SAFI_MPLS_VPN == safi) {
4226 mpls_label_t label_decoded = decode_label(label);
28070ee3 4227
d62a17ae 4228 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4229 sub_type, &label_decoded);
4230 }
4231 if (SAFI_ENCAP == safi) {
4232 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4233 sub_type, NULL);
4234 }
28070ee3
PZ
4235#endif
4236
d62a17ae 4237 return 0;
718e3744 4238
d62a17ae 4239/* This BGP update is filtered. Log the reason then update BGP
4240 entry. */
4241filtered:
9bcb3eef 4242 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4243
d62a17ae 4244 if (bgp_debug_update(peer, p, NULL, 1)) {
4245 if (!peer->rcvd_attr_printed) {
4246 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4247 peer->rcvd_attr_str);
4248 peer->rcvd_attr_printed = 1;
4249 }
718e3744 4250
a4d82a8a 4251 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4252 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4253 sizeof(pfx_buf));
4254 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4255 peer->host, pfx_buf, reason);
4256 }
128ea8ab 4257
40381db7 4258 if (pi) {
d62a17ae 4259 /* If this is an EVPN route, un-import it as it is now filtered.
4260 */
4261 if (safi == SAFI_EVPN)
40381db7 4262 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4263
ddb5b488
PZ
4264 if (SAFI_UNICAST == safi
4265 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4266 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4267
40381db7 4268 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4269 }
4270 if ((SAFI_MPLS_VPN == safi)
4271 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4272
40381db7 4273 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4274 }
4275
9bcb3eef 4276 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4277 }
4278
9bcb3eef 4279 bgp_dest_unlock_node(dest);
558d1fec 4280
49e5a4a0 4281#ifdef ENABLE_BGP_VNC
d62a17ae 4282 /*
4283 * Filtered update is treated as an implicit withdrawal (see
4284 * bgp_rib_remove()
4285 * a few lines above)
4286 */
4287 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4288 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4289 0);
4290 }
97736e32
PZ
4291#endif
4292
d62a17ae 4293 return 0;
718e3744 4294}
4295
26a3ffd6 4296int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4297 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4298 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4299 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4300{
d62a17ae 4301 struct bgp *bgp;
4302 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4303 struct bgp_dest *dest;
40381db7 4304 struct bgp_path_info *pi;
718e3744 4305
49e5a4a0 4306#ifdef ENABLE_BGP_VNC
d62a17ae 4307 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4308 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4309 0);
4310 }
28070ee3
PZ
4311#endif
4312
d62a17ae 4313 bgp = peer->bgp;
4314
4315 /* Lookup node. */
9bcb3eef 4316 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4317
4318 /* If peer is soft reconfiguration enabled. Record input packet for
4319 * further calculation.
4320 *
4321 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4322 * routes that are filtered. This tanks out Quagga RS pretty badly due
4323 * to
4324 * the iteration over all RS clients.
4325 * Since we need to remove the entry from adj_in anyway, do that first
4326 * and
4327 * if there was no entry, we don't need to do anything more.
4328 */
4329 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4330 && peer != bgp->peer_self)
9bcb3eef 4331 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4332 peer->stat_pfx_dup_withdraw++;
4333
d62a17ae 4334 if (bgp_debug_update(peer, p, NULL, 1)) {
4335 bgp_debug_rdpfxpath2str(
a4d82a8a 4336 afi, safi, prd, p, label, num_labels,
d62a17ae 4337 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4338 sizeof(pfx_buf));
4339 zlog_debug(
4340 "%s withdrawing route %s not in adj-in",
4341 peer->host, pfx_buf);
4342 }
9bcb3eef 4343 bgp_dest_unlock_node(dest);
d62a17ae 4344 return 0;
4345 }
cd808e74 4346
d62a17ae 4347 /* Lookup withdrawn route. */
9bcb3eef 4348 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4349 if (pi->peer == peer && pi->type == type
4350 && pi->sub_type == sub_type
4351 && pi->addpath_rx_id == addpath_id)
d62a17ae 4352 break;
4353
4354 /* Logging. */
4355 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4356 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4357 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4358 sizeof(pfx_buf));
4359 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4360 pfx_buf);
4361 }
718e3744 4362
d62a17ae 4363 /* Withdraw specified route from routing table. */
40381db7 4364 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4365 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4366 if (SAFI_UNICAST == safi
4367 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4368 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4369 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4370 }
4371 if ((SAFI_MPLS_VPN == safi)
4372 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4373
40381db7 4374 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4375 }
4376 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4377 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4378 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4379 sizeof(pfx_buf));
4380 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4381 }
718e3744 4382
d62a17ae 4383 /* Unlock bgp_node_get() lock. */
9bcb3eef 4384 bgp_dest_unlock_node(dest);
d62a17ae 4385
4386 return 0;
718e3744 4387}
6b0655a2 4388
d62a17ae 4389void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4390 int withdraw)
718e3744 4391{
d62a17ae 4392 struct update_subgroup *subgrp;
4393 subgrp = peer_subgroup(peer, afi, safi);
4394 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4395}
6182d65b 4396
718e3744 4397
3f9c7369
DS
4398/*
4399 * bgp_stop_announce_route_timer
4400 */
d62a17ae 4401void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4402{
d62a17ae 4403 if (!paf->t_announce_route)
4404 return;
4405
50478845 4406 thread_cancel(&paf->t_announce_route);
718e3744 4407}
6b0655a2 4408
3f9c7369
DS
4409/*
4410 * bgp_announce_route_timer_expired
4411 *
4412 * Callback that is invoked when the route announcement timer for a
4413 * peer_af expires.
4414 */
d62a17ae 4415static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4416{
d62a17ae 4417 struct peer_af *paf;
4418 struct peer *peer;
558d1fec 4419
d62a17ae 4420 paf = THREAD_ARG(t);
4421 peer = paf->peer;
718e3744 4422
d62a17ae 4423 if (peer->status != Established)
4424 return 0;
3f9c7369 4425
d62a17ae 4426 if (!peer->afc_nego[paf->afi][paf->safi])
4427 return 0;
3f9c7369 4428
d62a17ae 4429 peer_af_announce_route(paf, 1);
c5aec50b
MK
4430
4431 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4432 peer->advmap_config_change[paf->afi][paf->safi] = true;
c5aec50b 4433
d62a17ae 4434 return 0;
718e3744 4435}
4436
3f9c7369
DS
4437/*
4438 * bgp_announce_route
4439 *
4440 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4441 */
d62a17ae 4442void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4443{
4444 struct peer_af *paf;
4445 struct update_subgroup *subgrp;
4446
4447 paf = peer_af_find(peer, afi, safi);
4448 if (!paf)
4449 return;
4450 subgrp = PAF_SUBGRP(paf);
4451
4452 /*
4453 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4454 * or a refresh has already been triggered.
4455 */
4456 if (!subgrp || paf->t_announce_route)
4457 return;
4458
4459 /*
4460 * Start a timer to stagger/delay the announce. This serves
4461 * two purposes - announcement can potentially be combined for
4462 * multiple peers and the announcement doesn't happen in the
4463 * vty context.
4464 */
4465 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4466 (subgrp->peer_count == 1)
4467 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4468 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4469 &paf->t_announce_route);
3f9c7369
DS
4470}
4471
4472/*
4473 * Announce routes from all AF tables to a peer.
4474 *
4475 * This should ONLY be called when there is a need to refresh the
4476 * routes to the peer based on a policy change for this peer alone
4477 * or a route refresh request received from the peer.
4478 * The operation will result in splitting the peer from its existing
4479 * subgroups and putting it in new subgroups.
4480 */
d62a17ae 4481void bgp_announce_route_all(struct peer *peer)
718e3744 4482{
d62a17ae 4483 afi_t afi;
4484 safi_t safi;
4485
05c7a1cc
QY
4486 FOREACH_AFI_SAFI (afi, safi)
4487 bgp_announce_route(peer, afi, safi);
718e3744 4488}
6b0655a2 4489
d62a17ae 4490static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4491 struct bgp_table *table,
4492 struct prefix_rd *prd)
718e3744 4493{
d62a17ae 4494 int ret;
9bcb3eef 4495 struct bgp_dest *dest;
d62a17ae 4496 struct bgp_adj_in *ain;
718e3744 4497
d62a17ae 4498 if (!table)
4499 table = peer->bgp->rib[afi][safi];
718e3744 4500
9bcb3eef
DS
4501 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4502 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4503 if (ain->peer != peer)
4504 continue;
8692c506 4505
d7d15889 4506 struct bgp_path_info *pi;
d7c0a89a 4507 uint32_t num_labels = 0;
b57ba6d2 4508 mpls_label_t *label_pnt = NULL;
8cb687c2 4509 struct bgp_route_evpn evpn;
b57ba6d2 4510
9bcb3eef 4511 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
d7d15889
DS
4512 pi = pi->next)
4513 if (pi->peer == peer)
4514 break;
4515
40381db7
DS
4516 if (pi && pi->extra)
4517 num_labels = pi->extra->num_labels;
b57ba6d2 4518 if (num_labels)
40381db7 4519 label_pnt = &pi->extra->label[0];
8cb687c2 4520 if (pi)
6c924775
DS
4521 memcpy(&evpn,
4522 bgp_attr_get_evpn_overlay(pi->attr),
8cb687c2
DS
4523 sizeof(evpn));
4524 else
4525 memset(&evpn, 0, sizeof(evpn));
8692c506 4526
9bcb3eef
DS
4527 ret = bgp_update(peer, bgp_dest_get_prefix(dest),
4528 ain->addpath_rx_id, ain->attr, afi,
4529 safi, ZEBRA_ROUTE_BGP,
a4d82a8a 4530 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 4531 num_labels, 1, &evpn);
ea47320b
DL
4532
4533 if (ret < 0) {
9bcb3eef 4534 bgp_dest_unlock_node(dest);
ea47320b 4535 return;
d62a17ae 4536 }
4537 }
718e3744 4538}
4539
d62a17ae 4540void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4541{
9bcb3eef 4542 struct bgp_dest *dest;
d62a17ae 4543 struct bgp_table *table;
718e3744 4544
d62a17ae 4545 if (peer->status != Established)
4546 return;
718e3744 4547
d62a17ae 4548 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4549 && (safi != SAFI_EVPN))
4550 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4551 else
9bcb3eef
DS
4552 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4553 dest = bgp_route_next(dest)) {
4554 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4555
b54892e0
DS
4556 if (table == NULL)
4557 continue;
8692c506 4558
9bcb3eef 4559 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
4560 struct prefix_rd prd;
4561
4562 prd.family = AF_UNSPEC;
4563 prd.prefixlen = 64;
4564 memcpy(&prd.val, p->u.val, 8);
4565
4566 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 4567 }
718e3744 4568}
6b0655a2 4569
228da428 4570
d62a17ae 4571struct bgp_clear_node_queue {
9bcb3eef 4572 struct bgp_dest *dest;
228da428
CC
4573};
4574
d62a17ae 4575static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4576{
d62a17ae 4577 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 4578 struct bgp_dest *dest = cnq->dest;
d62a17ae 4579 struct peer *peer = wq->spec.data;
40381db7 4580 struct bgp_path_info *pi;
3103e8d2 4581 struct bgp *bgp;
9bcb3eef
DS
4582 afi_t afi = bgp_dest_table(dest)->afi;
4583 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 4584
9bcb3eef 4585 assert(dest && peer);
3103e8d2 4586 bgp = peer->bgp;
d62a17ae 4587
4588 /* It is possible that we have multiple paths for a prefix from a peer
4589 * if that peer is using AddPath.
4590 */
9bcb3eef 4591 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 4592 if (pi->peer != peer)
ea47320b
DL
4593 continue;
4594
4595 /* graceful restart STALE flag set. */
4596 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4597 && peer->nsf[afi][safi]
40381db7
DS
4598 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4599 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 4600 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
4601 else {
4602 /* If this is an EVPN route, process for
4603 * un-import. */
4604 if (safi == SAFI_EVPN)
9bcb3eef
DS
4605 bgp_evpn_unimport_route(
4606 bgp, afi, safi,
4607 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
4608 /* Handle withdraw for VRF route-leaking and L3VPN */
4609 if (SAFI_UNICAST == safi
4610 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4611 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4612 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4613 bgp, pi);
960035b2 4614 }
3103e8d2 4615 if (SAFI_MPLS_VPN == safi &&
960035b2 4616 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4617 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4618 }
3103e8d2 4619
9bcb3eef 4620 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4621 }
ea47320b 4622 }
d62a17ae 4623 return WQ_SUCCESS;
200df115 4624}
4625
d62a17ae 4626static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4627{
d62a17ae 4628 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
4629 struct bgp_dest *dest = cnq->dest;
4630 struct bgp_table *table = bgp_dest_table(dest);
228da428 4631
9bcb3eef 4632 bgp_dest_unlock_node(dest);
d62a17ae 4633 bgp_table_unlock(table);
4634 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4635}
4636
d62a17ae 4637static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4638{
d62a17ae 4639 struct peer *peer = wq->spec.data;
64e580a7 4640
d62a17ae 4641 /* Tickle FSM to start moving again */
4642 BGP_EVENT_ADD(peer, Clearing_Completed);
4643
4644 peer_unlock(peer); /* bgp_clear_route */
200df115 4645}
718e3744 4646
d62a17ae 4647static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4648{
d62a17ae 4649 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4650
4651 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4652#undef CLEAR_QUEUE_NAME_LEN
4653
0ce1ca80 4654 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4655 peer->clear_node_queue->spec.hold = 10;
4656 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4657 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4658 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4659 peer->clear_node_queue->spec.max_retries = 0;
4660
4661 /* we only 'lock' this peer reference when the queue is actually active
4662 */
4663 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4664}
4665
d62a17ae 4666static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4667 struct bgp_table *table)
65ca75e0 4668{
9bcb3eef 4669 struct bgp_dest *dest;
b6c386bb 4670 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 4671
d62a17ae 4672 if (!table)
4673 table = peer->bgp->rib[afi][safi];
dc83d712 4674
d62a17ae 4675 /* If still no table => afi/safi isn't configured at all or smth. */
4676 if (!table)
4677 return;
dc83d712 4678
9bcb3eef 4679 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 4680 struct bgp_path_info *pi, *next;
d62a17ae 4681 struct bgp_adj_in *ain;
4682 struct bgp_adj_in *ain_next;
4683
4684 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4685 * queued for every clearing peer, regardless of whether it is
4686 * relevant to the peer at hand.
4687 *
4688 * Overview: There are 3 different indices which need to be
4689 * scrubbed, potentially, when a peer is removed:
4690 *
4691 * 1 peer's routes visible via the RIB (ie accepted routes)
4692 * 2 peer's routes visible by the (optional) peer's adj-in index
4693 * 3 other routes visible by the peer's adj-out index
4694 *
4695 * 3 there is no hurry in scrubbing, once the struct peer is
4696 * removed from bgp->peer, we could just GC such deleted peer's
4697 * adj-outs at our leisure.
4698 *
4699 * 1 and 2 must be 'scrubbed' in some way, at least made
4700 * invisible via RIB index before peer session is allowed to be
4701 * brought back up. So one needs to know when such a 'search' is
4702 * complete.
4703 *
4704 * Ideally:
4705 *
4706 * - there'd be a single global queue or a single RIB walker
4707 * - rather than tracking which route_nodes still need to be
4708 * examined on a peer basis, we'd track which peers still
4709 * aren't cleared
4710 *
4711 * Given that our per-peer prefix-counts now should be reliable,
4712 * this may actually be achievable. It doesn't seem to be a huge
4713 * problem at this time,
4714 *
4715 * It is possible that we have multiple paths for a prefix from
4716 * a peer
4717 * if that peer is using AddPath.
4718 */
9bcb3eef 4719 ain = dest->adj_in;
d62a17ae 4720 while (ain) {
4721 ain_next = ain->next;
4722
4723 if (ain->peer == peer) {
9bcb3eef
DS
4724 bgp_adj_in_remove(dest, ain);
4725 bgp_dest_unlock_node(dest);
d62a17ae 4726 }
4727
4728 ain = ain_next;
4729 }
4730
9bcb3eef 4731 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
4732 next = pi->next;
4733 if (pi->peer != peer)
d62a17ae 4734 continue;
4735
4736 if (force)
9bcb3eef 4737 bgp_path_info_reap(dest, pi);
d62a17ae 4738 else {
4739 struct bgp_clear_node_queue *cnq;
4740
4741 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
4742 bgp_table_lock(bgp_dest_table(dest));
4743 bgp_dest_lock_node(dest);
d62a17ae 4744 cnq = XCALLOC(
4745 MTYPE_BGP_CLEAR_NODE_QUEUE,
4746 sizeof(struct bgp_clear_node_queue));
9bcb3eef 4747 cnq->dest = dest;
d62a17ae 4748 work_queue_add(peer->clear_node_queue, cnq);
4749 break;
4750 }
4751 }
4752 }
4753 return;
4754}
4755
4756void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4757{
9bcb3eef 4758 struct bgp_dest *dest;
d62a17ae 4759 struct bgp_table *table;
4760
4761 if (peer->clear_node_queue == NULL)
4762 bgp_clear_node_queue_init(peer);
4763
4764 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4765 * Idle until it receives a Clearing_Completed event. This protects
4766 * against peers which flap faster than we can we clear, which could
4767 * lead to:
4768 *
4769 * a) race with routes from the new session being installed before
4770 * clear_route_node visits the node (to delete the route of that
4771 * peer)
4772 * b) resource exhaustion, clear_route_node likely leads to an entry
4773 * on the process_main queue. Fast-flapping could cause that queue
4774 * to grow and grow.
4775 */
4776
4777 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4778 * the unlock will happen upon work-queue completion; other wise, the
4779 * unlock happens at the end of this function.
4780 */
4781 if (!peer->clear_node_queue->thread)
4782 peer_lock(peer);
4783
4784 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4785 bgp_clear_route_table(peer, afi, safi, NULL);
4786 else
9bcb3eef
DS
4787 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4788 dest = bgp_route_next(dest)) {
4789 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4790 if (!table)
4791 continue;
4792
4793 bgp_clear_route_table(peer, afi, safi, table);
4794 }
d62a17ae 4795
4796 /* unlock if no nodes got added to the clear-node-queue. */
4797 if (!peer->clear_node_queue->thread)
4798 peer_unlock(peer);
718e3744 4799}
d62a17ae 4800
4801void bgp_clear_route_all(struct peer *peer)
718e3744 4802{
d62a17ae 4803 afi_t afi;
4804 safi_t safi;
718e3744 4805
05c7a1cc
QY
4806 FOREACH_AFI_SAFI (afi, safi)
4807 bgp_clear_route(peer, afi, safi);
65efcfce 4808
49e5a4a0 4809#ifdef ENABLE_BGP_VNC
d62a17ae 4810 rfapiProcessPeerDown(peer);
65efcfce 4811#endif
718e3744 4812}
4813
d62a17ae 4814void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4815{
d62a17ae 4816 struct bgp_table *table;
9bcb3eef 4817 struct bgp_dest *dest;
d62a17ae 4818 struct bgp_adj_in *ain;
4819 struct bgp_adj_in *ain_next;
718e3744 4820
d62a17ae 4821 table = peer->bgp->rib[afi][safi];
718e3744 4822
d62a17ae 4823 /* It is possible that we have multiple paths for a prefix from a peer
4824 * if that peer is using AddPath.
4825 */
9bcb3eef
DS
4826 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4827 ain = dest->adj_in;
43143c8f 4828
d62a17ae 4829 while (ain) {
4830 ain_next = ain->next;
43143c8f 4831
d62a17ae 4832 if (ain->peer == peer) {
9bcb3eef
DS
4833 bgp_adj_in_remove(dest, ain);
4834 bgp_dest_unlock_node(dest);
d62a17ae 4835 }
43143c8f 4836
d62a17ae 4837 ain = ain_next;
4838 }
4839 }
718e3744 4840}
93406d87 4841
d62a17ae 4842void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4843{
9bcb3eef 4844 struct bgp_dest *dest;
40381db7 4845 struct bgp_path_info *pi;
d62a17ae 4846 struct bgp_table *table;
4847
4848 if (safi == SAFI_MPLS_VPN) {
9bcb3eef
DS
4849 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4850 dest = bgp_route_next(dest)) {
4851 struct bgp_dest *rm;
d62a17ae 4852
4853 /* look for neighbor in tables */
9bcb3eef 4854 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4855 if (!table)
ea47320b
DL
4856 continue;
4857
4858 for (rm = bgp_table_top(table); rm;
4859 rm = bgp_route_next(rm))
9bcb3eef 4860 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 4861 pi = pi->next) {
40381db7 4862 if (pi->peer != peer)
ea47320b 4863 continue;
40381db7 4864 if (!CHECK_FLAG(pi->flags,
1defdda8 4865 BGP_PATH_STALE))
ea47320b
DL
4866 break;
4867
40381db7 4868 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4869 break;
4870 }
d62a17ae 4871 }
4872 } else {
9bcb3eef
DS
4873 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4874 dest = bgp_route_next(dest))
4875 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 4876 pi = pi->next) {
40381db7 4877 if (pi->peer != peer)
ea47320b 4878 continue;
40381db7 4879 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4880 break;
9bcb3eef 4881 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
4882 break;
4883 }
d62a17ae 4884 }
93406d87 4885}
6b0655a2 4886
3dc339cd 4887bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 4888{
e0df4c04 4889 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 4890 return true;
e0df4c04 4891
9dac9fc8
DA
4892 if (peer->sort == BGP_PEER_EBGP
4893 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
4894 || FILTER_LIST_OUT_NAME(filter)
4895 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
4896 return true;
4897 return false;
9dac9fc8
DA
4898}
4899
3dc339cd 4900bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 4901{
e0df4c04 4902 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 4903 return true;
e0df4c04 4904
9dac9fc8
DA
4905 if (peer->sort == BGP_PEER_EBGP
4906 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
4907 || FILTER_LIST_IN_NAME(filter)
4908 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
4909 return true;
4910 return false;
9dac9fc8
DA
4911}
4912
568e10ca 4913static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
4914 safi_t safi)
bb86c601 4915{
9bcb3eef 4916 struct bgp_dest *dest;
40381db7 4917 struct bgp_path_info *pi;
4b7e6066 4918 struct bgp_path_info *next;
bb86c601 4919
9bcb3eef
DS
4920 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4921 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
4922 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 4923
40381db7 4924 next = pi->next;
1b7bb747
CS
4925
4926 /* Unimport EVPN routes from VRFs */
4927 if (safi == SAFI_EVPN)
4928 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 4929 SAFI_EVPN, p, pi);
1b7bb747 4930
40381db7
DS
4931 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
4932 && pi->type == ZEBRA_ROUTE_BGP
4933 && (pi->sub_type == BGP_ROUTE_NORMAL
4934 || pi->sub_type == BGP_ROUTE_AGGREGATE
4935 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 4936
d62a17ae 4937 if (bgp_fibupd_safi(safi))
b54892e0 4938 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 4939 }
9514b37d 4940
9bcb3eef 4941 bgp_path_info_reap(dest, pi);
d62a17ae 4942 }
bb86c601
LB
4943}
4944
718e3744 4945/* Delete all kernel routes. */
d62a17ae 4946void bgp_cleanup_routes(struct bgp *bgp)
4947{
4948 afi_t afi;
9bcb3eef 4949 struct bgp_dest *dest;
67009e22 4950 struct bgp_table *table;
d62a17ae 4951
4952 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
4953 if (afi == AFI_L2VPN)
4954 continue;
568e10ca 4955 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
4956 SAFI_UNICAST);
d62a17ae 4957 /*
4958 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4959 */
4960 if (afi != AFI_L2VPN) {
4961 safi_t safi;
4962 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
4963 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
4964 dest = bgp_route_next(dest)) {
4965 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4966 if (table != NULL) {
4967 bgp_cleanup_table(bgp, table, safi);
4968 bgp_table_finish(&table);
9bcb3eef
DS
4969 bgp_dest_set_bgp_table_info(dest, NULL);
4970 bgp_dest_unlock_node(dest);
d62a17ae 4971 }
4972 }
4973 safi = SAFI_ENCAP;
9bcb3eef
DS
4974 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
4975 dest = bgp_route_next(dest)) {
4976 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4977 if (table != NULL) {
4978 bgp_cleanup_table(bgp, table, safi);
4979 bgp_table_finish(&table);
9bcb3eef
DS
4980 bgp_dest_set_bgp_table_info(dest, NULL);
4981 bgp_dest_unlock_node(dest);
d62a17ae 4982 }
4983 }
4984 }
4985 }
9bcb3eef
DS
4986 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
4987 dest = bgp_route_next(dest)) {
4988 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4989 if (table != NULL) {
4990 bgp_cleanup_table(bgp, table, SAFI_EVPN);
4991 bgp_table_finish(&table);
9bcb3eef
DS
4992 bgp_dest_set_bgp_table_info(dest, NULL);
4993 bgp_dest_unlock_node(dest);
d62a17ae 4994 }
bb86c601 4995 }
718e3744 4996}
4997
d62a17ae 4998void bgp_reset(void)
718e3744 4999{
d62a17ae 5000 vty_reset();
5001 bgp_zclient_reset();
5002 access_list_reset();
5003 prefix_list_reset();
718e3744 5004}
6b0655a2 5005
d62a17ae 5006static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5007{
d62a17ae 5008 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5009 && CHECK_FLAG(peer->af_cap[afi][safi],
5010 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5011}
5012
718e3744 5013/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5014 value. */
d62a17ae 5015int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5016 struct bgp_nlri *packet)
5017{
d7c0a89a
QY
5018 uint8_t *pnt;
5019 uint8_t *lim;
d62a17ae 5020 struct prefix p;
5021 int psize;
5022 int ret;
5023 afi_t afi;
5024 safi_t safi;
5025 int addpath_encoded;
d7c0a89a 5026 uint32_t addpath_id;
d62a17ae 5027
d62a17ae 5028 pnt = packet->nlri;
5029 lim = pnt + packet->length;
5030 afi = packet->afi;
5031 safi = packet->safi;
5032 addpath_id = 0;
5033 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
5034
5035 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5036 syntactic validity. If the field is syntactically incorrect,
5037 then the Error Subcode is set to Invalid Network Field. */
5038 for (; pnt < lim; pnt += psize) {
5039 /* Clear prefix structure. */
5040 memset(&p, 0, sizeof(struct prefix));
5041
5042 if (addpath_encoded) {
5043
5044 /* When packet overflow occurs return immediately. */
761ed665 5045 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5046 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5047
a3a850a1 5048 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5049 addpath_id = ntohl(addpath_id);
d62a17ae 5050 pnt += BGP_ADDPATH_ID_LEN;
5051 }
718e3744 5052
d62a17ae 5053 /* Fetch prefix length. */
5054 p.prefixlen = *pnt++;
5055 /* afi/safi validity already verified by caller,
5056 * bgp_update_receive */
5057 p.family = afi2family(afi);
5058
5059 /* Prefix length check. */
5060 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5061 flog_err(
e50f7cfd 5062 EC_BGP_UPDATE_RCV,
14454c9f 5063 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5064 peer->host, p.prefixlen, packet->afi);
513386b5 5065 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5066 }
6b0655a2 5067
d62a17ae 5068 /* Packet size overflow check. */
5069 psize = PSIZE(p.prefixlen);
5070
5071 /* When packet overflow occur return immediately. */
5072 if (pnt + psize > lim) {
af4c2728 5073 flog_err(
e50f7cfd 5074 EC_BGP_UPDATE_RCV,
d62a17ae 5075 "%s [Error] Update packet error (prefix length %d overflows packet)",
5076 peer->host, p.prefixlen);
513386b5 5077 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5078 }
5079
5080 /* Defensive coding, double-check the psize fits in a struct
5081 * prefix */
5082 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 5083 flog_err(
e50f7cfd 5084 EC_BGP_UPDATE_RCV,
d62a17ae 5085 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5086 peer->host, p.prefixlen, sizeof(p.u));
513386b5 5087 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5088 }
5089
5090 /* Fetch prefix from NLRI packet. */
a85297a7 5091 memcpy(p.u.val, pnt, psize);
d62a17ae 5092
5093 /* Check address. */
5094 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5095 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5096 /* From RFC4271 Section 6.3:
5097 *
5098 * If a prefix in the NLRI field is semantically
5099 * incorrect
5100 * (e.g., an unexpected multicast IP address),
5101 * an error SHOULD
5102 * be logged locally, and the prefix SHOULD be
5103 * ignored.
a4d82a8a 5104 */
af4c2728 5105 flog_err(
e50f7cfd 5106 EC_BGP_UPDATE_RCV,
23d0a753
DA
5107 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5108 peer->host, &p.u.prefix4);
d62a17ae 5109 continue;
5110 }
5111 }
5112
5113 /* Check address. */
5114 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5115 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5116 char buf[BUFSIZ];
5117
af4c2728 5118 flog_err(
e50f7cfd 5119 EC_BGP_UPDATE_RCV,
d62a17ae 5120 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
5121 peer->host,
5122 inet_ntop(AF_INET6, &p.u.prefix6, buf,
5123 BUFSIZ));
5124
5125 continue;
5126 }
5127 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
5128 char buf[BUFSIZ];
5129
af4c2728 5130 flog_err(
e50f7cfd 5131 EC_BGP_UPDATE_RCV,
d62a17ae 5132 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
5133 peer->host,
5134 inet_ntop(AF_INET6, &p.u.prefix6, buf,
5135 BUFSIZ));
5136
5137 continue;
5138 }
5139 }
5140
5141 /* Normal process. */
5142 if (attr)
5143 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5144 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5145 NULL, NULL, 0, 0, NULL);
d62a17ae 5146 else
5147 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5148 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5149 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5150 NULL);
d62a17ae 5151
513386b5
DA
5152 /* Do not send BGP notification twice when maximum-prefix count
5153 * overflow. */
5154 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5155 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5156
5157 /* Address family configuration mismatch. */
d62a17ae 5158 if (ret < 0)
513386b5 5159 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5160 }
5161
5162 /* Packet length consistency check. */
5163 if (pnt != lim) {
af4c2728 5164 flog_err(
e50f7cfd 5165 EC_BGP_UPDATE_RCV,
d62a17ae 5166 "%s [Error] Update packet error (prefix length mismatch with total length)",
5167 peer->host);
513386b5 5168 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5169 }
6b0655a2 5170
513386b5 5171 return BGP_NLRI_PARSE_OK;
718e3744 5172}
5173
d62a17ae 5174static struct bgp_static *bgp_static_new(void)
718e3744 5175{
d62a17ae 5176 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5177}
5178
d62a17ae 5179static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5180{
0a22ddfb 5181 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5182 route_map_counter_decrement(bgp_static->rmap.map);
5183
0a22ddfb 5184 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5185 XFREE(MTYPE_BGP_STATIC, bgp_static);
5186}
5187
5f040085 5188void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5189 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5190{
9bcb3eef 5191 struct bgp_dest *dest;
40381db7 5192 struct bgp_path_info *pi;
4b7e6066 5193 struct bgp_path_info *new;
40381db7 5194 struct bgp_path_info rmap_path;
d62a17ae 5195 struct attr attr;
5196 struct attr *attr_new;
b68885f9 5197 route_map_result_t ret;
49e5a4a0 5198#ifdef ENABLE_BGP_VNC
d62a17ae 5199 int vnc_implicit_withdraw = 0;
65efcfce 5200#endif
fee0f4c6 5201
d62a17ae 5202 assert(bgp_static);
dd8103a9 5203
9bcb3eef 5204 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5205
d62a17ae 5206 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 5207
d62a17ae 5208 attr.nexthop = bgp_static->igpnexthop;
5209 attr.med = bgp_static->igpmetric;
5210 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5211
d62a17ae 5212 if (bgp_static->atomic)
5213 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5214
d62a17ae 5215 /* Store label index, if required. */
5216 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5217 attr.label_index = bgp_static->label_index;
5218 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5219 }
718e3744 5220
d62a17ae 5221 /* Apply route-map. */
5222 if (bgp_static->rmap.name) {
5223 struct attr attr_tmp = attr;
80ced710 5224
40381db7
DS
5225 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5226 rmap_path.peer = bgp->peer_self;
5227 rmap_path.attr = &attr_tmp;
fee0f4c6 5228
d62a17ae 5229 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5230
40381db7
DS
5231 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
5232 &rmap_path);
fee0f4c6 5233
d62a17ae 5234 bgp->peer_self->rmap_type = 0;
718e3744 5235
d62a17ae 5236 if (ret == RMAP_DENYMATCH) {
5237 /* Free uninterned attribute. */
5238 bgp_attr_flush(&attr_tmp);
718e3744 5239
d62a17ae 5240 /* Unintern original. */
5241 aspath_unintern(&attr.aspath);
5242 bgp_static_withdraw(bgp, p, afi, safi);
5243 return;
5244 }
7f323236 5245
637e5ba4 5246 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5247 bgp_attr_add_gshut_community(&attr_tmp);
5248
d62a17ae 5249 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5250 } else {
5251
637e5ba4 5252 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5253 bgp_attr_add_gshut_community(&attr);
5254
d62a17ae 5255 attr_new = bgp_attr_intern(&attr);
7f323236 5256 }
718e3744 5257
9bcb3eef 5258 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5259 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5260 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5261 break;
5262
40381db7
DS
5263 if (pi) {
5264 if (attrhash_cmp(pi->attr, attr_new)
5265 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5266 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5267 bgp_dest_unlock_node(dest);
d62a17ae 5268 bgp_attr_unintern(&attr_new);
5269 aspath_unintern(&attr.aspath);
5270 return;
5271 } else {
5272 /* The attribute is changed. */
9bcb3eef 5273 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5274
5275 /* Rewrite BGP route information. */
40381db7 5276 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5277 bgp_path_info_restore(dest, pi);
d62a17ae 5278 else
40381db7 5279 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5280#ifdef ENABLE_BGP_VNC
d62a17ae 5281 if ((afi == AFI_IP || afi == AFI_IP6)
5282 && (safi == SAFI_UNICAST)) {
40381db7 5283 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5284 /*
5285 * Implicit withdraw case.
40381db7 5286 * We have to do this before pi is
d62a17ae 5287 * changed
5288 */
5289 ++vnc_implicit_withdraw;
40381db7 5290 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5291 vnc_import_bgp_exterior_del_route(
40381db7 5292 bgp, p, pi);
d62a17ae 5293 }
5294 }
65efcfce 5295#endif
40381db7
DS
5296 bgp_attr_unintern(&pi->attr);
5297 pi->attr = attr_new;
5298 pi->uptime = bgp_clock();
49e5a4a0 5299#ifdef ENABLE_BGP_VNC
d62a17ae 5300 if ((afi == AFI_IP || afi == AFI_IP6)
5301 && (safi == SAFI_UNICAST)) {
5302 if (vnc_implicit_withdraw) {
40381db7 5303 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5304 vnc_import_bgp_exterior_add_route(
40381db7 5305 bgp, p, pi);
d62a17ae 5306 }
5307 }
65efcfce 5308#endif
718e3744 5309
d62a17ae 5310 /* Nexthop reachability check. */
892fedb6 5311 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5312 && (safi == SAFI_UNICAST
5313 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5314
5315 struct bgp *bgp_nexthop = bgp;
5316
40381db7
DS
5317 if (pi->extra && pi->extra->bgp_orig)
5318 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5319
5320 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
40381db7 5321 afi, pi, NULL, 0))
9bcb3eef 5322 bgp_path_info_set_flag(dest, pi,
18ee8310 5323 BGP_PATH_VALID);
d62a17ae 5324 else {
5325 if (BGP_DEBUG(nht, NHT)) {
5326 char buf1[INET6_ADDRSTRLEN];
5327 inet_ntop(p->family,
5328 &p->u.prefix, buf1,
5329 INET6_ADDRSTRLEN);
5330 zlog_debug(
5331 "%s(%s): Route not in table, not advertising",
15569c58 5332 __func__, buf1);
d62a17ae 5333 }
18ee8310 5334 bgp_path_info_unset_flag(
9bcb3eef 5335 dest, pi, BGP_PATH_VALID);
d62a17ae 5336 }
5337 } else {
5338 /* Delete the NHT structure if any, if we're
5339 * toggling between
5340 * enabling/disabling import check. We
5341 * deregister the route
5342 * from NHT to avoid overloading NHT and the
5343 * process interaction
5344 */
40381db7 5345 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5346 bgp_path_info_set_flag(dest, pi,
5347 BGP_PATH_VALID);
d62a17ae 5348 }
5349 /* Process change. */
40381db7 5350 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5351 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5352
5353 if (SAFI_UNICAST == safi
5354 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5355 || bgp->inst_type
5356 == BGP_INSTANCE_TYPE_DEFAULT)) {
5357 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5358 pi);
ddb5b488
PZ
5359 }
5360
9bcb3eef 5361 bgp_dest_unlock_node(dest);
d62a17ae 5362 aspath_unintern(&attr.aspath);
5363 return;
5364 }
718e3744 5365 }
718e3744 5366
d62a17ae 5367 /* Make new BGP info. */
5368 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5369 attr_new, dest);
d62a17ae 5370 /* Nexthop reachability check. */
892fedb6 5371 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5372 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 5373 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
9bcb3eef 5374 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5375 else {
5376 if (BGP_DEBUG(nht, NHT)) {
5377 char buf1[INET6_ADDRSTRLEN];
5378 inet_ntop(p->family, &p->u.prefix, buf1,
5379 INET6_ADDRSTRLEN);
5380 zlog_debug(
5381 "%s(%s): Route not in table, not advertising",
15569c58 5382 __func__, buf1);
d62a17ae 5383 }
9bcb3eef 5384 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5385 }
5386 } else {
5387 /* Delete the NHT structure if any, if we're toggling between
5388 * enabling/disabling import check. We deregister the route
5389 * from NHT to avoid overloading NHT and the process interaction
5390 */
5391 bgp_unlink_nexthop(new);
5392
9bcb3eef 5393 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 5394 }
078430f6 5395
d62a17ae 5396 /* Aggregate address increment. */
5397 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5398
d62a17ae 5399 /* Register new BGP information. */
9bcb3eef 5400 bgp_path_info_add(dest, new);
718e3744 5401
d62a17ae 5402 /* route_node_get lock */
9bcb3eef 5403 bgp_dest_unlock_node(dest);
d62a17ae 5404
5405 /* Process change. */
9bcb3eef 5406 bgp_process(bgp, dest, afi, safi);
d62a17ae 5407
ddb5b488
PZ
5408 if (SAFI_UNICAST == safi
5409 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5410 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5411 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5412 }
5413
d62a17ae 5414 /* Unintern original. */
5415 aspath_unintern(&attr.aspath);
718e3744 5416}
5417
5f040085 5418void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 5419 safi_t safi)
718e3744 5420{
9bcb3eef 5421 struct bgp_dest *dest;
40381db7 5422 struct bgp_path_info *pi;
718e3744 5423
9bcb3eef 5424 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5425
d62a17ae 5426 /* Check selected route and self inserted route. */
9bcb3eef 5427 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5428 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5429 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5430 break;
5431
5432 /* Withdraw static BGP route from routing table. */
40381db7 5433 if (pi) {
ddb5b488
PZ
5434 if (SAFI_UNICAST == safi
5435 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5436 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5437 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5438 }
40381db7
DS
5439 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5440 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5441 bgp_path_info_delete(dest, pi);
5442 bgp_process(bgp, dest, afi, safi);
d62a17ae 5443 }
718e3744 5444
d62a17ae 5445 /* Unlock bgp_node_lookup. */
9bcb3eef 5446 bgp_dest_unlock_node(dest);
718e3744 5447}
5448
137446f9
LB
5449/*
5450 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5451 */
5f040085 5452static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5453 afi_t afi, safi_t safi,
5454 struct prefix_rd *prd)
718e3744 5455{
9bcb3eef 5456 struct bgp_dest *dest;
40381db7 5457 struct bgp_path_info *pi;
718e3744 5458
9bcb3eef 5459 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5460
d62a17ae 5461 /* Check selected route and self inserted route. */
9bcb3eef 5462 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5463 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5464 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5465 break;
718e3744 5466
d62a17ae 5467 /* Withdraw static BGP route from routing table. */
40381db7 5468 if (pi) {
49e5a4a0 5469#ifdef ENABLE_BGP_VNC
d62a17ae 5470 rfapiProcessWithdraw(
40381db7 5471 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5472 1); /* Kill, since it is an administrative change */
65efcfce 5473#endif
ddb5b488
PZ
5474 if (SAFI_MPLS_VPN == safi
5475 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5476 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5477 }
40381db7 5478 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
5479 bgp_path_info_delete(dest, pi);
5480 bgp_process(bgp, dest, afi, safi);
d62a17ae 5481 }
718e3744 5482
d62a17ae 5483 /* Unlock bgp_node_lookup. */
9bcb3eef 5484 bgp_dest_unlock_node(dest);
718e3744 5485}
5486
5f040085 5487static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5488 struct bgp_static *bgp_static, afi_t afi,
5489 safi_t safi)
137446f9 5490{
9bcb3eef 5491 struct bgp_dest *dest;
4b7e6066 5492 struct bgp_path_info *new;
d62a17ae 5493 struct attr *attr_new;
5494 struct attr attr = {0};
40381db7 5495 struct bgp_path_info *pi;
49e5a4a0 5496#ifdef ENABLE_BGP_VNC
d62a17ae 5497 mpls_label_t label = 0;
65efcfce 5498#endif
d7c0a89a 5499 uint32_t num_labels = 0;
d62a17ae 5500 union gw_addr add;
137446f9 5501
d62a17ae 5502 assert(bgp_static);
137446f9 5503
b57ba6d2
MK
5504 if (bgp_static->label != MPLS_INVALID_LABEL)
5505 num_labels = 1;
9bcb3eef
DS
5506 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5507 &bgp_static->prd);
137446f9 5508
d62a17ae 5509 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5510
d62a17ae 5511 attr.nexthop = bgp_static->igpnexthop;
5512 attr.med = bgp_static->igpmetric;
5513 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5514
d62a17ae 5515 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5516 || (safi == SAFI_ENCAP)) {
5517 if (afi == AFI_IP) {
5518 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5519 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5520 }
5521 }
5522 if (afi == AFI_L2VPN) {
5523 if (bgp_static->gatewayIp.family == AF_INET)
5524 add.ipv4.s_addr =
5525 bgp_static->gatewayIp.u.prefix4.s_addr;
5526 else if (bgp_static->gatewayIp.family == AF_INET6)
5527 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5528 sizeof(struct in6_addr));
0a50c248 5529 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 5530 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5531 struct bgp_encap_type_vxlan bet;
5532 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5533 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5534 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5535 }
5536 if (bgp_static->router_mac) {
5537 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5538 }
5539 }
5540 /* Apply route-map. */
5541 if (bgp_static->rmap.name) {
5542 struct attr attr_tmp = attr;
40381db7 5543 struct bgp_path_info rmap_path;
b68885f9 5544 route_map_result_t ret;
137446f9 5545
40381db7
DS
5546 rmap_path.peer = bgp->peer_self;
5547 rmap_path.attr = &attr_tmp;
137446f9 5548
d62a17ae 5549 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5550
40381db7
DS
5551 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
5552 &rmap_path);
137446f9 5553
d62a17ae 5554 bgp->peer_self->rmap_type = 0;
137446f9 5555
d62a17ae 5556 if (ret == RMAP_DENYMATCH) {
5557 /* Free uninterned attribute. */
5558 bgp_attr_flush(&attr_tmp);
137446f9 5559
d62a17ae 5560 /* Unintern original. */
5561 aspath_unintern(&attr.aspath);
5562 bgp_static_withdraw_safi(bgp, p, afi, safi,
5563 &bgp_static->prd);
5564 return;
5565 }
137446f9 5566
d62a17ae 5567 attr_new = bgp_attr_intern(&attr_tmp);
5568 } else {
5569 attr_new = bgp_attr_intern(&attr);
5570 }
137446f9 5571
9bcb3eef 5572 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5573 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5574 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5575 break;
5576
40381db7 5577 if (pi) {
d62a17ae 5578 memset(&add, 0, sizeof(union gw_addr));
40381db7 5579 if (attrhash_cmp(pi->attr, attr_new)
0a50c248 5580 && overlay_index_equal(afi, pi, &add)
40381db7 5581 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 5582 bgp_dest_unlock_node(dest);
d62a17ae 5583 bgp_attr_unintern(&attr_new);
5584 aspath_unintern(&attr.aspath);
5585 return;
5586 } else {
5587 /* The attribute is changed. */
9bcb3eef 5588 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5589
5590 /* Rewrite BGP route information. */
40381db7 5591 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5592 bgp_path_info_restore(dest, pi);
d62a17ae 5593 else
40381db7
DS
5594 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5595 bgp_attr_unintern(&pi->attr);
5596 pi->attr = attr_new;
5597 pi->uptime = bgp_clock();
49e5a4a0 5598#ifdef ENABLE_BGP_VNC
40381db7
DS
5599 if (pi->extra)
5600 label = decode_label(&pi->extra->label[0]);
65efcfce 5601#endif
137446f9 5602
d62a17ae 5603 /* Process change. */
40381db7 5604 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5605 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5606
5607 if (SAFI_MPLS_VPN == safi
5608 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5609 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5610 }
49e5a4a0 5611#ifdef ENABLE_BGP_VNC
40381db7
DS
5612 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5613 pi->attr, afi, safi, pi->type,
5614 pi->sub_type, &label);
65efcfce 5615#endif
9bcb3eef 5616 bgp_dest_unlock_node(dest);
d62a17ae 5617 aspath_unintern(&attr.aspath);
5618 return;
5619 }
5620 }
137446f9
LB
5621
5622
d62a17ae 5623 /* Make new BGP info. */
5624 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5625 attr_new, dest);
1defdda8 5626 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5627 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5628 if (num_labels) {
5629 new->extra->label[0] = bgp_static->label;
5630 new->extra->num_labels = num_labels;
5631 }
49e5a4a0 5632#ifdef ENABLE_BGP_VNC
d62a17ae 5633 label = decode_label(&bgp_static->label);
65efcfce 5634#endif
137446f9 5635
d62a17ae 5636 /* Aggregate address increment. */
5637 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5638
d62a17ae 5639 /* Register new BGP information. */
9bcb3eef 5640 bgp_path_info_add(dest, new);
d62a17ae 5641 /* route_node_get lock */
9bcb3eef 5642 bgp_dest_unlock_node(dest);
137446f9 5643
d62a17ae 5644 /* Process change. */
9bcb3eef 5645 bgp_process(bgp, dest, afi, safi);
137446f9 5646
ddb5b488
PZ
5647 if (SAFI_MPLS_VPN == safi
5648 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5649 vpn_leak_to_vrf_update(bgp, new);
5650 }
49e5a4a0 5651#ifdef ENABLE_BGP_VNC
d62a17ae 5652 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5653 safi, new->type, new->sub_type, &label);
65efcfce
LB
5654#endif
5655
d62a17ae 5656 /* Unintern original. */
5657 aspath_unintern(&attr.aspath);
137446f9
LB
5658}
5659
718e3744 5660/* Configure static BGP network. When user don't run zebra, static
5661 route should be installed as valid. */
37a87b8f
CS
5662int bgp_static_set(struct bgp *bgp, const char *negate, struct prefix *pfx,
5663 afi_t afi, safi_t safi, const char *rmap, int backdoor,
5664 uint32_t label_index, char *errmsg, size_t errmsg_len)
d62a17ae 5665{
d62a17ae 5666 struct prefix p;
5667 struct bgp_static *bgp_static;
9bcb3eef 5668 struct bgp_dest *dest;
d7c0a89a 5669 uint8_t need_update = 0;
d62a17ae 5670
37a87b8f 5671 prefix_copy(&p, pfx);
d62a17ae 5672 apply_mask(&p);
718e3744 5673
e2a86ad9 5674 if (negate) {
718e3744 5675
e2a86ad9 5676 /* Set BGP static route configuration. */
9bcb3eef 5677 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5678
9bcb3eef 5679 if (!dest) {
37a87b8f
CS
5680 snprintf(errmsg, errmsg_len,
5681 "Can't find static route specified\n");
5682 return -1;
d62a17ae 5683 }
5684
9bcb3eef 5685 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 5686
e2a86ad9
DS
5687 if ((label_index != BGP_INVALID_LABEL_INDEX)
5688 && (label_index != bgp_static->label_index)) {
37a87b8f
CS
5689 snprintf(errmsg, errmsg_len,
5690 "label-index doesn't match static route\n");
5691 return -1;
d62a17ae 5692 }
d62a17ae 5693
e2a86ad9
DS
5694 if ((rmap && bgp_static->rmap.name)
5695 && strcmp(rmap, bgp_static->rmap.name)) {
37a87b8f
CS
5696 snprintf(errmsg, errmsg_len,
5697 "route-map name doesn't match static route\n");
5698 return -1;
d62a17ae 5699 }
718e3744 5700
e2a86ad9
DS
5701 /* Update BGP RIB. */
5702 if (!bgp_static->backdoor)
5703 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5704
e2a86ad9
DS
5705 /* Clear configuration. */
5706 bgp_static_free(bgp_static);
9bcb3eef
DS
5707 bgp_dest_set_bgp_static_info(dest, NULL);
5708 bgp_dest_unlock_node(dest);
5709 bgp_dest_unlock_node(dest);
e2a86ad9 5710 } else {
718e3744 5711
e2a86ad9 5712 /* Set BGP static route configuration. */
9bcb3eef
DS
5713 dest = bgp_node_get(bgp->route[afi][safi], &p);
5714 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 5715 if (bgp_static) {
e2a86ad9 5716 /* Configuration change. */
e2a86ad9
DS
5717 /* Label index cannot be changed. */
5718 if (bgp_static->label_index != label_index) {
37a87b8f
CS
5719 snprintf(errmsg, errmsg_len,
5720 "cannot change label-index\n");
5721 return -1;
e2a86ad9 5722 }
d62a17ae 5723
e2a86ad9 5724 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5725 if (bgp_static->valid
5726 && bgp_static->backdoor != backdoor)
e2a86ad9 5727 need_update = 1;
718e3744 5728
e2a86ad9 5729 bgp_static->backdoor = backdoor;
718e3744 5730
e2a86ad9 5731 if (rmap) {
0a22ddfb
QY
5732 XFREE(MTYPE_ROUTE_MAP_NAME,
5733 bgp_static->rmap.name);
b4897fa5 5734 route_map_counter_decrement(
5735 bgp_static->rmap.map);
e2a86ad9
DS
5736 bgp_static->rmap.name =
5737 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5738 bgp_static->rmap.map =
5739 route_map_lookup_by_name(rmap);
b4897fa5 5740 route_map_counter_increment(
5741 bgp_static->rmap.map);
e2a86ad9 5742 } else {
0a22ddfb
QY
5743 XFREE(MTYPE_ROUTE_MAP_NAME,
5744 bgp_static->rmap.name);
b4897fa5 5745 route_map_counter_decrement(
5746 bgp_static->rmap.map);
e2a86ad9
DS
5747 bgp_static->rmap.map = NULL;
5748 bgp_static->valid = 0;
5749 }
9bcb3eef 5750 bgp_dest_unlock_node(dest);
e2a86ad9
DS
5751 } else {
5752 /* New configuration. */
5753 bgp_static = bgp_static_new();
5754 bgp_static->backdoor = backdoor;
5755 bgp_static->valid = 0;
5756 bgp_static->igpmetric = 0;
975a328e 5757 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 5758 bgp_static->label_index = label_index;
718e3744 5759
e2a86ad9 5760 if (rmap) {
0a22ddfb
QY
5761 XFREE(MTYPE_ROUTE_MAP_NAME,
5762 bgp_static->rmap.name);
b4897fa5 5763 route_map_counter_decrement(
5764 bgp_static->rmap.map);
e2a86ad9
DS
5765 bgp_static->rmap.name =
5766 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5767 bgp_static->rmap.map =
5768 route_map_lookup_by_name(rmap);
b4897fa5 5769 route_map_counter_increment(
5770 bgp_static->rmap.map);
e2a86ad9 5771 }
9bcb3eef 5772 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 5773 }
d62a17ae 5774
e2a86ad9
DS
5775 bgp_static->valid = 1;
5776 if (need_update)
5777 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5778
e2a86ad9
DS
5779 if (!bgp_static->backdoor)
5780 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5781 }
d62a17ae 5782
37a87b8f 5783 return 0;
d62a17ae 5784}
5785
5786void bgp_static_add(struct bgp *bgp)
5787{
5788 afi_t afi;
5789 safi_t safi;
9bcb3eef
DS
5790 struct bgp_dest *dest;
5791 struct bgp_dest *rm;
d62a17ae 5792 struct bgp_table *table;
5793 struct bgp_static *bgp_static;
5794
05c7a1cc 5795 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5796 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5797 dest = bgp_route_next(dest)) {
5798 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5799 continue;
ea47320b 5800
05c7a1cc
QY
5801 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5802 || (safi == SAFI_EVPN)) {
9bcb3eef 5803 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5804
5805 for (rm = bgp_table_top(table); rm;
5806 rm = bgp_route_next(rm)) {
a78beeb5 5807 bgp_static =
9bcb3eef 5808 bgp_dest_get_bgp_static_info(
5a8ba9fc 5809 rm);
9bcb3eef
DS
5810 bgp_static_update_safi(
5811 bgp, bgp_dest_get_prefix(rm),
5812 bgp_static, afi, safi);
d62a17ae 5813 }
05c7a1cc 5814 } else {
5a8ba9fc 5815 bgp_static_update(
9bcb3eef
DS
5816 bgp, bgp_dest_get_prefix(dest),
5817 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 5818 safi);
ea47320b 5819 }
05c7a1cc 5820 }
6aeb9e78
DS
5821}
5822
718e3744 5823/* Called from bgp_delete(). Delete all static routes from the BGP
5824 instance. */
d62a17ae 5825void bgp_static_delete(struct bgp *bgp)
5826{
5827 afi_t afi;
5828 safi_t safi;
9bcb3eef
DS
5829 struct bgp_dest *dest;
5830 struct bgp_dest *rm;
d62a17ae 5831 struct bgp_table *table;
5832 struct bgp_static *bgp_static;
5833
05c7a1cc 5834 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5835 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5836 dest = bgp_route_next(dest)) {
5837 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5838 continue;
ea47320b 5839
05c7a1cc
QY
5840 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5841 || (safi == SAFI_EVPN)) {
9bcb3eef 5842 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5843
5844 for (rm = bgp_table_top(table); rm;
5845 rm = bgp_route_next(rm)) {
a78beeb5 5846 bgp_static =
9bcb3eef 5847 bgp_dest_get_bgp_static_info(
5a8ba9fc 5848 rm);
c7d14ba6
PG
5849 if (!bgp_static)
5850 continue;
5851
05c7a1cc 5852 bgp_static_withdraw_safi(
9bcb3eef 5853 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
5854 AFI_IP, safi,
5855 (struct prefix_rd *)
9bcb3eef
DS
5856 bgp_dest_get_prefix(
5857 dest));
ea47320b 5858 bgp_static_free(bgp_static);
811c6797 5859 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 5860 NULL);
811c6797 5861 bgp_dest_unlock_node(rm);
d62a17ae 5862 }
05c7a1cc 5863 } else {
9bcb3eef 5864 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 5865 bgp_static_withdraw(bgp,
9bcb3eef 5866 bgp_dest_get_prefix(dest),
b54892e0 5867 afi, safi);
05c7a1cc 5868 bgp_static_free(bgp_static);
9bcb3eef
DS
5869 bgp_dest_set_bgp_static_info(dest, NULL);
5870 bgp_dest_unlock_node(dest);
ea47320b 5871 }
05c7a1cc 5872 }
d62a17ae 5873}
5874
5875void bgp_static_redo_import_check(struct bgp *bgp)
5876{
5877 afi_t afi;
5878 safi_t safi;
9bcb3eef
DS
5879 struct bgp_dest *dest;
5880 struct bgp_dest *rm;
d62a17ae 5881 struct bgp_table *table;
5882 struct bgp_static *bgp_static;
5883
5884 /* Use this flag to force reprocessing of the route */
892fedb6 5885 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 5886 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
5887 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5888 dest = bgp_route_next(dest)) {
5889 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5890 continue;
ea47320b 5891
05c7a1cc
QY
5892 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5893 || (safi == SAFI_EVPN)) {
9bcb3eef 5894 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5895
5896 for (rm = bgp_table_top(table); rm;
5897 rm = bgp_route_next(rm)) {
a78beeb5 5898 bgp_static =
9bcb3eef 5899 bgp_dest_get_bgp_static_info(
5a8ba9fc 5900 rm);
9bcb3eef
DS
5901 bgp_static_update_safi(
5902 bgp, bgp_dest_get_prefix(rm),
5903 bgp_static, afi, safi);
d62a17ae 5904 }
05c7a1cc 5905 } else {
9bcb3eef
DS
5906 bgp_static = bgp_dest_get_bgp_static_info(dest);
5907 bgp_static_update(bgp,
5908 bgp_dest_get_prefix(dest),
5909 bgp_static, afi, safi);
ea47320b 5910 }
05c7a1cc
QY
5911 }
5912 }
892fedb6 5913 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 5914}
5915
5916static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
5917 safi_t safi)
5918{
5919 struct bgp_table *table;
9bcb3eef 5920 struct bgp_dest *dest;
40381db7 5921 struct bgp_path_info *pi;
d62a17ae 5922
dfb6fd1d
NT
5923 /* Do not install the aggregate route if BGP is in the
5924 * process of termination.
5925 */
892fedb6
DA
5926 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
5927 || (bgp->peer_self == NULL))
dfb6fd1d
NT
5928 return;
5929
d62a17ae 5930 table = bgp->rib[afi][safi];
9bcb3eef
DS
5931 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5932 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
5933 if (pi->peer == bgp->peer_self
5934 && ((pi->type == ZEBRA_ROUTE_BGP
5935 && pi->sub_type == BGP_ROUTE_STATIC)
5936 || (pi->type != ZEBRA_ROUTE_BGP
5937 && pi->sub_type
d62a17ae 5938 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
5939 bgp_aggregate_decrement(
5940 bgp, bgp_dest_get_prefix(dest), pi, afi,
5941 safi);
40381db7 5942 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5943 bgp_path_info_delete(dest, pi);
5944 bgp_process(bgp, dest, afi, safi);
d62a17ae 5945 }
5946 }
5947 }
ad4cbda1 5948}
5949
5950/*
5951 * Purge all networks and redistributed routes from routing table.
5952 * Invoked upon the instance going down.
5953 */
d62a17ae 5954void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 5955{
d62a17ae 5956 afi_t afi;
5957 safi_t safi;
ad4cbda1 5958
05c7a1cc
QY
5959 FOREACH_AFI_SAFI (afi, safi)
5960 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 5961}
5962
137446f9
LB
5963/*
5964 * gpz 110624
5965 * Currently this is used to set static routes for VPN and ENCAP.
5966 * I think it can probably be factored with bgp_static_set.
5967 */
d62a17ae 5968int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
5969 const char *ip_str, const char *rd_str,
5970 const char *label_str, const char *rmap_str,
5971 int evpn_type, const char *esi, const char *gwip,
5972 const char *ethtag, const char *routermac)
5973{
5974 VTY_DECLVAR_CONTEXT(bgp, bgp);
5975 int ret;
5976 struct prefix p;
5977 struct prefix_rd prd;
9bcb3eef
DS
5978 struct bgp_dest *pdest;
5979 struct bgp_dest *dest;
d62a17ae 5980 struct bgp_table *table;
5981 struct bgp_static *bgp_static;
5982 mpls_label_t label = MPLS_INVALID_LABEL;
5983 struct prefix gw_ip;
5984
5985 /* validate ip prefix */
5986 ret = str2prefix(ip_str, &p);
5987 if (!ret) {
5988 vty_out(vty, "%% Malformed prefix\n");
5989 return CMD_WARNING_CONFIG_FAILED;
5990 }
5991 apply_mask(&p);
5992 if ((afi == AFI_L2VPN)
5993 && (bgp_build_evpn_prefix(evpn_type,
5994 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5995 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5996 return CMD_WARNING_CONFIG_FAILED;
5997 }
718e3744 5998
d62a17ae 5999 ret = str2prefix_rd(rd_str, &prd);
6000 if (!ret) {
6001 vty_out(vty, "%% Malformed rd\n");
6002 return CMD_WARNING_CONFIG_FAILED;
6003 }
718e3744 6004
d62a17ae 6005 if (label_str) {
6006 unsigned long label_val;
6007 label_val = strtoul(label_str, NULL, 10);
6008 encode_label(label_val, &label);
6009 }
9bedbb1e 6010
d62a17ae 6011 if (safi == SAFI_EVPN) {
6012 if (esi && str2esi(esi, NULL) == 0) {
6013 vty_out(vty, "%% Malformed ESI\n");
6014 return CMD_WARNING_CONFIG_FAILED;
6015 }
6016 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6017 vty_out(vty, "%% Malformed Router MAC\n");
6018 return CMD_WARNING_CONFIG_FAILED;
6019 }
6020 if (gwip) {
6021 memset(&gw_ip, 0, sizeof(struct prefix));
6022 ret = str2prefix(gwip, &gw_ip);
6023 if (!ret) {
6024 vty_out(vty, "%% Malformed GatewayIp\n");
6025 return CMD_WARNING_CONFIG_FAILED;
6026 }
6027 if ((gw_ip.family == AF_INET
3714a385 6028 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6029 (struct prefix_evpn *)&p))
6030 || (gw_ip.family == AF_INET6
3714a385 6031 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6032 (struct prefix_evpn *)&p))) {
6033 vty_out(vty,
6034 "%% GatewayIp family differs with IP prefix\n");
6035 return CMD_WARNING_CONFIG_FAILED;
6036 }
6037 }
6038 }
9bcb3eef
DS
6039 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6040 if (!bgp_dest_has_bgp_path_info_data(pdest))
6041 bgp_dest_set_bgp_table_info(pdest,
67009e22 6042 bgp_table_init(bgp, afi, safi));
9bcb3eef 6043 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6044
9bcb3eef 6045 dest = bgp_node_get(table, &p);
d62a17ae 6046
9bcb3eef 6047 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6048 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6049 bgp_dest_unlock_node(dest);
d62a17ae 6050 } else {
6051 /* New configuration. */
6052 bgp_static = bgp_static_new();
6053 bgp_static->backdoor = 0;
6054 bgp_static->valid = 0;
6055 bgp_static->igpmetric = 0;
975a328e 6056 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6057 bgp_static->label = label;
6058 bgp_static->prd = prd;
6059
6060 if (rmap_str) {
0a22ddfb 6061 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6062 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6063 bgp_static->rmap.name =
6064 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6065 bgp_static->rmap.map =
6066 route_map_lookup_by_name(rmap_str);
b4897fa5 6067 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6068 }
718e3744 6069
d62a17ae 6070 if (safi == SAFI_EVPN) {
6071 if (esi) {
6072 bgp_static->eth_s_id =
6073 XCALLOC(MTYPE_ATTR,
0a50c248 6074 sizeof(esi_t));
d62a17ae 6075 str2esi(esi, bgp_static->eth_s_id);
6076 }
6077 if (routermac) {
6078 bgp_static->router_mac =
28328ea9 6079 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6080 (void)prefix_str2mac(routermac,
6081 bgp_static->router_mac);
d62a17ae 6082 }
6083 if (gwip)
6084 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6085 }
9bcb3eef 6086 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6087
d62a17ae 6088 bgp_static->valid = 1;
6089 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6090 }
718e3744 6091
d62a17ae 6092 return CMD_SUCCESS;
718e3744 6093}
6094
6095/* Configure static BGP network. */
d62a17ae 6096int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6097 const char *ip_str, const char *rd_str,
6098 const char *label_str, int evpn_type, const char *esi,
6099 const char *gwip, const char *ethtag)
6100{
6101 VTY_DECLVAR_CONTEXT(bgp, bgp);
6102 int ret;
6103 struct prefix p;
6104 struct prefix_rd prd;
9bcb3eef
DS
6105 struct bgp_dest *pdest;
6106 struct bgp_dest *dest;
d62a17ae 6107 struct bgp_table *table;
6108 struct bgp_static *bgp_static;
6109 mpls_label_t label = MPLS_INVALID_LABEL;
6110
6111 /* Convert IP prefix string to struct prefix. */
6112 ret = str2prefix(ip_str, &p);
6113 if (!ret) {
6114 vty_out(vty, "%% Malformed prefix\n");
6115 return CMD_WARNING_CONFIG_FAILED;
6116 }
6117 apply_mask(&p);
6118 if ((afi == AFI_L2VPN)
6119 && (bgp_build_evpn_prefix(evpn_type,
6120 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6121 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6122 return CMD_WARNING_CONFIG_FAILED;
6123 }
6124 ret = str2prefix_rd(rd_str, &prd);
6125 if (!ret) {
6126 vty_out(vty, "%% Malformed rd\n");
6127 return CMD_WARNING_CONFIG_FAILED;
6128 }
718e3744 6129
d62a17ae 6130 if (label_str) {
6131 unsigned long label_val;
6132 label_val = strtoul(label_str, NULL, 10);
6133 encode_label(label_val, &label);
6134 }
718e3744 6135
9bcb3eef
DS
6136 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6137 if (!bgp_dest_has_bgp_path_info_data(pdest))
6138 bgp_dest_set_bgp_table_info(pdest,
67009e22 6139 bgp_table_init(bgp, afi, safi));
d62a17ae 6140 else
9bcb3eef
DS
6141 bgp_dest_unlock_node(pdest);
6142 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6143
9bcb3eef 6144 dest = bgp_node_lookup(table, &p);
6b0655a2 6145
9bcb3eef 6146 if (dest) {
d62a17ae 6147 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6148
9bcb3eef 6149 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6150 bgp_static_free(bgp_static);
9bcb3eef
DS
6151 bgp_dest_set_bgp_static_info(dest, NULL);
6152 bgp_dest_unlock_node(dest);
6153 bgp_dest_unlock_node(dest);
d62a17ae 6154 } else
6155 vty_out(vty, "%% Can't find the route\n");
6156
6157 return CMD_SUCCESS;
6158}
6159
6160static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6161 const char *rmap_name)
6162{
6163 VTY_DECLVAR_CONTEXT(bgp, bgp);
6164 struct bgp_rmap *rmap;
6165
6166 rmap = &bgp->table_map[afi][safi];
6167 if (rmap_name) {
0a22ddfb 6168 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6169 route_map_counter_decrement(rmap->map);
d62a17ae 6170 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6171 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6172 route_map_counter_increment(rmap->map);
d62a17ae 6173 } else {
0a22ddfb 6174 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6175 route_map_counter_decrement(rmap->map);
d62a17ae 6176 rmap->map = NULL;
6177 }
73ac8160 6178
d62a17ae 6179 if (bgp_fibupd_safi(safi))
6180 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6181
d62a17ae 6182 return CMD_SUCCESS;
73ac8160
DS
6183}
6184
d62a17ae 6185static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6186 const char *rmap_name)
73ac8160 6187{
d62a17ae 6188 VTY_DECLVAR_CONTEXT(bgp, bgp);
6189 struct bgp_rmap *rmap;
73ac8160 6190
d62a17ae 6191 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6192 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6193 route_map_counter_decrement(rmap->map);
d62a17ae 6194 rmap->map = NULL;
73ac8160 6195
d62a17ae 6196 if (bgp_fibupd_safi(safi))
6197 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6198
d62a17ae 6199 return CMD_SUCCESS;
73ac8160
DS
6200}
6201
2b791107 6202void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6203 safi_t safi)
73ac8160 6204{
d62a17ae 6205 if (bgp->table_map[afi][safi].name) {
d62a17ae 6206 vty_out(vty, " table-map %s\n",
6207 bgp->table_map[afi][safi].name);
6208 }
73ac8160
DS
6209}
6210
73ac8160
DS
6211DEFUN (bgp_table_map,
6212 bgp_table_map_cmd,
6213 "table-map WORD",
6214 "BGP table to RIB route download filter\n"
6215 "Name of the route map\n")
6216{
d62a17ae 6217 int idx_word = 1;
6218 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6219 argv[idx_word]->arg);
73ac8160
DS
6220}
6221DEFUN (no_bgp_table_map,
6222 no_bgp_table_map_cmd,
6223 "no table-map WORD",
3a2d747c 6224 NO_STR
73ac8160
DS
6225 "BGP table to RIB route download filter\n"
6226 "Name of the route map\n")
6227{
d62a17ae 6228 int idx_word = 2;
6229 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6230 argv[idx_word]->arg);
73ac8160
DS
6231}
6232
37a87b8f
CS
6233DEFPY_YANG (bgp_network, bgp_network_cmd,
6234 "[no] network \
6235 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6236 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6237 backdoor$backdoor}]",
6238 NO_STR
6239 "Specify a network to announce via BGP\n"
6240 "IPv4 prefix\n"
6241 "Network number\n"
6242 "Network mask\n"
6243 "Network mask\n"
6244 "Route-map to modify the attributes\n"
6245 "Name of the route map\n"
6246 "Label index to associate with the prefix\n"
6247 "Label index value\n"
6248 "Specify a BGP backdoor route\n")
6249{
6250 char addr_prefix_str[PREFIX_STRLEN];
6251 char base_xpath[XPATH_MAXLEN];
6252 afi_t afi;
6253 safi_t safi;
e2a86ad9
DS
6254
6255 if (address_str) {
6256 int ret;
718e3744 6257
e2a86ad9
DS
6258 ret = netmask_str2prefix_str(address_str, netmask_str,
6259 addr_prefix_str);
6260 if (!ret) {
6261 vty_out(vty, "%% Inconsistent address and mask\n");
6262 return CMD_WARNING_CONFIG_FAILED;
6263 }
d62a17ae 6264 }
718e3744 6265
37a87b8f
CS
6266 afi = bgp_node_afi(vty);
6267 safi = bgp_node_safi(vty);
6268
6269 if (no) {
6270 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6271 } else {
6272 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6273
6274 if (map_name)
6275 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6276 NB_OP_CREATE, map_name);
6277 else
6278 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6279 NB_OP_DESTROY, NULL);
6280
6281 if (label_index_str)
6282 nb_cli_enqueue_change(vty, "./label-index",
6283 NB_OP_MODIFY, label_index_str);
6284
6285 nb_cli_enqueue_change(vty, "./backdoor", NB_OP_MODIFY,
6286 backdoor ? "true" : "false");
6287 }
6288
6289 snprintf(
6290 base_xpath, sizeof(base_xpath),
6291 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6292 yang_afi_safi_value2identity(afi, safi),
6293 bgp_afi_safi_get_container_str(afi, safi),
6294 address_str ? addr_prefix_str : prefix_str);
6295
6296 return nb_cli_apply_changes(vty, base_xpath);
718e3744 6297}
6298
37a87b8f
CS
6299DEFPY_YANG (ipv6_bgp_network,
6300 ipv6_bgp_network_cmd,
6301 "[no] network X:X::X:X/M$prefix \
6302 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6303 NO_STR
6304 "Specify a network to announce via BGP\n"
6305 "IPv6 prefix\n"
6306 "Route-map to modify the attributes\n"
6307 "Name of the route map\n"
6308 "Label index to associate with the prefix\n"
6309 "Label index value\n")
6310{
6311 char base_xpath[XPATH_MAXLEN];
6312 afi_t afi;
6313 safi_t safi;
6314
6315 afi = bgp_node_afi(vty);
6316 safi = bgp_node_safi(vty);
6317
6318 if (no) {
6319 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6320 } else {
6321 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6322
6323 if (map_name)
6324 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6325 NB_OP_MODIFY, map_name);
6326 else
6327 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6328 NB_OP_DESTROY, NULL);
6329
6330 if (label_index_str)
6331 nb_cli_enqueue_change(vty, "./label-index",
6332 NB_OP_MODIFY, label_index_str);
6333 }
6334
6335 snprintf(
6336 base_xpath, sizeof(base_xpath),
6337 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6338 yang_afi_safi_value2identity(afi, safi),
6339 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
6340
6341 return nb_cli_apply_changes(vty, base_xpath);
6342}
6343
6344void cli_show_bgp_global_afi_safi_network_config(struct vty *vty,
6345 struct lyd_node *dnode,
6346 bool show_defaults)
718e3744 6347{
37a87b8f
CS
6348 vty_out(vty, " network %s", yang_dnode_get_string(dnode, "./prefix"));
6349
6350 if (yang_dnode_exists(dnode, "./label-index"))
6351 vty_out(vty, " label-index %s",
6352 yang_dnode_get_string(dnode, "./label-index"));
6353
6354 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
6355 vty_out(vty, " route-map %s",
6356 yang_dnode_get_string(dnode, "./rmap-policy-export"));
6357
6358 if (yang_dnode_get_bool(dnode, "./backdoor"))
6359 vty_out(vty, " backdoor");
6360
6361 vty_out(vty, "\n");
1b6d5c7e
VV
6362}
6363
d62a17ae 6364static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6365{
d62a17ae 6366 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6367}
6368
d62a17ae 6369static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6370{
365ab2e7
RZ
6371 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6372 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6373 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6374 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6375 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6376}
718e3744 6377
365ab2e7
RZ
6378/**
6379 * Helper function to avoid repeated code: prepare variables for a
6380 * `route_map_apply` call.
6381 *
6382 * \returns `true` on route map match, otherwise `false`.
6383 */
6384static bool aggr_suppress_map_test(struct bgp *bgp,
6385 struct bgp_aggregate *aggregate,
6386 struct bgp_path_info *pi)
6387{
6388 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6389 route_map_result_t rmr = RMAP_DENYMATCH;
6390 struct bgp_path_info rmap_path = {};
6391 struct attr attr = {};
6392
6393 /* No route map entries created, just don't match. */
6394 if (aggregate->suppress_map == NULL)
6395 return false;
6396
6397 /* Call route map matching and return result. */
6398 attr.aspath = aspath_empty();
6399 rmap_path.peer = bgp->peer_self;
6400 rmap_path.attr = &attr;
6401
6402 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
6403 rmr = route_map_apply(aggregate->suppress_map, p, RMAP_BGP, &rmap_path);
6404 bgp->peer_self->rmap_type = 0;
6405
6406 bgp_attr_flush(&attr);
6407
6408 return rmr == RMAP_PERMITMATCH;
6409}
6410
4056a5f6
RZ
6411/** Test whether the aggregation has suppressed this path or not. */
6412static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6413 struct bgp_path_info *pi)
6414{
6415 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6416 return false;
6417
6418 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6419}
6420
6421/**
6422 * Suppress this path and keep the reference.
6423 *
6424 * \returns `true` if needs processing otherwise `false`.
6425 */
6426static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6427 struct bgp_path_info *pi)
6428{
6429 struct bgp_path_info_extra *pie;
6430
6431 /* Path is already suppressed by this aggregation. */
6432 if (aggr_suppress_exists(aggregate, pi))
6433 return false;
6434
6435 pie = bgp_path_info_extra_get(pi);
6436
6437 /* This is the first suppression, allocate memory and list it. */
6438 if (pie->aggr_suppressors == NULL)
6439 pie->aggr_suppressors = list_new();
6440
6441 listnode_add(pie->aggr_suppressors, aggregate);
6442
6443 /* Only mark for processing if suppressed. */
6444 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
6445 if (BGP_DEBUG(update, UPDATE_OUT))
6446 zlog_debug("aggregate-address suppressing: %pFX",
6447 bgp_dest_get_prefix(pi->net));
6448
4056a5f6
RZ
6449 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6450 return true;
6451 }
6452
6453 return false;
6454}
6455
6456/**
6457 * Unsuppress this path and remove the reference.
6458 *
6459 * \returns `true` if needs processing otherwise `false`.
6460 */
6461static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
6462 struct bgp_path_info *pi)
6463{
6464 /* Path wasn't suppressed. */
6465 if (!aggr_suppress_exists(aggregate, pi))
6466 return false;
6467
6468 listnode_delete(pi->extra->aggr_suppressors, aggregate);
6469
6470 /* Unsuppress and free extra memory if last item. */
6471 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
6472 if (BGP_DEBUG(update, UPDATE_OUT))
6473 zlog_debug("aggregate-address unsuppressing: %pFX",
6474 bgp_dest_get_prefix(pi->net));
6475
4056a5f6
RZ
6476 list_delete(&pi->extra->aggr_suppressors);
6477 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6478 return true;
6479 }
6480
6481 return false;
6482}
6483
3dc339cd
DA
6484static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6485 struct aspath *aspath,
6486 struct community *comm,
6487 struct ecommunity *ecomm,
6488 struct lcommunity *lcomm)
eaaf8adb
DS
6489{
6490 static struct aspath *ae = NULL;
6491
6492 if (!ae)
6493 ae = aspath_empty();
6494
40381db7 6495 if (!pi)
3dc339cd 6496 return false;
eaaf8adb 6497
40381db7 6498 if (origin != pi->attr->origin)
3dc339cd 6499 return false;
eaaf8adb 6500
40381db7 6501 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 6502 return false;
29f7d023 6503
40381db7 6504 if (!community_cmp(pi->attr->community, comm))
3dc339cd 6505 return false;
eaaf8adb 6506
3da2cc32 6507 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
3dc339cd 6508 return false;
eaaf8adb 6509
dd18c5a9 6510 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 6511 return false;
dd18c5a9 6512
40381db7 6513 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 6514 return false;
7ce8a8e0 6515
3dc339cd 6516 return true;
eaaf8adb
DS
6517}
6518
5f040085
DS
6519static void bgp_aggregate_install(
6520 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6521 uint8_t origin, struct aspath *aspath, struct community *community,
6522 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6523 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 6524{
9bcb3eef 6525 struct bgp_dest *dest;
c701010e 6526 struct bgp_table *table;
6f94b685 6527 struct bgp_path_info *pi, *orig, *new;
20894f50 6528 struct attr *attr;
c701010e
DS
6529
6530 table = bgp->rib[afi][safi];
6531
9bcb3eef 6532 dest = bgp_node_get(table, p);
eaaf8adb 6533
9bcb3eef 6534 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6535 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6536 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6537 break;
6538
6aabb15d
RZ
6539 /*
6540 * If we have paths with different MEDs, then don't install
6541 * (or uninstall) the aggregate route.
6542 */
6543 if (aggregate->match_med && aggregate->med_mismatched)
6544 goto uninstall_aggregate_route;
6545
c701010e 6546 if (aggregate->count > 0) {
eaaf8adb
DS
6547 /*
6548 * If the aggregate information has not changed
6549 * no need to re-install it again.
6550 */
6f94b685 6551 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6552 ecommunity, lcommunity)) {
9bcb3eef 6553 bgp_dest_unlock_node(dest);
eaaf8adb
DS
6554
6555 if (aspath)
6556 aspath_free(aspath);
6557 if (community)
3c1f53de 6558 community_free(&community);
3da2cc32
DS
6559 if (ecommunity)
6560 ecommunity_free(&ecommunity);
dd18c5a9
DS
6561 if (lcommunity)
6562 lcommunity_free(&lcommunity);
eaaf8adb
DS
6563
6564 return;
6565 }
6566
6567 /*
6568 * Mark the old as unusable
6569 */
40381db7 6570 if (pi)
9bcb3eef 6571 bgp_path_info_delete(dest, pi);
eaaf8adb 6572
20894f50
DA
6573 attr = bgp_attr_aggregate_intern(
6574 bgp, origin, aspath, community, ecommunity, lcommunity,
6575 aggregate, atomic_aggregate, p);
6576
6577 if (!attr) {
6578 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
6579 return;
6580 }
6581
3da2cc32 6582 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 6583 bgp->peer_self, attr, dest);
20894f50 6584
1defdda8 6585 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6586
9bcb3eef
DS
6587 bgp_path_info_add(dest, new);
6588 bgp_process(bgp, dest, afi, safi);
c701010e 6589 } else {
6aabb15d 6590 uninstall_aggregate_route:
6f94b685 6591 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6592 if (pi->peer == bgp->peer_self
6593 && pi->type == ZEBRA_ROUTE_BGP
6594 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6595 break;
6596
6597 /* Withdraw static BGP route from routing table. */
40381db7 6598 if (pi) {
9bcb3eef
DS
6599 bgp_path_info_delete(dest, pi);
6600 bgp_process(bgp, dest, afi, safi);
c701010e
DS
6601 }
6602 }
6603
9bcb3eef 6604 bgp_dest_unlock_node(dest);
c701010e
DS
6605}
6606
6aabb15d
RZ
6607/**
6608 * Check if the current path has different MED than other known paths.
6609 *
6610 * \returns `true` if the MED matched the others else `false`.
6611 */
6612static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
6613 struct bgp *bgp, struct bgp_path_info *pi)
6614{
6615 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
6616
6617 /* This is the first route being analyzed. */
6618 if (!aggregate->med_initialized) {
6619 aggregate->med_initialized = true;
6620 aggregate->med_mismatched = false;
6621 aggregate->med_matched_value = cur_med;
6622 } else {
6623 /* Check if routes with different MED showed up. */
6624 if (cur_med != aggregate->med_matched_value)
6625 aggregate->med_mismatched = true;
6626 }
6627
6628 return !aggregate->med_mismatched;
6629}
6630
6631/**
6632 * Initializes and tests all routes in the aggregate address path for MED
6633 * values.
6634 *
6635 * \returns `true` if all MEDs are the same otherwise `false`.
6636 */
6637static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
6638 struct bgp *bgp, const struct prefix *p,
6639 afi_t afi, safi_t safi)
6640{
6641 struct bgp_table *table = bgp->rib[afi][safi];
6642 const struct prefix *dest_p;
6643 struct bgp_dest *dest, *top;
6644 struct bgp_path_info *pi;
6645 bool med_matched = true;
6646
6647 aggregate->med_initialized = false;
6648
6649 top = bgp_node_get(table, p);
6650 for (dest = bgp_node_get(table, p); dest;
6651 dest = bgp_route_next_until(dest, top)) {
6652 dest_p = bgp_dest_get_prefix(dest);
6653 if (dest_p->prefixlen <= p->prefixlen)
6654 continue;
6655
6656 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6657 if (BGP_PATH_HOLDDOWN(pi))
6658 continue;
6659 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6660 continue;
6661 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
6662 med_matched = false;
6663 break;
6664 }
6665 }
6666 if (!med_matched)
6667 break;
6668 }
6669 bgp_dest_unlock_node(top);
6670
6671 return med_matched;
6672}
6673
6674/**
6675 * Toggles the route suppression status for this aggregate address
6676 * configuration.
6677 */
4056a5f6
RZ
6678void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
6679 struct bgp *bgp, const struct prefix *p,
6680 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
6681{
6682 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
6683 const struct prefix *dest_p;
6684 struct bgp_dest *dest, *top;
6685 struct bgp_path_info *pi;
6686 bool toggle_suppression;
6687
6688 /* We've found a different MED we must revert any suppressed routes. */
6689 top = bgp_node_get(table, p);
6690 for (dest = bgp_node_get(table, p); dest;
6691 dest = bgp_route_next_until(dest, top)) {
6692 dest_p = bgp_dest_get_prefix(dest);
6693 if (dest_p->prefixlen <= p->prefixlen)
6694 continue;
6695
6696 toggle_suppression = false;
6697 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6698 if (BGP_PATH_HOLDDOWN(pi))
6699 continue;
6700 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6701 continue;
6702
6aabb15d
RZ
6703 /* We are toggling suppression back. */
6704 if (suppress) {
6aabb15d 6705 /* Suppress route if not suppressed already. */
4056a5f6
RZ
6706 if (aggr_suppress_path(aggregate, pi))
6707 toggle_suppression = true;
6aabb15d
RZ
6708 continue;
6709 }
6710
6aabb15d 6711 /* Install route if there is no more suppression. */
4056a5f6 6712 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 6713 toggle_suppression = true;
6aabb15d
RZ
6714 }
6715
6716 if (toggle_suppression)
6717 bgp_process(bgp, dest, afi, safi);
6718 }
6719 bgp_dest_unlock_node(top);
6720}
6721
6722/**
6723 * Aggregate address MED matching incremental test: this function is called
6724 * when the initial aggregation occurred and we are only testing a single
6725 * new path.
6726 *
6727 * In addition to testing and setting the MED validity it also installs back
6728 * suppressed routes (if summary is configured).
6729 *
6730 * Must not be called in `bgp_aggregate_route`.
6731 */
6732static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
6733 struct bgp *bgp, const struct prefix *p,
6734 afi_t afi, safi_t safi,
6735 struct bgp_path_info *pi, bool is_adding)
6736{
6737 /* MED matching disabled. */
6738 if (!aggregate->match_med)
6739 return;
6740
6741 /* Aggregation with different MED, nothing to do. */
6742 if (aggregate->med_mismatched)
6743 return;
6744
6745 /*
6746 * Test the current entry:
6747 *
6748 * is_adding == true: if the new entry doesn't match then we must
6749 * install all suppressed routes.
6750 *
6751 * is_adding == false: if the entry being removed was the last
6752 * unmatching entry then we can suppress all routes.
6753 */
6754 if (!is_adding) {
6755 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
6756 && aggregate->summary_only)
6757 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
6758 safi, true);
6759 } else
6760 bgp_aggregate_med_match(aggregate, bgp, pi);
6761
6762 /* No mismatches, just quit. */
6763 if (!aggregate->med_mismatched)
6764 return;
6765
6766 /* Route summarization is disabled. */
6767 if (!aggregate->summary_only)
6768 return;
6769
6770 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
6771}
6772
b5d58c32 6773/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
6774void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
6775 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 6776{
6777 struct bgp_table *table;
9bcb3eef
DS
6778 struct bgp_dest *top;
6779 struct bgp_dest *dest;
d7c0a89a 6780 uint8_t origin;
d62a17ae 6781 struct aspath *aspath = NULL;
d62a17ae 6782 struct community *community = NULL;
3da2cc32 6783 struct ecommunity *ecommunity = NULL;
dd18c5a9 6784 struct lcommunity *lcommunity = NULL;
40381db7 6785 struct bgp_path_info *pi;
d62a17ae 6786 unsigned long match = 0;
d7c0a89a 6787 uint8_t atomic_aggregate = 0;
d62a17ae 6788
9f822fa2
S
6789 /* If the bgp instance is being deleted or self peer is deleted
6790 * then do not create aggregate route
6791 */
892fedb6
DA
6792 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6793 || (bgp->peer_self == NULL))
9f822fa2
S
6794 return;
6795
6aabb15d
RZ
6796 /* Initialize and test routes for MED difference. */
6797 if (aggregate->match_med)
6798 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
6799
4056a5f6
RZ
6800 /*
6801 * Reset aggregate count: we might've been called from route map
6802 * update so in that case we must retest all more specific routes.
6803 *
6804 * \see `bgp_route_map_process_update`.
6805 */
6806 aggregate->count = 0;
6807 aggregate->incomplete_origin_count = 0;
6808 aggregate->incomplete_origin_count = 0;
6809 aggregate->egp_origin_count = 0;
6810
d62a17ae 6811 /* ORIGIN attribute: If at least one route among routes that are
6812 aggregated has ORIGIN with the value INCOMPLETE, then the
6813 aggregated route must have the ORIGIN attribute with the value
6814 INCOMPLETE. Otherwise, if at least one route among routes that
6815 are aggregated has ORIGIN with the value EGP, then the aggregated
6816 route must have the origin attribute with the value EGP. In all
6817 other case the value of the ORIGIN attribute of the aggregated
6818 route is INTERNAL. */
6819 origin = BGP_ORIGIN_IGP;
718e3744 6820
d62a17ae 6821 table = bgp->rib[afi][safi];
718e3744 6822
d62a17ae 6823 top = bgp_node_get(table, p);
9bcb3eef
DS
6824 for (dest = bgp_node_get(table, p); dest;
6825 dest = bgp_route_next_until(dest, top)) {
6826 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6827
9bcb3eef 6828 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 6829 continue;
d62a17ae 6830
a77e2f4b
S
6831 /* If suppress fib is enabled and route not installed
6832 * in FIB, skip the route
6833 */
6834 if (!bgp_check_advertise(bgp, dest))
6835 continue;
6836
c2ff8b3e 6837 match = 0;
d62a17ae 6838
9bcb3eef 6839 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 6840 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 6841 continue;
718e3744 6842
40381db7 6843 if (pi->attr->flag
c2ff8b3e
DS
6844 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
6845 atomic_aggregate = 1;
d62a17ae 6846
40381db7 6847 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 6848 continue;
d62a17ae 6849
f273fef1
DS
6850 /*
6851 * summary-only aggregate route suppress
6852 * aggregated route announcements.
6aabb15d
RZ
6853 *
6854 * MED matching:
6855 * Don't create summaries if MED didn't match
6856 * otherwise neither the specific routes and the
6857 * aggregation will be announced.
f273fef1 6858 */
6aabb15d
RZ
6859 if (aggregate->summary_only
6860 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
6861 if (aggr_suppress_path(aggregate, pi))
6862 match++;
d62a17ae 6863 }
c2ff8b3e 6864
365ab2e7
RZ
6865 /*
6866 * Suppress more specific routes that match the route
6867 * map results.
6868 *
6869 * MED matching:
6870 * Don't suppress routes if MED matching is enabled and
6871 * it mismatched otherwise we might end up with no
6872 * routes for this path.
6873 */
6874 if (aggregate->suppress_map_name
6875 && AGGREGATE_MED_VALID(aggregate)
6876 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
6877 if (aggr_suppress_path(aggregate, pi))
6878 match++;
d62a17ae 6879 }
c2ff8b3e
DS
6880
6881 aggregate->count++;
6882
f273fef1
DS
6883 /*
6884 * If at least one route among routes that are
6885 * aggregated has ORIGIN with the value INCOMPLETE,
6886 * then the aggregated route MUST have the ORIGIN
6887 * attribute with the value INCOMPLETE. Otherwise, if
6888 * at least one route among routes that are aggregated
6889 * has ORIGIN with the value EGP, then the aggregated
6890 * route MUST have the ORIGIN attribute with the value
6891 * EGP.
6892 */
fc968841
NT
6893 switch (pi->attr->origin) {
6894 case BGP_ORIGIN_INCOMPLETE:
6895 aggregate->incomplete_origin_count++;
6896 break;
6897 case BGP_ORIGIN_EGP:
6898 aggregate->egp_origin_count++;
6899 break;
6900 default:
6901 /*Do nothing.
6902 */
6903 break;
6904 }
c2ff8b3e
DS
6905
6906 if (!aggregate->as_set)
6907 continue;
6908
f273fef1
DS
6909 /*
6910 * as-set aggregate route generate origin, as path,
6911 * and community aggregation.
6912 */
fc968841
NT
6913 /* Compute aggregate route's as-path.
6914 */
ef51a7d8 6915 bgp_compute_aggregate_aspath_hash(aggregate,
6916 pi->attr->aspath);
c2ff8b3e 6917
fc968841
NT
6918 /* Compute aggregate route's community.
6919 */
6920 if (pi->attr->community)
21fec674 6921 bgp_compute_aggregate_community_hash(
fc968841
NT
6922 aggregate,
6923 pi->attr->community);
dd18c5a9 6924
fc968841
NT
6925 /* Compute aggregate route's extended community.
6926 */
6927 if (pi->attr->ecommunity)
4edd83f9 6928 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
6929 aggregate,
6930 pi->attr->ecommunity);
6931
6932 /* Compute aggregate route's large community.
6933 */
6934 if (pi->attr->lcommunity)
f1eb1f05 6935 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
6936 aggregate,
6937 pi->attr->lcommunity);
d62a17ae 6938 }
c2ff8b3e 6939 if (match)
9bcb3eef 6940 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 6941 }
21fec674 6942 if (aggregate->as_set) {
ef51a7d8 6943 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 6944 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 6945 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 6946 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 6947 }
6948
f1eb1f05 6949
9bcb3eef 6950 bgp_dest_unlock_node(top);
718e3744 6951
718e3744 6952
fc968841
NT
6953 if (aggregate->incomplete_origin_count > 0)
6954 origin = BGP_ORIGIN_INCOMPLETE;
6955 else if (aggregate->egp_origin_count > 0)
6956 origin = BGP_ORIGIN_EGP;
d62a17ae 6957
229757f1
DA
6958 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6959 origin = aggregate->origin;
6960
fc968841
NT
6961 if (aggregate->as_set) {
6962 if (aggregate->aspath)
6963 /* Retrieve aggregate route's as-path.
6964 */
6965 aspath = aspath_dup(aggregate->aspath);
d62a17ae 6966
fc968841
NT
6967 if (aggregate->community)
6968 /* Retrieve aggregate route's community.
6969 */
6970 community = community_dup(aggregate->community);
3da2cc32 6971
fc968841
NT
6972 if (aggregate->ecommunity)
6973 /* Retrieve aggregate route's ecommunity.
6974 */
6975 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 6976
fc968841
NT
6977 if (aggregate->lcommunity)
6978 /* Retrieve aggregate route's lcommunity.
6979 */
6980 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 6981 }
718e3744 6982
c701010e 6983 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
6984 ecommunity, lcommunity, atomic_aggregate,
6985 aggregate);
718e3744 6986}
6987
5f040085
DS
6988void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
6989 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
6990{
6991 struct bgp_table *table;
9bcb3eef
DS
6992 struct bgp_dest *top;
6993 struct bgp_dest *dest;
40381db7 6994 struct bgp_path_info *pi;
3b7db173
DS
6995 unsigned long match;
6996
6997 table = bgp->rib[afi][safi];
6998
6999 /* If routes exists below this node, generate aggregate routes. */
7000 top = bgp_node_get(table, p);
9bcb3eef
DS
7001 for (dest = bgp_node_get(table, p); dest;
7002 dest = bgp_route_next_until(dest, top)) {
7003 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7004
9bcb3eef 7005 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7006 continue;
7007 match = 0;
7008
9bcb3eef 7009 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7010 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7011 continue;
7012
40381db7 7013 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7014 continue;
7015
6aabb15d
RZ
7016 if (aggregate->summary_only && pi->extra
7017 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6 7018 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7019 match++;
3b7db173 7020 }
3b7db173 7021
365ab2e7
RZ
7022 if (aggregate->suppress_map_name
7023 && AGGREGATE_MED_VALID(aggregate)
7024 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6 7025 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7026 match++;
3b7db173 7027 }
365ab2e7 7028
3b7db173 7029 aggregate->count--;
fc968841
NT
7030
7031 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7032 aggregate->incomplete_origin_count--;
7033 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7034 aggregate->egp_origin_count--;
7035
7036 if (aggregate->as_set) {
7037 /* Remove as-path from aggregate.
7038 */
ef51a7d8 7039 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7040 aggregate,
7041 pi->attr->aspath);
7042
7043 if (pi->attr->community)
7044 /* Remove community from aggregate.
7045 */
21fec674 7046 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
7047 aggregate,
7048 pi->attr->community);
7049
7050 if (pi->attr->ecommunity)
7051 /* Remove ecommunity from aggregate.
7052 */
4edd83f9 7053 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
7054 aggregate,
7055 pi->attr->ecommunity);
7056
7057 if (pi->attr->lcommunity)
7058 /* Remove lcommunity from aggregate.
7059 */
f1eb1f05 7060 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
7061 aggregate,
7062 pi->attr->lcommunity);
7063 }
3b7db173
DS
7064 }
7065
7066 /* If this node was suppressed, process the change. */
7067 if (match)
9bcb3eef 7068 bgp_process(bgp, dest, afi, safi);
3b7db173 7069 }
f1eb1f05 7070 if (aggregate->as_set) {
ef51a7d8 7071 aspath_free(aggregate->aspath);
7072 aggregate->aspath = NULL;
21fec674 7073 if (aggregate->community)
7074 community_free(&aggregate->community);
4edd83f9 7075 if (aggregate->ecommunity)
7076 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7077 if (aggregate->lcommunity)
7078 lcommunity_free(&aggregate->lcommunity);
7079 }
7080
9bcb3eef 7081 bgp_dest_unlock_node(top);
3b7db173 7082}
718e3744 7083
5f040085
DS
7084static void bgp_add_route_to_aggregate(struct bgp *bgp,
7085 const struct prefix *aggr_p,
fc968841
NT
7086 struct bgp_path_info *pinew, afi_t afi,
7087 safi_t safi,
7088 struct bgp_aggregate *aggregate)
7089{
7090 uint8_t origin;
7091 struct aspath *aspath = NULL;
7092 uint8_t atomic_aggregate = 0;
7093 struct community *community = NULL;
7094 struct ecommunity *ecommunity = NULL;
7095 struct lcommunity *lcommunity = NULL;
7096
7097 /* ORIGIN attribute: If at least one route among routes that are
7098 * aggregated has ORIGIN with the value INCOMPLETE, then the
7099 * aggregated route must have the ORIGIN attribute with the value
7100 * INCOMPLETE. Otherwise, if at least one route among routes that
7101 * are aggregated has ORIGIN with the value EGP, then the aggregated
7102 * route must have the origin attribute with the value EGP. In all
7103 * other case the value of the ORIGIN attribute of the aggregated
7104 * route is INTERNAL.
7105 */
7106 origin = BGP_ORIGIN_IGP;
7107
7108 aggregate->count++;
7109
6aabb15d
RZ
7110 /*
7111 * This must be called before `summary` check to avoid
7112 * "suppressing" twice.
7113 */
7114 if (aggregate->match_med)
7115 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7116 pinew, true);
7117
7118 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7119 aggr_suppress_path(aggregate, pinew);
fc968841 7120
365ab2e7
RZ
7121 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7122 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7123 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7124
7125 switch (pinew->attr->origin) {
7126 case BGP_ORIGIN_INCOMPLETE:
7127 aggregate->incomplete_origin_count++;
7128 break;
7129 case BGP_ORIGIN_EGP:
7130 aggregate->egp_origin_count++;
7131 break;
7132 default:
7133 /* Do nothing.
7134 */
7135 break;
7136 }
7137
7138 if (aggregate->incomplete_origin_count > 0)
7139 origin = BGP_ORIGIN_INCOMPLETE;
7140 else if (aggregate->egp_origin_count > 0)
7141 origin = BGP_ORIGIN_EGP;
7142
229757f1
DA
7143 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7144 origin = aggregate->origin;
7145
fc968841
NT
7146 if (aggregate->as_set) {
7147 /* Compute aggregate route's as-path.
7148 */
7149 bgp_compute_aggregate_aspath(aggregate,
7150 pinew->attr->aspath);
7151
7152 /* Compute aggregate route's community.
7153 */
7154 if (pinew->attr->community)
7155 bgp_compute_aggregate_community(
7156 aggregate,
7157 pinew->attr->community);
7158
7159 /* Compute aggregate route's extended community.
7160 */
7161 if (pinew->attr->ecommunity)
7162 bgp_compute_aggregate_ecommunity(
7163 aggregate,
7164 pinew->attr->ecommunity);
7165
7166 /* Compute aggregate route's large community.
7167 */
7168 if (pinew->attr->lcommunity)
7169 bgp_compute_aggregate_lcommunity(
7170 aggregate,
7171 pinew->attr->lcommunity);
7172
7173 /* Retrieve aggregate route's as-path.
7174 */
7175 if (aggregate->aspath)
7176 aspath = aspath_dup(aggregate->aspath);
7177
7178 /* Retrieve aggregate route's community.
7179 */
7180 if (aggregate->community)
7181 community = community_dup(aggregate->community);
7182
7183 /* Retrieve aggregate route's ecommunity.
7184 */
7185 if (aggregate->ecommunity)
7186 ecommunity = ecommunity_dup(aggregate->ecommunity);
7187
7188 /* Retrieve aggregate route's lcommunity.
7189 */
7190 if (aggregate->lcommunity)
7191 lcommunity = lcommunity_dup(aggregate->lcommunity);
7192 }
7193
7194 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7195 aspath, community, ecommunity,
7196 lcommunity, atomic_aggregate, aggregate);
7197}
7198
7199static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7200 safi_t safi,
7201 struct bgp_path_info *pi,
7202 struct bgp_aggregate *aggregate,
5f040085 7203 const struct prefix *aggr_p)
fc968841
NT
7204{
7205 uint8_t origin;
7206 struct aspath *aspath = NULL;
7207 uint8_t atomic_aggregate = 0;
7208 struct community *community = NULL;
7209 struct ecommunity *ecommunity = NULL;
7210 struct lcommunity *lcommunity = NULL;
7211 unsigned long match = 0;
7212
7213 if (BGP_PATH_HOLDDOWN(pi))
7214 return;
7215
7216 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7217 return;
7218
4056a5f6
RZ
7219 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7220 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7221 match++;
fc968841 7222
365ab2e7 7223 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7224 && aggr_suppress_map_test(bgp, aggregate, pi))
7225 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7226 match++;
fc968841 7227
6aabb15d 7228 /*
365ab2e7 7229 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7230 * "unsuppressing" twice.
7231 */
7232 if (aggregate->match_med)
7233 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7234 true);
7235
fc968841
NT
7236 if (aggregate->count > 0)
7237 aggregate->count--;
7238
7239 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7240 aggregate->incomplete_origin_count--;
7241 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7242 aggregate->egp_origin_count--;
7243
7244 if (aggregate->as_set) {
7245 /* Remove as-path from aggregate.
7246 */
7247 bgp_remove_aspath_from_aggregate(aggregate,
7248 pi->attr->aspath);
7249
7250 if (pi->attr->community)
7251 /* Remove community from aggregate.
7252 */
7253 bgp_remove_community_from_aggregate(
7254 aggregate,
7255 pi->attr->community);
7256
7257 if (pi->attr->ecommunity)
7258 /* Remove ecommunity from aggregate.
7259 */
7260 bgp_remove_ecommunity_from_aggregate(
7261 aggregate,
7262 pi->attr->ecommunity);
7263
7264 if (pi->attr->lcommunity)
7265 /* Remove lcommunity from aggregate.
7266 */
7267 bgp_remove_lcommunity_from_aggregate(
7268 aggregate,
7269 pi->attr->lcommunity);
7270 }
7271
7272 /* If this node was suppressed, process the change. */
7273 if (match)
7274 bgp_process(bgp, pi->net, afi, safi);
7275
7276 origin = BGP_ORIGIN_IGP;
7277 if (aggregate->incomplete_origin_count > 0)
7278 origin = BGP_ORIGIN_INCOMPLETE;
7279 else if (aggregate->egp_origin_count > 0)
7280 origin = BGP_ORIGIN_EGP;
7281
229757f1
DA
7282 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7283 origin = aggregate->origin;
7284
fc968841
NT
7285 if (aggregate->as_set) {
7286 /* Retrieve aggregate route's as-path.
7287 */
7288 if (aggregate->aspath)
7289 aspath = aspath_dup(aggregate->aspath);
7290
7291 /* Retrieve aggregate route's community.
7292 */
7293 if (aggregate->community)
7294 community = community_dup(aggregate->community);
7295
7296 /* Retrieve aggregate route's ecommunity.
7297 */
7298 if (aggregate->ecommunity)
7299 ecommunity = ecommunity_dup(aggregate->ecommunity);
7300
7301 /* Retrieve aggregate route's lcommunity.
7302 */
7303 if (aggregate->lcommunity)
7304 lcommunity = lcommunity_dup(aggregate->lcommunity);
7305 }
7306
7307 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7308 aspath, community, ecommunity,
7309 lcommunity, atomic_aggregate, aggregate);
7310}
7311
5a1ae2c2 7312void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7313 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7314{
9bcb3eef
DS
7315 struct bgp_dest *child;
7316 struct bgp_dest *dest;
d62a17ae 7317 struct bgp_aggregate *aggregate;
7318 struct bgp_table *table;
718e3744 7319
d62a17ae 7320 table = bgp->aggregate[afi][safi];
f018db83 7321
d62a17ae 7322 /* No aggregates configured. */
7323 if (bgp_table_top_nolock(table) == NULL)
7324 return;
f018db83 7325
d62a17ae 7326 if (p->prefixlen == 0)
7327 return;
718e3744 7328
40381db7 7329 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7330 return;
718e3744 7331
a77e2f4b
S
7332 /* If suppress fib is enabled and route not installed
7333 * in FIB, do not update the aggregate route
7334 */
7335 if (!bgp_check_advertise(bgp, pi->net))
7336 return;
7337
d62a17ae 7338 child = bgp_node_get(table, p);
718e3744 7339
d62a17ae 7340 /* Aggregate address configuration check. */
9bcb3eef
DS
7341 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7342 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7343
9bcb3eef
DS
7344 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7345 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7346 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7347 aggregate);
d62a17ae 7348 }
b1e62edd 7349 }
9bcb3eef 7350 bgp_dest_unlock_node(child);
718e3744 7351}
7352
5a1ae2c2 7353void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7354 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7355{
9bcb3eef
DS
7356 struct bgp_dest *child;
7357 struct bgp_dest *dest;
d62a17ae 7358 struct bgp_aggregate *aggregate;
7359 struct bgp_table *table;
718e3744 7360
d62a17ae 7361 table = bgp->aggregate[afi][safi];
718e3744 7362
d62a17ae 7363 /* No aggregates configured. */
7364 if (bgp_table_top_nolock(table) == NULL)
7365 return;
718e3744 7366
d62a17ae 7367 if (p->prefixlen == 0)
7368 return;
718e3744 7369
d62a17ae 7370 child = bgp_node_get(table, p);
718e3744 7371
d62a17ae 7372 /* Aggregate address configuration check. */
9bcb3eef
DS
7373 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7374 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7375
9bcb3eef
DS
7376 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7377 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 7378 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 7379 aggregate, dest_p);
d62a17ae 7380 }
b1e62edd 7381 }
9bcb3eef 7382 bgp_dest_unlock_node(child);
d62a17ae 7383}
718e3744 7384
718e3744 7385/* Aggregate route attribute. */
7386#define AGGREGATE_SUMMARY_ONLY 1
7387#define AGGREGATE_AS_SET 1
fb29348a 7388#define AGGREGATE_AS_UNSET 0
718e3744 7389
229757f1
DA
7390static const char *bgp_origin2str(uint8_t origin)
7391{
7392 switch (origin) {
7393 case BGP_ORIGIN_IGP:
7394 return "igp";
7395 case BGP_ORIGIN_EGP:
7396 return "egp";
7397 case BGP_ORIGIN_INCOMPLETE:
7398 return "incomplete";
7399 }
7400 return "n/a";
7401}
7402
37a87b8f
CS
7403int bgp_aggregate_unset(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7404 safi_t safi, char *errmsg, size_t errmsg_len)
718e3744 7405{
9bcb3eef 7406 struct bgp_dest *dest;
d62a17ae 7407 struct bgp_aggregate *aggregate;
718e3744 7408
37a87b8f 7409 apply_mask(prefix);
d62a17ae 7410 /* Old configuration check. */
37a87b8f 7411 dest = bgp_node_lookup(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7412 if (!dest) {
37a87b8f
CS
7413 snprintf(errmsg, errmsg_len,
7414 "There is no aggregate-address configuration.\n");
7415 return -1;
d62a17ae 7416 }
f6269b4f 7417
9bcb3eef 7418 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
37a87b8f
CS
7419 bgp_aggregate_delete(bgp, prefix, afi, safi, aggregate);
7420 bgp_aggregate_install(bgp, afi, safi, prefix, 0, NULL, NULL, NULL, NULL,
7421 0, aggregate);
d62a17ae 7422
7423 /* Unlock aggregate address configuration. */
9bcb3eef 7424 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
7425
7426 if (aggregate->community)
7427 community_free(&aggregate->community);
7428
7429 if (aggregate->community_hash) {
7430 /* Delete all communities in the hash.
7431 */
7432 hash_clean(aggregate->community_hash,
7433 bgp_aggr_community_remove);
7434 /* Free up the community_hash.
7435 */
7436 hash_free(aggregate->community_hash);
7437 }
7438
7439 if (aggregate->ecommunity)
7440 ecommunity_free(&aggregate->ecommunity);
7441
7442 if (aggregate->ecommunity_hash) {
7443 /* Delete all ecommunities in the hash.
7444 */
7445 hash_clean(aggregate->ecommunity_hash,
7446 bgp_aggr_ecommunity_remove);
7447 /* Free up the ecommunity_hash.
7448 */
7449 hash_free(aggregate->ecommunity_hash);
7450 }
7451
7452 if (aggregate->lcommunity)
7453 lcommunity_free(&aggregate->lcommunity);
7454
7455 if (aggregate->lcommunity_hash) {
7456 /* Delete all lcommunities in the hash.
7457 */
7458 hash_clean(aggregate->lcommunity_hash,
7459 bgp_aggr_lcommunity_remove);
7460 /* Free up the lcommunity_hash.
7461 */
7462 hash_free(aggregate->lcommunity_hash);
7463 }
7464
7465 if (aggregate->aspath)
7466 aspath_free(aggregate->aspath);
7467
7468 if (aggregate->aspath_hash) {
7469 /* Delete all as-paths in the hash.
7470 */
7471 hash_clean(aggregate->aspath_hash,
7472 bgp_aggr_aspath_remove);
7473 /* Free up the aspath_hash.
7474 */
7475 hash_free(aggregate->aspath_hash);
7476 }
7477
d62a17ae 7478 bgp_aggregate_free(aggregate);
9bcb3eef
DS
7479 bgp_dest_unlock_node(dest);
7480 bgp_dest_unlock_node(dest);
d62a17ae 7481
37a87b8f 7482 return 0;
d62a17ae 7483}
7484
37a87b8f
CS
7485int bgp_aggregate_set(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7486 safi_t safi, const char *rmap, uint8_t summary_only,
7487 uint8_t as_set, uint8_t origin, bool match_med,
7488 const char *suppress_map,
7489 char *errmsg, size_t errmsg_len)
d62a17ae 7490{
d62a17ae 7491 int ret;
9bcb3eef 7492 struct bgp_dest *dest;
d62a17ae 7493 struct bgp_aggregate *aggregate;
fb29348a 7494 uint8_t as_set_new = as_set;
37a87b8f 7495 char buf[PREFIX2STR_BUFFER];
d62a17ae 7496
365ab2e7 7497 if (suppress_map && summary_only) {
37a87b8f 7498 snprintf(errmsg, errmsg_len,
365ab2e7 7499 "'summary-only' and 'suppress-map' can't be used at the same time\n");
37a87b8f 7500 return -1;
365ab2e7
RZ
7501 }
7502
37a87b8f 7503 apply_mask(prefix);
d62a17ae 7504
37a87b8f
CS
7505 if ((afi == AFI_IP && prefix->prefixlen == IPV4_MAX_BITLEN)
7506 || (afi == AFI_IP6 && prefix->prefixlen == IPV6_MAX_BITLEN)) {
7507 snprintf(
7508 errmsg, errmsg_len,
7509 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7510 prefix2str(prefix, buf, PREFIX_STRLEN));
7511 return -1;
3624ac81
DS
7512 }
7513
d62a17ae 7514 /* Old configuration check. */
37a87b8f 7515 dest = bgp_node_get(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7516 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 7517
20894f50 7518 if (aggregate) {
37a87b8f
CS
7519 snprintf(errmsg, errmsg_len,
7520 "There is already same aggregate network.\n");
d62a17ae 7521 /* try to remove the old entry */
37a87b8f
CS
7522 ret = bgp_aggregate_unset(bgp, prefix, afi, safi, errmsg,
7523 errmsg_len);
d62a17ae 7524 if (ret) {
37a87b8f
CS
7525 snprintf(errmsg, errmsg_len,
7526 "Error deleting aggregate.\n");
9bcb3eef 7527 bgp_dest_unlock_node(dest);
37a87b8f 7528 return -1;
d62a17ae 7529 }
7530 }
718e3744 7531
d62a17ae 7532 /* Make aggregate address structure. */
7533 aggregate = bgp_aggregate_new();
7534 aggregate->summary_only = summary_only;
6aabb15d 7535 aggregate->match_med = match_med;
fb29348a
DA
7536
7537 /* Network operators MUST NOT locally generate any new
7538 * announcements containing AS_SET or AS_CONFED_SET. If they have
7539 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7540 * SHOULD withdraw those routes and re-announce routes for the
7541 * aggregate or component prefixes (i.e., the more-specific routes
7542 * subsumed by the previously aggregated route) without AS_SET
7543 * or AS_CONFED_SET in the updates.
7544 */
7f972cd8 7545 if (bgp->reject_as_sets) {
fb29348a
DA
7546 if (as_set == AGGREGATE_AS_SET) {
7547 as_set_new = AGGREGATE_AS_UNSET;
7548 zlog_warn(
63efca0e 7549 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 7550 __func__);
37a87b8f
CS
7551 snprintf(
7552 errmsg, errmsg_len,
fb29348a
DA
7553 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7554 }
7555 }
7556
7557 aggregate->as_set = as_set_new;
d62a17ae 7558 aggregate->safi = safi;
229757f1
DA
7559 /* Override ORIGIN attribute if defined.
7560 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7561 * to IGP which is not what rfc4271 says.
7562 * This enables the same behavior, optionally.
7563 */
7564 aggregate->origin = origin;
20894f50
DA
7565
7566 if (rmap) {
7567 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7568 route_map_counter_decrement(aggregate->rmap.map);
7569 aggregate->rmap.name =
7570 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
7571 aggregate->rmap.map = route_map_lookup_by_name(rmap);
7572 route_map_counter_increment(aggregate->rmap.map);
7573 }
365ab2e7
RZ
7574
7575 if (suppress_map) {
7576 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7577 route_map_counter_decrement(aggregate->suppress_map);
7578
7579 aggregate->suppress_map_name =
7580 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
7581 aggregate->suppress_map =
7582 route_map_lookup_by_name(aggregate->suppress_map_name);
7583 route_map_counter_increment(aggregate->suppress_map);
7584 }
7585
9bcb3eef 7586 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 7587
d62a17ae 7588 /* Aggregate address insert into BGP routing table. */
37a87b8f 7589 bgp_aggregate_route(bgp, prefix, afi, safi, aggregate);
718e3744 7590
37a87b8f 7591 return 0;
718e3744 7592}
7593
37a87b8f
CS
7594DEFPY_YANG(
7595 aggregate_addressv4, aggregate_addressv4_cmd,
7596 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
7597 "as-set$as_set_s"
7598 "|summary-only$summary_only"
7599 "|route-map WORD$rmap_name"
7600 "|origin <egp|igp|incomplete>$origin_s"
7601 "|matching-MED-only$match_med"
90e21f35 7602 "|suppress-map WORD$suppress_map"
37a87b8f
CS
7603 "}",
7604 NO_STR
7605 "Configure BGP aggregate entries\n"
7606 "Aggregate prefix\n"
7607 "Aggregate address\n"
7608 "Aggregate mask\n"
7609 "Generate AS set path information\n"
7610 "Filter more specific routes from updates\n"
7611 "Apply route map to aggregate network\n"
7612 "Route map name\n"
7613 "BGP origin code\n"
7614 "Remote EGP\n"
7615 "Local IGP\n"
7616 "Unknown heritage\n"
7617 "Only aggregate routes with matching MED\n"
90e21f35
CS
7618 "Suppress the selected more specific routes\n"
7619 "Route map with the route selectors\n")
37a87b8f
CS
7620{
7621 char base_xpath[XPATH_MAXLEN];
554b3b10 7622 safi_t safi = bgp_node_safi(vty);
554b3b10 7623 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 7624
554b3b10
RZ
7625 if (addr_str) {
7626 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf)
7627 == 0) {
7628 vty_out(vty, "%% Inconsistent address and mask\n");
7629 return CMD_WARNING_CONFIG_FAILED;
7630 }
37a87b8f
CS
7631 } else {
7632 strlcpy(prefix_buf, prefix_str, sizeof(prefix_buf));
229757f1
DA
7633 }
7634
37a87b8f
CS
7635 if (!no && origin_s)
7636 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7637
7638 if (!no && as_set_s)
7639 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7640 else
7641 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7642
7643 if (!no && summary_only)
7644 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7645 "true");
7646 else
7647 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7648 "false");
7649
fa423774
CS
7650 if (!no && match_med)
7651 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7652 else
7653 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7654 "false");
7655
37a87b8f
CS
7656 if (rmap_name)
7657 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7658 rmap_name);
7659 else
7660 nb_cli_enqueue_change(vty, "./rmap-policy-export",
7661 NB_OP_DESTROY, NULL);
7662
90e21f35
CS
7663 if (suppress_map)
7664 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7665 suppress_map);
7666 else
7667 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7668 NULL);
7669
37a87b8f
CS
7670 snprintf(
7671 base_xpath, sizeof(base_xpath),
7672 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7673 yang_afi_safi_value2identity(AFI_IP, safi),
7674 bgp_afi_safi_get_container_str(AFI_IP, safi), prefix_buf);
554b3b10 7675
554b3b10 7676 if (no)
37a87b8f
CS
7677 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7678 else
7679 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
7680
7681 return nb_cli_apply_changes(vty, base_xpath);
7682}
7683
7684DEFPY_YANG(aggregate_addressv6, aggregate_addressv6_cmd,
7685 "[no] aggregate-address X:X::X:X/M$prefix {"
7686 "as-set$as_set_s"
7687 "|summary-only$summary_only"
7688 "|route-map WORD$rmap_name"
7689 "|origin <egp|igp|incomplete>$origin_s"
7690 "|matching-MED-only$match_med"
90e21f35 7691 "|suppress-map WORD$suppress_map"
37a87b8f
CS
7692 "}",
7693 NO_STR
7694 "Configure BGP aggregate entries\n"
7695 "Aggregate prefix\n"
7696 "Generate AS set path information\n"
7697 "Filter more specific routes from updates\n"
7698 "Apply route map to aggregate network\n"
7699 "Route map name\n"
7700 "BGP origin code\n"
7701 "Remote EGP\n"
7702 "Local IGP\n"
7703 "Unknown heritage\n"
7704 "Only aggregate routes with matching MED\n"
7705 "Suppress the selected more specific routes\n"
90e21f35 7706 "Route map with the route selectors\n")
37a87b8f
CS
7707{
7708 char base_xpath[XPATH_MAXLEN];
7709 safi_t safi = bgp_node_safi(vty);
7710
7711 if (!no && origin_s)
7712 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7713
7714 if (!no && as_set_s)
7715 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7716 else
7717 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7718
7719 if (!no && summary_only)
7720 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7721 "true");
7722 else
7723 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7724 "false");
7725
fa423774
CS
7726 if (!no && match_med)
7727 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7728 else
7729 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7730 "false");
7731
37a87b8f
CS
7732 if (rmap_name)
7733 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7734 rmap_name);
7735
90e21f35
CS
7736 if (suppress_map)
7737 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7738 suppress_map);
7739 else
7740 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7741 NULL);
7742
37a87b8f
CS
7743 snprintf(
7744 base_xpath, sizeof(base_xpath),
7745 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7746 yang_afi_safi_value2identity(AFI_IP6, safi),
7747 bgp_afi_safi_get_container_str(AFI_IP6, safi), prefix_str);
7748
554b3b10 7749 if (no)
37a87b8f
CS
7750 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7751 else
7752 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
554b3b10 7753
37a87b8f
CS
7754 return nb_cli_apply_changes(vty, base_xpath);
7755}
7756
7757void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
7758 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
7759{
7760 uint8_t origin;
7761
7762 vty_out(vty, " aggregate-address %s",
7763 yang_dnode_get_string(dnode, "./prefix"));
7764
7765 if (yang_dnode_get_bool(dnode, "./as-set"))
7766 vty_out(vty, " as-set");
7767
7768 if (yang_dnode_get_bool(dnode, "./summary-only"))
7769 vty_out(vty, " summary-only");
7770
7771 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
7772 vty_out(vty, " route-map %s",
7773 yang_dnode_get_string(dnode, "./rmap-policy-export"));
7774
7775 origin = yang_dnode_get_enum(dnode, "./origin");
7776 if (origin != BGP_ORIGIN_UNSPECIFIED)
7777 vty_out(vty, " origin %s", bgp_origin2str(origin));
7778
fa423774
CS
7779 if (yang_dnode_get_bool(dnode, "./match-med"))
7780 vty_out(vty, " matching-MED-only");
7781
37a87b8f 7782 vty_out(vty, "\n");
718e3744 7783}
7784
718e3744 7785/* Redistribute route treatment. */
d62a17ae 7786void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
7787 const union g_addr *nexthop, ifindex_t ifindex,
7788 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
7789 uint8_t type, unsigned short instance,
7790 route_tag_t tag)
d62a17ae 7791{
4b7e6066 7792 struct bgp_path_info *new;
40381db7
DS
7793 struct bgp_path_info *bpi;
7794 struct bgp_path_info rmap_path;
9bcb3eef 7795 struct bgp_dest *bn;
d62a17ae 7796 struct attr attr;
7797 struct attr *new_attr;
7798 afi_t afi;
b68885f9 7799 route_map_result_t ret;
d62a17ae 7800 struct bgp_redist *red;
7801
7802 /* Make default attribute. */
7803 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
7804 /*
7805 * This must not be NULL to satisfy Coverity SA
7806 */
7807 assert(attr.aspath);
9de1f7ff 7808
a4d82a8a 7809 switch (nhtype) {
9de1f7ff
DS
7810 case NEXTHOP_TYPE_IFINDEX:
7811 break;
7812 case NEXTHOP_TYPE_IPV4:
7813 case NEXTHOP_TYPE_IPV4_IFINDEX:
7814 attr.nexthop = nexthop->ipv4;
7815 break;
7816 case NEXTHOP_TYPE_IPV6:
7817 case NEXTHOP_TYPE_IPV6_IFINDEX:
7818 attr.mp_nexthop_global = nexthop->ipv6;
7819 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
7820 break;
7821 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
7822 switch (p->family) {
7823 case AF_INET:
9de1f7ff 7824 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
7825 break;
7826 case AF_INET6:
9de1f7ff
DS
7827 memset(&attr.mp_nexthop_global, 0,
7828 sizeof(attr.mp_nexthop_global));
74489921 7829 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 7830 break;
74489921 7831 }
9de1f7ff 7832 break;
d62a17ae 7833 }
74489921 7834 attr.nh_ifindex = ifindex;
f04a80a5 7835
d62a17ae 7836 attr.med = metric;
7837 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
7838 attr.tag = tag;
718e3744 7839
d62a17ae 7840 afi = family2afi(p->family);
6aeb9e78 7841
d62a17ae 7842 red = bgp_redist_lookup(bgp, afi, type, instance);
7843 if (red) {
7844 struct attr attr_new;
718e3744 7845
d62a17ae 7846 /* Copy attribute for modification. */
6f4f49b2 7847 attr_new = attr;
718e3744 7848
d62a17ae 7849 if (red->redist_metric_flag)
7850 attr_new.med = red->redist_metric;
718e3744 7851
d62a17ae 7852 /* Apply route-map. */
7853 if (red->rmap.name) {
40381db7
DS
7854 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
7855 rmap_path.peer = bgp->peer_self;
7856 rmap_path.attr = &attr_new;
718e3744 7857
d62a17ae 7858 SET_FLAG(bgp->peer_self->rmap_type,
7859 PEER_RMAP_TYPE_REDISTRIBUTE);
7860
7861 ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
40381db7 7862 &rmap_path);
d62a17ae 7863
7864 bgp->peer_self->rmap_type = 0;
7865
7866 if (ret == RMAP_DENYMATCH) {
7867 /* Free uninterned attribute. */
7868 bgp_attr_flush(&attr_new);
7869
7870 /* Unintern original. */
7871 aspath_unintern(&attr.aspath);
7872 bgp_redistribute_delete(bgp, p, type, instance);
7873 return;
7874 }
7875 }
7876
637e5ba4 7877 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
7878 bgp_attr_add_gshut_community(&attr_new);
7879
d62a17ae 7880 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7881 SAFI_UNICAST, p, NULL);
7882
7883 new_attr = bgp_attr_intern(&attr_new);
7884
9bcb3eef 7885 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
7886 if (bpi->peer == bgp->peer_self
7887 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 7888 break;
7889
40381db7 7890 if (bpi) {
d62a17ae 7891 /* Ensure the (source route) type is updated. */
40381db7
DS
7892 bpi->type = type;
7893 if (attrhash_cmp(bpi->attr, new_attr)
7894 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 7895 bgp_attr_unintern(&new_attr);
7896 aspath_unintern(&attr.aspath);
9bcb3eef 7897 bgp_dest_unlock_node(bn);
d62a17ae 7898 return;
7899 } else {
7900 /* The attribute is changed. */
40381db7 7901 bgp_path_info_set_flag(bn, bpi,
18ee8310 7902 BGP_PATH_ATTR_CHANGED);
d62a17ae 7903
7904 /* Rewrite BGP route information. */
40381db7
DS
7905 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
7906 bgp_path_info_restore(bn, bpi);
d62a17ae 7907 else
40381db7
DS
7908 bgp_aggregate_decrement(
7909 bgp, p, bpi, afi, SAFI_UNICAST);
7910 bgp_attr_unintern(&bpi->attr);
7911 bpi->attr = new_attr;
7912 bpi->uptime = bgp_clock();
d62a17ae 7913
7914 /* Process change. */
40381db7 7915 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 7916 SAFI_UNICAST);
7917 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 7918 bgp_dest_unlock_node(bn);
d62a17ae 7919 aspath_unintern(&attr.aspath);
ddb5b488
PZ
7920
7921 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7922 || (bgp->inst_type
7923 == BGP_INSTANCE_TYPE_DEFAULT)) {
7924
7925 vpn_leak_from_vrf_update(
40381db7 7926 bgp_get_default(), bgp, bpi);
ddb5b488 7927 }
d62a17ae 7928 return;
7929 }
7930 }
7931
7932 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
7933 bgp->peer_self, new_attr, bn);
1defdda8 7934 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 7935
7936 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 7937 bgp_path_info_add(bn, new);
9bcb3eef 7938 bgp_dest_unlock_node(bn);
d62a17ae 7939 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
7940
7941 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7942 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7943
7944 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
7945 }
d62a17ae 7946 }
7947
7948 /* Unintern original. */
7949 aspath_unintern(&attr.aspath);
718e3744 7950}
7951
d7c0a89a
QY
7952void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
7953 unsigned short instance)
718e3744 7954{
d62a17ae 7955 afi_t afi;
9bcb3eef 7956 struct bgp_dest *dest;
40381db7 7957 struct bgp_path_info *pi;
d62a17ae 7958 struct bgp_redist *red;
718e3744 7959
d62a17ae 7960 afi = family2afi(p->family);
718e3744 7961
d62a17ae 7962 red = bgp_redist_lookup(bgp, afi, type, instance);
7963 if (red) {
9bcb3eef
DS
7964 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7965 SAFI_UNICAST, p, NULL);
d62a17ae 7966
9bcb3eef 7967 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 7968 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 7969 break;
7970
40381db7 7971 if (pi) {
ddb5b488
PZ
7972 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7973 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7974
7975 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7976 bgp, pi);
ddb5b488 7977 }
40381db7 7978 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
7979 bgp_path_info_delete(dest, pi);
7980 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 7981 }
9bcb3eef 7982 bgp_dest_unlock_node(dest);
d62a17ae 7983 }
7984}
7985
7986/* Withdraw specified route type's route. */
7987void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 7988 unsigned short instance)
d62a17ae 7989{
9bcb3eef 7990 struct bgp_dest *dest;
40381db7 7991 struct bgp_path_info *pi;
d62a17ae 7992 struct bgp_table *table;
7993
7994 table = bgp->rib[afi][SAFI_UNICAST];
7995
9bcb3eef
DS
7996 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
7997 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7998 if (pi->peer == bgp->peer_self && pi->type == type
7999 && pi->instance == instance)
d62a17ae 8000 break;
8001
40381db7 8002 if (pi) {
ddb5b488
PZ
8003 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8004 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8005
8006 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8007 bgp, pi);
ddb5b488 8008 }
9bcb3eef 8009 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8010 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8011 bgp_path_info_delete(dest, pi);
8012 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8013 }
718e3744 8014 }
718e3744 8015}
6b0655a2 8016
718e3744 8017/* Static function to display route. */
bd494ec5 8018static void route_vty_out_route(const struct prefix *p, struct vty *vty,
ae248832 8019 json_object *json, bool wide)
718e3744 8020{
be054588 8021 int len = 0;
d62a17ae 8022 char buf[BUFSIZ];
50e05855 8023 char buf2[BUFSIZ];
718e3744 8024
d62a17ae 8025 if (p->family == AF_INET) {
c6462ff4 8026 if (!json) {
8228a9a7 8027 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8028 } else {
8029 json_object_string_add(json, "prefix",
8030 inet_ntop(p->family,
8031 &p->u.prefix, buf,
8032 BUFSIZ));
8033 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 8034 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 8035 json_object_string_add(json, "network", buf2);
c6462ff4 8036 }
d62a17ae 8037 } else if (p->family == AF_ETHERNET) {
8228a9a7 8038 len = vty_out(vty, "%pFX", p);
b03b8898 8039 } else if (p->family == AF_EVPN) {
57f7feb6 8040 if (!json)
2dbe669b 8041 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8042 else
60466a63 8043 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8044 } else if (p->family == AF_FLOWSPEC) {
8045 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8046 json ?
8047 NLRI_STRING_FORMAT_JSON_SIMPLE :
8048 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8049 } else {
c6462ff4 8050 if (!json)
8228a9a7 8051 len = vty_out(vty, "%pFX", p);
50e05855
AD
8052 else {
8053 json_object_string_add(json, "prefix",
8054 inet_ntop(p->family,
8055 &p->u.prefix, buf,
8056 BUFSIZ));
8057 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
8058 prefix2str(p, buf2, PREFIX_STRLEN);
8059 json_object_string_add(json, "network", buf2);
8060 }
9c92b5f7 8061 }
d62a17ae 8062
9c92b5f7 8063 if (!json) {
ae248832 8064 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8065 if (len < 1)
8066 vty_out(vty, "\n%*s", 20, " ");
8067 else
8068 vty_out(vty, "%*s", len, " ");
8069 }
718e3744 8070}
8071
d62a17ae 8072enum bgp_display_type {
8073 normal_list,
718e3744 8074};
8075
18ee8310 8076/* Print the short form route status for a bgp_path_info */
4b7e6066 8077static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8078 struct bgp_path_info *path,
d62a17ae 8079 json_object *json_path)
718e3744 8080{
d62a17ae 8081 if (json_path) {
b05a1c8b 8082
d62a17ae 8083 /* Route status display. */
9b6d8fcf 8084 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8085 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8086
9b6d8fcf 8087 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8088 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8089
4056a5f6 8090 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8091 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8092
9b6d8fcf
DS
8093 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8094 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8095 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8096
d62a17ae 8097 /* Selected */
9b6d8fcf 8098 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8099 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8100
9b6d8fcf 8101 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8102 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8103
9b6d8fcf 8104 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8105 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b 8106
9b6d8fcf 8107 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8108 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8109
d62a17ae 8110 /* Internal route. */
9b6d8fcf
DS
8111 if ((path->peer->as)
8112 && (path->peer->as == path->peer->local_as))
d62a17ae 8113 json_object_string_add(json_path, "pathFrom",
8114 "internal");
8115 else
8116 json_object_string_add(json_path, "pathFrom",
8117 "external");
b05a1c8b 8118
d62a17ae 8119 return;
8120 }
b05a1c8b 8121
d62a17ae 8122 /* Route status display. */
9b6d8fcf 8123 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8124 vty_out(vty, "R");
9b6d8fcf 8125 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8126 vty_out(vty, "S");
4056a5f6 8127 else if (bgp_path_suppressed(path))
d62a17ae 8128 vty_out(vty, "s");
9b6d8fcf
DS
8129 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8130 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8131 vty_out(vty, "*");
8132 else
8133 vty_out(vty, " ");
8134
8135 /* Selected */
9b6d8fcf 8136 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8137 vty_out(vty, "h");
9b6d8fcf 8138 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8139 vty_out(vty, "d");
9b6d8fcf 8140 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8141 vty_out(vty, ">");
9b6d8fcf 8142 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8143 vty_out(vty, "=");
8144 else
8145 vty_out(vty, " ");
718e3744 8146
d62a17ae 8147 /* Internal route. */
9b6d8fcf
DS
8148 if (path->peer && (path->peer->as)
8149 && (path->peer->as == path->peer->local_as))
d62a17ae 8150 vty_out(vty, "i");
8151 else
8152 vty_out(vty, " ");
b40d939b 8153}
8154
2ba93fd6
DA
8155static char *bgp_nexthop_hostname(struct peer *peer,
8156 struct bgp_nexthop_cache *bnc)
25b5da8d 8157{
892fedb6 8158 if (peer->hostname
aef999a2 8159 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8160 return peer->hostname;
8161 return NULL;
8162}
8163
b40d939b 8164/* called from terminal list command */
bd494ec5 8165void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8166 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8167 json_object *json_paths, bool wide)
d62a17ae 8168{
aef999a2 8169 int len;
515c2602 8170 struct attr *attr = path->attr;
d62a17ae 8171 json_object *json_path = NULL;
8172 json_object *json_nexthops = NULL;
8173 json_object *json_nexthop_global = NULL;
8174 json_object *json_nexthop_ll = NULL;
6f214dd3 8175 json_object *json_ext_community = NULL;
9df8b37c 8176 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8177 bool nexthop_self =
9b6d8fcf 8178 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8179 bool nexthop_othervrf = false;
43089216 8180 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8181 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8182 char *nexthop_hostname =
8183 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8184 char esi_buf[ESI_STR_LEN];
d62a17ae 8185
8186 if (json_paths)
8187 json_path = json_object_new_object();
8188
8189 /* short status lead text */
9b6d8fcf 8190 route_vty_short_status_out(vty, path, json_path);
d62a17ae 8191
8192 if (!json_paths) {
8193 /* print prefix and mask */
8194 if (!display)
ae248832 8195 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 8196 else
ae248832 8197 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8198 } else {
ae248832 8199 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 8200 }
47fc97cc 8201
9df8b37c
PZ
8202 /*
8203 * If vrf id of nexthop is different from that of prefix,
8204 * set up printable string to append
8205 */
9b6d8fcf 8206 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8207 const char *self = "";
8208
8209 if (nexthop_self)
8210 self = "<";
8211
8212 nexthop_othervrf = true;
9b6d8fcf 8213 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8214
9b6d8fcf 8215 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8216 snprintf(vrf_id_str, sizeof(vrf_id_str),
8217 "@%s%s", VRFID_NONE_STR, self);
8218 else
8219 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8220 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8221
9b6d8fcf
DS
8222 if (path->extra->bgp_orig->inst_type
8223 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8224
9b6d8fcf 8225 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8226 } else {
8227 const char *self = "";
8228
8229 if (nexthop_self)
8230 self = "<";
8231
8232 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8233 }
8234
445c2480
DS
8235 /*
8236 * For ENCAP and EVPN routes, nexthop address family is not
8237 * neccessarily the same as the prefix address family.
8238 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8239 * EVPN routes are also exchanged with a MP nexthop. Currently,
8240 * this
8241 * is only IPv4, the value will be present in either
8242 * attr->nexthop or
8243 * attr->mp_nexthop_global_in
8244 */
8245 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8246 char buf[BUFSIZ];
8247 char nexthop[128];
8248 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8249
8250 switch (af) {
8251 case AF_INET:
772270f3
QY
8252 snprintf(nexthop, sizeof(nexthop), "%s",
8253 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8254 BUFSIZ));
445c2480
DS
8255 break;
8256 case AF_INET6:
772270f3
QY
8257 snprintf(nexthop, sizeof(nexthop), "%s",
8258 inet_ntop(af, &attr->mp_nexthop_global, buf,
8259 BUFSIZ));
445c2480
DS
8260 break;
8261 default:
772270f3 8262 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8263 break;
d62a17ae 8264 }
d62a17ae 8265
445c2480
DS
8266 if (json_paths) {
8267 json_nexthop_global = json_object_new_object();
8268
515c2602
DA
8269 json_object_string_add(json_nexthop_global, "ip",
8270 nexthop);
8271
939a97f4 8272 if (path->peer->hostname)
515c2602
DA
8273 json_object_string_add(json_nexthop_global,
8274 "hostname",
939a97f4 8275 path->peer->hostname);
515c2602
DA
8276
8277 json_object_string_add(json_nexthop_global, "afi",
8278 (af == AF_INET) ? "ipv4"
8279 : "ipv6");
445c2480
DS
8280 json_object_boolean_true_add(json_nexthop_global,
8281 "used");
aef999a2
DA
8282 } else {
8283 if (nexthop_hostname)
8284 len = vty_out(vty, "%s(%s)%s", nexthop,
8285 nexthop_hostname, vrf_id_str);
8286 else
8287 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8288
ae248832 8289 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8290 if (len < 1)
8291 vty_out(vty, "\n%*s", 36, " ");
8292 else
8293 vty_out(vty, "%*s", len, " ");
8294 }
445c2480
DS
8295 } else if (safi == SAFI_EVPN) {
8296 if (json_paths) {
23d0a753
DA
8297 char buf[BUFSIZ] = {0};
8298
445c2480
DS
8299 json_nexthop_global = json_object_new_object();
8300
515c2602 8301 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8302 inet_ntop(AF_INET,
8303 &attr->nexthop, buf,
8304 sizeof(buf)));
515c2602 8305
939a97f4 8306 if (path->peer->hostname)
515c2602
DA
8307 json_object_string_add(json_nexthop_global,
8308 "hostname",
939a97f4 8309 path->peer->hostname);
515c2602 8310
a4d82a8a
PZ
8311 json_object_string_add(json_nexthop_global, "afi",
8312 "ipv4");
445c2480
DS
8313 json_object_boolean_true_add(json_nexthop_global,
8314 "used");
aef999a2
DA
8315 } else {
8316 if (nexthop_hostname)
8317 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8318 nexthop_hostname, vrf_id_str);
8319 else
8320 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8321 vrf_id_str);
8322
ae248832 8323 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8324 if (len < 1)
8325 vty_out(vty, "\n%*s", 36, " ");
8326 else
8327 vty_out(vty, "%*s", len, " ");
8328 }
d33fc23b 8329 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8330 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a 8331 if (json_paths) {
23d0a753
DA
8332 char buf[BUFSIZ] = {0};
8333
026b914a 8334 json_nexthop_global = json_object_new_object();
515c2602 8335
026b914a
PG
8336 json_object_string_add(json_nexthop_global,
8337 "afi", "ipv4");
515c2602
DA
8338 json_object_string_add(
8339 json_nexthop_global, "ip",
23d0a753
DA
8340 inet_ntop(AF_INET, &attr->nexthop, buf,
8341 sizeof(buf)));
515c2602 8342
939a97f4 8343 if (path->peer->hostname)
515c2602
DA
8344 json_object_string_add(
8345 json_nexthop_global, "hostname",
939a97f4 8346 path->peer->hostname);
515c2602 8347
50e05855
AD
8348 json_object_boolean_true_add(
8349 json_nexthop_global,
026b914a
PG
8350 "used");
8351 } else {
aef999a2
DA
8352 if (nexthop_hostname)
8353 len = vty_out(vty, "%pI4(%s)%s",
8354 &attr->nexthop,
8355 nexthop_hostname,
8356 vrf_id_str);
8357 else
8358 len = vty_out(vty, "%pI4%s",
8359 &attr->nexthop,
8360 vrf_id_str);
8361
ae248832 8362 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8363 if (len < 1)
8364 vty_out(vty, "\n%*s", 36, " ");
8365 else
8366 vty_out(vty, "%*s", len, " ");
026b914a
PG
8367 }
8368 }
d33fc23b 8369 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8370 if (json_paths) {
23d0a753
DA
8371 char buf[BUFSIZ] = {0};
8372
445c2480 8373 json_nexthop_global = json_object_new_object();
d62a17ae 8374
515c2602 8375 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8376 inet_ntop(AF_INET,
8377 &attr->nexthop, buf,
8378 sizeof(buf)));
515c2602 8379
939a97f4 8380 if (path->peer->hostname)
515c2602
DA
8381 json_object_string_add(json_nexthop_global,
8382 "hostname",
939a97f4 8383 path->peer->hostname);
445c2480 8384
a4d82a8a
PZ
8385 json_object_string_add(json_nexthop_global, "afi",
8386 "ipv4");
445c2480
DS
8387 json_object_boolean_true_add(json_nexthop_global,
8388 "used");
8389 } else {
aef999a2
DA
8390 if (nexthop_hostname)
8391 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8392 nexthop_hostname, vrf_id_str);
8393 else
8394 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8395 vrf_id_str);
9df8b37c 8396
ae248832 8397 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8398 if (len < 1)
8399 vty_out(vty, "\n%*s", 36, " ");
8400 else
8401 vty_out(vty, "%*s", len, " ");
d62a17ae 8402 }
445c2480 8403 }
b05a1c8b 8404
445c2480 8405 /* IPv6 Next Hop */
a4d82a8a 8406 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8407 char buf[BUFSIZ];
d62a17ae 8408
445c2480
DS
8409 if (json_paths) {
8410 json_nexthop_global = json_object_new_object();
a4d82a8a 8411 json_object_string_add(
515c2602
DA
8412 json_nexthop_global, "ip",
8413 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8414 buf, BUFSIZ));
8415
939a97f4 8416 if (path->peer->hostname)
515c2602
DA
8417 json_object_string_add(json_nexthop_global,
8418 "hostname",
939a97f4 8419 path->peer->hostname);
515c2602 8420
a4d82a8a
PZ
8421 json_object_string_add(json_nexthop_global, "afi",
8422 "ipv6");
8423 json_object_string_add(json_nexthop_global, "scope",
8424 "global");
445c2480
DS
8425
8426 /* We display both LL & GL if both have been
8427 * received */
0606039c
DA
8428 if ((attr->mp_nexthop_len
8429 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 8430 || (path->peer->conf_if)) {
a4d82a8a 8431 json_nexthop_ll = json_object_new_object();
d62a17ae 8432 json_object_string_add(
515c2602
DA
8433 json_nexthop_ll, "ip",
8434 inet_ntop(AF_INET6,
8435 &attr->mp_nexthop_local, buf,
8436 BUFSIZ));
8437
939a97f4 8438 if (path->peer->hostname)
515c2602
DA
8439 json_object_string_add(
8440 json_nexthop_ll, "hostname",
939a97f4 8441 path->peer->hostname);
515c2602 8442
a4d82a8a
PZ
8443 json_object_string_add(json_nexthop_ll, "afi",
8444 "ipv6");
8445 json_object_string_add(json_nexthop_ll, "scope",
445c2480 8446 "link-local");
d62a17ae 8447
a4d82a8a
PZ
8448 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8449 &attr->mp_nexthop_local)
445c2480
DS
8450 != 0)
8451 && !attr->mp_nexthop_prefer_global)
d62a17ae 8452 json_object_boolean_true_add(
a4d82a8a 8453 json_nexthop_ll, "used");
445c2480
DS
8454 else
8455 json_object_boolean_true_add(
a4d82a8a 8456 json_nexthop_global, "used");
445c2480
DS
8457 } else
8458 json_object_boolean_true_add(
8459 json_nexthop_global, "used");
8460 } else {
8461 /* Display LL if LL/Global both in table unless
8462 * prefer-global is set */
0606039c
DA
8463 if (((attr->mp_nexthop_len
8464 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 8465 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
8466 || (path->peer->conf_if)) {
8467 if (path->peer->conf_if) {
a4d82a8a 8468 len = vty_out(vty, "%s",
9b6d8fcf 8469 path->peer->conf_if);
ae248832
MK
8470 /* len of IPv6 addr + max len of def
8471 * ifname */
8472 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8473
8474 if (len < 1)
a4d82a8a 8475 vty_out(vty, "\n%*s", 36, " ");
445c2480 8476 else
a4d82a8a 8477 vty_out(vty, "%*s", len, " ");
d62a17ae 8478 } else {
aef999a2
DA
8479 if (nexthop_hostname)
8480 len = vty_out(
8481 vty, "%pI6(%s)%s",
8482 &attr->mp_nexthop_local,
8483 nexthop_hostname,
8484 vrf_id_str);
8485 else
8486 len = vty_out(
8487 vty, "%pI6%s",
8488 &attr->mp_nexthop_local,
8489 vrf_id_str);
8490
ae248832 8491 len = wide ? (41 - len) : (16 - len);
d62a17ae 8492
8493 if (len < 1)
a4d82a8a 8494 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 8495 else
a4d82a8a 8496 vty_out(vty, "%*s", len, " ");
d62a17ae 8497 }
445c2480 8498 } else {
aef999a2
DA
8499 if (nexthop_hostname)
8500 len = vty_out(vty, "%pI6(%s)%s",
8501 &attr->mp_nexthop_global,
8502 nexthop_hostname,
8503 vrf_id_str);
8504 else
8505 len = vty_out(vty, "%pI6%s",
8506 &attr->mp_nexthop_global,
8507 vrf_id_str);
8508
ae248832 8509 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8510
8511 if (len < 1)
8512 vty_out(vty, "\n%*s", 36, " ");
8513 else
8514 vty_out(vty, "%*s", len, " ");
d62a17ae 8515 }
8516 }
445c2480 8517 }
718e3744 8518
445c2480
DS
8519 /* MED/Metric */
8520 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 8521 if (json_paths)
50e05855 8522 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
8523 else if (wide)
8524 vty_out(vty, "%7u", attr->med);
0fbac0b4 8525 else
445c2480 8526 vty_out(vty, "%10u", attr->med);
ae248832
MK
8527 else if (!json_paths) {
8528 if (wide)
8529 vty_out(vty, "%*s", 7, " ");
8530 else
8531 vty_out(vty, "%*s", 10, " ");
8532 }
d62a17ae 8533
445c2480
DS
8534 /* Local Pref */
8535 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 8536 if (json_paths)
50e05855 8537 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
8538 attr->local_pref);
8539 else
445c2480
DS
8540 vty_out(vty, "%7u", attr->local_pref);
8541 else if (!json_paths)
8542 vty_out(vty, " ");
d62a17ae 8543
445c2480
DS
8544 if (json_paths)
8545 json_object_int_add(json_path, "weight", attr->weight);
8546 else
8547 vty_out(vty, "%7u ", attr->weight);
47fc97cc 8548
445c2480
DS
8549 if (json_paths) {
8550 char buf[BUFSIZ];
a4d82a8a
PZ
8551 json_object_string_add(
8552 json_path, "peerId",
9b6d8fcf 8553 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 8554 }
b05a1c8b 8555
445c2480
DS
8556 /* Print aspath */
8557 if (attr->aspath) {
0fbac0b4 8558 if (json_paths)
50e05855 8559 json_object_string_add(json_path, "path",
0fbac0b4
DA
8560 attr->aspath->str);
8561 else
445c2480 8562 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8563 }
f1aa5d8a 8564
445c2480
DS
8565 /* Print origin */
8566 if (json_paths)
a4d82a8a
PZ
8567 json_object_string_add(json_path, "origin",
8568 bgp_origin_long_str[attr->origin]);
445c2480
DS
8569 else
8570 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8571
9df8b37c 8572 if (json_paths) {
d071f237 8573 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
8574 json_object_string_add(json_path, "esi",
8575 esi_to_str(&attr->esi,
8576 esi_buf, sizeof(esi_buf)));
8577 }
6f214dd3
CS
8578 if (safi == SAFI_EVPN &&
8579 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8580 json_ext_community = json_object_new_object();
8581 json_object_string_add(json_ext_community,
8582 "string",
8583 attr->ecommunity->str);
8584 json_object_object_add(json_path,
8585 "extendedCommunity",
8586 json_ext_community);
8587 }
8588
9df8b37c
PZ
8589 if (nexthop_self)
8590 json_object_boolean_true_add(json_path,
8591 "announceNexthopSelf");
8592 if (nexthop_othervrf) {
8593 json_object_string_add(json_path, "nhVrfName",
8594 nexthop_vrfname);
8595
8596 json_object_int_add(json_path, "nhVrfId",
8597 ((nexthop_vrfid == VRF_UNKNOWN)
8598 ? -1
8599 : (int)nexthop_vrfid));
8600 }
8601 }
8602
d62a17ae 8603 if (json_paths) {
8604 if (json_nexthop_global || json_nexthop_ll) {
8605 json_nexthops = json_object_new_array();
f1aa5d8a 8606
d62a17ae 8607 if (json_nexthop_global)
8608 json_object_array_add(json_nexthops,
8609 json_nexthop_global);
f1aa5d8a 8610
d62a17ae 8611 if (json_nexthop_ll)
8612 json_object_array_add(json_nexthops,
8613 json_nexthop_ll);
f1aa5d8a 8614
d62a17ae 8615 json_object_object_add(json_path, "nexthops",
8616 json_nexthops);
8617 }
8618
8619 json_object_array_add(json_paths, json_path);
8620 } else {
8621 vty_out(vty, "\n");
6f214dd3 8622
b5e140c8 8623 if (safi == SAFI_EVPN) {
d071f237 8624 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
8625 vty_out(vty, "%*s", 20, " ");
8626 vty_out(vty, "ESI:%s\n",
8627 esi_to_str(&attr->esi,
8628 esi_buf, sizeof(esi_buf)));
8629 }
8630 if (attr->flag &
8631 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8632 vty_out(vty, "%*s", 20, " ");
8633 vty_out(vty, "%s\n", attr->ecommunity->str);
8634 }
6f214dd3
CS
8635 }
8636
49e5a4a0 8637#ifdef ENABLE_BGP_VNC
d62a17ae 8638 /* prints an additional line, indented, with VNC info, if
8639 * present */
8640 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 8641 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 8642#endif
d62a17ae 8643 }
8644}
718e3744 8645
8646/* called from terminal list command */
5f040085
DS
8647void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
8648 struct attr *attr, safi_t safi, bool use_json,
ae248832 8649 json_object *json_ar, bool wide)
d62a17ae 8650{
8651 json_object *json_status = NULL;
8652 json_object *json_net = NULL;
aef999a2 8653 int len;
d62a17ae 8654 char buff[BUFSIZ];
dc387b0f 8655
d62a17ae 8656 /* Route status display. */
8657 if (use_json) {
8658 json_status = json_object_new_object();
8659 json_net = json_object_new_object();
8660 } else {
8661 vty_out(vty, "*");
8662 vty_out(vty, ">");
8663 vty_out(vty, " ");
8664 }
718e3744 8665
d62a17ae 8666 /* print prefix and mask */
50e05855 8667 if (use_json) {
dc387b0f
LK
8668 if (safi == SAFI_EVPN)
8669 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
8670 else if (p->family == AF_INET || p->family == AF_INET6) {
8671 json_object_string_add(
8672 json_net, "addrPrefix",
8673 inet_ntop(p->family, &p->u.prefix, buff,
8674 BUFSIZ));
8675 json_object_int_add(json_net, "prefixLen",
8676 p->prefixlen);
8677 prefix2str(p, buff, PREFIX_STRLEN);
8678 json_object_string_add(json_net, "network", buff);
8679 }
50e05855 8680 } else
ae248832 8681 route_vty_out_route(p, vty, NULL, wide);
d62a17ae 8682
8683 /* Print attribute */
8684 if (attr) {
8685 if (use_json) {
23d0a753
DA
8686 char buf[BUFSIZ] = {0};
8687
d62a17ae 8688 if (p->family == AF_INET
8689 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 8690 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 8691 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 8692 json_object_string_add(
8693 json_net, "nextHop",
23d0a753
DA
8694 inet_ntop(
8695 AF_INET,
8696 &attr->mp_nexthop_global_in,
8697 buf, sizeof(buf)));
d62a17ae 8698 else
8699 json_object_string_add(
8700 json_net, "nextHop",
23d0a753
DA
8701 inet_ntop(AF_INET,
8702 &attr->nexthop, buf,
8703 sizeof(buf)));
d62a17ae 8704 } else if (p->family == AF_INET6
8705 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8706 char buf[BUFSIZ];
8707
8708 json_object_string_add(
aa0a10fc 8709 json_net, "nextHopGlobal",
d62a17ae 8710 inet_ntop(AF_INET6,
8711 &attr->mp_nexthop_global, buf,
8712 BUFSIZ));
23d0a753
DA
8713 } else if (p->family == AF_EVPN
8714 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8715 char buf[BUFSIZ] = {0};
8716
8717 json_object_string_add(
8718 json_net, "nextHop",
8719 inet_ntop(AF_INET,
8720 &attr->mp_nexthop_global_in,
8721 buf, sizeof(buf)));
8722 }
d62a17ae 8723
8724 if (attr->flag
8725 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8726 json_object_int_add(json_net, "metric",
8727 attr->med);
8728
0fbac0b4 8729 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 8730 json_object_int_add(json_net, "locPrf",
0fbac0b4 8731 attr->local_pref);
d62a17ae 8732
8733 json_object_int_add(json_net, "weight", attr->weight);
8734
8735 /* Print aspath */
0fbac0b4 8736 if (attr->aspath)
50e05855 8737 json_object_string_add(json_net, "path",
0fbac0b4 8738 attr->aspath->str);
d62a17ae 8739
8740 /* Print origin */
8741 json_object_string_add(json_net, "bgpOriginCode",
8742 bgp_origin_str[attr->origin]);
8743 } else {
8744 if (p->family == AF_INET
8745 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8746 || safi == SAFI_EVPN
8747 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8748 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8749 || safi == SAFI_EVPN)
23d0a753
DA
8750 vty_out(vty, "%-16pI4",
8751 &attr->mp_nexthop_global_in);
ae248832 8752 else if (wide)
23d0a753 8753 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 8754 else
23d0a753 8755 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 8756 } else if (p->family == AF_INET6
8757 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 8758 char buf[BUFSIZ];
8759
8760 len = vty_out(
8761 vty, "%s",
8762 inet_ntop(AF_INET6,
8763 &attr->mp_nexthop_global, buf,
8764 BUFSIZ));
ae248832 8765 len = wide ? (41 - len) : (16 - len);
d62a17ae 8766 if (len < 1)
8767 vty_out(vty, "\n%*s", 36, " ");
8768 else
8769 vty_out(vty, "%*s", len, " ");
8770 }
8771 if (attr->flag
8772 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
8773 if (wide)
8774 vty_out(vty, "%7u", attr->med);
8775 else
8776 vty_out(vty, "%10u", attr->med);
8777 else if (wide)
8778 vty_out(vty, " ");
d62a17ae 8779 else
8780 vty_out(vty, " ");
718e3744 8781
d62a17ae 8782 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
8783 vty_out(vty, "%7u", attr->local_pref);
8784 else
8785 vty_out(vty, " ");
8786
8787 vty_out(vty, "%7u ", attr->weight);
8788
8789 /* Print aspath */
8790 if (attr->aspath)
8791 aspath_print_vty(vty, "%s", attr->aspath, " ");
8792
8793 /* Print origin */
8794 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8795 }
8796 }
8797 if (use_json) {
8798 json_object_boolean_true_add(json_status, "*");
8799 json_object_boolean_true_add(json_status, ">");
8800 json_object_object_add(json_net, "appliedStatusSymbols",
8801 json_status);
1608ff77 8802
dc387b0f
LK
8803 prefix2str(p, buff, PREFIX_STRLEN);
8804 json_object_object_add(json_ar, buff, json_net);
d62a17ae 8805 } else
8806 vty_out(vty, "\n");
8807}
8808
bd494ec5 8809void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 8810 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 8811 json_object *json)
8812{
8813 json_object *json_out = NULL;
8814 struct attr *attr;
8815 mpls_label_t label = MPLS_INVALID_LABEL;
8816
9b6d8fcf 8817 if (!path->extra)
d62a17ae 8818 return;
8819
8820 if (json)
8821 json_out = json_object_new_object();
8822
8823 /* short status lead text */
9b6d8fcf 8824 route_vty_short_status_out(vty, path, json_out);
d62a17ae 8825
8826 /* print prefix and mask */
8827 if (json == NULL) {
8828 if (!display)
ae248832 8829 route_vty_out_route(p, vty, NULL, false);
d62a17ae 8830 else
8831 vty_out(vty, "%*s", 17, " ");
8832 }
8833
8834 /* Print attribute */
9b6d8fcf 8835 attr = path->attr;
05864da7
DS
8836 if (((p->family == AF_INET)
8837 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8838 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8839 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
8840 char buf[BUFSIZ] = {0};
8841
05864da7
DS
8842 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8843 || safi == SAFI_EVPN) {
8844 if (json)
8845 json_object_string_add(
8846 json_out, "mpNexthopGlobalIn",
23d0a753
DA
8847 inet_ntop(AF_INET,
8848 &attr->mp_nexthop_global_in,
8849 buf, sizeof(buf)));
05864da7 8850 else
23d0a753
DA
8851 vty_out(vty, "%-16pI4",
8852 &attr->mp_nexthop_global_in);
05864da7
DS
8853 } else {
8854 if (json)
8855 json_object_string_add(
8856 json_out, "nexthop",
23d0a753
DA
8857 inet_ntop(AF_INET, &attr->nexthop, buf,
8858 sizeof(buf)));
05864da7 8859 else
23d0a753 8860 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
8861 }
8862 } else if (((p->family == AF_INET6)
8863 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8864 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8865 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8866 char buf_a[512];
8867
8868 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
8869 if (json)
8870 json_object_string_add(
8871 json_out, "mpNexthopGlobalIn",
8872 inet_ntop(AF_INET6,
8873 &attr->mp_nexthop_global,
8874 buf_a, sizeof(buf_a)));
8875 else
8876 vty_out(vty, "%s",
8877 inet_ntop(AF_INET6,
8878 &attr->mp_nexthop_global,
8879 buf_a, sizeof(buf_a)));
8880 } else if (attr->mp_nexthop_len
8881 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
8882 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
8883 &attr->mp_nexthop_global,
8884 &attr->mp_nexthop_local);
8885 if (json)
8886 json_object_string_add(json_out,
8887 "mpNexthopGlobalLocal",
8888 buf_a);
8889 else
8890 vty_out(vty, "%s", buf_a);
d62a17ae 8891 }
8892 }
8893
9b6d8fcf 8894 label = decode_label(&path->extra->label[0]);
d62a17ae 8895
8896 if (bgp_is_valid_label(&label)) {
8897 if (json) {
8898 json_object_int_add(json_out, "notag", label);
8899 json_object_array_add(json, json_out);
8900 } else {
8901 vty_out(vty, "notag/%d", label);
8902 vty_out(vty, "\n");
8903 }
8904 }
8905}
718e3744 8906
bd494ec5 8907void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 8908 struct bgp_path_info *path, int display,
d62a17ae 8909 json_object *json_paths)
718e3744 8910{
d62a17ae 8911 struct attr *attr;
14f51eba 8912 char buf[BUFSIZ] = {0};
d62a17ae 8913 json_object *json_path = NULL;
14f51eba
LK
8914 json_object *json_nexthop = NULL;
8915 json_object *json_overlay = NULL;
856ca177 8916
9b6d8fcf 8917 if (!path->extra)
d62a17ae 8918 return;
718e3744 8919
14f51eba
LK
8920 if (json_paths) {
8921 json_path = json_object_new_object();
8922 json_overlay = json_object_new_object();
8923 json_nexthop = json_object_new_object();
8924 }
8925
d62a17ae 8926 /* short status lead text */
9b6d8fcf 8927 route_vty_short_status_out(vty, path, json_path);
856ca177 8928
d62a17ae 8929 /* print prefix and mask */
8930 if (!display)
ae248832 8931 route_vty_out_route(p, vty, json_path, false);
d62a17ae 8932 else
8933 vty_out(vty, "%*s", 17, " ");
8934
8935 /* Print attribute */
9b6d8fcf 8936 attr = path->attr;
05864da7
DS
8937 char buf1[BUFSIZ];
8938 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 8939
05864da7
DS
8940 switch (af) {
8941 case AF_INET:
8942 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
8943 if (!json_path) {
8944 vty_out(vty, "%-16s", buf);
8945 } else {
8946 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 8947
05864da7 8948 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 8949
05864da7
DS
8950 json_object_object_add(json_path, "nexthop",
8951 json_nexthop);
8952 }
8953 break;
8954 case AF_INET6:
8955 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
8956 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
8957 if (!json_path) {
8958 vty_out(vty, "%s(%s)", buf, buf1);
8959 } else {
8960 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 8961
05864da7
DS
8962 json_object_string_add(json_nexthop, "ipv6LinkLocal",
8963 buf1);
14f51eba 8964
05864da7 8965 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 8966
05864da7
DS
8967 json_object_object_add(json_path, "nexthop",
8968 json_nexthop);
8969 }
8970 break;
8971 default:
8972 if (!json_path) {
8973 vty_out(vty, "?");
8974 } else {
8975 json_object_string_add(json_nexthop, "Error",
8976 "Unsupported address-family");
d62a17ae 8977 }
05864da7 8978 }
988258b4 8979
6c924775
DS
8980 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
8981
8982 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
8983 inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
8984 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
8985 inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
14f51eba 8986
05864da7
DS
8987 if (!json_path)
8988 vty_out(vty, "/%s", buf);
8989 else
8990 json_object_string_add(json_overlay, "gw", buf);
8991
8992 if (attr->ecommunity) {
8993 char *mac = NULL;
8994 struct ecommunity_val *routermac = ecommunity_lookup(
8995 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
8996 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
8997
8998 if (routermac)
8999 mac = ecom_mac2str((char *)routermac->val);
9000 if (mac) {
9001 if (!json_path) {
c4efd0f4 9002 vty_out(vty, "/%s", mac);
05864da7
DS
9003 } else {
9004 json_object_string_add(json_overlay, "rmac",
9005 mac);
988258b4 9006 }
05864da7 9007 XFREE(MTYPE_TMP, mac);
988258b4 9008 }
05864da7 9009 }
718e3744 9010
05864da7
DS
9011 if (!json_path) {
9012 vty_out(vty, "\n");
9013 } else {
9014 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9015
05864da7 9016 json_object_array_add(json_paths, json_path);
14f51eba 9017 }
d62a17ae 9018}
718e3744 9019
d62a17ae 9020/* dampening route */
5f040085
DS
9021static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9022 struct bgp_path_info *path, int display,
9023 afi_t afi, safi_t safi, bool use_json,
9024 json_object *json)
d62a17ae 9025{
9026 struct attr *attr;
9027 int len;
9028 char timebuf[BGP_UPTIME_LEN];
9029
9030 /* short status lead text */
9b6d8fcf 9031 route_vty_short_status_out(vty, path, json);
d62a17ae 9032
9033 /* print prefix and mask */
9034 if (!use_json) {
9035 if (!display)
ae248832 9036 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9037 else
9038 vty_out(vty, "%*s", 17, " ");
9039 }
9040
9b6d8fcf 9041 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9042 len = 17 - len;
9043 if (len < 1) {
9044 if (!use_json)
9045 vty_out(vty, "\n%*s", 34, " ");
9046 } else {
9047 if (use_json)
9048 json_object_int_add(json, "peerHost", len);
9049 else
9050 vty_out(vty, "%*s", len, " ");
9051 }
9052
9053 if (use_json)
a935f597
DA
9054 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9055 safi, use_json, json);
d62a17ae 9056 else
9b6d8fcf
DS
9057 vty_out(vty, "%s ",
9058 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9059 BGP_UPTIME_LEN, afi, safi,
9060 use_json, json));
d62a17ae 9061
9062 /* Print attribute */
9b6d8fcf 9063 attr = path->attr;
d62a17ae 9064
05864da7
DS
9065 /* Print aspath */
9066 if (attr->aspath) {
d62a17ae 9067 if (use_json)
05864da7
DS
9068 json_object_string_add(json, "asPath",
9069 attr->aspath->str);
d62a17ae 9070 else
05864da7 9071 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9072 }
05864da7
DS
9073
9074 /* Print origin */
9075 if (use_json)
9076 json_object_string_add(json, "origin",
9077 bgp_origin_str[attr->origin]);
9078 else
9079 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9080
d62a17ae 9081 if (!use_json)
9082 vty_out(vty, "\n");
9083}
718e3744 9084
d62a17ae 9085/* flap route */
5f040085
DS
9086static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9087 struct bgp_path_info *path, int display,
9088 afi_t afi, safi_t safi, bool use_json,
9089 json_object *json)
784d3a42 9090{
d62a17ae 9091 struct attr *attr;
9092 struct bgp_damp_info *bdi;
9093 char timebuf[BGP_UPTIME_LEN];
9094 int len;
784d3a42 9095
9b6d8fcf 9096 if (!path->extra)
d62a17ae 9097 return;
784d3a42 9098
9b6d8fcf 9099 bdi = path->extra->damp_info;
784d3a42 9100
d62a17ae 9101 /* short status lead text */
9b6d8fcf 9102 route_vty_short_status_out(vty, path, json);
784d3a42 9103
d62a17ae 9104 /* print prefix and mask */
9105 if (!use_json) {
9106 if (!display)
ae248832 9107 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9108 else
9109 vty_out(vty, "%*s", 17, " ");
9110 }
784d3a42 9111
9b6d8fcf 9112 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9113 len = 16 - len;
9114 if (len < 1) {
9115 if (!use_json)
9116 vty_out(vty, "\n%*s", 33, " ");
9117 } else {
9118 if (use_json)
9119 json_object_int_add(json, "peerHost", len);
9120 else
9121 vty_out(vty, "%*s", len, " ");
9122 }
784d3a42 9123
d62a17ae 9124 len = vty_out(vty, "%d", bdi->flap);
9125 len = 5 - len;
9126 if (len < 1) {
9127 if (!use_json)
9128 vty_out(vty, " ");
9129 } else {
9130 if (use_json)
9131 json_object_int_add(json, "bdiFlap", len);
9132 else
9133 vty_out(vty, "%*s", len, " ");
9134 }
9135
9136 if (use_json)
9137 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9138 json);
9139 else
996c9314
LB
9140 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9141 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9142
9b6d8fcf
DS
9143 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9144 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 9145 if (use_json)
9b6d8fcf 9146 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9147 BGP_UPTIME_LEN, afi, safi,
9148 use_json, json);
d62a17ae 9149 else
9150 vty_out(vty, "%s ",
9b6d8fcf 9151 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9152 BGP_UPTIME_LEN, afi,
9153 safi, use_json, json));
d62a17ae 9154 } else {
9155 if (!use_json)
9156 vty_out(vty, "%*s ", 8, " ");
9157 }
9158
9159 /* Print attribute */
9b6d8fcf 9160 attr = path->attr;
d62a17ae 9161
05864da7
DS
9162 /* Print aspath */
9163 if (attr->aspath) {
d62a17ae 9164 if (use_json)
05864da7
DS
9165 json_object_string_add(json, "asPath",
9166 attr->aspath->str);
d62a17ae 9167 else
05864da7 9168 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9169 }
05864da7
DS
9170
9171 /* Print origin */
9172 if (use_json)
9173 json_object_string_add(json, "origin",
9174 bgp_origin_str[attr->origin]);
9175 else
9176 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9177
d62a17ae 9178 if (!use_json)
9179 vty_out(vty, "\n");
9180}
9181
9182static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9183 int *first, const char *header,
9184 json_object *json_adv_to)
9185{
9186 char buf1[INET6_ADDRSTRLEN];
9187 json_object *json_peer = NULL;
9188
9189 if (json_adv_to) {
9190 /* 'advertised-to' is a dictionary of peers we have advertised
9191 * this
9192 * prefix too. The key is the peer's IP or swpX, the value is
9193 * the
9194 * hostname if we know it and "" if not.
9195 */
9196 json_peer = json_object_new_object();
9197
9198 if (peer->hostname)
9199 json_object_string_add(json_peer, "hostname",
9200 peer->hostname);
9201
9202 if (peer->conf_if)
9203 json_object_object_add(json_adv_to, peer->conf_if,
9204 json_peer);
9205 else
9206 json_object_object_add(
9207 json_adv_to,
9208 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9209 json_peer);
9210 } else {
9211 if (*first) {
9212 vty_out(vty, "%s", header);
9213 *first = 0;
9214 }
9215
9216 if (peer->hostname
892fedb6 9217 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9218 if (peer->conf_if)
9219 vty_out(vty, " %s(%s)", peer->hostname,
9220 peer->conf_if);
9221 else
9222 vty_out(vty, " %s(%s)", peer->hostname,
9223 sockunion2str(&peer->su, buf1,
9224 SU_ADDRSTRLEN));
9225 } else {
9226 if (peer->conf_if)
9227 vty_out(vty, " %s", peer->conf_if);
9228 else
9229 vty_out(vty, " %s",
9230 sockunion2str(&peer->su, buf1,
9231 SU_ADDRSTRLEN));
9232 }
9233 }
784d3a42
PG
9234}
9235
dcc68b5e
MS
9236static void route_vty_out_tx_ids(struct vty *vty,
9237 struct bgp_addpath_info_data *d)
9238{
9239 int i;
9240
9241 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9242 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9243 d->addpath_tx_id[i],
9244 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9245 }
9246}
9247
0dc8ee70
DS
9248static const char *bgp_path_selection_reason2str(
9249 enum bgp_path_selection_reason reason)
9250{
9251 switch (reason) {
9252 case bgp_path_selection_none:
9253 return "Nothing to Select";
0dc8ee70
DS
9254 case bgp_path_selection_first:
9255 return "First path received";
0dc8ee70
DS
9256 case bgp_path_selection_evpn_sticky_mac:
9257 return "EVPN Sticky Mac";
0dc8ee70
DS
9258 case bgp_path_selection_evpn_seq:
9259 return "EVPN sequence number";
0dc8ee70
DS
9260 case bgp_path_selection_evpn_lower_ip:
9261 return "EVPN lower IP";
d071f237
AK
9262 case bgp_path_selection_evpn_local_path:
9263 return "EVPN local ES path";
9264 case bgp_path_selection_evpn_non_proxy:
9265 return "EVPN non proxy";
0dc8ee70
DS
9266 case bgp_path_selection_weight:
9267 return "Weight";
0dc8ee70
DS
9268 case bgp_path_selection_local_pref:
9269 return "Local Pref";
0dc8ee70
DS
9270 case bgp_path_selection_local_route:
9271 return "Local Route";
0dc8ee70
DS
9272 case bgp_path_selection_confed_as_path:
9273 return "Confederation based AS Path";
0dc8ee70
DS
9274 case bgp_path_selection_as_path:
9275 return "AS Path";
0dc8ee70
DS
9276 case bgp_path_selection_origin:
9277 return "Origin";
0dc8ee70
DS
9278 case bgp_path_selection_med:
9279 return "MED";
0dc8ee70
DS
9280 case bgp_path_selection_peer:
9281 return "Peer Type";
0dc8ee70
DS
9282 case bgp_path_selection_confed:
9283 return "Confed Peer Type";
0dc8ee70
DS
9284 case bgp_path_selection_igp_metric:
9285 return "IGP Metric";
0dc8ee70
DS
9286 case bgp_path_selection_older:
9287 return "Older Path";
0dc8ee70
DS
9288 case bgp_path_selection_router_id:
9289 return "Router ID";
0dc8ee70
DS
9290 case bgp_path_selection_cluster_length:
9291 return "Cluser length";
0dc8ee70
DS
9292 case bgp_path_selection_stale:
9293 return "Path Staleness";
0dc8ee70
DS
9294 case bgp_path_selection_local_configured:
9295 return "Locally configured route";
0dc8ee70
DS
9296 case bgp_path_selection_neighbor_ip:
9297 return "Neighbor IP";
0dc8ee70
DS
9298 case bgp_path_selection_default:
9299 return "Nothing left to compare";
0dc8ee70 9300 }
a74879b2 9301 return "Invalid (internal error)";
0dc8ee70
DS
9302}
9303
5e4d4c8a
AK
9304static void route_vty_out_detail_es_info(struct vty *vty,
9305 struct attr *attr, json_object *json_path)
9306{
9307 char esi_buf[ESI_STR_LEN];
9308 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9309 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9310 ATTR_ES_PEER_ROUTER);
9311 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9312 ATTR_ES_PEER_ACTIVE);
9313 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9314 ATTR_ES_PEER_PROXY);
9315
9316 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9317 if (json_path) {
9318 json_object *json_es_info = NULL;
9319
9320 json_object_string_add(
9321 json_path, "esi",
9322 esi_buf);
9323 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9324 json_es_info = json_object_new_object();
9325 if (es_local)
9326 json_object_boolean_true_add(
9327 json_es_info, "localEs");
9328 if (peer_active)
9329 json_object_boolean_true_add(
9330 json_es_info, "peerActive");
9331 if (peer_proxy)
9332 json_object_boolean_true_add(
9333 json_es_info, "peerProxy");
9334 if (peer_router)
9335 json_object_boolean_true_add(
9336 json_es_info, "peerRouter");
9337 if (attr->mm_sync_seqnum)
9338 json_object_int_add(
9339 json_es_info, "peerSeq",
9340 attr->mm_sync_seqnum);
9341 json_object_object_add(
9342 json_path, "es_info",
9343 json_es_info);
9344 }
9345 } else {
9346 if (bgp_evpn_attr_is_sync(attr))
9347 vty_out(vty,
9348 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9349 esi_buf,
9350 es_local ? "local-es":"",
9351 peer_proxy ? "proxy " : "",
9352 peer_active ? "active ":"",
9353 peer_router ? "router ":"",
9354 attr->mm_sync_seqnum);
9355 else
9356 vty_out(vty, " ESI %s %s\n",
9357 esi_buf,
9358 es_local ? "local-es":"");
9359 }
9360}
9361
9362void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
9363 struct bgp_dest *bn, struct bgp_path_info *path,
9364 afi_t afi, safi_t safi, json_object *json_paths)
d62a17ae 9365{
9366 char buf[INET6_ADDRSTRLEN];
9367 char buf1[BUFSIZ];
515c2602 9368 struct attr *attr = path->attr;
d62a17ae 9369 int sockunion_vty_out(struct vty *, union sockunion *);
9370 time_t tbuf;
9371 json_object *json_bestpath = NULL;
9372 json_object *json_cluster_list = NULL;
9373 json_object *json_cluster_list_list = NULL;
9374 json_object *json_ext_community = NULL;
9375 json_object *json_last_update = NULL;
7fd077aa 9376 json_object *json_pmsi = NULL;
d62a17ae 9377 json_object *json_nexthop_global = NULL;
9378 json_object *json_nexthop_ll = NULL;
9379 json_object *json_nexthops = NULL;
9380 json_object *json_path = NULL;
9381 json_object *json_peer = NULL;
9382 json_object *json_string = NULL;
9383 json_object *json_adv_to = NULL;
9384 int first = 0;
9385 struct listnode *node, *nnode;
9386 struct peer *peer;
9387 int addpath_capable;
9388 int has_adj;
9389 unsigned int first_as;
1defdda8 9390 bool nexthop_self =
9b6d8fcf 9391 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9392 int i;
2ba93fd6
DA
9393 char *nexthop_hostname =
9394 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 9395
9396 if (json_paths) {
9397 json_path = json_object_new_object();
9398 json_peer = json_object_new_object();
9399 json_nexthop_global = json_object_new_object();
9400 }
9401
44c69747 9402 if (path->extra) {
b57ba6d2 9403 char tag_buf[30];
d62a17ae 9404
d62a17ae 9405 tag_buf[0] = '\0';
9b6d8fcf
DS
9406 if (path->extra && path->extra->num_labels) {
9407 bgp_evpn_label2str(path->extra->label,
9408 path->extra->num_labels, tag_buf,
a4d82a8a 9409 sizeof(tag_buf));
d62a17ae 9410 }
d7325ee7 9411 if (safi == SAFI_EVPN) {
44c69747 9412 if (!json_paths) {
2dbe669b
DA
9413 vty_out(vty, " Route %pFX",
9414 (struct prefix_evpn *)
9415 bgp_dest_get_prefix(bn));
44c69747
LK
9416 if (tag_buf[0] != '\0')
9417 vty_out(vty, " VNI %s", tag_buf);
9418 vty_out(vty, "\n");
9419 } else {
9420 if (tag_buf[0])
9421 json_object_string_add(json_path, "VNI",
9422 tag_buf);
9423 }
d7325ee7
DD
9424 }
9425
44c69747 9426 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9427 struct bgp_path_info *parent_ri;
9bcb3eef 9428 struct bgp_dest *dest, *pdest;
d62a17ae 9429
9b6d8fcf 9430 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9431 dest = parent_ri->net;
9432 if (dest && dest->pdest) {
9433 pdest = dest->pdest;
9434 prefix_rd2str(
9435 (struct prefix_rd *)bgp_dest_get_prefix(
9436 pdest),
9437 buf1, sizeof(buf1));
d7325ee7 9438 if (is_pi_family_evpn(parent_ri)) {
2dbe669b
DA
9439 vty_out(vty,
9440 " Imported from %s:%pFX, VNI %s\n",
9441 buf1,
9442 (struct prefix_evpn *)
9443 bgp_dest_get_prefix(
9444 dest),
9445 tag_buf);
d7325ee7 9446 } else
2dbe669b
DA
9447 vty_out(vty,
9448 " Imported from %s:%pFX\n",
9449 buf1,
9450 (struct prefix_evpn *)
9451 bgp_dest_get_prefix(
9452 dest));
d62a17ae 9453 }
9454 }
9455 }
d62a17ae 9456
05864da7
DS
9457 /* Line1 display AS-path, Aggregator */
9458 if (attr->aspath) {
9459 if (json_paths) {
9460 if (!attr->aspath->json)
9461 aspath_str_update(attr->aspath, true);
9462 json_object_lock(attr->aspath->json);
9463 json_object_object_add(json_path, "aspath",
9464 attr->aspath->json);
9465 } else {
9466 if (attr->aspath->segments)
9467 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9468 else
05864da7 9469 vty_out(vty, " Local");
d62a17ae 9470 }
05864da7 9471 }
d62a17ae 9472
05864da7
DS
9473 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9474 if (json_paths)
9475 json_object_boolean_true_add(json_path, "removed");
9476 else
9477 vty_out(vty, ", (removed)");
9478 }
d62a17ae 9479
05864da7
DS
9480 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9481 if (json_paths)
9482 json_object_boolean_true_add(json_path, "stale");
9483 else
9484 vty_out(vty, ", (stale)");
9485 }
d62a17ae 9486
05864da7
DS
9487 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9488 if (json_paths) {
23d0a753
DA
9489 char buf[BUFSIZ] = {0};
9490
05864da7
DS
9491 json_object_int_add(json_path, "aggregatorAs",
9492 attr->aggregator_as);
23d0a753
DA
9493 json_object_string_add(json_path, "aggregatorId",
9494 inet_ntop(AF_INET,
9495 &attr->aggregator_addr,
9496 buf, sizeof(buf)));
87c82131
DA
9497 if (attr->aggregator_as == BGP_AS_ZERO)
9498 json_object_boolean_true_add(
9499 json_path, "aggregatorAsMalformed");
9500 else
9501 json_object_boolean_false_add(
9502 json_path, "aggregatorAsMalformed");
05864da7 9503 } else {
87c82131
DA
9504 if (attr->aggregator_as == BGP_AS_ZERO)
9505 vty_out(vty,
23d0a753 9506 ", (aggregated by %u(malformed) %pI4)",
87c82131 9507 attr->aggregator_as,
23d0a753 9508 &attr->aggregator_addr);
87c82131 9509 else
23d0a753 9510 vty_out(vty, ", (aggregated by %u %pI4)",
87c82131 9511 attr->aggregator_as,
23d0a753 9512 &attr->aggregator_addr);
d62a17ae 9513 }
05864da7 9514 }
d62a17ae 9515
05864da7
DS
9516 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9517 PEER_FLAG_REFLECTOR_CLIENT)) {
9518 if (json_paths)
9519 json_object_boolean_true_add(json_path,
9520 "rxedFromRrClient");
9521 else
9522 vty_out(vty, ", (Received from a RR-client)");
9523 }
d62a17ae 9524
05864da7
DS
9525 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9526 PEER_FLAG_RSERVER_CLIENT)) {
9527 if (json_paths)
9528 json_object_boolean_true_add(json_path,
9529 "rxedFromRsClient");
9530 else
9531 vty_out(vty, ", (Received from a RS-client)");
9532 }
d62a17ae 9533
05864da7
DS
9534 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9535 if (json_paths)
9536 json_object_boolean_true_add(json_path,
9537 "dampeningHistoryEntry");
9538 else
9539 vty_out(vty, ", (history entry)");
9540 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
9541 if (json_paths)
9542 json_object_boolean_true_add(json_path,
9543 "dampeningSuppressed");
9544 else
9545 vty_out(vty, ", (suppressed due to dampening)");
9546 }
d62a17ae 9547
05864da7
DS
9548 if (!json_paths)
9549 vty_out(vty, "\n");
d62a17ae 9550
05864da7
DS
9551 /* Line2 display Next-hop, Neighbor, Router-id */
9552 /* Display the nexthop */
9bcb3eef 9553 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
9554
9555 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
9556 || bn_p->family == AF_EVPN)
05864da7
DS
9557 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
9558 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9559 char buf[BUFSIZ] = {0};
9560
05864da7
DS
9561 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9562 || safi == SAFI_EVPN) {
515c2602 9563 if (json_paths) {
d62a17ae 9564 json_object_string_add(
515c2602 9565 json_nexthop_global, "ip",
23d0a753
DA
9566 inet_ntop(AF_INET,
9567 &attr->mp_nexthop_global_in,
9568 buf, sizeof(buf)));
515c2602 9569
939a97f4 9570 if (path->peer->hostname)
515c2602
DA
9571 json_object_string_add(
9572 json_nexthop_global, "hostname",
939a97f4 9573 path->peer->hostname);
aef999a2
DA
9574 } else {
9575 if (nexthop_hostname)
9576 vty_out(vty, " %pI4(%s)",
9577 &attr->mp_nexthop_global_in,
9578 nexthop_hostname);
9579 else
9580 vty_out(vty, " %pI4",
9581 &attr->mp_nexthop_global_in);
9582 }
d62a17ae 9583 } else {
515c2602 9584 if (json_paths) {
05864da7 9585 json_object_string_add(
515c2602 9586 json_nexthop_global, "ip",
23d0a753
DA
9587 inet_ntop(AF_INET, &attr->nexthop, buf,
9588 sizeof(buf)));
515c2602 9589
939a97f4 9590 if (path->peer->hostname)
515c2602
DA
9591 json_object_string_add(
9592 json_nexthop_global, "hostname",
939a97f4 9593 path->peer->hostname);
aef999a2
DA
9594 } else {
9595 if (nexthop_hostname)
9596 vty_out(vty, " %pI4(%s)",
9597 &attr->nexthop,
9598 nexthop_hostname);
9599 else
9600 vty_out(vty, " %pI4",
9601 &attr->nexthop);
9602 }
d62a17ae 9603 }
9604
05864da7
DS
9605 if (json_paths)
9606 json_object_string_add(json_nexthop_global, "afi",
9607 "ipv4");
9608 } else {
9609 if (json_paths) {
9610 json_object_string_add(
515c2602
DA
9611 json_nexthop_global, "ip",
9612 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
9613 buf, INET6_ADDRSTRLEN));
9614
939a97f4 9615 if (path->peer->hostname)
515c2602
DA
9616 json_object_string_add(json_nexthop_global,
9617 "hostname",
939a97f4 9618 path->peer->hostname);
515c2602 9619
05864da7
DS
9620 json_object_string_add(json_nexthop_global, "afi",
9621 "ipv6");
9622 json_object_string_add(json_nexthop_global, "scope",
9623 "global");
9624 } else {
aef999a2
DA
9625 if (nexthop_hostname)
9626 vty_out(vty, " %pI6(%s)",
9627 &attr->mp_nexthop_global,
9628 nexthop_hostname);
9629 else
9630 vty_out(vty, " %pI6",
9631 &attr->mp_nexthop_global);
d62a17ae 9632 }
05864da7 9633 }
d62a17ae 9634
05864da7
DS
9635 /* Display the IGP cost or 'inaccessible' */
9636 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9637 if (json_paths)
9638 json_object_boolean_false_add(json_nexthop_global,
9639 "accessible");
9640 else
9641 vty_out(vty, " (inaccessible)");
9642 } else {
9643 if (path->extra && path->extra->igpmetric) {
d62a17ae 9644 if (json_paths)
05864da7
DS
9645 json_object_int_add(json_nexthop_global,
9646 "metric",
9647 path->extra->igpmetric);
d62a17ae 9648 else
05864da7
DS
9649 vty_out(vty, " (metric %u)",
9650 path->extra->igpmetric);
d62a17ae 9651 }
9652
05864da7 9653 /* IGP cost is 0, display this only for json */
d62a17ae 9654 else {
d62a17ae 9655 if (json_paths)
05864da7
DS
9656 json_object_int_add(json_nexthop_global,
9657 "metric", 0);
d62a17ae 9658 }
d62a17ae 9659
05864da7
DS
9660 if (json_paths)
9661 json_object_boolean_true_add(json_nexthop_global,
9662 "accessible");
9663 }
d62a17ae 9664
05864da7
DS
9665 /* Display peer "from" output */
9666 /* This path was originated locally */
9667 if (path->peer == bgp->peer_self) {
d62a17ae 9668
05864da7 9669 if (safi == SAFI_EVPN
b54892e0 9670 || (bn_p->family == AF_INET
05864da7 9671 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 9672 if (json_paths)
05864da7
DS
9673 json_object_string_add(json_peer, "peerId",
9674 "0.0.0.0");
d62a17ae 9675 else
05864da7
DS
9676 vty_out(vty, " from 0.0.0.0 ");
9677 } else {
d62a17ae 9678 if (json_paths)
05864da7
DS
9679 json_object_string_add(json_peer, "peerId",
9680 "::");
d62a17ae 9681 else
05864da7 9682 vty_out(vty, " from :: ");
d62a17ae 9683 }
d62a17ae 9684
23d0a753
DA
9685 if (json_paths) {
9686 char buf[BUFSIZ] = {0};
9687
05864da7 9688 json_object_string_add(json_peer, "routerId",
23d0a753
DA
9689 inet_ntop(AF_INET,
9690 &bgp->router_id, buf,
9691 sizeof(buf)));
9692 } else {
9693 vty_out(vty, "(%pI4)", &bgp->router_id);
9694 }
05864da7 9695 }
d62a17ae 9696
05864da7
DS
9697 /* We RXed this path from one of our peers */
9698 else {
9699
9700 if (json_paths) {
9701 json_object_string_add(json_peer, "peerId",
9702 sockunion2str(&path->peer->su,
9703 buf,
9704 SU_ADDRSTRLEN));
9705 json_object_string_add(json_peer, "routerId",
9706 inet_ntop(AF_INET,
9707 &path->peer->remote_id,
9708 buf1, sizeof(buf1)));
9709
9710 if (path->peer->hostname)
9711 json_object_string_add(json_peer, "hostname",
9712 path->peer->hostname);
9713
9714 if (path->peer->domainname)
9715 json_object_string_add(json_peer, "domainname",
9716 path->peer->domainname);
9717
9718 if (path->peer->conf_if)
9719 json_object_string_add(json_peer, "interface",
9720 path->peer->conf_if);
9721 } else {
9722 if (path->peer->conf_if) {
9723 if (path->peer->hostname
892fedb6
DA
9724 && CHECK_FLAG(path->peer->bgp->flags,
9725 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9726 vty_out(vty, " from %s(%s)",
9727 path->peer->hostname,
9728 path->peer->conf_if);
d62a17ae 9729 else
05864da7 9730 vty_out(vty, " from %s",
9b6d8fcf 9731 path->peer->conf_if);
d62a17ae 9732 } else {
05864da7 9733 if (path->peer->hostname
892fedb6
DA
9734 && CHECK_FLAG(path->peer->bgp->flags,
9735 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9736 vty_out(vty, " from %s(%s)",
9737 path->peer->hostname,
9738 path->peer->host);
d62a17ae 9739 else
05864da7
DS
9740 vty_out(vty, " from %s",
9741 sockunion2str(&path->peer->su,
9742 buf,
9743 SU_ADDRSTRLEN));
d62a17ae 9744 }
d62a17ae 9745
05864da7 9746 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 9747 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
9748 else
9749 vty_out(vty, " (%s)",
9750 inet_ntop(AF_INET,
9751 &path->peer->remote_id, buf1,
9752 sizeof(buf1)));
d62a17ae 9753 }
05864da7 9754 }
9df8b37c 9755
05864da7
DS
9756 /*
9757 * Note when vrfid of nexthop is different from that of prefix
9758 */
9759 if (path->extra && path->extra->bgp_orig) {
9760 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9761
05864da7
DS
9762 if (json_paths) {
9763 const char *vn;
9df8b37c 9764
05864da7
DS
9765 if (path->extra->bgp_orig->inst_type
9766 == BGP_INSTANCE_TYPE_DEFAULT)
9767 vn = VRF_DEFAULT_NAME;
9768 else
9769 vn = path->extra->bgp_orig->name;
9df8b37c 9770
05864da7 9771 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 9772
05864da7
DS
9773 if (nexthop_vrfid == VRF_UNKNOWN) {
9774 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 9775 } else {
05864da7
DS
9776 json_object_int_add(json_path, "nhVrfId",
9777 (int)nexthop_vrfid);
9df8b37c 9778 }
05864da7
DS
9779 } else {
9780 if (nexthop_vrfid == VRF_UNKNOWN)
9781 vty_out(vty, " vrf ?");
137147c6
DS
9782 else {
9783 struct vrf *vrf;
9784
9785 vrf = vrf_lookup_by_id(nexthop_vrfid);
9786 vty_out(vty, " vrf %s(%u)",
9787 VRF_LOGNAME(vrf), nexthop_vrfid);
9788 }
9df8b37c 9789 }
05864da7 9790 }
9df8b37c 9791
05864da7
DS
9792 if (nexthop_self) {
9793 if (json_paths) {
9794 json_object_boolean_true_add(json_path,
9795 "announceNexthopSelf");
9796 } else {
9797 vty_out(vty, " announce-nh-self");
9df8b37c 9798 }
05864da7 9799 }
9df8b37c 9800
05864da7
DS
9801 if (!json_paths)
9802 vty_out(vty, "\n");
d62a17ae 9803
05864da7
DS
9804 /* display the link-local nexthop */
9805 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9806 if (json_paths) {
9807 json_nexthop_ll = json_object_new_object();
9808 json_object_string_add(
515c2602
DA
9809 json_nexthop_ll, "ip",
9810 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9811 buf, INET6_ADDRSTRLEN));
9812
939a97f4 9813 if (path->peer->hostname)
515c2602
DA
9814 json_object_string_add(json_nexthop_ll,
9815 "hostname",
939a97f4 9816 path->peer->hostname);
515c2602 9817
05864da7
DS
9818 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
9819 json_object_string_add(json_nexthop_ll, "scope",
9820 "link-local");
d62a17ae 9821
05864da7
DS
9822 json_object_boolean_true_add(json_nexthop_ll,
9823 "accessible");
d62a17ae 9824
05864da7 9825 if (!attr->mp_nexthop_prefer_global)
d62a17ae 9826 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
9827 "used");
9828 else
9829 json_object_boolean_true_add(
9830 json_nexthop_global, "used");
9831 } else {
9832 vty_out(vty, " (%s) %s\n",
9833 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9834 buf, INET6_ADDRSTRLEN),
9835 attr->mp_nexthop_prefer_global
9836 ? "(prefer-global)"
9837 : "(used)");
d62a17ae 9838 }
05864da7
DS
9839 }
9840 /* If we do not have a link-local nexthop then we must flag the
9841 global as "used" */
9842 else {
9843 if (json_paths)
9844 json_object_boolean_true_add(json_nexthop_global,
9845 "used");
9846 }
d62a17ae 9847
b5e140c8 9848 if (safi == SAFI_EVPN &&
5e4d4c8a
AK
9849 bgp_evpn_is_esi_valid(&attr->esi)) {
9850 route_vty_out_detail_es_info(vty, attr, json_path);
b5e140c8
AK
9851 }
9852
05864da7
DS
9853 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
9854 * Int/Ext/Local, Atomic, best */
9855 if (json_paths)
9856 json_object_string_add(json_path, "origin",
9857 bgp_origin_long_str[attr->origin]);
9858 else
9859 vty_out(vty, " Origin %s",
9860 bgp_origin_long_str[attr->origin]);
9df8b37c 9861
05864da7 9862 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 9863 if (json_paths)
05864da7 9864 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 9865 else
05864da7
DS
9866 vty_out(vty, ", metric %u", attr->med);
9867 }
9df8b37c 9868
05864da7
DS
9869 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
9870 if (json_paths)
0fbac0b4 9871 json_object_int_add(json_path, "locPrf",
05864da7
DS
9872 attr->local_pref);
9873 else
9874 vty_out(vty, ", localpref %u", attr->local_pref);
9875 }
9df8b37c 9876
05864da7
DS
9877 if (attr->weight != 0) {
9878 if (json_paths)
9879 json_object_int_add(json_path, "weight", attr->weight);
9880 else
9881 vty_out(vty, ", weight %u", attr->weight);
9882 }
9df8b37c 9883
05864da7
DS
9884 if (attr->tag != 0) {
9885 if (json_paths)
9886 json_object_int_add(json_path, "tag", attr->tag);
9887 else
9888 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
9889 }
9df8b37c 9890
05864da7
DS
9891 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9892 if (json_paths)
9893 json_object_boolean_false_add(json_path, "valid");
9894 else
9895 vty_out(vty, ", invalid");
9896 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9897 if (json_paths)
9898 json_object_boolean_true_add(json_path, "valid");
9899 else
9900 vty_out(vty, ", valid");
9901 }
9df8b37c 9902
05864da7
DS
9903 if (path->peer != bgp->peer_self) {
9904 if (path->peer->as == path->peer->local_as) {
9905 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
9906 if (json_paths)
9907 json_object_string_add(
9908 json_peer, "type",
9909 "confed-internal");
d62a17ae 9910 else
05864da7 9911 vty_out(vty, ", confed-internal");
d62a17ae 9912 } else {
05864da7
DS
9913 if (json_paths)
9914 json_object_string_add(
9915 json_peer, "type", "internal");
9916 else
9917 vty_out(vty, ", internal");
9df8b37c 9918 }
05864da7
DS
9919 } else {
9920 if (bgp_confederation_peers_check(bgp,
9921 path->peer->as)) {
9922 if (json_paths)
9923 json_object_string_add(
9924 json_peer, "type",
9925 "confed-external");
d62a17ae 9926 else
05864da7 9927 vty_out(vty, ", confed-external");
d62a17ae 9928 } else {
05864da7
DS
9929 if (json_paths)
9930 json_object_string_add(
9931 json_peer, "type", "external");
9932 else
9933 vty_out(vty, ", external");
d62a17ae 9934 }
9935 }
05864da7
DS
9936 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
9937 if (json_paths) {
9938 json_object_boolean_true_add(json_path, "aggregated");
9939 json_object_boolean_true_add(json_path, "local");
9940 } else {
9941 vty_out(vty, ", aggregated, local");
9942 }
9943 } else if (path->type != ZEBRA_ROUTE_BGP) {
9944 if (json_paths)
9945 json_object_boolean_true_add(json_path, "sourced");
9946 else
9947 vty_out(vty, ", sourced");
9948 } else {
9949 if (json_paths) {
9950 json_object_boolean_true_add(json_path, "sourced");
9951 json_object_boolean_true_add(json_path, "local");
9952 } else {
9953 vty_out(vty, ", sourced, local");
d62a17ae 9954 }
05864da7 9955 }
718e3744 9956
05864da7 9957 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 9958 if (json_paths)
05864da7
DS
9959 json_object_boolean_true_add(json_path,
9960 "atomicAggregate");
d62a17ae 9961 else
05864da7
DS
9962 vty_out(vty, ", atomic-aggregate");
9963 }
d62a17ae 9964
05864da7
DS
9965 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
9966 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
9967 && bgp_path_info_mpath_count(path))) {
9968 if (json_paths)
9969 json_object_boolean_true_add(json_path, "multipath");
9970 else
9971 vty_out(vty, ", multipath");
9972 }
50e05855 9973
05864da7
DS
9974 // Mark the bestpath(s)
9975 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
9976 first_as = aspath_get_first_as(attr->aspath);
718e3744 9977
05864da7
DS
9978 if (json_paths) {
9979 if (!json_bestpath)
9980 json_bestpath = json_object_new_object();
9981 json_object_int_add(json_bestpath, "bestpathFromAs",
9982 first_as);
9983 } else {
9984 if (first_as)
9985 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 9986 else
05864da7 9987 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 9988 }
05864da7 9989 }
718e3744 9990
05864da7
DS
9991 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
9992 if (json_paths) {
9993 if (!json_bestpath)
9994 json_bestpath = json_object_new_object();
9995 json_object_boolean_true_add(json_bestpath, "overall");
9996 json_object_string_add(
9997 json_bestpath, "selectionReason",
9998 bgp_path_selection_reason2str(bn->reason));
9999 } else {
10000 vty_out(vty, ", best");
10001 vty_out(vty, " (%s)",
10002 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10003 }
05864da7 10004 }
718e3744 10005
05864da7
DS
10006 if (json_bestpath)
10007 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10008
05864da7
DS
10009 if (!json_paths)
10010 vty_out(vty, "\n");
10011
10012 /* Line 4 display Community */
10013 if (attr->community) {
10014 if (json_paths) {
10015 if (!attr->community->json)
10016 community_str(attr->community, true);
10017 json_object_lock(attr->community->json);
10018 json_object_object_add(json_path, "community",
10019 attr->community->json);
10020 } else {
10021 vty_out(vty, " Community: %s\n",
10022 attr->community->str);
d62a17ae 10023 }
05864da7 10024 }
718e3744 10025
05864da7
DS
10026 /* Line 5 display Extended-community */
10027 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10028 if (json_paths) {
10029 json_ext_community = json_object_new_object();
10030 json_object_string_add(json_ext_community, "string",
10031 attr->ecommunity->str);
10032 json_object_object_add(json_path, "extendedCommunity",
10033 json_ext_community);
d62a17ae 10034 } else {
05864da7
DS
10035 vty_out(vty, " Extended Community: %s\n",
10036 attr->ecommunity->str);
d62a17ae 10037 }
05864da7 10038 }
718e3744 10039
05864da7
DS
10040 /* Line 6 display Large community */
10041 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10042 if (json_paths) {
10043 if (!attr->lcommunity->json)
10044 lcommunity_str(attr->lcommunity, true);
10045 json_object_lock(attr->lcommunity->json);
10046 json_object_object_add(json_path, "largeCommunity",
10047 attr->lcommunity->json);
10048 } else {
10049 vty_out(vty, " Large Community: %s\n",
10050 attr->lcommunity->str);
d62a17ae 10051 }
05864da7 10052 }
718e3744 10053
05864da7
DS
10054 /* Line 7 display Originator, Cluster-id */
10055 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10056 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10057 char buf[BUFSIZ] = {0};
10058
05864da7 10059 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10060 if (json_paths)
05864da7
DS
10061 json_object_string_add(
10062 json_path, "originatorId",
23d0a753
DA
10063 inet_ntop(AF_INET, &attr->originator_id,
10064 buf, sizeof(buf)));
d62a17ae 10065 else
23d0a753
DA
10066 vty_out(vty, " Originator: %pI4",
10067 &attr->originator_id);
d62a17ae 10068 }
856ca177 10069
05864da7 10070 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10071 struct cluster_list *cluster =
10072 bgp_attr_get_cluster(attr);
05864da7 10073 int i;
d62a17ae 10074
10075 if (json_paths) {
05864da7
DS
10076 json_cluster_list = json_object_new_object();
10077 json_cluster_list_list =
10078 json_object_new_array();
10079
779fee93 10080 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10081 json_string = json_object_new_string(
779fee93
DS
10082 inet_ntop(AF_INET,
10083 &cluster->list[i],
10084 buf, sizeof(buf)));
05864da7
DS
10085 json_object_array_add(
10086 json_cluster_list_list,
10087 json_string);
10088 }
718e3744 10089
05864da7
DS
10090 /*
10091 * struct cluster_list does not have
10092 * "str" variable like aspath and community
10093 * do. Add this someday if someone asks
10094 * for it.
10095 * json_object_string_add(json_cluster_list,
779fee93 10096 * "string", cluster->str);
05864da7
DS
10097 */
10098 json_object_object_add(json_cluster_list,
10099 "list",
10100 json_cluster_list_list);
10101 json_object_object_add(json_path, "clusterList",
10102 json_cluster_list);
0dc8ee70 10103 } else {
05864da7
DS
10104 vty_out(vty, ", Cluster list: ");
10105
779fee93 10106 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10107 vty_out(vty, "%pI4 ",
779fee93 10108 &cluster->list[i]);
05864da7 10109 }
0dc8ee70 10110 }
d62a17ae 10111 }
718e3744 10112
d62a17ae 10113 if (!json_paths)
10114 vty_out(vty, "\n");
05864da7 10115 }
d62a17ae 10116
05864da7 10117 if (path->extra && path->extra->damp_info)
a935f597 10118 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10119
05864da7
DS
10120 /* Remote Label */
10121 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10122 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10123 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 10124
05864da7
DS
10125 if (json_paths)
10126 json_object_int_add(json_path, "remoteLabel", label);
10127 else
10128 vty_out(vty, " Remote label: %d\n", label);
10129 }
d62a17ae 10130
e496b420
HS
10131 /* Remote SID */
10132 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
10133 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
10134 if (json_paths)
10135 json_object_string_add(json_path, "remoteSid", buf);
10136 else
10137 vty_out(vty, " Remote SID: %s\n", buf);
10138 }
10139
05864da7
DS
10140 /* Label Index */
10141 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10142 if (json_paths)
10143 json_object_int_add(json_path, "labelIndex",
10144 attr->label_index);
10145 else
10146 vty_out(vty, " Label Index: %d\n",
10147 attr->label_index);
10148 }
d62a17ae 10149
05864da7
DS
10150 /* Line 8 display Addpath IDs */
10151 if (path->addpath_rx_id
10152 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10153 if (json_paths) {
10154 json_object_int_add(json_path, "addpathRxId",
10155 path->addpath_rx_id);
d62a17ae 10156
05864da7
DS
10157 /* Keep backwards compatibility with the old API
10158 * by putting TX All's ID in the old field
10159 */
10160 json_object_int_add(
10161 json_path, "addpathTxId",
10162 path->tx_addpath
10163 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10164
05864da7
DS
10165 /* ... but create a specific field for each
10166 * strategy
10167 */
10168 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10169 json_object_int_add(
10170 json_path,
10171 bgp_addpath_names(i)->id_json_name,
10172 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10173 }
05864da7
DS
10174 } else {
10175 vty_out(vty, " AddPath ID: RX %u, ",
10176 path->addpath_rx_id);
d62a17ae 10177
05864da7 10178 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10179 }
05864da7 10180 }
520d5d76 10181
05864da7
DS
10182 /* If we used addpath to TX a non-bestpath we need to display
10183 * "Advertised to" on a path-by-path basis
10184 */
10185 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10186 first = 1;
dcc68b5e 10187
05864da7
DS
10188 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10189 addpath_capable =
10190 bgp_addpath_encode_tx(peer, afi, safi);
10191 has_adj = bgp_adj_out_lookup(
10192 peer, path->net,
10193 bgp_addpath_id_for_peer(peer, afi, safi,
10194 &path->tx_addpath));
10195
10196 if ((addpath_capable && has_adj)
10197 || (!addpath_capable && has_adj
10198 && CHECK_FLAG(path->flags,
10199 BGP_PATH_SELECTED))) {
10200 if (json_path && !json_adv_to)
10201 json_adv_to = json_object_new_object();
dcc68b5e 10202
05864da7
DS
10203 route_vty_out_advertised_to(
10204 vty, peer, &first,
10205 " Advertised to:", json_adv_to);
d62a17ae 10206 }
10207 }
718e3744 10208
05864da7
DS
10209 if (json_path) {
10210 if (json_adv_to) {
10211 json_object_object_add(
10212 json_path, "advertisedTo", json_adv_to);
d62a17ae 10213 }
05864da7
DS
10214 } else {
10215 if (!first) {
10216 vty_out(vty, "\n");
d62a17ae 10217 }
10218 }
05864da7 10219 }
b05a1c8b 10220
05864da7
DS
10221 /* Line 9 display Uptime */
10222 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10223 if (json_paths) {
10224 json_last_update = json_object_new_object();
10225 json_object_int_add(json_last_update, "epoch", tbuf);
10226 json_object_string_add(json_last_update, "string",
10227 ctime(&tbuf));
10228 json_object_object_add(json_path, "lastUpdate",
10229 json_last_update);
10230 } else
10231 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10232
05864da7
DS
10233 /* Line 10 display PMSI tunnel attribute, if present */
10234 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10235 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10236 bgp_attr_get_pmsi_tnl_type(attr),
10237 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10238
05864da7
DS
10239 if (json_paths) {
10240 json_pmsi = json_object_new_object();
10241 json_object_string_add(json_pmsi, "tunnelType", str);
10242 json_object_int_add(json_pmsi, "label",
10243 label2vni(&attr->label));
10244 json_object_object_add(json_path, "pmsi", json_pmsi);
10245 } else
10246 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10247 str, label2vni(&attr->label));
d62a17ae 10248 }
f1aa5d8a 10249
d62a17ae 10250 /* We've constructed the json object for this path, add it to the json
10251 * array of paths
10252 */
10253 if (json_paths) {
10254 if (json_nexthop_global || json_nexthop_ll) {
10255 json_nexthops = json_object_new_array();
f1aa5d8a 10256
d62a17ae 10257 if (json_nexthop_global)
10258 json_object_array_add(json_nexthops,
10259 json_nexthop_global);
f1aa5d8a 10260
d62a17ae 10261 if (json_nexthop_ll)
10262 json_object_array_add(json_nexthops,
10263 json_nexthop_ll);
f1aa5d8a 10264
d62a17ae 10265 json_object_object_add(json_path, "nexthops",
10266 json_nexthops);
10267 }
10268
10269 json_object_object_add(json_path, "peer", json_peer);
10270 json_object_array_add(json_paths, json_path);
05864da7 10271 }
b366b518
BB
10272}
10273
96ade3ed 10274#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10275#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10276#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10277
d62a17ae 10278static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10279 const char *prefix_list_str, afi_t afi,
10280 safi_t safi, enum bgp_show_type type);
10281static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10282 const char *filter, afi_t afi, safi_t safi,
10283 enum bgp_show_type type);
10284static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10285 const char *rmap_str, afi_t afi, safi_t safi,
10286 enum bgp_show_type type);
10287static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10288 const char *com, int exact, afi_t afi,
10289 safi_t safi);
10290static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10291 const char *prefix, afi_t afi, safi_t safi,
10292 enum bgp_show_type type);
a4d82a8a 10293static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10294 afi_t afi, safi_t safi, enum bgp_show_type type,
10295 bool use_json);
7f323236
DW
10296static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10297 const char *comstr, int exact, afi_t afi,
96f3485c 10298 safi_t safi, uint8_t show_flags);
d62a17ae 10299
1ae44dfc
LB
10300
10301static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10302 struct bgp_table *table, enum bgp_show_type type,
96f3485c
MK
10303 void *output_arg, char *rd, int is_last,
10304 unsigned long *output_cum, unsigned long *total_cum,
10305 unsigned long *json_header_depth, uint8_t show_flags)
d62a17ae 10306{
40381db7 10307 struct bgp_path_info *pi;
9bcb3eef 10308 struct bgp_dest *dest;
d62a17ae 10309 int header = 1;
10310 int display;
1ae44dfc
LB
10311 unsigned long output_count = 0;
10312 unsigned long total_count = 0;
d62a17ae 10313 struct prefix *p;
d62a17ae 10314 json_object *json_paths = NULL;
10315 int first = 1;
96f3485c
MK
10316 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10317 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10318 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10319
1ae44dfc
LB
10320 if (output_cum && *output_cum != 0)
10321 header = 0;
10322
9386b588 10323 if (use_json && !*json_header_depth) {
96f3485c
MK
10324 if (all)
10325 *json_header_depth = 1;
10326 else {
10327 vty_out(vty, "{\n");
10328 *json_header_depth = 2;
10329 }
10330
d62a17ae 10331 vty_out(vty,
23d0a753
DA
10332 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10333 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10334 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10335 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10336 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10337 ? VRF_DEFAULT_NAME
10338 : bgp->name,
10339 table->version, &bgp->router_id,
01eced22 10340 bgp->default_local_pref, bgp->as);
9386b588 10341 if (rd) {
445c2480 10342 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10343 ++*json_header_depth;
10344 }
d62a17ae 10345 }
718e3744 10346
445c2480
DS
10347 if (use_json && rd) {
10348 vty_out(vty, " \"%s\" : { ", rd);
10349 }
10350
d62a17ae 10351 /* Start processing of routes. */
9bcb3eef
DS
10352 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10353 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10354
9bcb3eef 10355 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10356 if (pi == NULL)
98ce9a06 10357 continue;
d62a17ae 10358
98ce9a06 10359 display = 0;
98ce9a06
DS
10360 if (use_json)
10361 json_paths = json_object_new_array();
10362 else
10363 json_paths = NULL;
d62a17ae 10364
6f94b685 10365 for (; pi; pi = pi->next) {
98ce9a06
DS
10366 total_count++;
10367 if (type == bgp_show_type_flap_statistics
10368 || type == bgp_show_type_flap_neighbor
10369 || type == bgp_show_type_dampend_paths
10370 || type == bgp_show_type_damp_neighbor) {
40381db7 10371 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10372 continue;
10373 }
10374 if (type == bgp_show_type_regexp) {
10375 regex_t *regex = output_arg;
d62a17ae 10376
40381db7 10377 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10378 == REG_NOMATCH)
10379 continue;
10380 }
10381 if (type == bgp_show_type_prefix_list) {
10382 struct prefix_list *plist = output_arg;
d62a17ae 10383
9bcb3eef 10384 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10385 != PREFIX_PERMIT)
10386 continue;
10387 }
10388 if (type == bgp_show_type_filter_list) {
10389 struct as_list *as_list = output_arg;
d62a17ae 10390
40381db7 10391 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
10392 != AS_FILTER_PERMIT)
10393 continue;
10394 }
10395 if (type == bgp_show_type_route_map) {
10396 struct route_map *rmap = output_arg;
9b6d8fcf 10397 struct bgp_path_info path;
98ce9a06 10398 struct attr dummy_attr;
b68885f9 10399 route_map_result_t ret;
d62a17ae 10400
6f4f49b2 10401 dummy_attr = *pi->attr;
d62a17ae 10402
40381db7 10403 path.peer = pi->peer;
9b6d8fcf 10404 path.attr = &dummy_attr;
d62a17ae 10405
9bcb3eef 10406 ret = route_map_apply(rmap, dest_p, RMAP_BGP,
9b6d8fcf 10407 &path);
98ce9a06
DS
10408 if (ret == RMAP_DENYMATCH)
10409 continue;
10410 }
10411 if (type == bgp_show_type_neighbor
10412 || type == bgp_show_type_flap_neighbor
10413 || type == bgp_show_type_damp_neighbor) {
10414 union sockunion *su = output_arg;
10415
40381db7
DS
10416 if (pi->peer == NULL
10417 || pi->peer->su_remote == NULL
10418 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
10419 continue;
10420 }
10421 if (type == bgp_show_type_cidr_only) {
d7c0a89a 10422 uint32_t destination;
d62a17ae 10423
9bcb3eef 10424 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 10425 if (IN_CLASSC(destination)
9bcb3eef 10426 && dest_p->prefixlen == 24)
98ce9a06
DS
10427 continue;
10428 if (IN_CLASSB(destination)
9bcb3eef 10429 && dest_p->prefixlen == 16)
98ce9a06
DS
10430 continue;
10431 if (IN_CLASSA(destination)
9bcb3eef 10432 && dest_p->prefixlen == 8)
98ce9a06
DS
10433 continue;
10434 }
10435 if (type == bgp_show_type_prefix_longer) {
f7813c7c 10436 p = output_arg;
9bcb3eef 10437 if (!prefix_match(p, dest_p))
98ce9a06
DS
10438 continue;
10439 }
10440 if (type == bgp_show_type_community_all) {
40381db7 10441 if (!pi->attr->community)
98ce9a06
DS
10442 continue;
10443 }
10444 if (type == bgp_show_type_community) {
10445 struct community *com = output_arg;
d62a17ae 10446
40381db7
DS
10447 if (!pi->attr->community
10448 || !community_match(pi->attr->community,
98ce9a06
DS
10449 com))
10450 continue;
10451 }
10452 if (type == bgp_show_type_community_exact) {
10453 struct community *com = output_arg;
d62a17ae 10454
40381db7
DS
10455 if (!pi->attr->community
10456 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
10457 continue;
10458 }
10459 if (type == bgp_show_type_community_list) {
10460 struct community_list *list = output_arg;
d62a17ae 10461
40381db7 10462 if (!community_list_match(pi->attr->community,
a4d82a8a 10463 list))
98ce9a06
DS
10464 continue;
10465 }
a4d82a8a 10466 if (type == bgp_show_type_community_list_exact) {
98ce9a06 10467 struct community_list *list = output_arg;
d62a17ae 10468
98ce9a06 10469 if (!community_list_exact_match(
40381db7 10470 pi->attr->community, list))
98ce9a06
DS
10471 continue;
10472 }
10473 if (type == bgp_show_type_lcommunity) {
10474 struct lcommunity *lcom = output_arg;
d62a17ae 10475
40381db7
DS
10476 if (!pi->attr->lcommunity
10477 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
10478 lcom))
10479 continue;
10480 }
36a206db 10481
10482 if (type == bgp_show_type_lcommunity_exact) {
10483 struct lcommunity *lcom = output_arg;
10484
10485 if (!pi->attr->lcommunity
10486 || !lcommunity_cmp(pi->attr->lcommunity,
10487 lcom))
10488 continue;
10489 }
98ce9a06
DS
10490 if (type == bgp_show_type_lcommunity_list) {
10491 struct community_list *list = output_arg;
d62a17ae 10492
40381db7 10493 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 10494 list))
98ce9a06
DS
10495 continue;
10496 }
36a206db 10497 if (type
10498 == bgp_show_type_lcommunity_list_exact) {
10499 struct community_list *list = output_arg;
10500
10501 if (!lcommunity_list_exact_match(
10502 pi->attr->lcommunity, list))
10503 continue;
10504 }
98ce9a06 10505 if (type == bgp_show_type_lcommunity_all) {
40381db7 10506 if (!pi->attr->lcommunity)
98ce9a06
DS
10507 continue;
10508 }
10509 if (type == bgp_show_type_dampend_paths
10510 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
10511 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
10512 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
10513 continue;
10514 }
10515
10516 if (!use_json && header) {
23d0a753
DA
10517 vty_out(vty,
10518 "BGP table version is %" PRIu64
10519 ", local router ID is %pI4, vrf id ",
10520 table->version, &bgp->router_id);
9df8b37c
PZ
10521 if (bgp->vrf_id == VRF_UNKNOWN)
10522 vty_out(vty, "%s", VRFID_NONE_STR);
10523 else
10524 vty_out(vty, "%u", bgp->vrf_id);
10525 vty_out(vty, "\n");
01eced22
AD
10526 vty_out(vty, "Default local pref %u, ",
10527 bgp->default_local_pref);
10528 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 10529 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10530 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 10531 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 10532 if (type == bgp_show_type_dampend_paths
10533 || type == bgp_show_type_damp_neighbor)
98ce9a06 10534 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
10535 else if (type == bgp_show_type_flap_statistics
10536 || type == bgp_show_type_flap_neighbor)
98ce9a06 10537 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 10538 else
ae248832
MK
10539 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
10540 : BGP_SHOW_HEADER));
98ce9a06 10541 header = 0;
d62a17ae 10542 }
98ce9a06
DS
10543 if (rd != NULL && !display && !output_count) {
10544 if (!use_json)
10545 vty_out(vty,
10546 "Route Distinguisher: %s\n",
10547 rd);
d62a17ae 10548 }
98ce9a06
DS
10549 if (type == bgp_show_type_dampend_paths
10550 || type == bgp_show_type_damp_neighbor)
9bcb3eef 10551 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10552 AFI_IP, safi, use_json,
10553 json_paths);
98ce9a06
DS
10554 else if (type == bgp_show_type_flap_statistics
10555 || type == bgp_show_type_flap_neighbor)
9bcb3eef 10556 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10557 AFI_IP, safi, use_json,
10558 json_paths);
98ce9a06 10559 else
9bcb3eef 10560 route_vty_out(vty, dest_p, pi, display, safi,
ae248832 10561 json_paths, wide);
98ce9a06 10562 display++;
d62a17ae 10563 }
10564
98ce9a06
DS
10565 if (display) {
10566 output_count++;
10567 if (!use_json)
10568 continue;
10569
625d2931 10570 /* encode prefix */
9bcb3eef 10571 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
10572 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
10573
1840384b 10574
b54892e0
DS
10575 bgp_fs_nlri_get_string(
10576 (unsigned char *)
9bcb3eef
DS
10577 dest_p->u.prefix_flowspec.ptr,
10578 dest_p->u.prefix_flowspec.prefixlen,
1840384b 10579 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
10580 family2afi(dest_p->u
10581 .prefix_flowspec.family));
625d2931 10582 if (first)
b54892e0 10583 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 10584 dest_p->u.prefix_flowspec
b54892e0 10585 .prefixlen);
625d2931 10586 else
b54892e0 10587 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 10588 dest_p->u.prefix_flowspec
b54892e0 10589 .prefixlen);
625d2931 10590 } else {
625d2931 10591 if (first)
1b78780b 10592 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 10593 else
1b78780b 10594 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 10595 }
98ce9a06 10596 vty_out(vty, "%s",
f4ec52f7
DA
10597 json_object_to_json_string_ext(
10598 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 10599 json_object_free(json_paths);
449feb8e 10600 json_paths = NULL;
98ce9a06 10601 first = 0;
1f83ed02
DS
10602 } else
10603 json_object_free(json_paths);
98ce9a06
DS
10604 }
10605
1ae44dfc
LB
10606 if (output_cum) {
10607 output_count += *output_cum;
10608 *output_cum = output_count;
10609 }
10610 if (total_cum) {
10611 total_count += *total_cum;
10612 *total_cum = total_count;
10613 }
d62a17ae 10614 if (use_json) {
9386b588 10615 if (rd) {
a4d82a8a 10616 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
10617 }
10618 if (is_last) {
a4d82a8a
PZ
10619 unsigned long i;
10620 for (i = 0; i < *json_header_depth; ++i)
10621 vty_out(vty, " } ");
96f3485c
MK
10622 if (!all)
10623 vty_out(vty, "\n");
9386b588 10624 }
d62a17ae 10625 } else {
1ae44dfc
LB
10626 if (is_last) {
10627 /* No route is displayed */
10628 if (output_count == 0) {
10629 if (type == bgp_show_type_normal)
10630 vty_out(vty,
10631 "No BGP prefixes displayed, %ld exist\n",
10632 total_count);
10633 } else
d62a17ae 10634 vty_out(vty,
1ae44dfc
LB
10635 "\nDisplayed %ld routes and %ld total paths\n",
10636 output_count, total_count);
10637 }
d62a17ae 10638 }
718e3744 10639
d62a17ae 10640 return CMD_SUCCESS;
718e3744 10641}
10642
1ae44dfc
LB
10643int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
10644 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 10645 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 10646{
9bcb3eef 10647 struct bgp_dest *dest, *next;
1ae44dfc
LB
10648 unsigned long output_cum = 0;
10649 unsigned long total_cum = 0;
9386b588 10650 unsigned long json_header_depth = 0;
67009e22 10651 struct bgp_table *itable;
0136788c 10652 bool show_msg;
96f3485c 10653 uint8_t show_flags = 0;
0136788c
LB
10654
10655 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 10656
96f3485c
MK
10657 if (use_json)
10658 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10659
9bcb3eef
DS
10660 for (dest = bgp_table_top(table); dest; dest = next) {
10661 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10662
9bcb3eef
DS
10663 next = bgp_route_next(dest);
10664 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 10665 continue;
67009e22 10666
9bcb3eef 10667 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 10668 if (itable != NULL) {
1ae44dfc 10669 struct prefix_rd prd;
06b9f471 10670 char rd[RD_ADDRSTRLEN];
1ae44dfc 10671
9bcb3eef 10672 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 10673 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 10674 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
10675 rd, next == NULL, &output_cum,
10676 &total_cum, &json_header_depth,
10677 show_flags);
0136788c
LB
10678 if (next == NULL)
10679 show_msg = false;
1ae44dfc
LB
10680 }
10681 }
0136788c
LB
10682 if (show_msg) {
10683 if (output_cum == 0)
10684 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
10685 total_cum);
10686 else
10687 vty_out(vty,
10688 "\nDisplayed %ld routes and %ld total paths\n",
10689 output_cum, total_cum);
10690 }
1ae44dfc
LB
10691 return CMD_SUCCESS;
10692}
d62a17ae 10693static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c
MK
10694 enum bgp_show_type type, void *output_arg,
10695 uint8_t show_flags)
fee0f4c6 10696{
d62a17ae 10697 struct bgp_table *table;
9386b588 10698 unsigned long json_header_depth = 0;
96f3485c 10699 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 10700
d62a17ae 10701 if (bgp == NULL) {
10702 bgp = bgp_get_default();
10703 }
fee0f4c6 10704
d62a17ae 10705 if (bgp == NULL) {
10706 if (!use_json)
10707 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10708 else
10709 vty_out(vty, "{}\n");
d62a17ae 10710 return CMD_WARNING;
10711 }
4dd6177e 10712
1ae44dfc 10713 table = bgp->rib[afi][safi];
d62a17ae 10714 /* use MPLS and ENCAP specific shows until they are merged */
10715 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
10716 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
10717 output_arg, use_json);
d62a17ae 10718 }
dba3c1d3
PG
10719
10720 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
10721 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
10722 output_arg, use_json,
10723 1, NULL, NULL);
10724 }
d62a17ae 10725 /* labeled-unicast routes live in the unicast table */
10726 else if (safi == SAFI_LABELED_UNICAST)
10727 safi = SAFI_UNICAST;
fee0f4c6 10728
96f3485c
MK
10729 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
10730 NULL, NULL, &json_header_depth, show_flags);
fee0f4c6 10731}
10732
d62a17ae 10733static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96f3485c 10734 safi_t safi, uint8_t show_flags)
f186de26 10735{
d62a17ae 10736 struct listnode *node, *nnode;
10737 struct bgp *bgp;
10738 int is_first = 1;
9f049418 10739 bool route_output = false;
96f3485c 10740 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 10741
d62a17ae 10742 if (use_json)
10743 vty_out(vty, "{\n");
9f689658 10744
d62a17ae 10745 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 10746 route_output = true;
d62a17ae 10747 if (use_json) {
10748 if (!is_first)
10749 vty_out(vty, ",\n");
10750 else
10751 is_first = 0;
10752
10753 vty_out(vty, "\"%s\":",
10754 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10755 ? VRF_DEFAULT_NAME
d62a17ae 10756 : bgp->name);
10757 } else {
10758 vty_out(vty, "\nInstance %s:\n",
10759 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10760 ? VRF_DEFAULT_NAME
d62a17ae 10761 : bgp->name);
10762 }
10763 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
96f3485c 10764 show_flags);
d62a17ae 10765 }
9f689658 10766
d62a17ae 10767 if (use_json)
10768 vty_out(vty, "}\n");
9f049418
DS
10769 else if (!route_output)
10770 vty_out(vty, "%% BGP instance not found\n");
f186de26 10771}
10772
718e3744 10773/* Header of detailed BGP route information */
d62a17ae 10774void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9bcb3eef 10775 struct bgp_dest *dest, struct prefix_rd *prd,
d62a17ae 10776 afi_t afi, safi_t safi, json_object *json)
10777{
40381db7 10778 struct bgp_path_info *pi;
b54892e0 10779 const struct prefix *p;
d62a17ae 10780 struct peer *peer;
10781 struct listnode *node, *nnode;
06b9f471 10782 char buf1[RD_ADDRSTRLEN];
0291c246 10783 char prefix_str[BUFSIZ];
d62a17ae 10784 int count = 0;
10785 int best = 0;
10786 int suppress = 0;
c5f1e1b2
C
10787 int accept_own = 0;
10788 int route_filter_translated_v4 = 0;
10789 int route_filter_v4 = 0;
10790 int route_filter_translated_v6 = 0;
10791 int route_filter_v6 = 0;
10792 int llgr_stale = 0;
10793 int no_llgr = 0;
10794 int accept_own_nexthop = 0;
10795 int blackhole = 0;
d62a17ae 10796 int no_export = 0;
10797 int no_advertise = 0;
10798 int local_as = 0;
c5f1e1b2 10799 int no_peer = 0;
d62a17ae 10800 int first = 1;
10801 int has_valid_label = 0;
10802 mpls_label_t label = 0;
10803 json_object *json_adv_to = NULL;
9bedbb1e 10804
9bcb3eef
DS
10805 p = bgp_dest_get_prefix(dest);
10806 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 10807
10808 if (has_valid_label)
9bcb3eef 10809 label = label_pton(&dest->local_label);
d62a17ae 10810
44c69747 10811 if (safi == SAFI_EVPN) {
d62a17ae 10812
44c69747 10813 if (!json) {
2dbe669b 10814 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 10815 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 10816 : "",
2dbe669b 10817 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
10818 } else {
10819 json_object_string_add(json, "rd",
10820 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
10821 "");
10822 bgp_evpn_route2json((struct prefix_evpn *)p, json);
10823 }
10824 } else {
10825 if (!json) {
8228a9a7 10826 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
d62a17ae 10827 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
10828 ? prefix_rd2str(prd, buf1,
10829 sizeof(buf1))
10830 : ""),
10831 safi == SAFI_MPLS_VPN ? ":" : "", p);
cd1964ff 10832
44c69747
LK
10833 } else
10834 json_object_string_add(json, "prefix",
10835 prefix2str(p, prefix_str, sizeof(prefix_str)));
10836 }
10837
10838 if (has_valid_label) {
10839 if (json)
10840 json_object_int_add(json, "localLabel", label);
10841 else
d62a17ae 10842 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
10843 }
10844
10845 if (!json)
d62a17ae 10846 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 10847 vty_out(vty, "not allocated\n");
718e3744 10848
9bcb3eef 10849 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 10850 count++;
40381db7 10851 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 10852 best = count;
4056a5f6 10853 if (bgp_path_suppressed(pi))
d62a17ae 10854 suppress = 1;
cee9c031 10855
40381db7 10856 if (pi->attr->community == NULL)
cee9c031
QY
10857 continue;
10858
10859 no_advertise += community_include(
40381db7
DS
10860 pi->attr->community, COMMUNITY_NO_ADVERTISE);
10861 no_export += community_include(pi->attr->community,
cee9c031 10862 COMMUNITY_NO_EXPORT);
40381db7 10863 local_as += community_include(pi->attr->community,
cee9c031 10864 COMMUNITY_LOCAL_AS);
40381db7 10865 accept_own += community_include(pi->attr->community,
cee9c031
QY
10866 COMMUNITY_ACCEPT_OWN);
10867 route_filter_translated_v4 += community_include(
40381db7 10868 pi->attr->community,
cee9c031
QY
10869 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
10870 route_filter_translated_v6 += community_include(
40381db7 10871 pi->attr->community,
cee9c031
QY
10872 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
10873 route_filter_v4 += community_include(
40381db7 10874 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 10875 route_filter_v6 += community_include(
40381db7
DS
10876 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
10877 llgr_stale += community_include(pi->attr->community,
cee9c031 10878 COMMUNITY_LLGR_STALE);
40381db7 10879 no_llgr += community_include(pi->attr->community,
cee9c031
QY
10880 COMMUNITY_NO_LLGR);
10881 accept_own_nexthop +=
40381db7 10882 community_include(pi->attr->community,
cee9c031 10883 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 10884 blackhole += community_include(pi->attr->community,
cee9c031 10885 COMMUNITY_BLACKHOLE);
40381db7 10886 no_peer += community_include(pi->attr->community,
cee9c031 10887 COMMUNITY_NO_PEER);
d62a17ae 10888 }
718e3744 10889 }
718e3744 10890
d62a17ae 10891 if (!json) {
10892 vty_out(vty, "Paths: (%d available", count);
10893 if (best) {
10894 vty_out(vty, ", best #%d", best);
b84060bb
PG
10895 if (safi == SAFI_UNICAST) {
10896 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
10897 vty_out(vty, ", table %s",
10898 VRF_DEFAULT_NAME);
10899 else
10900 vty_out(vty, ", vrf %s",
10901 bgp->name);
10902 }
d62a17ae 10903 } else
10904 vty_out(vty, ", no best path");
10905
c5f1e1b2
C
10906 if (accept_own)
10907 vty_out(vty,
10908 ", accept own local route exported and imported in different VRF");
10909 else if (route_filter_translated_v4)
10910 vty_out(vty,
10911 ", mark translated RTs for VPNv4 route filtering");
10912 else if (route_filter_v4)
10913 vty_out(vty,
10914 ", attach RT as-is for VPNv4 route filtering");
10915 else if (route_filter_translated_v6)
10916 vty_out(vty,
10917 ", mark translated RTs for VPNv6 route filtering");
10918 else if (route_filter_v6)
10919 vty_out(vty,
10920 ", attach RT as-is for VPNv6 route filtering");
10921 else if (llgr_stale)
10922 vty_out(vty,
10923 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
10924 else if (no_llgr)
10925 vty_out(vty,
10926 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
10927 else if (accept_own_nexthop)
10928 vty_out(vty,
10929 ", accept local nexthop");
10930 else if (blackhole)
10931 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 10932 else if (no_export)
10933 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
10934 else if (no_advertise)
10935 vty_out(vty, ", not advertised to any peer");
d62a17ae 10936 else if (local_as)
10937 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
10938 else if (no_peer)
10939 vty_out(vty,
10940 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 10941
10942 if (suppress)
10943 vty_out(vty,
10944 ", Advertisements suppressed by an aggregate.");
10945 vty_out(vty, ")\n");
10946 }
718e3744 10947
d62a17ae 10948 /* If we are not using addpath then we can display Advertised to and
10949 * that will
10950 * show what peers we advertised the bestpath to. If we are using
10951 * addpath
10952 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 10953 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 10954 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 10955 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 10956 if (json && !json_adv_to)
10957 json_adv_to = json_object_new_object();
10958
10959 route_vty_out_advertised_to(
10960 vty, peer, &first,
10961 " Advertised to non peer-group peers:\n ",
10962 json_adv_to);
10963 }
10964 }
10965
10966 if (json) {
10967 if (json_adv_to) {
10968 json_object_object_add(json, "advertisedTo",
10969 json_adv_to);
10970 }
10971 } else {
10972 if (first)
10973 vty_out(vty, " Not advertised to any peer");
10974 vty_out(vty, "\n");
10975 }
10976 }
718e3744 10977}
10978
44c69747 10979static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9bcb3eef
DS
10980 struct bgp_dest *bgp_node, struct vty *vty,
10981 struct bgp *bgp, afi_t afi, safi_t safi,
10982 json_object *json, enum bgp_path_type pathtype,
10983 int *display)
44c69747
LK
10984{
10985 struct bgp_path_info *pi;
10986 int header = 1;
10987 char rdbuf[RD_ADDRSTRLEN];
10988 json_object *json_header = NULL;
10989 json_object *json_paths = NULL;
10990
9bcb3eef 10991 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
44c69747
LK
10992
10993 if (json && !json_paths) {
10994 /* Instantiate json_paths only if path is valid */
10995 json_paths = json_object_new_array();
10996 if (pfx_rd) {
10997 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
10998 json_header = json_object_new_object();
10999 } else
11000 json_header = json;
11001 }
11002
11003 if (header) {
11004 route_vty_out_detail_header(
11005 vty, bgp, bgp_node, pfx_rd,
11006 AFI_IP, safi, json_header);
11007 header = 0;
11008 }
11009 (*display)++;
11010
11011 if (pathtype == BGP_PATH_SHOW_ALL
11012 || (pathtype == BGP_PATH_SHOW_BESTPATH
11013 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11014 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11015 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11016 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
11017 route_vty_out_detail(vty, bgp, bgp_node,
11018 pi, AFI_IP, safi,
11019 json_paths);
11020 }
11021
11022 if (json && json_paths) {
11023 json_object_object_add(json_header, "paths", json_paths);
11024
11025 if (pfx_rd)
11026 json_object_object_add(json, rdbuf, json_header);
11027 }
11028}
11029
718e3744 11030/* Display specified route of BGP table. */
d62a17ae 11031static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11032 struct bgp_table *rib, const char *ip_str,
11033 afi_t afi, safi_t safi,
11034 struct prefix_rd *prd, int prefix_check,
9f049418 11035 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11036{
11037 int ret;
d62a17ae 11038 int display = 0;
11039 struct prefix match;
9bcb3eef
DS
11040 struct bgp_dest *dest;
11041 struct bgp_dest *rm;
d62a17ae 11042 struct bgp_table *table;
11043 json_object *json = NULL;
11044 json_object *json_paths = NULL;
11045
11046 /* Check IP address argument. */
11047 ret = str2prefix(ip_str, &match);
11048 if (!ret) {
11049 vty_out(vty, "address is malformed\n");
11050 return CMD_WARNING;
11051 }
718e3744 11052
d62a17ae 11053 match.family = afi2family(afi);
b05a1c8b 11054
44c69747 11055 if (use_json)
d62a17ae 11056 json = json_object_new_object();
718e3744 11057
44c69747 11058 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11059 for (dest = bgp_table_top(rib); dest;
11060 dest = bgp_route_next(dest)) {
11061 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11062
9bcb3eef 11063 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11064 continue;
9bcb3eef 11065 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11066 if (!table)
ea47320b 11067 continue;
d62a17ae 11068
ea47320b
DL
11069 if ((rm = bgp_node_match(table, &match)) == NULL)
11070 continue;
d62a17ae 11071
9bcb3eef 11072 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11073 if (prefix_check
b54892e0 11074 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11075 bgp_dest_unlock_node(rm);
ea47320b
DL
11076 continue;
11077 }
d62a17ae 11078
9bcb3eef 11079 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
11080 bgp, afi, safi, json, pathtype,
11081 &display);
44c69747 11082
9bcb3eef 11083 bgp_dest_unlock_node(rm);
44c69747
LK
11084 }
11085 } else if (safi == SAFI_EVPN) {
9bcb3eef 11086 struct bgp_dest *longest_pfx;
cded3b72 11087 bool is_exact_pfxlen_match = false;
44c69747 11088
9bcb3eef
DS
11089 for (dest = bgp_table_top(rib); dest;
11090 dest = bgp_route_next(dest)) {
11091 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11092
9bcb3eef 11093 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11094 continue;
9bcb3eef 11095 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11096 if (!table)
11097 continue;
11098
11099 longest_pfx = NULL;
cded3b72 11100 is_exact_pfxlen_match = false;
44c69747
LK
11101 /*
11102 * Search through all the prefixes for a match. The
11103 * pfx's are enumerated in ascending order of pfxlens.
11104 * So, the last pfx match is the longest match. Set
11105 * is_exact_pfxlen_match when we get exact pfxlen match
11106 */
11107 for (rm = bgp_table_top(table); rm;
11108 rm = bgp_route_next(rm)) {
b54892e0 11109 const struct prefix *rm_p =
9bcb3eef 11110 bgp_dest_get_prefix(rm);
44c69747
LK
11111 /*
11112 * Get prefixlen of the ip-prefix within type5
11113 * evpn route
11114 */
b54892e0
DS
11115 if (evpn_type5_prefix_match(rm_p, &match)
11116 && rm->info) {
44c69747
LK
11117 longest_pfx = rm;
11118 int type5_pfxlen =
b54892e0
DS
11119 bgp_evpn_get_type5_prefixlen(
11120 rm_p);
44c69747 11121 if (type5_pfxlen == match.prefixlen) {
cded3b72 11122 is_exact_pfxlen_match = true;
9bcb3eef 11123 bgp_dest_unlock_node(rm);
44c69747
LK
11124 break;
11125 }
d62a17ae 11126 }
11127 }
ea47320b 11128
44c69747
LK
11129 if (!longest_pfx)
11130 continue;
11131
11132 if (prefix_check && !is_exact_pfxlen_match)
11133 continue;
11134
11135 rm = longest_pfx;
9bcb3eef 11136 bgp_dest_lock_node(rm);
44c69747 11137
9bcb3eef 11138 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
11139 bgp, afi, safi, json, pathtype,
11140 &display);
44c69747 11141
9bcb3eef 11142 bgp_dest_unlock_node(rm);
d62a17ae 11143 }
98a9dbc7 11144 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11145 if (use_json)
11146 json_paths = json_object_new_array();
11147
63a0b7a9
PG
11148 display = bgp_flowspec_display_match_per_ip(afi, rib,
11149 &match, prefix_check,
11150 vty,
11151 use_json,
11152 json_paths);
44c69747
LK
11153 if (use_json && display)
11154 json_object_object_add(json, "paths", json_paths);
d62a17ae 11155 } else {
9bcb3eef
DS
11156 if ((dest = bgp_node_match(rib, &match)) != NULL) {
11157 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11158 if (!prefix_check
9bcb3eef
DS
11159 || dest_p->prefixlen == match.prefixlen) {
11160 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11161 safi, json, pathtype,
11162 &display);
d62a17ae 11163 }
11164
9bcb3eef 11165 bgp_dest_unlock_node(dest);
d62a17ae 11166 }
11167 }
e5eee9af 11168
d62a17ae 11169 if (use_json) {
996c9314 11170 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
11171 json, JSON_C_TO_STRING_PRETTY |
11172 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 11173 json_object_free(json);
11174 } else {
11175 if (!display) {
11176 vty_out(vty, "%% Network not in table\n");
11177 return CMD_WARNING;
11178 }
11179 }
b05a1c8b 11180
d62a17ae 11181 return CMD_SUCCESS;
718e3744 11182}
11183
fee0f4c6 11184/* Display specified route of Main RIB */
d62a17ae 11185static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11186 afi_t afi, safi_t safi, struct prefix_rd *prd,
11187 int prefix_check, enum bgp_path_type pathtype,
9f049418 11188 bool use_json)
d62a17ae 11189{
9b86009a 11190 if (!bgp) {
d62a17ae 11191 bgp = bgp_get_default();
9b86009a
RW
11192 if (!bgp) {
11193 if (!use_json)
11194 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11195 else
11196 vty_out(vty, "{}\n");
9b86009a
RW
11197 return CMD_WARNING;
11198 }
11199 }
d62a17ae 11200
11201 /* labeled-unicast routes live in the unicast table */
11202 if (safi == SAFI_LABELED_UNICAST)
11203 safi = SAFI_UNICAST;
11204
11205 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
11206 afi, safi, prd, prefix_check, pathtype,
11207 use_json);
11208}
11209
11210static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11211 struct cmd_token **argv, bool exact, afi_t afi,
11212 safi_t safi, bool uj)
d62a17ae 11213{
11214 struct lcommunity *lcom;
11215 struct buffer *b;
11216 int i;
11217 char *str;
11218 int first = 0;
96f3485c 11219 uint8_t show_flags = 0;
4f28b2b5 11220 int ret;
96f3485c
MK
11221
11222 if (uj)
11223 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11224
11225 b = buffer_new(1024);
11226 for (i = 0; i < argc; i++) {
11227 if (first)
11228 buffer_putc(b, ' ');
11229 else {
11230 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11231 first = 1;
11232 buffer_putstr(b, argv[i]->arg);
11233 }
11234 }
11235 }
11236 buffer_putc(b, '\0');
57d187bc 11237
d62a17ae 11238 str = buffer_getstr(b);
11239 buffer_free(b);
57d187bc 11240
d62a17ae 11241 lcom = lcommunity_str2com(str);
11242 XFREE(MTYPE_TMP, str);
11243 if (!lcom) {
11244 vty_out(vty, "%% Large-community malformed\n");
11245 return CMD_WARNING;
11246 }
57d187bc 11247
4f28b2b5 11248 ret = bgp_show(vty, bgp, afi, safi,
36a206db 11249 (exact ? bgp_show_type_lcommunity_exact
ae248832 11250 : bgp_show_type_lcommunity),
96f3485c 11251 lcom, show_flags);
4f28b2b5
DS
11252
11253 lcommunity_free(&lcom);
11254 return ret;
57d187bc
JS
11255}
11256
d62a17ae 11257static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11258 const char *lcom, bool exact, afi_t afi,
11259 safi_t safi, bool uj)
57d187bc 11260{
d62a17ae 11261 struct community_list *list;
96f3485c
MK
11262 uint8_t show_flags = 0;
11263
11264 if (uj)
11265 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11266
57d187bc 11267
e237b0d2 11268 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11269 LARGE_COMMUNITY_LIST_MASTER);
11270 if (list == NULL) {
11271 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11272 lcom);
11273 return CMD_WARNING;
11274 }
57d187bc 11275
36a206db 11276 return bgp_show(vty, bgp, afi, safi,
11277 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11278 : bgp_show_type_lcommunity_list),
96f3485c 11279 list, show_flags);
fee0f4c6 11280}
11281
52951b63
DS
11282DEFUN (show_ip_bgp_large_community_list,
11283 show_ip_bgp_large_community_list_cmd,
36a206db 11284 "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
11285 SHOW_STR
11286 IP_STR
11287 BGP_STR
11288 BGP_INSTANCE_HELP_STR
9bedbb1e 11289 BGP_AFI_HELP_STR
4dd6177e 11290 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11291 "Display routes matching the large-community-list\n"
11292 "large-community-list number\n"
11293 "large-community-list name\n"
36a206db 11294 "Exact match of the large-communities\n"
52951b63
DS
11295 JSON_STR)
11296{
d62a17ae 11297 afi_t afi = AFI_IP6;
11298 safi_t safi = SAFI_UNICAST;
11299 int idx = 0;
36a206db 11300 bool exact_match = 0;
4d678463 11301 struct bgp *bgp = NULL;
9f049418 11302 bool uj = use_json(argc, argv);
d62a17ae 11303
4d678463
KA
11304 if (uj)
11305 argc--;
11306
11307 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11308 &bgp, uj);
11309 if (!idx)
11310 return CMD_WARNING;
d62a17ae 11311
11312 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11313
11314 const char *clist_number_or_name = argv[++idx]->arg;
11315
11316 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11317 exact_match = 1;
11318
11319 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11320 exact_match, afi, safi, uj);
52951b63
DS
11321}
11322DEFUN (show_ip_bgp_large_community,
11323 show_ip_bgp_large_community_cmd,
36a206db 11324 "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
11325 SHOW_STR
11326 IP_STR
11327 BGP_STR
11328 BGP_INSTANCE_HELP_STR
9bedbb1e 11329 BGP_AFI_HELP_STR
4dd6177e 11330 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11331 "Display routes matching the large-communities\n"
11332 "List of large-community numbers\n"
36a206db 11333 "Exact match of the large-communities\n"
52951b63
DS
11334 JSON_STR)
11335{
d62a17ae 11336 afi_t afi = AFI_IP6;
11337 safi_t safi = SAFI_UNICAST;
11338 int idx = 0;
36a206db 11339 bool exact_match = 0;
4d678463 11340 struct bgp *bgp = NULL;
9f049418 11341 bool uj = use_json(argc, argv);
96f3485c 11342 uint8_t show_flags = 0;
d62a17ae 11343
96f3485c
MK
11344 if (uj) {
11345 argc--;
11346 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11347 }
4d678463 11348
96f3485c
MK
11349 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11350 &bgp, uj);
11351 if (!idx)
11352 return CMD_WARNING;
d62a17ae 11353
36a206db 11354 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11355 if (argv_find(argv, argc, "exact-match", &idx))
11356 exact_match = 1;
11357 return bgp_show_lcommunity(vty, bgp, argc, argv,
11358 exact_match, afi, safi, uj);
11359 } else
d62a17ae 11360 return bgp_show(vty, bgp, afi, safi,
96f3485c 11361 bgp_show_type_lcommunity_all, NULL, show_flags);
52951b63
DS
11362}
11363
71f1613a
DA
11364static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11365 safi_t safi, struct json_object *json_array);
d62a17ae 11366static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 11367 safi_t safi, struct json_object *json);
e01ca200 11368
7b2ff250 11369
9ab0cf58
PG
11370DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11371 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11372 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11373 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
11374{
11375 bool uj = use_json(argc, argv);
11376 struct bgp *bgp = NULL;
ec76a1d1
DA
11377 safi_t safi = SAFI_UNICAST;
11378 afi_t afi = AFI_IP6;
4265b261 11379 int idx = 0;
6c9d22e2
PG
11380 struct json_object *json_all = NULL;
11381 struct json_object *json_afi_safi = NULL;
4265b261
PG
11382
11383 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11384 &bgp, false);
71f1613a 11385 if (!idx)
4265b261 11386 return CMD_WARNING;
6c9d22e2 11387
4265b261 11388 if (uj)
6c9d22e2 11389 json_all = json_object_new_object();
4265b261 11390
9ab0cf58
PG
11391 FOREACH_AFI_SAFI (afi, safi) {
11392 /*
11393 * So limit output to those afi/safi pairs that
11394 * actually have something interesting in them
11395 */
11396 if (strmatch(get_afi_safi_str(afi, safi, true),
11397 "Unknown")) {
11398 continue;
11399 }
11400 if (uj) {
11401 json_afi_safi = json_object_new_array();
11402 json_object_object_add(
11403 json_all,
11404 get_afi_safi_str(afi, safi, true),
11405 json_afi_safi);
11406 } else {
11407 json_afi_safi = NULL;
6c9d22e2 11408 }
9ab0cf58
PG
11409
11410 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 11411 }
6c9d22e2
PG
11412
11413 if (uj) {
9ab0cf58
PG
11414 vty_out(vty, "%s",
11415 json_object_to_json_string_ext(
11416 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 11417 json_object_free(json_all);
4265b261 11418 }
6c9d22e2 11419
4265b261
PG
11420 return CMD_SUCCESS;
11421}
11422
7b2ff250 11423/* BGP route print out function without JSON */
14718643
PG
11424DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
11425 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 11426 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
11427 SHOW_STR
11428 IP_STR
11429 BGP_STR
11430 BGP_INSTANCE_HELP_STR
11431 L2VPN_HELP_STR
11432 EVPN_HELP_STR
11433 "BGP RIB advertisement statistics\n"
11434 JSON_STR)
11435{
ec76a1d1
DA
11436 afi_t afi = AFI_IP6;
11437 safi_t safi = SAFI_UNICAST;
14718643
PG
11438 struct bgp *bgp = NULL;
11439 int idx = 0, ret;
11440 bool uj = use_json(argc, argv);
11441 struct json_object *json_afi_safi = NULL, *json = NULL;
11442
11443 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11444 &bgp, false);
11445 if (!idx)
11446 return CMD_WARNING;
11447
11448 if (uj)
11449 json_afi_safi = json_object_new_array();
11450 else
11451 json_afi_safi = NULL;
11452
11453 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11454
11455 if (uj) {
11456 json = json_object_new_object();
11457 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11458 json_afi_safi);
11459 vty_out(vty, "%s", json_object_to_json_string_ext(
11460 json, JSON_C_TO_STRING_PRETTY));
11461 json_object_free(json);
11462 }
11463 return ret;
11464}
11465
893cccd0 11466/* BGP route print out function without JSON */
9ab0cf58
PG
11467DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
11468 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11469 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11470 "]]\
893cccd0 11471 statistics [json]",
9ab0cf58
PG
11472 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11473 BGP_SAFI_WITH_LABEL_HELP_STR
11474 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 11475{
ec76a1d1
DA
11476 afi_t afi = AFI_IP6;
11477 safi_t safi = SAFI_UNICAST;
893cccd0
PG
11478 struct bgp *bgp = NULL;
11479 int idx = 0, ret;
11480 bool uj = use_json(argc, argv);
6c9d22e2 11481 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
11482
11483 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11484 &bgp, false);
11485 if (!idx)
11486 return CMD_WARNING;
6c9d22e2 11487
893cccd0 11488 if (uj)
6c9d22e2
PG
11489 json_afi_safi = json_object_new_array();
11490 else
11491 json_afi_safi = NULL;
11492
11493 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11494
11495 if (uj) {
11496 json = json_object_new_object();
11497 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11498 json_afi_safi);
9ab0cf58
PG
11499 vty_out(vty, "%s",
11500 json_object_to_json_string_ext(
11501 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
11502 json_object_free(json);
11503 }
11504 return ret;
893cccd0 11505}
7b2ff250
DW
11506
11507/* BGP route print out function without JSON */
96f3485c 11508DEFPY(show_ip_bgp, show_ip_bgp_cmd,
9ab0cf58
PG
11509 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11510 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11511 "]]\
96f3485c 11512 <[all$all] dampening <parameters>\
7b2ff250
DW
11513 |route-map WORD\
11514 |prefix-list WORD\
11515 |filter-list WORD\
7b2ff250
DW
11516 |community-list <(1-500)|WORD> [exact-match]\
11517 |A.B.C.D/M longer-prefixes\
11518 |X:X::X:X/M longer-prefixes\
893cccd0 11519 >",
9ab0cf58
PG
11520 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11521 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11522 "Display the entries for all address families\n"
9ab0cf58
PG
11523 "Display detailed information about dampening\n"
11524 "Display detail of configured dampening parameters\n"
11525 "Display routes matching the route-map\n"
11526 "A route-map to match on\n"
11527 "Display routes conforming to the prefix-list\n"
11528 "Prefix-list name\n"
11529 "Display routes conforming to the filter-list\n"
11530 "Regular expression access list name\n"
11531 "Display routes matching the community-list\n"
11532 "community-list number\n"
11533 "community-list name\n"
11534 "Exact match of the communities\n"
11535 "IPv4 prefix\n"
11536 "Display route and more specific routes\n"
11537 "IPv6 prefix\n"
11538 "Display route and more specific routes\n")
718e3744 11539{
d62a17ae 11540 afi_t afi = AFI_IP6;
11541 safi_t safi = SAFI_UNICAST;
11542 int exact_match = 0;
d62a17ae 11543 struct bgp *bgp = NULL;
11544 int idx = 0;
96f3485c
MK
11545 uint8_t show_flags = 0;
11546
11547 /* [<ipv4|ipv6> [all]] */
11548 if (all) {
11549 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11550 if (argv_find(argv, argc, "ipv4", &idx))
11551 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11552
11553 if (argv_find(argv, argc, "ipv6", &idx))
11554 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11555 }
d62a17ae 11556
11557 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11558 &bgp, false);
d62a17ae 11559 if (!idx)
11560 return CMD_WARNING;
11561
d62a17ae 11562 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 11563 if (argv_find(argv, argc, "parameters", &idx))
96f3485c
MK
11564 return bgp_show_dampening_parameters(vty, afi, safi,
11565 show_flags);
d62a17ae 11566 }
c016b6c7 11567
d62a17ae 11568 if (argv_find(argv, argc, "prefix-list", &idx))
11569 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
11570 safi, bgp_show_type_prefix_list);
11571
11572 if (argv_find(argv, argc, "filter-list", &idx))
11573 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
11574 safi, bgp_show_type_filter_list);
11575
d62a17ae 11576 if (argv_find(argv, argc, "route-map", &idx))
11577 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
11578 safi, bgp_show_type_route_map);
11579
d62a17ae 11580 if (argv_find(argv, argc, "community-list", &idx)) {
11581 const char *clist_number_or_name = argv[++idx]->arg;
11582 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11583 exact_match = 1;
11584 return bgp_show_community_list(vty, bgp, clist_number_or_name,
11585 exact_match, afi, safi);
11586 }
11587 /* prefix-longer */
11588 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11589 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11590 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
11591 safi,
11592 bgp_show_type_prefix_longer);
11593
7b2ff250
DW
11594 return CMD_WARNING;
11595}
11596
11597/* BGP route print out function with JSON */
ae248832 11598DEFPY (show_ip_bgp_json,
7b2ff250
DW
11599 show_ip_bgp_json_cmd,
11600 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
96f3485c 11601 [all$all]\
cf4898bc
QY
11602 [cidr-only\
11603 |dampening <flap-statistics|dampened-paths>\
11604 |community [AA:NN|local-AS|no-advertise|no-export\
11605 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11606 |accept-own|accept-own-nexthop|route-filter-v6\
11607 |route-filter-v4|route-filter-translated-v6\
11608 |route-filter-translated-v4] [exact-match]\
ae248832 11609 ] [json$uj | wide$wide]",
7b2ff250
DW
11610 SHOW_STR
11611 IP_STR
11612 BGP_STR
11613 BGP_INSTANCE_HELP_STR
11614 BGP_AFI_HELP_STR
11615 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11616 "Display the entries for all address families\n"
7b2ff250
DW
11617 "Display only routes with non-natural netmasks\n"
11618 "Display detailed information about dampening\n"
11619 "Display flap statistics of routes\n"
11620 "Display paths suppressed due to dampening\n"
11621 "Display routes matching the communities\n"
d0086e8e
AD
11622 COMMUNITY_AANN_STR
11623 "Do not send outside local AS (well-known community)\n"
11624 "Do not advertise to any peer (well-known community)\n"
11625 "Do not export to next AS (well-known community)\n"
11626 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
11627 "Do not export to any peer (well-known community)\n"
11628 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11629 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11630 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11631 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11632 "Should accept VPN route with local nexthop (well-known community)\n"
11633 "RT VPNv6 route filtering (well-known community)\n"
11634 "RT VPNv4 route filtering (well-known community)\n"
11635 "RT translated VPNv6 route filtering (well-known community)\n"
11636 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 11637 "Exact match of the communities\n"
ae248832
MK
11638 JSON_STR
11639 "Increase table width for longer prefixes\n")
7b2ff250
DW
11640{
11641 afi_t afi = AFI_IP6;
11642 safi_t safi = SAFI_UNICAST;
11643 enum bgp_show_type sh_type = bgp_show_type_normal;
11644 struct bgp *bgp = NULL;
11645 int idx = 0;
d0086e8e 11646 int exact_match = 0;
96f3485c
MK
11647 char *community = NULL;
11648 bool first = true;
11649 uint8_t show_flags = 0;
9f049418 11650
96f3485c
MK
11651
11652 if (uj) {
9f049418 11653 argc--;
96f3485c
MK
11654 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11655 }
11656
11657 /* [<ipv4|ipv6> [all]] */
11658 if (all) {
11659 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11660
11661 if (argv_find(argv, argc, "ipv4", &idx))
11662 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11663
11664 if (argv_find(argv, argc, "ipv6", &idx))
11665 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11666 }
11667
11668 if (wide)
11669 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
11670
11671 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11672 &bgp, uj);
7b2ff250
DW
11673 if (!idx)
11674 return CMD_WARNING;
11675
7b2ff250 11676 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 11677 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
11678
11679 if (argv_find(argv, argc, "dampening", &idx)) {
11680 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 11681 sh_type = bgp_show_type_dampend_paths;
7b2ff250 11682 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 11683 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
11684 }
11685
11686 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 11687 char *maybecomm = NULL;
d0086e8e 11688
79bc257a
RW
11689 if (idx + 1 < argc) {
11690 if (argv[idx + 1]->type == VARIABLE_TKN)
11691 maybecomm = argv[idx + 1]->arg;
11692 else
11693 maybecomm = argv[idx + 1]->text;
11694 }
11695
cf4898bc
QY
11696 if (maybecomm && !strmatch(maybecomm, "json")
11697 && !strmatch(maybecomm, "exact-match"))
11698 community = maybecomm;
d0086e8e 11699
cf4898bc
QY
11700 if (argv_find(argv, argc, "exact-match", &idx))
11701 exact_match = 1;
d0086e8e 11702
96f3485c
MK
11703 if (!community)
11704 sh_type = bgp_show_type_community_all;
11705 }
11706
11707 if (!all) {
11708 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
11709 if (community)
11710 return bgp_show_community(vty, bgp, community,
96f3485c
MK
11711 exact_match, afi, safi,
11712 show_flags);
cf4898bc 11713 else
96f3485c
MK
11714 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
11715 show_flags);
11716 } else {
11717 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
11718 * AFI_IP6 */
11719
11720 if (uj)
11721 vty_out(vty, "{\n");
11722
11723 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11724 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
11725 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11726 ? AFI_IP
11727 : AFI_IP6;
11728 FOREACH_SAFI (safi) {
11729 if (strmatch(get_afi_safi_str(afi, safi, true),
11730 "Unknown"))
11731 continue;
11732
11733 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11734 continue;
11735
11736 if (uj) {
11737 if (first)
11738 first = false;
11739 else
11740 vty_out(vty, ",\n");
11741 vty_out(vty, "\"%s\":{\n",
11742 get_afi_safi_str(afi, safi,
11743 true));
11744 } else
11745 vty_out(vty,
11746 "\nFor address family: %s\n",
11747 get_afi_safi_str(afi, safi,
11748 false));
11749
11750 if (community)
11751 bgp_show_community(vty, bgp, community,
11752 exact_match, afi,
11753 safi, show_flags);
11754 else
11755 bgp_show(vty, bgp, afi, safi, sh_type,
11756 NULL, show_flags);
11757 if (uj)
11758 vty_out(vty, "}\n");
11759 }
11760 } else {
11761 /* show <ip> bgp all: for each AFI and SAFI*/
11762 FOREACH_AFI_SAFI (afi, safi) {
11763 if (strmatch(get_afi_safi_str(afi, safi, true),
11764 "Unknown"))
11765 continue;
11766
11767 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11768 continue;
11769
11770 if (uj) {
11771 if (first)
11772 first = false;
11773 else
11774 vty_out(vty, ",\n");
d0086e8e 11775
96f3485c
MK
11776 vty_out(vty, "\"%s\":{\n",
11777 get_afi_safi_str(afi, safi,
11778 true));
11779 } else
11780 vty_out(vty,
11781 "\nFor address family: %s\n",
11782 get_afi_safi_str(afi, safi,
11783 false));
11784
11785 if (community)
11786 bgp_show_community(vty, bgp, community,
11787 exact_match, afi,
11788 safi, show_flags);
11789 else
11790 bgp_show(vty, bgp, afi, safi, sh_type,
11791 NULL, show_flags);
11792 if (uj)
11793 vty_out(vty, "}\n");
11794 }
11795 }
11796 if (uj)
11797 vty_out(vty, "}\n");
11798 }
11799 return CMD_SUCCESS;
a636c635 11800}
47fc97cc 11801
718e3744 11802DEFUN (show_ip_bgp_route,
11803 show_ip_bgp_route_cmd,
3efd0893 11804 "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 11805 SHOW_STR
11806 IP_STR
11807 BGP_STR
a636c635 11808 BGP_INSTANCE_HELP_STR
4f280b15 11809 BGP_AFI_HELP_STR
4dd6177e 11810 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 11811 "Network in the BGP routing table to display\n"
0c7b1b01 11812 "IPv4 prefix\n"
8c3deaae 11813 "Network in the BGP routing table to display\n"
0c7b1b01 11814 "IPv6 prefix\n"
4092b06c 11815 "Display only the bestpath\n"
b05a1c8b 11816 "Display only multipaths\n"
9973d184 11817 JSON_STR)
4092b06c 11818{
d62a17ae 11819 int prefix_check = 0;
ae19d7dd 11820
d62a17ae 11821 afi_t afi = AFI_IP6;
11822 safi_t safi = SAFI_UNICAST;
11823 char *prefix = NULL;
11824 struct bgp *bgp = NULL;
11825 enum bgp_path_type path_type;
9f049418 11826 bool uj = use_json(argc, argv);
b05a1c8b 11827
d62a17ae 11828 int idx = 0;
ae19d7dd 11829
d62a17ae 11830 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11831 &bgp, uj);
d62a17ae 11832 if (!idx)
11833 return CMD_WARNING;
c41247f5 11834
d62a17ae 11835 if (!bgp) {
11836 vty_out(vty,
11837 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
11838 return CMD_WARNING;
11839 }
a636c635 11840
d62a17ae 11841 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
11842 if (argv_find(argv, argc, "A.B.C.D", &idx)
11843 || argv_find(argv, argc, "X:X::X:X", &idx))
11844 prefix_check = 0;
11845 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11846 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11847 prefix_check = 1;
11848
11849 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
11850 && afi != AFI_IP6) {
11851 vty_out(vty,
11852 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
11853 return CMD_WARNING;
11854 }
11855 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
11856 && afi != AFI_IP) {
11857 vty_out(vty,
11858 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
11859 return CMD_WARNING;
11860 }
11861
11862 prefix = argv[idx]->arg;
11863
11864 /* [<bestpath|multipath>] */
11865 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 11866 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 11867 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 11868 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 11869 else
360660c6 11870 path_type = BGP_PATH_SHOW_ALL;
a636c635 11871
d62a17ae 11872 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
11873 path_type, uj);
4092b06c
DS
11874}
11875
8c3deaae
QY
11876DEFUN (show_ip_bgp_regexp,
11877 show_ip_bgp_regexp_cmd,
3e5b31b3 11878 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
11879 SHOW_STR
11880 IP_STR
11881 BGP_STR
b00b230a 11882 BGP_INSTANCE_HELP_STR
4f280b15 11883 BGP_AFI_HELP_STR
4dd6177e 11884 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 11885 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
11886 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
11887 JSON_STR)
8c3deaae 11888{
d62a17ae 11889 afi_t afi = AFI_IP6;
11890 safi_t safi = SAFI_UNICAST;
11891 struct bgp *bgp = NULL;
3e5b31b3
DA
11892 bool uj = use_json(argc, argv);
11893 char *regstr = NULL;
8c3deaae 11894
d62a17ae 11895 int idx = 0;
11896 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11897 &bgp, false);
d62a17ae 11898 if (!idx)
11899 return CMD_WARNING;
8c3deaae 11900
d62a17ae 11901 // get index of regex
3e5b31b3
DA
11902 if (argv_find(argv, argc, "REGEX", &idx))
11903 regstr = argv[idx]->arg;
8c3deaae 11904
5f71d11c 11905 assert(regstr);
3e5b31b3
DA
11906 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
11907 bgp_show_type_regexp, uj);
8c3deaae
QY
11908}
11909
ae248832 11910DEFPY (show_ip_bgp_instance_all,
a636c635 11911 show_ip_bgp_instance_all_cmd,
ae248832 11912 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 11913 SHOW_STR
a636c635 11914 IP_STR
4092b06c 11915 BGP_STR
a636c635 11916 BGP_INSTANCE_ALL_HELP_STR
4f280b15 11917 BGP_AFI_HELP_STR
4dd6177e 11918 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
11919 JSON_STR
11920 "Increase table width for longer prefixes\n")
4092b06c 11921{
d62a17ae 11922 afi_t afi = AFI_IP;
11923 safi_t safi = SAFI_UNICAST;
11924 struct bgp *bgp = NULL;
d62a17ae 11925 int idx = 0;
96f3485c 11926 uint8_t show_flags = 0;
ae19d7dd 11927
96f3485c 11928 if (uj) {
d62a17ae 11929 argc--;
96f3485c
MK
11930 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11931 }
11932
11933 if (wide)
11934 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 11935
9f049418
DS
11936 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11937 &bgp, uj);
11938 if (!idx)
11939 return CMD_WARNING;
11940
96f3485c 11941 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 11942 return CMD_SUCCESS;
e3e29b32
LB
11943}
11944
a4d82a8a 11945static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11946 afi_t afi, safi_t safi, enum bgp_show_type type,
11947 bool use_json)
718e3744 11948{
d62a17ae 11949 regex_t *regex;
11950 int rc;
96f3485c
MK
11951 uint8_t show_flags = 0;
11952
11953 if (use_json)
11954 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 11955
c3900853 11956 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 11957 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
11958 regstr);
11959 return CMD_WARNING_CONFIG_FAILED;
11960 }
11961
d62a17ae 11962 regex = bgp_regcomp(regstr);
11963 if (!regex) {
11964 vty_out(vty, "Can't compile regexp %s\n", regstr);
11965 return CMD_WARNING;
11966 }
a636c635 11967
96f3485c 11968 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags);
d62a17ae 11969 bgp_regex_free(regex);
11970 return rc;
e3e29b32
LB
11971}
11972
d62a17ae 11973static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
11974 const char *prefix_list_str, afi_t afi,
11975 safi_t safi, enum bgp_show_type type)
e3e29b32 11976{
d62a17ae 11977 struct prefix_list *plist;
96f3485c 11978 uint8_t show_flags = 0;
718e3744 11979
d62a17ae 11980 plist = prefix_list_lookup(afi, prefix_list_str);
11981 if (plist == NULL) {
11982 vty_out(vty, "%% %s is not a valid prefix-list name\n",
11983 prefix_list_str);
11984 return CMD_WARNING;
11985 }
718e3744 11986
96f3485c 11987 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags);
4092b06c
DS
11988}
11989
d62a17ae 11990static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
11991 const char *filter, afi_t afi, safi_t safi,
11992 enum bgp_show_type type)
4092b06c 11993{
d62a17ae 11994 struct as_list *as_list;
96f3485c 11995 uint8_t show_flags = 0;
718e3744 11996
d62a17ae 11997 as_list = as_list_lookup(filter);
11998 if (as_list == NULL) {
11999 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
12000 filter);
12001 return CMD_WARNING;
12002 }
a636c635 12003
96f3485c 12004 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags);
718e3744 12005}
12006
d62a17ae 12007static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
12008 const char *rmap_str, afi_t afi, safi_t safi,
12009 enum bgp_show_type type)
718e3744 12010{
d62a17ae 12011 struct route_map *rmap;
96f3485c 12012 uint8_t show_flags = 0;
bb46e94f 12013
d62a17ae 12014 rmap = route_map_lookup_by_name(rmap_str);
12015 if (!rmap) {
12016 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
12017 return CMD_WARNING;
12018 }
12019
96f3485c 12020 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags);
d62a17ae 12021}
12022
7f323236
DW
12023static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12024 const char *comstr, int exact, afi_t afi,
96f3485c 12025 safi_t safi, uint8_t show_flags)
d62a17ae 12026{
12027 struct community *com;
d62a17ae 12028 int ret = 0;
12029
7f323236 12030 com = community_str2com(comstr);
d62a17ae 12031 if (!com) {
7f323236 12032 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12033 return CMD_WARNING;
12034 }
12035
12036 ret = bgp_show(vty, bgp, afi, safi,
12037 (exact ? bgp_show_type_community_exact
12038 : bgp_show_type_community),
96f3485c 12039 com, show_flags);
3c1f53de 12040 community_free(&com);
46c3ce83 12041
d62a17ae 12042 return ret;
718e3744 12043}
12044
d62a17ae 12045static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
12046 const char *com, int exact, afi_t afi,
12047 safi_t safi)
50ef26d4 12048{
d62a17ae 12049 struct community_list *list;
96f3485c 12050 uint8_t show_flags = 0;
50ef26d4 12051
e237b0d2 12052 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 12053 if (list == NULL) {
12054 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12055 return CMD_WARNING;
12056 }
718e3744 12057
d62a17ae 12058 return bgp_show(vty, bgp, afi, safi,
12059 (exact ? bgp_show_type_community_list_exact
12060 : bgp_show_type_community_list),
96f3485c 12061 list, show_flags);
50ef26d4 12062}
12063
d62a17ae 12064static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12065 const char *prefix, afi_t afi, safi_t safi,
12066 enum bgp_show_type type)
718e3744 12067{
d62a17ae 12068 int ret;
12069 struct prefix *p;
96f3485c 12070 uint8_t show_flags = 0;
47fc97cc 12071
d62a17ae 12072 p = prefix_new();
95cbbd2a 12073
d62a17ae 12074 ret = str2prefix(prefix, p);
12075 if (!ret) {
12076 vty_out(vty, "%% Malformed Prefix\n");
12077 return CMD_WARNING;
12078 }
47e9b292 12079
96f3485c 12080 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags);
63265b5c 12081 prefix_free(&p);
d62a17ae 12082 return ret;
12083}
12084
d62a17ae 12085enum bgp_stats {
12086 BGP_STATS_MAXBITLEN = 0,
12087 BGP_STATS_RIB,
12088 BGP_STATS_PREFIXES,
12089 BGP_STATS_TOTPLEN,
12090 BGP_STATS_UNAGGREGATEABLE,
12091 BGP_STATS_MAX_AGGREGATEABLE,
12092 BGP_STATS_AGGREGATES,
12093 BGP_STATS_SPACE,
12094 BGP_STATS_ASPATH_COUNT,
12095 BGP_STATS_ASPATH_MAXHOPS,
12096 BGP_STATS_ASPATH_TOTHOPS,
12097 BGP_STATS_ASPATH_MAXSIZE,
12098 BGP_STATS_ASPATH_TOTSIZE,
12099 BGP_STATS_ASN_HIGHEST,
12100 BGP_STATS_MAX,
a636c635 12101};
2815e61f 12102
9ab0cf58 12103#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12104#define TABLE_STATS_IDX_JSON 1
12105
12106static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12107 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12108 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12109 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12110 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12111 "unaggregateablePrefixes"},
12112 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12113 "maximumAggregateablePrefixes"},
12114 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12115 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12116 [BGP_STATS_SPACE] = {"Address space advertised",
12117 "addressSpaceAdvertised"},
9ab0cf58
PG
12118 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12119 "advertisementsWithPaths"},
12120 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12121 "longestAsPath"},
12122 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12123 "largestAsPath"},
12124 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12125 "averageAsPathLengthHops"},
12126 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12127 "averageAsPathSizeBytes"},
12128 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12129 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12130};
2815e61f 12131
d62a17ae 12132struct bgp_table_stats {
12133 struct bgp_table *table;
12134 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12135 double total_space;
ff7924f6
PJ
12136};
12137
a636c635
DW
12138#if 0
12139#define TALLY_SIGFIG 100000
12140static unsigned long
12141ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 12142{
a636c635
DW
12143 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
12144 unsigned long res = (newtot * TALLY_SIGFIG) / count;
12145 unsigned long ret = newtot / count;
07d0c4ed 12146
a636c635
DW
12147 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
12148 return ret + 1;
12149 else
12150 return ret;
12151}
12152#endif
ff7924f6 12153
9bcb3eef 12154static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12155 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12156{
9bcb3eef 12157 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12158 struct bgp_path_info *pi;
b54892e0 12159 const struct prefix *rn_p;
d62a17ae 12160
9bcb3eef 12161 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12162 return;
d62a17ae 12163
9bcb3eef 12164 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12165 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12166 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12167
a636c635
DW
12168#if 0
12169 ts->counts[BGP_STATS_AVGPLEN]
12170 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
12171 ts->counts[BGP_STATS_AVGPLEN],
b54892e0 12172 rn_p->prefixlen);
a636c635 12173#endif
d62a17ae 12174
9c14ec72 12175 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12176 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12177 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12178
9bcb3eef 12179 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12180 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12181 /* announced address space */
12182 if (space)
b54892e0 12183 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12184 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12185 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12186
9c14ec72 12187
9bcb3eef 12188 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12189 ts->counts[BGP_STATS_RIB]++;
12190
05864da7
DS
12191 if (CHECK_FLAG(pi->attr->flag,
12192 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12193 ts->counts[BGP_STATS_AGGREGATES]++;
12194
12195 /* as-path stats */
05864da7 12196 if (pi->attr->aspath) {
9c14ec72
RW
12197 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12198 unsigned int size = aspath_size(pi->attr->aspath);
12199 as_t highest = aspath_highest(pi->attr->aspath);
12200
12201 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12202
12203 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12204 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12205
12206 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12207 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12208
12209 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12210 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 12211#if 0
07d0c4ed 12212 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
12213 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
12214 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
12215 hops);
12216 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
12217 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
12218 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
12219 size);
12220#endif
9c14ec72
RW
12221 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12222 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12223 }
12224 }
12225}
12226
12227static int bgp_table_stats_walker(struct thread *t)
12228{
9bcb3eef
DS
12229 struct bgp_dest *dest, *ndest;
12230 struct bgp_dest *top;
9c14ec72
RW
12231 struct bgp_table_stats *ts = THREAD_ARG(t);
12232 unsigned int space = 0;
12233
12234 if (!(top = bgp_table_top(ts->table)))
12235 return 0;
12236
12237 switch (ts->table->afi) {
12238 case AFI_IP:
12239 space = IPV4_MAX_BITLEN;
12240 break;
12241 case AFI_IP6:
12242 space = IPV6_MAX_BITLEN;
12243 break;
12244 default:
12245 return 0;
12246 }
12247
12248 ts->counts[BGP_STATS_MAXBITLEN] = space;
12249
9bcb3eef 12250 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12251 if (ts->table->safi == SAFI_MPLS_VPN
12252 || ts->table->safi == SAFI_ENCAP
12253 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12254 struct bgp_table *table;
12255
9bcb3eef 12256 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12257 if (!table)
12258 continue;
12259
12260 top = bgp_table_top(table);
9bcb3eef
DS
12261 for (ndest = bgp_table_top(table); ndest;
12262 ndest = bgp_route_next(ndest))
12263 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12264 } else {
9bcb3eef 12265 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12266 }
12267 }
9c14ec72 12268
d62a17ae 12269 return 0;
2815e61f 12270}
ff7924f6 12271
71f1613a
DA
12272static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12273 struct json_object *json_array)
12274{
12275 struct listnode *node, *nnode;
12276 struct bgp *bgp;
12277
12278 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12279 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12280}
12281
12282static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12283 safi_t safi, struct json_object *json_array)
2815e61f 12284{
d62a17ae 12285 struct bgp_table_stats ts;
12286 unsigned int i;
893cccd0
PG
12287 int ret = CMD_SUCCESS;
12288 char temp_buf[20];
6c9d22e2
PG
12289 struct json_object *json = NULL;
12290
12291 if (json_array)
12292 json = json_object_new_object();
019386c2 12293
d62a17ae 12294 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12295 char warning_msg[50];
12296
12297 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12298 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12299 safi);
6c9d22e2
PG
12300
12301 if (!json)
893cccd0
PG
12302 vty_out(vty, "%s\n", warning_msg);
12303 else
9ab0cf58 12304 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12305
893cccd0
PG
12306 ret = CMD_WARNING;
12307 goto end_table_stats;
d62a17ae 12308 }
019386c2 12309
893cccd0 12310 if (!json)
5290ceab
DA
12311 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12312 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12313 else
12314 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12315
d62a17ae 12316 /* labeled-unicast routes live in the unicast table */
12317 if (safi == SAFI_LABELED_UNICAST)
12318 safi = SAFI_UNICAST;
019386c2 12319
d62a17ae 12320 memset(&ts, 0, sizeof(ts));
12321 ts.table = bgp->rib[afi][safi];
12322 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12323
d62a17ae 12324 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12325 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12326 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12327 continue;
12328
12329 switch (i) {
a636c635
DW
12330#if 0
12331 case BGP_STATS_ASPATH_AVGHOPS:
12332 case BGP_STATS_ASPATH_AVGSIZE:
12333 case BGP_STATS_AVGPLEN:
12334 vty_out (vty, "%-30s: ", table_stats_strs[i]);
12335 vty_out (vty, "%12.2f",
12336 (float)ts.counts[i] / (float)TALLY_SIGFIG);
12337 break;
12338#endif
d62a17ae 12339 case BGP_STATS_ASPATH_TOTHOPS:
12340 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12341 if (!json) {
9ab0cf58
PG
12342 snprintf(
12343 temp_buf, sizeof(temp_buf), "%12.2f",
12344 ts.counts[i]
12345 ? (float)ts.counts[i]
12346 / (float)ts.counts
12347 [BGP_STATS_ASPATH_COUNT]
12348 : 0);
893cccd0 12349 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12350 table_stats_strs[i]
12351 [TABLE_STATS_IDX_VTY],
893cccd0 12352 temp_buf);
9ab0cf58
PG
12353 } else {
12354 json_object_double_add(
12355 json,
12356 table_stats_strs[i]
12357 [TABLE_STATS_IDX_JSON],
12358 ts.counts[i]
12359 ? (double)ts.counts[i]
12360 / (double)ts.counts
d62a17ae 12361 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12362 : 0);
12363 }
d62a17ae 12364 break;
12365 case BGP_STATS_TOTPLEN:
6c9d22e2 12366 if (!json) {
9ab0cf58
PG
12367 snprintf(
12368 temp_buf, sizeof(temp_buf), "%12.2f",
12369 ts.counts[i]
12370 ? (float)ts.counts[i]
12371 / (float)ts.counts
12372 [BGP_STATS_PREFIXES]
12373 : 0);
893cccd0 12374 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12375 table_stats_strs[i]
12376 [TABLE_STATS_IDX_VTY],
893cccd0 12377 temp_buf);
9ab0cf58
PG
12378 } else {
12379 json_object_double_add(
12380 json,
12381 table_stats_strs[i]
12382 [TABLE_STATS_IDX_JSON],
12383 ts.counts[i]
12384 ? (double)ts.counts[i]
12385 / (double)ts.counts
d62a17ae 12386 [BGP_STATS_PREFIXES]
9ab0cf58
PG
12387 : 0);
12388 }
d62a17ae 12389 break;
12390 case BGP_STATS_SPACE:
6c9d22e2
PG
12391 if (!json) {
12392 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12393 ts.total_space);
893cccd0 12394 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
12395 table_stats_strs[i]
12396 [TABLE_STATS_IDX_VTY],
893cccd0 12397 temp_buf);
9ab0cf58
PG
12398 } else {
12399 json_object_double_add(
12400 json,
12401 table_stats_strs[i]
12402 [TABLE_STATS_IDX_JSON],
12403 (double)ts.total_space);
12404 }
8d0ab76d 12405 if (afi == AFI_IP6) {
6c9d22e2
PG
12406 if (!json) {
12407 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12408 "%12g",
12409 ts.total_space
12410 * pow(2.0, -128 + 32));
6c9d22e2
PG
12411 vty_out(vty, "%30s: %s\n",
12412 "/32 equivalent %s\n",
12413 temp_buf);
9ab0cf58
PG
12414 } else {
12415 json_object_double_add(
12416 json, "/32equivalent",
12417 (double)(ts.total_space
12418 * pow(2.0,
12419 -128 + 32)));
12420 }
6c9d22e2
PG
12421 if (!json) {
12422 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12423 "%12g",
12424 ts.total_space
12425 * pow(2.0, -128 + 48));
6c9d22e2
PG
12426 vty_out(vty, "%30s: %s\n",
12427 "/48 equivalent %s\n",
12428 temp_buf);
9ab0cf58
PG
12429 } else {
12430 json_object_double_add(
12431 json, "/48equivalent",
12432 (double)(ts.total_space
12433 * pow(2.0,
12434 -128 + 48)));
12435 }
8d0ab76d 12436 } else {
6c9d22e2
PG
12437 if (!json) {
12438 snprintf(temp_buf, sizeof(temp_buf),
12439 "%12.2f",
9ab0cf58
PG
12440 ts.total_space * 100.
12441 * pow(2.0, -32));
6c9d22e2 12442 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12443 "% announced ", temp_buf);
12444 } else {
12445 json_object_double_add(
12446 json, "%announced",
12447 (double)(ts.total_space * 100.
12448 * pow(2.0, -32)));
12449 }
6c9d22e2
PG
12450 if (!json) {
12451 snprintf(temp_buf, sizeof(temp_buf),
12452 "%12.2f",
9ab0cf58
PG
12453 ts.total_space
12454 * pow(2.0, -32 + 8));
6c9d22e2
PG
12455 vty_out(vty, "%30s: %s\n",
12456 "/8 equivalent ", temp_buf);
9ab0cf58
PG
12457 } else {
12458 json_object_double_add(
12459 json, "/8equivalent",
12460 (double)(ts.total_space
12461 * pow(2.0, -32 + 8)));
12462 }
6c9d22e2
PG
12463 if (!json) {
12464 snprintf(temp_buf, sizeof(temp_buf),
12465 "%12.2f",
9ab0cf58
PG
12466 ts.total_space
12467 * pow(2.0, -32 + 24));
6c9d22e2 12468 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12469 "/24 equivalent ", temp_buf);
12470 } else {
12471 json_object_double_add(
12472 json, "/24equivalent",
12473 (double)(ts.total_space
12474 * pow(2.0, -32 + 24)));
12475 }
8d0ab76d 12476 }
d62a17ae 12477 break;
12478 default:
6c9d22e2
PG
12479 if (!json) {
12480 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
12481 ts.counts[i]);
893cccd0 12482 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12483 table_stats_strs[i]
12484 [TABLE_STATS_IDX_VTY],
12485 temp_buf);
12486 } else {
12487 json_object_int_add(
12488 json,
12489 table_stats_strs[i]
12490 [TABLE_STATS_IDX_JSON],
12491 ts.counts[i]);
12492 }
d62a17ae 12493 }
893cccd0
PG
12494 if (!json)
12495 vty_out(vty, "\n");
d62a17ae 12496 }
9ab0cf58 12497end_table_stats:
6c9d22e2
PG
12498 if (json)
12499 json_object_array_add(json_array, json);
893cccd0 12500 return ret;
d62a17ae 12501}
12502
71f1613a
DA
12503static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
12504 safi_t safi, struct json_object *json_array)
12505{
12506 if (!bgp) {
12507 bgp_table_stats_all(vty, afi, safi, json_array);
12508 return CMD_SUCCESS;
12509 }
12510
12511 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12512}
12513
d62a17ae 12514enum bgp_pcounts {
12515 PCOUNT_ADJ_IN = 0,
12516 PCOUNT_DAMPED,
12517 PCOUNT_REMOVED,
12518 PCOUNT_HISTORY,
12519 PCOUNT_STALE,
12520 PCOUNT_VALID,
12521 PCOUNT_ALL,
12522 PCOUNT_COUNTED,
7e3d9632 12523 PCOUNT_BPATH_SELECTED,
d62a17ae 12524 PCOUNT_PFCNT, /* the figure we display to users */
12525 PCOUNT_MAX,
a636c635 12526};
718e3744 12527
2b64873d 12528static const char *const pcount_strs[] = {
9d303b37
DL
12529 [PCOUNT_ADJ_IN] = "Adj-in",
12530 [PCOUNT_DAMPED] = "Damped",
12531 [PCOUNT_REMOVED] = "Removed",
12532 [PCOUNT_HISTORY] = "History",
12533 [PCOUNT_STALE] = "Stale",
12534 [PCOUNT_VALID] = "Valid",
12535 [PCOUNT_ALL] = "All RIB",
12536 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 12537 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
12538 [PCOUNT_PFCNT] = "Useable",
12539 [PCOUNT_MAX] = NULL,
a636c635 12540};
718e3744 12541
d62a17ae 12542struct peer_pcounts {
12543 unsigned int count[PCOUNT_MAX];
12544 const struct peer *peer;
12545 const struct bgp_table *table;
54317cba 12546 safi_t safi;
a636c635 12547};
47fc97cc 12548
9bcb3eef 12549static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 12550{
54317cba
JW
12551 const struct bgp_adj_in *ain;
12552 const struct bgp_path_info *pi;
d62a17ae 12553 const struct peer *peer = pc->peer;
12554
54317cba
JW
12555 for (ain = rn->adj_in; ain; ain = ain->next)
12556 if (ain->peer == peer)
12557 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 12558
9bcb3eef 12559 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 12560
54317cba
JW
12561 if (pi->peer != peer)
12562 continue;
d62a17ae 12563
54317cba 12564 pc->count[PCOUNT_ALL]++;
d62a17ae 12565
54317cba
JW
12566 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
12567 pc->count[PCOUNT_DAMPED]++;
12568 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
12569 pc->count[PCOUNT_HISTORY]++;
12570 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
12571 pc->count[PCOUNT_REMOVED]++;
12572 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
12573 pc->count[PCOUNT_STALE]++;
12574 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
12575 pc->count[PCOUNT_VALID]++;
12576 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12577 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
12578 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12579 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
12580
12581 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
12582 pc->count[PCOUNT_COUNTED]++;
12583 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12584 flog_err(
12585 EC_LIB_DEVELOPMENT,
12586 "Attempting to count but flags say it is unusable");
12587 } else {
40381db7 12588 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
12589 flog_err(
12590 EC_LIB_DEVELOPMENT,
12591 "Not counted but flags say we should");
d62a17ae 12592 }
12593 }
54317cba
JW
12594}
12595
12596static int bgp_peer_count_walker(struct thread *t)
12597{
9bcb3eef 12598 struct bgp_dest *rn, *rm;
54317cba
JW
12599 const struct bgp_table *table;
12600 struct peer_pcounts *pc = THREAD_ARG(t);
12601
12602 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
12603 || pc->safi == SAFI_EVPN) {
12604 /* Special handling for 2-level routing tables. */
12605 for (rn = bgp_table_top(pc->table); rn;
12606 rn = bgp_route_next(rn)) {
9bcb3eef 12607 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
12608 if (table != NULL)
12609 for (rm = bgp_table_top(table); rm;
12610 rm = bgp_route_next(rm))
12611 bgp_peer_count_proc(rm, pc);
12612 }
12613 } else
12614 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
12615 bgp_peer_count_proc(rn, pc);
12616
d62a17ae 12617 return 0;
718e3744 12618}
12619
d62a17ae 12620static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 12621 safi_t safi, bool use_json)
856ca177 12622{
d62a17ae 12623 struct peer_pcounts pcounts = {.peer = peer};
12624 unsigned int i;
12625 json_object *json = NULL;
12626 json_object *json_loop = NULL;
856ca177 12627
d62a17ae 12628 if (use_json) {
12629 json = json_object_new_object();
12630 json_loop = json_object_new_object();
12631 }
718e3744 12632
d62a17ae 12633 if (!peer || !peer->bgp || !peer->afc[afi][safi]
12634 || !peer->bgp->rib[afi][safi]) {
12635 if (use_json) {
12636 json_object_string_add(
12637 json, "warning",
12638 "No such neighbor or address family");
12639 vty_out(vty, "%s\n", json_object_to_json_string(json));
12640 json_object_free(json);
12641 } else
12642 vty_out(vty, "%% No such neighbor or address family\n");
12643
12644 return CMD_WARNING;
12645 }
2a71e9ce 12646
d62a17ae 12647 memset(&pcounts, 0, sizeof(pcounts));
12648 pcounts.peer = peer;
12649 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 12650 pcounts.safi = safi;
d62a17ae 12651
12652 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
12653 * stats for the thread-walk (i.e. ensure this can't be blamed on
12654 * on just vty_read()).
12655 */
d62a17ae 12656 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
12657
12658 if (use_json) {
12659 json_object_string_add(json, "prefixCountsFor", peer->host);
12660 json_object_string_add(json, "multiProtocol",
5cb5f4d0 12661 get_afi_safi_str(afi, safi, true));
d62a17ae 12662 json_object_int_add(json, "pfxCounter",
12663 peer->pcount[afi][safi]);
12664
12665 for (i = 0; i < PCOUNT_MAX; i++)
12666 json_object_int_add(json_loop, pcount_strs[i],
12667 pcounts.count[i]);
12668
12669 json_object_object_add(json, "ribTableWalkCounters", json_loop);
12670
12671 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12672 json_object_string_add(json, "pfxctDriftFor",
12673 peer->host);
12674 json_object_string_add(
12675 json, "recommended",
12676 "Please report this bug, with the above command output");
12677 }
996c9314
LB
12678 vty_out(vty, "%s\n", json_object_to_json_string_ext(
12679 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 12680 json_object_free(json);
12681 } else {
12682
12683 if (peer->hostname
892fedb6 12684 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 12685 vty_out(vty, "Prefix counts for %s/%s, %s\n",
12686 peer->hostname, peer->host,
5cb5f4d0 12687 get_afi_safi_str(afi, safi, false));
d62a17ae 12688 } else {
12689 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 12690 get_afi_safi_str(afi, safi, false));
d62a17ae 12691 }
12692
6cde4b45 12693 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 12694 vty_out(vty, "\nCounts from RIB table walk:\n\n");
12695
12696 for (i = 0; i < PCOUNT_MAX; i++)
12697 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
12698 pcounts.count[i]);
12699
12700 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12701 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
12702 vty_out(vty,
12703 "Please report this bug, with the above command output\n");
12704 }
12705 }
12706
12707 return CMD_SUCCESS;
718e3744 12708}
12709
a636c635
DW
12710DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
12711 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 12712 "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 12713 SHOW_STR
12714 IP_STR
12715 BGP_STR
8386ac43 12716 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
12717 BGP_AFI_HELP_STR
12718 BGP_SAFI_HELP_STR
0b16f239
DS
12719 "Detailed information on TCP and BGP neighbor connections\n"
12720 "Neighbor to display information about\n"
12721 "Neighbor to display information about\n"
91d37724 12722 "Neighbor on BGP configured interface\n"
a636c635 12723 "Display detailed prefix count information\n"
9973d184 12724 JSON_STR)
0b16f239 12725{
d62a17ae 12726 afi_t afi = AFI_IP6;
12727 safi_t safi = SAFI_UNICAST;
12728 struct peer *peer;
12729 int idx = 0;
12730 struct bgp *bgp = NULL;
9f049418
DS
12731 bool uj = use_json(argc, argv);
12732
12733 if (uj)
12734 argc--;
856ca177 12735
d62a17ae 12736 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12737 &bgp, uj);
d62a17ae 12738 if (!idx)
12739 return CMD_WARNING;
0b16f239 12740
d62a17ae 12741 argv_find(argv, argc, "neighbors", &idx);
12742 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
12743 if (!peer)
12744 return CMD_WARNING;
bb46e94f 12745
29c8d9da 12746 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 12747}
0b16f239 12748
d6902373
PG
12749#ifdef KEEP_OLD_VPN_COMMANDS
12750DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
12751 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
12752 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
12753 SHOW_STR
12754 IP_STR
12755 BGP_STR
d6902373 12756 BGP_VPNVX_HELP_STR
91d37724 12757 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
12758 "Detailed information on TCP and BGP neighbor connections\n"
12759 "Neighbor to display information about\n"
12760 "Neighbor to display information about\n"
91d37724 12761 "Neighbor on BGP configured interface\n"
a636c635 12762 "Display detailed prefix count information\n"
9973d184 12763 JSON_STR)
a636c635 12764{
d62a17ae 12765 int idx_peer = 6;
12766 struct peer *peer;
9f049418 12767 bool uj = use_json(argc, argv);
a636c635 12768
d62a17ae 12769 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
12770 if (!peer)
12771 return CMD_WARNING;
12772
12773 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
12774}
12775
d6902373
PG
12776DEFUN (show_ip_bgp_vpn_all_route_prefix,
12777 show_ip_bgp_vpn_all_route_prefix_cmd,
12778 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
12779 SHOW_STR
12780 IP_STR
12781 BGP_STR
d6902373 12782 BGP_VPNVX_HELP_STR
91d37724
QY
12783 "Display information about all VPNv4 NLRIs\n"
12784 "Network in the BGP routing table to display\n"
3a2d747c 12785 "Network in the BGP routing table to display\n"
9973d184 12786 JSON_STR)
91d37724 12787{
d62a17ae 12788 int idx = 0;
12789 char *network = NULL;
12790 struct bgp *bgp = bgp_get_default();
12791 if (!bgp) {
12792 vty_out(vty, "Can't find default instance\n");
12793 return CMD_WARNING;
12794 }
87e34b58 12795
d62a17ae 12796 if (argv_find(argv, argc, "A.B.C.D", &idx))
12797 network = argv[idx]->arg;
12798 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
12799 network = argv[idx]->arg;
12800 else {
12801 vty_out(vty, "Unable to figure out Network\n");
12802 return CMD_WARNING;
12803 }
87e34b58 12804
d62a17ae 12805 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 12806 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 12807}
d6902373 12808#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 12809
44c69747
LK
12810DEFUN (show_bgp_l2vpn_evpn_route_prefix,
12811 show_bgp_l2vpn_evpn_route_prefix_cmd,
12812 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 12813 SHOW_STR
4c63a661
PG
12814 BGP_STR
12815 L2VPN_HELP_STR
12816 EVPN_HELP_STR
44c69747
LK
12817 "Network in the BGP routing table to display\n"
12818 "Network in the BGP routing table to display\n"
4c63a661
PG
12819 "Network in the BGP routing table to display\n"
12820 "Network in the BGP routing table to display\n"
12821 JSON_STR)
12822{
d62a17ae 12823 int idx = 0;
12824 char *network = NULL;
44c69747 12825 int prefix_check = 0;
a636c635 12826
44c69747
LK
12827 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
12828 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 12829 network = argv[idx]->arg;
44c69747 12830 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 12831 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 12832 network = argv[idx]->arg;
44c69747
LK
12833 prefix_check = 1;
12834 } else {
d62a17ae 12835 vty_out(vty, "Unable to figure out Network\n");
12836 return CMD_WARNING;
12837 }
44c69747
LK
12838 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
12839 prefix_check, BGP_PATH_SHOW_ALL,
12840 use_json(argc, argv));
d62a17ae 12841}
12842
2f9bc755
DS
12843static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
12844 struct bgp_table *table, int *header1,
12845 int *header2, json_object *json,
12846 json_object *json_scode,
12847 json_object *json_ocode, bool wide)
12848{
12849 uint64_t version = table ? table->version : 0;
23d0a753 12850 char buf[BUFSIZ] = {0};
2f9bc755
DS
12851
12852 if (*header1) {
12853 if (json) {
12854 json_object_int_add(json, "bgpTableVersion", version);
12855 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
12856 inet_ntop(AF_INET,
12857 &bgp->router_id, buf,
12858 sizeof(buf)));
2f9bc755
DS
12859 json_object_int_add(json, "defaultLocPrf",
12860 bgp->default_local_pref);
12861 json_object_int_add(json, "localAS", bgp->as);
12862 json_object_object_add(json, "bgpStatusCodes",
12863 json_scode);
12864 json_object_object_add(json, "bgpOriginCodes",
12865 json_ocode);
12866 } else {
12867 vty_out(vty,
23d0a753
DA
12868 "BGP table version is %" PRIu64
12869 ", local router ID is %pI4, vrf id ",
12870 version, &bgp->router_id);
2f9bc755
DS
12871 if (bgp->vrf_id == VRF_UNKNOWN)
12872 vty_out(vty, "%s", VRFID_NONE_STR);
12873 else
12874 vty_out(vty, "%u", bgp->vrf_id);
12875 vty_out(vty, "\n");
12876 vty_out(vty, "Default local pref %u, ",
12877 bgp->default_local_pref);
12878 vty_out(vty, "local AS %u\n", bgp->as);
12879 vty_out(vty, BGP_SHOW_SCODE_HEADER);
12880 vty_out(vty, BGP_SHOW_NCODE_HEADER);
12881 vty_out(vty, BGP_SHOW_OCODE_HEADER);
12882 }
12883 *header1 = 0;
12884 }
12885 if (*header2) {
12886 if (!json)
12887 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
12888 : BGP_SHOW_HEADER));
12889 *header2 = 0;
12890 }
12891}
12892
d62a17ae 12893static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 12894 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c
MK
12895 const char *rmap_name, json_object *json,
12896 uint8_t show_flags)
d62a17ae 12897{
12898 struct bgp_table *table;
12899 struct bgp_adj_in *ain;
12900 struct bgp_adj_out *adj;
74a630b6
NT
12901 unsigned long output_count = 0;
12902 unsigned long filtered_count = 0;
9bcb3eef 12903 struct bgp_dest *dest;
d62a17ae 12904 int header1 = 1;
12905 struct bgp *bgp;
12906 int header2 = 1;
12907 struct attr attr;
12908 int ret;
12909 struct update_subgroup *subgrp;
12910 json_object *json_scode = NULL;
12911 json_object *json_ocode = NULL;
12912 json_object *json_ar = NULL;
12913 struct peer_af *paf;
f99def61 12914 bool route_filtered;
96f3485c
MK
12915 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12916 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d62a17ae 12917
12918 if (use_json) {
12919 json_scode = json_object_new_object();
12920 json_ocode = json_object_new_object();
12921 json_ar = json_object_new_object();
12922
12923 json_object_string_add(json_scode, "suppressed", "s");
12924 json_object_string_add(json_scode, "damped", "d");
12925 json_object_string_add(json_scode, "history", "h");
12926 json_object_string_add(json_scode, "valid", "*");
12927 json_object_string_add(json_scode, "best", ">");
12928 json_object_string_add(json_scode, "multipath", "=");
12929 json_object_string_add(json_scode, "internal", "i");
12930 json_object_string_add(json_scode, "ribFailure", "r");
12931 json_object_string_add(json_scode, "stale", "S");
12932 json_object_string_add(json_scode, "removed", "R");
12933
12934 json_object_string_add(json_ocode, "igp", "i");
12935 json_object_string_add(json_ocode, "egp", "e");
12936 json_object_string_add(json_ocode, "incomplete", "?");
12937 }
a636c635 12938
d62a17ae 12939 bgp = peer->bgp;
a636c635 12940
d62a17ae 12941 if (!bgp) {
12942 if (use_json) {
12943 json_object_string_add(json, "alert", "no BGP");
12944 vty_out(vty, "%s\n", json_object_to_json_string(json));
12945 json_object_free(json);
12946 } else
12947 vty_out(vty, "%% No bgp\n");
12948 return;
12949 }
a636c635 12950
c512a642
EDP
12951 /* labeled-unicast routes live in the unicast table */
12952 if (safi == SAFI_LABELED_UNICAST)
12953 table = bgp->rib[afi][SAFI_UNICAST];
12954 else
12955 table = bgp->rib[afi][safi];
d62a17ae 12956
12957 output_count = filtered_count = 0;
12958 subgrp = peer_subgroup(peer, afi, safi);
12959
6392aaa6 12960 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 12961 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
23d0a753
DA
12962 char buf[BUFSIZ] = {0};
12963
d62a17ae 12964 if (use_json) {
12965 json_object_int_add(json, "bgpTableVersion",
12966 table->version);
12967 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
12968 inet_ntop(AF_INET,
12969 &bgp->router_id, buf,
12970 sizeof(buf)));
01eced22
AD
12971 json_object_int_add(json, "defaultLocPrf",
12972 bgp->default_local_pref);
12973 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 12974 json_object_object_add(json, "bgpStatusCodes",
12975 json_scode);
12976 json_object_object_add(json, "bgpOriginCodes",
12977 json_ocode);
07d0c4ed
DA
12978 json_object_string_add(
12979 json, "bgpOriginatingDefaultNetwork",
12980 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 12981 } else {
23d0a753
DA
12982 vty_out(vty,
12983 "BGP table version is %" PRIu64
12984 ", local router ID is %pI4, vrf id ",
12985 table->version, &bgp->router_id);
9df8b37c
PZ
12986 if (bgp->vrf_id == VRF_UNKNOWN)
12987 vty_out(vty, "%s", VRFID_NONE_STR);
12988 else
12989 vty_out(vty, "%u", bgp->vrf_id);
12990 vty_out(vty, "\n");
01eced22
AD
12991 vty_out(vty, "Default local pref %u, ",
12992 bgp->default_local_pref);
12993 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 12994 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 12995 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 12996 vty_out(vty, BGP_SHOW_OCODE_HEADER);
12997
07d0c4ed
DA
12998 vty_out(vty, "Originating default network %s\n\n",
12999 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13000 }
13001 header1 = 0;
13002 }
a636c635 13003
9bcb3eef 13004 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13005 if (type == bgp_show_adj_route_received
13006 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13007 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13008 if (ain->peer != peer)
ea47320b 13009 continue;
6392aaa6 13010
2f9bc755
DS
13011 show_adj_route_header(
13012 vty, bgp, table, &header1, &header2,
13013 json, json_scode, json_ocode, wide);
6392aaa6 13014
6f4f49b2 13015 attr = *ain->attr;
f99def61
AD
13016 route_filtered = false;
13017
13018 /* Filter prefix using distribute list,
13019 * filter list or prefix list
13020 */
b54892e0 13021 const struct prefix *rn_p =
9bcb3eef 13022 bgp_dest_get_prefix(dest);
b54892e0
DS
13023 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13024 safi))
13025 == FILTER_DENY)
f99def61
AD
13026 route_filtered = true;
13027
13028 /* Filter prefix using route-map */
b54892e0
DS
13029 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13030 safi, rmap_name, NULL,
13031 0, NULL);
6392aaa6 13032
13c8e163
AD
13033 if (type == bgp_show_adj_route_filtered &&
13034 !route_filtered && ret != RMAP_DENY) {
b755861b 13035 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13036 continue;
d62a17ae 13037 }
6392aaa6 13038
13c8e163
AD
13039 if (type == bgp_show_adj_route_received &&
13040 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
13041 filtered_count++;
13042
b54892e0 13043 route_vty_out_tmp(vty, rn_p, &attr, safi,
ae248832 13044 use_json, json_ar, wide);
b755861b 13045 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13046 output_count++;
d62a17ae 13047 }
6392aaa6 13048 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13049 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13050 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13051 if (paf->peer != peer || !adj->attr)
924c3f6a 13052 continue;
d62a17ae 13053
2f9bc755
DS
13054 show_adj_route_header(
13055 vty, bgp, table, &header1,
13056 &header2, json, json_scode,
13057 json_ocode, wide);
d62a17ae 13058
b54892e0 13059 const struct prefix *rn_p =
9bcb3eef 13060 bgp_dest_get_prefix(dest);
b54892e0 13061
6f4f49b2 13062 attr = *adj->attr;
b755861b 13063 ret = bgp_output_modifier(
b54892e0 13064 peer, rn_p, &attr, afi, safi,
b755861b 13065 rmap_name);
f46d8e1e 13066
b755861b 13067 if (ret != RMAP_DENY) {
b54892e0
DS
13068 route_vty_out_tmp(
13069 vty, rn_p, &attr, safi,
ae248832
MK
13070 use_json, json_ar,
13071 wide);
b755861b
PM
13072 output_count++;
13073 } else {
13074 filtered_count++;
a2addae8 13075 }
b755861b
PM
13076
13077 bgp_attr_undup(&attr, adj->attr);
924c3f6a 13078 }
f20ce998
DS
13079 } else if (type == bgp_show_adj_route_bestpath) {
13080 struct bgp_path_info *pi;
13081
13082 show_adj_route_header(vty, bgp, table, &header1,
13083 &header2, json, json_scode,
13084 json_ocode, wide);
13085
13086 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13087 pi = pi->next) {
13088 if (pi->peer != peer)
13089 continue;
13090
13091 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13092 continue;
13093
13094 route_vty_out_tmp(vty,
13095 bgp_dest_get_prefix(dest),
13096 pi->attr, safi, use_json,
13097 json_ar, wide);
13098 output_count++;
13099 }
d62a17ae 13100 }
13101 }
d62a17ae 13102
d62a17ae 13103 if (use_json) {
6392aaa6
PM
13104 json_object_object_add(json, "advertisedRoutes", json_ar);
13105 json_object_int_add(json, "totalPrefixCounter", output_count);
13106 json_object_int_add(json, "filteredPrefixCounter",
13107 filtered_count);
13108
996c9314
LB
13109 vty_out(vty, "%s\n", json_object_to_json_string_ext(
13110 json, JSON_C_TO_STRING_PRETTY));
74a630b6
NT
13111
13112 if (!output_count && !filtered_count) {
13113 json_object_free(json_scode);
13114 json_object_free(json_ocode);
13115 }
13116
d62a17ae 13117 json_object_free(json);
6392aaa6
PM
13118 } else if (output_count > 0) {
13119 if (filtered_count > 0)
13120 vty_out(vty,
13121 "\nTotal number of prefixes %ld (%ld filtered)\n",
13122 output_count, filtered_count);
13123 else
13124 vty_out(vty, "\nTotal number of prefixes %ld\n",
13125 output_count);
d62a17ae 13126 }
a636c635 13127}
2a71e9ce 13128
d62a17ae 13129static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13130 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c 13131 const char *rmap_name, uint8_t show_flags)
0b16f239 13132{
d62a17ae 13133 json_object *json = NULL;
96f3485c 13134 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13135
d62a17ae 13136 if (use_json)
13137 json = json_object_new_object();
0b16f239 13138
d62a17ae 13139 if (!peer || !peer->afc[afi][safi]) {
13140 if (use_json) {
13141 json_object_string_add(
13142 json, "warning",
13143 "No such neighbor or address family");
13144 vty_out(vty, "%s\n", json_object_to_json_string(json));
13145 json_object_free(json);
13146 } else
13147 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13148
d62a17ae 13149 return CMD_WARNING;
13150 }
13151
6392aaa6
PM
13152 if ((type == bgp_show_adj_route_received
13153 || type == bgp_show_adj_route_filtered)
d62a17ae 13154 && !CHECK_FLAG(peer->af_flags[afi][safi],
13155 PEER_FLAG_SOFT_RECONFIG)) {
13156 if (use_json) {
13157 json_object_string_add(
13158 json, "warning",
13159 "Inbound soft reconfiguration not enabled");
13160 vty_out(vty, "%s\n", json_object_to_json_string(json));
13161 json_object_free(json);
13162 } else
13163 vty_out(vty,
13164 "%% Inbound soft reconfiguration not enabled\n");
13165
13166 return CMD_WARNING;
13167 }
0b16f239 13168
96f3485c 13169 show_adj_route(vty, peer, afi, safi, type, rmap_name, json, show_flags);
0b16f239 13170
d62a17ae 13171 return CMD_SUCCESS;
a636c635 13172}
50ef26d4 13173
f20ce998
DS
13174DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13175 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13176 "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]",
13177 SHOW_STR
13178 IP_STR
13179 BGP_STR
13180 BGP_INSTANCE_HELP_STR
13181 BGP_AFI_HELP_STR
13182 BGP_SAFI_WITH_LABEL_HELP_STR
13183 "Detailed information on TCP and BGP neighbor connections\n"
13184 "Neighbor to display information about\n"
13185 "Neighbor to display information about\n"
13186 "Neighbor on BGP configured interface\n"
13187 "Display the routes selected by best path\n"
13188 JSON_STR
13189 "Increase table width for longer prefixes\n")
13190{
13191 afi_t afi = AFI_IP6;
13192 safi_t safi = SAFI_UNICAST;
13193 char *rmap_name = NULL;
13194 char *peerstr = NULL;
13195 struct bgp *bgp = NULL;
13196 struct peer *peer;
13197 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13198 int idx = 0;
96f3485c
MK
13199 uint8_t show_flags = 0;
13200
13201 if (uj)
13202 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13203
13204 if (wide)
13205 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13206
13207 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13208 &bgp, uj);
13209
13210 if (!idx)
13211 return CMD_WARNING;
13212
13213 argv_find(argv, argc, "neighbors", &idx);
13214 peerstr = argv[++idx]->arg;
13215
13216 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13217 if (!peer)
13218 return CMD_WARNING;
13219
96f3485c
MK
13220 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13221 show_flags);
f20ce998
DS
13222}
13223
ae248832 13224DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13225 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13226 "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 13227 SHOW_STR
13228 IP_STR
13229 BGP_STR
a636c635 13230 BGP_INSTANCE_HELP_STR
7395a2c9 13231 BGP_AFI_HELP_STR
4dd6177e 13232 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13233 "Display the entries for all address families\n"
718e3744 13234 "Detailed information on TCP and BGP neighbor connections\n"
13235 "Neighbor to display information about\n"
13236 "Neighbor to display information about\n"
91d37724 13237 "Neighbor on BGP configured interface\n"
a636c635 13238 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13239 "Display the received routes from neighbor\n"
13240 "Display the filtered routes received from neighbor\n"
a636c635
DW
13241 "Route-map to modify the attributes\n"
13242 "Name of the route map\n"
ae248832
MK
13243 JSON_STR
13244 "Increase table width for longer prefixes\n")
718e3744 13245{
d62a17ae 13246 afi_t afi = AFI_IP6;
13247 safi_t safi = SAFI_UNICAST;
13248 char *rmap_name = NULL;
13249 char *peerstr = NULL;
d62a17ae 13250 struct bgp *bgp = NULL;
13251 struct peer *peer;
6392aaa6 13252 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13253 int idx = 0;
96f3485c
MK
13254 bool first = true;
13255 uint8_t show_flags = 0;
6392aaa6 13256
96f3485c 13257 if (uj) {
d62a17ae 13258 argc--;
96f3485c
MK
13259 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13260 }
13261
13262 if (all) {
13263 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13264 if (argv_find(argv, argc, "ipv4", &idx))
13265 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13266
13267 if (argv_find(argv, argc, "ipv6", &idx))
13268 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13269 }
13270
13271 if (wide)
13272 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13273
9f049418
DS
13274 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13275 &bgp, uj);
13276 if (!idx)
13277 return CMD_WARNING;
13278
d62a17ae 13279 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13280 argv_find(argv, argc, "neighbors", &idx);
13281 peerstr = argv[++idx]->arg;
8c3deaae 13282
d62a17ae 13283 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13284 if (!peer)
13285 return CMD_WARNING;
856ca177 13286
d62a17ae 13287 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13288 type = bgp_show_adj_route_advertised;
13289 else if (argv_find(argv, argc, "received-routes", &idx))
13290 type = bgp_show_adj_route_received;
13291 else if (argv_find(argv, argc, "filtered-routes", &idx))
13292 type = bgp_show_adj_route_filtered;
13293
d62a17ae 13294 if (argv_find(argv, argc, "route-map", &idx))
13295 rmap_name = argv[++idx]->arg;
95cbbd2a 13296
96f3485c
MK
13297 if (!all)
13298 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13299 show_flags);
13300 if (uj)
13301 vty_out(vty, "{\n");
13302
13303 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13304 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13305 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
13306 : AFI_IP6;
13307 FOREACH_SAFI (safi) {
13308 if (strmatch(get_afi_safi_str(afi, safi, true),
13309 "Unknown"))
13310 continue;
13311
13312 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13313 continue;
13314
13315 if (uj) {
13316 if (first)
13317 first = false;
13318 else
13319 vty_out(vty, ",\n");
13320 vty_out(vty, "\"%s\":",
13321 get_afi_safi_str(afi, safi, true));
13322 } else
13323 vty_out(vty, "\nFor address family: %s\n",
13324 get_afi_safi_str(afi, safi, false));
13325
13326 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13327 show_flags);
13328 }
13329 } else {
13330 FOREACH_AFI_SAFI (afi, safi) {
13331 if (strmatch(get_afi_safi_str(afi, safi, true),
13332 "Unknown"))
13333 continue;
13334
13335 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13336 continue;
13337
13338 if (uj) {
13339 if (first)
13340 first = false;
13341 else
13342 vty_out(vty, ",\n");
13343 vty_out(vty, "\"%s\":",
13344 get_afi_safi_str(afi, safi, true));
13345 } else
13346 vty_out(vty, "\nFor address family: %s\n",
13347 get_afi_safi_str(afi, safi, false));
13348
13349 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13350 show_flags);
13351 }
13352 }
13353 if (uj)
13354 vty_out(vty, "}\n");
13355
13356 return CMD_SUCCESS;
95cbbd2a
ML
13357}
13358
718e3744 13359DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
13360 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 13361 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 13362 SHOW_STR
13363 IP_STR
13364 BGP_STR
8c3deaae
QY
13365 "Address Family\n"
13366 "Address Family\n"
718e3744 13367 "Address Family modifier\n"
13368 "Detailed information on TCP and BGP neighbor connections\n"
13369 "Neighbor to display information about\n"
13370 "Neighbor to display information about\n"
91d37724 13371 "Neighbor on BGP configured interface\n"
718e3744 13372 "Display information received from a BGP neighbor\n"
856ca177 13373 "Display the prefixlist filter\n"
9973d184 13374 JSON_STR)
718e3744 13375{
d62a17ae 13376 afi_t afi = AFI_IP6;
13377 safi_t safi = SAFI_UNICAST;
13378 char *peerstr = NULL;
13379
13380 char name[BUFSIZ];
13381 union sockunion su;
13382 struct peer *peer;
13383 int count, ret;
13384
13385 int idx = 0;
13386
13387 /* show [ip] bgp */
13388 if (argv_find(argv, argc, "ip", &idx))
13389 afi = AFI_IP;
13390 /* [<ipv4|ipv6> [unicast]] */
13391 if (argv_find(argv, argc, "ipv4", &idx))
13392 afi = AFI_IP;
13393 if (argv_find(argv, argc, "ipv6", &idx))
13394 afi = AFI_IP6;
13395 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13396 argv_find(argv, argc, "neighbors", &idx);
13397 peerstr = argv[++idx]->arg;
13398
9f049418 13399 bool uj = use_json(argc, argv);
d62a17ae 13400
13401 ret = str2sockunion(peerstr, &su);
13402 if (ret < 0) {
13403 peer = peer_lookup_by_conf_if(NULL, peerstr);
13404 if (!peer) {
13405 if (uj)
13406 vty_out(vty, "{}\n");
13407 else
13408 vty_out(vty,
13409 "%% Malformed address or name: %s\n",
13410 peerstr);
13411 return CMD_WARNING;
13412 }
13413 } else {
13414 peer = peer_lookup(NULL, &su);
13415 if (!peer) {
13416 if (uj)
13417 vty_out(vty, "{}\n");
13418 else
13419 vty_out(vty, "No peer\n");
13420 return CMD_WARNING;
13421 }
13422 }
718e3744 13423
4ced1a2c 13424 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 13425 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
13426 if (count) {
13427 if (!uj)
13428 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 13429 get_afi_safi_str(afi, safi, false));
d62a17ae 13430 prefix_bgp_show_prefix_list(vty, afi, name, uj);
13431 } else {
13432 if (uj)
13433 vty_out(vty, "{}\n");
13434 else
13435 vty_out(vty, "No functional output\n");
13436 }
718e3744 13437
d62a17ae 13438 return CMD_SUCCESS;
13439}
13440
13441static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
13442 afi_t afi, safi_t safi,
9f049418 13443 enum bgp_show_type type, bool use_json)
d62a17ae 13444{
96f3485c
MK
13445 uint8_t show_flags = 0;
13446
13447 if (use_json)
13448 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13449
d62a17ae 13450 if (!peer || !peer->afc[afi][safi]) {
13451 if (use_json) {
13452 json_object *json_no = NULL;
13453 json_no = json_object_new_object();
13454 json_object_string_add(
13455 json_no, "warning",
13456 "No such neighbor or address family");
13457 vty_out(vty, "%s\n",
13458 json_object_to_json_string(json_no));
13459 json_object_free(json_no);
13460 } else
13461 vty_out(vty, "%% No such neighbor or address family\n");
13462 return CMD_WARNING;
13463 }
47fc97cc 13464
7daf25a3
TA
13465 /* labeled-unicast routes live in the unicast table */
13466 if (safi == SAFI_LABELED_UNICAST)
13467 safi = SAFI_UNICAST;
13468
96f3485c 13469 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags);
718e3744 13470}
13471
dba3c1d3
PG
13472DEFUN (show_ip_bgp_flowspec_routes_detailed,
13473 show_ip_bgp_flowspec_routes_detailed_cmd,
13474 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
13475 SHOW_STR
13476 IP_STR
13477 BGP_STR
13478 BGP_INSTANCE_HELP_STR
13479 BGP_AFI_HELP_STR
13480 "SAFI Flowspec\n"
13481 "Detailed information on flowspec entries\n"
13482 JSON_STR)
13483{
13484 afi_t afi = AFI_IP;
13485 safi_t safi = SAFI_UNICAST;
13486 struct bgp *bgp = NULL;
13487 int idx = 0;
9f049418 13488 bool uj = use_json(argc, argv);
96f3485c 13489 uint8_t show_flags = 0;
9f049418 13490
96f3485c 13491 if (uj) {
9f049418 13492 argc--;
96f3485c
MK
13493 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13494 }
dba3c1d3
PG
13495
13496 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13497 &bgp, uj);
dba3c1d3
PG
13498 if (!idx)
13499 return CMD_WARNING;
13500
96f3485c
MK
13501 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
13502 show_flags);
dba3c1d3
PG
13503}
13504
718e3744 13505DEFUN (show_ip_bgp_neighbor_routes,
13506 show_ip_bgp_neighbor_routes_cmd,
3efd0893 13507 "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 13508 SHOW_STR
13509 IP_STR
13510 BGP_STR
8386ac43 13511 BGP_INSTANCE_HELP_STR
4f280b15 13512 BGP_AFI_HELP_STR
4dd6177e 13513 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 13514 "Detailed information on TCP and BGP neighbor connections\n"
13515 "Neighbor to display information about\n"
13516 "Neighbor to display information about\n"
91d37724 13517 "Neighbor on BGP configured interface\n"
2525cf39 13518 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
13519 "Display the dampened routes received from neighbor\n"
13520 "Display routes learned from neighbor\n"
9973d184 13521 JSON_STR)
718e3744 13522{
d62a17ae 13523 char *peerstr = NULL;
13524 struct bgp *bgp = NULL;
13525 afi_t afi = AFI_IP6;
13526 safi_t safi = SAFI_UNICAST;
13527 struct peer *peer;
13528 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 13529 int idx = 0;
9f049418
DS
13530 bool uj = use_json(argc, argv);
13531
13532 if (uj)
13533 argc--;
bb46e94f 13534
d62a17ae 13535 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13536 &bgp, uj);
d62a17ae 13537 if (!idx)
13538 return CMD_WARNING;
c493f2d8 13539
d62a17ae 13540 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13541 argv_find(argv, argc, "neighbors", &idx);
13542 peerstr = argv[++idx]->arg;
8c3deaae 13543
d62a17ae 13544 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 13545 if (!peer)
d62a17ae 13546 return CMD_WARNING;
bb46e94f 13547
d62a17ae 13548 if (argv_find(argv, argc, "flap-statistics", &idx))
13549 sh_type = bgp_show_type_flap_neighbor;
13550 else if (argv_find(argv, argc, "dampened-routes", &idx))
13551 sh_type = bgp_show_type_damp_neighbor;
13552 else if (argv_find(argv, argc, "routes", &idx))
13553 sh_type = bgp_show_type_neighbor;
2525cf39 13554
d62a17ae 13555 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 13556}
6b0655a2 13557
734b349e 13558struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 13559
d62a17ae 13560struct bgp_distance {
13561 /* Distance value for the IP source prefix. */
d7c0a89a 13562 uint8_t distance;
718e3744 13563
d62a17ae 13564 /* Name of the access-list to be matched. */
13565 char *access_list;
718e3744 13566};
13567
4f280b15
LB
13568DEFUN (show_bgp_afi_vpn_rd_route,
13569 show_bgp_afi_vpn_rd_route_cmd,
d114b977 13570 "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
13571 SHOW_STR
13572 BGP_STR
13573 BGP_AFI_HELP_STR
13574 "Address Family modifier\n"
13575 "Display information for a route distinguisher\n"
13576 "Route Distinguisher\n"
7395a2c9
DS
13577 "Network in the BGP routing table to display\n"
13578 "Network in the BGP routing table to display\n"
13579 JSON_STR)
4f280b15 13580{
d62a17ae 13581 int ret;
13582 struct prefix_rd prd;
13583 afi_t afi = AFI_MAX;
13584 int idx = 0;
4f280b15 13585
ff6566f3
DS
13586 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
13587 vty_out(vty, "%% Malformed Address Family\n");
13588 return CMD_WARNING;
13589 }
13590
d62a17ae 13591 ret = str2prefix_rd(argv[5]->arg, &prd);
13592 if (!ret) {
13593 vty_out(vty, "%% Malformed Route Distinguisher\n");
13594 return CMD_WARNING;
13595 }
ff6566f3 13596
d62a17ae 13597 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 13598 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
13599}
13600
d62a17ae 13601static struct bgp_distance *bgp_distance_new(void)
718e3744 13602{
d62a17ae 13603 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 13604}
13605
d62a17ae 13606static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 13607{
d62a17ae 13608 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 13609}
13610
37a87b8f
CS
13611int bgp_distance_set(uint8_t distance, const char *ip_str,
13612 const char *access_list_str, afi_t afi, safi_t safi,
13613 char *errmsg, size_t errmsg_len)
718e3744 13614{
d62a17ae 13615 int ret;
d62a17ae 13616 struct prefix p;
9bcb3eef 13617 struct bgp_dest *dest;
d62a17ae 13618 struct bgp_distance *bdistance;
718e3744 13619
d62a17ae 13620 ret = str2prefix(ip_str, &p);
13621 if (ret == 0) {
37a87b8f 13622 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 13623 return CMD_WARNING_CONFIG_FAILED;
13624 }
718e3744 13625
d62a17ae 13626 /* Get BGP distance node. */
9bcb3eef
DS
13627 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
13628 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 13629 if (bdistance)
9bcb3eef 13630 bgp_dest_unlock_node(dest);
ca2e160d 13631 else {
d62a17ae 13632 bdistance = bgp_distance_new();
9bcb3eef 13633 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 13634 }
718e3744 13635
d62a17ae 13636 /* Set distance value. */
13637 bdistance->distance = distance;
718e3744 13638
d62a17ae 13639 /* Reset access-list configuration. */
e1b36e13 13640 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13641 if (access_list_str)
13642 bdistance->access_list =
13643 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 13644
d62a17ae 13645 return CMD_SUCCESS;
718e3744 13646}
13647
37a87b8f
CS
13648int bgp_distance_unset(uint8_t distance, const char *ip_str,
13649 const char *access_list_str, afi_t afi, safi_t safi,
13650 char *errmsg, size_t errmsg_len)
718e3744 13651{
d62a17ae 13652 int ret;
d62a17ae 13653 struct prefix p;
9bcb3eef 13654 struct bgp_dest *dest;
d62a17ae 13655 struct bgp_distance *bdistance;
718e3744 13656
d62a17ae 13657 ret = str2prefix(ip_str, &p);
13658 if (ret == 0) {
37a87b8f 13659 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 13660 return CMD_WARNING_CONFIG_FAILED;
13661 }
718e3744 13662
9bcb3eef
DS
13663 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
13664 if (!dest) {
37a87b8f 13665 snprintf(errmsg, errmsg_len, "Can't find specified prefix\n");
d62a17ae 13666 return CMD_WARNING_CONFIG_FAILED;
13667 }
718e3744 13668
9bcb3eef 13669 bdistance = bgp_dest_get_bgp_distance_info(dest);
1f9a9fff 13670
d62a17ae 13671 if (bdistance->distance != distance) {
37a87b8f
CS
13672 snprintf(errmsg, errmsg_len,
13673 "Distance does not match configured\n");
d62a17ae 13674 return CMD_WARNING_CONFIG_FAILED;
13675 }
718e3744 13676
0a22ddfb 13677 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13678 bgp_distance_free(bdistance);
718e3744 13679
9bcb3eef
DS
13680 bgp_dest_set_bgp_path_info(dest, NULL);
13681 bgp_dest_unlock_node(dest);
13682 bgp_dest_unlock_node(dest);
718e3744 13683
d62a17ae 13684 return CMD_SUCCESS;
718e3744 13685}
13686
718e3744 13687/* Apply BGP information to distance method. */
b8685f9b 13688uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 13689 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 13690{
9bcb3eef 13691 struct bgp_dest *dest;
d62a17ae 13692 struct prefix q;
13693 struct peer *peer;
13694 struct bgp_distance *bdistance;
13695 struct access_list *alist;
13696 struct bgp_static *bgp_static;
13697
13698 if (!bgp)
13699 return 0;
13700
40381db7 13701 peer = pinfo->peer;
d62a17ae 13702
7b7d48e5
DS
13703 if (pinfo->attr->distance)
13704 return pinfo->attr->distance;
13705
d62a17ae 13706 /* Check source address. */
13707 sockunion2hostprefix(&peer->su, &q);
9bcb3eef
DS
13708 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
13709 if (dest) {
13710 bdistance = bgp_dest_get_bgp_distance_info(dest);
13711 bgp_dest_unlock_node(dest);
d62a17ae 13712
13713 if (bdistance->access_list) {
13714 alist = access_list_lookup(afi, bdistance->access_list);
13715 if (alist
13716 && access_list_apply(alist, p) == FILTER_PERMIT)
13717 return bdistance->distance;
13718 } else
13719 return bdistance->distance;
718e3744 13720 }
718e3744 13721
d62a17ae 13722 /* Backdoor check. */
9bcb3eef
DS
13723 dest = bgp_node_lookup(bgp->route[afi][safi], p);
13724 if (dest) {
13725 bgp_static = bgp_dest_get_bgp_static_info(dest);
13726 bgp_dest_unlock_node(dest);
718e3744 13727
d62a17ae 13728 if (bgp_static->backdoor) {
13729 if (bgp->distance_local[afi][safi])
13730 return bgp->distance_local[afi][safi];
13731 else
13732 return ZEBRA_IBGP_DISTANCE_DEFAULT;
13733 }
718e3744 13734 }
718e3744 13735
d62a17ae 13736 if (peer->sort == BGP_PEER_EBGP) {
13737 if (bgp->distance_ebgp[afi][safi])
13738 return bgp->distance_ebgp[afi][safi];
13739 return ZEBRA_EBGP_DISTANCE_DEFAULT;
13740 } else {
13741 if (bgp->distance_ibgp[afi][safi])
13742 return bgp->distance_ibgp[afi][safi];
13743 return ZEBRA_IBGP_DISTANCE_DEFAULT;
13744 }
718e3744 13745}
13746
a612fb77
DA
13747/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
13748 * we should tell ZEBRA update the routes for a specific
13749 * AFI/SAFI to reflect changes in RIB.
13750 */
37a87b8f
CS
13751void bgp_announce_routes_distance_update(struct bgp *bgp, afi_t update_afi,
13752 safi_t update_safi)
a612fb77
DA
13753{
13754 afi_t afi;
13755 safi_t safi;
13756
13757 FOREACH_AFI_SAFI (afi, safi) {
13758 if (!bgp_fibupd_safi(safi))
13759 continue;
13760
8b54bc30
DA
13761 if (afi != update_afi && safi != update_safi)
13762 continue;
13763
13764 if (BGP_DEBUG(zebra, ZEBRA))
13765 zlog_debug(
13766 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
13767 __func__, afi, safi);
13768 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
13769 }
13770}
13771
37a87b8f
CS
13772DEFUN_YANG(bgp_distance, bgp_distance_cmd,
13773 "distance bgp (1-255) (1-255) (1-255)",
13774 "Define an administrative distance\n"
13775 "BGP distance\n"
13776 "Distance for routes external to the AS\n"
13777 "Distance for routes internal to the AS\n"
13778 "Distance for local routes\n")
718e3744 13779{
d62a17ae 13780 int idx_number = 2;
13781 int idx_number_2 = 3;
13782 int idx_number_3 = 4;
13783 afi_t afi;
13784 safi_t safi;
37a87b8f 13785 char xpath[XPATH_MAXLEN];
718e3744 13786
d62a17ae 13787 afi = bgp_node_afi(vty);
13788 safi = bgp_node_safi(vty);
718e3744 13789
37a87b8f
CS
13790 snprintf(
13791 xpath, sizeof(xpath),
13792 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
13793 yang_afi_safi_value2identity(afi, safi),
13794 bgp_afi_safi_get_container_str(afi, safi));
13795 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[idx_number]->arg);
13796 snprintf(
13797 xpath, sizeof(xpath),
13798 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
13799 yang_afi_safi_value2identity(afi, safi),
13800 bgp_afi_safi_get_container_str(afi, safi));
13801 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
13802 argv[idx_number_2]->arg);
13803 snprintf(
13804 xpath, sizeof(xpath),
13805 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
13806 yang_afi_safi_value2identity(afi, safi),
13807 bgp_afi_safi_get_container_str(afi, safi));
13808
13809 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
13810 argv[idx_number_3]->arg);
13811
13812 return nb_cli_apply_changes(vty, NULL);
13813}
13814
13815DEFUN_YANG(no_bgp_distance, no_bgp_distance_cmd,
13816 "no distance bgp [(1-255) (1-255) (1-255)]",
13817 NO_STR
13818 "Define an administrative distance\n"
13819 "BGP distance\n"
13820 "Distance for routes external to the AS\n"
13821 "Distance for routes internal to the AS\n"
13822 "Distance for local routes\n")
13823{
13824 afi_t afi;
13825 safi_t safi;
13826 char xpath[XPATH_MAXLEN];
13827
13828 afi = bgp_node_afi(vty);
13829 safi = bgp_node_safi(vty);
13830
13831 snprintf(
13832 xpath, sizeof(xpath),
13833 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
13834 yang_afi_safi_value2identity(afi, safi),
13835 bgp_afi_safi_get_container_str(afi, safi));
13836 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13837 snprintf(
13838 xpath, sizeof(xpath),
13839 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
13840 yang_afi_safi_value2identity(afi, safi),
13841 bgp_afi_safi_get_container_str(afi, safi));
13842 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13843 snprintf(
13844 xpath, sizeof(xpath),
13845 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
13846 yang_afi_safi_value2identity(afi, safi),
13847 bgp_afi_safi_get_container_str(afi, safi));
13848
13849 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13850
13851 return nb_cli_apply_changes(vty, NULL);
718e3744 13852}
13853
37a87b8f
CS
13854void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty *vty,
13855 struct lyd_node *dnode,
13856 bool show_defaults)
718e3744 13857{
37a87b8f
CS
13858 uint8_t distance_ebgp, distance_ibgp, distance_local;
13859
13860 distance_ebgp = yang_dnode_get_uint8(dnode, "./external");
13861 distance_ibgp = yang_dnode_get_uint8(dnode, "./internal");
13862 distance_local = yang_dnode_get_uint8(dnode, "./local");
13863
13864 vty_out(vty, " distance bgp %d %d %d\n", distance_ebgp, distance_ibgp,
13865 distance_local);
13866}
13867
8cc7152a
CS
13868DEFPY_YANG(bgp_distance_source,
13869 bgp_distance_source_cmd,
13870 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
37a87b8f
CS
13871 NO_STR
13872 "Define an administrative distance\n"
8cc7152a 13873 "Distance value\n"
e12affc1
SW
13874 "IPv4 source prefix\n"
13875 "IPv6 source prefix\n"
37a87b8f 13876 "Access list name\n")
718e3744 13877{
37a87b8f
CS
13878 afi_t afi;
13879 safi_t safi;
13880 char xpath[XPATH_MAXLEN];
13881
13882 afi = bgp_node_afi(vty);
13883 safi = bgp_node_safi(vty);
13884
8cc7152a
CS
13885 if (!no) {
13886 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
13887 nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY,
13888 distance_str);
13889 if (acl)
13890 nb_cli_enqueue_change(vty,
13891 "./access-list-policy-export",
13892 NB_OP_CREATE, acl);
13893 else
13894 nb_cli_enqueue_change(vty,
13895 "./access-list-policy-export",
13896 NB_OP_DESTROY, NULL);
13897 } else {
13898 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
13899 }
37a87b8f
CS
13900
13901 snprintf(
13902 xpath, sizeof(xpath),
13903 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
13904 yang_afi_safi_value2identity(afi, safi),
8cc7152a 13905 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
37a87b8f
CS
13906
13907 return nb_cli_apply_changes(vty, xpath);
734b349e
MZ
13908}
13909
37a87b8f
CS
13910void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
13911 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
13912{
13913 vty_out(vty, " distance %d %s %s\n",
13914 yang_dnode_get_uint8(dnode, "./distance"),
13915 yang_dnode_get_string(dnode, "./prefix"),
13916 (yang_dnode_exists(dnode, "./access-list-policy-export"))
13917 ? yang_dnode_get_string(dnode,
13918 "./access-list-policy-export")
13919 : "");
13920}
13921
d9ce5113
CS
13922DEFPY_YANG(bgp_dampening,
13923 bgp_dampening_cmd,
13924 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_supress]]",
37a87b8f
CS
13925 NO_STR
13926 "BGP Specific commands\n"
13927 "Enable route-flap dampening\n"
13928 "Half-life time for the penalty\n"
13929 "Value to start reusing a route\n"
13930 "Value to start suppressing a route\n"
13931 "Maximum duration to suppress a stable route\n")
13932{
13933 afi_t afi;
13934 safi_t safi;
13935 char xpath[XPATH_MAXLEN];
718e3744 13936
37a87b8f
CS
13937 afi = bgp_node_afi(vty);
13938 safi = bgp_node_safi(vty);
13939
d9ce5113
CS
13940 if (!no) {
13941 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
13942 if (argc == 6) {
13943 nb_cli_enqueue_change(vty, "./reach-decay",
13944 NB_OP_MODIFY, halflife_str);
13945 nb_cli_enqueue_change(vty, "./reuse-above",
13946 NB_OP_MODIFY, reuse_str);
13947 nb_cli_enqueue_change(vty, "./suppress-above",
13948 NB_OP_MODIFY, suppress_str);
13949 nb_cli_enqueue_change(vty, "./unreach-decay",
13950 NB_OP_MODIFY, max_supress_str);
13951 } if (argc == 3) {
13952 nb_cli_enqueue_change(vty, "./reach-decay",
13953 NB_OP_MODIFY, halflife_str);
13954 }
13955 } else {
13956 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "false");
13957 }
7ebe9748 13958
37a87b8f
CS
13959 snprintf(
13960 xpath, sizeof(xpath),
13961 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
13962 yang_afi_safi_value2identity(afi, safi),
13963 bgp_afi_safi_get_container_str(afi, safi));
13964
13965 return nb_cli_apply_changes(vty, xpath);
718e3744 13966}
13967
37a87b8f
CS
13968void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty *vty,
13969 struct lyd_node *dnode,
13970 bool show_defaults)
718e3744 13971{
37a87b8f
CS
13972 if (!yang_dnode_get_bool(dnode, "./enable"))
13973 return;
13974
13975 int half = DEFAULT_HALF_LIFE * 60;
13976 int reuse = DEFAULT_REUSE;
13977 int suppress = DEFAULT_SUPPRESS;
13978 int max;
13979
13980 half = yang_dnode_get_uint8(dnode, "../reach-decay");
13981 reuse = yang_dnode_get_uint16(dnode, "../reuse-above");
13982 suppress = yang_dnode_get_uint16(dnode, "../suppress-above");
13983 max = yang_dnode_get_uint8(dnode, "../unreach-decay");
13984
13985 if (half == DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
13986 && suppress == DEFAULT_SUPPRESS && max == half * 4)
13987 vty_out(vty, " bgp dampening\n");
13988 else if (half != DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
13989 && suppress == DEFAULT_SUPPRESS && max == half * 4)
13990 vty_out(vty, " bgp dampening %u\n", half);
13991 else
13992 vty_out(vty, " bgp dampening %u %d %d %d\n", half, reuse,
13993 suppress, max);
718e3744 13994}
13995
718e3744 13996/* Display specified route of BGP table. */
d62a17ae 13997static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
13998 const char *ip_str, afi_t afi, safi_t safi,
13999 struct prefix_rd *prd, int prefix_check)
14000{
14001 int ret;
14002 struct prefix match;
9bcb3eef
DS
14003 struct bgp_dest *dest;
14004 struct bgp_dest *rm;
40381db7
DS
14005 struct bgp_path_info *pi;
14006 struct bgp_path_info *pi_temp;
d62a17ae 14007 struct bgp *bgp;
14008 struct bgp_table *table;
14009
14010 /* BGP structure lookup. */
14011 if (view_name) {
14012 bgp = bgp_lookup_by_name(view_name);
14013 if (bgp == NULL) {
14014 vty_out(vty, "%% Can't find BGP instance %s\n",
14015 view_name);
14016 return CMD_WARNING;
14017 }
14018 } else {
14019 bgp = bgp_get_default();
14020 if (bgp == NULL) {
14021 vty_out(vty, "%% No BGP process is configured\n");
14022 return CMD_WARNING;
14023 }
718e3744 14024 }
718e3744 14025
d62a17ae 14026 /* Check IP address argument. */
14027 ret = str2prefix(ip_str, &match);
14028 if (!ret) {
14029 vty_out(vty, "%% address is malformed\n");
14030 return CMD_WARNING;
14031 }
718e3744 14032
d62a17ae 14033 match.family = afi2family(afi);
14034
14035 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14036 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14037 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14038 dest = bgp_route_next(dest)) {
14039 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14040
9bcb3eef 14041 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14042 continue;
9bcb3eef 14043 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14044 if (!table)
ea47320b
DL
14045 continue;
14046 if ((rm = bgp_node_match(table, &match)) == NULL)
14047 continue;
d62a17ae 14048
9bcb3eef 14049 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14050
ea47320b 14051 if (!prefix_check
b54892e0 14052 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14053 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14054 while (pi) {
14055 if (pi->extra && pi->extra->damp_info) {
14056 pi_temp = pi->next;
ea47320b 14057 bgp_damp_info_free(
40381db7 14058 pi->extra->damp_info,
a935f597 14059 1, afi, safi);
40381db7 14060 pi = pi_temp;
ea47320b 14061 } else
40381db7 14062 pi = pi->next;
d62a17ae 14063 }
ea47320b
DL
14064 }
14065
9bcb3eef 14066 bgp_dest_unlock_node(rm);
d62a17ae 14067 }
14068 } else {
9bcb3eef 14069 if ((dest = bgp_node_match(bgp->rib[afi][safi], &match))
d62a17ae 14070 != NULL) {
9bcb3eef 14071 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14072
d62a17ae 14073 if (!prefix_check
9bcb3eef
DS
14074 || dest_p->prefixlen == match.prefixlen) {
14075 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14076 while (pi) {
14077 if (pi->extra && pi->extra->damp_info) {
14078 pi_temp = pi->next;
d62a17ae 14079 bgp_damp_info_free(
40381db7 14080 pi->extra->damp_info,
a935f597 14081 1, afi, safi);
40381db7 14082 pi = pi_temp;
d62a17ae 14083 } else
40381db7 14084 pi = pi->next;
d62a17ae 14085 }
14086 }
14087
9bcb3eef 14088 bgp_dest_unlock_node(dest);
d62a17ae 14089 }
14090 }
718e3744 14091
d62a17ae 14092 return CMD_SUCCESS;
718e3744 14093}
14094
14095DEFUN (clear_ip_bgp_dampening,
14096 clear_ip_bgp_dampening_cmd,
14097 "clear ip bgp dampening",
14098 CLEAR_STR
14099 IP_STR
14100 BGP_STR
14101 "Clear route flap dampening information\n")
14102{
a935f597 14103 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 14104 return CMD_SUCCESS;
718e3744 14105}
14106
14107DEFUN (clear_ip_bgp_dampening_prefix,
14108 clear_ip_bgp_dampening_prefix_cmd,
14109 "clear ip bgp dampening A.B.C.D/M",
14110 CLEAR_STR
14111 IP_STR
14112 BGP_STR
14113 "Clear route flap dampening information\n"
0c7b1b01 14114 "IPv4 prefix\n")
718e3744 14115{
d62a17ae 14116 int idx_ipv4_prefixlen = 4;
14117 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14118 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14119}
14120
14121DEFUN (clear_ip_bgp_dampening_address,
14122 clear_ip_bgp_dampening_address_cmd,
14123 "clear ip bgp dampening A.B.C.D",
14124 CLEAR_STR
14125 IP_STR
14126 BGP_STR
14127 "Clear route flap dampening information\n"
14128 "Network to clear damping information\n")
14129{
d62a17ae 14130 int idx_ipv4 = 4;
14131 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14132 SAFI_UNICAST, NULL, 0);
718e3744 14133}
14134
14135DEFUN (clear_ip_bgp_dampening_address_mask,
14136 clear_ip_bgp_dampening_address_mask_cmd,
14137 "clear ip bgp dampening A.B.C.D A.B.C.D",
14138 CLEAR_STR
14139 IP_STR
14140 BGP_STR
14141 "Clear route flap dampening information\n"
14142 "Network to clear damping information\n"
14143 "Network mask\n")
14144{
d62a17ae 14145 int idx_ipv4 = 4;
14146 int idx_ipv4_2 = 5;
14147 int ret;
14148 char prefix_str[BUFSIZ];
718e3744 14149
d62a17ae 14150 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
14151 prefix_str);
14152 if (!ret) {
14153 vty_out(vty, "%% Inconsistent address and mask\n");
14154 return CMD_WARNING;
14155 }
718e3744 14156
d62a17ae 14157 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14158 NULL, 0);
718e3744 14159}
6b0655a2 14160
e3b78da8 14161static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14162{
14163 struct vty *vty = arg;
e3b78da8 14164 struct peer *peer = bucket->data;
825d9834
DS
14165 char buf[SU_ADDRSTRLEN];
14166
14167 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14168 sockunion2str(&peer->su, buf, sizeof(buf)));
14169}
14170
2a0e69ae
DS
14171DEFUN (show_bgp_listeners,
14172 show_bgp_listeners_cmd,
14173 "show bgp listeners",
14174 SHOW_STR
14175 BGP_STR
14176 "Display Listen Sockets and who created them\n")
14177{
14178 bgp_dump_listener_info(vty);
14179
14180 return CMD_SUCCESS;
14181}
14182
825d9834
DS
14183DEFUN (show_bgp_peerhash,
14184 show_bgp_peerhash_cmd,
14185 "show bgp peerhash",
14186 SHOW_STR
14187 BGP_STR
14188 "Display information about the BGP peerhash\n")
14189{
14190 struct list *instances = bm->bgp;
14191 struct listnode *node;
14192 struct bgp *bgp;
14193
14194 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14195 vty_out(vty, "BGP: %s\n", bgp->name);
14196 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14197 vty);
14198 }
14199
14200 return CMD_SUCCESS;
14201}
14202
587ff0fd 14203/* also used for encap safi */
2b791107
DL
14204static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14205 afi_t afi, safi_t safi)
d62a17ae 14206{
9bcb3eef
DS
14207 struct bgp_dest *pdest;
14208 struct bgp_dest *dest;
d62a17ae 14209 struct bgp_table *table;
b54892e0
DS
14210 const struct prefix *p;
14211 const struct prefix_rd *prd;
d62a17ae 14212 struct bgp_static *bgp_static;
14213 mpls_label_t label;
d62a17ae 14214 char rdbuf[RD_ADDRSTRLEN];
14215
14216 /* Network configuration. */
9bcb3eef
DS
14217 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14218 pdest = bgp_route_next(pdest)) {
14219 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14220 if (!table)
ea47320b 14221 continue;
d62a17ae 14222
9bcb3eef
DS
14223 for (dest = bgp_table_top(table); dest;
14224 dest = bgp_route_next(dest)) {
14225 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14226 if (bgp_static == NULL)
ea47320b 14227 continue;
d62a17ae 14228
9bcb3eef
DS
14229 p = bgp_dest_get_prefix(dest);
14230 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14231 pdest);
d62a17ae 14232
ea47320b 14233 /* "network" configuration display. */
06b9f471 14234 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14235 label = decode_label(&bgp_static->label);
14236
8228a9a7 14237 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14238 if (safi == SAFI_MPLS_VPN)
14239 vty_out(vty, " label %u", label);
14240
14241 if (bgp_static->rmap.name)
14242 vty_out(vty, " route-map %s",
14243 bgp_static->rmap.name);
e2a86ad9
DS
14244
14245 if (bgp_static->backdoor)
14246 vty_out(vty, " backdoor");
14247
ea47320b
DL
14248 vty_out(vty, "\n");
14249 }
14250 }
d62a17ae 14251}
14252
2b791107
DL
14253static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14254 afi_t afi, safi_t safi)
d62a17ae 14255{
9bcb3eef
DS
14256 struct bgp_dest *pdest;
14257 struct bgp_dest *dest;
d62a17ae 14258 struct bgp_table *table;
b54892e0
DS
14259 const struct prefix *p;
14260 const struct prefix_rd *prd;
d62a17ae 14261 struct bgp_static *bgp_static;
ff44f570 14262 char buf[PREFIX_STRLEN * 2];
d62a17ae 14263 char buf2[SU_ADDRSTRLEN];
14264 char rdbuf[RD_ADDRSTRLEN];
0a50c248 14265 char esi_buf[ESI_BYTES];
d62a17ae 14266
14267 /* Network configuration. */
9bcb3eef
DS
14268 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14269 pdest = bgp_route_next(pdest)) {
14270 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14271 if (!table)
ea47320b 14272 continue;
d62a17ae 14273
9bcb3eef
DS
14274 for (dest = bgp_table_top(table); dest;
14275 dest = bgp_route_next(dest)) {
14276 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14277 if (bgp_static == NULL)
ea47320b 14278 continue;
d62a17ae 14279
ea47320b 14280 char *macrouter = NULL;
d62a17ae 14281
ea47320b
DL
14282 if (bgp_static->router_mac)
14283 macrouter = prefix_mac2str(
14284 bgp_static->router_mac, NULL, 0);
14285 if (bgp_static->eth_s_id)
0a50c248
AK
14286 esi_to_str(bgp_static->eth_s_id,
14287 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
14288 p = bgp_dest_get_prefix(dest);
14289 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 14290
ea47320b 14291 /* "network" configuration display. */
06b9f471 14292 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
14293 if (p->u.prefix_evpn.route_type == 5) {
14294 char local_buf[PREFIX_STRLEN];
3714a385 14295 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
14296 struct prefix_evpn *)p)
14297 ? AF_INET
14298 : AF_INET6;
3714a385 14299 inet_ntop(family,
14300 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 14301 local_buf, PREFIX_STRLEN);
772270f3
QY
14302 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
14303 p->u.prefix_evpn.prefix_addr
14304 .ip_prefix_length);
197cb530
PG
14305 } else {
14306 prefix2str(p, buf, sizeof(buf));
14307 }
ea47320b 14308
a4d82a8a
PZ
14309 if (bgp_static->gatewayIp.family == AF_INET
14310 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
14311 inet_ntop(bgp_static->gatewayIp.family,
14312 &bgp_static->gatewayIp.u.prefix, buf2,
14313 sizeof(buf2));
ea47320b 14314 vty_out(vty,
7bcc8dac 14315 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 14316 buf, rdbuf,
14317 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 14318 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
14319 macrouter);
14320
0a22ddfb 14321 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
14322 }
14323 }
3da6fcd5
PG
14324}
14325
718e3744 14326/* Configuration of static route announcement and aggregate
14327 information. */
2b791107
DL
14328void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
14329 safi_t safi)
d62a17ae 14330{
9bcb3eef 14331 struct bgp_dest *dest;
b54892e0 14332 const struct prefix *p;
d62a17ae 14333 struct bgp_static *bgp_static;
14334 struct bgp_aggregate *bgp_aggregate;
d62a17ae 14335
2b791107
DL
14336 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
14337 bgp_config_write_network_vpn(vty, bgp, afi, safi);
14338 return;
14339 }
d62a17ae 14340
2b791107
DL
14341 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
14342 bgp_config_write_network_evpn(vty, bgp, afi, safi);
14343 return;
14344 }
d62a17ae 14345
14346 /* Network configuration. */
9bcb3eef
DS
14347 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
14348 dest = bgp_route_next(dest)) {
14349 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14350 if (bgp_static == NULL)
ea47320b 14351 continue;
d62a17ae 14352
9bcb3eef 14353 p = bgp_dest_get_prefix(dest);
d62a17ae 14354
8228a9a7 14355 vty_out(vty, " network %pFX", p);
d62a17ae 14356
ea47320b
DL
14357 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
14358 vty_out(vty, " label-index %u",
14359 bgp_static->label_index);
d62a17ae 14360
ea47320b
DL
14361 if (bgp_static->rmap.name)
14362 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
14363
14364 if (bgp_static->backdoor)
14365 vty_out(vty, " backdoor");
718e3744 14366
ea47320b
DL
14367 vty_out(vty, "\n");
14368 }
14369
d62a17ae 14370 /* Aggregate-address configuration. */
9bcb3eef
DS
14371 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
14372 dest = bgp_route_next(dest)) {
14373 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 14374 if (bgp_aggregate == NULL)
ea47320b 14375 continue;
d62a17ae 14376
9bcb3eef 14377 p = bgp_dest_get_prefix(dest);
d62a17ae 14378
8228a9a7 14379 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 14380
ea47320b
DL
14381 if (bgp_aggregate->as_set)
14382 vty_out(vty, " as-set");
d62a17ae 14383
ea47320b
DL
14384 if (bgp_aggregate->summary_only)
14385 vty_out(vty, " summary-only");
718e3744 14386
20894f50
DA
14387 if (bgp_aggregate->rmap.name)
14388 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
14389
229757f1
DA
14390 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
14391 vty_out(vty, " origin %s",
14392 bgp_origin2str(bgp_aggregate->origin));
14393
6aabb15d
RZ
14394 if (bgp_aggregate->match_med)
14395 vty_out(vty, " matching-MED-only");
14396
365ab2e7
RZ
14397 if (bgp_aggregate->suppress_map_name)
14398 vty_out(vty, " suppress-map %s",
14399 bgp_aggregate->suppress_map_name);
14400
ea47320b
DL
14401 vty_out(vty, "\n");
14402 }
d62a17ae 14403}
734b349e 14404
2b791107 14405void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 14406 safi_t safi)
d62a17ae 14407{
9bcb3eef 14408 struct bgp_dest *dest;
d62a17ae 14409 struct bgp_distance *bdistance;
14410
14411 /* Distance configuration. */
14412 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
14413 && bgp->distance_local[afi][safi]
14414 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
14415 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
14416 || bgp->distance_local[afi][safi]
14417 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 14418 vty_out(vty, " distance bgp %d %d %d\n",
14419 bgp->distance_ebgp[afi][safi],
14420 bgp->distance_ibgp[afi][safi],
14421 bgp->distance_local[afi][safi]);
14422 }
734b349e 14423
9bcb3eef
DS
14424 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
14425 dest = bgp_route_next(dest)) {
14426 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 14427 if (bdistance != NULL)
56ca3b5b 14428 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 14429 bdistance->distance, dest,
d62a17ae 14430 bdistance->access_list ? bdistance->access_list
14431 : "");
ca2e160d 14432 }
718e3744 14433}
14434
14435/* Allocate routing table structure and install commands. */
d62a17ae 14436void bgp_route_init(void)
14437{
14438 afi_t afi;
14439 safi_t safi;
14440
14441 /* Init BGP distance table. */
05c7a1cc 14442 FOREACH_AFI_SAFI (afi, safi)
960035b2 14443 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 14444
14445 /* IPv4 BGP commands. */
14446 install_element(BGP_NODE, &bgp_table_map_cmd);
14447 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 14448 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 14449
554b3b10 14450 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 14451
14452 /* IPv4 unicast configuration. */
14453 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
14454 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 14455 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 14456
554b3b10 14457 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 14458
14459 /* IPv4 multicast configuration. */
14460 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
14461 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 14462 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 14463 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 14464
14465 /* IPv4 labeled-unicast configuration. */
fb985e0c 14466 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 14467 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 14468
d62a17ae 14469 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
14470 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 14471 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 14472 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 14473 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 14474 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
14475 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 14476 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 14477
14478 install_element(VIEW_NODE,
14479 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
14480 install_element(VIEW_NODE,
14481 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 14482 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
14483 install_element(VIEW_NODE,
14484 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 14485#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14486 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 14487#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 14488 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
14489 install_element(VIEW_NODE,
44c69747 14490 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 14491
d62a17ae 14492 /* BGP dampening clear commands */
14493 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
14494 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 14495
d62a17ae 14496 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
14497 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
14498
14499 /* prefix count */
14500 install_element(ENABLE_NODE,
14501 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 14502#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14503 install_element(ENABLE_NODE,
14504 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 14505#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 14506
d62a17ae 14507 /* New config IPv6 BGP commands. */
14508 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
14509 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14510 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 14511
554b3b10 14512 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 14513
14514 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14515
fb985e0c
DA
14516 /* IPv6 labeled unicast address family. */
14517 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 14518 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 14519
d62a17ae 14520 install_element(BGP_NODE, &bgp_distance_cmd);
14521 install_element(BGP_NODE, &no_bgp_distance_cmd);
14522 install_element(BGP_NODE, &bgp_distance_source_cmd);
d62a17ae 14523 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
14524 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
14525 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
d62a17ae 14526 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
14527 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
14528 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
d62a17ae 14529 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
14530 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
8cc7152a 14531 install_element(BGP_IPV6_NODE, &bgp_distance_source_cmd);
d62a17ae 14532 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
14533 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
8cc7152a 14534 install_element(BGP_IPV6M_NODE, &bgp_distance_source_cmd);
d62a17ae 14535
ef5f4b23 14536 /* BGP dampening */
d9ce5113
CS
14537 install_element(BGP_NODE, &bgp_dampening_cmd);
14538 install_element(BGP_IPV4_NODE, &bgp_dampening_cmd);
14539 install_element(BGP_IPV4M_NODE, &bgp_dampening_cmd);
14540 install_element(BGP_IPV4L_NODE, &bgp_dampening_cmd);
14541 install_element(BGP_IPV6_NODE, &bgp_dampening_cmd);
14542 install_element(BGP_IPV6M_NODE, &bgp_dampening_cmd);
14543 install_element(BGP_IPV6L_NODE, &bgp_dampening_cmd);
d62a17ae 14544
14545 /* Large Communities */
14546 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
14547 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
14548
14549 /* show bgp ipv4 flowspec detailed */
14550 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
14551
2a0e69ae 14552 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 14553 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 14554}
14555
14556void bgp_route_finish(void)
14557{
14558 afi_t afi;
14559 safi_t safi;
14560
05c7a1cc
QY
14561 FOREACH_AFI_SAFI (afi, safi) {
14562 bgp_table_unlock(bgp_distance_table[afi][safi]);
14563 bgp_distance_table[afi][safi] = NULL;
14564 }
228da428 14565}