]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
*: un-split strings across lines
[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"
718e3744 73
49e5a4a0 74#ifdef ENABLE_BGP_VNC
f8b6f499
LB
75#include "bgpd/rfapi/rfapi_backend.h"
76#include "bgpd/rfapi/vnc_import_bgp.h"
77#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 78#endif
aee875b5
PG
79#include "bgpd/bgp_encap_types.h"
80#include "bgpd/bgp_encap_tlv.h"
684a7227 81#include "bgpd/bgp_evpn.h"
3da6fcd5 82#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 83#include "bgpd/bgp_flowspec.h"
98a9dbc7 84#include "bgpd/bgp_flowspec_util.h"
45918cfb 85#include "bgpd/bgp_pbr.h"
65efcfce 86
e2a86ad9
DS
87#ifndef VTYSH_EXTRACT_PL
88#include "bgpd/bgp_route_clippy.c"
89#endif
aee875b5 90
718e3744 91/* Extern from bgp_dump.c */
dde72586
SH
92extern const char *bgp_origin_str[];
93extern const char *bgp_origin_long_str[];
36235319 94const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json);
b7d08f5a 95/* PMSI strings. */
96#define PMSI_TNLTYPE_STR_NO_INFO "No info"
97#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
98static const struct message bgp_pmsi_tnltype_str[] = {
99 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
100 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
101 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
102 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
103 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
104 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
105 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
106 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 107 {0}
108};
b7d08f5a 109
9df8b37c
PZ
110#define VRFID_NONE_STR "-"
111
4a11bf2c 112DEFINE_HOOK(bgp_process,
9bcb3eef
DS
113 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
114 struct peer *peer, bool withdraw),
115 (bgp, afi, safi, bn, peer, withdraw))
4a11bf2c
DL
116
117
9bcb3eef 118struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 119 safi_t safi, const struct prefix *p,
d62a17ae 120 struct prefix_rd *prd)
121{
9bcb3eef
DS
122 struct bgp_dest *dest;
123 struct bgp_dest *pdest = NULL;
d62a17ae 124
125 assert(table);
d62a17ae 126
127 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
128 || (safi == SAFI_EVPN)) {
9bcb3eef 129 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 130
9bcb3eef
DS
131 if (!bgp_dest_has_bgp_path_info_data(pdest))
132 bgp_dest_set_bgp_table_info(
133 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 134 else
9bcb3eef
DS
135 bgp_dest_unlock_node(pdest);
136 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 137 }
718e3744 138
9bcb3eef 139 dest = bgp_node_get(table, p);
718e3744 140
d62a17ae 141 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
142 || (safi == SAFI_EVPN))
9bcb3eef 143 dest->pdest = pdest;
718e3744 144
9bcb3eef 145 return dest;
718e3744 146}
6b0655a2 147
9bcb3eef 148struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 149 safi_t safi, const struct prefix *p,
d62a17ae 150 struct prefix_rd *prd)
128ea8ab 151{
9bcb3eef
DS
152 struct bgp_dest *dest;
153 struct bgp_dest *pdest = NULL;
128ea8ab 154
d62a17ae 155 if (!table)
156 return NULL;
128ea8ab 157
d62a17ae 158 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
159 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
160 pdest = bgp_node_lookup(table, (struct prefix *)prd);
161 if (!pdest)
d62a17ae 162 return NULL;
128ea8ab 163
9bcb3eef
DS
164 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
165 bgp_dest_unlock_node(pdest);
d62a17ae 166 return NULL;
167 }
128ea8ab 168
9bcb3eef 169 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 170 }
128ea8ab 171
9bcb3eef 172 dest = bgp_node_lookup(table, p);
128ea8ab 173
9bcb3eef 174 return dest;
128ea8ab 175}
176
18ee8310
DS
177/* Allocate bgp_path_info_extra */
178static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 179{
4b7e6066
DS
180 struct bgp_path_info_extra *new;
181 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
182 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
183 new->label[0] = MPLS_INVALID_LABEL;
184 new->num_labels = 0;
3e3708cb
PG
185 new->bgp_fs_pbr = NULL;
186 new->bgp_fs_iprule = NULL;
d62a17ae 187 return new;
fb982c25
PJ
188}
189
a2e219fe 190void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 191{
4b7e6066 192 struct bgp_path_info_extra *e;
d62a17ae 193
c93a3b77
DS
194 if (!extra || !*extra)
195 return;
d62a17ae 196
c93a3b77
DS
197 e = *extra;
198 if (e->damp_info)
a935f597
DA
199 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
200 e->damp_info->safi);
d62a17ae 201
c93a3b77
DS
202 e->damp_info = NULL;
203 if (e->parent) {
40381db7 204 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 205
40381db7 206 if (bpi->net) {
0e70e6c8
DL
207 /* FIXME: since multiple e may have the same e->parent
208 * and e->parent->net is holding a refcount for each
209 * of them, we need to do some fudging here.
210 *
40381db7
DS
211 * WARNING: if bpi->net->lock drops to 0, bpi may be
212 * freed as well (because bpi->net was holding the
213 * last reference to bpi) => write after free!
0e70e6c8
DL
214 */
215 unsigned refcount;
216
40381db7
DS
217 bpi = bgp_path_info_lock(bpi);
218 refcount = bpi->net->lock - 1;
9bcb3eef 219 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 220 if (!refcount)
40381db7
DS
221 bpi->net = NULL;
222 bgp_path_info_unlock(bpi);
0e70e6c8 223 }
18ee8310 224 bgp_path_info_unlock(e->parent);
c93a3b77 225 e->parent = NULL;
d62a17ae 226 }
c93a3b77
DS
227
228 if (e->bgp_orig)
229 bgp_unlock(e->bgp_orig);
c26edcda 230
ce3c0614
PG
231 if ((*extra)->bgp_fs_iprule)
232 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 233 if ((*extra)->bgp_fs_pbr)
6a154c88 234 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 235 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
236}
237
18ee8310
DS
238/* Get bgp_path_info extra information for the given bgp_path_info, lazy
239 * allocated if required.
fb982c25 240 */
40381db7 241struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 242{
40381db7
DS
243 if (!pi->extra)
244 pi->extra = bgp_path_info_extra_new();
245 return pi->extra;
fb982c25
PJ
246}
247
718e3744 248/* Free bgp route information. */
9b6d8fcf 249static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 250{
05864da7 251 bgp_attr_unintern(&path->attr);
fb018d25 252
9b6d8fcf
DS
253 bgp_unlink_nexthop(path);
254 bgp_path_info_extra_free(&path->extra);
255 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
256 if (path->net)
257 bgp_addpath_free_info_data(&path->tx_addpath,
258 &path->net->tx_addpath);
718e3744 259
9b6d8fcf 260 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 261
9b6d8fcf 262 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 263}
264
9b6d8fcf 265struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 266{
9b6d8fcf
DS
267 path->lock++;
268 return path;
200df115 269}
270
9b6d8fcf 271struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 272{
9b6d8fcf
DS
273 assert(path && path->lock > 0);
274 path->lock--;
d62a17ae 275
9b6d8fcf 276 if (path->lock == 0) {
200df115 277#if 0
278 zlog_debug ("%s: unlocked and freeing", __func__);
279 zlog_backtrace (LOG_DEBUG);
280#endif
9b6d8fcf 281 bgp_path_info_free(path);
d62a17ae 282 return NULL;
283 }
200df115 284
285#if 0
9b6d8fcf 286 if (path->lock == 1)
200df115 287 {
288 zlog_debug ("%s: unlocked to 1", __func__);
289 zlog_backtrace (LOG_DEBUG);
290 }
291#endif
d62a17ae 292
9b6d8fcf 293 return path;
200df115 294}
295
f009ff26 296/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 297static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 298{
299 struct peer *peer;
300 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 301 bool set_flag = false;
f009ff26 302 struct bgp *bgp = NULL;
303 struct bgp_table *table = NULL;
304 afi_t afi = 0;
305 safi_t safi = 0;
f009ff26 306
307 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
308 * then the route selection is deferred
309 */
9bcb3eef 310 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 311 return 0;
312
9bcb3eef 313 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 314 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 315 zlog_debug(
b54892e0 316 "Route %pRN is in workqueue and being processed, not deferred.",
9bcb3eef 317 bgp_dest_to_rnode(dest));
b54892e0 318
5f9c1aa2 319 return 0;
320 }
321
9bcb3eef 322 table = bgp_dest_table(dest);
f009ff26 323 if (table) {
324 bgp = table->bgp;
325 afi = table->afi;
326 safi = table->safi;
327 }
328
9bcb3eef 329 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 330 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
331 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
332 continue;
333
334 /* Route selection is deferred if there is a stale path which
335 * which indicates peer is in restart mode
336 */
36235319
QY
337 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
338 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 339 set_flag = true;
f009ff26 340 } else {
341 /* If the peer is graceful restart capable and peer is
342 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
343 */
344 peer = old_pi->peer;
36235319
QY
345 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
346 && BGP_PEER_RESTARTING_MODE(peer)
347 && (old_pi
348 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 349 set_flag = true;
f009ff26 350 }
351 }
352 if (set_flag)
353 break;
354 }
355
356 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
357 * is active
358 */
2ba1fe69 359 if (set_flag && table) {
f009ff26 360 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
9bcb3eef
DS
361 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
362 if (dest->rt_node == NULL)
363 dest->rt_node = listnode_add(
364 bgp->gr_info[afi][safi].route_list,
365 dest);
f009ff26 366 if (BGP_DEBUG(update, UPDATE_OUT))
9bcb3eef
DS
367 zlog_debug("DEFER route %pRN, dest %p, node %p",
368 dest, dest, dest->rt_node);
f009ff26 369 return 0;
370 }
371 }
372 return -1;
373}
374
9bcb3eef 375void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 376{
4b7e6066 377 struct bgp_path_info *top;
718e3744 378
9bcb3eef 379 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 380
6f94b685 381 pi->next = top;
40381db7 382 pi->prev = NULL;
d62a17ae 383 if (top)
40381db7 384 top->prev = pi;
9bcb3eef 385 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 386
40381db7 387 bgp_path_info_lock(pi);
9bcb3eef 388 bgp_dest_lock_node(dest);
40381db7 389 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 390 bgp_dest_set_defer_flag(dest, false);
718e3744 391}
392
d62a17ae 393/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 394 completion callback *only* */
9bcb3eef 395void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 396{
40381db7
DS
397 if (pi->next)
398 pi->next->prev = pi->prev;
399 if (pi->prev)
400 pi->prev->next = pi->next;
d62a17ae 401 else
9bcb3eef 402 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 403
40381db7
DS
404 bgp_path_info_mpath_dequeue(pi);
405 bgp_path_info_unlock(pi);
9bcb3eef 406 bgp_dest_unlock_node(dest);
718e3744 407}
408
9bcb3eef 409void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 410{
9bcb3eef 411 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 412 /* set of previous already took care of pcount */
40381db7 413 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 414}
415
18ee8310 416/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
417 called when a route is deleted and then quickly re-added before the
418 deletion has been processed */
9bcb3eef 419void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 420{
9bcb3eef 421 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 422 /* unset of previous already took care of pcount */
40381db7 423 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
424}
425
d62a17ae 426/* Adjust pcount as required */
9bcb3eef 427static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 428{
d62a17ae 429 struct bgp_table *table;
67174041 430
9bcb3eef 431 assert(dest && bgp_dest_table(dest));
40381db7 432 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 433
9bcb3eef 434 table = bgp_dest_table(dest);
67174041 435
40381db7 436 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 437 return;
438
40381db7
DS
439 if (!BGP_PATH_COUNTABLE(pi)
440 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 441
40381db7 442 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 443
444 /* slight hack, but more robust against errors. */
40381db7
DS
445 if (pi->peer->pcount[table->afi][table->safi])
446 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 447 else
450971aa 448 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 449 "Asked to decrement 0 prefix count for peer");
40381db7
DS
450 } else if (BGP_PATH_COUNTABLE(pi)
451 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
452 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
453 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 454 }
1a392d46
PJ
455}
456
40381db7
DS
457static int bgp_label_index_differs(struct bgp_path_info *pi1,
458 struct bgp_path_info *pi2)
28d58fd7 459{
40381db7 460 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 461}
1a392d46 462
18ee8310 463/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
464 * This is here primarily to keep prefix-count in check.
465 */
9bcb3eef 466void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 467 uint32_t flag)
1a392d46 468{
40381db7 469 SET_FLAG(pi->flags, flag);
d62a17ae 470
471 /* early bath if we know it's not a flag that changes countability state
472 */
473 if (!CHECK_FLAG(flag,
1defdda8 474 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 475 return;
476
9bcb3eef 477 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
478}
479
9bcb3eef 480void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 481 uint32_t flag)
1a392d46 482{
40381db7 483 UNSET_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
718e3744 494/* Get MED value. If MED value is missing and "bgp bestpath
495 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 496static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 497{
498 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
499 return attr->med;
500 else {
892fedb6 501 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 502 return BGP_MED_MAX;
503 else
504 return 0;
505 }
718e3744 506}
507
40381db7 508void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf)
2ec1e66f 509{
40381db7
DS
510 if (pi->addpath_rx_id)
511 sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
512 pi->addpath_rx_id);
d62a17ae 513 else
40381db7 514 sprintf(buf, "path %s", pi->peer->host);
d62a17ae 515}
9fbdd100 516
d62a17ae 517/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
518 */
18ee8310
DS
519static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
520 struct bgp_path_info *exist, int *paths_eq,
521 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
522 char *pfx_buf, afi_t afi, safi_t safi,
523 enum bgp_path_selection_reason *reason)
d62a17ae 524{
525 struct attr *newattr, *existattr;
526 bgp_peer_sort_t new_sort;
527 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
528 uint32_t new_pref;
529 uint32_t exist_pref;
530 uint32_t new_med;
531 uint32_t exist_med;
532 uint32_t new_weight;
533 uint32_t exist_weight;
d62a17ae 534 uint32_t newm, existm;
535 struct in_addr new_id;
536 struct in_addr exist_id;
537 int new_cluster;
538 int exist_cluster;
539 int internal_as_route;
540 int confed_as_route;
04d14c8b 541 int ret = 0;
d62a17ae 542 char new_buf[PATH_ADDPATH_STR_BUFFER];
543 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
544 uint32_t new_mm_seq;
545 uint32_t exist_mm_seq;
6d8c603a 546 int nh_cmp;
d62a17ae 547
548 *paths_eq = 0;
549
550 /* 0. Null check. */
551 if (new == NULL) {
fdf81fa0 552 *reason = bgp_path_selection_none;
d62a17ae 553 if (debug)
554 zlog_debug("%s: new is NULL", pfx_buf);
555 return 0;
556 }
2ec1e66f 557
d62a17ae 558 if (debug)
18ee8310 559 bgp_path_info_path_with_addpath_rx_str(new, new_buf);
718e3744 560
d62a17ae 561 if (exist == NULL) {
fdf81fa0 562 *reason = bgp_path_selection_first;
d62a17ae 563 if (debug)
564 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
565 new_buf);
566 return 1;
567 }
2ec1e66f 568
d62a17ae 569 if (debug) {
18ee8310 570 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
d62a17ae 571 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
572 pfx_buf, new_buf, new->flags, exist_buf,
573 exist->flags);
574 }
8ff56318 575
d62a17ae 576 newattr = new->attr;
577 existattr = exist->attr;
578
579 /* For EVPN routes, we cannot just go by local vs remote, we have to
580 * look at the MAC mobility sequence number, if present.
581 */
582 if (safi == SAFI_EVPN) {
583 /* This is an error condition described in RFC 7432 Section
584 * 15.2. The RFC
585 * states that in this scenario "the PE MUST alert the operator"
586 * but it
587 * does not state what other action to take. In order to provide
588 * some
589 * consistency in this scenario we are going to prefer the path
590 * with the
591 * sticky flag.
592 */
593 if (newattr->sticky != existattr->sticky) {
594 if (!debug) {
9bcb3eef
DS
595 prefix2str(
596 bgp_dest_get_prefix(new->net), pfx_buf,
597 sizeof(*pfx_buf) * PREFIX2STR_BUFFER);
18ee8310
DS
598 bgp_path_info_path_with_addpath_rx_str(new,
599 new_buf);
600 bgp_path_info_path_with_addpath_rx_str(
601 exist, exist_buf);
d62a17ae 602 }
603
604 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 605 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
606 if (debug)
607 zlog_debug(
608 "%s: %s wins over %s due to sticky MAC flag",
609 pfx_buf, new_buf, exist_buf);
d62a17ae 610 return 1;
611 }
612
613 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 614 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
615 if (debug)
616 zlog_debug(
617 "%s: %s loses to %s due to sticky MAC flag",
618 pfx_buf, new_buf, exist_buf);
d62a17ae 619 return 0;
620 }
621 }
128ea8ab 622
d62a17ae 623 new_mm_seq = mac_mobility_seqnum(newattr);
624 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 625
d62a17ae 626 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 627 *reason = bgp_path_selection_evpn_seq;
d62a17ae 628 if (debug)
629 zlog_debug(
630 "%s: %s wins over %s due to MM seq %u > %u",
631 pfx_buf, new_buf, exist_buf, new_mm_seq,
632 exist_mm_seq);
633 return 1;
634 }
8ff56318 635
d62a17ae 636 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 637 *reason = bgp_path_selection_evpn_seq;
d62a17ae 638 if (debug)
639 zlog_debug(
640 "%s: %s loses to %s due to MM seq %u < %u",
641 pfx_buf, new_buf, exist_buf, new_mm_seq,
642 exist_mm_seq);
643 return 0;
644 }
6d8c603a
AK
645
646 /*
647 * if sequence numbers are the same path with the lowest IP
648 * wins
649 */
650 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
651 if (nh_cmp < 0) {
fdf81fa0 652 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
653 if (debug)
654 zlog_debug(
655 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
656 pfx_buf, new_buf, exist_buf, new_mm_seq,
657 inet_ntoa(new->attr->nexthop));
658 return 1;
659 }
660 if (nh_cmp > 0) {
fdf81fa0 661 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
662 if (debug)
663 zlog_debug(
664 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
665 pfx_buf, new_buf, exist_buf, new_mm_seq,
666 inet_ntoa(new->attr->nexthop));
667 return 0;
668 }
d62a17ae 669 }
9fbdd100 670
d62a17ae 671 /* 1. Weight check. */
d62a17ae 672 new_weight = newattr->weight;
673 exist_weight = existattr->weight;
8ff56318 674
d62a17ae 675 if (new_weight > exist_weight) {
fdf81fa0 676 *reason = bgp_path_selection_weight;
d62a17ae 677 if (debug)
678 zlog_debug("%s: %s wins over %s due to weight %d > %d",
679 pfx_buf, new_buf, exist_buf, new_weight,
680 exist_weight);
681 return 1;
682 }
718e3744 683
d62a17ae 684 if (new_weight < exist_weight) {
fdf81fa0 685 *reason = bgp_path_selection_weight;
d62a17ae 686 if (debug)
687 zlog_debug("%s: %s loses to %s due to weight %d < %d",
688 pfx_buf, new_buf, exist_buf, new_weight,
689 exist_weight);
690 return 0;
691 }
9fbdd100 692
d62a17ae 693 /* 2. Local preference check. */
694 new_pref = exist_pref = bgp->default_local_pref;
695
696 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
697 new_pref = newattr->local_pref;
698 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
699 exist_pref = existattr->local_pref;
700
701 if (new_pref > exist_pref) {
fdf81fa0 702 *reason = bgp_path_selection_local_pref;
d62a17ae 703 if (debug)
704 zlog_debug(
705 "%s: %s wins over %s due to localpref %d > %d",
706 pfx_buf, new_buf, exist_buf, new_pref,
707 exist_pref);
708 return 1;
709 }
718e3744 710
d62a17ae 711 if (new_pref < exist_pref) {
fdf81fa0 712 *reason = bgp_path_selection_local_pref;
d62a17ae 713 if (debug)
714 zlog_debug(
715 "%s: %s loses to %s due to localpref %d < %d",
716 pfx_buf, new_buf, exist_buf, new_pref,
717 exist_pref);
718 return 0;
719 }
9fbdd100 720
d62a17ae 721 /* 3. Local route check. We prefer:
722 * - BGP_ROUTE_STATIC
723 * - BGP_ROUTE_AGGREGATE
724 * - BGP_ROUTE_REDISTRIBUTE
725 */
90f4f482 726 if (!(new->sub_type == BGP_ROUTE_NORMAL ||
727 new->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 728 *reason = bgp_path_selection_local_route;
d62a17ae 729 if (debug)
730 zlog_debug(
731 "%s: %s wins over %s due to preferred BGP_ROUTE type",
732 pfx_buf, new_buf, exist_buf);
733 return 1;
734 }
718e3744 735
90f4f482 736 if (!(exist->sub_type == BGP_ROUTE_NORMAL ||
88493076 737 exist->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 738 *reason = bgp_path_selection_local_route;
d62a17ae 739 if (debug)
740 zlog_debug(
741 "%s: %s loses to %s due to preferred BGP_ROUTE type",
742 pfx_buf, new_buf, exist_buf);
743 return 0;
6811845b 744 }
718e3744 745
d62a17ae 746 /* 4. AS path length check. */
892fedb6 747 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 748 int exist_hops = aspath_count_hops(existattr->aspath);
749 int exist_confeds = aspath_count_confeds(existattr->aspath);
750
892fedb6 751 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 752 int aspath_hops;
753
754 aspath_hops = aspath_count_hops(newattr->aspath);
755 aspath_hops += aspath_count_confeds(newattr->aspath);
756
757 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 758 *reason = bgp_path_selection_confed_as_path;
d62a17ae 759 if (debug)
760 zlog_debug(
761 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
762 pfx_buf, new_buf, exist_buf,
763 aspath_hops,
764 (exist_hops + exist_confeds));
765 return 1;
766 }
767
768 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 769 *reason = bgp_path_selection_confed_as_path;
d62a17ae 770 if (debug)
771 zlog_debug(
772 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
773 pfx_buf, new_buf, exist_buf,
774 aspath_hops,
775 (exist_hops + exist_confeds));
776 return 0;
777 }
778 } else {
779 int newhops = aspath_count_hops(newattr->aspath);
780
781 if (newhops < exist_hops) {
fdf81fa0 782 *reason = bgp_path_selection_as_path;
d62a17ae 783 if (debug)
784 zlog_debug(
785 "%s: %s wins over %s due to aspath hopcount %d < %d",
786 pfx_buf, new_buf, exist_buf,
787 newhops, exist_hops);
788 return 1;
789 }
790
791 if (newhops > exist_hops) {
fdf81fa0 792 *reason = bgp_path_selection_as_path;
d62a17ae 793 if (debug)
794 zlog_debug(
795 "%s: %s loses to %s due to aspath hopcount %d > %d",
796 pfx_buf, new_buf, exist_buf,
797 newhops, exist_hops);
798 return 0;
799 }
800 }
801 }
9fbdd100 802
d62a17ae 803 /* 5. Origin check. */
804 if (newattr->origin < existattr->origin) {
fdf81fa0 805 *reason = bgp_path_selection_origin;
d62a17ae 806 if (debug)
807 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
808 pfx_buf, new_buf, exist_buf,
809 bgp_origin_long_str[newattr->origin],
810 bgp_origin_long_str[existattr->origin]);
811 return 1;
812 }
718e3744 813
d62a17ae 814 if (newattr->origin > existattr->origin) {
fdf81fa0 815 *reason = bgp_path_selection_origin;
d62a17ae 816 if (debug)
817 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
818 pfx_buf, new_buf, exist_buf,
819 bgp_origin_long_str[newattr->origin],
820 bgp_origin_long_str[existattr->origin]);
821 return 0;
822 }
718e3744 823
d62a17ae 824 /* 6. MED check. */
825 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
826 && aspath_count_hops(existattr->aspath) == 0);
827 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
828 && aspath_count_confeds(existattr->aspath) > 0
829 && aspath_count_hops(newattr->aspath) == 0
830 && aspath_count_hops(existattr->aspath) == 0);
831
892fedb6
DA
832 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
833 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 834 || aspath_cmp_left(newattr->aspath, existattr->aspath)
835 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
836 || internal_as_route) {
837 new_med = bgp_med_value(new->attr, bgp);
838 exist_med = bgp_med_value(exist->attr, bgp);
839
840 if (new_med < exist_med) {
fdf81fa0 841 *reason = bgp_path_selection_med;
d62a17ae 842 if (debug)
843 zlog_debug(
844 "%s: %s wins over %s due to MED %d < %d",
845 pfx_buf, new_buf, exist_buf, new_med,
846 exist_med);
847 return 1;
848 }
8ff56318 849
d62a17ae 850 if (new_med > exist_med) {
fdf81fa0 851 *reason = bgp_path_selection_med;
d62a17ae 852 if (debug)
853 zlog_debug(
854 "%s: %s loses to %s due to MED %d > %d",
855 pfx_buf, new_buf, exist_buf, new_med,
856 exist_med);
857 return 0;
858 }
859 }
9fbdd100 860
d62a17ae 861 /* 7. Peer type check. */
862 new_sort = new->peer->sort;
863 exist_sort = exist->peer->sort;
864
865 if (new_sort == BGP_PEER_EBGP
866 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 867 *reason = bgp_path_selection_peer;
d62a17ae 868 if (debug)
869 zlog_debug(
870 "%s: %s wins over %s due to eBGP peer > iBGP peer",
871 pfx_buf, new_buf, exist_buf);
872 return 1;
873 }
718e3744 874
d62a17ae 875 if (exist_sort == BGP_PEER_EBGP
876 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 877 *reason = bgp_path_selection_peer;
d62a17ae 878 if (debug)
879 zlog_debug(
880 "%s: %s loses to %s due to iBGP peer < eBGP peer",
881 pfx_buf, new_buf, exist_buf);
882 return 0;
883 }
8ff56318 884
d62a17ae 885 /* 8. IGP metric check. */
886 newm = existm = 0;
8ff56318 887
d62a17ae 888 if (new->extra)
889 newm = new->extra->igpmetric;
890 if (exist->extra)
891 existm = exist->extra->igpmetric;
9fbdd100 892
d62a17ae 893 if (newm < existm) {
894 if (debug)
895 zlog_debug(
896 "%s: %s wins over %s due to IGP metric %d < %d",
897 pfx_buf, new_buf, exist_buf, newm, existm);
898 ret = 1;
899 }
718e3744 900
d62a17ae 901 if (newm > existm) {
902 if (debug)
903 zlog_debug(
904 "%s: %s loses to %s due to IGP metric %d > %d",
905 pfx_buf, new_buf, exist_buf, newm, existm);
906 ret = 0;
5e242b0d 907 }
5e242b0d 908
d62a17ae 909 /* 9. Same IGP metric. Compare the cluster list length as
910 representative of IGP hops metric. Rewrite the metric value
911 pair (newm, existm) with the cluster list length. Prefer the
912 path with smaller cluster list length. */
913 if (newm == existm) {
bf0d28dc
DS
914 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
915 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
d62a17ae 916 && (mpath_cfg == NULL
917 || CHECK_FLAG(
918 mpath_cfg->ibgp_flags,
919 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
920 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
921 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
922
923 if (newm < existm) {
924 if (debug)
925 zlog_debug(
926 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
927 pfx_buf, new_buf, exist_buf,
928 newm, existm);
929 ret = 1;
930 }
931
932 if (newm > existm) {
933 if (debug)
934 zlog_debug(
935 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
936 pfx_buf, new_buf, exist_buf,
937 newm, existm);
938 ret = 0;
939 }
940 }
941 }
31a4638f 942
d62a17ae 943 /* 10. confed-external vs. confed-internal */
944 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
945 if (new_sort == BGP_PEER_CONFED
946 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 947 *reason = bgp_path_selection_confed;
d62a17ae 948 if (debug)
949 zlog_debug(
950 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
951 pfx_buf, new_buf, exist_buf);
952 return 1;
953 }
718e3744 954
d62a17ae 955 if (exist_sort == BGP_PEER_CONFED
956 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 957 *reason = bgp_path_selection_confed;
d62a17ae 958 if (debug)
959 zlog_debug(
960 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
961 pfx_buf, new_buf, exist_buf);
962 return 0;
963 }
964 }
718e3744 965
d62a17ae 966 /* 11. Maximum path check. */
967 if (newm == existm) {
968 /* If one path has a label but the other does not, do not treat
969 * them as equals for multipath
970 */
a4d82a8a 971 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 972 != (exist->extra
b57ba6d2 973 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 974 if (debug)
975 zlog_debug(
976 "%s: %s and %s cannot be multipath, one has a label while the other does not",
977 pfx_buf, new_buf, exist_buf);
892fedb6
DA
978 } else if (CHECK_FLAG(bgp->flags,
979 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 980
981 /*
982 * For the two paths, all comparison steps till IGP
983 * metric
984 * have succeeded - including AS_PATH hop count. Since
985 * 'bgp
986 * bestpath as-path multipath-relax' knob is on, we
987 * don't need
988 * an exact match of AS_PATH. Thus, mark the paths are
989 * equal.
990 * That will trigger both these paths to get into the
991 * multipath
992 * array.
993 */
994 *paths_eq = 1;
995
996 if (debug)
997 zlog_debug(
998 "%s: %s and %s are equal via multipath-relax",
999 pfx_buf, new_buf, exist_buf);
1000 } else if (new->peer->sort == BGP_PEER_IBGP) {
1001 if (aspath_cmp(new->attr->aspath,
1002 exist->attr->aspath)) {
1003 *paths_eq = 1;
1004
1005 if (debug)
1006 zlog_debug(
1007 "%s: %s and %s are equal via matching aspaths",
1008 pfx_buf, new_buf, exist_buf);
1009 }
1010 } else if (new->peer->as == exist->peer->as) {
1011 *paths_eq = 1;
1012
1013 if (debug)
1014 zlog_debug(
1015 "%s: %s and %s are equal via same remote-as",
1016 pfx_buf, new_buf, exist_buf);
1017 }
1018 } else {
1019 /*
1020 * TODO: If unequal cost ibgp multipath is enabled we can
1021 * mark the paths as equal here instead of returning
1022 */
1023 if (debug) {
1024 if (ret == 1)
1025 zlog_debug(
1026 "%s: %s wins over %s after IGP metric comparison",
1027 pfx_buf, new_buf, exist_buf);
1028 else
1029 zlog_debug(
1030 "%s: %s loses to %s after IGP metric comparison",
1031 pfx_buf, new_buf, exist_buf);
1032 }
fdf81fa0 1033 *reason = bgp_path_selection_igp_metric;
d62a17ae 1034 return ret;
1035 }
718e3744 1036
d62a17ae 1037 /* 12. If both paths are external, prefer the path that was received
1038 first (the oldest one). This step minimizes route-flap, since a
1039 newer path won't displace an older one, even if it was the
1040 preferred route based on the additional decision criteria below. */
892fedb6 1041 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1042 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1043 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1044 *reason = bgp_path_selection_older;
d62a17ae 1045 if (debug)
1046 zlog_debug(
1047 "%s: %s wins over %s due to oldest external",
1048 pfx_buf, new_buf, exist_buf);
1049 return 1;
1050 }
9fbdd100 1051
1defdda8 1052 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1053 *reason = bgp_path_selection_older;
d62a17ae 1054 if (debug)
1055 zlog_debug(
1056 "%s: %s loses to %s due to oldest external",
1057 pfx_buf, new_buf, exist_buf);
1058 return 0;
1059 }
1060 }
718e3744 1061
d62a17ae 1062 /* 13. Router-ID comparision. */
1063 /* If one of the paths is "stale", the corresponding peer router-id will
1064 * be 0 and would always win over the other path. If originator id is
1065 * used for the comparision, it will decide which path is better.
1066 */
1067 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1068 new_id.s_addr = newattr->originator_id.s_addr;
1069 else
1070 new_id.s_addr = new->peer->remote_id.s_addr;
1071 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1072 exist_id.s_addr = existattr->originator_id.s_addr;
1073 else
1074 exist_id.s_addr = exist->peer->remote_id.s_addr;
1075
1076 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1077 *reason = bgp_path_selection_router_id;
d62a17ae 1078 if (debug)
1079 zlog_debug(
1080 "%s: %s wins over %s due to Router-ID comparison",
1081 pfx_buf, new_buf, exist_buf);
1082 return 1;
1083 }
718e3744 1084
d62a17ae 1085 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1086 *reason = bgp_path_selection_router_id;
d62a17ae 1087 if (debug)
1088 zlog_debug(
1089 "%s: %s loses to %s due to Router-ID comparison",
1090 pfx_buf, new_buf, exist_buf);
1091 return 0;
1092 }
9fbdd100 1093
d62a17ae 1094 /* 14. Cluster length comparision. */
1095 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1096 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1097
1098 if (new_cluster < exist_cluster) {
fdf81fa0 1099 *reason = bgp_path_selection_cluster_length;
d62a17ae 1100 if (debug)
1101 zlog_debug(
1102 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1103 pfx_buf, new_buf, exist_buf, new_cluster,
1104 exist_cluster);
1105 return 1;
1106 }
718e3744 1107
d62a17ae 1108 if (new_cluster > exist_cluster) {
fdf81fa0 1109 *reason = bgp_path_selection_cluster_length;
d62a17ae 1110 if (debug)
1111 zlog_debug(
1112 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1113 pfx_buf, new_buf, exist_buf, new_cluster,
1114 exist_cluster);
1115 return 0;
1116 }
9fbdd100 1117
d62a17ae 1118 /* 15. Neighbor address comparision. */
1119 /* Do this only if neither path is "stale" as stale paths do not have
1120 * valid peer information (as the connection may or may not be up).
1121 */
1defdda8 1122 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1123 *reason = bgp_path_selection_stale;
d62a17ae 1124 if (debug)
1125 zlog_debug(
1126 "%s: %s wins over %s due to latter path being STALE",
1127 pfx_buf, new_buf, exist_buf);
1128 return 1;
1129 }
0de5153c 1130
1defdda8 1131 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1132 *reason = bgp_path_selection_stale;
d62a17ae 1133 if (debug)
1134 zlog_debug(
1135 "%s: %s loses to %s due to former path being STALE",
1136 pfx_buf, new_buf, exist_buf);
1137 return 0;
1138 }
718e3744 1139
d62a17ae 1140 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1141 if (new->peer->su_remote == NULL) {
1142 *reason = bgp_path_selection_local_configured;
d62a17ae 1143 return 0;
fdf81fa0
DS
1144 }
1145 if (exist->peer->su_remote == NULL) {
1146 *reason = bgp_path_selection_local_configured;
d62a17ae 1147 return 1;
fdf81fa0 1148 }
9fbdd100 1149
d62a17ae 1150 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1151
1152 if (ret == 1) {
fdf81fa0 1153 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1154 if (debug)
1155 zlog_debug(
1156 "%s: %s loses to %s due to Neighor IP comparison",
1157 pfx_buf, new_buf, exist_buf);
1158 return 0;
1159 }
1160
1161 if (ret == -1) {
fdf81fa0 1162 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1163 if (debug)
1164 zlog_debug(
1165 "%s: %s wins over %s due to Neighor IP comparison",
1166 pfx_buf, new_buf, exist_buf);
1167 return 1;
1168 }
9fbdd100 1169
fdf81fa0 1170 *reason = bgp_path_selection_default;
d62a17ae 1171 if (debug)
1172 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1173 pfx_buf, new_buf, exist_buf);
718e3744 1174
d62a17ae 1175 return 1;
718e3744 1176}
1177
65efcfce
LB
1178/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1179 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1180 * multipath is enabled
65efcfce 1181 * This version is compatible with */
18ee8310
DS
1182int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1183 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1184 afi_t afi, safi_t safi,
1185 enum bgp_path_selection_reason *reason)
d62a17ae 1186{
1187 int paths_eq;
1188 int ret;
18ee8310 1189 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1190 afi, safi, reason);
d62a17ae 1191
1192 if (paths_eq)
1193 ret = 0;
1194 else {
1195 if (ret == 1)
1196 ret = -1;
1197 else
1198 ret = 1;
1199 }
1200 return ret;
65efcfce
LB
1201}
1202
5a1ae2c2
DS
1203static enum filter_type bgp_input_filter(struct peer *peer,
1204 const struct prefix *p,
d62a17ae 1205 struct attr *attr, afi_t afi,
1206 safi_t safi)
718e3744 1207{
d62a17ae 1208 struct bgp_filter *filter;
718e3744 1209
d62a17ae 1210 filter = &peer->filter[afi][safi];
718e3744 1211
d62a17ae 1212#define FILTER_EXIST_WARN(F, f, filter) \
1213 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1214 zlog_debug("%s: Could not find configured input %s-list %s!", \
1215 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1216
1217 if (DISTRIBUTE_IN_NAME(filter)) {
1218 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1219
1220 if (access_list_apply(DISTRIBUTE_IN(filter), p) == FILTER_DENY)
1221 return FILTER_DENY;
1222 }
1223
1224 if (PREFIX_LIST_IN_NAME(filter)) {
1225 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1226
1227 if (prefix_list_apply(PREFIX_LIST_IN(filter), p) == PREFIX_DENY)
1228 return FILTER_DENY;
1229 }
1230
1231 if (FILTER_LIST_IN_NAME(filter)) {
1232 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1233
1234 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
1235 == AS_FILTER_DENY)
1236 return FILTER_DENY;
1237 }
1238
1239 return FILTER_PERMIT;
650f76c2 1240#undef FILTER_EXIST_WARN
718e3744 1241}
1242
b8685f9b
DS
1243static enum filter_type bgp_output_filter(struct peer *peer,
1244 const struct prefix *p,
d62a17ae 1245 struct attr *attr, afi_t afi,
1246 safi_t safi)
718e3744 1247{
d62a17ae 1248 struct bgp_filter *filter;
1249
1250 filter = &peer->filter[afi][safi];
1251
1252#define FILTER_EXIST_WARN(F, f, filter) \
1253 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1254 zlog_debug("%s: Could not find configured output %s-list %s!", \
1255 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1256
d62a17ae 1257 if (DISTRIBUTE_OUT_NAME(filter)) {
1258 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1259
d62a17ae 1260 if (access_list_apply(DISTRIBUTE_OUT(filter), p) == FILTER_DENY)
1261 return FILTER_DENY;
1262 }
1263
1264 if (PREFIX_LIST_OUT_NAME(filter)) {
1265 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1266
d62a17ae 1267 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
1268 == PREFIX_DENY)
1269 return FILTER_DENY;
1270 }
718e3744 1271
d62a17ae 1272 if (FILTER_LIST_OUT_NAME(filter)) {
1273 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1274
d62a17ae 1275 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
1276 == AS_FILTER_DENY)
1277 return FILTER_DENY;
1278 }
718e3744 1279
d62a17ae 1280 return FILTER_PERMIT;
650f76c2 1281#undef FILTER_EXIST_WARN
718e3744 1282}
1283
1284/* If community attribute includes no_export then return 1. */
3dc339cd 1285static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1286{
1287 if (attr->community) {
1288 /* NO_ADVERTISE check. */
1289 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
3dc339cd 1290 return true;
d62a17ae 1291
1292 /* NO_EXPORT check. */
1293 if (peer->sort == BGP_PEER_EBGP
1294 && community_include(attr->community, COMMUNITY_NO_EXPORT))
3dc339cd 1295 return true;
d62a17ae 1296
1297 /* NO_EXPORT_SUBCONFED check. */
1298 if (peer->sort == BGP_PEER_EBGP
1299 || peer->sort == BGP_PEER_CONFED)
1300 if (community_include(attr->community,
1301 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1302 return true;
d62a17ae 1303 }
3dc339cd 1304 return false;
718e3744 1305}
1306
1307/* Route reflection loop check. */
3dc339cd 1308static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1309{
d62a17ae 1310 struct in_addr cluster_id;
718e3744 1311
d62a17ae 1312 if (attr->cluster) {
1313 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1314 cluster_id = peer->bgp->cluster_id;
1315 else
1316 cluster_id = peer->bgp->router_id;
1317
1318 if (cluster_loop_check(attr->cluster, cluster_id))
3dc339cd 1319 return true;
d62a17ae 1320 }
3dc339cd 1321 return false;
718e3744 1322}
6b0655a2 1323
5a1ae2c2 1324static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1325 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1326 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1327 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1328{
d62a17ae 1329 struct bgp_filter *filter;
82b692c0
LK
1330 struct bgp_path_info rmap_path = { 0 };
1331 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1332 route_map_result_t ret;
1333 struct route_map *rmap = NULL;
718e3744 1334
d62a17ae 1335 filter = &peer->filter[afi][safi];
718e3744 1336
d62a17ae 1337 /* Apply default weight value. */
1338 if (peer->weight[afi][safi])
1339 attr->weight = peer->weight[afi][safi];
718e3744 1340
d62a17ae 1341 if (rmap_name) {
1342 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1343
d62a17ae 1344 if (rmap == NULL)
1345 return RMAP_DENY;
1346 } else {
1347 if (ROUTE_MAP_IN_NAME(filter)) {
1348 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1349
d62a17ae 1350 if (rmap == NULL)
1351 return RMAP_DENY;
1352 }
1353 }
0b16f239 1354
d62a17ae 1355 /* Route map apply. */
1356 if (rmap) {
40381db7 1357 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1358 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1359 rmap_path.peer = peer;
1360 rmap_path.attr = attr;
82b692c0 1361 rmap_path.extra = &extra;
9bcb3eef 1362 rmap_path.net = dest;
196c6b09 1363
82b692c0
LK
1364 extra.num_labels = num_labels;
1365 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1366 memcpy(extra.label, label,
1367 num_labels * sizeof(mpls_label_t));
718e3744 1368
d62a17ae 1369 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1370
d62a17ae 1371 /* Apply BGP route map to the attribute. */
40381db7 1372 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
0b16f239 1373
d62a17ae 1374 peer->rmap_type = 0;
0b16f239 1375
1f2263be 1376 if (ret == RMAP_DENYMATCH)
d62a17ae 1377 return RMAP_DENY;
0b16f239 1378 }
d62a17ae 1379 return RMAP_PERMIT;
0b16f239
DS
1380}
1381
5f040085 1382static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1383 struct attr *attr, afi_t afi, safi_t safi,
1384 const char *rmap_name)
0b16f239 1385{
40381db7 1386 struct bgp_path_info rmap_path;
d62a17ae 1387 route_map_result_t ret;
1388 struct route_map *rmap = NULL;
d7c0a89a 1389 uint8_t rmap_type;
0b16f239 1390
b787157a
DS
1391 /*
1392 * So if we get to this point and have no rmap_name
1393 * we want to just show the output as it currently
1394 * exists.
1395 */
1396 if (!rmap_name)
1397 return RMAP_PERMIT;
0b16f239 1398
d62a17ae 1399 /* Apply default weight value. */
1400 if (peer->weight[afi][safi])
1401 attr->weight = peer->weight[afi][safi];
0b16f239 1402
b787157a 1403 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1404
b787157a
DS
1405 /*
1406 * If we have a route map name and we do not find
1407 * the routemap that means we have an implicit
1408 * deny.
1409 */
1410 if (rmap == NULL)
1411 return RMAP_DENY;
0b16f239 1412
40381db7 1413 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1414 /* Route map apply. */
b787157a 1415 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1416 rmap_path.peer = peer;
1417 rmap_path.attr = attr;
0b16f239 1418
0f672529 1419 rmap_type = peer->rmap_type;
b787157a 1420 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1421
b787157a 1422 /* Apply BGP route map to the attribute. */
40381db7 1423 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
ac41b2a2 1424
0f672529 1425 peer->rmap_type = rmap_type;
b787157a
DS
1426
1427 if (ret == RMAP_DENYMATCH)
1428 /*
1429 * caller has multiple error paths with bgp_attr_flush()
1430 */
1431 return RMAP_DENY;
ac41b2a2 1432
d62a17ae 1433 return RMAP_PERMIT;
718e3744 1434}
6b0655a2 1435
5000f21c 1436/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1437static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1438 struct peer *peer, struct attr *attr)
1439{
1440 if (peer->sort == BGP_PEER_EBGP
1441 && (peer_af_flag_check(peer, afi, safi,
1442 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1443 || peer_af_flag_check(peer, afi, safi,
1444 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1445 || peer_af_flag_check(peer, afi, safi,
1446 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1447 || peer_af_flag_check(peer, afi, safi,
1448 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1449 // Take action on the entire aspath
1450 if (peer_af_flag_check(peer, afi, safi,
1451 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1452 || peer_af_flag_check(peer, afi, safi,
1453 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1454 if (peer_af_flag_check(
1455 peer, afi, safi,
1456 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1457 attr->aspath = aspath_replace_private_asns(
bf26b80e 1458 attr->aspath, bgp->as, peer->as);
d62a17ae 1459
1460 // The entire aspath consists of private ASNs so create
1461 // an empty aspath
1462 else if (aspath_private_as_check(attr->aspath))
1463 attr->aspath = aspath_empty_get();
1464
1465 // There are some public and some private ASNs, remove
1466 // the private ASNs
1467 else
1468 attr->aspath = aspath_remove_private_asns(
bf26b80e 1469 attr->aspath, peer->as);
d62a17ae 1470 }
1471
1472 // 'all' was not specified so the entire aspath must be private
1473 // ASNs
1474 // for us to do anything
1475 else if (aspath_private_as_check(attr->aspath)) {
1476 if (peer_af_flag_check(
1477 peer, afi, safi,
1478 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1479 attr->aspath = aspath_replace_private_asns(
bf26b80e 1480 attr->aspath, bgp->as, peer->as);
d62a17ae 1481 else
1482 attr->aspath = aspath_empty_get();
1483 }
1484 }
5000f21c
DS
1485}
1486
c7122e14 1487/* If this is an EBGP peer with as-override */
d62a17ae 1488static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1489 struct peer *peer, struct attr *attr)
1490{
1491 if (peer->sort == BGP_PEER_EBGP
1492 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1493 if (aspath_single_asn_check(attr->aspath, peer->as))
1494 attr->aspath = aspath_replace_specific_asn(
1495 attr->aspath, peer->as, bgp->as);
1496 }
1497}
1498
7f323236
DW
1499void bgp_attr_add_gshut_community(struct attr *attr)
1500{
1501 struct community *old;
1502 struct community *new;
1503 struct community *merge;
1504 struct community *gshut;
1505
1506 old = attr->community;
1507 gshut = community_str2com("graceful-shutdown");
1508
990f4f91 1509 assert(gshut);
1510
7f323236
DW
1511 if (old) {
1512 merge = community_merge(community_dup(old), gshut);
1513
a4d82a8a 1514 if (old->refcnt == 0)
3c1f53de 1515 community_free(&old);
7f323236
DW
1516
1517 new = community_uniq_sort(merge);
3c1f53de 1518 community_free(&merge);
7f323236
DW
1519 } else {
1520 new = community_dup(gshut);
1521 }
1522
3c1f53de 1523 community_free(&gshut);
7f323236
DW
1524 attr->community = new;
1525 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1526
1527 /* When we add the graceful-shutdown community we must also
1528 * lower the local-preference */
1529 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1530 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1531}
1532
1533
d7c0a89a 1534static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1535{
960035b2 1536 if (family == AF_INET) {
975a328e
DA
1537 attr->nexthop.s_addr = INADDR_ANY;
1538 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1539 }
d62a17ae 1540 if (family == AF_INET6)
1541 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1542 if (family == AF_EVPN)
1543 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1544}
1545
9bcb3eef 1546bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b
DS
1547 struct update_subgroup *subgrp,
1548 const struct prefix *p, struct attr *attr)
d62a17ae 1549{
1550 struct bgp_filter *filter;
1551 struct peer *from;
1552 struct peer *peer;
1553 struct peer *onlypeer;
1554 struct bgp *bgp;
40381db7 1555 struct attr *piattr;
d62a17ae 1556 char buf[PREFIX_STRLEN];
b68885f9 1557 route_map_result_t ret;
d62a17ae 1558 int transparent;
1559 int reflect;
1560 afi_t afi;
1561 safi_t safi;
1562 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1563 bool nh_reset = false;
1564 uint64_t cum_bw;
d62a17ae 1565
1566 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1567 return false;
d62a17ae 1568
1569 afi = SUBGRP_AFI(subgrp);
1570 safi = SUBGRP_SAFI(subgrp);
1571 peer = SUBGRP_PEER(subgrp);
1572 onlypeer = NULL;
1573 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1574 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1575
40381db7 1576 from = pi->peer;
d62a17ae 1577 filter = &peer->filter[afi][safi];
1578 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1579 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1580 : pi->attr;
3f9c7369 1581
49e5a4a0 1582#ifdef ENABLE_BGP_VNC
d62a17ae 1583 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1584 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1585 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1586
1587 /*
1588 * direct and direct_ext type routes originate internally even
1589 * though they can have peer pointers that reference other
1590 * systems
1591 */
1592 prefix2str(p, buf, PREFIX_STRLEN);
1593 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1594 __func__, buf);
1595 samepeer_safe = 1;
1596 }
65efcfce
LB
1597#endif
1598
ddb5b488
PZ
1599 if (((afi == AFI_IP) || (afi == AFI_IP6))
1600 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1601 && (pi->type == ZEBRA_ROUTE_BGP)
1602 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1603
1604 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1605
1606 samepeer_safe = 1;
1607 }
1608
d62a17ae 1609 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1610 * pi is valid */
1611 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1612 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1613 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1614 return false;
d62a17ae 1615 }
adbac85e 1616
d62a17ae 1617 /* If this is not the bestpath then check to see if there is an enabled
1618 * addpath
1619 * feature that requires us to advertise it */
40381db7 1620 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1621 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1622 return false;
d62a17ae 1623 }
1624 }
06370dac 1625
d62a17ae 1626 /* Aggregate-address suppress check. */
40381db7 1627 if (pi->extra && pi->extra->suppress)
d62a17ae 1628 if (!UNSUPPRESS_MAP_NAME(filter)) {
3dc339cd 1629 return false;
d62a17ae 1630 }
3f9c7369 1631
13b7e7f0
DS
1632 /*
1633 * If we are doing VRF 2 VRF leaking via the import
1634 * statement, we want to prevent the route going
1635 * off box as that the RT and RD created are localy
1636 * significant and globaly useless.
1637 */
40381db7
DS
1638 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1639 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1640 return false;
13b7e7f0 1641
d62a17ae 1642 /* If it's labeled safi, make sure the route has a valid label. */
1643 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1644 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1645 if (!bgp_is_valid_label(&label)) {
1646 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1647 zlog_debug("u%" PRIu64 ":s%" PRIu64
1648 " %s/%d is filtered - no label (%p)",
1649 subgrp->update_group->id, subgrp->id,
1650 inet_ntop(p->family, &p->u.prefix,
1651 buf, SU_ADDRSTRLEN),
1652 p->prefixlen, &label);
3dc339cd 1653 return false;
d62a17ae 1654 }
1655 }
cd1964ff 1656
d62a17ae 1657 /* Do not send back route to sender. */
1658 if (onlypeer && from == onlypeer) {
3dc339cd 1659 return false;
d62a17ae 1660 }
3f9c7369 1661
d62a17ae 1662 /* Do not send the default route in the BGP table if the neighbor is
1663 * configured for default-originate */
1664 if (CHECK_FLAG(peer->af_flags[afi][safi],
1665 PEER_FLAG_DEFAULT_ORIGINATE)) {
1666 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1667 return false;
d62a17ae 1668 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1669 return false;
d62a17ae 1670 }
4125bb67 1671
d62a17ae 1672 /* Transparency check. */
1673 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1674 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1675 transparent = 1;
1676 else
1677 transparent = 0;
1678
1679 /* If community is not disabled check the no-export and local. */
40381db7 1680 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1681 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1682 zlog_debug(
1683 "subgrpannouncecheck: community filter check fail");
3dc339cd 1684 return false;
d62a17ae 1685 }
3f9c7369 1686
d62a17ae 1687 /* If the attribute has originator-id and it is same as remote
1688 peer's id. */
40381db7
DS
1689 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1690 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1691 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1692 zlog_debug(
3efd0893 1693 "%s [Update:SEND] %s originator-id is same as remote router-id",
d62a17ae 1694 onlypeer->host,
1695 prefix2str(p, buf, sizeof(buf)));
3dc339cd 1696 return false;
d62a17ae 1697 }
3f9c7369 1698
d62a17ae 1699 /* ORF prefix-list filter check */
1700 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1701 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1702 || CHECK_FLAG(peer->af_cap[afi][safi],
1703 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1704 if (peer->orf_plist[afi][safi]) {
1705 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1706 == PREFIX_DENY) {
1707 if (bgp_debug_update(NULL, p,
1708 subgrp->update_group, 0))
1709 zlog_debug(
1710 "%s [Update:SEND] %s is filtered via ORF",
1711 peer->host,
1712 prefix2str(p, buf,
1713 sizeof(buf)));
3dc339cd 1714 return false;
d62a17ae 1715 }
1716 }
1717
1718 /* Output filter check. */
40381db7 1719 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1720 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1721 zlog_debug("%s [Update:SEND] %s is filtered",
1722 peer->host, prefix2str(p, buf, sizeof(buf)));
3dc339cd 1723 return false;
d62a17ae 1724 }
3f9c7369 1725
d62a17ae 1726 /* AS path loop check. */
2b31007c
RZ
1727 if (onlypeer && onlypeer->as_path_loop_detection
1728 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1729 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1730 zlog_debug(
3efd0893 1731 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 1732 onlypeer->host, onlypeer->as);
3dc339cd 1733 return false;
d62a17ae 1734 }
3f9c7369 1735
d62a17ae 1736 /* If we're a CONFED we need to loop check the CONFED ID too */
1737 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1738 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1739 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1740 zlog_debug(
3efd0893 1741 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 1742 peer->host, bgp->confed_id);
3dc339cd 1743 return false;
d62a17ae 1744 }
3f9c7369 1745 }
3f9c7369 1746
d62a17ae 1747 /* Route-Reflect check. */
1748 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1749 reflect = 1;
1750 else
1751 reflect = 0;
1752
1753 /* IBGP reflection check. */
1754 if (reflect && !samepeer_safe) {
1755 /* A route from a Client peer. */
1756 if (CHECK_FLAG(from->af_flags[afi][safi],
1757 PEER_FLAG_REFLECTOR_CLIENT)) {
1758 /* Reflect to all the Non-Client peers and also to the
1759 Client peers other than the originator. Originator
1760 check
1761 is already done. So there is noting to do. */
1762 /* no bgp client-to-client reflection check. */
892fedb6
DA
1763 if (CHECK_FLAG(bgp->flags,
1764 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 1765 if (CHECK_FLAG(peer->af_flags[afi][safi],
1766 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1767 return false;
d62a17ae 1768 } else {
1769 /* A route from a Non-client peer. Reflect to all other
1770 clients. */
1771 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1772 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1773 return false;
d62a17ae 1774 }
1775 }
3f9c7369 1776
d62a17ae 1777 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1778 *attr = *piattr;
d62a17ae 1779
1780 /* If local-preference is not set. */
1781 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1782 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1783 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1784 attr->local_pref = bgp->default_local_pref;
3f9c7369 1785 }
3f9c7369 1786
d62a17ae 1787 /* If originator-id is not set and the route is to be reflected,
1788 set the originator id */
1789 if (reflect
1790 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1791 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1792 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1793 }
3f9c7369 1794
d62a17ae 1795 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1796 */
1797 if (peer->sort == BGP_PEER_EBGP
1798 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1799 if (from != bgp->peer_self && !transparent
1800 && !CHECK_FLAG(peer->af_flags[afi][safi],
1801 PEER_FLAG_MED_UNCHANGED))
1802 attr->flag &=
1803 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1804 }
3f9c7369 1805
d62a17ae 1806 /* Since the nexthop attribute can vary per peer, it is not explicitly
1807 * set
1808 * in announce check, only certain flags and length (or number of
1809 * nexthops
1810 * -- for IPv6/MP_REACH) are set here in order to guide the update
1811 * formation
1812 * code in setting the nexthop(s) on a per peer basis in
1813 * reformat_peer().
1814 * Typically, the source nexthop in the attribute is preserved but in
1815 * the
1816 * scenarios where we know it will always be overwritten, we reset the
1817 * nexthop to "0" in an attempt to achieve better Update packing. An
1818 * example of this is when a prefix from each of 2 IBGP peers needs to
1819 * be
1820 * announced to an EBGP peer (and they have the same attributes barring
1821 * their nexthop).
1822 */
1823 if (reflect)
1824 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1825
1826#define NEXTHOP_IS_V6 \
1827 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1828 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1829 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1830 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1831
1832 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1833 * if
1834 * the peer (group) is configured to receive link-local nexthop
1835 * unchanged
c728d027
DA
1836 * and it is available in the prefix OR we're not reflecting the route,
1837 * link-local nexthop address is valid and
d62a17ae 1838 * the peer (group) to whom we're going to announce is on a shared
1839 * network
1840 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
1841 * By checking if nexthop LL address is valid we are sure that
1842 * we do not announce LL address as `::`.
d62a17ae 1843 */
1844 if (NEXTHOP_IS_V6) {
1845 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
1846 if ((CHECK_FLAG(peer->af_flags[afi][safi],
1847 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
1848 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
1849 || (!reflect
1850 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
1851 && peer->shared_network
d62a17ae 1852 && (from == bgp->peer_self
1853 || peer->sort == BGP_PEER_EBGP))) {
1854 attr->mp_nexthop_len =
1855 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
1856 }
3f9c7369 1857
d62a17ae 1858 /* Clear off link-local nexthop in source, whenever it is not
1859 * needed to
1860 * ensure more prefixes share the same attribute for
1861 * announcement.
1862 */
1863 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
1864 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
1865 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
1866 }
3f9c7369 1867
d62a17ae 1868 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
1869 bgp_peer_as_override(bgp, afi, safi, peer, attr);
1870
1871 /* Route map & unsuppress-map apply. */
40381db7 1872 if (ROUTE_MAP_OUT_NAME(filter) || (pi->extra && pi->extra->suppress)) {
b8694ef4
DS
1873 struct bgp_path_info rmap_path = {0};
1874 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
1875 struct attr dummy_attr = {0};
d62a17ae 1876
e34291b8 1877 /* Fill temp path_info */
9bcb3eef
DS
1878 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
1879 pi, peer, attr);
16f7ce2b 1880
d62a17ae 1881 /* don't confuse inbound and outbound setting */
1882 RESET_FLAG(attr->rmap_change_flags);
1883
1884 /*
1885 * The route reflector is not allowed to modify the attributes
1886 * of the reflected IBGP routes unless explicitly allowed.
1887 */
1888 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
1889 && !CHECK_FLAG(bgp->flags,
1890 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 1891 dummy_attr = *attr;
40381db7 1892 rmap_path.attr = &dummy_attr;
d62a17ae 1893 }
3f9c7369 1894
d62a17ae 1895 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 1896
40381db7 1897 if (pi->extra && pi->extra->suppress)
d62a17ae 1898 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
40381db7 1899 RMAP_BGP, &rmap_path);
d62a17ae 1900 else
1901 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
40381db7 1902 RMAP_BGP, &rmap_path);
d62a17ae 1903
1904 peer->rmap_type = 0;
1905
1906 if (ret == RMAP_DENYMATCH) {
778048bf
AD
1907 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1908 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1909 peer->host, prefix2str(p, buf, sizeof(buf)));
1910
d62a17ae 1911 bgp_attr_flush(attr);
3dc339cd 1912 return false;
d62a17ae 1913 }
3f9c7369 1914 }
3f9c7369 1915
9dac9fc8
DA
1916 /* RFC 8212 to prevent route leaks.
1917 * This specification intends to improve this situation by requiring the
1918 * explicit configuration of both BGP Import and Export Policies for any
1919 * External BGP (EBGP) session such as customers, peers, or
1920 * confederation boundaries for all enabled address families. Through
1921 * codification of the aforementioned requirement, operators will
1922 * benefit from consistent behavior across different BGP
1923 * implementations.
1924 */
1d3fdccf 1925 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
9dac9fc8 1926 if (!bgp_outbound_policy_exists(peer, filter))
3dc339cd 1927 return false;
9dac9fc8 1928
fb29348a
DA
1929 /* draft-ietf-idr-deprecate-as-set-confed-set
1930 * Filter routes having AS_SET or AS_CONFED_SET in the path.
1931 * Eventually, This document (if approved) updates RFC 4271
1932 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
1933 * and obsoletes RFC 6472.
1934 */
7f972cd8 1935 if (peer->bgp->reject_as_sets)
fb29348a 1936 if (aspath_check_as_sets(attr->aspath))
3dc339cd 1937 return false;
fb29348a 1938
33d022bc
DA
1939 /* Codification of AS 0 Processing */
1940 if (aspath_check_as_zero(attr->aspath))
e2369003 1941 return false;
33d022bc 1942
892fedb6 1943 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
a4d82a8a
PZ
1944 if (peer->sort == BGP_PEER_IBGP
1945 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
1946 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1947 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1948 } else {
1949 bgp_attr_add_gshut_community(attr);
1950 }
1951 }
1952
d62a17ae 1953 /* After route-map has been applied, we check to see if the nexthop to
1954 * be carried in the attribute (that is used for the announcement) can
1955 * be cleared off or not. We do this in all cases where we would be
1956 * setting the nexthop to "ourselves". For IPv6, we only need to
1957 * consider
1958 * the global nexthop here; the link-local nexthop would have been
1959 * cleared
1960 * already, and if not, it is required by the update formation code.
1961 * Also see earlier comments in this function.
1962 */
1963 /*
1964 * If route-map has performed some operation on the nexthop or the peer
1965 * configuration says to pass it unchanged, we cannot reset the nexthop
1966 * here, so only attempt to do it if these aren't true. Note that the
1967 * route-map handler itself might have cleared the nexthop, if for
1968 * example,
1969 * it is configured as 'peer-address'.
1970 */
1971 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 1972 piattr->rmap_change_flags)
d62a17ae 1973 && !transparent
1974 && !CHECK_FLAG(peer->af_flags[afi][safi],
1975 PEER_FLAG_NEXTHOP_UNCHANGED)) {
1976 /* We can reset the nexthop, if setting (or forcing) it to
1977 * 'self' */
1978 if (CHECK_FLAG(peer->af_flags[afi][safi],
1979 PEER_FLAG_NEXTHOP_SELF)
1980 || CHECK_FLAG(peer->af_flags[afi][safi],
1981 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
1982 if (!reflect
1983 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 1984 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 1985 subgroup_announce_reset_nhop(
1986 (peer_cap_enhe(peer, afi, safi)
1987 ? AF_INET6
1988 : p->family),
1989 attr);
7b651a32 1990 nh_reset = true;
1991 }
d62a17ae 1992 } else if (peer->sort == BGP_PEER_EBGP) {
1993 /* Can also reset the nexthop if announcing to EBGP, but
1994 * only if
1995 * no peer in the subgroup is on a shared subnet.
1996 * Note: 3rd party nexthop currently implemented for
1997 * IPv4 only.
1998 */
737af885
BS
1999 if ((p->family == AF_INET) &&
2000 (!bgp_subgrp_multiaccess_check_v4(
2001 piattr->nexthop,
7b651a32 2002 subgrp, from))) {
d62a17ae 2003 subgroup_announce_reset_nhop(
2004 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2005 ? AF_INET6
2006 : p->family),
737af885 2007 attr);
7b651a32 2008 nh_reset = true;
2009 }
737af885
BS
2010
2011 if ((p->family == AF_INET6) &&
2012 (!bgp_subgrp_multiaccess_check_v6(
2013 piattr->mp_nexthop_global,
7b651a32 2014 subgrp, from))) {
737af885
BS
2015 subgroup_announce_reset_nhop(
2016 (peer_cap_enhe(peer, afi, safi)
2017 ? AF_INET6
2018 : p->family),
2019 attr);
7b651a32 2020 nh_reset = true;
2021 }
737af885
BS
2022
2023
2024
40381db7 2025 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2026 /*
2027 * This flag is used for leaked vpn-vrf routes
2028 */
2029 int family = p->family;
2030
2031 if (peer_cap_enhe(peer, afi, safi))
2032 family = AF_INET6;
2033
2034 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2035 zlog_debug(
1defdda8 2036 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2037 __func__, family2str(family));
2038 subgroup_announce_reset_nhop(family, attr);
7b651a32 2039 nh_reset = true;
d62a17ae 2040 }
63696f1d 2041 }
960035b2 2042
63696f1d 2043 /* If IPv6/MP and nexthop does not have any override and happens
2044 * to
2045 * be a link-local address, reset it so that we don't pass along
2046 * the
2047 * source's link-local IPv6 address to recipients who may not be
2048 * on
2049 * the same interface.
2050 */
2051 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2052 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2053 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2054 nh_reset = true;
2055 }
d62a17ae 2056 }
3f9c7369 2057
7b651a32 2058 /*
2059 * When the next hop is set to ourselves, if all multipaths have
2060 * link-bandwidth announce the cumulative bandwidth as that makes
2061 * the most sense. However, don't modify if the link-bandwidth has
2062 * been explicitly set by user policy.
2063 */
2064 if (nh_reset &&
f7e1c681 2065 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2066 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2067 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2068 attr->ecommunity = ecommunity_replace_linkbw(
2069 bgp->as, attr->ecommunity, cum_bw);
2070
3dc339cd 2071 return true;
3f9c7369
DS
2072}
2073
f009ff26 2074static int bgp_route_select_timer_expire(struct thread *thread)
2075{
2076 struct afi_safi_info *info;
2077 afi_t afi;
2078 safi_t safi;
2079 struct bgp *bgp;
2080
2081 info = THREAD_ARG(thread);
2082 afi = info->afi;
2083 safi = info->safi;
2084 bgp = info->bgp;
2085
2086 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2087 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2088 safi);
f009ff26 2089
2090 bgp->gr_info[afi][safi].t_route_select = NULL;
2091
2092 XFREE(MTYPE_TMP, info);
2093
2094 /* Best path selection */
2095 return bgp_best_path_select_defer(bgp, afi, safi);
2096}
2097
9bcb3eef 2098void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2099 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2100 struct bgp_path_info_pair *result, afi_t afi,
2101 safi_t safi)
2102{
2103 struct bgp_path_info *new_select;
2104 struct bgp_path_info *old_select;
40381db7
DS
2105 struct bgp_path_info *pi;
2106 struct bgp_path_info *pi1;
2107 struct bgp_path_info *pi2;
2108 struct bgp_path_info *nextpi = NULL;
d62a17ae 2109 int paths_eq, do_mpath, debug;
2110 struct list mp_list;
2111 char pfx_buf[PREFIX2STR_BUFFER];
2112 char path_buf[PATH_ADDPATH_STR_BUFFER];
2113
2114 bgp_mp_list_init(&mp_list);
2115 do_mpath =
2116 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2117
9bcb3eef 2118 debug = bgp_debug_bestpath(dest);
d62a17ae 2119
2120 if (debug)
9bcb3eef 2121 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2122
9bcb3eef 2123 dest->reason = bgp_path_selection_none;
d62a17ae 2124 /* bgp deterministic-med */
2125 new_select = NULL;
892fedb6 2126 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2127
1defdda8 2128 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2129 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2130 pi1 = pi1->next)
9bcb3eef 2131 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2132 BGP_PATH_DMED_SELECTED);
d62a17ae 2133
9bcb3eef 2134 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2135 pi1 = pi1->next) {
40381db7 2136 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2137 continue;
40381db7 2138 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2139 continue;
ea8b2282 2140 if (pi1->peer != bgp->peer_self)
40381db7 2141 if (pi1->peer->status != Established)
d62a17ae 2142 continue;
2143
40381db7
DS
2144 new_select = pi1;
2145 if (pi1->next) {
2146 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2147 if (CHECK_FLAG(pi2->flags,
1defdda8 2148 BGP_PATH_DMED_CHECK))
d62a17ae 2149 continue;
40381db7 2150 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2151 continue;
ea8b2282 2152 if (pi2->peer != bgp->peer_self
d62a17ae 2153 && !CHECK_FLAG(
ea8b2282
DS
2154 pi2->peer->sflags,
2155 PEER_STATUS_NSF_WAIT))
40381db7 2156 if (pi2->peer->status
d62a17ae 2157 != Established)
2158 continue;
2159
121e245d
DS
2160 if (!aspath_cmp_left(pi1->attr->aspath,
2161 pi2->attr->aspath)
2162 && !aspath_cmp_left_confed(
40381db7 2163 pi1->attr->aspath,
121e245d
DS
2164 pi2->attr->aspath))
2165 continue;
d62a17ae 2166
121e245d
DS
2167 if (bgp_path_info_cmp(
2168 bgp, pi2, new_select,
2169 &paths_eq, mpath_cfg, debug,
fdf81fa0 2170 pfx_buf, afi, safi,
9bcb3eef 2171 &dest->reason)) {
121e245d 2172 bgp_path_info_unset_flag(
9bcb3eef 2173 dest, new_select,
121e245d
DS
2174 BGP_PATH_DMED_SELECTED);
2175 new_select = pi2;
d62a17ae 2176 }
121e245d
DS
2177
2178 bgp_path_info_set_flag(
9bcb3eef 2179 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2180 }
2181 }
9bcb3eef 2182 bgp_path_info_set_flag(dest, new_select,
18ee8310 2183 BGP_PATH_DMED_CHECK);
9bcb3eef 2184 bgp_path_info_set_flag(dest, new_select,
18ee8310 2185 BGP_PATH_DMED_SELECTED);
d62a17ae 2186
2187 if (debug) {
18ee8310
DS
2188 bgp_path_info_path_with_addpath_rx_str(
2189 new_select, path_buf);
c66faab1 2190 zlog_debug("%s: %s is the bestpath from AS %u",
d62a17ae 2191 pfx_buf, path_buf,
2192 aspath_get_first_as(
2193 new_select->attr->aspath));
2194 }
2195 }
2196 }
96450faf 2197
d62a17ae 2198 /* Check old selected route and new selected route. */
2199 old_select = NULL;
2200 new_select = NULL;
9bcb3eef 2201 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2202 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2203 enum bgp_path_selection_reason reason;
2204
40381db7
DS
2205 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2206 old_select = pi;
d62a17ae 2207
40381db7 2208 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2209 /* reap REMOVED routes, if needs be
2210 * selected route must stay for a while longer though
2211 */
40381db7
DS
2212 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2213 && (pi != old_select))
9bcb3eef 2214 bgp_path_info_reap(dest, pi);
d62a17ae 2215
ddb5b488 2216 if (debug)
40381db7
DS
2217 zlog_debug("%s: pi %p in holddown", __func__,
2218 pi);
ddb5b488 2219
d62a17ae 2220 continue;
2221 }
96450faf 2222
40381db7
DS
2223 if (pi->peer && pi->peer != bgp->peer_self
2224 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2225 if (pi->peer->status != Established) {
ddb5b488
PZ
2226
2227 if (debug)
2228 zlog_debug(
40381db7
DS
2229 "%s: pi %p non self peer %s not estab state",
2230 __func__, pi, pi->peer->host);
ddb5b488 2231
d62a17ae 2232 continue;
ddb5b488 2233 }
9fbdd100 2234
892fedb6 2235 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2236 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2237 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2238 if (debug)
40381db7 2239 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2240 continue;
2241 }
9fbdd100 2242
9bcb3eef 2243 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2244
9bcb3eef 2245 reason = dest->reason;
40381db7 2246 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2247 debug, pfx_buf, afi, safi,
2248 &dest->reason)) {
19ea4cec
DS
2249 if (new_select == NULL &&
2250 reason != bgp_path_selection_none)
9bcb3eef 2251 dest->reason = reason;
40381db7 2252 new_select = pi;
d62a17ae 2253 }
2254 }
718e3744 2255
d62a17ae 2256 /* Now that we know which path is the bestpath see if any of the other
2257 * paths
2258 * qualify as multipaths
2259 */
2260 if (debug) {
2261 if (new_select)
18ee8310
DS
2262 bgp_path_info_path_with_addpath_rx_str(new_select,
2263 path_buf);
d62a17ae 2264 else
772270f3 2265 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2266 zlog_debug(
2267 "%s: After path selection, newbest is %s oldbest was %s",
2268 pfx_buf, path_buf,
2269 old_select ? old_select->peer->host : "NONE");
96450faf 2270 }
9fbdd100 2271
d62a17ae 2272 if (do_mpath && new_select) {
9bcb3eef 2273 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2274 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2275
2276 if (debug)
18ee8310 2277 bgp_path_info_path_with_addpath_rx_str(
40381db7 2278 pi, path_buf);
d62a17ae 2279
40381db7 2280 if (pi == new_select) {
d62a17ae 2281 if (debug)
2282 zlog_debug(
2283 "%s: %s is the bestpath, add to the multipath list",
2284 pfx_buf, path_buf);
40381db7 2285 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2286 continue;
2287 }
2288
40381db7 2289 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2290 continue;
2291
40381db7
DS
2292 if (pi->peer && pi->peer != bgp->peer_self
2293 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2294 PEER_STATUS_NSF_WAIT))
40381db7 2295 if (pi->peer->status != Established)
d62a17ae 2296 continue;
2297
40381db7 2298 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2299 if (debug)
2300 zlog_debug(
2301 "%s: %s has the same nexthop as the bestpath, skip it",
2302 pfx_buf, path_buf);
2303 continue;
2304 }
2305
40381db7 2306 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2307 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2308 &dest->reason);
d62a17ae 2309
2310 if (paths_eq) {
2311 if (debug)
2312 zlog_debug(
2313 "%s: %s is equivalent to the bestpath, add to the multipath list",
2314 pfx_buf, path_buf);
40381db7 2315 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2316 }
2317 }
2318 }
fee0f4c6 2319
9bcb3eef 2320 bgp_path_info_mpath_update(dest, new_select, old_select, &mp_list,
18ee8310
DS
2321 mpath_cfg);
2322 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2323 bgp_mp_list_clear(&mp_list);
96450faf 2324
9bcb3eef 2325 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2326
d62a17ae 2327 result->old = old_select;
2328 result->new = new_select;
96450faf 2329
d62a17ae 2330 return;
fee0f4c6 2331}
2332
3f9c7369
DS
2333/*
2334 * A new route/change in bestpath of an existing route. Evaluate the path
2335 * for advertisement to the subgroup.
2336 */
3dc339cd
DA
2337void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2338 struct bgp_path_info *selected,
9bcb3eef 2339 struct bgp_dest *dest,
3dc339cd 2340 uint32_t addpath_tx_id)
d62a17ae 2341{
b54892e0 2342 const struct prefix *p;
d62a17ae 2343 struct peer *onlypeer;
2344 struct attr attr;
2345 afi_t afi;
2346 safi_t safi;
adbac85e 2347
9bcb3eef 2348 p = bgp_dest_get_prefix(dest);
d62a17ae 2349 afi = SUBGRP_AFI(subgrp);
2350 safi = SUBGRP_SAFI(subgrp);
2351 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2352 : NULL);
2353
e0207895
PZ
2354 if (BGP_DEBUG(update, UPDATE_OUT)) {
2355 char buf_prefix[PREFIX_STRLEN];
2356 prefix2str(p, buf_prefix, sizeof(buf_prefix));
ddb5b488
PZ
2357 zlog_debug("%s: p=%s, selected=%p", __func__, buf_prefix,
2358 selected);
e0207895
PZ
2359 }
2360
d62a17ae 2361 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2362 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2363 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2364 return;
d62a17ae 2365
2366 memset(&attr, 0, sizeof(struct attr));
2367 /* It's initialized in bgp_announce_check() */
2368
2369 /* Announcement to the subgroup. If the route is filtered withdraw it.
2370 */
2371 if (selected) {
9bcb3eef
DS
2372 if (subgroup_announce_check(dest, selected, subgrp, p, &attr))
2373 bgp_adj_out_set_subgroup(dest, subgrp, &attr, selected);
d62a17ae 2374 else
9bcb3eef 2375 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2376 addpath_tx_id);
d62a17ae 2377 }
2378
2379 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2380 else {
9bcb3eef 2381 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2382 }
200df115 2383}
fee0f4c6 2384
3064bf43 2385/*
e1072051 2386 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2387 * This is called at the end of route processing.
3064bf43 2388 */
9bcb3eef 2389void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2390{
40381db7 2391 struct bgp_path_info *pi;
3064bf43 2392
9bcb3eef 2393 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2394 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2395 continue;
40381db7
DS
2396 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2397 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2398 }
3064bf43 2399}
2400
2401/*
2402 * Has the route changed from the RIB's perspective? This is invoked only
2403 * if the route selection returns the same best route as earlier - to
2404 * determine if we need to update zebra or not.
2405 */
9bcb3eef 2406bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2407{
4b7e6066 2408 struct bgp_path_info *mpinfo;
d62a17ae 2409
2bb9eff4
DS
2410 /* If this is multipath, check all selected paths for any nexthop
2411 * change or attribute change. Some attribute changes (e.g., community)
2412 * aren't of relevance to the RIB, but we'll update zebra to ensure
2413 * we handle the case of BGP nexthop change. This is the behavior
2414 * when the best path has an attribute change anyway.
d62a17ae 2415 */
1defdda8 2416 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2417 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2418 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2419 return true;
d62a17ae 2420
2bb9eff4
DS
2421 /*
2422 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2423 */
18ee8310
DS
2424 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2425 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2426 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2427 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2428 return true;
d62a17ae 2429 }
3064bf43 2430
d62a17ae 2431 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2432 return false;
3064bf43 2433}
2434
d62a17ae 2435struct bgp_process_queue {
2436 struct bgp *bgp;
9bcb3eef 2437 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2438#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2439 unsigned int flags;
2440 unsigned int queued;
200df115 2441};
2442
3b0c17e1 2443static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2444 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2445 struct bgp_path_info *new_select,
2446 struct bgp_path_info *old_select)
2447{
9bcb3eef 2448 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2449
2450 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2451 return;
2452
2453 if (advertise_type5_routes(bgp, afi) && new_select
2454 && is_route_injectable_into_evpn(new_select)) {
2455
2456 /* apply the route-map */
2457 if (bgp->adv_cmd_rmap[afi][safi].map) {
2458 route_map_result_t ret;
2459 struct bgp_path_info rmap_path;
2460 struct bgp_path_info_extra rmap_path_extra;
2461 struct attr dummy_attr;
2462
2463 dummy_attr = *new_select->attr;
2464
2465 /* Fill temp path_info */
9bcb3eef 2466 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2467 new_select, new_select->peer,
2468 &dummy_attr);
2469
2470 RESET_FLAG(dummy_attr.rmap_change_flags);
2471
2472 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
2473 p, RMAP_BGP, &rmap_path);
2474
2475 if (ret == RMAP_DENYMATCH) {
2476 bgp_attr_flush(&dummy_attr);
2477 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2478 safi);
2479 } else
2480 bgp_evpn_advertise_type5_route(
2481 bgp, p, &dummy_attr, afi, safi);
2482 } else {
2483 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2484 afi, safi);
2485 }
2486 } else if (advertise_type5_routes(bgp, afi) && old_select
2487 && is_route_injectable_into_evpn(old_select))
2488 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2489}
2490
3103e8d2
DS
2491/*
2492 * old_select = The old best path
2493 * new_select = the new best path
2494 *
2495 * if (!old_select && new_select)
2496 * We are sending new information on.
2497 *
2498 * if (old_select && new_select) {
2499 * if (new_select != old_select)
2500 * We have a new best path send a change
2501 * else
2502 * We've received a update with new attributes that needs
2503 * to be passed on.
2504 * }
2505 *
2506 * if (old_select && !new_select)
2507 * We have no eligible route that we can announce or the rn
2508 * is being removed.
2509 */
9bcb3eef 2510static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2511 afi_t afi, safi_t safi)
d62a17ae 2512{
4b7e6066
DS
2513 struct bgp_path_info *new_select;
2514 struct bgp_path_info *old_select;
2515 struct bgp_path_info_pair old_and_new;
ddb5b488 2516 int debug = 0;
d62a17ae 2517
892fedb6 2518 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2519 if (dest)
2520 debug = bgp_debug_bestpath(dest);
b54892e0 2521 if (debug)
f4c713ae 2522 zlog_debug(
b54892e0 2523 "%s: bgp delete in progress, ignoring event, p=%pRN",
9bcb3eef 2524 __func__, dest);
f4c713ae
LB
2525 return;
2526 }
d62a17ae 2527 /* Is it end of initial update? (after startup) */
9bcb3eef 2528 if (!dest) {
d62a17ae 2529 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2530 sizeof(bgp->update_delay_zebra_resume_time));
2531
2532 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2533 FOREACH_AFI_SAFI (afi, safi) {
2534 if (bgp_fibupd_safi(safi))
2535 bgp_zebra_announce_table(bgp, afi, safi);
2536 }
d62a17ae 2537 bgp->main_peers_update_hold = 0;
2538
2539 bgp_start_routeadv(bgp);
aac24838 2540 return;
d62a17ae 2541 }
cb1faec9 2542
9bcb3eef 2543 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2544
9bcb3eef 2545 debug = bgp_debug_bestpath(dest);
b54892e0 2546 if (debug)
9bcb3eef 2547 zlog_debug("%s: p=%pRN afi=%s, safi=%s start", __func__, dest,
ddb5b488 2548 afi2str(afi), safi2str(safi));
ddb5b488 2549
f009ff26 2550 /* The best path calculation for the route is deferred if
2551 * BGP_NODE_SELECT_DEFER is set
2552 */
9bcb3eef 2553 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2554 if (BGP_DEBUG(update, UPDATE_OUT))
9bcb3eef 2555 zlog_debug("SELECT_DEFER falg set for route %p", dest);
f009ff26 2556 return;
2557 }
2558
d62a17ae 2559 /* Best path selection. */
9bcb3eef 2560 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2561 afi, safi);
2562 old_select = old_and_new.old;
2563 new_select = old_and_new.new;
2564
2565 /* Do we need to allocate or free labels?
2566 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2567 * necessary to do this upon changes to best path. Exceptions:
2568 * - label index has changed -> recalculate resulting label
2569 * - path_info sub_type changed -> switch to/from implicit-null
2570 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2571 */
318cac96 2572 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2573 if (new_select) {
2574 if (!old_select
2575 || bgp_label_index_differs(new_select, old_select)
57592a53 2576 || new_select->sub_type != old_select->sub_type
9bcb3eef 2577 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2578 /* Enforced penultimate hop popping:
2579 * implicit-null for local routes, aggregate
2580 * and redistributed routes
2581 */
d62a17ae 2582 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2583 || new_select->sub_type
2584 == BGP_ROUTE_AGGREGATE
2585 || new_select->sub_type
2586 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2587 if (CHECK_FLAG(
9bcb3eef 2588 dest->flags,
d62a17ae 2589 BGP_NODE_REGISTERED_FOR_LABEL))
9bcb3eef 2590 bgp_unregister_for_label(dest);
70e98a7f 2591 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2592 &dest->local_label);
2593 bgp_set_valid_label(&dest->local_label);
d62a17ae 2594 } else
9bcb3eef
DS
2595 bgp_register_for_label(dest,
2596 new_select);
d62a17ae 2597 }
9bcb3eef 2598 } else if (CHECK_FLAG(dest->flags,
a4d82a8a 2599 BGP_NODE_REGISTERED_FOR_LABEL)) {
9bcb3eef 2600 bgp_unregister_for_label(dest);
318cac96 2601 }
9bcb3eef
DS
2602 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
2603 bgp_unregister_for_label(dest);
d62a17ae 2604 }
cd1964ff 2605
b54892e0 2606 if (debug)
ddb5b488 2607 zlog_debug(
b54892e0 2608 "%s: p=%pRN afi=%s, safi=%s, old_select=%p, new_select=%p",
9bcb3eef 2609 __func__, dest, afi2str(afi), safi2str(safi),
ddb5b488 2610 old_select, new_select);
ddb5b488 2611
d62a17ae 2612 /* If best route remains the same and this is not due to user-initiated
2613 * clear, see exactly what needs to be done.
2614 */
d62a17ae 2615 if (old_select && old_select == new_select
9bcb3eef 2616 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2617 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2618 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2619 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2620#ifdef ENABLE_BGP_VNC
d62a17ae 2621 vnc_import_bgp_add_route(bgp, p, old_select);
2622 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2623#endif
bb744275 2624 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2625 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2626
2627 if (new_select->type == ZEBRA_ROUTE_BGP
2628 && (new_select->sub_type == BGP_ROUTE_NORMAL
2629 || new_select->sub_type
2630 == BGP_ROUTE_IMPORTED))
2631
9bcb3eef 2632 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
2633 bgp, afi, safi);
2634 }
d62a17ae 2635 }
d62a17ae 2636
2637 /* If there is a change of interest to peers, reannounce the
2638 * route. */
1defdda8 2639 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 2640 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
2641 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2642 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2643
2644 /* unicast routes must also be annouced to
2645 * labeled-unicast update-groups */
2646 if (safi == SAFI_UNICAST)
2647 group_announce_route(bgp, afi,
9bcb3eef 2648 SAFI_LABELED_UNICAST, dest,
d62a17ae 2649 new_select);
2650
1defdda8 2651 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 2652 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 2653 }
fee0f4c6 2654
3b0c17e1 2655 /* advertise/withdraw type-5 routes */
2656 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2657 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2658 bgp_process_evpn_route_injection(
9bcb3eef 2659 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 2660
b1875e65 2661 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2662 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
2663 bgp_zebra_clear_route_change_flags(dest);
2664 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2665 return;
d62a17ae 2666 }
8ad7271d 2667
d62a17ae 2668 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2669 */
9bcb3eef 2670 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 2671
2672 /* bestpath has changed; bump version */
2673 if (old_select || new_select) {
9bcb3eef 2674 bgp_bump_version(dest);
d62a17ae 2675
2676 if (!bgp->t_rmap_def_originate_eval) {
2677 bgp_lock(bgp);
2678 thread_add_timer(
2679 bm->master,
2680 update_group_refresh_default_originate_route_map,
2681 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2682 &bgp->t_rmap_def_originate_eval);
2683 }
2684 }
3f9c7369 2685
d62a17ae 2686 if (old_select)
9bcb3eef 2687 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 2688 if (new_select) {
ddb5b488
PZ
2689 if (debug)
2690 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
2691 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2692 bgp_path_info_unset_flag(dest, new_select,
2693 BGP_PATH_ATTR_CHANGED);
1defdda8 2694 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 2695 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 2696 }
338b3424 2697
49e5a4a0 2698#ifdef ENABLE_BGP_VNC
d62a17ae 2699 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2700 if (old_select != new_select) {
2701 if (old_select) {
2702 vnc_import_bgp_exterior_del_route(bgp, p,
2703 old_select);
2704 vnc_import_bgp_del_route(bgp, p, old_select);
2705 }
2706 if (new_select) {
2707 vnc_import_bgp_exterior_add_route(bgp, p,
2708 new_select);
2709 vnc_import_bgp_add_route(bgp, p, new_select);
2710 }
2711 }
2712 }
65efcfce
LB
2713#endif
2714
9bcb3eef 2715 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2716
2717 /* unicast routes must also be annouced to labeled-unicast update-groups
2718 */
2719 if (safi == SAFI_UNICAST)
9bcb3eef 2720 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 2721 new_select);
2722
2723 /* FIB update. */
2724 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2725 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2726 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2727 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2728 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2729 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2730
2731 /* if this is an evpn imported type-5 prefix,
2732 * we need to withdraw the route first to clear
2733 * the nh neigh and the RMAC entry.
2734 */
2735 if (old_select &&
2736 is_route_parent_evpn(old_select))
2737 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2738
9bcb3eef 2739 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 2740 } else {
d62a17ae 2741 /* Withdraw the route from the kernel. */
2742 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2743 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2744 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2745 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2746
568e10ca 2747 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2748 }
718e3744 2749 }
3064bf43 2750
9bcb3eef 2751 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 2752 old_select);
5424b7ba 2753
d62a17ae 2754 /* Clear any route change flags. */
9bcb3eef 2755 bgp_zebra_clear_route_change_flags(dest);
3064bf43 2756
18ee8310 2757 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2758 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 2759 bgp_path_info_reap(dest, old_select);
d62a17ae 2760
9bcb3eef 2761 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2762 return;
718e3744 2763}
2764
f009ff26 2765/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2766int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2767{
9bcb3eef 2768 struct bgp_dest *dest;
f009ff26 2769 int cnt = 0;
2770 struct afi_safi_info *thread_info;
2771 struct listnode *node = NULL, *nnode = NULL;
2772
2773 if (bgp->gr_info[afi][safi].t_route_select)
2774 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
2775
2776 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
2777 zlog_debug("%s: processing route for %s : cnt %d", __func__,
2778 get_afi_safi_str(afi, safi, false),
2779 listcount(bgp->gr_info[afi][safi].route_list));
f009ff26 2780 }
2781
2782 /* Process the route list */
2783 node = listhead(bgp->gr_info[afi][safi].route_list);
f009ff26 2784 while (node) {
9bcb3eef 2785 dest = listgetdata(node);
f009ff26 2786 nnode = node->next;
2787 list_delete_node(bgp->gr_info[afi][safi].route_list, node);
9bcb3eef 2788 dest->rt_node = NULL;
f009ff26 2789
9bcb3eef
DS
2790 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
2791 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
2792 bgp_process_main_one(bgp, dest, afi, safi);
f009ff26 2793 cnt++;
2794 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT)
2795 break;
2796 }
2797 node = nnode;
2798 }
2799
9e3b51a7 2800 /* Send EOR message when all routes are processed */
2801 if (list_isempty(bgp->gr_info[afi][safi].route_list)) {
2802 bgp_send_delayed_eor(bgp);
8c48b3b6 2803 /* Send route processing complete message to RIB */
2804 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 2805 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 2806 return 0;
9e3b51a7 2807 }
f009ff26 2808
2809 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 2810
2811 thread_info->afi = afi;
2812 thread_info->safi = safi;
2813 thread_info->bgp = bgp;
2814
2815 /* If there are more routes to be processed, start the
2816 * selection timer
2817 */
2818 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
2819 BGP_ROUTE_SELECT_DELAY,
2820 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 2821 return 0;
2822}
2823
aac24838 2824static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 2825{
aac24838
JB
2826 struct bgp_process_queue *pqnode = data;
2827 struct bgp *bgp = pqnode->bgp;
d62a17ae 2828 struct bgp_table *table;
9bcb3eef 2829 struct bgp_dest *dest;
aac24838
JB
2830
2831 /* eoiu marker */
2832 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
2833 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
2834 /* should always have dedicated wq call */
2835 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
2836 return WQ_SUCCESS;
2837 }
2838
ac021f40 2839 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 2840 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 2841 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
2842 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
2843 table = bgp_dest_table(dest);
2844 /* note, new DESTs may be added as part of processing */
2845 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 2846
9bcb3eef 2847 bgp_dest_unlock_node(dest);
d62a17ae 2848 bgp_table_unlock(table);
2849 }
aac24838
JB
2850
2851 return WQ_SUCCESS;
2852}
2853
2854static void bgp_processq_del(struct work_queue *wq, void *data)
2855{
2856 struct bgp_process_queue *pqnode = data;
2857
2858 bgp_unlock(pqnode->bgp);
2859
2860 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 2861}
2862
d62a17ae 2863void bgp_process_queue_init(void)
200df115 2864{
0ce1ca80 2865 if (!bm->process_main_queue)
d62a17ae 2866 bm->process_main_queue =
2867 work_queue_new(bm->master, "process_main_queue");
2868
aac24838 2869 bm->process_main_queue->spec.workfunc = &bgp_process_wq;
d62a17ae 2870 bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
2871 bm->process_main_queue->spec.max_retries = 0;
2872 bm->process_main_queue->spec.hold = 50;
2873 /* Use a higher yield value of 50ms for main queue processing */
2874 bm->process_main_queue->spec.yield = 50 * 1000L;
200df115 2875}
2876
cfe8d15a 2877static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
2878{
2879 struct bgp_process_queue *pqnode;
2880
a4d82a8a
PZ
2881 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
2882 sizeof(struct bgp_process_queue));
aac24838
JB
2883
2884 /* unlocked in bgp_processq_del */
2885 pqnode->bgp = bgp_lock(bgp);
2886 STAILQ_INIT(&pqnode->pqueue);
2887
aac24838
JB
2888 return pqnode;
2889}
2890
9bcb3eef 2891void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 2892{
aac24838
JB
2893#define ARBITRARY_PROCESS_QLEN 10000
2894 struct work_queue *wq = bm->process_main_queue;
d62a17ae 2895 struct bgp_process_queue *pqnode;
cfe8d15a 2896 int pqnode_reuse = 0;
495f0b13 2897
d62a17ae 2898 /* already scheduled for processing? */
9bcb3eef 2899 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 2900 return;
2e02b9b2 2901
f009ff26 2902 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
2903 * the workqueue
2904 */
9bcb3eef 2905 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2906 if (BGP_DEBUG(update, UPDATE_OUT))
2907 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 2908 dest);
f009ff26 2909 return;
2910 }
2911
aac24838 2912 if (wq == NULL)
d62a17ae 2913 return;
2914
aac24838 2915 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
2916 limit only if is from the same BGP view and it's not an EOIU marker
2917 */
aac24838
JB
2918 if (work_queue_item_count(wq)) {
2919 struct work_queue_item *item = work_queue_last_item(wq);
2920 pqnode = item->data;
228da428 2921
a4d82a8a
PZ
2922 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
2923 || pqnode->bgp != bgp
2924 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
2925 pqnode = bgp_processq_alloc(bgp);
2926 else
2927 pqnode_reuse = 1;
aac24838 2928 } else
cfe8d15a 2929 pqnode = bgp_processq_alloc(bgp);
aac24838 2930 /* all unlocked in bgp_process_wq */
9bcb3eef 2931 bgp_table_lock(bgp_dest_table(dest));
aac24838 2932
9bcb3eef
DS
2933 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
2934 bgp_dest_lock_node(dest);
aac24838 2935
60466a63 2936 /* can't be enqueued twice */
9bcb3eef
DS
2937 assert(STAILQ_NEXT(dest, pq) == NULL);
2938 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
2939 pqnode->queued++;
2940
cfe8d15a
LB
2941 if (!pqnode_reuse)
2942 work_queue_add(wq, pqnode);
2943
d62a17ae 2944 return;
fee0f4c6 2945}
0a486e5f 2946
d62a17ae 2947void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 2948{
d62a17ae 2949 struct bgp_process_queue *pqnode;
cb1faec9 2950
d62a17ae 2951 if (bm->process_main_queue == NULL)
2952 return;
2e02b9b2 2953
cfe8d15a 2954 pqnode = bgp_processq_alloc(bgp);
cb1faec9 2955
aac24838 2956 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
cfe8d15a 2957 work_queue_add(bm->process_main_queue, pqnode);
cb1faec9
DS
2958}
2959
d62a17ae 2960static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 2961{
d62a17ae 2962 struct peer *peer;
0a486e5f 2963
d62a17ae 2964 peer = THREAD_ARG(thread);
2965 peer->t_pmax_restart = NULL;
0a486e5f 2966
d62a17ae 2967 if (bgp_debug_neighbor_events(peer))
2968 zlog_debug(
2969 "%s Maximum-prefix restart timer expired, restore peering",
2970 peer->host);
0a486e5f 2971
a9bafa95 2972 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 2973 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 2974
d62a17ae 2975 return 0;
0a486e5f 2976}
2977
3dc339cd
DA
2978bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
2979 int always)
718e3744 2980{
d62a17ae 2981 iana_afi_t pkt_afi;
5c525538 2982 iana_safi_t pkt_safi;
9cabb64b 2983
d62a17ae 2984 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 2985 return false;
e0701b79 2986
d62a17ae 2987 if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) {
2988 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2989 PEER_STATUS_PREFIX_LIMIT)
2990 && !always)
3dc339cd 2991 return false;
e0701b79 2992
d62a17ae 2993 zlog_info(
a0a87037
DA
2994 "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32
2995 " exceed, limit %" PRIu32,
5cb5f4d0 2996 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 2997 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2998 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
2999
3000 if (CHECK_FLAG(peer->af_flags[afi][safi],
3001 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3002 return false;
d62a17ae 3003
3004 /* Convert AFI, SAFI to values for packet. */
3005 pkt_afi = afi_int2iana(afi);
3006 pkt_safi = safi_int2iana(safi);
3007 {
d7c0a89a 3008 uint8_t ndata[7];
d62a17ae 3009
3010 ndata[0] = (pkt_afi >> 8);
3011 ndata[1] = pkt_afi;
3012 ndata[2] = pkt_safi;
3013 ndata[3] = (peer->pmax[afi][safi] >> 24);
3014 ndata[4] = (peer->pmax[afi][safi] >> 16);
3015 ndata[5] = (peer->pmax[afi][safi] >> 8);
3016 ndata[6] = (peer->pmax[afi][safi]);
3017
3018 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3019 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3020 BGP_NOTIFY_CEASE_MAX_PREFIX,
3021 ndata, 7);
3022 }
3023
3024 /* Dynamic peers will just close their connection. */
3025 if (peer_dynamic_neighbor(peer))
3dc339cd 3026 return true;
d62a17ae 3027
3028 /* restart timer start */
3029 if (peer->pmax_restart[afi][safi]) {
3030 peer->v_pmax_restart =
3031 peer->pmax_restart[afi][safi] * 60;
3032
3033 if (bgp_debug_neighbor_events(peer))
3034 zlog_debug(
3035 "%s Maximum-prefix restart timer started for %d secs",
3036 peer->host, peer->v_pmax_restart);
3037
3038 BGP_TIMER_ON(peer->t_pmax_restart,
3039 bgp_maximum_prefix_restart_timer,
3040 peer->v_pmax_restart);
3041 }
3042
3dc339cd 3043 return true;
d62a17ae 3044 } else
3045 UNSET_FLAG(peer->af_sflags[afi][safi],
3046 PEER_STATUS_PREFIX_LIMIT);
3047
3048 if (peer->pcount[afi][safi]
3049 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
3050 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3051 PEER_STATUS_PREFIX_THRESHOLD)
3052 && !always)
3dc339cd 3053 return false;
d62a17ae 3054
3055 zlog_info(
a0a87037
DA
3056 "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32
3057 ", max %" PRIu32,
5cb5f4d0 3058 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 3059 peer->pcount[afi][safi], peer->pmax[afi][safi]);
3060 SET_FLAG(peer->af_sflags[afi][safi],
3061 PEER_STATUS_PREFIX_THRESHOLD);
3062 } else
3063 UNSET_FLAG(peer->af_sflags[afi][safi],
3064 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3065 return false;
718e3744 3066}
3067
b40d939b 3068/* Unconditionally remove the route from the RIB, without taking
3069 * damping into consideration (eg, because the session went down)
3070 */
9bcb3eef 3071void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3072 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3073{
f009ff26 3074
3075 struct bgp *bgp = NULL;
3076 bool delete_route = false;
3077
9bcb3eef
DS
3078 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3079 safi);
d62a17ae 3080
f009ff26 3081 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3082 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3083
f009ff26 3084 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3085 * flag
3086 */
3087 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3088 delete_route = true;
9bcb3eef 3089 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3090 delete_route = true;
f009ff26 3091 if (delete_route) {
9bcb3eef
DS
3092 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3093 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3094 bgp = pi->peer->bgp;
9bcb3eef 3095 if ((dest->rt_node)
36235319
QY
3096 && (bgp->gr_info[afi][safi].route_list)) {
3097 list_delete_node(bgp->gr_info[afi][safi]
3098 .route_list,
9bcb3eef
DS
3099 dest->rt_node);
3100 dest->rt_node = NULL;
f009ff26 3101 }
3102 }
3103 }
3104 }
4a11bf2c 3105
9bcb3eef
DS
3106 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3107 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3108}
3109
9bcb3eef 3110static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3111 struct peer *peer, afi_t afi, safi_t safi,
3112 struct prefix_rd *prd)
3113{
9bcb3eef 3114 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3115
d62a17ae 3116 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3117 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3118 */
3119 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3120 && peer->sort == BGP_PEER_EBGP)
9bcb3eef 3121 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
d62a17ae 3122 == BGP_DAMP_SUPPRESSED) {
b54892e0 3123 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
d62a17ae 3124 safi);
3125 return;
3126 }
3127
49e5a4a0 3128#ifdef ENABLE_BGP_VNC
d62a17ae 3129 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3130 struct bgp_dest *pdest = NULL;
d62a17ae 3131 struct bgp_table *table = NULL;
3132
9bcb3eef
DS
3133 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3134 (struct prefix *)prd);
3135 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3136 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3137
3138 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3139 peer->bgp, prd, table, p, pi);
d62a17ae 3140 }
9bcb3eef 3141 bgp_dest_unlock_node(pdest);
d62a17ae 3142 }
3143 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3144 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3145
b54892e0
DS
3146 vnc_import_bgp_del_route(peer->bgp, p, pi);
3147 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3148 }
65efcfce 3149 }
d62a17ae 3150#endif
128ea8ab 3151
d62a17ae 3152 /* If this is an EVPN route, process for un-import. */
3153 if (safi == SAFI_EVPN)
b54892e0 3154 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3155
9bcb3eef 3156 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3157}
3158
4b7e6066
DS
3159struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3160 struct peer *peer, struct attr *attr,
9bcb3eef 3161 struct bgp_dest *dest)
fb018d25 3162{
4b7e6066 3163 struct bgp_path_info *new;
fb018d25 3164
d62a17ae 3165 /* Make new BGP info. */
4b7e6066 3166 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3167 new->type = type;
3168 new->instance = instance;
3169 new->sub_type = sub_type;
3170 new->peer = peer;
3171 new->attr = attr;
3172 new->uptime = bgp_clock();
9bcb3eef 3173 new->net = dest;
d62a17ae 3174 return new;
fb018d25
DS
3175}
3176
d62a17ae 3177static void overlay_index_update(struct attr *attr,
3178 struct eth_segment_id *eth_s_id,
3179 union gw_addr *gw_ip)
684a7227 3180{
d62a17ae 3181 if (!attr)
3182 return;
684a7227 3183
d62a17ae 3184 if (eth_s_id == NULL) {
3185 memset(&(attr->evpn_overlay.eth_s_id), 0,
3186 sizeof(struct eth_segment_id));
3187 } else {
3188 memcpy(&(attr->evpn_overlay.eth_s_id), eth_s_id,
3189 sizeof(struct eth_segment_id));
3190 }
3191 if (gw_ip == NULL) {
3192 memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr));
3193 } else {
3194 memcpy(&(attr->evpn_overlay.gw_ip), gw_ip,
3195 sizeof(union gw_addr));
3196 }
684a7227
PG
3197}
3198
40381db7 3199static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3200 struct eth_segment_id *eth_s_id,
3201 union gw_addr *gw_ip)
3202{
40381db7
DS
3203 struct eth_segment_id *path_eth_s_id, *path_eth_s_id_remote;
3204 union gw_addr *path_gw_ip, *path_gw_ip_remote;
11ebf4ed
DS
3205 union {
3206 struct eth_segment_id esi;
3207 union gw_addr ip;
3208 } temp;
d62a17ae 3209
3210 if (afi != AFI_L2VPN)
3211 return true;
11ebf4ed 3212
05864da7
DS
3213 path_eth_s_id = &(path->attr->evpn_overlay.eth_s_id);
3214 path_gw_ip = &(path->attr->evpn_overlay.gw_ip);
11ebf4ed
DS
3215
3216 if (gw_ip == NULL) {
3217 memset(&temp, 0, sizeof(temp));
40381db7 3218 path_gw_ip_remote = &temp.ip;
11ebf4ed 3219 } else
40381db7 3220 path_gw_ip_remote = gw_ip;
11ebf4ed
DS
3221
3222 if (eth_s_id == NULL) {
3223 memset(&temp, 0, sizeof(temp));
40381db7 3224 path_eth_s_id_remote = &temp.esi;
11ebf4ed 3225 } else
40381db7 3226 path_eth_s_id_remote = eth_s_id;
11ebf4ed 3227
40381db7 3228 if (!memcmp(path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr)))
d62a17ae 3229 return false;
11ebf4ed 3230
40381db7 3231 return !memcmp(path_eth_s_id, path_eth_s_id_remote,
d62a17ae 3232 sizeof(struct eth_segment_id));
684a7227
PG
3233}
3234
c265ee22 3235/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3236bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3237 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3238 struct bgp_dest *dest)
d62a17ae 3239{
2dbe3fa9 3240 bool ret = false;
b099a5c8
DA
3241 bool is_bgp_static_route =
3242 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3243 : false;
d62a17ae 3244
3245 /* Only validated for unicast and multicast currently. */
3246 /* Also valid for EVPN where the nexthop is an IP address. */
3247 if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN)
3dc339cd 3248 return false;
d62a17ae 3249
3250 /* If NEXT_HOP is present, validate it. */
3251 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
b099a5c8 3252 if ((attr->nexthop.s_addr == INADDR_ANY && !is_bgp_static_route)
d62a17ae 3253 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3254 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3255 return true;
d62a17ae 3256 }
c265ee22 3257
d62a17ae 3258 /* If MP_NEXTHOP is present, validate it. */
3259 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3260 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3261 * it is not an IPv6 link-local address.
0355b41d
DA
3262 *
3263 * If we receive an UPDATE with nexthop length set to 32 bytes
3264 * we shouldn't discard an UPDATE if it's set to (::).
3265 * The link-local (2st) is validated along the code path later.
d62a17ae 3266 */
3267 if (attr->mp_nexthop_len) {
3268 switch (attr->mp_nexthop_len) {
3269 case BGP_ATTR_NHLEN_IPV4:
3270 case BGP_ATTR_NHLEN_VPNV4:
b099a5c8
DA
3271 ret = ((attr->mp_nexthop_global_in.s_addr == INADDR_ANY
3272 && !is_bgp_static_route)
975a328e
DA
3273 || IPV4_CLASS_DE(
3274 ntohl(attr->mp_nexthop_global_in.s_addr))
3275 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3276 dest));
d62a17ae 3277 break;
3278
3279 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3280 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
b099a5c8
DA
3281 ret = ((IN6_IS_ADDR_UNSPECIFIED(
3282 &attr->mp_nexthop_global)
3283 && !is_bgp_static_route)
d62a17ae 3284 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3285 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3286 &attr->mp_nexthop_global)
3287 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3288 dest));
d62a17ae 3289 break;
0355b41d
DA
3290 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3291 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3292 || IN6_IS_ADDR_MULTICAST(
3293 &attr->mp_nexthop_global)
3294 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3295 dest));
0355b41d 3296 break;
d62a17ae 3297
3298 default:
3dc339cd 3299 ret = true;
d62a17ae 3300 break;
3301 }
3302 }
c265ee22 3303
d62a17ae 3304 return ret;
3305}
3306
5a1ae2c2 3307int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3308 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3309 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3310 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3311 struct bgp_route_evpn *evpn)
d62a17ae 3312{
3313 int ret;
3314 int aspath_loop_count = 0;
9bcb3eef 3315 struct bgp_dest *dest;
d62a17ae 3316 struct bgp *bgp;
3317 struct attr new_attr;
3318 struct attr *attr_new;
40381db7 3319 struct bgp_path_info *pi;
4b7e6066
DS
3320 struct bgp_path_info *new;
3321 struct bgp_path_info_extra *extra;
d62a17ae 3322 const char *reason;
3323 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3324 int connected = 0;
3325 int do_loop_check = 1;
3326 int has_valid_label = 0;
7c312383 3327 afi_t nh_afi;
949b0f24 3328 uint8_t pi_type = 0;
3329 uint8_t pi_sub_type = 0;
3330
49e5a4a0 3331#ifdef ENABLE_BGP_VNC
d62a17ae 3332 int vnc_implicit_withdraw = 0;
65efcfce 3333#endif
d62a17ae 3334 int same_attr = 0;
718e3744 3335
d62a17ae 3336 memset(&new_attr, 0, sizeof(struct attr));
3337 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3338 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3339
d62a17ae 3340 bgp = peer->bgp;
9bcb3eef 3341 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3342 /* TODO: Check to see if we can get rid of "is_valid_label" */
3343 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3344 has_valid_label = (num_labels > 0) ? 1 : 0;
3345 else
3346 has_valid_label = bgp_is_valid_label(label);
718e3744 3347
d62a17ae 3348 /* When peer's soft reconfiguration enabled. Record input packet in
3349 Adj-RIBs-In. */
3350 if (!soft_reconfig
3351 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3352 && peer != bgp->peer_self)
9bcb3eef 3353 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3354
3355 /* Check previously received route. */
9bcb3eef 3356 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3357 if (pi->peer == peer && pi->type == type
3358 && pi->sub_type == sub_type
3359 && pi->addpath_rx_id == addpath_id)
d62a17ae 3360 break;
3361
3362 /* AS path local-as loop check. */
3363 if (peer->change_local_as) {
c4368918
DW
3364 if (peer->allowas_in[afi][safi])
3365 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3366 else if (!CHECK_FLAG(peer->flags,
3367 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3368 aspath_loop_count = 1;
3369
3370 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3371 > aspath_loop_count) {
b4d46cc9 3372 peer->stat_pfx_aspath_loop++;
9bcb3eef 3373 reason = "as-path contains our own AS A;";
d62a17ae 3374 goto filtered;
3375 }
718e3744 3376 }
718e3744 3377
d62a17ae 3378 /* If the peer is configured for "allowas-in origin" and the last ASN in
3379 * the
3380 * as-path is our ASN then we do not need to call aspath_loop_check
3381 */
3382 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3383 if (aspath_get_last_as(attr->aspath) == bgp->as)
3384 do_loop_check = 0;
3385
3386 /* AS path loop check. */
3387 if (do_loop_check) {
3388 if (aspath_loop_check(attr->aspath, bgp->as)
3389 > peer->allowas_in[afi][safi]
3390 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3391 && aspath_loop_check(attr->aspath, bgp->confed_id)
3392 > peer->allowas_in[afi][safi])) {
b4d46cc9 3393 peer->stat_pfx_aspath_loop++;
d62a17ae 3394 reason = "as-path contains our own AS;";
3395 goto filtered;
3396 }
3397 }
aac9ef6c 3398
d62a17ae 3399 /* Route reflector originator ID check. */
3400 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3401 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3402 peer->stat_pfx_originator_loop++;
d62a17ae 3403 reason = "originator is us;";
3404 goto filtered;
3405 }
718e3744 3406
d62a17ae 3407 /* Route reflector cluster ID check. */
3408 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3409 peer->stat_pfx_cluster_loop++;
d62a17ae 3410 reason = "reflected from the same cluster;";
3411 goto filtered;
3412 }
718e3744 3413
d62a17ae 3414 /* Apply incoming filter. */
3415 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3416 peer->stat_pfx_filter++;
d62a17ae 3417 reason = "filter;";
3418 goto filtered;
3419 }
718e3744 3420
a8b72dc6
DA
3421 /* RFC 8212 to prevent route leaks.
3422 * This specification intends to improve this situation by requiring the
3423 * explicit configuration of both BGP Import and Export Policies for any
3424 * External BGP (EBGP) session such as customers, peers, or
3425 * confederation boundaries for all enabled address families. Through
3426 * codification of the aforementioned requirement, operators will
3427 * benefit from consistent behavior across different BGP
3428 * implementations.
3429 */
1d3fdccf 3430 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3431 if (!bgp_inbound_policy_exists(peer,
3432 &peer->filter[afi][safi])) {
3433 reason = "inbound policy missing";
3434 goto filtered;
3435 }
3436
fb29348a
DA
3437 /* draft-ietf-idr-deprecate-as-set-confed-set
3438 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3439 * Eventually, This document (if approved) updates RFC 4271
3440 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3441 * and obsoletes RFC 6472.
3442 */
7f972cd8 3443 if (peer->bgp->reject_as_sets)
fb29348a
DA
3444 if (aspath_check_as_sets(attr->aspath)) {
3445 reason =
3446 "as-path contains AS_SET or AS_CONFED_SET type;";
3447 goto filtered;
3448 }
3449
6f4f49b2 3450 new_attr = *attr;
d62a17ae 3451
3452 /* Apply incoming route-map.
3453 * NB: new_attr may now contain newly allocated values from route-map
3454 * "set"
3455 * commands, so we need bgp_attr_flush in the error paths, until we
3456 * intern
3457 * the attr (which takes over the memory references) */
9bcb3eef
DS
3458 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3459 num_labels, dest)
3460 == RMAP_DENY) {
b4d46cc9 3461 peer->stat_pfx_filter++;
d62a17ae 3462 reason = "route-map;";
3463 bgp_attr_flush(&new_attr);
3464 goto filtered;
3465 }
718e3744 3466
05864da7 3467 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3468 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3469 /* remove from RIB previous entry */
3470 bgp_zebra_withdraw(p, pi, bgp, safi);
3471 }
3472
7f323236
DW
3473 if (peer->sort == BGP_PEER_EBGP) {
3474
a4d82a8a
PZ
3475 /* If we receive the graceful-shutdown community from an eBGP
3476 * peer we must lower local-preference */
3477 if (new_attr.community
3478 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3479 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3480 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3481
a4d82a8a
PZ
3482 /* If graceful-shutdown is configured then add the GSHUT
3483 * community to all paths received from eBGP peers */
892fedb6
DA
3484 } else if (CHECK_FLAG(peer->bgp->flags,
3485 BGP_FLAG_GRACEFUL_SHUTDOWN))
7f323236 3486 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3487 }
3488
949b0f24 3489 if (pi) {
3490 pi_type = pi->type;
3491 pi_sub_type = pi->sub_type;
3492 }
3493
d62a17ae 3494 /* next hop check. */
a4d82a8a 3495 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3496 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3497 &new_attr, dest)) {
b4d46cc9 3498 peer->stat_pfx_nh_invalid++;
d62a17ae 3499 reason = "martian or self next-hop;";
3500 bgp_attr_flush(&new_attr);
3501 goto filtered;
3502 }
718e3744 3503
5c14a191 3504 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3505 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3506 reason = "self mac;";
3507 goto filtered;
3508 }
3509
d62a17ae 3510 attr_new = bgp_attr_intern(&new_attr);
3511
3512 /* If the update is implicit withdraw. */
40381db7
DS
3513 if (pi) {
3514 pi->uptime = bgp_clock();
3515 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3516
9bcb3eef 3517 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3518
d62a17ae 3519 /* Same attribute comes in. */
40381db7
DS
3520 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3521 && attrhash_cmp(pi->attr, attr_new)
d62a17ae 3522 && (!has_valid_label
40381db7 3523 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3524 num_labels * sizeof(mpls_label_t))
d62a17ae 3525 == 0)
3526 && (overlay_index_equal(
40381db7 3527 afi, pi, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3528 evpn == NULL ? NULL : &evpn->gw_ip))) {
3529 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3530 BGP_CONFIG_DAMPENING)
3531 && peer->sort == BGP_PEER_EBGP
40381db7 3532 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3533 if (bgp_debug_update(peer, p, NULL, 1)) {
3534 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3535 afi, safi, prd, p, label,
3536 num_labels, addpath_id ? 1 : 0,
3537 addpath_id, pfx_buf,
3538 sizeof(pfx_buf));
d62a17ae 3539 zlog_debug("%s rcvd %s", peer->host,
3540 pfx_buf);
3541 }
3542
9bcb3eef 3543 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 3544 != BGP_DAMP_SUPPRESSED) {
40381db7 3545 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3546 safi);
9bcb3eef 3547 bgp_process(bgp, dest, afi, safi);
d62a17ae 3548 }
3549 } else /* Duplicate - odd */
3550 {
3551 if (bgp_debug_update(peer, p, NULL, 1)) {
3552 if (!peer->rcvd_attr_printed) {
3553 zlog_debug(
3554 "%s rcvd UPDATE w/ attr: %s",
3555 peer->host,
3556 peer->rcvd_attr_str);
3557 peer->rcvd_attr_printed = 1;
3558 }
3559
3560 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3561 afi, safi, prd, p, label,
3562 num_labels, addpath_id ? 1 : 0,
3563 addpath_id, pfx_buf,
3564 sizeof(pfx_buf));
d62a17ae 3565 zlog_debug(
3566 "%s rcvd %s...duplicate ignored",
3567 peer->host, pfx_buf);
3568 }
3569
3570 /* graceful restart STALE flag unset. */
40381db7 3571 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3572 bgp_path_info_unset_flag(
9bcb3eef
DS
3573 dest, pi, BGP_PATH_STALE);
3574 bgp_dest_set_defer_flag(dest, false);
3575 bgp_process(bgp, dest, afi, safi);
d62a17ae 3576 }
3577 }
3578
9bcb3eef 3579 bgp_dest_unlock_node(dest);
d62a17ae 3580 bgp_attr_unintern(&attr_new);
3581
3582 return 0;
3583 }
718e3744 3584
d62a17ae 3585 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3586 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3587 if (bgp_debug_update(peer, p, NULL, 1)) {
3588 bgp_debug_rdpfxpath2str(
a4d82a8a 3589 afi, safi, prd, p, label, num_labels,
d62a17ae 3590 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3591 sizeof(pfx_buf));
3592 zlog_debug(
3593 "%s rcvd %s, flapped quicker than processing",
3594 peer->host, pfx_buf);
3595 }
3596
9bcb3eef 3597 bgp_path_info_restore(dest, pi);
d62a17ae 3598 }
718e3744 3599
d62a17ae 3600 /* Received Logging. */
3601 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3602 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3603 num_labels, addpath_id ? 1 : 0,
3604 addpath_id, pfx_buf,
3605 sizeof(pfx_buf));
d62a17ae 3606 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3607 }
718e3744 3608
d62a17ae 3609 /* graceful restart STALE flag unset. */
f009ff26 3610 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
3611 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3612 bgp_dest_set_defer_flag(dest, false);
f009ff26 3613 }
d62a17ae 3614
3615 /* The attribute is changed. */
9bcb3eef 3616 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3617
3618 /* implicit withdraw, decrement aggregate and pcount here.
3619 * only if update is accepted, they'll increment below.
3620 */
40381db7 3621 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3622
3623 /* Update bgp route dampening information. */
3624 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3625 && peer->sort == BGP_PEER_EBGP) {
3626 /* This is implicit withdraw so we should update
3627 dampening
3628 information. */
40381db7 3629 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 3630 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 3631 }
49e5a4a0 3632#ifdef ENABLE_BGP_VNC
d62a17ae 3633 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3634 struct bgp_dest *pdest = NULL;
d62a17ae 3635 struct bgp_table *table = NULL;
3636
9bcb3eef
DS
3637 pdest = bgp_node_get(bgp->rib[afi][safi],
3638 (struct prefix *)prd);
3639 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3640 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3641
3642 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3643 bgp, prd, table, p, pi);
d62a17ae 3644 }
9bcb3eef 3645 bgp_dest_unlock_node(pdest);
d62a17ae 3646 }
3647 if ((afi == AFI_IP || afi == AFI_IP6)
3648 && (safi == SAFI_UNICAST)) {
40381db7 3649 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3650 /*
3651 * Implicit withdraw case.
3652 */
3653 ++vnc_implicit_withdraw;
40381db7
DS
3654 vnc_import_bgp_del_route(bgp, p, pi);
3655 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3656 }
3657 }
65efcfce 3658#endif
128ea8ab 3659
d62a17ae 3660 /* Special handling for EVPN update of an existing route. If the
3661 * extended community attribute has changed, we need to
3662 * un-import
3663 * the route using its existing extended community. It will be
3664 * subsequently processed for import with the new extended
3665 * community.
3666 */
6f8c9c11
PR
3667 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
3668 && !same_attr) {
40381db7 3669 if ((pi->attr->flag
d62a17ae 3670 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3671 && (attr_new->flag
3672 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3673 int cmp;
3674
40381db7 3675 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3676 attr_new->ecommunity);
3677 if (!cmp) {
3678 if (bgp_debug_update(peer, p, NULL, 1))
3679 zlog_debug(
3680 "Change in EXT-COMM, existing %s new %s",
3681 ecommunity_str(
40381db7 3682 pi->attr->ecommunity),
d62a17ae 3683 ecommunity_str(
3684 attr_new->ecommunity));
6f8c9c11
PR
3685 if (safi == SAFI_EVPN)
3686 bgp_evpn_unimport_route(
3687 bgp, afi, safi, p, pi);
3688 else /* SAFI_MPLS_VPN */
3689 vpn_leak_to_vrf_withdraw(bgp,
3690 pi);
d62a17ae 3691 }
3692 }
3693 }
718e3744 3694
d62a17ae 3695 /* Update to new attribute. */
40381db7
DS
3696 bgp_attr_unintern(&pi->attr);
3697 pi->attr = attr_new;
d62a17ae 3698
3699 /* Update MPLS label */
3700 if (has_valid_label) {
40381db7 3701 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3702 if (extra->label != label) {
3703 memcpy(&extra->label, label,
dbd587da 3704 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3705 extra->num_labels = num_labels;
3706 }
b57ba6d2
MK
3707 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3708 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3709 }
718e3744 3710
e496b420
HS
3711 /* Update SRv6 SID */
3712 if (attr->srv6_l3vpn) {
3713 extra = bgp_path_info_extra_get(pi);
3714 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
3715 sid_copy(&extra->sid[0],
3716 &attr->srv6_l3vpn->sid);
3717 extra->num_sids = 1;
3718 }
3719 } else if (attr->srv6_vpn) {
3720 extra = bgp_path_info_extra_get(pi);
3721 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
3722 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3723 extra->num_sids = 1;
3724 }
3725 }
3726
49e5a4a0 3727#ifdef ENABLE_BGP_VNC
d62a17ae 3728 if ((afi == AFI_IP || afi == AFI_IP6)
3729 && (safi == SAFI_UNICAST)) {
3730 if (vnc_implicit_withdraw) {
3731 /*
3732 * Add back the route with its new attributes
3733 * (e.g., nexthop).
3734 * The route is still selected, until the route
3735 * selection
3736 * queued by bgp_process actually runs. We have
3737 * to make this
3738 * update to the VNC side immediately to avoid
3739 * racing against
3740 * configuration changes (e.g., route-map
3741 * changes) which
3742 * trigger re-importation of the entire RIB.
3743 */
40381db7
DS
3744 vnc_import_bgp_add_route(bgp, p, pi);
3745 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 3746 }
3747 }
65efcfce 3748#endif
d62a17ae 3749 /* Update Overlay Index */
3750 if (afi == AFI_L2VPN) {
3751 overlay_index_update(
40381db7 3752 pi->attr, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3753 evpn == NULL ? NULL : &evpn->gw_ip);
3754 }
65efcfce 3755
d62a17ae 3756 /* Update bgp route dampening information. */
3757 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3758 && peer->sort == BGP_PEER_EBGP) {
3759 /* Now we do normal update dampening. */
9bcb3eef 3760 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 3761 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 3762 bgp_dest_unlock_node(dest);
d62a17ae 3763 return 0;
3764 }
3765 }
128ea8ab 3766
d62a17ae 3767 /* Nexthop reachability check - for unicast and
3768 * labeled-unicast.. */
7c312383
AD
3769 if (((afi == AFI_IP || afi == AFI_IP6)
3770 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3771 || (safi == SAFI_EVPN &&
3772 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
3773 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
3774 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 3775 && !CHECK_FLAG(peer->flags,
3776 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
3777 && !CHECK_FLAG(bgp->flags,
3778 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 3779 connected = 1;
3780 else
3781 connected = 0;
3782
960035b2
PZ
3783 struct bgp *bgp_nexthop = bgp;
3784
40381db7
DS
3785 if (pi->extra && pi->extra->bgp_orig)
3786 bgp_nexthop = pi->extra->bgp_orig;
960035b2 3787
7c312383
AD
3788 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
3789
3790 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
3791 pi, NULL, connected)
a4d82a8a 3792 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
3793 bgp_path_info_set_flag(dest, pi,
3794 BGP_PATH_VALID);
d62a17ae 3795 else {
3796 if (BGP_DEBUG(nht, NHT)) {
3797 char buf1[INET6_ADDRSTRLEN];
3798 inet_ntop(AF_INET,
3799 (const void *)&attr_new
3800 ->nexthop,
3801 buf1, INET6_ADDRSTRLEN);
3802 zlog_debug("%s(%s): NH unresolved",
15569c58 3803 __func__, buf1);
d62a17ae 3804 }
9bcb3eef 3805 bgp_path_info_unset_flag(dest, pi,
18ee8310 3806 BGP_PATH_VALID);
d62a17ae 3807 }
3808 } else
9bcb3eef 3809 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 3810
49e5a4a0 3811#ifdef ENABLE_BGP_VNC
d62a17ae 3812 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3813 struct bgp_dest *pdest = NULL;
d62a17ae 3814 struct bgp_table *table = NULL;
3815
9bcb3eef
DS
3816 pdest = bgp_node_get(bgp->rib[afi][safi],
3817 (struct prefix *)prd);
3818 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3819 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3820
3821 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 3822 bgp, prd, table, p, pi);
d62a17ae 3823 }
9bcb3eef 3824 bgp_dest_unlock_node(pdest);
d62a17ae 3825 }
3826#endif
718e3744 3827
d62a17ae 3828 /* If this is an EVPN route and some attribute has changed,
3829 * process
3830 * route for import. If the extended community has changed, we
3831 * would
3832 * have done the un-import earlier and the import would result
3833 * in the
3834 * route getting injected into appropriate L2 VNIs. If it is
3835 * just
3836 * some other attribute change, the import will result in
3837 * updating
3838 * the attributes for the route in the VNI(s).
3839 */
7c312383
AD
3840 if (safi == SAFI_EVPN && !same_attr &&
3841 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 3842 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 3843
3844 /* Process change. */
40381db7 3845 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 3846
9bcb3eef
DS
3847 bgp_process(bgp, dest, afi, safi);
3848 bgp_dest_unlock_node(dest);
558d1fec 3849
ddb5b488
PZ
3850 if (SAFI_UNICAST == safi
3851 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3852 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3853
40381db7 3854 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3855 }
3856 if ((SAFI_MPLS_VPN == safi)
3857 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3858
40381db7 3859 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
3860 }
3861
49e5a4a0 3862#ifdef ENABLE_BGP_VNC
d62a17ae 3863 if (SAFI_MPLS_VPN == safi) {
3864 mpls_label_t label_decoded = decode_label(label);
28070ee3 3865
d62a17ae 3866 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3867 type, sub_type, &label_decoded);
3868 }
3869 if (SAFI_ENCAP == safi) {
3870 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3871 type, sub_type, NULL);
3872 }
28070ee3
PZ
3873#endif
3874
d62a17ae 3875 return 0;
3876 } // End of implicit withdraw
718e3744 3877
d62a17ae 3878 /* Received Logging. */
3879 if (bgp_debug_update(peer, p, NULL, 1)) {
3880 if (!peer->rcvd_attr_printed) {
3881 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3882 peer->rcvd_attr_str);
3883 peer->rcvd_attr_printed = 1;
3884 }
718e3744 3885
a4d82a8a 3886 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3887 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3888 sizeof(pfx_buf));
3889 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3890 }
718e3744 3891
d62a17ae 3892 /* Make new BGP info. */
9bcb3eef 3893 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 3894
d62a17ae 3895 /* Update MPLS label */
3896 if (has_valid_label) {
18ee8310 3897 extra = bgp_path_info_extra_get(new);
8ba71050 3898 if (extra->label != label) {
dbd587da
QY
3899 memcpy(&extra->label, label,
3900 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3901 extra->num_labels = num_labels;
3902 }
b57ba6d2
MK
3903 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3904 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3905 }
718e3744 3906
e496b420
HS
3907 /* Update SRv6 SID */
3908 if (safi == SAFI_MPLS_VPN) {
3909 extra = bgp_path_info_extra_get(new);
3910 if (attr->srv6_l3vpn) {
3911 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
3912 extra->num_sids = 1;
3913 } else if (attr->srv6_vpn) {
3914 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3915 extra->num_sids = 1;
3916 }
3917 }
3918
d62a17ae 3919 /* Update Overlay Index */
3920 if (afi == AFI_L2VPN) {
3921 overlay_index_update(new->attr,
3922 evpn == NULL ? NULL : &evpn->eth_s_id,
3923 evpn == NULL ? NULL : &evpn->gw_ip);
3924 }
3925 /* Nexthop reachability check. */
7c312383
AD
3926 if (((afi == AFI_IP || afi == AFI_IP6)
3927 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3928 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
3929 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
3930 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 3931 && !CHECK_FLAG(peer->flags,
3932 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
3933 && !CHECK_FLAG(bgp->flags,
3934 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 3935 connected = 1;
3936 else
3937 connected = 0;
3938
7c312383
AD
3939 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
3940
3941 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, new, NULL,
3942 connected)
a4d82a8a 3943 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 3944 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 3945 else {
3946 if (BGP_DEBUG(nht, NHT)) {
3947 char buf1[INET6_ADDRSTRLEN];
3948 inet_ntop(AF_INET,
3949 (const void *)&attr_new->nexthop,
3950 buf1, INET6_ADDRSTRLEN);
15569c58
DA
3951 zlog_debug("%s(%s): NH unresolved", __func__,
3952 buf1);
d62a17ae 3953 }
9bcb3eef 3954 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 3955 }
3956 } else
9bcb3eef 3957 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 3958
d62a17ae 3959 /* Addpath ID */
3960 new->addpath_rx_id = addpath_id;
3961
3962 /* Increment prefix */
3963 bgp_aggregate_increment(bgp, p, new, afi, safi);
3964
3965 /* Register new BGP information. */
9bcb3eef 3966 bgp_path_info_add(dest, new);
d62a17ae 3967
3968 /* route_node_get lock */
9bcb3eef 3969 bgp_dest_unlock_node(dest);
558d1fec 3970
49e5a4a0 3971#ifdef ENABLE_BGP_VNC
d62a17ae 3972 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3973 struct bgp_dest *pdest = NULL;
d62a17ae 3974 struct bgp_table *table = NULL;
3975
9bcb3eef
DS
3976 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
3977 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3978 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3979
3980 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3981 bgp, prd, table, p, new);
3982 }
9bcb3eef 3983 bgp_dest_unlock_node(pdest);
d62a17ae 3984 }
65efcfce
LB
3985#endif
3986
d62a17ae 3987 /* If maximum prefix count is configured and current prefix
3988 count exeed it. */
3989 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3990 return -1;
718e3744 3991
d62a17ae 3992 /* If this is an EVPN route, process for import. */
7c312383 3993 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 3994 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 3995
9bcb3eef 3996 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 3997
d62a17ae 3998 /* Process change. */
9bcb3eef 3999 bgp_process(bgp, dest, afi, safi);
718e3744 4000
ddb5b488
PZ
4001 if (SAFI_UNICAST == safi
4002 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4003 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4004 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4005 }
4006 if ((SAFI_MPLS_VPN == safi)
4007 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4008
4009 vpn_leak_to_vrf_update(bgp, new);
4010 }
49e5a4a0 4011#ifdef ENABLE_BGP_VNC
d62a17ae 4012 if (SAFI_MPLS_VPN == safi) {
4013 mpls_label_t label_decoded = decode_label(label);
28070ee3 4014
d62a17ae 4015 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4016 sub_type, &label_decoded);
4017 }
4018 if (SAFI_ENCAP == safi) {
4019 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4020 sub_type, NULL);
4021 }
28070ee3
PZ
4022#endif
4023
d62a17ae 4024 return 0;
718e3744 4025
d62a17ae 4026/* This BGP update is filtered. Log the reason then update BGP
4027 entry. */
4028filtered:
9bcb3eef 4029 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4030
d62a17ae 4031 if (bgp_debug_update(peer, p, NULL, 1)) {
4032 if (!peer->rcvd_attr_printed) {
4033 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4034 peer->rcvd_attr_str);
4035 peer->rcvd_attr_printed = 1;
4036 }
718e3744 4037
a4d82a8a 4038 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4039 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4040 sizeof(pfx_buf));
4041 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4042 peer->host, pfx_buf, reason);
4043 }
128ea8ab 4044
40381db7 4045 if (pi) {
d62a17ae 4046 /* If this is an EVPN route, un-import it as it is now filtered.
4047 */
4048 if (safi == SAFI_EVPN)
40381db7 4049 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4050
ddb5b488
PZ
4051 if (SAFI_UNICAST == safi
4052 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4053 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4054
40381db7 4055 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4056 }
4057 if ((SAFI_MPLS_VPN == safi)
4058 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4059
40381db7 4060 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4061 }
4062
9bcb3eef 4063 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4064 }
4065
9bcb3eef 4066 bgp_dest_unlock_node(dest);
558d1fec 4067
49e5a4a0 4068#ifdef ENABLE_BGP_VNC
d62a17ae 4069 /*
4070 * Filtered update is treated as an implicit withdrawal (see
4071 * bgp_rib_remove()
4072 * a few lines above)
4073 */
4074 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4075 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4076 0);
4077 }
97736e32
PZ
4078#endif
4079
d62a17ae 4080 return 0;
718e3744 4081}
4082
26a3ffd6 4083int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4084 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4085 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4086 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4087{
d62a17ae 4088 struct bgp *bgp;
4089 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4090 struct bgp_dest *dest;
40381db7 4091 struct bgp_path_info *pi;
718e3744 4092
49e5a4a0 4093#ifdef ENABLE_BGP_VNC
d62a17ae 4094 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4095 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4096 0);
4097 }
28070ee3
PZ
4098#endif
4099
d62a17ae 4100 bgp = peer->bgp;
4101
4102 /* Lookup node. */
9bcb3eef 4103 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4104
4105 /* If peer is soft reconfiguration enabled. Record input packet for
4106 * further calculation.
4107 *
4108 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4109 * routes that are filtered. This tanks out Quagga RS pretty badly due
4110 * to
4111 * the iteration over all RS clients.
4112 * Since we need to remove the entry from adj_in anyway, do that first
4113 * and
4114 * if there was no entry, we don't need to do anything more.
4115 */
4116 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4117 && peer != bgp->peer_self)
9bcb3eef 4118 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4119 peer->stat_pfx_dup_withdraw++;
4120
d62a17ae 4121 if (bgp_debug_update(peer, p, NULL, 1)) {
4122 bgp_debug_rdpfxpath2str(
a4d82a8a 4123 afi, safi, prd, p, label, num_labels,
d62a17ae 4124 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4125 sizeof(pfx_buf));
4126 zlog_debug(
4127 "%s withdrawing route %s not in adj-in",
4128 peer->host, pfx_buf);
4129 }
9bcb3eef 4130 bgp_dest_unlock_node(dest);
d62a17ae 4131 return 0;
4132 }
cd808e74 4133
d62a17ae 4134 /* Lookup withdrawn route. */
9bcb3eef 4135 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4136 if (pi->peer == peer && pi->type == type
4137 && pi->sub_type == sub_type
4138 && pi->addpath_rx_id == addpath_id)
d62a17ae 4139 break;
4140
4141 /* Logging. */
4142 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4143 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4144 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4145 sizeof(pfx_buf));
4146 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4147 pfx_buf);
4148 }
718e3744 4149
d62a17ae 4150 /* Withdraw specified route from routing table. */
40381db7 4151 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4152 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4153 if (SAFI_UNICAST == safi
4154 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4155 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4156 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4157 }
4158 if ((SAFI_MPLS_VPN == safi)
4159 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4160
40381db7 4161 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4162 }
4163 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4164 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4165 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4166 sizeof(pfx_buf));
4167 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4168 }
718e3744 4169
d62a17ae 4170 /* Unlock bgp_node_get() lock. */
9bcb3eef 4171 bgp_dest_unlock_node(dest);
d62a17ae 4172
4173 return 0;
718e3744 4174}
6b0655a2 4175
d62a17ae 4176void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4177 int withdraw)
718e3744 4178{
d62a17ae 4179 struct update_subgroup *subgrp;
4180 subgrp = peer_subgroup(peer, afi, safi);
4181 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4182}
6182d65b 4183
718e3744 4184
3f9c7369
DS
4185/*
4186 * bgp_stop_announce_route_timer
4187 */
d62a17ae 4188void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4189{
d62a17ae 4190 if (!paf->t_announce_route)
4191 return;
4192
4193 THREAD_TIMER_OFF(paf->t_announce_route);
718e3744 4194}
6b0655a2 4195
3f9c7369
DS
4196/*
4197 * bgp_announce_route_timer_expired
4198 *
4199 * Callback that is invoked when the route announcement timer for a
4200 * peer_af expires.
4201 */
d62a17ae 4202static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4203{
d62a17ae 4204 struct peer_af *paf;
4205 struct peer *peer;
558d1fec 4206
d62a17ae 4207 paf = THREAD_ARG(t);
4208 peer = paf->peer;
718e3744 4209
d62a17ae 4210 if (peer->status != Established)
4211 return 0;
3f9c7369 4212
d62a17ae 4213 if (!peer->afc_nego[paf->afi][paf->safi])
4214 return 0;
3f9c7369 4215
d62a17ae 4216 peer_af_announce_route(paf, 1);
4217 return 0;
718e3744 4218}
4219
3f9c7369
DS
4220/*
4221 * bgp_announce_route
4222 *
4223 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4224 */
d62a17ae 4225void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4226{
4227 struct peer_af *paf;
4228 struct update_subgroup *subgrp;
4229
4230 paf = peer_af_find(peer, afi, safi);
4231 if (!paf)
4232 return;
4233 subgrp = PAF_SUBGRP(paf);
4234
4235 /*
4236 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4237 * or a refresh has already been triggered.
4238 */
4239 if (!subgrp || paf->t_announce_route)
4240 return;
4241
4242 /*
4243 * Start a timer to stagger/delay the announce. This serves
4244 * two purposes - announcement can potentially be combined for
4245 * multiple peers and the announcement doesn't happen in the
4246 * vty context.
4247 */
4248 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4249 (subgrp->peer_count == 1)
4250 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4251 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4252 &paf->t_announce_route);
3f9c7369
DS
4253}
4254
4255/*
4256 * Announce routes from all AF tables to a peer.
4257 *
4258 * This should ONLY be called when there is a need to refresh the
4259 * routes to the peer based on a policy change for this peer alone
4260 * or a route refresh request received from the peer.
4261 * The operation will result in splitting the peer from its existing
4262 * subgroups and putting it in new subgroups.
4263 */
d62a17ae 4264void bgp_announce_route_all(struct peer *peer)
718e3744 4265{
d62a17ae 4266 afi_t afi;
4267 safi_t safi;
4268
05c7a1cc
QY
4269 FOREACH_AFI_SAFI (afi, safi)
4270 bgp_announce_route(peer, afi, safi);
718e3744 4271}
6b0655a2 4272
d62a17ae 4273static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4274 struct bgp_table *table,
4275 struct prefix_rd *prd)
718e3744 4276{
d62a17ae 4277 int ret;
9bcb3eef 4278 struct bgp_dest *dest;
d62a17ae 4279 struct bgp_adj_in *ain;
718e3744 4280
d62a17ae 4281 if (!table)
4282 table = peer->bgp->rib[afi][safi];
718e3744 4283
9bcb3eef
DS
4284 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4285 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4286 if (ain->peer != peer)
4287 continue;
8692c506 4288
d7d15889 4289 struct bgp_path_info *pi;
d7c0a89a 4290 uint32_t num_labels = 0;
b57ba6d2 4291 mpls_label_t *label_pnt = NULL;
8cb687c2 4292 struct bgp_route_evpn evpn;
b57ba6d2 4293
9bcb3eef 4294 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
d7d15889
DS
4295 pi = pi->next)
4296 if (pi->peer == peer)
4297 break;
4298
40381db7
DS
4299 if (pi && pi->extra)
4300 num_labels = pi->extra->num_labels;
b57ba6d2 4301 if (num_labels)
40381db7 4302 label_pnt = &pi->extra->label[0];
8cb687c2
DS
4303 if (pi)
4304 memcpy(&evpn, &pi->attr->evpn_overlay,
4305 sizeof(evpn));
4306 else
4307 memset(&evpn, 0, sizeof(evpn));
8692c506 4308
9bcb3eef
DS
4309 ret = bgp_update(peer, bgp_dest_get_prefix(dest),
4310 ain->addpath_rx_id, ain->attr, afi,
4311 safi, ZEBRA_ROUTE_BGP,
a4d82a8a 4312 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 4313 num_labels, 1, &evpn);
ea47320b
DL
4314
4315 if (ret < 0) {
9bcb3eef 4316 bgp_dest_unlock_node(dest);
ea47320b 4317 return;
d62a17ae 4318 }
4319 }
718e3744 4320}
4321
d62a17ae 4322void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4323{
9bcb3eef 4324 struct bgp_dest *dest;
d62a17ae 4325 struct bgp_table *table;
718e3744 4326
d62a17ae 4327 if (peer->status != Established)
4328 return;
718e3744 4329
d62a17ae 4330 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4331 && (safi != SAFI_EVPN))
4332 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4333 else
9bcb3eef
DS
4334 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4335 dest = bgp_route_next(dest)) {
4336 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4337
b54892e0
DS
4338 if (table == NULL)
4339 continue;
8692c506 4340
9bcb3eef 4341 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
4342 struct prefix_rd prd;
4343
4344 prd.family = AF_UNSPEC;
4345 prd.prefixlen = 64;
4346 memcpy(&prd.val, p->u.val, 8);
4347
4348 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 4349 }
718e3744 4350}
6b0655a2 4351
228da428 4352
d62a17ae 4353struct bgp_clear_node_queue {
9bcb3eef 4354 struct bgp_dest *dest;
228da428
CC
4355};
4356
d62a17ae 4357static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4358{
d62a17ae 4359 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 4360 struct bgp_dest *dest = cnq->dest;
d62a17ae 4361 struct peer *peer = wq->spec.data;
40381db7 4362 struct bgp_path_info *pi;
3103e8d2 4363 struct bgp *bgp;
9bcb3eef
DS
4364 afi_t afi = bgp_dest_table(dest)->afi;
4365 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 4366
9bcb3eef 4367 assert(dest && peer);
3103e8d2 4368 bgp = peer->bgp;
d62a17ae 4369
4370 /* It is possible that we have multiple paths for a prefix from a peer
4371 * if that peer is using AddPath.
4372 */
9bcb3eef 4373 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 4374 if (pi->peer != peer)
ea47320b
DL
4375 continue;
4376
4377 /* graceful restart STALE flag set. */
4378 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4379 && peer->nsf[afi][safi]
40381db7
DS
4380 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4381 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 4382 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
4383 else {
4384 /* If this is an EVPN route, process for
4385 * un-import. */
4386 if (safi == SAFI_EVPN)
9bcb3eef
DS
4387 bgp_evpn_unimport_route(
4388 bgp, afi, safi,
4389 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
4390 /* Handle withdraw for VRF route-leaking and L3VPN */
4391 if (SAFI_UNICAST == safi
4392 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4393 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4394 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4395 bgp, pi);
960035b2 4396 }
3103e8d2 4397 if (SAFI_MPLS_VPN == safi &&
960035b2 4398 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4399 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4400 }
3103e8d2 4401
9bcb3eef 4402 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4403 }
ea47320b 4404 }
d62a17ae 4405 return WQ_SUCCESS;
200df115 4406}
4407
d62a17ae 4408static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4409{
d62a17ae 4410 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
4411 struct bgp_dest *dest = cnq->dest;
4412 struct bgp_table *table = bgp_dest_table(dest);
228da428 4413
9bcb3eef 4414 bgp_dest_unlock_node(dest);
d62a17ae 4415 bgp_table_unlock(table);
4416 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4417}
4418
d62a17ae 4419static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4420{
d62a17ae 4421 struct peer *peer = wq->spec.data;
64e580a7 4422
d62a17ae 4423 /* Tickle FSM to start moving again */
4424 BGP_EVENT_ADD(peer, Clearing_Completed);
4425
4426 peer_unlock(peer); /* bgp_clear_route */
200df115 4427}
718e3744 4428
d62a17ae 4429static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4430{
d62a17ae 4431 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4432
4433 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4434#undef CLEAR_QUEUE_NAME_LEN
4435
0ce1ca80 4436 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4437 peer->clear_node_queue->spec.hold = 10;
4438 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4439 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4440 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4441 peer->clear_node_queue->spec.max_retries = 0;
4442
4443 /* we only 'lock' this peer reference when the queue is actually active
4444 */
4445 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4446}
4447
d62a17ae 4448static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4449 struct bgp_table *table)
65ca75e0 4450{
9bcb3eef 4451 struct bgp_dest *dest;
d62a17ae 4452 int force = bm->process_main_queue ? 0 : 1;
6cf159b9 4453
d62a17ae 4454 if (!table)
4455 table = peer->bgp->rib[afi][safi];
dc83d712 4456
d62a17ae 4457 /* If still no table => afi/safi isn't configured at all or smth. */
4458 if (!table)
4459 return;
dc83d712 4460
9bcb3eef 4461 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 4462 struct bgp_path_info *pi, *next;
d62a17ae 4463 struct bgp_adj_in *ain;
4464 struct bgp_adj_in *ain_next;
4465
4466 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4467 * queued for every clearing peer, regardless of whether it is
4468 * relevant to the peer at hand.
4469 *
4470 * Overview: There are 3 different indices which need to be
4471 * scrubbed, potentially, when a peer is removed:
4472 *
4473 * 1 peer's routes visible via the RIB (ie accepted routes)
4474 * 2 peer's routes visible by the (optional) peer's adj-in index
4475 * 3 other routes visible by the peer's adj-out index
4476 *
4477 * 3 there is no hurry in scrubbing, once the struct peer is
4478 * removed from bgp->peer, we could just GC such deleted peer's
4479 * adj-outs at our leisure.
4480 *
4481 * 1 and 2 must be 'scrubbed' in some way, at least made
4482 * invisible via RIB index before peer session is allowed to be
4483 * brought back up. So one needs to know when such a 'search' is
4484 * complete.
4485 *
4486 * Ideally:
4487 *
4488 * - there'd be a single global queue or a single RIB walker
4489 * - rather than tracking which route_nodes still need to be
4490 * examined on a peer basis, we'd track which peers still
4491 * aren't cleared
4492 *
4493 * Given that our per-peer prefix-counts now should be reliable,
4494 * this may actually be achievable. It doesn't seem to be a huge
4495 * problem at this time,
4496 *
4497 * It is possible that we have multiple paths for a prefix from
4498 * a peer
4499 * if that peer is using AddPath.
4500 */
9bcb3eef 4501 ain = dest->adj_in;
d62a17ae 4502 while (ain) {
4503 ain_next = ain->next;
4504
4505 if (ain->peer == peer) {
9bcb3eef
DS
4506 bgp_adj_in_remove(dest, ain);
4507 bgp_dest_unlock_node(dest);
d62a17ae 4508 }
4509
4510 ain = ain_next;
4511 }
4512
9bcb3eef 4513 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
4514 next = pi->next;
4515 if (pi->peer != peer)
d62a17ae 4516 continue;
4517
4518 if (force)
9bcb3eef 4519 bgp_path_info_reap(dest, pi);
d62a17ae 4520 else {
4521 struct bgp_clear_node_queue *cnq;
4522
4523 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
4524 bgp_table_lock(bgp_dest_table(dest));
4525 bgp_dest_lock_node(dest);
d62a17ae 4526 cnq = XCALLOC(
4527 MTYPE_BGP_CLEAR_NODE_QUEUE,
4528 sizeof(struct bgp_clear_node_queue));
9bcb3eef 4529 cnq->dest = dest;
d62a17ae 4530 work_queue_add(peer->clear_node_queue, cnq);
4531 break;
4532 }
4533 }
4534 }
4535 return;
4536}
4537
4538void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4539{
9bcb3eef 4540 struct bgp_dest *dest;
d62a17ae 4541 struct bgp_table *table;
4542
4543 if (peer->clear_node_queue == NULL)
4544 bgp_clear_node_queue_init(peer);
4545
4546 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4547 * Idle until it receives a Clearing_Completed event. This protects
4548 * against peers which flap faster than we can we clear, which could
4549 * lead to:
4550 *
4551 * a) race with routes from the new session being installed before
4552 * clear_route_node visits the node (to delete the route of that
4553 * peer)
4554 * b) resource exhaustion, clear_route_node likely leads to an entry
4555 * on the process_main queue. Fast-flapping could cause that queue
4556 * to grow and grow.
4557 */
4558
4559 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4560 * the unlock will happen upon work-queue completion; other wise, the
4561 * unlock happens at the end of this function.
4562 */
4563 if (!peer->clear_node_queue->thread)
4564 peer_lock(peer);
4565
4566 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4567 bgp_clear_route_table(peer, afi, safi, NULL);
4568 else
9bcb3eef
DS
4569 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4570 dest = bgp_route_next(dest)) {
4571 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4572 if (!table)
4573 continue;
4574
4575 bgp_clear_route_table(peer, afi, safi, table);
4576 }
d62a17ae 4577
4578 /* unlock if no nodes got added to the clear-node-queue. */
4579 if (!peer->clear_node_queue->thread)
4580 peer_unlock(peer);
718e3744 4581}
d62a17ae 4582
4583void bgp_clear_route_all(struct peer *peer)
718e3744 4584{
d62a17ae 4585 afi_t afi;
4586 safi_t safi;
718e3744 4587
05c7a1cc
QY
4588 FOREACH_AFI_SAFI (afi, safi)
4589 bgp_clear_route(peer, afi, safi);
65efcfce 4590
49e5a4a0 4591#ifdef ENABLE_BGP_VNC
d62a17ae 4592 rfapiProcessPeerDown(peer);
65efcfce 4593#endif
718e3744 4594}
4595
d62a17ae 4596void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4597{
d62a17ae 4598 struct bgp_table *table;
9bcb3eef 4599 struct bgp_dest *dest;
d62a17ae 4600 struct bgp_adj_in *ain;
4601 struct bgp_adj_in *ain_next;
718e3744 4602
d62a17ae 4603 table = peer->bgp->rib[afi][safi];
718e3744 4604
d62a17ae 4605 /* It is possible that we have multiple paths for a prefix from a peer
4606 * if that peer is using AddPath.
4607 */
9bcb3eef
DS
4608 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4609 ain = dest->adj_in;
43143c8f 4610
d62a17ae 4611 while (ain) {
4612 ain_next = ain->next;
43143c8f 4613
d62a17ae 4614 if (ain->peer == peer) {
9bcb3eef
DS
4615 bgp_adj_in_remove(dest, ain);
4616 bgp_dest_unlock_node(dest);
d62a17ae 4617 }
43143c8f 4618
d62a17ae 4619 ain = ain_next;
4620 }
4621 }
718e3744 4622}
93406d87 4623
d62a17ae 4624void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4625{
9bcb3eef 4626 struct bgp_dest *dest;
40381db7 4627 struct bgp_path_info *pi;
d62a17ae 4628 struct bgp_table *table;
4629
4630 if (safi == SAFI_MPLS_VPN) {
9bcb3eef
DS
4631 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4632 dest = bgp_route_next(dest)) {
4633 struct bgp_dest *rm;
d62a17ae 4634
4635 /* look for neighbor in tables */
9bcb3eef 4636 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4637 if (!table)
ea47320b
DL
4638 continue;
4639
4640 for (rm = bgp_table_top(table); rm;
4641 rm = bgp_route_next(rm))
9bcb3eef 4642 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 4643 pi = pi->next) {
40381db7 4644 if (pi->peer != peer)
ea47320b 4645 continue;
40381db7 4646 if (!CHECK_FLAG(pi->flags,
1defdda8 4647 BGP_PATH_STALE))
ea47320b
DL
4648 break;
4649
40381db7 4650 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4651 break;
4652 }
d62a17ae 4653 }
4654 } else {
9bcb3eef
DS
4655 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4656 dest = bgp_route_next(dest))
4657 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 4658 pi = pi->next) {
40381db7 4659 if (pi->peer != peer)
ea47320b 4660 continue;
40381db7 4661 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4662 break;
9bcb3eef 4663 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
4664 break;
4665 }
d62a17ae 4666 }
93406d87 4667}
6b0655a2 4668
3dc339cd 4669bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 4670{
e0df4c04 4671 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 4672 return true;
e0df4c04 4673
9dac9fc8
DA
4674 if (peer->sort == BGP_PEER_EBGP
4675 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
4676 || FILTER_LIST_OUT_NAME(filter)
4677 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
4678 return true;
4679 return false;
9dac9fc8
DA
4680}
4681
3dc339cd 4682bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 4683{
e0df4c04 4684 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 4685 return true;
e0df4c04 4686
9dac9fc8
DA
4687 if (peer->sort == BGP_PEER_EBGP
4688 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
4689 || FILTER_LIST_IN_NAME(filter)
4690 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
4691 return true;
4692 return false;
9dac9fc8
DA
4693}
4694
568e10ca 4695static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
4696 safi_t safi)
bb86c601 4697{
9bcb3eef 4698 struct bgp_dest *dest;
40381db7 4699 struct bgp_path_info *pi;
4b7e6066 4700 struct bgp_path_info *next;
bb86c601 4701
9bcb3eef
DS
4702 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4703 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
4704 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 4705
40381db7 4706 next = pi->next;
1b7bb747
CS
4707
4708 /* Unimport EVPN routes from VRFs */
4709 if (safi == SAFI_EVPN)
4710 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 4711 SAFI_EVPN, p, pi);
1b7bb747 4712
40381db7
DS
4713 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
4714 && pi->type == ZEBRA_ROUTE_BGP
4715 && (pi->sub_type == BGP_ROUTE_NORMAL
4716 || pi->sub_type == BGP_ROUTE_AGGREGATE
4717 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 4718
d62a17ae 4719 if (bgp_fibupd_safi(safi))
b54892e0 4720 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 4721 }
9514b37d 4722
9bcb3eef 4723 bgp_path_info_reap(dest, pi);
d62a17ae 4724 }
bb86c601
LB
4725}
4726
718e3744 4727/* Delete all kernel routes. */
d62a17ae 4728void bgp_cleanup_routes(struct bgp *bgp)
4729{
4730 afi_t afi;
9bcb3eef 4731 struct bgp_dest *dest;
67009e22 4732 struct bgp_table *table;
d62a17ae 4733
4734 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
4735 if (afi == AFI_L2VPN)
4736 continue;
568e10ca 4737 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
4738 SAFI_UNICAST);
d62a17ae 4739 /*
4740 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4741 */
4742 if (afi != AFI_L2VPN) {
4743 safi_t safi;
4744 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
4745 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
4746 dest = bgp_route_next(dest)) {
4747 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4748 if (table != NULL) {
4749 bgp_cleanup_table(bgp, table, safi);
4750 bgp_table_finish(&table);
9bcb3eef
DS
4751 bgp_dest_set_bgp_table_info(dest, NULL);
4752 bgp_dest_unlock_node(dest);
d62a17ae 4753 }
4754 }
4755 safi = SAFI_ENCAP;
9bcb3eef
DS
4756 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
4757 dest = bgp_route_next(dest)) {
4758 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4759 if (table != NULL) {
4760 bgp_cleanup_table(bgp, table, safi);
4761 bgp_table_finish(&table);
9bcb3eef
DS
4762 bgp_dest_set_bgp_table_info(dest, NULL);
4763 bgp_dest_unlock_node(dest);
d62a17ae 4764 }
4765 }
4766 }
4767 }
9bcb3eef
DS
4768 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
4769 dest = bgp_route_next(dest)) {
4770 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4771 if (table != NULL) {
4772 bgp_cleanup_table(bgp, table, SAFI_EVPN);
4773 bgp_table_finish(&table);
9bcb3eef
DS
4774 bgp_dest_set_bgp_table_info(dest, NULL);
4775 bgp_dest_unlock_node(dest);
d62a17ae 4776 }
bb86c601 4777 }
718e3744 4778}
4779
d62a17ae 4780void bgp_reset(void)
718e3744 4781{
d62a17ae 4782 vty_reset();
4783 bgp_zclient_reset();
4784 access_list_reset();
4785 prefix_list_reset();
718e3744 4786}
6b0655a2 4787
d62a17ae 4788static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 4789{
d62a17ae 4790 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
4791 && CHECK_FLAG(peer->af_cap[afi][safi],
4792 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
4793}
4794
718e3744 4795/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4796 value. */
d62a17ae 4797int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
4798 struct bgp_nlri *packet)
4799{
d7c0a89a
QY
4800 uint8_t *pnt;
4801 uint8_t *lim;
d62a17ae 4802 struct prefix p;
4803 int psize;
4804 int ret;
4805 afi_t afi;
4806 safi_t safi;
4807 int addpath_encoded;
d7c0a89a 4808 uint32_t addpath_id;
d62a17ae 4809
d62a17ae 4810 pnt = packet->nlri;
4811 lim = pnt + packet->length;
4812 afi = packet->afi;
4813 safi = packet->safi;
4814 addpath_id = 0;
4815 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
4816
4817 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4818 syntactic validity. If the field is syntactically incorrect,
4819 then the Error Subcode is set to Invalid Network Field. */
4820 for (; pnt < lim; pnt += psize) {
4821 /* Clear prefix structure. */
4822 memset(&p, 0, sizeof(struct prefix));
4823
4824 if (addpath_encoded) {
4825
4826 /* When packet overflow occurs return immediately. */
761ed665 4827 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 4828 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4829
a3a850a1 4830 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 4831 addpath_id = ntohl(addpath_id);
d62a17ae 4832 pnt += BGP_ADDPATH_ID_LEN;
4833 }
718e3744 4834
d62a17ae 4835 /* Fetch prefix length. */
4836 p.prefixlen = *pnt++;
4837 /* afi/safi validity already verified by caller,
4838 * bgp_update_receive */
4839 p.family = afi2family(afi);
4840
4841 /* Prefix length check. */
4842 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 4843 flog_err(
e50f7cfd 4844 EC_BGP_UPDATE_RCV,
14454c9f 4845 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 4846 peer->host, p.prefixlen, packet->afi);
513386b5 4847 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 4848 }
6b0655a2 4849
d62a17ae 4850 /* Packet size overflow check. */
4851 psize = PSIZE(p.prefixlen);
4852
4853 /* When packet overflow occur return immediately. */
4854 if (pnt + psize > lim) {
af4c2728 4855 flog_err(
e50f7cfd 4856 EC_BGP_UPDATE_RCV,
d62a17ae 4857 "%s [Error] Update packet error (prefix length %d overflows packet)",
4858 peer->host, p.prefixlen);
513386b5 4859 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4860 }
4861
4862 /* Defensive coding, double-check the psize fits in a struct
4863 * prefix */
4864 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 4865 flog_err(
e50f7cfd 4866 EC_BGP_UPDATE_RCV,
d62a17ae 4867 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4868 peer->host, p.prefixlen, sizeof(p.u));
513386b5 4869 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4870 }
4871
4872 /* Fetch prefix from NLRI packet. */
a85297a7 4873 memcpy(p.u.val, pnt, psize);
d62a17ae 4874
4875 /* Check address. */
4876 if (afi == AFI_IP && safi == SAFI_UNICAST) {
4877 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
4878 /* From RFC4271 Section 6.3:
4879 *
4880 * If a prefix in the NLRI field is semantically
4881 * incorrect
4882 * (e.g., an unexpected multicast IP address),
4883 * an error SHOULD
4884 * be logged locally, and the prefix SHOULD be
4885 * ignored.
a4d82a8a 4886 */
af4c2728 4887 flog_err(
e50f7cfd 4888 EC_BGP_UPDATE_RCV,
d62a17ae 4889 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4890 peer->host, inet_ntoa(p.u.prefix4));
4891 continue;
4892 }
4893 }
4894
4895 /* Check address. */
4896 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
4897 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4898 char buf[BUFSIZ];
4899
af4c2728 4900 flog_err(
e50f7cfd 4901 EC_BGP_UPDATE_RCV,
d62a17ae 4902 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4903 peer->host,
4904 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4905 BUFSIZ));
4906
4907 continue;
4908 }
4909 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
4910 char buf[BUFSIZ];
4911
af4c2728 4912 flog_err(
e50f7cfd 4913 EC_BGP_UPDATE_RCV,
d62a17ae 4914 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4915 peer->host,
4916 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4917 BUFSIZ));
4918
4919 continue;
4920 }
4921 }
4922
4923 /* Normal process. */
4924 if (attr)
4925 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
4926 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 4927 NULL, NULL, 0, 0, NULL);
d62a17ae 4928 else
4929 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
4930 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
4931 BGP_ROUTE_NORMAL, NULL, NULL, 0,
4932 NULL);
d62a17ae 4933
513386b5
DA
4934 /* Do not send BGP notification twice when maximum-prefix count
4935 * overflow. */
4936 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4937 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
4938
4939 /* Address family configuration mismatch. */
d62a17ae 4940 if (ret < 0)
513386b5 4941 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 4942 }
4943
4944 /* Packet length consistency check. */
4945 if (pnt != lim) {
af4c2728 4946 flog_err(
e50f7cfd 4947 EC_BGP_UPDATE_RCV,
d62a17ae 4948 "%s [Error] Update packet error (prefix length mismatch with total length)",
4949 peer->host);
513386b5 4950 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4951 }
6b0655a2 4952
513386b5 4953 return BGP_NLRI_PARSE_OK;
718e3744 4954}
4955
d62a17ae 4956static struct bgp_static *bgp_static_new(void)
718e3744 4957{
d62a17ae 4958 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 4959}
4960
d62a17ae 4961static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 4962{
0a22ddfb 4963 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 4964 route_map_counter_decrement(bgp_static->rmap.map);
4965
0a22ddfb 4966 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 4967 XFREE(MTYPE_BGP_STATIC, bgp_static);
4968}
4969
5f040085 4970void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 4971 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
4972{
9bcb3eef 4973 struct bgp_dest *dest;
40381db7 4974 struct bgp_path_info *pi;
4b7e6066 4975 struct bgp_path_info *new;
40381db7 4976 struct bgp_path_info rmap_path;
d62a17ae 4977 struct attr attr;
4978 struct attr *attr_new;
b68885f9 4979 route_map_result_t ret;
49e5a4a0 4980#ifdef ENABLE_BGP_VNC
d62a17ae 4981 int vnc_implicit_withdraw = 0;
65efcfce 4982#endif
fee0f4c6 4983
d62a17ae 4984 assert(bgp_static);
dd8103a9 4985
9bcb3eef 4986 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4987
d62a17ae 4988 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 4989
d62a17ae 4990 attr.nexthop = bgp_static->igpnexthop;
4991 attr.med = bgp_static->igpmetric;
4992 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 4993
d62a17ae 4994 if (bgp_static->atomic)
4995 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 4996
d62a17ae 4997 /* Store label index, if required. */
4998 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
4999 attr.label_index = bgp_static->label_index;
5000 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5001 }
718e3744 5002
d62a17ae 5003 /* Apply route-map. */
5004 if (bgp_static->rmap.name) {
5005 struct attr attr_tmp = attr;
80ced710 5006
40381db7
DS
5007 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5008 rmap_path.peer = bgp->peer_self;
5009 rmap_path.attr = &attr_tmp;
fee0f4c6 5010
d62a17ae 5011 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5012
40381db7
DS
5013 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
5014 &rmap_path);
fee0f4c6 5015
d62a17ae 5016 bgp->peer_self->rmap_type = 0;
718e3744 5017
d62a17ae 5018 if (ret == RMAP_DENYMATCH) {
5019 /* Free uninterned attribute. */
5020 bgp_attr_flush(&attr_tmp);
718e3744 5021
d62a17ae 5022 /* Unintern original. */
5023 aspath_unintern(&attr.aspath);
5024 bgp_static_withdraw(bgp, p, afi, safi);
5025 return;
5026 }
7f323236 5027
892fedb6 5028 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
7f323236
DW
5029 bgp_attr_add_gshut_community(&attr_tmp);
5030
d62a17ae 5031 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5032 } else {
5033
892fedb6 5034 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
7f323236
DW
5035 bgp_attr_add_gshut_community(&attr);
5036
d62a17ae 5037 attr_new = bgp_attr_intern(&attr);
7f323236 5038 }
718e3744 5039
9bcb3eef 5040 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5041 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5042 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5043 break;
5044
40381db7
DS
5045 if (pi) {
5046 if (attrhash_cmp(pi->attr, attr_new)
5047 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5048 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5049 bgp_dest_unlock_node(dest);
d62a17ae 5050 bgp_attr_unintern(&attr_new);
5051 aspath_unintern(&attr.aspath);
5052 return;
5053 } else {
5054 /* The attribute is changed. */
9bcb3eef 5055 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5056
5057 /* Rewrite BGP route information. */
40381db7 5058 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5059 bgp_path_info_restore(dest, pi);
d62a17ae 5060 else
40381db7 5061 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5062#ifdef ENABLE_BGP_VNC
d62a17ae 5063 if ((afi == AFI_IP || afi == AFI_IP6)
5064 && (safi == SAFI_UNICAST)) {
40381db7 5065 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5066 /*
5067 * Implicit withdraw case.
40381db7 5068 * We have to do this before pi is
d62a17ae 5069 * changed
5070 */
5071 ++vnc_implicit_withdraw;
40381db7 5072 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5073 vnc_import_bgp_exterior_del_route(
40381db7 5074 bgp, p, pi);
d62a17ae 5075 }
5076 }
65efcfce 5077#endif
40381db7
DS
5078 bgp_attr_unintern(&pi->attr);
5079 pi->attr = attr_new;
5080 pi->uptime = bgp_clock();
49e5a4a0 5081#ifdef ENABLE_BGP_VNC
d62a17ae 5082 if ((afi == AFI_IP || afi == AFI_IP6)
5083 && (safi == SAFI_UNICAST)) {
5084 if (vnc_implicit_withdraw) {
40381db7 5085 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5086 vnc_import_bgp_exterior_add_route(
40381db7 5087 bgp, p, pi);
d62a17ae 5088 }
5089 }
65efcfce 5090#endif
718e3744 5091
d62a17ae 5092 /* Nexthop reachability check. */
892fedb6 5093 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5094 && (safi == SAFI_UNICAST
5095 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5096
5097 struct bgp *bgp_nexthop = bgp;
5098
40381db7
DS
5099 if (pi->extra && pi->extra->bgp_orig)
5100 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5101
5102 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
40381db7 5103 afi, pi, NULL, 0))
9bcb3eef 5104 bgp_path_info_set_flag(dest, pi,
18ee8310 5105 BGP_PATH_VALID);
d62a17ae 5106 else {
5107 if (BGP_DEBUG(nht, NHT)) {
5108 char buf1[INET6_ADDRSTRLEN];
5109 inet_ntop(p->family,
5110 &p->u.prefix, buf1,
5111 INET6_ADDRSTRLEN);
5112 zlog_debug(
5113 "%s(%s): Route not in table, not advertising",
15569c58 5114 __func__, buf1);
d62a17ae 5115 }
18ee8310 5116 bgp_path_info_unset_flag(
9bcb3eef 5117 dest, pi, BGP_PATH_VALID);
d62a17ae 5118 }
5119 } else {
5120 /* Delete the NHT structure if any, if we're
5121 * toggling between
5122 * enabling/disabling import check. We
5123 * deregister the route
5124 * from NHT to avoid overloading NHT and the
5125 * process interaction
5126 */
40381db7 5127 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5128 bgp_path_info_set_flag(dest, pi,
5129 BGP_PATH_VALID);
d62a17ae 5130 }
5131 /* Process change. */
40381db7 5132 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5133 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5134
5135 if (SAFI_UNICAST == safi
5136 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5137 || bgp->inst_type
5138 == BGP_INSTANCE_TYPE_DEFAULT)) {
5139 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5140 pi);
ddb5b488
PZ
5141 }
5142
9bcb3eef 5143 bgp_dest_unlock_node(dest);
d62a17ae 5144 aspath_unintern(&attr.aspath);
5145 return;
5146 }
718e3744 5147 }
718e3744 5148
d62a17ae 5149 /* Make new BGP info. */
5150 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5151 attr_new, dest);
d62a17ae 5152 /* Nexthop reachability check. */
892fedb6 5153 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5154 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 5155 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
9bcb3eef 5156 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5157 else {
5158 if (BGP_DEBUG(nht, NHT)) {
5159 char buf1[INET6_ADDRSTRLEN];
5160 inet_ntop(p->family, &p->u.prefix, buf1,
5161 INET6_ADDRSTRLEN);
5162 zlog_debug(
5163 "%s(%s): Route not in table, not advertising",
15569c58 5164 __func__, buf1);
d62a17ae 5165 }
9bcb3eef 5166 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5167 }
5168 } else {
5169 /* Delete the NHT structure if any, if we're toggling between
5170 * enabling/disabling import check. We deregister the route
5171 * from NHT to avoid overloading NHT and the process interaction
5172 */
5173 bgp_unlink_nexthop(new);
5174
9bcb3eef 5175 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 5176 }
078430f6 5177
d62a17ae 5178 /* Aggregate address increment. */
5179 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5180
d62a17ae 5181 /* Register new BGP information. */
9bcb3eef 5182 bgp_path_info_add(dest, new);
718e3744 5183
d62a17ae 5184 /* route_node_get lock */
9bcb3eef 5185 bgp_dest_unlock_node(dest);
d62a17ae 5186
5187 /* Process change. */
9bcb3eef 5188 bgp_process(bgp, dest, afi, safi);
d62a17ae 5189
ddb5b488
PZ
5190 if (SAFI_UNICAST == safi
5191 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5192 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5193 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5194 }
5195
d62a17ae 5196 /* Unintern original. */
5197 aspath_unintern(&attr.aspath);
718e3744 5198}
5199
5f040085 5200void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 5201 safi_t safi)
718e3744 5202{
9bcb3eef 5203 struct bgp_dest *dest;
40381db7 5204 struct bgp_path_info *pi;
718e3744 5205
9bcb3eef 5206 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5207
d62a17ae 5208 /* Check selected route and self inserted route. */
9bcb3eef 5209 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5210 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5211 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5212 break;
5213
5214 /* Withdraw static BGP route from routing table. */
40381db7 5215 if (pi) {
ddb5b488
PZ
5216 if (SAFI_UNICAST == safi
5217 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5218 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5219 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5220 }
40381db7
DS
5221 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5222 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5223 bgp_path_info_delete(dest, pi);
5224 bgp_process(bgp, dest, afi, safi);
d62a17ae 5225 }
718e3744 5226
d62a17ae 5227 /* Unlock bgp_node_lookup. */
9bcb3eef 5228 bgp_dest_unlock_node(dest);
718e3744 5229}
5230
137446f9
LB
5231/*
5232 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5233 */
5f040085 5234static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5235 afi_t afi, safi_t safi,
5236 struct prefix_rd *prd)
718e3744 5237{
9bcb3eef 5238 struct bgp_dest *dest;
40381db7 5239 struct bgp_path_info *pi;
718e3744 5240
9bcb3eef 5241 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5242
d62a17ae 5243 /* Check selected route and self inserted route. */
9bcb3eef 5244 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5245 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5246 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5247 break;
718e3744 5248
d62a17ae 5249 /* Withdraw static BGP route from routing table. */
40381db7 5250 if (pi) {
49e5a4a0 5251#ifdef ENABLE_BGP_VNC
d62a17ae 5252 rfapiProcessWithdraw(
40381db7 5253 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5254 1); /* Kill, since it is an administrative change */
65efcfce 5255#endif
ddb5b488
PZ
5256 if (SAFI_MPLS_VPN == safi
5257 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5258 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5259 }
40381db7 5260 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
5261 bgp_path_info_delete(dest, pi);
5262 bgp_process(bgp, dest, afi, safi);
d62a17ae 5263 }
718e3744 5264
d62a17ae 5265 /* Unlock bgp_node_lookup. */
9bcb3eef 5266 bgp_dest_unlock_node(dest);
718e3744 5267}
5268
5f040085 5269static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5270 struct bgp_static *bgp_static, afi_t afi,
5271 safi_t safi)
137446f9 5272{
9bcb3eef 5273 struct bgp_dest *dest;
4b7e6066 5274 struct bgp_path_info *new;
d62a17ae 5275 struct attr *attr_new;
5276 struct attr attr = {0};
40381db7 5277 struct bgp_path_info *pi;
49e5a4a0 5278#ifdef ENABLE_BGP_VNC
d62a17ae 5279 mpls_label_t label = 0;
65efcfce 5280#endif
d7c0a89a 5281 uint32_t num_labels = 0;
d62a17ae 5282 union gw_addr add;
137446f9 5283
d62a17ae 5284 assert(bgp_static);
137446f9 5285
b57ba6d2
MK
5286 if (bgp_static->label != MPLS_INVALID_LABEL)
5287 num_labels = 1;
9bcb3eef
DS
5288 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5289 &bgp_static->prd);
137446f9 5290
d62a17ae 5291 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5292
d62a17ae 5293 attr.nexthop = bgp_static->igpnexthop;
5294 attr.med = bgp_static->igpmetric;
5295 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5296
d62a17ae 5297 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5298 || (safi == SAFI_ENCAP)) {
5299 if (afi == AFI_IP) {
5300 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5301 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5302 }
5303 }
5304 if (afi == AFI_L2VPN) {
5305 if (bgp_static->gatewayIp.family == AF_INET)
5306 add.ipv4.s_addr =
5307 bgp_static->gatewayIp.u.prefix4.s_addr;
5308 else if (bgp_static->gatewayIp.family == AF_INET6)
5309 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5310 sizeof(struct in6_addr));
5311 overlay_index_update(&attr, bgp_static->eth_s_id, &add);
5312 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5313 struct bgp_encap_type_vxlan bet;
5314 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5315 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5316 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5317 }
5318 if (bgp_static->router_mac) {
5319 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5320 }
5321 }
5322 /* Apply route-map. */
5323 if (bgp_static->rmap.name) {
5324 struct attr attr_tmp = attr;
40381db7 5325 struct bgp_path_info rmap_path;
b68885f9 5326 route_map_result_t ret;
137446f9 5327
40381db7
DS
5328 rmap_path.peer = bgp->peer_self;
5329 rmap_path.attr = &attr_tmp;
137446f9 5330
d62a17ae 5331 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5332
40381db7
DS
5333 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
5334 &rmap_path);
137446f9 5335
d62a17ae 5336 bgp->peer_self->rmap_type = 0;
137446f9 5337
d62a17ae 5338 if (ret == RMAP_DENYMATCH) {
5339 /* Free uninterned attribute. */
5340 bgp_attr_flush(&attr_tmp);
137446f9 5341
d62a17ae 5342 /* Unintern original. */
5343 aspath_unintern(&attr.aspath);
5344 bgp_static_withdraw_safi(bgp, p, afi, safi,
5345 &bgp_static->prd);
5346 return;
5347 }
137446f9 5348
d62a17ae 5349 attr_new = bgp_attr_intern(&attr_tmp);
5350 } else {
5351 attr_new = bgp_attr_intern(&attr);
5352 }
137446f9 5353
9bcb3eef 5354 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5355 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5356 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5357 break;
5358
40381db7 5359 if (pi) {
d62a17ae 5360 memset(&add, 0, sizeof(union gw_addr));
40381db7
DS
5361 if (attrhash_cmp(pi->attr, attr_new)
5362 && overlay_index_equal(afi, pi, bgp_static->eth_s_id, &add)
5363 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 5364 bgp_dest_unlock_node(dest);
d62a17ae 5365 bgp_attr_unintern(&attr_new);
5366 aspath_unintern(&attr.aspath);
5367 return;
5368 } else {
5369 /* The attribute is changed. */
9bcb3eef 5370 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5371
5372 /* Rewrite BGP route information. */
40381db7 5373 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5374 bgp_path_info_restore(dest, pi);
d62a17ae 5375 else
40381db7
DS
5376 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5377 bgp_attr_unintern(&pi->attr);
5378 pi->attr = attr_new;
5379 pi->uptime = bgp_clock();
49e5a4a0 5380#ifdef ENABLE_BGP_VNC
40381db7
DS
5381 if (pi->extra)
5382 label = decode_label(&pi->extra->label[0]);
65efcfce 5383#endif
137446f9 5384
d62a17ae 5385 /* Process change. */
40381db7 5386 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5387 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5388
5389 if (SAFI_MPLS_VPN == safi
5390 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5391 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5392 }
49e5a4a0 5393#ifdef ENABLE_BGP_VNC
40381db7
DS
5394 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5395 pi->attr, afi, safi, pi->type,
5396 pi->sub_type, &label);
65efcfce 5397#endif
9bcb3eef 5398 bgp_dest_unlock_node(dest);
d62a17ae 5399 aspath_unintern(&attr.aspath);
5400 return;
5401 }
5402 }
137446f9
LB
5403
5404
d62a17ae 5405 /* Make new BGP info. */
5406 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5407 attr_new, dest);
1defdda8 5408 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5409 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5410 if (num_labels) {
5411 new->extra->label[0] = bgp_static->label;
5412 new->extra->num_labels = num_labels;
5413 }
49e5a4a0 5414#ifdef ENABLE_BGP_VNC
d62a17ae 5415 label = decode_label(&bgp_static->label);
65efcfce 5416#endif
137446f9 5417
d62a17ae 5418 /* Aggregate address increment. */
5419 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5420
d62a17ae 5421 /* Register new BGP information. */
9bcb3eef 5422 bgp_path_info_add(dest, new);
d62a17ae 5423 /* route_node_get lock */
9bcb3eef 5424 bgp_dest_unlock_node(dest);
137446f9 5425
d62a17ae 5426 /* Process change. */
9bcb3eef 5427 bgp_process(bgp, dest, afi, safi);
137446f9 5428
ddb5b488
PZ
5429 if (SAFI_MPLS_VPN == safi
5430 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5431 vpn_leak_to_vrf_update(bgp, new);
5432 }
49e5a4a0 5433#ifdef ENABLE_BGP_VNC
d62a17ae 5434 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5435 safi, new->type, new->sub_type, &label);
65efcfce
LB
5436#endif
5437
d62a17ae 5438 /* Unintern original. */
5439 aspath_unintern(&attr.aspath);
137446f9
LB
5440}
5441
718e3744 5442/* Configure static BGP network. When user don't run zebra, static
5443 route should be installed as valid. */
e2a86ad9
DS
5444static int bgp_static_set(struct vty *vty, const char *negate,
5445 const char *ip_str, afi_t afi, safi_t safi,
d7c0a89a 5446 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 5447{
5448 VTY_DECLVAR_CONTEXT(bgp, bgp);
5449 int ret;
5450 struct prefix p;
5451 struct bgp_static *bgp_static;
9bcb3eef 5452 struct bgp_dest *dest;
d7c0a89a 5453 uint8_t need_update = 0;
d62a17ae 5454
5455 /* Convert IP prefix string to struct prefix. */
5456 ret = str2prefix(ip_str, &p);
5457 if (!ret) {
5458 vty_out(vty, "%% Malformed prefix\n");
5459 return CMD_WARNING_CONFIG_FAILED;
5460 }
5461 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5462 vty_out(vty, "%% Malformed prefix (link-local address)\n");
5463 return CMD_WARNING_CONFIG_FAILED;
5464 }
718e3744 5465
d62a17ae 5466 apply_mask(&p);
718e3744 5467
e2a86ad9 5468 if (negate) {
718e3744 5469
e2a86ad9 5470 /* Set BGP static route configuration. */
9bcb3eef 5471 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5472
9bcb3eef 5473 if (!dest) {
a4d82a8a 5474 vty_out(vty, "%% Can't find static route specified\n");
d62a17ae 5475 return CMD_WARNING_CONFIG_FAILED;
5476 }
5477
9bcb3eef 5478 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 5479
e2a86ad9
DS
5480 if ((label_index != BGP_INVALID_LABEL_INDEX)
5481 && (label_index != bgp_static->label_index)) {
5482 vty_out(vty,
5483 "%% label-index doesn't match static route\n");
5484 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5485 }
d62a17ae 5486
e2a86ad9
DS
5487 if ((rmap && bgp_static->rmap.name)
5488 && strcmp(rmap, bgp_static->rmap.name)) {
5489 vty_out(vty,
5490 "%% route-map name doesn't match static route\n");
5491 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5492 }
718e3744 5493
e2a86ad9
DS
5494 /* Update BGP RIB. */
5495 if (!bgp_static->backdoor)
5496 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5497
e2a86ad9
DS
5498 /* Clear configuration. */
5499 bgp_static_free(bgp_static);
9bcb3eef
DS
5500 bgp_dest_set_bgp_static_info(dest, NULL);
5501 bgp_dest_unlock_node(dest);
5502 bgp_dest_unlock_node(dest);
e2a86ad9 5503 } else {
718e3744 5504
e2a86ad9 5505 /* Set BGP static route configuration. */
9bcb3eef
DS
5506 dest = bgp_node_get(bgp->route[afi][safi], &p);
5507 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 5508 if (bgp_static) {
e2a86ad9 5509 /* Configuration change. */
e2a86ad9
DS
5510 /* Label index cannot be changed. */
5511 if (bgp_static->label_index != label_index) {
5512 vty_out(vty, "%% cannot change label-index\n");
5513 return CMD_WARNING_CONFIG_FAILED;
5514 }
d62a17ae 5515
e2a86ad9 5516 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5517 if (bgp_static->valid
5518 && bgp_static->backdoor != backdoor)
e2a86ad9 5519 need_update = 1;
718e3744 5520
e2a86ad9 5521 bgp_static->backdoor = backdoor;
718e3744 5522
e2a86ad9 5523 if (rmap) {
0a22ddfb
QY
5524 XFREE(MTYPE_ROUTE_MAP_NAME,
5525 bgp_static->rmap.name);
b4897fa5 5526 route_map_counter_decrement(
5527 bgp_static->rmap.map);
e2a86ad9
DS
5528 bgp_static->rmap.name =
5529 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5530 bgp_static->rmap.map =
5531 route_map_lookup_by_name(rmap);
b4897fa5 5532 route_map_counter_increment(
5533 bgp_static->rmap.map);
e2a86ad9 5534 } else {
0a22ddfb
QY
5535 XFREE(MTYPE_ROUTE_MAP_NAME,
5536 bgp_static->rmap.name);
b4897fa5 5537 route_map_counter_decrement(
5538 bgp_static->rmap.map);
e2a86ad9
DS
5539 bgp_static->rmap.map = NULL;
5540 bgp_static->valid = 0;
5541 }
9bcb3eef 5542 bgp_dest_unlock_node(dest);
e2a86ad9
DS
5543 } else {
5544 /* New configuration. */
5545 bgp_static = bgp_static_new();
5546 bgp_static->backdoor = backdoor;
5547 bgp_static->valid = 0;
5548 bgp_static->igpmetric = 0;
975a328e 5549 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 5550 bgp_static->label_index = label_index;
718e3744 5551
e2a86ad9 5552 if (rmap) {
0a22ddfb
QY
5553 XFREE(MTYPE_ROUTE_MAP_NAME,
5554 bgp_static->rmap.name);
b4897fa5 5555 route_map_counter_decrement(
5556 bgp_static->rmap.map);
e2a86ad9
DS
5557 bgp_static->rmap.name =
5558 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5559 bgp_static->rmap.map =
5560 route_map_lookup_by_name(rmap);
b4897fa5 5561 route_map_counter_increment(
5562 bgp_static->rmap.map);
e2a86ad9 5563 }
9bcb3eef 5564 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 5565 }
d62a17ae 5566
e2a86ad9
DS
5567 bgp_static->valid = 1;
5568 if (need_update)
5569 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5570
e2a86ad9
DS
5571 if (!bgp_static->backdoor)
5572 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5573 }
d62a17ae 5574
5575 return CMD_SUCCESS;
5576}
5577
5578void bgp_static_add(struct bgp *bgp)
5579{
5580 afi_t afi;
5581 safi_t safi;
9bcb3eef
DS
5582 struct bgp_dest *dest;
5583 struct bgp_dest *rm;
d62a17ae 5584 struct bgp_table *table;
5585 struct bgp_static *bgp_static;
5586
05c7a1cc 5587 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5588 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5589 dest = bgp_route_next(dest)) {
5590 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5591 continue;
ea47320b 5592
05c7a1cc
QY
5593 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5594 || (safi == SAFI_EVPN)) {
9bcb3eef 5595 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5596
5597 for (rm = bgp_table_top(table); rm;
5598 rm = bgp_route_next(rm)) {
a78beeb5 5599 bgp_static =
9bcb3eef 5600 bgp_dest_get_bgp_static_info(
5a8ba9fc 5601 rm);
9bcb3eef
DS
5602 bgp_static_update_safi(
5603 bgp, bgp_dest_get_prefix(rm),
5604 bgp_static, afi, safi);
d62a17ae 5605 }
05c7a1cc 5606 } else {
5a8ba9fc 5607 bgp_static_update(
9bcb3eef
DS
5608 bgp, bgp_dest_get_prefix(dest),
5609 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 5610 safi);
ea47320b 5611 }
05c7a1cc 5612 }
6aeb9e78
DS
5613}
5614
718e3744 5615/* Called from bgp_delete(). Delete all static routes from the BGP
5616 instance. */
d62a17ae 5617void bgp_static_delete(struct bgp *bgp)
5618{
5619 afi_t afi;
5620 safi_t safi;
9bcb3eef
DS
5621 struct bgp_dest *dest;
5622 struct bgp_dest *rm;
d62a17ae 5623 struct bgp_table *table;
5624 struct bgp_static *bgp_static;
5625
05c7a1cc 5626 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5627 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5628 dest = bgp_route_next(dest)) {
5629 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5630 continue;
ea47320b 5631
05c7a1cc
QY
5632 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5633 || (safi == SAFI_EVPN)) {
9bcb3eef 5634 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5635
5636 for (rm = bgp_table_top(table); rm;
5637 rm = bgp_route_next(rm)) {
a78beeb5 5638 bgp_static =
9bcb3eef 5639 bgp_dest_get_bgp_static_info(
5a8ba9fc 5640 rm);
c7d14ba6
PG
5641 if (!bgp_static)
5642 continue;
5643
05c7a1cc 5644 bgp_static_withdraw_safi(
9bcb3eef 5645 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
5646 AFI_IP, safi,
5647 (struct prefix_rd *)
9bcb3eef
DS
5648 bgp_dest_get_prefix(
5649 dest));
ea47320b 5650 bgp_static_free(bgp_static);
9bcb3eef
DS
5651 bgp_dest_set_bgp_static_info(dest,
5652 NULL);
5653 bgp_dest_unlock_node(dest);
d62a17ae 5654 }
05c7a1cc 5655 } else {
9bcb3eef 5656 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 5657 bgp_static_withdraw(bgp,
9bcb3eef 5658 bgp_dest_get_prefix(dest),
b54892e0 5659 afi, safi);
05c7a1cc 5660 bgp_static_free(bgp_static);
9bcb3eef
DS
5661 bgp_dest_set_bgp_static_info(dest, NULL);
5662 bgp_dest_unlock_node(dest);
ea47320b 5663 }
05c7a1cc 5664 }
d62a17ae 5665}
5666
5667void bgp_static_redo_import_check(struct bgp *bgp)
5668{
5669 afi_t afi;
5670 safi_t safi;
9bcb3eef
DS
5671 struct bgp_dest *dest;
5672 struct bgp_dest *rm;
d62a17ae 5673 struct bgp_table *table;
5674 struct bgp_static *bgp_static;
5675
5676 /* Use this flag to force reprocessing of the route */
892fedb6 5677 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 5678 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
5679 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5680 dest = bgp_route_next(dest)) {
5681 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5682 continue;
ea47320b 5683
05c7a1cc
QY
5684 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5685 || (safi == SAFI_EVPN)) {
9bcb3eef 5686 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5687
5688 for (rm = bgp_table_top(table); rm;
5689 rm = bgp_route_next(rm)) {
a78beeb5 5690 bgp_static =
9bcb3eef 5691 bgp_dest_get_bgp_static_info(
5a8ba9fc 5692 rm);
9bcb3eef
DS
5693 bgp_static_update_safi(
5694 bgp, bgp_dest_get_prefix(rm),
5695 bgp_static, afi, safi);
d62a17ae 5696 }
05c7a1cc 5697 } else {
9bcb3eef
DS
5698 bgp_static = bgp_dest_get_bgp_static_info(dest);
5699 bgp_static_update(bgp,
5700 bgp_dest_get_prefix(dest),
5701 bgp_static, afi, safi);
ea47320b 5702 }
05c7a1cc
QY
5703 }
5704 }
892fedb6 5705 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 5706}
5707
5708static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
5709 safi_t safi)
5710{
5711 struct bgp_table *table;
9bcb3eef 5712 struct bgp_dest *dest;
40381db7 5713 struct bgp_path_info *pi;
d62a17ae 5714
dfb6fd1d
NT
5715 /* Do not install the aggregate route if BGP is in the
5716 * process of termination.
5717 */
892fedb6
DA
5718 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
5719 || (bgp->peer_self == NULL))
dfb6fd1d
NT
5720 return;
5721
d62a17ae 5722 table = bgp->rib[afi][safi];
9bcb3eef
DS
5723 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5724 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
5725 if (pi->peer == bgp->peer_self
5726 && ((pi->type == ZEBRA_ROUTE_BGP
5727 && pi->sub_type == BGP_ROUTE_STATIC)
5728 || (pi->type != ZEBRA_ROUTE_BGP
5729 && pi->sub_type
d62a17ae 5730 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
5731 bgp_aggregate_decrement(
5732 bgp, bgp_dest_get_prefix(dest), pi, afi,
5733 safi);
40381db7 5734 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5735 bgp_path_info_delete(dest, pi);
5736 bgp_process(bgp, dest, afi, safi);
d62a17ae 5737 }
5738 }
5739 }
ad4cbda1 5740}
5741
5742/*
5743 * Purge all networks and redistributed routes from routing table.
5744 * Invoked upon the instance going down.
5745 */
d62a17ae 5746void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 5747{
d62a17ae 5748 afi_t afi;
5749 safi_t safi;
ad4cbda1 5750
05c7a1cc
QY
5751 FOREACH_AFI_SAFI (afi, safi)
5752 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 5753}
5754
137446f9
LB
5755/*
5756 * gpz 110624
5757 * Currently this is used to set static routes for VPN and ENCAP.
5758 * I think it can probably be factored with bgp_static_set.
5759 */
d62a17ae 5760int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
5761 const char *ip_str, const char *rd_str,
5762 const char *label_str, const char *rmap_str,
5763 int evpn_type, const char *esi, const char *gwip,
5764 const char *ethtag, const char *routermac)
5765{
5766 VTY_DECLVAR_CONTEXT(bgp, bgp);
5767 int ret;
5768 struct prefix p;
5769 struct prefix_rd prd;
9bcb3eef
DS
5770 struct bgp_dest *pdest;
5771 struct bgp_dest *dest;
d62a17ae 5772 struct bgp_table *table;
5773 struct bgp_static *bgp_static;
5774 mpls_label_t label = MPLS_INVALID_LABEL;
5775 struct prefix gw_ip;
5776
5777 /* validate ip prefix */
5778 ret = str2prefix(ip_str, &p);
5779 if (!ret) {
5780 vty_out(vty, "%% Malformed prefix\n");
5781 return CMD_WARNING_CONFIG_FAILED;
5782 }
5783 apply_mask(&p);
5784 if ((afi == AFI_L2VPN)
5785 && (bgp_build_evpn_prefix(evpn_type,
5786 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5787 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5788 return CMD_WARNING_CONFIG_FAILED;
5789 }
718e3744 5790
d62a17ae 5791 ret = str2prefix_rd(rd_str, &prd);
5792 if (!ret) {
5793 vty_out(vty, "%% Malformed rd\n");
5794 return CMD_WARNING_CONFIG_FAILED;
5795 }
718e3744 5796
d62a17ae 5797 if (label_str) {
5798 unsigned long label_val;
5799 label_val = strtoul(label_str, NULL, 10);
5800 encode_label(label_val, &label);
5801 }
9bedbb1e 5802
d62a17ae 5803 if (safi == SAFI_EVPN) {
5804 if (esi && str2esi(esi, NULL) == 0) {
5805 vty_out(vty, "%% Malformed ESI\n");
5806 return CMD_WARNING_CONFIG_FAILED;
5807 }
5808 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
5809 vty_out(vty, "%% Malformed Router MAC\n");
5810 return CMD_WARNING_CONFIG_FAILED;
5811 }
5812 if (gwip) {
5813 memset(&gw_ip, 0, sizeof(struct prefix));
5814 ret = str2prefix(gwip, &gw_ip);
5815 if (!ret) {
5816 vty_out(vty, "%% Malformed GatewayIp\n");
5817 return CMD_WARNING_CONFIG_FAILED;
5818 }
5819 if ((gw_ip.family == AF_INET
3714a385 5820 && is_evpn_prefix_ipaddr_v6(
d62a17ae 5821 (struct prefix_evpn *)&p))
5822 || (gw_ip.family == AF_INET6
3714a385 5823 && is_evpn_prefix_ipaddr_v4(
d62a17ae 5824 (struct prefix_evpn *)&p))) {
5825 vty_out(vty,
5826 "%% GatewayIp family differs with IP prefix\n");
5827 return CMD_WARNING_CONFIG_FAILED;
5828 }
5829 }
5830 }
9bcb3eef
DS
5831 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
5832 if (!bgp_dest_has_bgp_path_info_data(pdest))
5833 bgp_dest_set_bgp_table_info(pdest,
67009e22 5834 bgp_table_init(bgp, afi, safi));
9bcb3eef 5835 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 5836
9bcb3eef 5837 dest = bgp_node_get(table, &p);
d62a17ae 5838
9bcb3eef 5839 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 5840 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 5841 bgp_dest_unlock_node(dest);
d62a17ae 5842 } else {
5843 /* New configuration. */
5844 bgp_static = bgp_static_new();
5845 bgp_static->backdoor = 0;
5846 bgp_static->valid = 0;
5847 bgp_static->igpmetric = 0;
975a328e 5848 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 5849 bgp_static->label = label;
5850 bgp_static->prd = prd;
5851
5852 if (rmap_str) {
0a22ddfb 5853 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5854 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 5855 bgp_static->rmap.name =
5856 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
5857 bgp_static->rmap.map =
5858 route_map_lookup_by_name(rmap_str);
b4897fa5 5859 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 5860 }
718e3744 5861
d62a17ae 5862 if (safi == SAFI_EVPN) {
5863 if (esi) {
5864 bgp_static->eth_s_id =
5865 XCALLOC(MTYPE_ATTR,
5866 sizeof(struct eth_segment_id));
5867 str2esi(esi, bgp_static->eth_s_id);
5868 }
5869 if (routermac) {
5870 bgp_static->router_mac =
28328ea9 5871 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
5872 (void)prefix_str2mac(routermac,
5873 bgp_static->router_mac);
d62a17ae 5874 }
5875 if (gwip)
5876 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
5877 }
9bcb3eef 5878 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 5879
d62a17ae 5880 bgp_static->valid = 1;
5881 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
5882 }
718e3744 5883
d62a17ae 5884 return CMD_SUCCESS;
718e3744 5885}
5886
5887/* Configure static BGP network. */
d62a17ae 5888int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
5889 const char *ip_str, const char *rd_str,
5890 const char *label_str, int evpn_type, const char *esi,
5891 const char *gwip, const char *ethtag)
5892{
5893 VTY_DECLVAR_CONTEXT(bgp, bgp);
5894 int ret;
5895 struct prefix p;
5896 struct prefix_rd prd;
9bcb3eef
DS
5897 struct bgp_dest *pdest;
5898 struct bgp_dest *dest;
d62a17ae 5899 struct bgp_table *table;
5900 struct bgp_static *bgp_static;
5901 mpls_label_t label = MPLS_INVALID_LABEL;
5902
5903 /* Convert IP prefix string to struct prefix. */
5904 ret = str2prefix(ip_str, &p);
5905 if (!ret) {
5906 vty_out(vty, "%% Malformed prefix\n");
5907 return CMD_WARNING_CONFIG_FAILED;
5908 }
5909 apply_mask(&p);
5910 if ((afi == AFI_L2VPN)
5911 && (bgp_build_evpn_prefix(evpn_type,
5912 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5913 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5914 return CMD_WARNING_CONFIG_FAILED;
5915 }
5916 ret = str2prefix_rd(rd_str, &prd);
5917 if (!ret) {
5918 vty_out(vty, "%% Malformed rd\n");
5919 return CMD_WARNING_CONFIG_FAILED;
5920 }
718e3744 5921
d62a17ae 5922 if (label_str) {
5923 unsigned long label_val;
5924 label_val = strtoul(label_str, NULL, 10);
5925 encode_label(label_val, &label);
5926 }
718e3744 5927
9bcb3eef
DS
5928 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
5929 if (!bgp_dest_has_bgp_path_info_data(pdest))
5930 bgp_dest_set_bgp_table_info(pdest,
67009e22 5931 bgp_table_init(bgp, afi, safi));
d62a17ae 5932 else
9bcb3eef
DS
5933 bgp_dest_unlock_node(pdest);
5934 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 5935
9bcb3eef 5936 dest = bgp_node_lookup(table, &p);
6b0655a2 5937
9bcb3eef 5938 if (dest) {
d62a17ae 5939 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 5940
9bcb3eef 5941 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 5942 bgp_static_free(bgp_static);
9bcb3eef
DS
5943 bgp_dest_set_bgp_static_info(dest, NULL);
5944 bgp_dest_unlock_node(dest);
5945 bgp_dest_unlock_node(dest);
d62a17ae 5946 } else
5947 vty_out(vty, "%% Can't find the route\n");
5948
5949 return CMD_SUCCESS;
5950}
5951
5952static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
5953 const char *rmap_name)
5954{
5955 VTY_DECLVAR_CONTEXT(bgp, bgp);
5956 struct bgp_rmap *rmap;
5957
5958 rmap = &bgp->table_map[afi][safi];
5959 if (rmap_name) {
0a22ddfb 5960 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5961 route_map_counter_decrement(rmap->map);
d62a17ae 5962 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
5963 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 5964 route_map_counter_increment(rmap->map);
d62a17ae 5965 } else {
0a22ddfb 5966 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5967 route_map_counter_decrement(rmap->map);
d62a17ae 5968 rmap->map = NULL;
5969 }
73ac8160 5970
d62a17ae 5971 if (bgp_fibupd_safi(safi))
5972 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5973
d62a17ae 5974 return CMD_SUCCESS;
73ac8160
DS
5975}
5976
d62a17ae 5977static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
5978 const char *rmap_name)
73ac8160 5979{
d62a17ae 5980 VTY_DECLVAR_CONTEXT(bgp, bgp);
5981 struct bgp_rmap *rmap;
73ac8160 5982
d62a17ae 5983 rmap = &bgp->table_map[afi][safi];
0a22ddfb 5984 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5985 route_map_counter_decrement(rmap->map);
d62a17ae 5986 rmap->map = NULL;
73ac8160 5987
d62a17ae 5988 if (bgp_fibupd_safi(safi))
5989 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5990
d62a17ae 5991 return CMD_SUCCESS;
73ac8160
DS
5992}
5993
2b791107 5994void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 5995 safi_t safi)
73ac8160 5996{
d62a17ae 5997 if (bgp->table_map[afi][safi].name) {
d62a17ae 5998 vty_out(vty, " table-map %s\n",
5999 bgp->table_map[afi][safi].name);
6000 }
73ac8160
DS
6001}
6002
73ac8160
DS
6003DEFUN (bgp_table_map,
6004 bgp_table_map_cmd,
6005 "table-map WORD",
6006 "BGP table to RIB route download filter\n"
6007 "Name of the route map\n")
6008{
d62a17ae 6009 int idx_word = 1;
6010 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6011 argv[idx_word]->arg);
73ac8160
DS
6012}
6013DEFUN (no_bgp_table_map,
6014 no_bgp_table_map_cmd,
6015 "no table-map WORD",
3a2d747c 6016 NO_STR
73ac8160
DS
6017 "BGP table to RIB route download filter\n"
6018 "Name of the route map\n")
6019{
d62a17ae 6020 int idx_word = 2;
6021 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6022 argv[idx_word]->arg);
73ac8160
DS
6023}
6024
e2a86ad9
DS
6025DEFPY(bgp_network,
6026 bgp_network_cmd,
6027 "[no] network \
6028 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6029 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6030 backdoor$backdoor}]",
6031 NO_STR
6032 "Specify a network to announce via BGP\n"
6033 "IPv4 prefix\n"
6034 "Network number\n"
6035 "Network mask\n"
6036 "Network mask\n"
6037 "Route-map to modify the attributes\n"
6038 "Name of the route map\n"
6039 "Label index to associate with the prefix\n"
6040 "Label index value\n"
6041 "Specify a BGP backdoor route\n")
6042{
6043 char addr_prefix_str[BUFSIZ];
6044
6045 if (address_str) {
6046 int ret;
718e3744 6047
e2a86ad9
DS
6048 ret = netmask_str2prefix_str(address_str, netmask_str,
6049 addr_prefix_str);
6050 if (!ret) {
6051 vty_out(vty, "%% Inconsistent address and mask\n");
6052 return CMD_WARNING_CONFIG_FAILED;
6053 }
d62a17ae 6054 }
718e3744 6055
a4d82a8a
PZ
6056 return bgp_static_set(
6057 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
6058 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
6059 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 6060}
6061
e2a86ad9
DS
6062DEFPY(ipv6_bgp_network,
6063 ipv6_bgp_network_cmd,
6064 "[no] network X:X::X:X/M$prefix \
6065 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6066 NO_STR
6067 "Specify a network to announce via BGP\n"
6068 "IPv6 prefix\n"
6069 "Route-map to modify the attributes\n"
6070 "Name of the route map\n"
6071 "Label index to associate with the prefix\n"
6072 "Label index value\n")
718e3744 6073{
a4d82a8a
PZ
6074 return bgp_static_set(
6075 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
6076 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
6077}
6078
d62a17ae 6079static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6080{
d62a17ae 6081 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6082}
6083
d62a17ae 6084static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6085{
20894f50
DA
6086 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6087 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6088 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6089}
718e3744 6090
3dc339cd
DA
6091static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6092 struct aspath *aspath,
6093 struct community *comm,
6094 struct ecommunity *ecomm,
6095 struct lcommunity *lcomm)
eaaf8adb
DS
6096{
6097 static struct aspath *ae = NULL;
6098
6099 if (!ae)
6100 ae = aspath_empty();
6101
40381db7 6102 if (!pi)
3dc339cd 6103 return false;
eaaf8adb 6104
40381db7 6105 if (origin != pi->attr->origin)
3dc339cd 6106 return false;
eaaf8adb 6107
40381db7 6108 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 6109 return false;
29f7d023 6110
40381db7 6111 if (!community_cmp(pi->attr->community, comm))
3dc339cd 6112 return false;
eaaf8adb 6113
3da2cc32 6114 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
3dc339cd 6115 return false;
eaaf8adb 6116
dd18c5a9 6117 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 6118 return false;
dd18c5a9 6119
40381db7 6120 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 6121 return false;
7ce8a8e0 6122
3dc339cd 6123 return true;
eaaf8adb
DS
6124}
6125
5f040085
DS
6126static void bgp_aggregate_install(
6127 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6128 uint8_t origin, struct aspath *aspath, struct community *community,
6129 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6130 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 6131{
9bcb3eef 6132 struct bgp_dest *dest;
c701010e 6133 struct bgp_table *table;
6f94b685 6134 struct bgp_path_info *pi, *orig, *new;
20894f50 6135 struct attr *attr;
c701010e
DS
6136
6137 table = bgp->rib[afi][safi];
6138
9bcb3eef 6139 dest = bgp_node_get(table, p);
eaaf8adb 6140
9bcb3eef 6141 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6142 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6143 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6144 break;
6145
c701010e 6146 if (aggregate->count > 0) {
eaaf8adb
DS
6147 /*
6148 * If the aggregate information has not changed
6149 * no need to re-install it again.
6150 */
6f94b685 6151 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6152 ecommunity, lcommunity)) {
9bcb3eef 6153 bgp_dest_unlock_node(dest);
eaaf8adb
DS
6154
6155 if (aspath)
6156 aspath_free(aspath);
6157 if (community)
3c1f53de 6158 community_free(&community);
3da2cc32
DS
6159 if (ecommunity)
6160 ecommunity_free(&ecommunity);
dd18c5a9
DS
6161 if (lcommunity)
6162 lcommunity_free(&lcommunity);
eaaf8adb
DS
6163
6164 return;
6165 }
6166
6167 /*
6168 * Mark the old as unusable
6169 */
40381db7 6170 if (pi)
9bcb3eef 6171 bgp_path_info_delete(dest, pi);
eaaf8adb 6172
20894f50
DA
6173 attr = bgp_attr_aggregate_intern(
6174 bgp, origin, aspath, community, ecommunity, lcommunity,
6175 aggregate, atomic_aggregate, p);
6176
6177 if (!attr) {
6178 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
6179 return;
6180 }
6181
3da2cc32 6182 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 6183 bgp->peer_self, attr, dest);
20894f50 6184
1defdda8 6185 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6186
9bcb3eef
DS
6187 bgp_path_info_add(dest, new);
6188 bgp_process(bgp, dest, afi, safi);
c701010e 6189 } else {
6f94b685 6190 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6191 if (pi->peer == bgp->peer_self
6192 && pi->type == ZEBRA_ROUTE_BGP
6193 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6194 break;
6195
6196 /* Withdraw static BGP route from routing table. */
40381db7 6197 if (pi) {
9bcb3eef
DS
6198 bgp_path_info_delete(dest, pi);
6199 bgp_process(bgp, dest, afi, safi);
c701010e
DS
6200 }
6201 }
6202
9bcb3eef 6203 bgp_dest_unlock_node(dest);
c701010e
DS
6204}
6205
b5d58c32 6206/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
6207void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
6208 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 6209{
6210 struct bgp_table *table;
9bcb3eef
DS
6211 struct bgp_dest *top;
6212 struct bgp_dest *dest;
d7c0a89a 6213 uint8_t origin;
d62a17ae 6214 struct aspath *aspath = NULL;
d62a17ae 6215 struct community *community = NULL;
3da2cc32 6216 struct ecommunity *ecommunity = NULL;
dd18c5a9 6217 struct lcommunity *lcommunity = NULL;
40381db7 6218 struct bgp_path_info *pi;
d62a17ae 6219 unsigned long match = 0;
d7c0a89a 6220 uint8_t atomic_aggregate = 0;
d62a17ae 6221
9f822fa2
S
6222 /* If the bgp instance is being deleted or self peer is deleted
6223 * then do not create aggregate route
6224 */
892fedb6
DA
6225 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6226 || (bgp->peer_self == NULL))
9f822fa2
S
6227 return;
6228
d62a17ae 6229 /* ORIGIN attribute: If at least one route among routes that are
6230 aggregated has ORIGIN with the value INCOMPLETE, then the
6231 aggregated route must have the ORIGIN attribute with the value
6232 INCOMPLETE. Otherwise, if at least one route among routes that
6233 are aggregated has ORIGIN with the value EGP, then the aggregated
6234 route must have the origin attribute with the value EGP. In all
6235 other case the value of the ORIGIN attribute of the aggregated
6236 route is INTERNAL. */
6237 origin = BGP_ORIGIN_IGP;
718e3744 6238
d62a17ae 6239 table = bgp->rib[afi][safi];
718e3744 6240
d62a17ae 6241 top = bgp_node_get(table, p);
9bcb3eef
DS
6242 for (dest = bgp_node_get(table, p); dest;
6243 dest = bgp_route_next_until(dest, top)) {
6244 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6245
9bcb3eef 6246 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 6247 continue;
d62a17ae 6248
c2ff8b3e 6249 match = 0;
d62a17ae 6250
9bcb3eef 6251 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 6252 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 6253 continue;
718e3744 6254
40381db7 6255 if (pi->attr->flag
c2ff8b3e
DS
6256 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
6257 atomic_aggregate = 1;
d62a17ae 6258
40381db7 6259 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 6260 continue;
d62a17ae 6261
f273fef1
DS
6262 /*
6263 * summary-only aggregate route suppress
6264 * aggregated route announcements.
6265 */
c2ff8b3e 6266 if (aggregate->summary_only) {
40381db7 6267 (bgp_path_info_extra_get(pi))->suppress++;
9bcb3eef 6268 bgp_path_info_set_flag(dest, pi,
18ee8310 6269 BGP_PATH_ATTR_CHANGED);
c2ff8b3e 6270 match++;
d62a17ae 6271 }
c2ff8b3e
DS
6272
6273 aggregate->count++;
6274
f273fef1
DS
6275 /*
6276 * If at least one route among routes that are
6277 * aggregated has ORIGIN with the value INCOMPLETE,
6278 * then the aggregated route MUST have the ORIGIN
6279 * attribute with the value INCOMPLETE. Otherwise, if
6280 * at least one route among routes that are aggregated
6281 * has ORIGIN with the value EGP, then the aggregated
6282 * route MUST have the ORIGIN attribute with the value
6283 * EGP.
6284 */
fc968841
NT
6285 switch (pi->attr->origin) {
6286 case BGP_ORIGIN_INCOMPLETE:
6287 aggregate->incomplete_origin_count++;
6288 break;
6289 case BGP_ORIGIN_EGP:
6290 aggregate->egp_origin_count++;
6291 break;
6292 default:
6293 /*Do nothing.
6294 */
6295 break;
6296 }
c2ff8b3e
DS
6297
6298 if (!aggregate->as_set)
6299 continue;
6300
f273fef1
DS
6301 /*
6302 * as-set aggregate route generate origin, as path,
6303 * and community aggregation.
6304 */
fc968841
NT
6305 /* Compute aggregate route's as-path.
6306 */
ef51a7d8 6307 bgp_compute_aggregate_aspath_hash(aggregate,
6308 pi->attr->aspath);
c2ff8b3e 6309
fc968841
NT
6310 /* Compute aggregate route's community.
6311 */
6312 if (pi->attr->community)
21fec674 6313 bgp_compute_aggregate_community_hash(
fc968841
NT
6314 aggregate,
6315 pi->attr->community);
dd18c5a9 6316
fc968841
NT
6317 /* Compute aggregate route's extended community.
6318 */
6319 if (pi->attr->ecommunity)
4edd83f9 6320 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
6321 aggregate,
6322 pi->attr->ecommunity);
6323
6324 /* Compute aggregate route's large community.
6325 */
6326 if (pi->attr->lcommunity)
f1eb1f05 6327 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
6328 aggregate,
6329 pi->attr->lcommunity);
d62a17ae 6330 }
c2ff8b3e 6331 if (match)
9bcb3eef 6332 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 6333 }
21fec674 6334 if (aggregate->as_set) {
ef51a7d8 6335 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 6336 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 6337 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 6338 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 6339 }
6340
f1eb1f05 6341
9bcb3eef 6342 bgp_dest_unlock_node(top);
718e3744 6343
718e3744 6344
fc968841
NT
6345 if (aggregate->incomplete_origin_count > 0)
6346 origin = BGP_ORIGIN_INCOMPLETE;
6347 else if (aggregate->egp_origin_count > 0)
6348 origin = BGP_ORIGIN_EGP;
d62a17ae 6349
229757f1
DA
6350 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6351 origin = aggregate->origin;
6352
fc968841
NT
6353 if (aggregate->as_set) {
6354 if (aggregate->aspath)
6355 /* Retrieve aggregate route's as-path.
6356 */
6357 aspath = aspath_dup(aggregate->aspath);
d62a17ae 6358
fc968841
NT
6359 if (aggregate->community)
6360 /* Retrieve aggregate route's community.
6361 */
6362 community = community_dup(aggregate->community);
3da2cc32 6363
fc968841
NT
6364 if (aggregate->ecommunity)
6365 /* Retrieve aggregate route's ecommunity.
6366 */
6367 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 6368
fc968841
NT
6369 if (aggregate->lcommunity)
6370 /* Retrieve aggregate route's lcommunity.
6371 */
6372 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 6373 }
718e3744 6374
c701010e 6375 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
6376 ecommunity, lcommunity, atomic_aggregate,
6377 aggregate);
718e3744 6378}
6379
5f040085
DS
6380void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
6381 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
6382{
6383 struct bgp_table *table;
9bcb3eef
DS
6384 struct bgp_dest *top;
6385 struct bgp_dest *dest;
40381db7 6386 struct bgp_path_info *pi;
3b7db173
DS
6387 unsigned long match;
6388
6389 table = bgp->rib[afi][safi];
6390
6391 /* If routes exists below this node, generate aggregate routes. */
6392 top = bgp_node_get(table, p);
9bcb3eef
DS
6393 for (dest = bgp_node_get(table, p); dest;
6394 dest = bgp_route_next_until(dest, top)) {
6395 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6396
9bcb3eef 6397 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
6398 continue;
6399 match = 0;
6400
9bcb3eef 6401 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 6402 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
6403 continue;
6404
40381db7 6405 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
6406 continue;
6407
40381db7
DS
6408 if (aggregate->summary_only && pi->extra) {
6409 pi->extra->suppress--;
3b7db173 6410
40381db7 6411 if (pi->extra->suppress == 0) {
18ee8310 6412 bgp_path_info_set_flag(
9bcb3eef
DS
6413 dest, pi,
6414 BGP_PATH_ATTR_CHANGED);
3b7db173
DS
6415 match++;
6416 }
6417 }
6418 aggregate->count--;
fc968841
NT
6419
6420 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6421 aggregate->incomplete_origin_count--;
6422 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6423 aggregate->egp_origin_count--;
6424
6425 if (aggregate->as_set) {
6426 /* Remove as-path from aggregate.
6427 */
ef51a7d8 6428 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
6429 aggregate,
6430 pi->attr->aspath);
6431
6432 if (pi->attr->community)
6433 /* Remove community from aggregate.
6434 */
21fec674 6435 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
6436 aggregate,
6437 pi->attr->community);
6438
6439 if (pi->attr->ecommunity)
6440 /* Remove ecommunity from aggregate.
6441 */
4edd83f9 6442 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
6443 aggregate,
6444 pi->attr->ecommunity);
6445
6446 if (pi->attr->lcommunity)
6447 /* Remove lcommunity from aggregate.
6448 */
f1eb1f05 6449 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
6450 aggregate,
6451 pi->attr->lcommunity);
6452 }
3b7db173
DS
6453 }
6454
6455 /* If this node was suppressed, process the change. */
6456 if (match)
9bcb3eef 6457 bgp_process(bgp, dest, afi, safi);
3b7db173 6458 }
f1eb1f05 6459 if (aggregate->as_set) {
ef51a7d8 6460 aspath_free(aggregate->aspath);
6461 aggregate->aspath = NULL;
21fec674 6462 if (aggregate->community)
6463 community_free(&aggregate->community);
4edd83f9 6464 if (aggregate->ecommunity)
6465 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 6466 if (aggregate->lcommunity)
6467 lcommunity_free(&aggregate->lcommunity);
6468 }
6469
9bcb3eef 6470 bgp_dest_unlock_node(top);
3b7db173 6471}
718e3744 6472
5f040085
DS
6473static void bgp_add_route_to_aggregate(struct bgp *bgp,
6474 const struct prefix *aggr_p,
fc968841
NT
6475 struct bgp_path_info *pinew, afi_t afi,
6476 safi_t safi,
6477 struct bgp_aggregate *aggregate)
6478{
6479 uint8_t origin;
6480 struct aspath *aspath = NULL;
6481 uint8_t atomic_aggregate = 0;
6482 struct community *community = NULL;
6483 struct ecommunity *ecommunity = NULL;
6484 struct lcommunity *lcommunity = NULL;
6485
6486 /* ORIGIN attribute: If at least one route among routes that are
6487 * aggregated has ORIGIN with the value INCOMPLETE, then the
6488 * aggregated route must have the ORIGIN attribute with the value
6489 * INCOMPLETE. Otherwise, if at least one route among routes that
6490 * are aggregated has ORIGIN with the value EGP, then the aggregated
6491 * route must have the origin attribute with the value EGP. In all
6492 * other case the value of the ORIGIN attribute of the aggregated
6493 * route is INTERNAL.
6494 */
6495 origin = BGP_ORIGIN_IGP;
6496
6497 aggregate->count++;
6498
6499 if (aggregate->summary_only)
6500 (bgp_path_info_extra_get(pinew))->suppress++;
6501
6502 switch (pinew->attr->origin) {
6503 case BGP_ORIGIN_INCOMPLETE:
6504 aggregate->incomplete_origin_count++;
6505 break;
6506 case BGP_ORIGIN_EGP:
6507 aggregate->egp_origin_count++;
6508 break;
6509 default:
6510 /* Do nothing.
6511 */
6512 break;
6513 }
6514
6515 if (aggregate->incomplete_origin_count > 0)
6516 origin = BGP_ORIGIN_INCOMPLETE;
6517 else if (aggregate->egp_origin_count > 0)
6518 origin = BGP_ORIGIN_EGP;
6519
229757f1
DA
6520 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6521 origin = aggregate->origin;
6522
fc968841
NT
6523 if (aggregate->as_set) {
6524 /* Compute aggregate route's as-path.
6525 */
6526 bgp_compute_aggregate_aspath(aggregate,
6527 pinew->attr->aspath);
6528
6529 /* Compute aggregate route's community.
6530 */
6531 if (pinew->attr->community)
6532 bgp_compute_aggregate_community(
6533 aggregate,
6534 pinew->attr->community);
6535
6536 /* Compute aggregate route's extended community.
6537 */
6538 if (pinew->attr->ecommunity)
6539 bgp_compute_aggregate_ecommunity(
6540 aggregate,
6541 pinew->attr->ecommunity);
6542
6543 /* Compute aggregate route's large community.
6544 */
6545 if (pinew->attr->lcommunity)
6546 bgp_compute_aggregate_lcommunity(
6547 aggregate,
6548 pinew->attr->lcommunity);
6549
6550 /* Retrieve aggregate route's as-path.
6551 */
6552 if (aggregate->aspath)
6553 aspath = aspath_dup(aggregate->aspath);
6554
6555 /* Retrieve aggregate route's community.
6556 */
6557 if (aggregate->community)
6558 community = community_dup(aggregate->community);
6559
6560 /* Retrieve aggregate route's ecommunity.
6561 */
6562 if (aggregate->ecommunity)
6563 ecommunity = ecommunity_dup(aggregate->ecommunity);
6564
6565 /* Retrieve aggregate route's lcommunity.
6566 */
6567 if (aggregate->lcommunity)
6568 lcommunity = lcommunity_dup(aggregate->lcommunity);
6569 }
6570
6571 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6572 aspath, community, ecommunity,
6573 lcommunity, atomic_aggregate, aggregate);
6574}
6575
6576static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
6577 safi_t safi,
6578 struct bgp_path_info *pi,
6579 struct bgp_aggregate *aggregate,
5f040085 6580 const struct prefix *aggr_p)
fc968841
NT
6581{
6582 uint8_t origin;
6583 struct aspath *aspath = NULL;
6584 uint8_t atomic_aggregate = 0;
6585 struct community *community = NULL;
6586 struct ecommunity *ecommunity = NULL;
6587 struct lcommunity *lcommunity = NULL;
6588 unsigned long match = 0;
6589
6590 if (BGP_PATH_HOLDDOWN(pi))
6591 return;
6592
6593 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6594 return;
6595
6596 if (aggregate->summary_only
6597 && pi->extra
6598 && pi->extra->suppress > 0) {
6599 pi->extra->suppress--;
6600
6601 if (pi->extra->suppress == 0) {
6602 bgp_path_info_set_flag(pi->net, pi,
6603 BGP_PATH_ATTR_CHANGED);
6604 match++;
6605 }
6606 }
6607
6608 if (aggregate->count > 0)
6609 aggregate->count--;
6610
6611 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6612 aggregate->incomplete_origin_count--;
6613 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6614 aggregate->egp_origin_count--;
6615
6616 if (aggregate->as_set) {
6617 /* Remove as-path from aggregate.
6618 */
6619 bgp_remove_aspath_from_aggregate(aggregate,
6620 pi->attr->aspath);
6621
6622 if (pi->attr->community)
6623 /* Remove community from aggregate.
6624 */
6625 bgp_remove_community_from_aggregate(
6626 aggregate,
6627 pi->attr->community);
6628
6629 if (pi->attr->ecommunity)
6630 /* Remove ecommunity from aggregate.
6631 */
6632 bgp_remove_ecommunity_from_aggregate(
6633 aggregate,
6634 pi->attr->ecommunity);
6635
6636 if (pi->attr->lcommunity)
6637 /* Remove lcommunity from aggregate.
6638 */
6639 bgp_remove_lcommunity_from_aggregate(
6640 aggregate,
6641 pi->attr->lcommunity);
6642 }
6643
6644 /* If this node was suppressed, process the change. */
6645 if (match)
6646 bgp_process(bgp, pi->net, afi, safi);
6647
6648 origin = BGP_ORIGIN_IGP;
6649 if (aggregate->incomplete_origin_count > 0)
6650 origin = BGP_ORIGIN_INCOMPLETE;
6651 else if (aggregate->egp_origin_count > 0)
6652 origin = BGP_ORIGIN_EGP;
6653
229757f1
DA
6654 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6655 origin = aggregate->origin;
6656
fc968841
NT
6657 if (aggregate->as_set) {
6658 /* Retrieve aggregate route's as-path.
6659 */
6660 if (aggregate->aspath)
6661 aspath = aspath_dup(aggregate->aspath);
6662
6663 /* Retrieve aggregate route's community.
6664 */
6665 if (aggregate->community)
6666 community = community_dup(aggregate->community);
6667
6668 /* Retrieve aggregate route's ecommunity.
6669 */
6670 if (aggregate->ecommunity)
6671 ecommunity = ecommunity_dup(aggregate->ecommunity);
6672
6673 /* Retrieve aggregate route's lcommunity.
6674 */
6675 if (aggregate->lcommunity)
6676 lcommunity = lcommunity_dup(aggregate->lcommunity);
6677 }
6678
6679 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6680 aspath, community, ecommunity,
6681 lcommunity, atomic_aggregate, aggregate);
6682}
6683
5a1ae2c2 6684void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 6685 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 6686{
9bcb3eef
DS
6687 struct bgp_dest *child;
6688 struct bgp_dest *dest;
d62a17ae 6689 struct bgp_aggregate *aggregate;
6690 struct bgp_table *table;
718e3744 6691
d62a17ae 6692 table = bgp->aggregate[afi][safi];
f018db83 6693
d62a17ae 6694 /* No aggregates configured. */
6695 if (bgp_table_top_nolock(table) == NULL)
6696 return;
f018db83 6697
d62a17ae 6698 if (p->prefixlen == 0)
6699 return;
718e3744 6700
40381db7 6701 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 6702 return;
718e3744 6703
d62a17ae 6704 child = bgp_node_get(table, p);
718e3744 6705
d62a17ae 6706 /* Aggregate address configuration check. */
9bcb3eef
DS
6707 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
6708 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6709
9bcb3eef
DS
6710 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
6711 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
6712 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 6713 aggregate);
d62a17ae 6714 }
b1e62edd 6715 }
9bcb3eef 6716 bgp_dest_unlock_node(child);
718e3744 6717}
6718
5a1ae2c2 6719void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 6720 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 6721{
9bcb3eef
DS
6722 struct bgp_dest *child;
6723 struct bgp_dest *dest;
d62a17ae 6724 struct bgp_aggregate *aggregate;
6725 struct bgp_table *table;
718e3744 6726
d62a17ae 6727 table = bgp->aggregate[afi][safi];
718e3744 6728
d62a17ae 6729 /* No aggregates configured. */
6730 if (bgp_table_top_nolock(table) == NULL)
6731 return;
718e3744 6732
d62a17ae 6733 if (p->prefixlen == 0)
6734 return;
718e3744 6735
d62a17ae 6736 child = bgp_node_get(table, p);
718e3744 6737
d62a17ae 6738 /* Aggregate address configuration check. */
9bcb3eef
DS
6739 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
6740 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6741
9bcb3eef
DS
6742 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
6743 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 6744 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 6745 aggregate, dest_p);
d62a17ae 6746 }
b1e62edd 6747 }
9bcb3eef 6748 bgp_dest_unlock_node(child);
d62a17ae 6749}
718e3744 6750
718e3744 6751/* Aggregate route attribute. */
6752#define AGGREGATE_SUMMARY_ONLY 1
6753#define AGGREGATE_AS_SET 1
fb29348a 6754#define AGGREGATE_AS_UNSET 0
718e3744 6755
229757f1
DA
6756static const char *bgp_origin2str(uint8_t origin)
6757{
6758 switch (origin) {
6759 case BGP_ORIGIN_IGP:
6760 return "igp";
6761 case BGP_ORIGIN_EGP:
6762 return "egp";
6763 case BGP_ORIGIN_INCOMPLETE:
6764 return "incomplete";
6765 }
6766 return "n/a";
6767}
6768
d62a17ae 6769static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
6770 afi_t afi, safi_t safi)
718e3744 6771{
d62a17ae 6772 VTY_DECLVAR_CONTEXT(bgp, bgp);
6773 int ret;
6774 struct prefix p;
9bcb3eef 6775 struct bgp_dest *dest;
d62a17ae 6776 struct bgp_aggregate *aggregate;
718e3744 6777
d62a17ae 6778 /* Convert string to prefix structure. */
6779 ret = str2prefix(prefix_str, &p);
6780 if (!ret) {
6781 vty_out(vty, "Malformed prefix\n");
6782 return CMD_WARNING_CONFIG_FAILED;
6783 }
6784 apply_mask(&p);
6785
6786 /* Old configuration check. */
9bcb3eef
DS
6787 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
6788 if (!dest) {
d62a17ae 6789 vty_out(vty,
6790 "%% There is no aggregate-address configuration.\n");
6791 return CMD_WARNING_CONFIG_FAILED;
6792 }
f6269b4f 6793
9bcb3eef 6794 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
09990cdd 6795 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
dd18c5a9
DS
6796 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
6797 NULL, NULL, 0, aggregate);
d62a17ae 6798
6799 /* Unlock aggregate address configuration. */
9bcb3eef 6800 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
6801
6802 if (aggregate->community)
6803 community_free(&aggregate->community);
6804
6805 if (aggregate->community_hash) {
6806 /* Delete all communities in the hash.
6807 */
6808 hash_clean(aggregate->community_hash,
6809 bgp_aggr_community_remove);
6810 /* Free up the community_hash.
6811 */
6812 hash_free(aggregate->community_hash);
6813 }
6814
6815 if (aggregate->ecommunity)
6816 ecommunity_free(&aggregate->ecommunity);
6817
6818 if (aggregate->ecommunity_hash) {
6819 /* Delete all ecommunities in the hash.
6820 */
6821 hash_clean(aggregate->ecommunity_hash,
6822 bgp_aggr_ecommunity_remove);
6823 /* Free up the ecommunity_hash.
6824 */
6825 hash_free(aggregate->ecommunity_hash);
6826 }
6827
6828 if (aggregate->lcommunity)
6829 lcommunity_free(&aggregate->lcommunity);
6830
6831 if (aggregate->lcommunity_hash) {
6832 /* Delete all lcommunities in the hash.
6833 */
6834 hash_clean(aggregate->lcommunity_hash,
6835 bgp_aggr_lcommunity_remove);
6836 /* Free up the lcommunity_hash.
6837 */
6838 hash_free(aggregate->lcommunity_hash);
6839 }
6840
6841 if (aggregate->aspath)
6842 aspath_free(aggregate->aspath);
6843
6844 if (aggregate->aspath_hash) {
6845 /* Delete all as-paths in the hash.
6846 */
6847 hash_clean(aggregate->aspath_hash,
6848 bgp_aggr_aspath_remove);
6849 /* Free up the aspath_hash.
6850 */
6851 hash_free(aggregate->aspath_hash);
6852 }
6853
d62a17ae 6854 bgp_aggregate_free(aggregate);
9bcb3eef
DS
6855 bgp_dest_unlock_node(dest);
6856 bgp_dest_unlock_node(dest);
d62a17ae 6857
6858 return CMD_SUCCESS;
6859}
6860
6861static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
229757f1
DA
6862 safi_t safi, const char *rmap,
6863 uint8_t summary_only, uint8_t as_set,
6864 uint8_t origin)
d62a17ae 6865{
6866 VTY_DECLVAR_CONTEXT(bgp, bgp);
6867 int ret;
6868 struct prefix p;
9bcb3eef 6869 struct bgp_dest *dest;
d62a17ae 6870 struct bgp_aggregate *aggregate;
fb29348a 6871 uint8_t as_set_new = as_set;
d62a17ae 6872
6873 /* Convert string to prefix structure. */
6874 ret = str2prefix(prefix_str, &p);
6875 if (!ret) {
6876 vty_out(vty, "Malformed prefix\n");
6877 return CMD_WARNING_CONFIG_FAILED;
6878 }
6879 apply_mask(&p);
6880
3624ac81
DS
6881 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
6882 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
6883 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6884 prefix_str);
6885 return CMD_WARNING_CONFIG_FAILED;
6886 }
6887
d62a17ae 6888 /* Old configuration check. */
9bcb3eef
DS
6889 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
6890 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 6891
20894f50 6892 if (aggregate) {
d62a17ae 6893 vty_out(vty, "There is already same aggregate network.\n");
6894 /* try to remove the old entry */
6895 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
6896 if (ret) {
6897 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 6898 bgp_dest_unlock_node(dest);
d62a17ae 6899 return CMD_WARNING_CONFIG_FAILED;
6900 }
6901 }
718e3744 6902
d62a17ae 6903 /* Make aggregate address structure. */
6904 aggregate = bgp_aggregate_new();
6905 aggregate->summary_only = summary_only;
fb29348a
DA
6906
6907 /* Network operators MUST NOT locally generate any new
6908 * announcements containing AS_SET or AS_CONFED_SET. If they have
6909 * announced routes with AS_SET or AS_CONFED_SET in them, then they
6910 * SHOULD withdraw those routes and re-announce routes for the
6911 * aggregate or component prefixes (i.e., the more-specific routes
6912 * subsumed by the previously aggregated route) without AS_SET
6913 * or AS_CONFED_SET in the updates.
6914 */
7f972cd8 6915 if (bgp->reject_as_sets) {
fb29348a
DA
6916 if (as_set == AGGREGATE_AS_SET) {
6917 as_set_new = AGGREGATE_AS_UNSET;
6918 zlog_warn(
63efca0e 6919 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a
DA
6920 __func__);
6921 vty_out(vty,
6922 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
6923 }
6924 }
6925
6926 aggregate->as_set = as_set_new;
d62a17ae 6927 aggregate->safi = safi;
229757f1
DA
6928 /* Override ORIGIN attribute if defined.
6929 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
6930 * to IGP which is not what rfc4271 says.
6931 * This enables the same behavior, optionally.
6932 */
6933 aggregate->origin = origin;
20894f50
DA
6934
6935 if (rmap) {
6936 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6937 route_map_counter_decrement(aggregate->rmap.map);
6938 aggregate->rmap.name =
6939 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6940 aggregate->rmap.map = route_map_lookup_by_name(rmap);
6941 route_map_counter_increment(aggregate->rmap.map);
6942 }
9bcb3eef 6943 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 6944
d62a17ae 6945 /* Aggregate address insert into BGP routing table. */
fc968841 6946 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 6947
d62a17ae 6948 return CMD_SUCCESS;
718e3744 6949}
6950
6951DEFUN (aggregate_address,
6952 aggregate_address_cmd,
229757f1 6953 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 6954 "Configure BGP aggregate entries\n"
6955 "Aggregate prefix\n"
6956 "Generate AS set path information\n"
a636c635
DW
6957 "Filter more specific routes from updates\n"
6958 "Filter more specific routes from updates\n"
20894f50
DA
6959 "Generate AS set path information\n"
6960 "Apply route map to aggregate network\n"
229757f1
DA
6961 "Name of route map\n"
6962 "BGP origin code\n"
6963 "Remote EGP\n"
6964 "Local IGP\n"
6965 "Unknown heritage\n")
718e3744 6966{
d62a17ae 6967 int idx = 0;
6968 argv_find(argv, argc, "A.B.C.D/M", &idx);
6969 char *prefix = argv[idx]->arg;
20894f50 6970 char *rmap = NULL;
229757f1 6971 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
fb29348a
DA
6972 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
6973 : AGGREGATE_AS_UNSET;
d62a17ae 6974 idx = 0;
6975 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6976 ? AGGREGATE_SUMMARY_ONLY
6977 : 0;
e3e6107d 6978
20894f50
DA
6979 idx = 0;
6980 argv_find(argv, argc, "WORD", &idx);
6981 if (idx)
6982 rmap = argv[idx]->arg;
6983
229757f1
DA
6984 idx = 0;
6985 if (argv_find(argv, argc, "origin", &idx)) {
6986 if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
6987 origin = BGP_ORIGIN_IGP;
6988 if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
6989 origin = BGP_ORIGIN_EGP;
6990 if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
6991 origin = BGP_ORIGIN_INCOMPLETE;
6992 }
6993
6994 return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty), rmap,
6995 summary_only, as_set, origin);
718e3744 6996}
6997
e3e6107d
QY
6998DEFUN (aggregate_address_mask,
6999 aggregate_address_mask_cmd,
229757f1 7000 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 7001 "Configure BGP aggregate entries\n"
7002 "Aggregate address\n"
7003 "Aggregate mask\n"
7004 "Generate AS set path information\n"
a636c635
DW
7005 "Filter more specific routes from updates\n"
7006 "Filter more specific routes from updates\n"
20894f50
DA
7007 "Generate AS set path information\n"
7008 "Apply route map to aggregate network\n"
229757f1
DA
7009 "Name of route map\n"
7010 "BGP origin code\n"
7011 "Remote EGP\n"
7012 "Local IGP\n"
7013 "Unknown heritage\n")
718e3744 7014{
d62a17ae 7015 int idx = 0;
7016 argv_find(argv, argc, "A.B.C.D", &idx);
7017 char *prefix = argv[idx]->arg;
7018 char *mask = argv[idx + 1]->arg;
cf40d052 7019 bool rmap_found;
20894f50 7020 char *rmap = NULL;
229757f1 7021 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
fb29348a
DA
7022 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
7023 : AGGREGATE_AS_UNSET;
d62a17ae 7024 idx = 0;
7025 int summary_only = argv_find(argv, argc, "summary-only", &idx)
7026 ? AGGREGATE_SUMMARY_ONLY
7027 : 0;
7028
cf40d052
DS
7029 rmap_found = argv_find(argv, argc, "WORD", &idx);
7030 if (rmap_found)
20894f50
DA
7031 rmap = argv[idx]->arg;
7032
d62a17ae 7033 char prefix_str[BUFSIZ];
7034 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
7035
7036 if (!ret) {
7037 vty_out(vty, "%% Inconsistent address and mask\n");
7038 return CMD_WARNING_CONFIG_FAILED;
7039 }
718e3744 7040
229757f1
DA
7041 idx = 0;
7042 if (argv_find(argv, argc, "origin", &idx)) {
7043 if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
7044 origin = BGP_ORIGIN_IGP;
7045 if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
7046 origin = BGP_ORIGIN_EGP;
7047 if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
7048 origin = BGP_ORIGIN_INCOMPLETE;
7049 }
7050
d62a17ae 7051 return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
229757f1 7052 rmap, summary_only, as_set, origin);
718e3744 7053}
7054
718e3744 7055DEFUN (no_aggregate_address,
7056 no_aggregate_address_cmd,
229757f1 7057 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 7058 NO_STR
7059 "Configure BGP aggregate entries\n"
a636c635
DW
7060 "Aggregate prefix\n"
7061 "Generate AS set path information\n"
e3e6107d
QY
7062 "Filter more specific routes from updates\n"
7063 "Filter more specific routes from updates\n"
b84da0db
DA
7064 "Generate AS set path information\n"
7065 "Apply route map to aggregate network\n"
229757f1
DA
7066 "Name of route map\n"
7067 "BGP origin code\n"
7068 "Remote EGP\n"
7069 "Local IGP\n"
7070 "Unknown heritage\n")
718e3744 7071{
d62a17ae 7072 int idx = 0;
7073 argv_find(argv, argc, "A.B.C.D/M", &idx);
7074 char *prefix = argv[idx]->arg;
7075 return bgp_aggregate_unset(vty, prefix, AFI_IP, bgp_node_safi(vty));
718e3744 7076}
7077
718e3744 7078DEFUN (no_aggregate_address_mask,
7079 no_aggregate_address_mask_cmd,
229757f1 7080 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 7081 NO_STR
7082 "Configure BGP aggregate entries\n"
7083 "Aggregate address\n"
a636c635
DW
7084 "Aggregate mask\n"
7085 "Generate AS set path information\n"
e3e6107d
QY
7086 "Filter more specific routes from updates\n"
7087 "Filter more specific routes from updates\n"
b84da0db
DA
7088 "Generate AS set path information\n"
7089 "Apply route map to aggregate network\n"
229757f1
DA
7090 "Name of route map\n"
7091 "BGP origin code\n"
7092 "Remote EGP\n"
7093 "Local IGP\n"
7094 "Unknown heritage\n")
718e3744 7095{
d62a17ae 7096 int idx = 0;
7097 argv_find(argv, argc, "A.B.C.D", &idx);
7098 char *prefix = argv[idx]->arg;
7099 char *mask = argv[idx + 1]->arg;
718e3744 7100
d62a17ae 7101 char prefix_str[BUFSIZ];
7102 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
718e3744 7103
d62a17ae 7104 if (!ret) {
7105 vty_out(vty, "%% Inconsistent address and mask\n");
7106 return CMD_WARNING_CONFIG_FAILED;
7107 }
718e3744 7108
d62a17ae 7109 return bgp_aggregate_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
718e3744 7110}
7111
718e3744 7112DEFUN (ipv6_aggregate_address,
7113 ipv6_aggregate_address_cmd,
229757f1 7114 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 7115 "Configure BGP aggregate entries\n"
7116 "Aggregate prefix\n"
5101fece 7117 "Generate AS set path information\n"
7118 "Filter more specific routes from updates\n"
7119 "Filter more specific routes from updates\n"
20894f50
DA
7120 "Generate AS set path information\n"
7121 "Apply route map to aggregate network\n"
229757f1
DA
7122 "Name of route map\n"
7123 "BGP origin code\n"
7124 "Remote EGP\n"
7125 "Local IGP\n"
7126 "Unknown heritage\n")
718e3744 7127{
d62a17ae 7128 int idx = 0;
7129 argv_find(argv, argc, "X:X::X:X/M", &idx);
7130 char *prefix = argv[idx]->arg;
20894f50 7131 char *rmap = NULL;
273fae13 7132 bool rmap_found;
229757f1 7133 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
fb29348a
DA
7134 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
7135 : AGGREGATE_AS_UNSET;
5101fece 7136
7137 idx = 0;
d62a17ae 7138 int sum_only = argv_find(argv, argc, "summary-only", &idx)
7139 ? AGGREGATE_SUMMARY_ONLY
7140 : 0;
20894f50 7141
273fae13
DA
7142 rmap_found = argv_find(argv, argc, "WORD", &idx);
7143 if (rmap_found)
20894f50
DA
7144 rmap = argv[idx]->arg;
7145
229757f1
DA
7146 idx = 0;
7147 if (argv_find(argv, argc, "origin", &idx)) {
7148 if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
7149 origin = BGP_ORIGIN_IGP;
7150 if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
7151 origin = BGP_ORIGIN_EGP;
7152 if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
7153 origin = BGP_ORIGIN_INCOMPLETE;
7154 }
7155
20894f50 7156 return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, rmap,
229757f1 7157 sum_only, as_set, origin);
718e3744 7158}
7159
7160DEFUN (no_ipv6_aggregate_address,
7161 no_ipv6_aggregate_address_cmd,
229757f1 7162 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 7163 NO_STR
7164 "Configure BGP aggregate entries\n"
16cedbb0 7165 "Aggregate prefix\n"
5101fece 7166 "Generate AS set path information\n"
7167 "Filter more specific routes from updates\n"
7168 "Filter more specific routes from updates\n"
b84da0db
DA
7169 "Generate AS set path information\n"
7170 "Apply route map to aggregate network\n"
229757f1
DA
7171 "Name of route map\n"
7172 "BGP origin code\n"
7173 "Remote EGP\n"
7174 "Local IGP\n"
7175 "Unknown heritage\n")
718e3744 7176{
d62a17ae 7177 int idx = 0;
7178 argv_find(argv, argc, "X:X::X:X/M", &idx);
7179 char *prefix = argv[idx]->arg;
7180 return bgp_aggregate_unset(vty, prefix, AFI_IP6, SAFI_UNICAST);
718e3744 7181}
7182
718e3744 7183/* Redistribute route treatment. */
d62a17ae 7184void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
7185 const union g_addr *nexthop, ifindex_t ifindex,
7186 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
7187 uint8_t type, unsigned short instance,
7188 route_tag_t tag)
d62a17ae 7189{
4b7e6066 7190 struct bgp_path_info *new;
40381db7
DS
7191 struct bgp_path_info *bpi;
7192 struct bgp_path_info rmap_path;
9bcb3eef 7193 struct bgp_dest *bn;
d62a17ae 7194 struct attr attr;
7195 struct attr *new_attr;
7196 afi_t afi;
b68885f9 7197 route_map_result_t ret;
d62a17ae 7198 struct bgp_redist *red;
7199
7200 /* Make default attribute. */
7201 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
7202 /*
7203 * This must not be NULL to satisfy Coverity SA
7204 */
7205 assert(attr.aspath);
9de1f7ff 7206
a4d82a8a 7207 switch (nhtype) {
9de1f7ff
DS
7208 case NEXTHOP_TYPE_IFINDEX:
7209 break;
7210 case NEXTHOP_TYPE_IPV4:
7211 case NEXTHOP_TYPE_IPV4_IFINDEX:
7212 attr.nexthop = nexthop->ipv4;
7213 break;
7214 case NEXTHOP_TYPE_IPV6:
7215 case NEXTHOP_TYPE_IPV6_IFINDEX:
7216 attr.mp_nexthop_global = nexthop->ipv6;
7217 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
7218 break;
7219 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
7220 switch (p->family) {
7221 case AF_INET:
9de1f7ff 7222 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
7223 break;
7224 case AF_INET6:
9de1f7ff
DS
7225 memset(&attr.mp_nexthop_global, 0,
7226 sizeof(attr.mp_nexthop_global));
74489921 7227 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 7228 break;
74489921 7229 }
9de1f7ff 7230 break;
d62a17ae 7231 }
74489921 7232 attr.nh_ifindex = ifindex;
f04a80a5 7233
d62a17ae 7234 attr.med = metric;
7235 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
7236 attr.tag = tag;
718e3744 7237
d62a17ae 7238 afi = family2afi(p->family);
6aeb9e78 7239
d62a17ae 7240 red = bgp_redist_lookup(bgp, afi, type, instance);
7241 if (red) {
7242 struct attr attr_new;
718e3744 7243
d62a17ae 7244 /* Copy attribute for modification. */
6f4f49b2 7245 attr_new = attr;
718e3744 7246
d62a17ae 7247 if (red->redist_metric_flag)
7248 attr_new.med = red->redist_metric;
718e3744 7249
d62a17ae 7250 /* Apply route-map. */
7251 if (red->rmap.name) {
40381db7
DS
7252 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
7253 rmap_path.peer = bgp->peer_self;
7254 rmap_path.attr = &attr_new;
718e3744 7255
d62a17ae 7256 SET_FLAG(bgp->peer_self->rmap_type,
7257 PEER_RMAP_TYPE_REDISTRIBUTE);
7258
7259 ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
40381db7 7260 &rmap_path);
d62a17ae 7261
7262 bgp->peer_self->rmap_type = 0;
7263
7264 if (ret == RMAP_DENYMATCH) {
7265 /* Free uninterned attribute. */
7266 bgp_attr_flush(&attr_new);
7267
7268 /* Unintern original. */
7269 aspath_unintern(&attr.aspath);
7270 bgp_redistribute_delete(bgp, p, type, instance);
7271 return;
7272 }
7273 }
7274
892fedb6 7275 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
7f323236
DW
7276 bgp_attr_add_gshut_community(&attr_new);
7277
d62a17ae 7278 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7279 SAFI_UNICAST, p, NULL);
7280
7281 new_attr = bgp_attr_intern(&attr_new);
7282
9bcb3eef 7283 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
7284 if (bpi->peer == bgp->peer_self
7285 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 7286 break;
7287
40381db7 7288 if (bpi) {
d62a17ae 7289 /* Ensure the (source route) type is updated. */
40381db7
DS
7290 bpi->type = type;
7291 if (attrhash_cmp(bpi->attr, new_attr)
7292 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 7293 bgp_attr_unintern(&new_attr);
7294 aspath_unintern(&attr.aspath);
9bcb3eef 7295 bgp_dest_unlock_node(bn);
d62a17ae 7296 return;
7297 } else {
7298 /* The attribute is changed. */
40381db7 7299 bgp_path_info_set_flag(bn, bpi,
18ee8310 7300 BGP_PATH_ATTR_CHANGED);
d62a17ae 7301
7302 /* Rewrite BGP route information. */
40381db7
DS
7303 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
7304 bgp_path_info_restore(bn, bpi);
d62a17ae 7305 else
40381db7
DS
7306 bgp_aggregate_decrement(
7307 bgp, p, bpi, afi, SAFI_UNICAST);
7308 bgp_attr_unintern(&bpi->attr);
7309 bpi->attr = new_attr;
7310 bpi->uptime = bgp_clock();
d62a17ae 7311
7312 /* Process change. */
40381db7 7313 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 7314 SAFI_UNICAST);
7315 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 7316 bgp_dest_unlock_node(bn);
d62a17ae 7317 aspath_unintern(&attr.aspath);
ddb5b488
PZ
7318
7319 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7320 || (bgp->inst_type
7321 == BGP_INSTANCE_TYPE_DEFAULT)) {
7322
7323 vpn_leak_from_vrf_update(
40381db7 7324 bgp_get_default(), bgp, bpi);
ddb5b488 7325 }
d62a17ae 7326 return;
7327 }
7328 }
7329
7330 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
7331 bgp->peer_self, new_attr, bn);
1defdda8 7332 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 7333
7334 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 7335 bgp_path_info_add(bn, new);
9bcb3eef 7336 bgp_dest_unlock_node(bn);
d62a17ae 7337 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
7338
7339 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7340 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7341
7342 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
7343 }
d62a17ae 7344 }
7345
7346 /* Unintern original. */
7347 aspath_unintern(&attr.aspath);
718e3744 7348}
7349
d7c0a89a
QY
7350void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
7351 unsigned short instance)
718e3744 7352{
d62a17ae 7353 afi_t afi;
9bcb3eef 7354 struct bgp_dest *dest;
40381db7 7355 struct bgp_path_info *pi;
d62a17ae 7356 struct bgp_redist *red;
718e3744 7357
d62a17ae 7358 afi = family2afi(p->family);
718e3744 7359
d62a17ae 7360 red = bgp_redist_lookup(bgp, afi, type, instance);
7361 if (red) {
9bcb3eef
DS
7362 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7363 SAFI_UNICAST, p, NULL);
d62a17ae 7364
9bcb3eef 7365 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 7366 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 7367 break;
7368
40381db7 7369 if (pi) {
ddb5b488
PZ
7370 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7371 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7372
7373 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7374 bgp, pi);
ddb5b488 7375 }
40381db7 7376 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
7377 bgp_path_info_delete(dest, pi);
7378 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 7379 }
9bcb3eef 7380 bgp_dest_unlock_node(dest);
d62a17ae 7381 }
7382}
7383
7384/* Withdraw specified route type's route. */
7385void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 7386 unsigned short instance)
d62a17ae 7387{
9bcb3eef 7388 struct bgp_dest *dest;
40381db7 7389 struct bgp_path_info *pi;
d62a17ae 7390 struct bgp_table *table;
7391
7392 table = bgp->rib[afi][SAFI_UNICAST];
7393
9bcb3eef
DS
7394 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
7395 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7396 if (pi->peer == bgp->peer_self && pi->type == type
7397 && pi->instance == instance)
d62a17ae 7398 break;
7399
40381db7 7400 if (pi) {
ddb5b488
PZ
7401 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7402 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7403
7404 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7405 bgp, pi);
ddb5b488 7406 }
9bcb3eef 7407 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 7408 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
7409 bgp_path_info_delete(dest, pi);
7410 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 7411 }
718e3744 7412 }
718e3744 7413}
6b0655a2 7414
718e3744 7415/* Static function to display route. */
bd494ec5 7416static void route_vty_out_route(const struct prefix *p, struct vty *vty,
9c92b5f7 7417 json_object *json)
718e3744 7418{
be054588 7419 int len = 0;
d62a17ae 7420 char buf[BUFSIZ];
50e05855 7421 char buf2[BUFSIZ];
718e3744 7422
d62a17ae 7423 if (p->family == AF_INET) {
c6462ff4 7424 if (!json) {
89e5e9f0
PM
7425 len = vty_out(
7426 vty, "%s/%d",
7427 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
7428 p->prefixlen);
c6462ff4
MK
7429 } else {
7430 json_object_string_add(json, "prefix",
7431 inet_ntop(p->family,
7432 &p->u.prefix, buf,
7433 BUFSIZ));
7434 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 7435 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 7436 json_object_string_add(json, "network", buf2);
c6462ff4 7437 }
d62a17ae 7438 } else if (p->family == AF_ETHERNET) {
b03b8898
DS
7439 prefix2str(p, buf, PREFIX_STRLEN);
7440 len = vty_out(vty, "%s", buf);
7441 } else if (p->family == AF_EVPN) {
57f7feb6 7442 if (!json)
60466a63
QY
7443 len = vty_out(
7444 vty, "%s",
7445 bgp_evpn_route2str((struct prefix_evpn *)p, buf,
7446 BUFSIZ));
57f7feb6 7447 else
60466a63 7448 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
7449 } else if (p->family == AF_FLOWSPEC) {
7450 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
7451 json ?
7452 NLRI_STRING_FORMAT_JSON_SIMPLE :
7453 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 7454 } else {
c6462ff4 7455 if (!json)
60466a63
QY
7456 len = vty_out(
7457 vty, "%s/%d",
7458 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
7459 p->prefixlen);
50e05855
AD
7460 else {
7461 json_object_string_add(json, "prefix",
7462 inet_ntop(p->family,
7463 &p->u.prefix, buf,
7464 BUFSIZ));
7465 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
7466 prefix2str(p, buf2, PREFIX_STRLEN);
7467 json_object_string_add(json, "network", buf2);
7468 }
9c92b5f7 7469 }
d62a17ae 7470
9c92b5f7
MK
7471 if (!json) {
7472 len = 17 - len;
7473 if (len < 1)
7474 vty_out(vty, "\n%*s", 20, " ");
7475 else
7476 vty_out(vty, "%*s", len, " ");
7477 }
718e3744 7478}
7479
d62a17ae 7480enum bgp_display_type {
7481 normal_list,
718e3744 7482};
7483
18ee8310 7484/* Print the short form route status for a bgp_path_info */
4b7e6066 7485static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 7486 struct bgp_path_info *path,
d62a17ae 7487 json_object *json_path)
718e3744 7488{
d62a17ae 7489 if (json_path) {
b05a1c8b 7490
d62a17ae 7491 /* Route status display. */
9b6d8fcf 7492 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7493 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 7494
9b6d8fcf 7495 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7496 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 7497
9b6d8fcf 7498 if (path->extra && path->extra->suppress)
d62a17ae 7499 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 7500
9b6d8fcf
DS
7501 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7502 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7503 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 7504
d62a17ae 7505 /* Selected */
9b6d8fcf 7506 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7507 json_object_boolean_true_add(json_path, "history");
b05a1c8b 7508
9b6d8fcf 7509 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7510 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 7511
9b6d8fcf 7512 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7513 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b 7514
9b6d8fcf 7515 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7516 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 7517
d62a17ae 7518 /* Internal route. */
9b6d8fcf
DS
7519 if ((path->peer->as)
7520 && (path->peer->as == path->peer->local_as))
d62a17ae 7521 json_object_string_add(json_path, "pathFrom",
7522 "internal");
7523 else
7524 json_object_string_add(json_path, "pathFrom",
7525 "external");
b05a1c8b 7526
d62a17ae 7527 return;
7528 }
b05a1c8b 7529
d62a17ae 7530 /* Route status display. */
9b6d8fcf 7531 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7532 vty_out(vty, "R");
9b6d8fcf 7533 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7534 vty_out(vty, "S");
9b6d8fcf 7535 else if (path->extra && path->extra->suppress)
d62a17ae 7536 vty_out(vty, "s");
9b6d8fcf
DS
7537 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7538 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7539 vty_out(vty, "*");
7540 else
7541 vty_out(vty, " ");
7542
7543 /* Selected */
9b6d8fcf 7544 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7545 vty_out(vty, "h");
9b6d8fcf 7546 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7547 vty_out(vty, "d");
9b6d8fcf 7548 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7549 vty_out(vty, ">");
9b6d8fcf 7550 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7551 vty_out(vty, "=");
7552 else
7553 vty_out(vty, " ");
718e3744 7554
d62a17ae 7555 /* Internal route. */
9b6d8fcf
DS
7556 if (path->peer && (path->peer->as)
7557 && (path->peer->as == path->peer->local_as))
d62a17ae 7558 vty_out(vty, "i");
7559 else
7560 vty_out(vty, " ");
b40d939b 7561}
7562
2ba93fd6
DA
7563static char *bgp_nexthop_hostname(struct peer *peer,
7564 struct bgp_nexthop_cache *bnc)
25b5da8d 7565{
892fedb6 7566 if (peer->hostname
aef999a2 7567 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
7568 return peer->hostname;
7569 return NULL;
7570}
7571
b40d939b 7572/* called from terminal list command */
bd494ec5 7573void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 7574 struct bgp_path_info *path, int display, safi_t safi,
4b7e6066 7575 json_object *json_paths)
d62a17ae 7576{
aef999a2 7577 int len;
515c2602 7578 struct attr *attr = path->attr;
d62a17ae 7579 json_object *json_path = NULL;
7580 json_object *json_nexthops = NULL;
7581 json_object *json_nexthop_global = NULL;
7582 json_object *json_nexthop_ll = NULL;
6f214dd3 7583 json_object *json_ext_community = NULL;
9df8b37c 7584 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 7585 bool nexthop_self =
9b6d8fcf 7586 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 7587 bool nexthop_othervrf = false;
43089216 7588 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 7589 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
7590 char *nexthop_hostname =
7591 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 7592
7593 if (json_paths)
7594 json_path = json_object_new_object();
7595
7596 /* short status lead text */
9b6d8fcf 7597 route_vty_short_status_out(vty, path, json_path);
d62a17ae 7598
7599 if (!json_paths) {
7600 /* print prefix and mask */
7601 if (!display)
9c92b5f7 7602 route_vty_out_route(p, vty, json_path);
d62a17ae 7603 else
7604 vty_out(vty, "%*s", 17, " ");
9c92b5f7 7605 } else {
b682f6de 7606 route_vty_out_route(p, vty, json_path);
d62a17ae 7607 }
47fc97cc 7608
9df8b37c
PZ
7609 /*
7610 * If vrf id of nexthop is different from that of prefix,
7611 * set up printable string to append
7612 */
9b6d8fcf 7613 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
7614 const char *self = "";
7615
7616 if (nexthop_self)
7617 self = "<";
7618
7619 nexthop_othervrf = true;
9b6d8fcf 7620 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 7621
9b6d8fcf 7622 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
7623 snprintf(vrf_id_str, sizeof(vrf_id_str),
7624 "@%s%s", VRFID_NONE_STR, self);
7625 else
7626 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 7627 path->extra->bgp_orig->vrf_id, self);
9df8b37c 7628
9b6d8fcf
DS
7629 if (path->extra->bgp_orig->inst_type
7630 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 7631
9b6d8fcf 7632 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
7633 } else {
7634 const char *self = "";
7635
7636 if (nexthop_self)
7637 self = "<";
7638
7639 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
7640 }
7641
445c2480
DS
7642 /*
7643 * For ENCAP and EVPN routes, nexthop address family is not
7644 * neccessarily the same as the prefix address family.
7645 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7646 * EVPN routes are also exchanged with a MP nexthop. Currently,
7647 * this
7648 * is only IPv4, the value will be present in either
7649 * attr->nexthop or
7650 * attr->mp_nexthop_global_in
7651 */
7652 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
7653 char buf[BUFSIZ];
7654 char nexthop[128];
7655 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
7656
7657 switch (af) {
7658 case AF_INET:
772270f3
QY
7659 snprintf(nexthop, sizeof(nexthop), "%s",
7660 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
7661 BUFSIZ));
445c2480
DS
7662 break;
7663 case AF_INET6:
772270f3
QY
7664 snprintf(nexthop, sizeof(nexthop), "%s",
7665 inet_ntop(af, &attr->mp_nexthop_global, buf,
7666 BUFSIZ));
445c2480
DS
7667 break;
7668 default:
772270f3 7669 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 7670 break;
d62a17ae 7671 }
d62a17ae 7672
445c2480
DS
7673 if (json_paths) {
7674 json_nexthop_global = json_object_new_object();
7675
515c2602
DA
7676 json_object_string_add(json_nexthop_global, "ip",
7677 nexthop);
7678
939a97f4 7679 if (path->peer->hostname)
515c2602
DA
7680 json_object_string_add(json_nexthop_global,
7681 "hostname",
939a97f4 7682 path->peer->hostname);
515c2602
DA
7683
7684 json_object_string_add(json_nexthop_global, "afi",
7685 (af == AF_INET) ? "ipv4"
7686 : "ipv6");
445c2480
DS
7687 json_object_boolean_true_add(json_nexthop_global,
7688 "used");
aef999a2
DA
7689 } else {
7690 if (nexthop_hostname)
7691 len = vty_out(vty, "%s(%s)%s", nexthop,
7692 nexthop_hostname, vrf_id_str);
7693 else
7694 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
7695
7696 len = 16 - len;
7697 if (len < 1)
7698 vty_out(vty, "\n%*s", 36, " ");
7699 else
7700 vty_out(vty, "%*s", len, " ");
7701 }
445c2480
DS
7702 } else if (safi == SAFI_EVPN) {
7703 if (json_paths) {
7704 json_nexthop_global = json_object_new_object();
7705
515c2602
DA
7706 json_object_string_add(json_nexthop_global, "ip",
7707 inet_ntoa(attr->nexthop));
7708
939a97f4 7709 if (path->peer->hostname)
515c2602
DA
7710 json_object_string_add(json_nexthop_global,
7711 "hostname",
939a97f4 7712 path->peer->hostname);
515c2602 7713
a4d82a8a
PZ
7714 json_object_string_add(json_nexthop_global, "afi",
7715 "ipv4");
445c2480
DS
7716 json_object_boolean_true_add(json_nexthop_global,
7717 "used");
aef999a2
DA
7718 } else {
7719 if (nexthop_hostname)
7720 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
7721 nexthop_hostname, vrf_id_str);
7722 else
7723 len = vty_out(vty, "%pI4%s", &attr->nexthop,
7724 vrf_id_str);
7725
7726 len = 16 - len;
7727 if (len < 1)
7728 vty_out(vty, "\n%*s", 36, " ");
7729 else
7730 vty_out(vty, "%*s", len, " ");
7731 }
d33fc23b 7732 } else if (safi == SAFI_FLOWSPEC) {
975a328e 7733 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
7734 if (json_paths) {
7735 json_nexthop_global = json_object_new_object();
515c2602 7736
026b914a
PG
7737 json_object_string_add(json_nexthop_global,
7738 "afi", "ipv4");
515c2602
DA
7739 json_object_string_add(
7740 json_nexthop_global, "ip",
7741 inet_ntoa(attr->nexthop));
7742
939a97f4 7743 if (path->peer->hostname)
515c2602
DA
7744 json_object_string_add(
7745 json_nexthop_global, "hostname",
939a97f4 7746 path->peer->hostname);
515c2602 7747
50e05855
AD
7748 json_object_boolean_true_add(
7749 json_nexthop_global,
026b914a
PG
7750 "used");
7751 } else {
aef999a2
DA
7752 if (nexthop_hostname)
7753 len = vty_out(vty, "%pI4(%s)%s",
7754 &attr->nexthop,
7755 nexthop_hostname,
7756 vrf_id_str);
7757 else
7758 len = vty_out(vty, "%pI4%s",
7759 &attr->nexthop,
7760 vrf_id_str);
7761
7762 len = 16 - len;
7763 if (len < 1)
7764 vty_out(vty, "\n%*s", 36, " ");
7765 else
7766 vty_out(vty, "%*s", len, " ");
026b914a
PG
7767 }
7768 }
d33fc23b 7769 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
7770 if (json_paths) {
7771 json_nexthop_global = json_object_new_object();
d62a17ae 7772
515c2602
DA
7773 json_object_string_add(json_nexthop_global, "ip",
7774 inet_ntoa(attr->nexthop));
7775
939a97f4 7776 if (path->peer->hostname)
515c2602
DA
7777 json_object_string_add(json_nexthop_global,
7778 "hostname",
939a97f4 7779 path->peer->hostname);
445c2480 7780
a4d82a8a
PZ
7781 json_object_string_add(json_nexthop_global, "afi",
7782 "ipv4");
445c2480
DS
7783 json_object_boolean_true_add(json_nexthop_global,
7784 "used");
7785 } else {
aef999a2
DA
7786 if (nexthop_hostname)
7787 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
7788 nexthop_hostname, vrf_id_str);
7789 else
7790 len = vty_out(vty, "%pI4%s", &attr->nexthop,
7791 vrf_id_str);
9df8b37c 7792
aef999a2
DA
7793 len = 16 - len;
7794 if (len < 1)
7795 vty_out(vty, "\n%*s", 36, " ");
7796 else
7797 vty_out(vty, "%*s", len, " ");
d62a17ae 7798 }
445c2480 7799 }
b05a1c8b 7800
445c2480 7801 /* IPv6 Next Hop */
a4d82a8a 7802 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 7803 char buf[BUFSIZ];
d62a17ae 7804
445c2480
DS
7805 if (json_paths) {
7806 json_nexthop_global = json_object_new_object();
a4d82a8a 7807 json_object_string_add(
515c2602
DA
7808 json_nexthop_global, "ip",
7809 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
7810 buf, BUFSIZ));
7811
939a97f4 7812 if (path->peer->hostname)
515c2602
DA
7813 json_object_string_add(json_nexthop_global,
7814 "hostname",
939a97f4 7815 path->peer->hostname);
515c2602 7816
a4d82a8a
PZ
7817 json_object_string_add(json_nexthop_global, "afi",
7818 "ipv6");
7819 json_object_string_add(json_nexthop_global, "scope",
7820 "global");
445c2480
DS
7821
7822 /* We display both LL & GL if both have been
7823 * received */
0606039c
DA
7824 if ((attr->mp_nexthop_len
7825 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 7826 || (path->peer->conf_if)) {
a4d82a8a 7827 json_nexthop_ll = json_object_new_object();
d62a17ae 7828 json_object_string_add(
515c2602
DA
7829 json_nexthop_ll, "ip",
7830 inet_ntop(AF_INET6,
7831 &attr->mp_nexthop_local, buf,
7832 BUFSIZ));
7833
939a97f4 7834 if (path->peer->hostname)
515c2602
DA
7835 json_object_string_add(
7836 json_nexthop_ll, "hostname",
939a97f4 7837 path->peer->hostname);
515c2602 7838
a4d82a8a
PZ
7839 json_object_string_add(json_nexthop_ll, "afi",
7840 "ipv6");
7841 json_object_string_add(json_nexthop_ll, "scope",
445c2480 7842 "link-local");
d62a17ae 7843
a4d82a8a
PZ
7844 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
7845 &attr->mp_nexthop_local)
445c2480
DS
7846 != 0)
7847 && !attr->mp_nexthop_prefer_global)
d62a17ae 7848 json_object_boolean_true_add(
a4d82a8a 7849 json_nexthop_ll, "used");
445c2480
DS
7850 else
7851 json_object_boolean_true_add(
a4d82a8a 7852 json_nexthop_global, "used");
445c2480
DS
7853 } else
7854 json_object_boolean_true_add(
7855 json_nexthop_global, "used");
7856 } else {
7857 /* Display LL if LL/Global both in table unless
7858 * prefer-global is set */
0606039c
DA
7859 if (((attr->mp_nexthop_len
7860 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 7861 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
7862 || (path->peer->conf_if)) {
7863 if (path->peer->conf_if) {
a4d82a8a 7864 len = vty_out(vty, "%s",
9b6d8fcf 7865 path->peer->conf_if);
445c2480
DS
7866 len = 16 - len; /* len of IPv6
7867 addr + max
7868 len of def
7869 ifname */
7870
7871 if (len < 1)
a4d82a8a 7872 vty_out(vty, "\n%*s", 36, " ");
445c2480 7873 else
a4d82a8a 7874 vty_out(vty, "%*s", len, " ");
d62a17ae 7875 } else {
aef999a2
DA
7876 if (nexthop_hostname)
7877 len = vty_out(
7878 vty, "%pI6(%s)%s",
7879 &attr->mp_nexthop_local,
7880 nexthop_hostname,
7881 vrf_id_str);
7882 else
7883 len = vty_out(
7884 vty, "%pI6%s",
7885 &attr->mp_nexthop_local,
7886 vrf_id_str);
7887
d62a17ae 7888 len = 16 - len;
7889
7890 if (len < 1)
a4d82a8a 7891 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 7892 else
a4d82a8a 7893 vty_out(vty, "%*s", len, " ");
d62a17ae 7894 }
445c2480 7895 } else {
aef999a2
DA
7896 if (nexthop_hostname)
7897 len = vty_out(vty, "%pI6(%s)%s",
7898 &attr->mp_nexthop_global,
7899 nexthop_hostname,
7900 vrf_id_str);
7901 else
7902 len = vty_out(vty, "%pI6%s",
7903 &attr->mp_nexthop_global,
7904 vrf_id_str);
7905
445c2480
DS
7906 len = 16 - len;
7907
7908 if (len < 1)
7909 vty_out(vty, "\n%*s", 36, " ");
7910 else
7911 vty_out(vty, "%*s", len, " ");
d62a17ae 7912 }
7913 }
445c2480 7914 }
718e3744 7915
445c2480
DS
7916 /* MED/Metric */
7917 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 7918 if (json_paths)
50e05855 7919 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 7920 else
445c2480
DS
7921 vty_out(vty, "%10u", attr->med);
7922 else if (!json_paths)
7923 vty_out(vty, " ");
d62a17ae 7924
445c2480
DS
7925 /* Local Pref */
7926 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 7927 if (json_paths)
50e05855 7928 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
7929 attr->local_pref);
7930 else
445c2480
DS
7931 vty_out(vty, "%7u", attr->local_pref);
7932 else if (!json_paths)
7933 vty_out(vty, " ");
d62a17ae 7934
445c2480
DS
7935 if (json_paths)
7936 json_object_int_add(json_path, "weight", attr->weight);
7937 else
7938 vty_out(vty, "%7u ", attr->weight);
47fc97cc 7939
445c2480
DS
7940 if (json_paths) {
7941 char buf[BUFSIZ];
a4d82a8a
PZ
7942 json_object_string_add(
7943 json_path, "peerId",
9b6d8fcf 7944 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 7945 }
b05a1c8b 7946
445c2480
DS
7947 /* Print aspath */
7948 if (attr->aspath) {
0fbac0b4 7949 if (json_paths)
50e05855 7950 json_object_string_add(json_path, "path",
0fbac0b4
DA
7951 attr->aspath->str);
7952 else
445c2480 7953 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 7954 }
f1aa5d8a 7955
445c2480
DS
7956 /* Print origin */
7957 if (json_paths)
a4d82a8a
PZ
7958 json_object_string_add(json_path, "origin",
7959 bgp_origin_long_str[attr->origin]);
445c2480
DS
7960 else
7961 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7962
9df8b37c 7963 if (json_paths) {
6f214dd3
CS
7964 if (safi == SAFI_EVPN &&
7965 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7966 json_ext_community = json_object_new_object();
7967 json_object_string_add(json_ext_community,
7968 "string",
7969 attr->ecommunity->str);
7970 json_object_object_add(json_path,
7971 "extendedCommunity",
7972 json_ext_community);
7973 }
7974
9df8b37c
PZ
7975 if (nexthop_self)
7976 json_object_boolean_true_add(json_path,
7977 "announceNexthopSelf");
7978 if (nexthop_othervrf) {
7979 json_object_string_add(json_path, "nhVrfName",
7980 nexthop_vrfname);
7981
7982 json_object_int_add(json_path, "nhVrfId",
7983 ((nexthop_vrfid == VRF_UNKNOWN)
7984 ? -1
7985 : (int)nexthop_vrfid));
7986 }
7987 }
7988
d62a17ae 7989 if (json_paths) {
7990 if (json_nexthop_global || json_nexthop_ll) {
7991 json_nexthops = json_object_new_array();
f1aa5d8a 7992
d62a17ae 7993 if (json_nexthop_global)
7994 json_object_array_add(json_nexthops,
7995 json_nexthop_global);
f1aa5d8a 7996
d62a17ae 7997 if (json_nexthop_ll)
7998 json_object_array_add(json_nexthops,
7999 json_nexthop_ll);
f1aa5d8a 8000
d62a17ae 8001 json_object_object_add(json_path, "nexthops",
8002 json_nexthops);
8003 }
8004
8005 json_object_array_add(json_paths, json_path);
8006 } else {
8007 vty_out(vty, "\n");
6f214dd3
CS
8008
8009 if (safi == SAFI_EVPN &&
8010 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8011 vty_out(vty, "%*s", 20, " ");
8012 vty_out(vty, "%s\n", attr->ecommunity->str);
8013 }
8014
49e5a4a0 8015#ifdef ENABLE_BGP_VNC
d62a17ae 8016 /* prints an additional line, indented, with VNC info, if
8017 * present */
8018 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 8019 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 8020#endif
d62a17ae 8021 }
8022}
718e3744 8023
8024/* called from terminal list command */
5f040085
DS
8025void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
8026 struct attr *attr, safi_t safi, bool use_json,
8027 json_object *json_ar)
d62a17ae 8028{
8029 json_object *json_status = NULL;
8030 json_object *json_net = NULL;
aef999a2 8031 int len;
d62a17ae 8032 char buff[BUFSIZ];
dc387b0f 8033
d62a17ae 8034 /* Route status display. */
8035 if (use_json) {
8036 json_status = json_object_new_object();
8037 json_net = json_object_new_object();
8038 } else {
8039 vty_out(vty, "*");
8040 vty_out(vty, ">");
8041 vty_out(vty, " ");
8042 }
718e3744 8043
d62a17ae 8044 /* print prefix and mask */
50e05855 8045 if (use_json) {
dc387b0f
LK
8046 if (safi == SAFI_EVPN)
8047 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
8048 else if (p->family == AF_INET || p->family == AF_INET6) {
8049 json_object_string_add(
8050 json_net, "addrPrefix",
8051 inet_ntop(p->family, &p->u.prefix, buff,
8052 BUFSIZ));
8053 json_object_int_add(json_net, "prefixLen",
8054 p->prefixlen);
8055 prefix2str(p, buff, PREFIX_STRLEN);
8056 json_object_string_add(json_net, "network", buff);
8057 }
50e05855 8058 } else
9c92b5f7 8059 route_vty_out_route(p, vty, NULL);
d62a17ae 8060
8061 /* Print attribute */
8062 if (attr) {
8063 if (use_json) {
8064 if (p->family == AF_INET
8065 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 8066 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 8067 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 8068 json_object_string_add(
8069 json_net, "nextHop",
8070 inet_ntoa(
8071 attr->mp_nexthop_global_in));
8072 else
8073 json_object_string_add(
8074 json_net, "nextHop",
8075 inet_ntoa(attr->nexthop));
8076 } else if (p->family == AF_INET6
8077 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8078 char buf[BUFSIZ];
8079
8080 json_object_string_add(
aa0a10fc 8081 json_net, "nextHopGlobal",
d62a17ae 8082 inet_ntop(AF_INET6,
8083 &attr->mp_nexthop_global, buf,
8084 BUFSIZ));
dc387b0f
LK
8085 } else if (p->family == AF_EVPN &&
8086 !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8087 json_object_string_add(json_net,
8088 "nextHop", inet_ntoa(
8089 attr->mp_nexthop_global_in));
d62a17ae 8090
8091 if (attr->flag
8092 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8093 json_object_int_add(json_net, "metric",
8094 attr->med);
8095
0fbac0b4 8096 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 8097 json_object_int_add(json_net, "locPrf",
0fbac0b4 8098 attr->local_pref);
d62a17ae 8099
8100 json_object_int_add(json_net, "weight", attr->weight);
8101
8102 /* Print aspath */
0fbac0b4 8103 if (attr->aspath)
50e05855 8104 json_object_string_add(json_net, "path",
0fbac0b4 8105 attr->aspath->str);
d62a17ae 8106
8107 /* Print origin */
8108 json_object_string_add(json_net, "bgpOriginCode",
8109 bgp_origin_str[attr->origin]);
8110 } else {
8111 if (p->family == AF_INET
8112 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8113 || safi == SAFI_EVPN
8114 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8115 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8116 || safi == SAFI_EVPN)
8117 vty_out(vty, "%-16s",
8118 inet_ntoa(
8119 attr->mp_nexthop_global_in));
8120 else
8121 vty_out(vty, "%-16s",
8122 inet_ntoa(attr->nexthop));
8123 } else if (p->family == AF_INET6
8124 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 8125 char buf[BUFSIZ];
8126
8127 len = vty_out(
8128 vty, "%s",
8129 inet_ntop(AF_INET6,
8130 &attr->mp_nexthop_global, buf,
8131 BUFSIZ));
8132 len = 16 - len;
8133 if (len < 1)
8134 vty_out(vty, "\n%*s", 36, " ");
8135 else
8136 vty_out(vty, "%*s", len, " ");
8137 }
8138 if (attr->flag
8139 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8140 vty_out(vty, "%10u", attr->med);
8141 else
8142 vty_out(vty, " ");
718e3744 8143
d62a17ae 8144 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
8145 vty_out(vty, "%7u", attr->local_pref);
8146 else
8147 vty_out(vty, " ");
8148
8149 vty_out(vty, "%7u ", attr->weight);
8150
8151 /* Print aspath */
8152 if (attr->aspath)
8153 aspath_print_vty(vty, "%s", attr->aspath, " ");
8154
8155 /* Print origin */
8156 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8157 }
8158 }
8159 if (use_json) {
8160 json_object_boolean_true_add(json_status, "*");
8161 json_object_boolean_true_add(json_status, ">");
8162 json_object_object_add(json_net, "appliedStatusSymbols",
8163 json_status);
1608ff77 8164
dc387b0f
LK
8165 prefix2str(p, buff, PREFIX_STRLEN);
8166 json_object_object_add(json_ar, buff, json_net);
d62a17ae 8167 } else
8168 vty_out(vty, "\n");
8169}
8170
bd494ec5 8171void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 8172 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 8173 json_object *json)
8174{
8175 json_object *json_out = NULL;
8176 struct attr *attr;
8177 mpls_label_t label = MPLS_INVALID_LABEL;
8178
9b6d8fcf 8179 if (!path->extra)
d62a17ae 8180 return;
8181
8182 if (json)
8183 json_out = json_object_new_object();
8184
8185 /* short status lead text */
9b6d8fcf 8186 route_vty_short_status_out(vty, path, json_out);
d62a17ae 8187
8188 /* print prefix and mask */
8189 if (json == NULL) {
8190 if (!display)
9c92b5f7 8191 route_vty_out_route(p, vty, NULL);
d62a17ae 8192 else
8193 vty_out(vty, "%*s", 17, " ");
8194 }
8195
8196 /* Print attribute */
9b6d8fcf 8197 attr = path->attr;
05864da7
DS
8198 if (((p->family == AF_INET)
8199 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8200 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8201 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8202 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8203 || safi == SAFI_EVPN) {
8204 if (json)
8205 json_object_string_add(
8206 json_out, "mpNexthopGlobalIn",
8207 inet_ntoa(attr->mp_nexthop_global_in));
8208 else
8209 vty_out(vty, "%-16s",
8210 inet_ntoa(attr->mp_nexthop_global_in));
8211 } else {
8212 if (json)
8213 json_object_string_add(
8214 json_out, "nexthop",
8215 inet_ntoa(attr->nexthop));
8216 else
8217 vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
8218 }
8219 } else if (((p->family == AF_INET6)
8220 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8221 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8222 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8223 char buf_a[512];
8224
8225 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
8226 if (json)
8227 json_object_string_add(
8228 json_out, "mpNexthopGlobalIn",
8229 inet_ntop(AF_INET6,
8230 &attr->mp_nexthop_global,
8231 buf_a, sizeof(buf_a)));
8232 else
8233 vty_out(vty, "%s",
8234 inet_ntop(AF_INET6,
8235 &attr->mp_nexthop_global,
8236 buf_a, sizeof(buf_a)));
8237 } else if (attr->mp_nexthop_len
8238 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
8239 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
8240 &attr->mp_nexthop_global,
8241 &attr->mp_nexthop_local);
8242 if (json)
8243 json_object_string_add(json_out,
8244 "mpNexthopGlobalLocal",
8245 buf_a);
8246 else
8247 vty_out(vty, "%s", buf_a);
d62a17ae 8248 }
8249 }
8250
9b6d8fcf 8251 label = decode_label(&path->extra->label[0]);
d62a17ae 8252
8253 if (bgp_is_valid_label(&label)) {
8254 if (json) {
8255 json_object_int_add(json_out, "notag", label);
8256 json_object_array_add(json, json_out);
8257 } else {
8258 vty_out(vty, "notag/%d", label);
8259 vty_out(vty, "\n");
8260 }
8261 }
8262}
718e3744 8263
bd494ec5 8264void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 8265 struct bgp_path_info *path, int display,
d62a17ae 8266 json_object *json_paths)
718e3744 8267{
d62a17ae 8268 struct attr *attr;
14f51eba 8269 char buf[BUFSIZ] = {0};
d62a17ae 8270 json_object *json_path = NULL;
14f51eba
LK
8271 json_object *json_nexthop = NULL;
8272 json_object *json_overlay = NULL;
856ca177 8273
9b6d8fcf 8274 if (!path->extra)
d62a17ae 8275 return;
718e3744 8276
14f51eba
LK
8277 if (json_paths) {
8278 json_path = json_object_new_object();
8279 json_overlay = json_object_new_object();
8280 json_nexthop = json_object_new_object();
8281 }
8282
d62a17ae 8283 /* short status lead text */
9b6d8fcf 8284 route_vty_short_status_out(vty, path, json_path);
856ca177 8285
d62a17ae 8286 /* print prefix and mask */
8287 if (!display)
14f51eba 8288 route_vty_out_route(p, vty, json_path);
d62a17ae 8289 else
8290 vty_out(vty, "%*s", 17, " ");
8291
8292 /* Print attribute */
9b6d8fcf 8293 attr = path->attr;
05864da7
DS
8294 char buf1[BUFSIZ];
8295 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 8296
05864da7
DS
8297 switch (af) {
8298 case AF_INET:
8299 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
8300 if (!json_path) {
8301 vty_out(vty, "%-16s", buf);
8302 } else {
8303 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 8304
05864da7 8305 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 8306
05864da7
DS
8307 json_object_object_add(json_path, "nexthop",
8308 json_nexthop);
8309 }
8310 break;
8311 case AF_INET6:
8312 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
8313 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
8314 if (!json_path) {
8315 vty_out(vty, "%s(%s)", buf, buf1);
8316 } else {
8317 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 8318
05864da7
DS
8319 json_object_string_add(json_nexthop, "ipv6LinkLocal",
8320 buf1);
14f51eba 8321
05864da7 8322 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 8323
05864da7
DS
8324 json_object_object_add(json_path, "nexthop",
8325 json_nexthop);
8326 }
8327 break;
8328 default:
8329 if (!json_path) {
8330 vty_out(vty, "?");
8331 } else {
8332 json_object_string_add(json_nexthop, "Error",
8333 "Unsupported address-family");
d62a17ae 8334 }
05864da7 8335 }
988258b4 8336
05864da7 8337 char *str = esi2str(&(attr->evpn_overlay.eth_s_id));
988258b4 8338
05864da7
DS
8339 if (!json_path)
8340 vty_out(vty, "%s", str);
8341 else
8342 json_object_string_add(json_overlay, "esi", str);
25b5da8d 8343
05864da7 8344 XFREE(MTYPE_TMP, str);
988258b4 8345
05864da7
DS
8346 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
8347 inet_ntop(AF_INET, &(attr->evpn_overlay.gw_ip.ipv4), buf,
8348 BUFSIZ);
8349 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
8350 inet_ntop(AF_INET6, &(attr->evpn_overlay.gw_ip.ipv6), buf,
8351 BUFSIZ);
8352 }
14f51eba 8353
05864da7
DS
8354 if (!json_path)
8355 vty_out(vty, "/%s", buf);
8356 else
8357 json_object_string_add(json_overlay, "gw", buf);
8358
8359 if (attr->ecommunity) {
8360 char *mac = NULL;
8361 struct ecommunity_val *routermac = ecommunity_lookup(
8362 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
8363 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
8364
8365 if (routermac)
8366 mac = ecom_mac2str((char *)routermac->val);
8367 if (mac) {
8368 if (!json_path) {
c4efd0f4 8369 vty_out(vty, "/%s", mac);
05864da7
DS
8370 } else {
8371 json_object_string_add(json_overlay, "rmac",
8372 mac);
988258b4 8373 }
05864da7 8374 XFREE(MTYPE_TMP, mac);
988258b4 8375 }
05864da7 8376 }
718e3744 8377
05864da7
DS
8378 if (!json_path) {
8379 vty_out(vty, "\n");
8380 } else {
8381 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 8382
05864da7 8383 json_object_array_add(json_paths, json_path);
14f51eba 8384 }
d62a17ae 8385}
718e3744 8386
d62a17ae 8387/* dampening route */
5f040085
DS
8388static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
8389 struct bgp_path_info *path, int display,
8390 afi_t afi, safi_t safi, bool use_json,
8391 json_object *json)
d62a17ae 8392{
8393 struct attr *attr;
8394 int len;
8395 char timebuf[BGP_UPTIME_LEN];
8396
8397 /* short status lead text */
9b6d8fcf 8398 route_vty_short_status_out(vty, path, json);
d62a17ae 8399
8400 /* print prefix and mask */
8401 if (!use_json) {
8402 if (!display)
9c92b5f7 8403 route_vty_out_route(p, vty, NULL);
d62a17ae 8404 else
8405 vty_out(vty, "%*s", 17, " ");
8406 }
8407
9b6d8fcf 8408 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 8409 len = 17 - len;
8410 if (len < 1) {
8411 if (!use_json)
8412 vty_out(vty, "\n%*s", 34, " ");
8413 } else {
8414 if (use_json)
8415 json_object_int_add(json, "peerHost", len);
8416 else
8417 vty_out(vty, "%*s", len, " ");
8418 }
8419
8420 if (use_json)
a935f597
DA
8421 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
8422 safi, use_json, json);
d62a17ae 8423 else
9b6d8fcf
DS
8424 vty_out(vty, "%s ",
8425 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8426 BGP_UPTIME_LEN, afi, safi,
8427 use_json, json));
d62a17ae 8428
8429 /* Print attribute */
9b6d8fcf 8430 attr = path->attr;
d62a17ae 8431
05864da7
DS
8432 /* Print aspath */
8433 if (attr->aspath) {
d62a17ae 8434 if (use_json)
05864da7
DS
8435 json_object_string_add(json, "asPath",
8436 attr->aspath->str);
d62a17ae 8437 else
05864da7 8438 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8439 }
05864da7
DS
8440
8441 /* Print origin */
8442 if (use_json)
8443 json_object_string_add(json, "origin",
8444 bgp_origin_str[attr->origin]);
8445 else
8446 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8447
d62a17ae 8448 if (!use_json)
8449 vty_out(vty, "\n");
8450}
718e3744 8451
d62a17ae 8452/* flap route */
5f040085
DS
8453static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
8454 struct bgp_path_info *path, int display,
8455 afi_t afi, safi_t safi, bool use_json,
8456 json_object *json)
784d3a42 8457{
d62a17ae 8458 struct attr *attr;
8459 struct bgp_damp_info *bdi;
8460 char timebuf[BGP_UPTIME_LEN];
8461 int len;
784d3a42 8462
9b6d8fcf 8463 if (!path->extra)
d62a17ae 8464 return;
784d3a42 8465
9b6d8fcf 8466 bdi = path->extra->damp_info;
784d3a42 8467
d62a17ae 8468 /* short status lead text */
9b6d8fcf 8469 route_vty_short_status_out(vty, path, json);
784d3a42 8470
d62a17ae 8471 /* print prefix and mask */
8472 if (!use_json) {
8473 if (!display)
9c92b5f7 8474 route_vty_out_route(p, vty, NULL);
d62a17ae 8475 else
8476 vty_out(vty, "%*s", 17, " ");
8477 }
784d3a42 8478
9b6d8fcf 8479 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 8480 len = 16 - len;
8481 if (len < 1) {
8482 if (!use_json)
8483 vty_out(vty, "\n%*s", 33, " ");
8484 } else {
8485 if (use_json)
8486 json_object_int_add(json, "peerHost", len);
8487 else
8488 vty_out(vty, "%*s", len, " ");
8489 }
784d3a42 8490
d62a17ae 8491 len = vty_out(vty, "%d", bdi->flap);
8492 len = 5 - len;
8493 if (len < 1) {
8494 if (!use_json)
8495 vty_out(vty, " ");
8496 } else {
8497 if (use_json)
8498 json_object_int_add(json, "bdiFlap", len);
8499 else
8500 vty_out(vty, "%*s", len, " ");
8501 }
8502
8503 if (use_json)
8504 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
8505 json);
8506 else
996c9314
LB
8507 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
8508 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 8509
9b6d8fcf
DS
8510 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
8511 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 8512 if (use_json)
9b6d8fcf 8513 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8514 BGP_UPTIME_LEN, afi, safi,
8515 use_json, json);
d62a17ae 8516 else
8517 vty_out(vty, "%s ",
9b6d8fcf 8518 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8519 BGP_UPTIME_LEN, afi,
8520 safi, use_json, json));
d62a17ae 8521 } else {
8522 if (!use_json)
8523 vty_out(vty, "%*s ", 8, " ");
8524 }
8525
8526 /* Print attribute */
9b6d8fcf 8527 attr = path->attr;
d62a17ae 8528
05864da7
DS
8529 /* Print aspath */
8530 if (attr->aspath) {
d62a17ae 8531 if (use_json)
05864da7
DS
8532 json_object_string_add(json, "asPath",
8533 attr->aspath->str);
d62a17ae 8534 else
05864da7 8535 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8536 }
05864da7
DS
8537
8538 /* Print origin */
8539 if (use_json)
8540 json_object_string_add(json, "origin",
8541 bgp_origin_str[attr->origin]);
8542 else
8543 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8544
d62a17ae 8545 if (!use_json)
8546 vty_out(vty, "\n");
8547}
8548
8549static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
8550 int *first, const char *header,
8551 json_object *json_adv_to)
8552{
8553 char buf1[INET6_ADDRSTRLEN];
8554 json_object *json_peer = NULL;
8555
8556 if (json_adv_to) {
8557 /* 'advertised-to' is a dictionary of peers we have advertised
8558 * this
8559 * prefix too. The key is the peer's IP or swpX, the value is
8560 * the
8561 * hostname if we know it and "" if not.
8562 */
8563 json_peer = json_object_new_object();
8564
8565 if (peer->hostname)
8566 json_object_string_add(json_peer, "hostname",
8567 peer->hostname);
8568
8569 if (peer->conf_if)
8570 json_object_object_add(json_adv_to, peer->conf_if,
8571 json_peer);
8572 else
8573 json_object_object_add(
8574 json_adv_to,
8575 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
8576 json_peer);
8577 } else {
8578 if (*first) {
8579 vty_out(vty, "%s", header);
8580 *first = 0;
8581 }
8582
8583 if (peer->hostname
892fedb6 8584 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 8585 if (peer->conf_if)
8586 vty_out(vty, " %s(%s)", peer->hostname,
8587 peer->conf_if);
8588 else
8589 vty_out(vty, " %s(%s)", peer->hostname,
8590 sockunion2str(&peer->su, buf1,
8591 SU_ADDRSTRLEN));
8592 } else {
8593 if (peer->conf_if)
8594 vty_out(vty, " %s", peer->conf_if);
8595 else
8596 vty_out(vty, " %s",
8597 sockunion2str(&peer->su, buf1,
8598 SU_ADDRSTRLEN));
8599 }
8600 }
784d3a42
PG
8601}
8602
dcc68b5e
MS
8603static void route_vty_out_tx_ids(struct vty *vty,
8604 struct bgp_addpath_info_data *d)
8605{
8606 int i;
8607
8608 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
8609 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
8610 d->addpath_tx_id[i],
8611 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
8612 }
8613}
8614
0dc8ee70
DS
8615static const char *bgp_path_selection_reason2str(
8616 enum bgp_path_selection_reason reason)
8617{
8618 switch (reason) {
8619 case bgp_path_selection_none:
8620 return "Nothing to Select";
0dc8ee70
DS
8621 case bgp_path_selection_first:
8622 return "First path received";
0dc8ee70
DS
8623 case bgp_path_selection_evpn_sticky_mac:
8624 return "EVPN Sticky Mac";
0dc8ee70
DS
8625 case bgp_path_selection_evpn_seq:
8626 return "EVPN sequence number";
0dc8ee70
DS
8627 case bgp_path_selection_evpn_lower_ip:
8628 return "EVPN lower IP";
0dc8ee70
DS
8629 case bgp_path_selection_weight:
8630 return "Weight";
0dc8ee70
DS
8631 case bgp_path_selection_local_pref:
8632 return "Local Pref";
0dc8ee70
DS
8633 case bgp_path_selection_local_route:
8634 return "Local Route";
0dc8ee70
DS
8635 case bgp_path_selection_confed_as_path:
8636 return "Confederation based AS Path";
0dc8ee70
DS
8637 case bgp_path_selection_as_path:
8638 return "AS Path";
0dc8ee70
DS
8639 case bgp_path_selection_origin:
8640 return "Origin";
0dc8ee70
DS
8641 case bgp_path_selection_med:
8642 return "MED";
0dc8ee70
DS
8643 case bgp_path_selection_peer:
8644 return "Peer Type";
0dc8ee70
DS
8645 case bgp_path_selection_confed:
8646 return "Confed Peer Type";
0dc8ee70
DS
8647 case bgp_path_selection_igp_metric:
8648 return "IGP Metric";
0dc8ee70
DS
8649 case bgp_path_selection_older:
8650 return "Older Path";
0dc8ee70
DS
8651 case bgp_path_selection_router_id:
8652 return "Router ID";
0dc8ee70
DS
8653 case bgp_path_selection_cluster_length:
8654 return "Cluser length";
0dc8ee70
DS
8655 case bgp_path_selection_stale:
8656 return "Path Staleness";
0dc8ee70
DS
8657 case bgp_path_selection_local_configured:
8658 return "Locally configured route";
0dc8ee70
DS
8659 case bgp_path_selection_neighbor_ip:
8660 return "Neighbor IP";
0dc8ee70
DS
8661 case bgp_path_selection_default:
8662 return "Nothing left to compare";
0dc8ee70 8663 }
a74879b2 8664 return "Invalid (internal error)";
0dc8ee70
DS
8665}
8666
9bcb3eef
DS
8667void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
8668 struct bgp_path_info *path, afi_t afi, safi_t safi,
8669 json_object *json_paths)
d62a17ae 8670{
8671 char buf[INET6_ADDRSTRLEN];
8672 char buf1[BUFSIZ];
d62a17ae 8673 char buf2[EVPN_ROUTE_STRLEN];
515c2602 8674 struct attr *attr = path->attr;
d62a17ae 8675 int sockunion_vty_out(struct vty *, union sockunion *);
8676 time_t tbuf;
8677 json_object *json_bestpath = NULL;
8678 json_object *json_cluster_list = NULL;
8679 json_object *json_cluster_list_list = NULL;
8680 json_object *json_ext_community = NULL;
8681 json_object *json_last_update = NULL;
7fd077aa 8682 json_object *json_pmsi = NULL;
d62a17ae 8683 json_object *json_nexthop_global = NULL;
8684 json_object *json_nexthop_ll = NULL;
8685 json_object *json_nexthops = NULL;
8686 json_object *json_path = NULL;
8687 json_object *json_peer = NULL;
8688 json_object *json_string = NULL;
8689 json_object *json_adv_to = NULL;
8690 int first = 0;
8691 struct listnode *node, *nnode;
8692 struct peer *peer;
8693 int addpath_capable;
8694 int has_adj;
8695 unsigned int first_as;
1defdda8 8696 bool nexthop_self =
9b6d8fcf 8697 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 8698 int i;
2ba93fd6
DA
8699 char *nexthop_hostname =
8700 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 8701
8702 if (json_paths) {
8703 json_path = json_object_new_object();
8704 json_peer = json_object_new_object();
8705 json_nexthop_global = json_object_new_object();
8706 }
8707
44c69747 8708 if (path->extra) {
b57ba6d2 8709 char tag_buf[30];
d62a17ae 8710
d7325ee7 8711 buf2[0] = '\0';
d62a17ae 8712 tag_buf[0] = '\0';
9b6d8fcf
DS
8713 if (path->extra && path->extra->num_labels) {
8714 bgp_evpn_label2str(path->extra->label,
8715 path->extra->num_labels, tag_buf,
a4d82a8a 8716 sizeof(tag_buf));
d62a17ae 8717 }
d7325ee7 8718 if (safi == SAFI_EVPN) {
44c69747 8719 if (!json_paths) {
b54892e0
DS
8720 bgp_evpn_route2str(
8721 (struct prefix_evpn *)
9bcb3eef 8722 bgp_dest_get_prefix(bn),
b54892e0 8723 buf2, sizeof(buf2));
44c69747
LK
8724 vty_out(vty, " Route %s", buf2);
8725 if (tag_buf[0] != '\0')
8726 vty_out(vty, " VNI %s", tag_buf);
8727 vty_out(vty, "\n");
8728 } else {
8729 if (tag_buf[0])
8730 json_object_string_add(json_path, "VNI",
8731 tag_buf);
8732 }
d7325ee7
DD
8733 }
8734
44c69747 8735 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 8736 struct bgp_path_info *parent_ri;
9bcb3eef 8737 struct bgp_dest *dest, *pdest;
d62a17ae 8738
9b6d8fcf 8739 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
8740 dest = parent_ri->net;
8741 if (dest && dest->pdest) {
8742 pdest = dest->pdest;
8743 prefix_rd2str(
8744 (struct prefix_rd *)bgp_dest_get_prefix(
8745 pdest),
8746 buf1, sizeof(buf1));
d7325ee7 8747 if (is_pi_family_evpn(parent_ri)) {
b54892e0
DS
8748 bgp_evpn_route2str(
8749 (struct prefix_evpn *)
9bcb3eef
DS
8750 bgp_dest_get_prefix(
8751 dest),
b54892e0 8752 buf2, sizeof(buf2));
d7325ee7
DD
8753 vty_out(vty, " Imported from %s:%s, VNI %s\n", buf1, buf2, tag_buf);
8754 } else
8755 vty_out(vty, " Imported from %s:%s\n", buf1, buf2);
d62a17ae 8756 }
8757 }
8758 }
d62a17ae 8759
05864da7
DS
8760 /* Line1 display AS-path, Aggregator */
8761 if (attr->aspath) {
8762 if (json_paths) {
8763 if (!attr->aspath->json)
8764 aspath_str_update(attr->aspath, true);
8765 json_object_lock(attr->aspath->json);
8766 json_object_object_add(json_path, "aspath",
8767 attr->aspath->json);
8768 } else {
8769 if (attr->aspath->segments)
8770 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 8771 else
05864da7 8772 vty_out(vty, " Local");
d62a17ae 8773 }
05864da7 8774 }
d62a17ae 8775
05864da7
DS
8776 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
8777 if (json_paths)
8778 json_object_boolean_true_add(json_path, "removed");
8779 else
8780 vty_out(vty, ", (removed)");
8781 }
d62a17ae 8782
05864da7
DS
8783 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
8784 if (json_paths)
8785 json_object_boolean_true_add(json_path, "stale");
8786 else
8787 vty_out(vty, ", (stale)");
8788 }
d62a17ae 8789
05864da7
DS
8790 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
8791 if (json_paths) {
8792 json_object_int_add(json_path, "aggregatorAs",
8793 attr->aggregator_as);
8794 json_object_string_add(
8795 json_path, "aggregatorId",
8796 inet_ntoa(attr->aggregator_addr));
87c82131
DA
8797 if (attr->aggregator_as == BGP_AS_ZERO)
8798 json_object_boolean_true_add(
8799 json_path, "aggregatorAsMalformed");
8800 else
8801 json_object_boolean_false_add(
8802 json_path, "aggregatorAsMalformed");
05864da7 8803 } else {
87c82131
DA
8804 if (attr->aggregator_as == BGP_AS_ZERO)
8805 vty_out(vty,
8806 ", (aggregated by %u(malformed) %s)",
8807 attr->aggregator_as,
8808 inet_ntoa(attr->aggregator_addr));
8809 else
8810 vty_out(vty, ", (aggregated by %u %s)",
8811 attr->aggregator_as,
8812 inet_ntoa(attr->aggregator_addr));
d62a17ae 8813 }
05864da7 8814 }
d62a17ae 8815
05864da7
DS
8816 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
8817 PEER_FLAG_REFLECTOR_CLIENT)) {
8818 if (json_paths)
8819 json_object_boolean_true_add(json_path,
8820 "rxedFromRrClient");
8821 else
8822 vty_out(vty, ", (Received from a RR-client)");
8823 }
d62a17ae 8824
05864da7
DS
8825 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
8826 PEER_FLAG_RSERVER_CLIENT)) {
8827 if (json_paths)
8828 json_object_boolean_true_add(json_path,
8829 "rxedFromRsClient");
8830 else
8831 vty_out(vty, ", (Received from a RS-client)");
8832 }
d62a17ae 8833
05864da7
DS
8834 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
8835 if (json_paths)
8836 json_object_boolean_true_add(json_path,
8837 "dampeningHistoryEntry");
8838 else
8839 vty_out(vty, ", (history entry)");
8840 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
8841 if (json_paths)
8842 json_object_boolean_true_add(json_path,
8843 "dampeningSuppressed");
8844 else
8845 vty_out(vty, ", (suppressed due to dampening)");
8846 }
d62a17ae 8847
05864da7
DS
8848 if (!json_paths)
8849 vty_out(vty, "\n");
d62a17ae 8850
05864da7
DS
8851 /* Line2 display Next-hop, Neighbor, Router-id */
8852 /* Display the nexthop */
9bcb3eef 8853 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
8854
8855 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
8856 || bn_p->family == AF_EVPN)
05864da7
DS
8857 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
8858 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8859 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8860 || safi == SAFI_EVPN) {
515c2602 8861 if (json_paths) {
d62a17ae 8862 json_object_string_add(
515c2602
DA
8863 json_nexthop_global, "ip",
8864 inet_ntoa(attr->mp_nexthop_global_in));
8865
939a97f4 8866 if (path->peer->hostname)
515c2602
DA
8867 json_object_string_add(
8868 json_nexthop_global, "hostname",
939a97f4 8869 path->peer->hostname);
aef999a2
DA
8870 } else {
8871 if (nexthop_hostname)
8872 vty_out(vty, " %pI4(%s)",
8873 &attr->mp_nexthop_global_in,
8874 nexthop_hostname);
8875 else
8876 vty_out(vty, " %pI4",
8877 &attr->mp_nexthop_global_in);
8878 }
d62a17ae 8879 } else {
515c2602 8880 if (json_paths) {
05864da7 8881 json_object_string_add(
515c2602
DA
8882 json_nexthop_global, "ip",
8883 inet_ntoa(attr->nexthop));
8884
939a97f4 8885 if (path->peer->hostname)
515c2602
DA
8886 json_object_string_add(
8887 json_nexthop_global, "hostname",
939a97f4 8888 path->peer->hostname);
aef999a2
DA
8889 } else {
8890 if (nexthop_hostname)
8891 vty_out(vty, " %pI4(%s)",
8892 &attr->nexthop,
8893 nexthop_hostname);
8894 else
8895 vty_out(vty, " %pI4",
8896 &attr->nexthop);
8897 }
d62a17ae 8898 }
8899
05864da7
DS
8900 if (json_paths)
8901 json_object_string_add(json_nexthop_global, "afi",
8902 "ipv4");
8903 } else {
8904 if (json_paths) {
8905 json_object_string_add(
515c2602
DA
8906 json_nexthop_global, "ip",
8907 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8908 buf, INET6_ADDRSTRLEN));
8909
939a97f4 8910 if (path->peer->hostname)
515c2602
DA
8911 json_object_string_add(json_nexthop_global,
8912 "hostname",
939a97f4 8913 path->peer->hostname);
515c2602 8914
05864da7
DS
8915 json_object_string_add(json_nexthop_global, "afi",
8916 "ipv6");
8917 json_object_string_add(json_nexthop_global, "scope",
8918 "global");
8919 } else {
aef999a2
DA
8920 if (nexthop_hostname)
8921 vty_out(vty, " %pI6(%s)",
8922 &attr->mp_nexthop_global,
8923 nexthop_hostname);
8924 else
8925 vty_out(vty, " %pI6",
8926 &attr->mp_nexthop_global);
d62a17ae 8927 }
05864da7 8928 }
d62a17ae 8929
05864da7
DS
8930 /* Display the IGP cost or 'inaccessible' */
8931 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
8932 if (json_paths)
8933 json_object_boolean_false_add(json_nexthop_global,
8934 "accessible");
8935 else
8936 vty_out(vty, " (inaccessible)");
8937 } else {
8938 if (path->extra && path->extra->igpmetric) {
d62a17ae 8939 if (json_paths)
05864da7
DS
8940 json_object_int_add(json_nexthop_global,
8941 "metric",
8942 path->extra->igpmetric);
d62a17ae 8943 else
05864da7
DS
8944 vty_out(vty, " (metric %u)",
8945 path->extra->igpmetric);
d62a17ae 8946 }
8947
05864da7 8948 /* IGP cost is 0, display this only for json */
d62a17ae 8949 else {
d62a17ae 8950 if (json_paths)
05864da7
DS
8951 json_object_int_add(json_nexthop_global,
8952 "metric", 0);
d62a17ae 8953 }
d62a17ae 8954
05864da7
DS
8955 if (json_paths)
8956 json_object_boolean_true_add(json_nexthop_global,
8957 "accessible");
8958 }
d62a17ae 8959
05864da7
DS
8960 /* Display peer "from" output */
8961 /* This path was originated locally */
8962 if (path->peer == bgp->peer_self) {
d62a17ae 8963
05864da7 8964 if (safi == SAFI_EVPN
b54892e0 8965 || (bn_p->family == AF_INET
05864da7 8966 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 8967 if (json_paths)
05864da7
DS
8968 json_object_string_add(json_peer, "peerId",
8969 "0.0.0.0");
d62a17ae 8970 else
05864da7
DS
8971 vty_out(vty, " from 0.0.0.0 ");
8972 } else {
d62a17ae 8973 if (json_paths)
05864da7
DS
8974 json_object_string_add(json_peer, "peerId",
8975 "::");
d62a17ae 8976 else
05864da7 8977 vty_out(vty, " from :: ");
d62a17ae 8978 }
d62a17ae 8979
05864da7
DS
8980 if (json_paths)
8981 json_object_string_add(json_peer, "routerId",
8982 inet_ntoa(bgp->router_id));
8983 else
8984 vty_out(vty, "(%s)", inet_ntoa(bgp->router_id));
8985 }
d62a17ae 8986
05864da7
DS
8987 /* We RXed this path from one of our peers */
8988 else {
8989
8990 if (json_paths) {
8991 json_object_string_add(json_peer, "peerId",
8992 sockunion2str(&path->peer->su,
8993 buf,
8994 SU_ADDRSTRLEN));
8995 json_object_string_add(json_peer, "routerId",
8996 inet_ntop(AF_INET,
8997 &path->peer->remote_id,
8998 buf1, sizeof(buf1)));
8999
9000 if (path->peer->hostname)
9001 json_object_string_add(json_peer, "hostname",
9002 path->peer->hostname);
9003
9004 if (path->peer->domainname)
9005 json_object_string_add(json_peer, "domainname",
9006 path->peer->domainname);
9007
9008 if (path->peer->conf_if)
9009 json_object_string_add(json_peer, "interface",
9010 path->peer->conf_if);
9011 } else {
9012 if (path->peer->conf_if) {
9013 if (path->peer->hostname
892fedb6
DA
9014 && CHECK_FLAG(path->peer->bgp->flags,
9015 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9016 vty_out(vty, " from %s(%s)",
9017 path->peer->hostname,
9018 path->peer->conf_if);
d62a17ae 9019 else
05864da7 9020 vty_out(vty, " from %s",
9b6d8fcf 9021 path->peer->conf_if);
d62a17ae 9022 } else {
05864da7 9023 if (path->peer->hostname
892fedb6
DA
9024 && CHECK_FLAG(path->peer->bgp->flags,
9025 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9026 vty_out(vty, " from %s(%s)",
9027 path->peer->hostname,
9028 path->peer->host);
d62a17ae 9029 else
05864da7
DS
9030 vty_out(vty, " from %s",
9031 sockunion2str(&path->peer->su,
9032 buf,
9033 SU_ADDRSTRLEN));
d62a17ae 9034 }
d62a17ae 9035
05864da7
DS
9036 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
9037 vty_out(vty, " (%s)",
9038 inet_ntoa(attr->originator_id));
9039 else
9040 vty_out(vty, " (%s)",
9041 inet_ntop(AF_INET,
9042 &path->peer->remote_id, buf1,
9043 sizeof(buf1)));
d62a17ae 9044 }
05864da7 9045 }
9df8b37c 9046
05864da7
DS
9047 /*
9048 * Note when vrfid of nexthop is different from that of prefix
9049 */
9050 if (path->extra && path->extra->bgp_orig) {
9051 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9052
05864da7
DS
9053 if (json_paths) {
9054 const char *vn;
9df8b37c 9055
05864da7
DS
9056 if (path->extra->bgp_orig->inst_type
9057 == BGP_INSTANCE_TYPE_DEFAULT)
9058 vn = VRF_DEFAULT_NAME;
9059 else
9060 vn = path->extra->bgp_orig->name;
9df8b37c 9061
05864da7 9062 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 9063
05864da7
DS
9064 if (nexthop_vrfid == VRF_UNKNOWN) {
9065 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 9066 } else {
05864da7
DS
9067 json_object_int_add(json_path, "nhVrfId",
9068 (int)nexthop_vrfid);
9df8b37c 9069 }
05864da7
DS
9070 } else {
9071 if (nexthop_vrfid == VRF_UNKNOWN)
9072 vty_out(vty, " vrf ?");
137147c6
DS
9073 else {
9074 struct vrf *vrf;
9075
9076 vrf = vrf_lookup_by_id(nexthop_vrfid);
9077 vty_out(vty, " vrf %s(%u)",
9078 VRF_LOGNAME(vrf), nexthop_vrfid);
9079 }
9df8b37c 9080 }
05864da7 9081 }
9df8b37c 9082
05864da7
DS
9083 if (nexthop_self) {
9084 if (json_paths) {
9085 json_object_boolean_true_add(json_path,
9086 "announceNexthopSelf");
9087 } else {
9088 vty_out(vty, " announce-nh-self");
9df8b37c 9089 }
05864da7 9090 }
9df8b37c 9091
05864da7
DS
9092 if (!json_paths)
9093 vty_out(vty, "\n");
d62a17ae 9094
05864da7
DS
9095 /* display the link-local nexthop */
9096 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9097 if (json_paths) {
9098 json_nexthop_ll = json_object_new_object();
9099 json_object_string_add(
515c2602
DA
9100 json_nexthop_ll, "ip",
9101 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9102 buf, INET6_ADDRSTRLEN));
9103
939a97f4 9104 if (path->peer->hostname)
515c2602
DA
9105 json_object_string_add(json_nexthop_ll,
9106 "hostname",
939a97f4 9107 path->peer->hostname);
515c2602 9108
05864da7
DS
9109 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
9110 json_object_string_add(json_nexthop_ll, "scope",
9111 "link-local");
d62a17ae 9112
05864da7
DS
9113 json_object_boolean_true_add(json_nexthop_ll,
9114 "accessible");
d62a17ae 9115
05864da7 9116 if (!attr->mp_nexthop_prefer_global)
d62a17ae 9117 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
9118 "used");
9119 else
9120 json_object_boolean_true_add(
9121 json_nexthop_global, "used");
9122 } else {
9123 vty_out(vty, " (%s) %s\n",
9124 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9125 buf, INET6_ADDRSTRLEN),
9126 attr->mp_nexthop_prefer_global
9127 ? "(prefer-global)"
9128 : "(used)");
d62a17ae 9129 }
05864da7
DS
9130 }
9131 /* If we do not have a link-local nexthop then we must flag the
9132 global as "used" */
9133 else {
9134 if (json_paths)
9135 json_object_boolean_true_add(json_nexthop_global,
9136 "used");
9137 }
d62a17ae 9138
05864da7
DS
9139 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
9140 * Int/Ext/Local, Atomic, best */
9141 if (json_paths)
9142 json_object_string_add(json_path, "origin",
9143 bgp_origin_long_str[attr->origin]);
9144 else
9145 vty_out(vty, " Origin %s",
9146 bgp_origin_long_str[attr->origin]);
9df8b37c 9147
05864da7 9148 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 9149 if (json_paths)
05864da7 9150 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 9151 else
05864da7
DS
9152 vty_out(vty, ", metric %u", attr->med);
9153 }
9df8b37c 9154
05864da7
DS
9155 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
9156 if (json_paths)
0fbac0b4 9157 json_object_int_add(json_path, "locPrf",
05864da7
DS
9158 attr->local_pref);
9159 else
9160 vty_out(vty, ", localpref %u", attr->local_pref);
9161 }
9df8b37c 9162
05864da7
DS
9163 if (attr->weight != 0) {
9164 if (json_paths)
9165 json_object_int_add(json_path, "weight", attr->weight);
9166 else
9167 vty_out(vty, ", weight %u", attr->weight);
9168 }
9df8b37c 9169
05864da7
DS
9170 if (attr->tag != 0) {
9171 if (json_paths)
9172 json_object_int_add(json_path, "tag", attr->tag);
9173 else
9174 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
9175 }
9df8b37c 9176
05864da7
DS
9177 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9178 if (json_paths)
9179 json_object_boolean_false_add(json_path, "valid");
9180 else
9181 vty_out(vty, ", invalid");
9182 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9183 if (json_paths)
9184 json_object_boolean_true_add(json_path, "valid");
9185 else
9186 vty_out(vty, ", valid");
9187 }
9df8b37c 9188
05864da7
DS
9189 if (path->peer != bgp->peer_self) {
9190 if (path->peer->as == path->peer->local_as) {
9191 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
9192 if (json_paths)
9193 json_object_string_add(
9194 json_peer, "type",
9195 "confed-internal");
d62a17ae 9196 else
05864da7 9197 vty_out(vty, ", confed-internal");
d62a17ae 9198 } else {
05864da7
DS
9199 if (json_paths)
9200 json_object_string_add(
9201 json_peer, "type", "internal");
9202 else
9203 vty_out(vty, ", internal");
9df8b37c 9204 }
05864da7
DS
9205 } else {
9206 if (bgp_confederation_peers_check(bgp,
9207 path->peer->as)) {
9208 if (json_paths)
9209 json_object_string_add(
9210 json_peer, "type",
9211 "confed-external");
d62a17ae 9212 else
05864da7 9213 vty_out(vty, ", confed-external");
d62a17ae 9214 } else {
05864da7
DS
9215 if (json_paths)
9216 json_object_string_add(
9217 json_peer, "type", "external");
9218 else
9219 vty_out(vty, ", external");
d62a17ae 9220 }
9221 }
05864da7
DS
9222 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
9223 if (json_paths) {
9224 json_object_boolean_true_add(json_path, "aggregated");
9225 json_object_boolean_true_add(json_path, "local");
9226 } else {
9227 vty_out(vty, ", aggregated, local");
9228 }
9229 } else if (path->type != ZEBRA_ROUTE_BGP) {
9230 if (json_paths)
9231 json_object_boolean_true_add(json_path, "sourced");
9232 else
9233 vty_out(vty, ", sourced");
9234 } else {
9235 if (json_paths) {
9236 json_object_boolean_true_add(json_path, "sourced");
9237 json_object_boolean_true_add(json_path, "local");
9238 } else {
9239 vty_out(vty, ", sourced, local");
d62a17ae 9240 }
05864da7 9241 }
718e3744 9242
05864da7 9243 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 9244 if (json_paths)
05864da7
DS
9245 json_object_boolean_true_add(json_path,
9246 "atomicAggregate");
d62a17ae 9247 else
05864da7
DS
9248 vty_out(vty, ", atomic-aggregate");
9249 }
d62a17ae 9250
05864da7
DS
9251 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
9252 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
9253 && bgp_path_info_mpath_count(path))) {
9254 if (json_paths)
9255 json_object_boolean_true_add(json_path, "multipath");
9256 else
9257 vty_out(vty, ", multipath");
9258 }
50e05855 9259
05864da7
DS
9260 // Mark the bestpath(s)
9261 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
9262 first_as = aspath_get_first_as(attr->aspath);
718e3744 9263
05864da7
DS
9264 if (json_paths) {
9265 if (!json_bestpath)
9266 json_bestpath = json_object_new_object();
9267 json_object_int_add(json_bestpath, "bestpathFromAs",
9268 first_as);
9269 } else {
9270 if (first_as)
9271 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 9272 else
05864da7 9273 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 9274 }
05864da7 9275 }
718e3744 9276
05864da7
DS
9277 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
9278 if (json_paths) {
9279 if (!json_bestpath)
9280 json_bestpath = json_object_new_object();
9281 json_object_boolean_true_add(json_bestpath, "overall");
9282 json_object_string_add(
9283 json_bestpath, "selectionReason",
9284 bgp_path_selection_reason2str(bn->reason));
9285 } else {
9286 vty_out(vty, ", best");
9287 vty_out(vty, " (%s)",
9288 bgp_path_selection_reason2str(bn->reason));
d62a17ae 9289 }
05864da7 9290 }
718e3744 9291
05864da7
DS
9292 if (json_bestpath)
9293 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 9294
05864da7
DS
9295 if (!json_paths)
9296 vty_out(vty, "\n");
9297
9298 /* Line 4 display Community */
9299 if (attr->community) {
9300 if (json_paths) {
9301 if (!attr->community->json)
9302 community_str(attr->community, true);
9303 json_object_lock(attr->community->json);
9304 json_object_object_add(json_path, "community",
9305 attr->community->json);
9306 } else {
9307 vty_out(vty, " Community: %s\n",
9308 attr->community->str);
d62a17ae 9309 }
05864da7 9310 }
718e3744 9311
05864da7
DS
9312 /* Line 5 display Extended-community */
9313 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9314 if (json_paths) {
9315 json_ext_community = json_object_new_object();
9316 json_object_string_add(json_ext_community, "string",
9317 attr->ecommunity->str);
9318 json_object_object_add(json_path, "extendedCommunity",
9319 json_ext_community);
d62a17ae 9320 } else {
05864da7
DS
9321 vty_out(vty, " Extended Community: %s\n",
9322 attr->ecommunity->str);
d62a17ae 9323 }
05864da7 9324 }
718e3744 9325
05864da7
DS
9326 /* Line 6 display Large community */
9327 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
9328 if (json_paths) {
9329 if (!attr->lcommunity->json)
9330 lcommunity_str(attr->lcommunity, true);
9331 json_object_lock(attr->lcommunity->json);
9332 json_object_object_add(json_path, "largeCommunity",
9333 attr->lcommunity->json);
9334 } else {
9335 vty_out(vty, " Large Community: %s\n",
9336 attr->lcommunity->str);
d62a17ae 9337 }
05864da7 9338 }
718e3744 9339
05864da7
DS
9340 /* Line 7 display Originator, Cluster-id */
9341 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
9342 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
9343 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 9344 if (json_paths)
05864da7
DS
9345 json_object_string_add(
9346 json_path, "originatorId",
9347 inet_ntoa(attr->originator_id));
d62a17ae 9348 else
05864da7
DS
9349 vty_out(vty, " Originator: %s",
9350 inet_ntoa(attr->originator_id));
d62a17ae 9351 }
856ca177 9352
05864da7
DS
9353 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
9354 int i;
d62a17ae 9355
9356 if (json_paths) {
05864da7
DS
9357 json_cluster_list = json_object_new_object();
9358 json_cluster_list_list =
9359 json_object_new_array();
9360
9361 for (i = 0; i < attr->cluster->length / 4;
9362 i++) {
9363 json_string = json_object_new_string(
9364 inet_ntoa(attr->cluster
9365 ->list[i]));
9366 json_object_array_add(
9367 json_cluster_list_list,
9368 json_string);
9369 }
718e3744 9370
05864da7
DS
9371 /*
9372 * struct cluster_list does not have
9373 * "str" variable like aspath and community
9374 * do. Add this someday if someone asks
9375 * for it.
9376 * json_object_string_add(json_cluster_list,
9377 * "string", attr->cluster->str);
9378 */
9379 json_object_object_add(json_cluster_list,
9380 "list",
9381 json_cluster_list_list);
9382 json_object_object_add(json_path, "clusterList",
9383 json_cluster_list);
0dc8ee70 9384 } else {
05864da7
DS
9385 vty_out(vty, ", Cluster list: ");
9386
9387 for (i = 0; i < attr->cluster->length / 4;
9388 i++) {
9389 vty_out(vty, "%s ",
9390 inet_ntoa(attr->cluster
9391 ->list[i]));
9392 }
0dc8ee70 9393 }
d62a17ae 9394 }
718e3744 9395
d62a17ae 9396 if (!json_paths)
9397 vty_out(vty, "\n");
05864da7 9398 }
d62a17ae 9399
05864da7 9400 if (path->extra && path->extra->damp_info)
a935f597 9401 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 9402
05864da7
DS
9403 /* Remote Label */
9404 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
9405 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
9406 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 9407
05864da7
DS
9408 if (json_paths)
9409 json_object_int_add(json_path, "remoteLabel", label);
9410 else
9411 vty_out(vty, " Remote label: %d\n", label);
9412 }
d62a17ae 9413
e496b420
HS
9414 /* Remote SID */
9415 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
9416 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
9417 if (json_paths)
9418 json_object_string_add(json_path, "remoteSid", buf);
9419 else
9420 vty_out(vty, " Remote SID: %s\n", buf);
9421 }
9422
05864da7
DS
9423 /* Label Index */
9424 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
9425 if (json_paths)
9426 json_object_int_add(json_path, "labelIndex",
9427 attr->label_index);
9428 else
9429 vty_out(vty, " Label Index: %d\n",
9430 attr->label_index);
9431 }
d62a17ae 9432
05864da7
DS
9433 /* Line 8 display Addpath IDs */
9434 if (path->addpath_rx_id
9435 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
9436 if (json_paths) {
9437 json_object_int_add(json_path, "addpathRxId",
9438 path->addpath_rx_id);
d62a17ae 9439
05864da7
DS
9440 /* Keep backwards compatibility with the old API
9441 * by putting TX All's ID in the old field
9442 */
9443 json_object_int_add(
9444 json_path, "addpathTxId",
9445 path->tx_addpath
9446 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 9447
05864da7
DS
9448 /* ... but create a specific field for each
9449 * strategy
9450 */
9451 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9452 json_object_int_add(
9453 json_path,
9454 bgp_addpath_names(i)->id_json_name,
9455 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 9456 }
05864da7
DS
9457 } else {
9458 vty_out(vty, " AddPath ID: RX %u, ",
9459 path->addpath_rx_id);
d62a17ae 9460
05864da7 9461 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 9462 }
05864da7 9463 }
520d5d76 9464
05864da7
DS
9465 /* If we used addpath to TX a non-bestpath we need to display
9466 * "Advertised to" on a path-by-path basis
9467 */
9468 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9469 first = 1;
dcc68b5e 9470
05864da7
DS
9471 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9472 addpath_capable =
9473 bgp_addpath_encode_tx(peer, afi, safi);
9474 has_adj = bgp_adj_out_lookup(
9475 peer, path->net,
9476 bgp_addpath_id_for_peer(peer, afi, safi,
9477 &path->tx_addpath));
9478
9479 if ((addpath_capable && has_adj)
9480 || (!addpath_capable && has_adj
9481 && CHECK_FLAG(path->flags,
9482 BGP_PATH_SELECTED))) {
9483 if (json_path && !json_adv_to)
9484 json_adv_to = json_object_new_object();
dcc68b5e 9485
05864da7
DS
9486 route_vty_out_advertised_to(
9487 vty, peer, &first,
9488 " Advertised to:", json_adv_to);
d62a17ae 9489 }
9490 }
718e3744 9491
05864da7
DS
9492 if (json_path) {
9493 if (json_adv_to) {
9494 json_object_object_add(
9495 json_path, "advertisedTo", json_adv_to);
d62a17ae 9496 }
05864da7
DS
9497 } else {
9498 if (!first) {
9499 vty_out(vty, "\n");
d62a17ae 9500 }
9501 }
05864da7 9502 }
b05a1c8b 9503
05864da7
DS
9504 /* Line 9 display Uptime */
9505 tbuf = time(NULL) - (bgp_clock() - path->uptime);
9506 if (json_paths) {
9507 json_last_update = json_object_new_object();
9508 json_object_int_add(json_last_update, "epoch", tbuf);
9509 json_object_string_add(json_last_update, "string",
9510 ctime(&tbuf));
9511 json_object_object_add(json_path, "lastUpdate",
9512 json_last_update);
9513 } else
9514 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 9515
05864da7
DS
9516 /* Line 10 display PMSI tunnel attribute, if present */
9517 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
9518 const char *str =
9519 lookup_msg(bgp_pmsi_tnltype_str, attr->pmsi_tnl_type,
9520 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 9521
05864da7
DS
9522 if (json_paths) {
9523 json_pmsi = json_object_new_object();
9524 json_object_string_add(json_pmsi, "tunnelType", str);
9525 json_object_int_add(json_pmsi, "label",
9526 label2vni(&attr->label));
9527 json_object_object_add(json_path, "pmsi", json_pmsi);
9528 } else
9529 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
9530 str, label2vni(&attr->label));
d62a17ae 9531 }
f1aa5d8a 9532
d62a17ae 9533 /* We've constructed the json object for this path, add it to the json
9534 * array of paths
9535 */
9536 if (json_paths) {
9537 if (json_nexthop_global || json_nexthop_ll) {
9538 json_nexthops = json_object_new_array();
f1aa5d8a 9539
d62a17ae 9540 if (json_nexthop_global)
9541 json_object_array_add(json_nexthops,
9542 json_nexthop_global);
f1aa5d8a 9543
d62a17ae 9544 if (json_nexthop_ll)
9545 json_object_array_add(json_nexthops,
9546 json_nexthop_ll);
f1aa5d8a 9547
d62a17ae 9548 json_object_object_add(json_path, "nexthops",
9549 json_nexthops);
9550 }
9551
9552 json_object_object_add(json_path, "peer", json_peer);
9553 json_object_array_add(json_paths, json_path);
05864da7 9554 }
b366b518
BB
9555}
9556
96ade3ed 9557#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
9558#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9559#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 9560
d62a17ae 9561static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
9562 const char *prefix_list_str, afi_t afi,
9563 safi_t safi, enum bgp_show_type type);
9564static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
9565 const char *filter, afi_t afi, safi_t safi,
9566 enum bgp_show_type type);
9567static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
9568 const char *rmap_str, afi_t afi, safi_t safi,
9569 enum bgp_show_type type);
9570static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
9571 const char *com, int exact, afi_t afi,
9572 safi_t safi);
9573static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
9574 const char *prefix, afi_t afi, safi_t safi,
9575 enum bgp_show_type type);
a4d82a8a 9576static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
9577 afi_t afi, safi_t safi, enum bgp_show_type type,
9578 bool use_json);
7f323236
DW
9579static int bgp_show_community(struct vty *vty, struct bgp *bgp,
9580 const char *comstr, int exact, afi_t afi,
9f049418 9581 safi_t safi, bool use_json);
d62a17ae 9582
1ae44dfc
LB
9583
9584static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 9585 struct bgp_table *table, enum bgp_show_type type,
9f049418 9586 void *output_arg, bool use_json, char *rd,
a4d82a8a
PZ
9587 int is_last, unsigned long *output_cum,
9588 unsigned long *total_cum,
9386b588 9589 unsigned long *json_header_depth)
d62a17ae 9590{
40381db7 9591 struct bgp_path_info *pi;
9bcb3eef 9592 struct bgp_dest *dest;
d62a17ae 9593 int header = 1;
9594 int display;
1ae44dfc
LB
9595 unsigned long output_count = 0;
9596 unsigned long total_count = 0;
d62a17ae 9597 struct prefix *p;
d62a17ae 9598 char buf2[BUFSIZ];
9599 json_object *json_paths = NULL;
9600 int first = 1;
9601
1ae44dfc
LB
9602 if (output_cum && *output_cum != 0)
9603 header = 0;
9604
9386b588 9605 if (use_json && !*json_header_depth) {
d62a17ae 9606 vty_out(vty,
66f80d74 9607 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
01eced22
AD
9608 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9609 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 9610 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b
DS
9611 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
9612 ? VRF_DEFAULT_NAME
9613 : bgp->name,
01eced22
AD
9614 table->version, inet_ntoa(bgp->router_id),
9615 bgp->default_local_pref, bgp->as);
9386b588
PZ
9616 *json_header_depth = 2;
9617 if (rd) {
445c2480 9618 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
9619 ++*json_header_depth;
9620 }
d62a17ae 9621 }
718e3744 9622
445c2480
DS
9623 if (use_json && rd) {
9624 vty_out(vty, " \"%s\" : { ", rd);
9625 }
9626
d62a17ae 9627 /* Start processing of routes. */
9bcb3eef
DS
9628 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
9629 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 9630
9bcb3eef 9631 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 9632 if (pi == NULL)
98ce9a06 9633 continue;
d62a17ae 9634
98ce9a06 9635 display = 0;
98ce9a06
DS
9636 if (use_json)
9637 json_paths = json_object_new_array();
9638 else
9639 json_paths = NULL;
d62a17ae 9640
6f94b685 9641 for (; pi; pi = pi->next) {
98ce9a06
DS
9642 total_count++;
9643 if (type == bgp_show_type_flap_statistics
9644 || type == bgp_show_type_flap_neighbor
9645 || type == bgp_show_type_dampend_paths
9646 || type == bgp_show_type_damp_neighbor) {
40381db7 9647 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
9648 continue;
9649 }
9650 if (type == bgp_show_type_regexp) {
9651 regex_t *regex = output_arg;
d62a17ae 9652
40381db7 9653 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
9654 == REG_NOMATCH)
9655 continue;
9656 }
9657 if (type == bgp_show_type_prefix_list) {
9658 struct prefix_list *plist = output_arg;
d62a17ae 9659
9bcb3eef 9660 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
9661 != PREFIX_PERMIT)
9662 continue;
9663 }
9664 if (type == bgp_show_type_filter_list) {
9665 struct as_list *as_list = output_arg;
d62a17ae 9666
40381db7 9667 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
9668 != AS_FILTER_PERMIT)
9669 continue;
9670 }
9671 if (type == bgp_show_type_route_map) {
9672 struct route_map *rmap = output_arg;
9b6d8fcf 9673 struct bgp_path_info path;
98ce9a06 9674 struct attr dummy_attr;
b68885f9 9675 route_map_result_t ret;
d62a17ae 9676
6f4f49b2 9677 dummy_attr = *pi->attr;
d62a17ae 9678
40381db7 9679 path.peer = pi->peer;
9b6d8fcf 9680 path.attr = &dummy_attr;
d62a17ae 9681
9bcb3eef 9682 ret = route_map_apply(rmap, dest_p, RMAP_BGP,
9b6d8fcf 9683 &path);
98ce9a06
DS
9684 if (ret == RMAP_DENYMATCH)
9685 continue;
9686 }
9687 if (type == bgp_show_type_neighbor
9688 || type == bgp_show_type_flap_neighbor
9689 || type == bgp_show_type_damp_neighbor) {
9690 union sockunion *su = output_arg;
9691
40381db7
DS
9692 if (pi->peer == NULL
9693 || pi->peer->su_remote == NULL
9694 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
9695 continue;
9696 }
9697 if (type == bgp_show_type_cidr_only) {
d7c0a89a 9698 uint32_t destination;
d62a17ae 9699
9bcb3eef 9700 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 9701 if (IN_CLASSC(destination)
9bcb3eef 9702 && dest_p->prefixlen == 24)
98ce9a06
DS
9703 continue;
9704 if (IN_CLASSB(destination)
9bcb3eef 9705 && dest_p->prefixlen == 16)
98ce9a06
DS
9706 continue;
9707 if (IN_CLASSA(destination)
9bcb3eef 9708 && dest_p->prefixlen == 8)
98ce9a06
DS
9709 continue;
9710 }
9711 if (type == bgp_show_type_prefix_longer) {
f7813c7c 9712 p = output_arg;
9bcb3eef 9713 if (!prefix_match(p, dest_p))
98ce9a06
DS
9714 continue;
9715 }
9716 if (type == bgp_show_type_community_all) {
40381db7 9717 if (!pi->attr->community)
98ce9a06
DS
9718 continue;
9719 }
9720 if (type == bgp_show_type_community) {
9721 struct community *com = output_arg;
d62a17ae 9722
40381db7
DS
9723 if (!pi->attr->community
9724 || !community_match(pi->attr->community,
98ce9a06
DS
9725 com))
9726 continue;
9727 }
9728 if (type == bgp_show_type_community_exact) {
9729 struct community *com = output_arg;
d62a17ae 9730
40381db7
DS
9731 if (!pi->attr->community
9732 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
9733 continue;
9734 }
9735 if (type == bgp_show_type_community_list) {
9736 struct community_list *list = output_arg;
d62a17ae 9737
40381db7 9738 if (!community_list_match(pi->attr->community,
a4d82a8a 9739 list))
98ce9a06
DS
9740 continue;
9741 }
a4d82a8a 9742 if (type == bgp_show_type_community_list_exact) {
98ce9a06 9743 struct community_list *list = output_arg;
d62a17ae 9744
98ce9a06 9745 if (!community_list_exact_match(
40381db7 9746 pi->attr->community, list))
98ce9a06
DS
9747 continue;
9748 }
9749 if (type == bgp_show_type_lcommunity) {
9750 struct lcommunity *lcom = output_arg;
d62a17ae 9751
40381db7
DS
9752 if (!pi->attr->lcommunity
9753 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
9754 lcom))
9755 continue;
9756 }
36a206db 9757
9758 if (type == bgp_show_type_lcommunity_exact) {
9759 struct lcommunity *lcom = output_arg;
9760
9761 if (!pi->attr->lcommunity
9762 || !lcommunity_cmp(pi->attr->lcommunity,
9763 lcom))
9764 continue;
9765 }
98ce9a06
DS
9766 if (type == bgp_show_type_lcommunity_list) {
9767 struct community_list *list = output_arg;
d62a17ae 9768
40381db7 9769 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 9770 list))
98ce9a06
DS
9771 continue;
9772 }
36a206db 9773 if (type
9774 == bgp_show_type_lcommunity_list_exact) {
9775 struct community_list *list = output_arg;
9776
9777 if (!lcommunity_list_exact_match(
9778 pi->attr->lcommunity, list))
9779 continue;
9780 }
98ce9a06 9781 if (type == bgp_show_type_lcommunity_all) {
40381db7 9782 if (!pi->attr->lcommunity)
98ce9a06
DS
9783 continue;
9784 }
9785 if (type == bgp_show_type_dampend_paths
9786 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
9787 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
9788 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
9789 continue;
9790 }
9791
9792 if (!use_json && header) {
996c9314 9793 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 9794 ", local router ID is %s, vrf id ",
98ce9a06
DS
9795 table->version,
9796 inet_ntoa(bgp->router_id));
9df8b37c
PZ
9797 if (bgp->vrf_id == VRF_UNKNOWN)
9798 vty_out(vty, "%s", VRFID_NONE_STR);
9799 else
9800 vty_out(vty, "%u", bgp->vrf_id);
9801 vty_out(vty, "\n");
01eced22
AD
9802 vty_out(vty, "Default local pref %u, ",
9803 bgp->default_local_pref);
9804 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 9805 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 9806 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 9807 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 9808 if (type == bgp_show_type_dampend_paths
9809 || type == bgp_show_type_damp_neighbor)
98ce9a06 9810 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
9811 else if (type == bgp_show_type_flap_statistics
9812 || type == bgp_show_type_flap_neighbor)
98ce9a06 9813 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 9814 else
98ce9a06
DS
9815 vty_out(vty, BGP_SHOW_HEADER);
9816 header = 0;
d62a17ae 9817 }
98ce9a06
DS
9818 if (rd != NULL && !display && !output_count) {
9819 if (!use_json)
9820 vty_out(vty,
9821 "Route Distinguisher: %s\n",
9822 rd);
d62a17ae 9823 }
98ce9a06
DS
9824 if (type == bgp_show_type_dampend_paths
9825 || type == bgp_show_type_damp_neighbor)
9bcb3eef 9826 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
9827 AFI_IP, safi, use_json,
9828 json_paths);
98ce9a06
DS
9829 else if (type == bgp_show_type_flap_statistics
9830 || type == bgp_show_type_flap_neighbor)
9bcb3eef 9831 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
9832 AFI_IP, safi, use_json,
9833 json_paths);
98ce9a06 9834 else
9bcb3eef 9835 route_vty_out(vty, dest_p, pi, display, safi,
a4d82a8a 9836 json_paths);
98ce9a06 9837 display++;
d62a17ae 9838 }
9839
98ce9a06
DS
9840 if (display) {
9841 output_count++;
9842 if (!use_json)
9843 continue;
9844
625d2931 9845 /* encode prefix */
9bcb3eef 9846 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
9847 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
9848
b54892e0
DS
9849 bgp_fs_nlri_get_string(
9850 (unsigned char *)
9bcb3eef
DS
9851 dest_p->u.prefix_flowspec.ptr,
9852 dest_p->u.prefix_flowspec.prefixlen,
b54892e0 9853 retstr, NLRI_STRING_FORMAT_MIN, NULL);
625d2931 9854 if (first)
b54892e0 9855 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 9856 dest_p->u.prefix_flowspec
b54892e0 9857 .prefixlen);
625d2931 9858 else
b54892e0 9859 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 9860 dest_p->u.prefix_flowspec
b54892e0 9861 .prefixlen);
625d2931 9862 } else {
9bcb3eef 9863 prefix2str(dest_p, buf2, sizeof(buf2));
625d2931
PG
9864 if (first)
9865 vty_out(vty, "\"%s\": ", buf2);
9866 else
9867 vty_out(vty, ",\"%s\": ", buf2);
9868 }
98ce9a06 9869 vty_out(vty, "%s",
f4ec52f7
DA
9870 json_object_to_json_string_ext(
9871 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 9872 json_object_free(json_paths);
449feb8e 9873 json_paths = NULL;
98ce9a06 9874 first = 0;
1f83ed02
DS
9875 } else
9876 json_object_free(json_paths);
98ce9a06
DS
9877 }
9878
1ae44dfc
LB
9879 if (output_cum) {
9880 output_count += *output_cum;
9881 *output_cum = output_count;
9882 }
9883 if (total_cum) {
9884 total_count += *total_cum;
9885 *total_cum = total_count;
9886 }
d62a17ae 9887 if (use_json) {
9386b588 9888 if (rd) {
a4d82a8a 9889 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
9890 }
9891 if (is_last) {
a4d82a8a
PZ
9892 unsigned long i;
9893 for (i = 0; i < *json_header_depth; ++i)
9894 vty_out(vty, " } ");
faf6559a 9895 vty_out(vty, "\n");
9386b588 9896 }
d62a17ae 9897 } else {
1ae44dfc
LB
9898 if (is_last) {
9899 /* No route is displayed */
9900 if (output_count == 0) {
9901 if (type == bgp_show_type_normal)
9902 vty_out(vty,
9903 "No BGP prefixes displayed, %ld exist\n",
9904 total_count);
9905 } else
d62a17ae 9906 vty_out(vty,
1ae44dfc
LB
9907 "\nDisplayed %ld routes and %ld total paths\n",
9908 output_count, total_count);
9909 }
d62a17ae 9910 }
718e3744 9911
d62a17ae 9912 return CMD_SUCCESS;
718e3744 9913}
9914
1ae44dfc
LB
9915int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
9916 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 9917 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 9918{
9bcb3eef 9919 struct bgp_dest *dest, *next;
1ae44dfc
LB
9920 unsigned long output_cum = 0;
9921 unsigned long total_cum = 0;
9386b588 9922 unsigned long json_header_depth = 0;
67009e22 9923 struct bgp_table *itable;
0136788c
LB
9924 bool show_msg;
9925
9926 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 9927
9bcb3eef
DS
9928 for (dest = bgp_table_top(table); dest; dest = next) {
9929 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 9930
9bcb3eef
DS
9931 next = bgp_route_next(dest);
9932 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 9933 continue;
67009e22 9934
9bcb3eef 9935 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 9936 if (itable != NULL) {
1ae44dfc 9937 struct prefix_rd prd;
06b9f471 9938 char rd[RD_ADDRSTRLEN];
1ae44dfc 9939
9bcb3eef 9940 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 9941 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22
DS
9942 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
9943 use_json, rd, next == NULL, &output_cum,
9944 &total_cum, &json_header_depth);
0136788c
LB
9945 if (next == NULL)
9946 show_msg = false;
1ae44dfc
LB
9947 }
9948 }
0136788c
LB
9949 if (show_msg) {
9950 if (output_cum == 0)
9951 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
9952 total_cum);
9953 else
9954 vty_out(vty,
9955 "\nDisplayed %ld routes and %ld total paths\n",
9956 output_cum, total_cum);
9957 }
1ae44dfc
LB
9958 return CMD_SUCCESS;
9959}
d62a17ae 9960static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
9f049418 9961 enum bgp_show_type type, void *output_arg, bool use_json)
fee0f4c6 9962{
d62a17ae 9963 struct bgp_table *table;
9386b588 9964 unsigned long json_header_depth = 0;
fee0f4c6 9965
d62a17ae 9966 if (bgp == NULL) {
9967 bgp = bgp_get_default();
9968 }
fee0f4c6 9969
d62a17ae 9970 if (bgp == NULL) {
9971 if (!use_json)
9972 vty_out(vty, "No BGP process is configured\n");
16307668
RW
9973 else
9974 vty_out(vty, "{}\n");
d62a17ae 9975 return CMD_WARNING;
9976 }
4dd6177e 9977
1ae44dfc 9978 table = bgp->rib[afi][safi];
d62a17ae 9979 /* use MPLS and ENCAP specific shows until they are merged */
9980 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
9981 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
9982 output_arg, use_json);
d62a17ae 9983 }
dba3c1d3
PG
9984
9985 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
9986 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
9987 output_arg, use_json,
9988 1, NULL, NULL);
9989 }
d62a17ae 9990 /* labeled-unicast routes live in the unicast table */
9991 else if (safi == SAFI_LABELED_UNICAST)
9992 safi = SAFI_UNICAST;
fee0f4c6 9993
1ae44dfc 9994 return bgp_show_table(vty, bgp, safi, table, type, output_arg, use_json,
9386b588 9995 NULL, 1, NULL, NULL, &json_header_depth);
fee0f4c6 9996}
9997
d62a17ae 9998static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
9f049418 9999 safi_t safi, bool use_json)
f186de26 10000{
d62a17ae 10001 struct listnode *node, *nnode;
10002 struct bgp *bgp;
10003 int is_first = 1;
9f049418 10004 bool route_output = false;
f186de26 10005
d62a17ae 10006 if (use_json)
10007 vty_out(vty, "{\n");
9f689658 10008
d62a17ae 10009 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 10010 route_output = true;
d62a17ae 10011 if (use_json) {
10012 if (!is_first)
10013 vty_out(vty, ",\n");
10014 else
10015 is_first = 0;
10016
10017 vty_out(vty, "\"%s\":",
10018 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10019 ? VRF_DEFAULT_NAME
d62a17ae 10020 : bgp->name);
10021 } else {
10022 vty_out(vty, "\nInstance %s:\n",
10023 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10024 ? VRF_DEFAULT_NAME
d62a17ae 10025 : bgp->name);
10026 }
10027 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
10028 use_json);
10029 }
9f689658 10030
d62a17ae 10031 if (use_json)
10032 vty_out(vty, "}\n");
9f049418
DS
10033 else if (!route_output)
10034 vty_out(vty, "%% BGP instance not found\n");
f186de26 10035}
10036
718e3744 10037/* Header of detailed BGP route information */
d62a17ae 10038void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9bcb3eef 10039 struct bgp_dest *dest, struct prefix_rd *prd,
d62a17ae 10040 afi_t afi, safi_t safi, json_object *json)
10041{
40381db7 10042 struct bgp_path_info *pi;
b54892e0 10043 const struct prefix *p;
d62a17ae 10044 struct peer *peer;
10045 struct listnode *node, *nnode;
06b9f471 10046 char buf1[RD_ADDRSTRLEN];
d62a17ae 10047 char buf2[INET6_ADDRSTRLEN];
d62a17ae 10048 char buf3[EVPN_ROUTE_STRLEN];
0291c246 10049 char prefix_str[BUFSIZ];
d62a17ae 10050 int count = 0;
10051 int best = 0;
10052 int suppress = 0;
c5f1e1b2
C
10053 int accept_own = 0;
10054 int route_filter_translated_v4 = 0;
10055 int route_filter_v4 = 0;
10056 int route_filter_translated_v6 = 0;
10057 int route_filter_v6 = 0;
10058 int llgr_stale = 0;
10059 int no_llgr = 0;
10060 int accept_own_nexthop = 0;
10061 int blackhole = 0;
d62a17ae 10062 int no_export = 0;
10063 int no_advertise = 0;
10064 int local_as = 0;
c5f1e1b2 10065 int no_peer = 0;
d62a17ae 10066 int first = 1;
10067 int has_valid_label = 0;
10068 mpls_label_t label = 0;
10069 json_object *json_adv_to = NULL;
9bedbb1e 10070
9bcb3eef
DS
10071 p = bgp_dest_get_prefix(dest);
10072 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 10073
10074 if (has_valid_label)
9bcb3eef 10075 label = label_pton(&dest->local_label);
d62a17ae 10076
44c69747 10077 if (safi == SAFI_EVPN) {
d62a17ae 10078
44c69747 10079 if (!json) {
d62a17ae 10080 vty_out(vty, "BGP routing table entry for %s%s%s\n",
06b9f471 10081 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
44c69747 10082 : "", prd ? ":" : "",
d62a17ae 10083 bgp_evpn_route2str((struct prefix_evpn *)p,
44c69747
LK
10084 buf3, sizeof(buf3)));
10085 } else {
10086 json_object_string_add(json, "rd",
10087 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
10088 "");
10089 bgp_evpn_route2json((struct prefix_evpn *)p, json);
10090 }
10091 } else {
10092 if (!json) {
d62a17ae 10093 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
10094 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
44c69747
LK
10095 ? prefix_rd2str(prd, buf1,
10096 sizeof(buf1))
10097 : ""),
d62a17ae 10098 safi == SAFI_MPLS_VPN ? ":" : "",
10099 inet_ntop(p->family, &p->u.prefix, buf2,
44c69747 10100 INET6_ADDRSTRLEN),
d62a17ae 10101 p->prefixlen);
cd1964ff 10102
44c69747
LK
10103 } else
10104 json_object_string_add(json, "prefix",
10105 prefix2str(p, prefix_str, sizeof(prefix_str)));
10106 }
10107
10108 if (has_valid_label) {
10109 if (json)
10110 json_object_int_add(json, "localLabel", label);
10111 else
d62a17ae 10112 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
10113 }
10114
10115 if (!json)
d62a17ae 10116 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 10117 vty_out(vty, "not allocated\n");
718e3744 10118
9bcb3eef 10119 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 10120 count++;
40381db7 10121 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 10122 best = count;
40381db7 10123 if (pi->extra && pi->extra->suppress)
d62a17ae 10124 suppress = 1;
cee9c031 10125
40381db7 10126 if (pi->attr->community == NULL)
cee9c031
QY
10127 continue;
10128
10129 no_advertise += community_include(
40381db7
DS
10130 pi->attr->community, COMMUNITY_NO_ADVERTISE);
10131 no_export += community_include(pi->attr->community,
cee9c031 10132 COMMUNITY_NO_EXPORT);
40381db7 10133 local_as += community_include(pi->attr->community,
cee9c031 10134 COMMUNITY_LOCAL_AS);
40381db7 10135 accept_own += community_include(pi->attr->community,
cee9c031
QY
10136 COMMUNITY_ACCEPT_OWN);
10137 route_filter_translated_v4 += community_include(
40381db7 10138 pi->attr->community,
cee9c031
QY
10139 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
10140 route_filter_translated_v6 += community_include(
40381db7 10141 pi->attr->community,
cee9c031
QY
10142 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
10143 route_filter_v4 += community_include(
40381db7 10144 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 10145 route_filter_v6 += community_include(
40381db7
DS
10146 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
10147 llgr_stale += community_include(pi->attr->community,
cee9c031 10148 COMMUNITY_LLGR_STALE);
40381db7 10149 no_llgr += community_include(pi->attr->community,
cee9c031
QY
10150 COMMUNITY_NO_LLGR);
10151 accept_own_nexthop +=
40381db7 10152 community_include(pi->attr->community,
cee9c031 10153 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 10154 blackhole += community_include(pi->attr->community,
cee9c031 10155 COMMUNITY_BLACKHOLE);
40381db7 10156 no_peer += community_include(pi->attr->community,
cee9c031 10157 COMMUNITY_NO_PEER);
d62a17ae 10158 }
718e3744 10159 }
718e3744 10160
d62a17ae 10161 if (!json) {
10162 vty_out(vty, "Paths: (%d available", count);
10163 if (best) {
10164 vty_out(vty, ", best #%d", best);
b84060bb
PG
10165 if (safi == SAFI_UNICAST) {
10166 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
10167 vty_out(vty, ", table %s",
10168 VRF_DEFAULT_NAME);
10169 else
10170 vty_out(vty, ", vrf %s",
10171 bgp->name);
10172 }
d62a17ae 10173 } else
10174 vty_out(vty, ", no best path");
10175
c5f1e1b2
C
10176 if (accept_own)
10177 vty_out(vty,
10178 ", accept own local route exported and imported in different VRF");
10179 else if (route_filter_translated_v4)
10180 vty_out(vty,
10181 ", mark translated RTs for VPNv4 route filtering");
10182 else if (route_filter_v4)
10183 vty_out(vty,
10184 ", attach RT as-is for VPNv4 route filtering");
10185 else if (route_filter_translated_v6)
10186 vty_out(vty,
10187 ", mark translated RTs for VPNv6 route filtering");
10188 else if (route_filter_v6)
10189 vty_out(vty,
10190 ", attach RT as-is for VPNv6 route filtering");
10191 else if (llgr_stale)
10192 vty_out(vty,
10193 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
10194 else if (no_llgr)
10195 vty_out(vty,
10196 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
10197 else if (accept_own_nexthop)
10198 vty_out(vty,
10199 ", accept local nexthop");
10200 else if (blackhole)
10201 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 10202 else if (no_export)
10203 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
10204 else if (no_advertise)
10205 vty_out(vty, ", not advertised to any peer");
d62a17ae 10206 else if (local_as)
10207 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
10208 else if (no_peer)
10209 vty_out(vty,
10210 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 10211
10212 if (suppress)
10213 vty_out(vty,
10214 ", Advertisements suppressed by an aggregate.");
10215 vty_out(vty, ")\n");
10216 }
718e3744 10217
d62a17ae 10218 /* If we are not using addpath then we can display Advertised to and
10219 * that will
10220 * show what peers we advertised the bestpath to. If we are using
10221 * addpath
10222 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 10223 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 10224 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 10225 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 10226 if (json && !json_adv_to)
10227 json_adv_to = json_object_new_object();
10228
10229 route_vty_out_advertised_to(
10230 vty, peer, &first,
10231 " Advertised to non peer-group peers:\n ",
10232 json_adv_to);
10233 }
10234 }
10235
10236 if (json) {
10237 if (json_adv_to) {
10238 json_object_object_add(json, "advertisedTo",
10239 json_adv_to);
10240 }
10241 } else {
10242 if (first)
10243 vty_out(vty, " Not advertised to any peer");
10244 vty_out(vty, "\n");
10245 }
10246 }
718e3744 10247}
10248
44c69747 10249static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9bcb3eef
DS
10250 struct bgp_dest *bgp_node, struct vty *vty,
10251 struct bgp *bgp, afi_t afi, safi_t safi,
10252 json_object *json, enum bgp_path_type pathtype,
10253 int *display)
44c69747
LK
10254{
10255 struct bgp_path_info *pi;
10256 int header = 1;
10257 char rdbuf[RD_ADDRSTRLEN];
10258 json_object *json_header = NULL;
10259 json_object *json_paths = NULL;
10260
9bcb3eef 10261 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
44c69747
LK
10262
10263 if (json && !json_paths) {
10264 /* Instantiate json_paths only if path is valid */
10265 json_paths = json_object_new_array();
10266 if (pfx_rd) {
10267 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
10268 json_header = json_object_new_object();
10269 } else
10270 json_header = json;
10271 }
10272
10273 if (header) {
10274 route_vty_out_detail_header(
10275 vty, bgp, bgp_node, pfx_rd,
10276 AFI_IP, safi, json_header);
10277 header = 0;
10278 }
10279 (*display)++;
10280
10281 if (pathtype == BGP_PATH_SHOW_ALL
10282 || (pathtype == BGP_PATH_SHOW_BESTPATH
10283 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
10284 || (pathtype == BGP_PATH_SHOW_MULTIPATH
10285 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
10286 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
10287 route_vty_out_detail(vty, bgp, bgp_node,
10288 pi, AFI_IP, safi,
10289 json_paths);
10290 }
10291
10292 if (json && json_paths) {
10293 json_object_object_add(json_header, "paths", json_paths);
10294
10295 if (pfx_rd)
10296 json_object_object_add(json, rdbuf, json_header);
10297 }
10298}
10299
718e3744 10300/* Display specified route of BGP table. */
d62a17ae 10301static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
10302 struct bgp_table *rib, const char *ip_str,
10303 afi_t afi, safi_t safi,
10304 struct prefix_rd *prd, int prefix_check,
9f049418 10305 enum bgp_path_type pathtype, bool use_json)
d62a17ae 10306{
10307 int ret;
d62a17ae 10308 int display = 0;
10309 struct prefix match;
9bcb3eef
DS
10310 struct bgp_dest *dest;
10311 struct bgp_dest *rm;
d62a17ae 10312 struct bgp_table *table;
10313 json_object *json = NULL;
10314 json_object *json_paths = NULL;
10315
10316 /* Check IP address argument. */
10317 ret = str2prefix(ip_str, &match);
10318 if (!ret) {
10319 vty_out(vty, "address is malformed\n");
10320 return CMD_WARNING;
10321 }
718e3744 10322
d62a17ae 10323 match.family = afi2family(afi);
b05a1c8b 10324
44c69747 10325 if (use_json)
d62a17ae 10326 json = json_object_new_object();
718e3744 10327
44c69747 10328 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
10329 for (dest = bgp_table_top(rib); dest;
10330 dest = bgp_route_next(dest)) {
10331 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10332
9bcb3eef 10333 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 10334 continue;
9bcb3eef 10335 table = bgp_dest_get_bgp_table_info(dest);
67009e22 10336 if (!table)
ea47320b 10337 continue;
d62a17ae 10338
ea47320b
DL
10339 if ((rm = bgp_node_match(table, &match)) == NULL)
10340 continue;
d62a17ae 10341
9bcb3eef 10342 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 10343 if (prefix_check
b54892e0 10344 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 10345 bgp_dest_unlock_node(rm);
ea47320b
DL
10346 continue;
10347 }
d62a17ae 10348
9bcb3eef 10349 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
10350 bgp, afi, safi, json, pathtype,
10351 &display);
44c69747 10352
9bcb3eef 10353 bgp_dest_unlock_node(rm);
44c69747
LK
10354 }
10355 } else if (safi == SAFI_EVPN) {
9bcb3eef 10356 struct bgp_dest *longest_pfx;
cded3b72 10357 bool is_exact_pfxlen_match = false;
44c69747 10358
9bcb3eef
DS
10359 for (dest = bgp_table_top(rib); dest;
10360 dest = bgp_route_next(dest)) {
10361 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10362
9bcb3eef 10363 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 10364 continue;
9bcb3eef 10365 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
10366 if (!table)
10367 continue;
10368
10369 longest_pfx = NULL;
cded3b72 10370 is_exact_pfxlen_match = false;
44c69747
LK
10371 /*
10372 * Search through all the prefixes for a match. The
10373 * pfx's are enumerated in ascending order of pfxlens.
10374 * So, the last pfx match is the longest match. Set
10375 * is_exact_pfxlen_match when we get exact pfxlen match
10376 */
10377 for (rm = bgp_table_top(table); rm;
10378 rm = bgp_route_next(rm)) {
b54892e0 10379 const struct prefix *rm_p =
9bcb3eef 10380 bgp_dest_get_prefix(rm);
44c69747
LK
10381 /*
10382 * Get prefixlen of the ip-prefix within type5
10383 * evpn route
10384 */
b54892e0
DS
10385 if (evpn_type5_prefix_match(rm_p, &match)
10386 && rm->info) {
44c69747
LK
10387 longest_pfx = rm;
10388 int type5_pfxlen =
b54892e0
DS
10389 bgp_evpn_get_type5_prefixlen(
10390 rm_p);
44c69747 10391 if (type5_pfxlen == match.prefixlen) {
cded3b72 10392 is_exact_pfxlen_match = true;
9bcb3eef 10393 bgp_dest_unlock_node(rm);
44c69747
LK
10394 break;
10395 }
d62a17ae 10396 }
10397 }
ea47320b 10398
44c69747
LK
10399 if (!longest_pfx)
10400 continue;
10401
10402 if (prefix_check && !is_exact_pfxlen_match)
10403 continue;
10404
10405 rm = longest_pfx;
9bcb3eef 10406 bgp_dest_lock_node(rm);
44c69747 10407
9bcb3eef 10408 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
10409 bgp, afi, safi, json, pathtype,
10410 &display);
44c69747 10411
9bcb3eef 10412 bgp_dest_unlock_node(rm);
d62a17ae 10413 }
98a9dbc7 10414 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
10415 if (use_json)
10416 json_paths = json_object_new_array();
10417
63a0b7a9
PG
10418 display = bgp_flowspec_display_match_per_ip(afi, rib,
10419 &match, prefix_check,
10420 vty,
10421 use_json,
10422 json_paths);
44c69747
LK
10423 if (use_json && display)
10424 json_object_object_add(json, "paths", json_paths);
d62a17ae 10425 } else {
9bcb3eef
DS
10426 if ((dest = bgp_node_match(rib, &match)) != NULL) {
10427 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 10428 if (!prefix_check
9bcb3eef
DS
10429 || dest_p->prefixlen == match.prefixlen) {
10430 bgp_show_path_info(NULL, dest, vty, bgp, afi,
10431 safi, json, pathtype,
10432 &display);
d62a17ae 10433 }
10434
9bcb3eef 10435 bgp_dest_unlock_node(dest);
d62a17ae 10436 }
10437 }
e5eee9af 10438
d62a17ae 10439 if (use_json) {
996c9314 10440 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
10441 json, JSON_C_TO_STRING_PRETTY |
10442 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 10443 json_object_free(json);
10444 } else {
10445 if (!display) {
10446 vty_out(vty, "%% Network not in table\n");
10447 return CMD_WARNING;
10448 }
10449 }
b05a1c8b 10450
d62a17ae 10451 return CMD_SUCCESS;
718e3744 10452}
10453
fee0f4c6 10454/* Display specified route of Main RIB */
d62a17ae 10455static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
10456 afi_t afi, safi_t safi, struct prefix_rd *prd,
10457 int prefix_check, enum bgp_path_type pathtype,
9f049418 10458 bool use_json)
d62a17ae 10459{
9b86009a 10460 if (!bgp) {
d62a17ae 10461 bgp = bgp_get_default();
9b86009a
RW
10462 if (!bgp) {
10463 if (!use_json)
10464 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10465 else
10466 vty_out(vty, "{}\n");
9b86009a
RW
10467 return CMD_WARNING;
10468 }
10469 }
d62a17ae 10470
10471 /* labeled-unicast routes live in the unicast table */
10472 if (safi == SAFI_LABELED_UNICAST)
10473 safi = SAFI_UNICAST;
10474
10475 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
10476 afi, safi, prd, prefix_check, pathtype,
10477 use_json);
10478}
10479
10480static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 10481 struct cmd_token **argv, bool exact, afi_t afi,
10482 safi_t safi, bool uj)
d62a17ae 10483{
10484 struct lcommunity *lcom;
10485 struct buffer *b;
10486 int i;
10487 char *str;
10488 int first = 0;
10489
10490 b = buffer_new(1024);
10491 for (i = 0; i < argc; i++) {
10492 if (first)
10493 buffer_putc(b, ' ');
10494 else {
10495 if (strmatch(argv[i]->text, "AA:BB:CC")) {
10496 first = 1;
10497 buffer_putstr(b, argv[i]->arg);
10498 }
10499 }
10500 }
10501 buffer_putc(b, '\0');
57d187bc 10502
d62a17ae 10503 str = buffer_getstr(b);
10504 buffer_free(b);
57d187bc 10505
d62a17ae 10506 lcom = lcommunity_str2com(str);
10507 XFREE(MTYPE_TMP, str);
10508 if (!lcom) {
10509 vty_out(vty, "%% Large-community malformed\n");
10510 return CMD_WARNING;
10511 }
57d187bc 10512
36a206db 10513 return bgp_show(vty, bgp, afi, safi,
10514 (exact ? bgp_show_type_lcommunity_exact
10515 : bgp_show_type_lcommunity),
10516 lcom, uj);
57d187bc
JS
10517}
10518
d62a17ae 10519static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 10520 const char *lcom, bool exact, afi_t afi,
10521 safi_t safi, bool uj)
57d187bc 10522{
d62a17ae 10523 struct community_list *list;
57d187bc 10524
e237b0d2 10525 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 10526 LARGE_COMMUNITY_LIST_MASTER);
10527 if (list == NULL) {
10528 vty_out(vty, "%% %s is not a valid large-community-list name\n",
10529 lcom);
10530 return CMD_WARNING;
10531 }
57d187bc 10532
36a206db 10533 return bgp_show(vty, bgp, afi, safi,
10534 (exact ? bgp_show_type_lcommunity_list_exact
10535 : bgp_show_type_lcommunity_list),
d62a17ae 10536 list, uj);
fee0f4c6 10537}
10538
52951b63
DS
10539DEFUN (show_ip_bgp_large_community_list,
10540 show_ip_bgp_large_community_list_cmd,
36a206db 10541 "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
10542 SHOW_STR
10543 IP_STR
10544 BGP_STR
10545 BGP_INSTANCE_HELP_STR
9bedbb1e 10546 BGP_AFI_HELP_STR
4dd6177e 10547 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10548 "Display routes matching the large-community-list\n"
10549 "large-community-list number\n"
10550 "large-community-list name\n"
36a206db 10551 "Exact match of the large-communities\n"
52951b63
DS
10552 JSON_STR)
10553{
d62a17ae 10554 afi_t afi = AFI_IP6;
10555 safi_t safi = SAFI_UNICAST;
10556 int idx = 0;
36a206db 10557 bool exact_match = 0;
4d678463 10558 struct bgp *bgp = NULL;
9f049418 10559 bool uj = use_json(argc, argv);
d62a17ae 10560
4d678463
KA
10561 if (uj)
10562 argc--;
10563
10564 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10565 &bgp, uj);
10566 if (!idx)
10567 return CMD_WARNING;
d62a17ae 10568
10569 argv_find(argv, argc, "large-community-list", &idx);
36a206db 10570
10571 const char *clist_number_or_name = argv[++idx]->arg;
10572
10573 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10574 exact_match = 1;
10575
10576 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
10577 exact_match, afi, safi, uj);
52951b63
DS
10578}
10579DEFUN (show_ip_bgp_large_community,
10580 show_ip_bgp_large_community_cmd,
36a206db 10581 "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
10582 SHOW_STR
10583 IP_STR
10584 BGP_STR
10585 BGP_INSTANCE_HELP_STR
9bedbb1e 10586 BGP_AFI_HELP_STR
4dd6177e 10587 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10588 "Display routes matching the large-communities\n"
10589 "List of large-community numbers\n"
36a206db 10590 "Exact match of the large-communities\n"
52951b63
DS
10591 JSON_STR)
10592{
d62a17ae 10593 afi_t afi = AFI_IP6;
10594 safi_t safi = SAFI_UNICAST;
10595 int idx = 0;
36a206db 10596 bool exact_match = 0;
4d678463 10597 struct bgp *bgp = NULL;
9f049418 10598 bool uj = use_json(argc, argv);
d62a17ae 10599
4d678463
KA
10600 if (uj)
10601 argc--;
10602
10603 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10604 &bgp, uj);
10605 if (!idx)
10606 return CMD_WARNING;
d62a17ae 10607
36a206db 10608 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
10609 if (argv_find(argv, argc, "exact-match", &idx))
10610 exact_match = 1;
10611 return bgp_show_lcommunity(vty, bgp, argc, argv,
10612 exact_match, afi, safi, uj);
10613 } else
d62a17ae 10614 return bgp_show(vty, bgp, afi, safi,
10615 bgp_show_type_lcommunity_all, NULL, uj);
52951b63
DS
10616}
10617
d62a17ae 10618static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 10619 safi_t safi, struct json_object *json);
e01ca200 10620
7b2ff250 10621
9ab0cf58
PG
10622DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
10623 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
10624 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
10625 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
10626{
10627 bool uj = use_json(argc, argv);
10628 struct bgp *bgp = NULL;
ec76a1d1
DA
10629 safi_t safi = SAFI_UNICAST;
10630 afi_t afi = AFI_IP6;
4265b261 10631 int idx = 0;
6c9d22e2
PG
10632 struct json_object *json_all = NULL;
10633 struct json_object *json_afi_safi = NULL;
4265b261
PG
10634
10635 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10636 &bgp, false);
9ab0cf58 10637 if (!bgp)
4265b261 10638 return CMD_WARNING;
6c9d22e2 10639
4265b261 10640 if (uj)
6c9d22e2 10641 json_all = json_object_new_object();
4265b261 10642
9ab0cf58
PG
10643 FOREACH_AFI_SAFI (afi, safi) {
10644 /*
10645 * So limit output to those afi/safi pairs that
10646 * actually have something interesting in them
10647 */
10648 if (strmatch(get_afi_safi_str(afi, safi, true),
10649 "Unknown")) {
10650 continue;
10651 }
10652 if (uj) {
10653 json_afi_safi = json_object_new_array();
10654 json_object_object_add(
10655 json_all,
10656 get_afi_safi_str(afi, safi, true),
10657 json_afi_safi);
10658 } else {
10659 json_afi_safi = NULL;
6c9d22e2 10660 }
9ab0cf58
PG
10661
10662 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 10663 }
6c9d22e2
PG
10664
10665 if (uj) {
9ab0cf58
PG
10666 vty_out(vty, "%s",
10667 json_object_to_json_string_ext(
10668 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 10669 json_object_free(json_all);
4265b261 10670 }
6c9d22e2 10671
4265b261
PG
10672 return CMD_SUCCESS;
10673}
10674
7b2ff250 10675/* BGP route print out function without JSON */
14718643
PG
10676DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
10677 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 10678 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
10679 SHOW_STR
10680 IP_STR
10681 BGP_STR
10682 BGP_INSTANCE_HELP_STR
10683 L2VPN_HELP_STR
10684 EVPN_HELP_STR
10685 "BGP RIB advertisement statistics\n"
10686 JSON_STR)
10687{
ec76a1d1
DA
10688 afi_t afi = AFI_IP6;
10689 safi_t safi = SAFI_UNICAST;
14718643
PG
10690 struct bgp *bgp = NULL;
10691 int idx = 0, ret;
10692 bool uj = use_json(argc, argv);
10693 struct json_object *json_afi_safi = NULL, *json = NULL;
10694
10695 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10696 &bgp, false);
10697 if (!idx)
10698 return CMD_WARNING;
10699
10700 if (uj)
10701 json_afi_safi = json_object_new_array();
10702 else
10703 json_afi_safi = NULL;
10704
10705 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
10706
10707 if (uj) {
10708 json = json_object_new_object();
10709 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
10710 json_afi_safi);
10711 vty_out(vty, "%s", json_object_to_json_string_ext(
10712 json, JSON_C_TO_STRING_PRETTY));
10713 json_object_free(json);
10714 }
10715 return ret;
10716}
10717
893cccd0 10718/* BGP route print out function without JSON */
9ab0cf58
PG
10719DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
10720 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
10721 " [" BGP_SAFI_WITH_LABEL_CMD_STR
10722 "]]\
893cccd0 10723 statistics [json]",
9ab0cf58
PG
10724 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
10725 BGP_SAFI_WITH_LABEL_HELP_STR
10726 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 10727{
ec76a1d1
DA
10728 afi_t afi = AFI_IP6;
10729 safi_t safi = SAFI_UNICAST;
893cccd0
PG
10730 struct bgp *bgp = NULL;
10731 int idx = 0, ret;
10732 bool uj = use_json(argc, argv);
6c9d22e2 10733 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
10734
10735 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10736 &bgp, false);
10737 if (!idx)
10738 return CMD_WARNING;
6c9d22e2 10739
893cccd0 10740 if (uj)
6c9d22e2
PG
10741 json_afi_safi = json_object_new_array();
10742 else
10743 json_afi_safi = NULL;
10744
10745 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
10746
10747 if (uj) {
10748 json = json_object_new_object();
10749 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
10750 json_afi_safi);
9ab0cf58
PG
10751 vty_out(vty, "%s",
10752 json_object_to_json_string_ext(
10753 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
10754 json_object_free(json);
10755 }
10756 return ret;
893cccd0 10757}
7b2ff250
DW
10758
10759/* BGP route print out function without JSON */
9ab0cf58
PG
10760DEFUN(show_ip_bgp, show_ip_bgp_cmd,
10761 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
10762 " [" BGP_SAFI_WITH_LABEL_CMD_STR
10763 "]]\
7b2ff250
DW
10764 <dampening <parameters>\
10765 |route-map WORD\
10766 |prefix-list WORD\
10767 |filter-list WORD\
7b2ff250
DW
10768 |community-list <(1-500)|WORD> [exact-match]\
10769 |A.B.C.D/M longer-prefixes\
10770 |X:X::X:X/M longer-prefixes\
893cccd0 10771 >",
9ab0cf58
PG
10772 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
10773 BGP_SAFI_WITH_LABEL_HELP_STR
10774 "Display detailed information about dampening\n"
10775 "Display detail of configured dampening parameters\n"
10776 "Display routes matching the route-map\n"
10777 "A route-map to match on\n"
10778 "Display routes conforming to the prefix-list\n"
10779 "Prefix-list name\n"
10780 "Display routes conforming to the filter-list\n"
10781 "Regular expression access list name\n"
10782 "Display routes matching the community-list\n"
10783 "community-list number\n"
10784 "community-list name\n"
10785 "Exact match of the communities\n"
10786 "IPv4 prefix\n"
10787 "Display route and more specific routes\n"
10788 "IPv6 prefix\n"
10789 "Display route and more specific routes\n")
718e3744 10790{
d62a17ae 10791 afi_t afi = AFI_IP6;
10792 safi_t safi = SAFI_UNICAST;
10793 int exact_match = 0;
d62a17ae 10794 struct bgp *bgp = NULL;
10795 int idx = 0;
10796
10797 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10798 &bgp, false);
d62a17ae 10799 if (!idx)
10800 return CMD_WARNING;
10801
d62a17ae 10802 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 10803 if (argv_find(argv, argc, "parameters", &idx))
d62a17ae 10804 return bgp_show_dampening_parameters(vty, afi, safi);
10805 }
c016b6c7 10806
d62a17ae 10807 if (argv_find(argv, argc, "prefix-list", &idx))
10808 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
10809 safi, bgp_show_type_prefix_list);
10810
10811 if (argv_find(argv, argc, "filter-list", &idx))
10812 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
10813 safi, bgp_show_type_filter_list);
10814
d62a17ae 10815 if (argv_find(argv, argc, "route-map", &idx))
10816 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
10817 safi, bgp_show_type_route_map);
10818
d62a17ae 10819 if (argv_find(argv, argc, "community-list", &idx)) {
10820 const char *clist_number_or_name = argv[++idx]->arg;
10821 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10822 exact_match = 1;
10823 return bgp_show_community_list(vty, bgp, clist_number_or_name,
10824 exact_match, afi, safi);
10825 }
10826 /* prefix-longer */
10827 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10828 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10829 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
10830 safi,
10831 bgp_show_type_prefix_longer);
10832
7b2ff250
DW
10833 return CMD_WARNING;
10834}
10835
10836/* BGP route print out function with JSON */
10837DEFUN (show_ip_bgp_json,
10838 show_ip_bgp_json_cmd,
10839 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
cf4898bc
QY
10840 [cidr-only\
10841 |dampening <flap-statistics|dampened-paths>\
10842 |community [AA:NN|local-AS|no-advertise|no-export\
10843 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10844 |accept-own|accept-own-nexthop|route-filter-v6\
10845 |route-filter-v4|route-filter-translated-v6\
10846 |route-filter-translated-v4] [exact-match]\
10847 ] [json]",
7b2ff250
DW
10848 SHOW_STR
10849 IP_STR
10850 BGP_STR
10851 BGP_INSTANCE_HELP_STR
10852 BGP_AFI_HELP_STR
10853 BGP_SAFI_WITH_LABEL_HELP_STR
10854 "Display only routes with non-natural netmasks\n"
10855 "Display detailed information about dampening\n"
10856 "Display flap statistics of routes\n"
10857 "Display paths suppressed due to dampening\n"
10858 "Display routes matching the communities\n"
d0086e8e
AD
10859 COMMUNITY_AANN_STR
10860 "Do not send outside local AS (well-known community)\n"
10861 "Do not advertise to any peer (well-known community)\n"
10862 "Do not export to next AS (well-known community)\n"
10863 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
10864 "Do not export to any peer (well-known community)\n"
10865 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10866 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10867 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10868 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10869 "Should accept VPN route with local nexthop (well-known community)\n"
10870 "RT VPNv6 route filtering (well-known community)\n"
10871 "RT VPNv4 route filtering (well-known community)\n"
10872 "RT translated VPNv6 route filtering (well-known community)\n"
10873 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 10874 "Exact match of the communities\n"
7b2ff250
DW
10875 JSON_STR)
10876{
10877 afi_t afi = AFI_IP6;
10878 safi_t safi = SAFI_UNICAST;
10879 enum bgp_show_type sh_type = bgp_show_type_normal;
10880 struct bgp *bgp = NULL;
10881 int idx = 0;
d0086e8e 10882 int exact_match = 0;
9f049418
DS
10883 bool uj = use_json(argc, argv);
10884
10885 if (uj)
10886 argc--;
7b2ff250
DW
10887
10888 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10889 &bgp, uj);
7b2ff250
DW
10890 if (!idx)
10891 return CMD_WARNING;
10892
7b2ff250
DW
10893 if (argv_find(argv, argc, "cidr-only", &idx))
10894 return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
10895 NULL, uj);
10896
10897 if (argv_find(argv, argc, "dampening", &idx)) {
10898 if (argv_find(argv, argc, "dampened-paths", &idx))
10899 return bgp_show(vty, bgp, afi, safi,
10900 bgp_show_type_dampend_paths, NULL, uj);
10901 else if (argv_find(argv, argc, "flap-statistics", &idx))
10902 return bgp_show(vty, bgp, afi, safi,
10903 bgp_show_type_flap_statistics, NULL,
10904 uj);
10905 }
10906
10907 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 10908 char *maybecomm = NULL;
cf4898bc 10909 char *community = NULL;
d0086e8e 10910
79bc257a
RW
10911 if (idx + 1 < argc) {
10912 if (argv[idx + 1]->type == VARIABLE_TKN)
10913 maybecomm = argv[idx + 1]->arg;
10914 else
10915 maybecomm = argv[idx + 1]->text;
10916 }
10917
cf4898bc
QY
10918 if (maybecomm && !strmatch(maybecomm, "json")
10919 && !strmatch(maybecomm, "exact-match"))
10920 community = maybecomm;
d0086e8e 10921
cf4898bc
QY
10922 if (argv_find(argv, argc, "exact-match", &idx))
10923 exact_match = 1;
d0086e8e 10924
cf4898bc
QY
10925 if (community)
10926 return bgp_show_community(vty, bgp, community,
10927 exact_match, afi, safi, uj);
10928 else
d0086e8e 10929 return (bgp_show(vty, bgp, afi, safi,
cf4898bc
QY
10930 bgp_show_type_community_all, NULL,
10931 uj));
7b2ff250 10932 }
d0086e8e 10933
1ae44dfc 10934 return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj);
a636c635 10935}
47fc97cc 10936
718e3744 10937DEFUN (show_ip_bgp_route,
10938 show_ip_bgp_route_cmd,
3efd0893 10939 "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 10940 SHOW_STR
10941 IP_STR
10942 BGP_STR
a636c635 10943 BGP_INSTANCE_HELP_STR
4f280b15 10944 BGP_AFI_HELP_STR
4dd6177e 10945 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 10946 "Network in the BGP routing table to display\n"
0c7b1b01 10947 "IPv4 prefix\n"
8c3deaae 10948 "Network in the BGP routing table to display\n"
0c7b1b01 10949 "IPv6 prefix\n"
4092b06c 10950 "Display only the bestpath\n"
b05a1c8b 10951 "Display only multipaths\n"
9973d184 10952 JSON_STR)
4092b06c 10953{
d62a17ae 10954 int prefix_check = 0;
ae19d7dd 10955
d62a17ae 10956 afi_t afi = AFI_IP6;
10957 safi_t safi = SAFI_UNICAST;
10958 char *prefix = NULL;
10959 struct bgp *bgp = NULL;
10960 enum bgp_path_type path_type;
9f049418 10961 bool uj = use_json(argc, argv);
b05a1c8b 10962
d62a17ae 10963 int idx = 0;
ae19d7dd 10964
d62a17ae 10965 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10966 &bgp, uj);
d62a17ae 10967 if (!idx)
10968 return CMD_WARNING;
c41247f5 10969
d62a17ae 10970 if (!bgp) {
10971 vty_out(vty,
10972 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10973 return CMD_WARNING;
10974 }
a636c635 10975
d62a17ae 10976 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10977 if (argv_find(argv, argc, "A.B.C.D", &idx)
10978 || argv_find(argv, argc, "X:X::X:X", &idx))
10979 prefix_check = 0;
10980 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10981 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10982 prefix_check = 1;
10983
10984 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
10985 && afi != AFI_IP6) {
10986 vty_out(vty,
10987 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10988 return CMD_WARNING;
10989 }
10990 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
10991 && afi != AFI_IP) {
10992 vty_out(vty,
10993 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10994 return CMD_WARNING;
10995 }
10996
10997 prefix = argv[idx]->arg;
10998
10999 /* [<bestpath|multipath>] */
11000 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 11001 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 11002 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 11003 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 11004 else
360660c6 11005 path_type = BGP_PATH_SHOW_ALL;
a636c635 11006
d62a17ae 11007 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
11008 path_type, uj);
4092b06c
DS
11009}
11010
8c3deaae
QY
11011DEFUN (show_ip_bgp_regexp,
11012 show_ip_bgp_regexp_cmd,
3e5b31b3 11013 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
11014 SHOW_STR
11015 IP_STR
11016 BGP_STR
b00b230a 11017 BGP_INSTANCE_HELP_STR
4f280b15 11018 BGP_AFI_HELP_STR
4dd6177e 11019 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 11020 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
11021 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
11022 JSON_STR)
8c3deaae 11023{
d62a17ae 11024 afi_t afi = AFI_IP6;
11025 safi_t safi = SAFI_UNICAST;
11026 struct bgp *bgp = NULL;
3e5b31b3
DA
11027 bool uj = use_json(argc, argv);
11028 char *regstr = NULL;
8c3deaae 11029
d62a17ae 11030 int idx = 0;
11031 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11032 &bgp, false);
d62a17ae 11033 if (!idx)
11034 return CMD_WARNING;
8c3deaae 11035
d62a17ae 11036 // get index of regex
3e5b31b3
DA
11037 if (argv_find(argv, argc, "REGEX", &idx))
11038 regstr = argv[idx]->arg;
8c3deaae 11039
5f71d11c 11040 assert(regstr);
3e5b31b3
DA
11041 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
11042 bgp_show_type_regexp, uj);
8c3deaae
QY
11043}
11044
a636c635
DW
11045DEFUN (show_ip_bgp_instance_all,
11046 show_ip_bgp_instance_all_cmd,
4dd6177e 11047 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json]",
4092b06c 11048 SHOW_STR
a636c635 11049 IP_STR
4092b06c 11050 BGP_STR
a636c635 11051 BGP_INSTANCE_ALL_HELP_STR
4f280b15 11052 BGP_AFI_HELP_STR
4dd6177e 11053 BGP_SAFI_WITH_LABEL_HELP_STR
9973d184 11054 JSON_STR)
4092b06c 11055{
d62a17ae 11056 afi_t afi = AFI_IP;
11057 safi_t safi = SAFI_UNICAST;
11058 struct bgp *bgp = NULL;
d62a17ae 11059 int idx = 0;
9f049418 11060 bool uj = use_json(argc, argv);
ae19d7dd 11061
d62a17ae 11062 if (uj)
11063 argc--;
e3e29b32 11064
9f049418
DS
11065 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11066 &bgp, uj);
11067 if (!idx)
11068 return CMD_WARNING;
11069
d62a17ae 11070 bgp_show_all_instances_routes_vty(vty, afi, safi, uj);
11071 return CMD_SUCCESS;
e3e29b32
LB
11072}
11073
a4d82a8a 11074static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11075 afi_t afi, safi_t safi, enum bgp_show_type type,
11076 bool use_json)
718e3744 11077{
d62a17ae 11078 regex_t *regex;
11079 int rc;
e3e29b32 11080
c3900853 11081 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 11082 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
11083 regstr);
11084 return CMD_WARNING_CONFIG_FAILED;
11085 }
11086
d62a17ae 11087 regex = bgp_regcomp(regstr);
11088 if (!regex) {
11089 vty_out(vty, "Can't compile regexp %s\n", regstr);
11090 return CMD_WARNING;
11091 }
a636c635 11092
3e5b31b3 11093 rc = bgp_show(vty, bgp, afi, safi, type, regex, use_json);
d62a17ae 11094 bgp_regex_free(regex);
11095 return rc;
e3e29b32
LB
11096}
11097
d62a17ae 11098static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
11099 const char *prefix_list_str, afi_t afi,
11100 safi_t safi, enum bgp_show_type type)
e3e29b32 11101{
d62a17ae 11102 struct prefix_list *plist;
718e3744 11103
d62a17ae 11104 plist = prefix_list_lookup(afi, prefix_list_str);
11105 if (plist == NULL) {
11106 vty_out(vty, "%% %s is not a valid prefix-list name\n",
11107 prefix_list_str);
11108 return CMD_WARNING;
11109 }
718e3744 11110
d62a17ae 11111 return bgp_show(vty, bgp, afi, safi, type, plist, 0);
4092b06c
DS
11112}
11113
d62a17ae 11114static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
11115 const char *filter, afi_t afi, safi_t safi,
11116 enum bgp_show_type type)
4092b06c 11117{
d62a17ae 11118 struct as_list *as_list;
718e3744 11119
d62a17ae 11120 as_list = as_list_lookup(filter);
11121 if (as_list == NULL) {
11122 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
11123 filter);
11124 return CMD_WARNING;
11125 }
a636c635 11126
d62a17ae 11127 return bgp_show(vty, bgp, afi, safi, type, as_list, 0);
718e3744 11128}
11129
d62a17ae 11130static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
11131 const char *rmap_str, afi_t afi, safi_t safi,
11132 enum bgp_show_type type)
718e3744 11133{
d62a17ae 11134 struct route_map *rmap;
bb46e94f 11135
d62a17ae 11136 rmap = route_map_lookup_by_name(rmap_str);
11137 if (!rmap) {
11138 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
11139 return CMD_WARNING;
11140 }
11141
11142 return bgp_show(vty, bgp, afi, safi, type, rmap, 0);
11143}
11144
7f323236
DW
11145static int bgp_show_community(struct vty *vty, struct bgp *bgp,
11146 const char *comstr, int exact, afi_t afi,
9f049418 11147 safi_t safi, bool use_json)
d62a17ae 11148{
11149 struct community *com;
d62a17ae 11150 int ret = 0;
11151
7f323236 11152 com = community_str2com(comstr);
d62a17ae 11153 if (!com) {
7f323236 11154 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 11155 return CMD_WARNING;
11156 }
11157
11158 ret = bgp_show(vty, bgp, afi, safi,
11159 (exact ? bgp_show_type_community_exact
11160 : bgp_show_type_community),
d0086e8e 11161 com, use_json);
3c1f53de 11162 community_free(&com);
46c3ce83 11163
d62a17ae 11164 return ret;
718e3744 11165}
11166
d62a17ae 11167static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
11168 const char *com, int exact, afi_t afi,
11169 safi_t safi)
50ef26d4 11170{
d62a17ae 11171 struct community_list *list;
50ef26d4 11172
e237b0d2 11173 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 11174 if (list == NULL) {
11175 vty_out(vty, "%% %s is not a valid community-list name\n", com);
11176 return CMD_WARNING;
11177 }
718e3744 11178
d62a17ae 11179 return bgp_show(vty, bgp, afi, safi,
11180 (exact ? bgp_show_type_community_list_exact
11181 : bgp_show_type_community_list),
11182 list, 0);
50ef26d4 11183}
11184
d62a17ae 11185static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
11186 const char *prefix, afi_t afi, safi_t safi,
11187 enum bgp_show_type type)
718e3744 11188{
d62a17ae 11189 int ret;
11190 struct prefix *p;
47fc97cc 11191
d62a17ae 11192 p = prefix_new();
95cbbd2a 11193
d62a17ae 11194 ret = str2prefix(prefix, p);
11195 if (!ret) {
11196 vty_out(vty, "%% Malformed Prefix\n");
11197 return CMD_WARNING;
11198 }
47e9b292 11199
d62a17ae 11200 ret = bgp_show(vty, bgp, afi, safi, type, p, 0);
63265b5c 11201 prefix_free(&p);
d62a17ae 11202 return ret;
11203}
11204
d62a17ae 11205enum bgp_stats {
11206 BGP_STATS_MAXBITLEN = 0,
11207 BGP_STATS_RIB,
11208 BGP_STATS_PREFIXES,
11209 BGP_STATS_TOTPLEN,
11210 BGP_STATS_UNAGGREGATEABLE,
11211 BGP_STATS_MAX_AGGREGATEABLE,
11212 BGP_STATS_AGGREGATES,
11213 BGP_STATS_SPACE,
11214 BGP_STATS_ASPATH_COUNT,
11215 BGP_STATS_ASPATH_MAXHOPS,
11216 BGP_STATS_ASPATH_TOTHOPS,
11217 BGP_STATS_ASPATH_MAXSIZE,
11218 BGP_STATS_ASPATH_TOTSIZE,
11219 BGP_STATS_ASN_HIGHEST,
11220 BGP_STATS_MAX,
a636c635 11221};
2815e61f 11222
9ab0cf58 11223#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
11224#define TABLE_STATS_IDX_JSON 1
11225
11226static const char *table_stats_strs[][2] = {
6c9d22e2
PG
11227 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
11228 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
11229 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
11230 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
11231 "unaggregateablePrefixes"},
11232 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
11233 "maximumAggregateablePrefixes"},
11234 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
11235 "bgpAggregateAdvertisements"},
6c9d22e2
PG
11236 [BGP_STATS_SPACE] = {"Address space advertised",
11237 "addressSpaceAdvertised"},
9ab0cf58
PG
11238 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
11239 "advertisementsWithPaths"},
11240 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
11241 "longestAsPath"},
11242 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
11243 "largestAsPath"},
11244 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
11245 "averageAsPathLengthHops"},
11246 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
11247 "averageAsPathSizeBytes"},
11248 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 11249 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 11250};
2815e61f 11251
d62a17ae 11252struct bgp_table_stats {
11253 struct bgp_table *table;
11254 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 11255 double total_space;
ff7924f6
PJ
11256};
11257
a636c635
DW
11258#if 0
11259#define TALLY_SIGFIG 100000
11260static unsigned long
11261ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 11262{
a636c635
DW
11263 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
11264 unsigned long res = (newtot * TALLY_SIGFIG) / count;
11265 unsigned long ret = newtot / count;
07d0c4ed 11266
a636c635
DW
11267 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
11268 return ret + 1;
11269 else
11270 return ret;
11271}
11272#endif
ff7924f6 11273
9bcb3eef 11274static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 11275 struct bgp_table_stats *ts, unsigned int space)
2815e61f 11276{
9bcb3eef 11277 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 11278 struct bgp_path_info *pi;
b54892e0 11279 const struct prefix *rn_p;
d62a17ae 11280
9bcb3eef 11281 if (dest == top)
9c14ec72 11282 return;
d62a17ae 11283
9bcb3eef 11284 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 11285 return;
d62a17ae 11286
9bcb3eef 11287 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 11288 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 11289 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 11290
a636c635
DW
11291#if 0
11292 ts->counts[BGP_STATS_AVGPLEN]
11293 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
11294 ts->counts[BGP_STATS_AVGPLEN],
b54892e0 11295 rn_p->prefixlen);
a636c635 11296#endif
d62a17ae 11297
9c14ec72 11298 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
11299 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
11300 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 11301
9bcb3eef 11302 if (pdest == NULL || pdest == top) {
9c14ec72
RW
11303 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
11304 /* announced address space */
11305 if (space)
b54892e0 11306 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 11307 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 11308 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 11309
9c14ec72 11310
9bcb3eef 11311 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
11312 ts->counts[BGP_STATS_RIB]++;
11313
05864da7
DS
11314 if (CHECK_FLAG(pi->attr->flag,
11315 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
11316 ts->counts[BGP_STATS_AGGREGATES]++;
11317
11318 /* as-path stats */
05864da7 11319 if (pi->attr->aspath) {
9c14ec72
RW
11320 unsigned int hops = aspath_count_hops(pi->attr->aspath);
11321 unsigned int size = aspath_size(pi->attr->aspath);
11322 as_t highest = aspath_highest(pi->attr->aspath);
11323
11324 ts->counts[BGP_STATS_ASPATH_COUNT]++;
11325
11326 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
11327 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
11328
11329 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
11330 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
11331
11332 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
11333 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 11334#if 0
07d0c4ed 11335 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
11336 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
11337 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
11338 hops);
11339 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
11340 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
11341 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
11342 size);
11343#endif
9c14ec72
RW
11344 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
11345 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
11346 }
11347 }
11348}
11349
11350static int bgp_table_stats_walker(struct thread *t)
11351{
9bcb3eef
DS
11352 struct bgp_dest *dest, *ndest;
11353 struct bgp_dest *top;
9c14ec72
RW
11354 struct bgp_table_stats *ts = THREAD_ARG(t);
11355 unsigned int space = 0;
11356
11357 if (!(top = bgp_table_top(ts->table)))
11358 return 0;
11359
11360 switch (ts->table->afi) {
11361 case AFI_IP:
11362 space = IPV4_MAX_BITLEN;
11363 break;
11364 case AFI_IP6:
11365 space = IPV6_MAX_BITLEN;
11366 break;
11367 default:
11368 return 0;
11369 }
11370
11371 ts->counts[BGP_STATS_MAXBITLEN] = space;
11372
9bcb3eef 11373 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
11374 if (ts->table->safi == SAFI_MPLS_VPN
11375 || ts->table->safi == SAFI_ENCAP
11376 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
11377 struct bgp_table *table;
11378
9bcb3eef 11379 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
11380 if (!table)
11381 continue;
11382
11383 top = bgp_table_top(table);
9bcb3eef
DS
11384 for (ndest = bgp_table_top(table); ndest;
11385 ndest = bgp_route_next(ndest))
11386 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 11387 } else {
9bcb3eef 11388 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 11389 }
11390 }
9c14ec72 11391
d62a17ae 11392 return 0;
2815e61f 11393}
ff7924f6 11394
d62a17ae 11395static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
6c9d22e2 11396 safi_t safi, struct json_object *json_array)
2815e61f 11397{
d62a17ae 11398 struct bgp_table_stats ts;
11399 unsigned int i;
893cccd0
PG
11400 int ret = CMD_SUCCESS;
11401 char temp_buf[20];
6c9d22e2
PG
11402 struct json_object *json = NULL;
11403
11404 if (json_array)
11405 json = json_object_new_object();
019386c2 11406
d62a17ae 11407 if (!bgp->rib[afi][safi]) {
893cccd0
PG
11408 char warning_msg[50];
11409
11410 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
11411 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
11412 safi);
6c9d22e2
PG
11413
11414 if (!json)
893cccd0
PG
11415 vty_out(vty, "%s\n", warning_msg);
11416 else
9ab0cf58 11417 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 11418
893cccd0
PG
11419 ret = CMD_WARNING;
11420 goto end_table_stats;
d62a17ae 11421 }
019386c2 11422
893cccd0
PG
11423 if (!json)
11424 vty_out(vty, "BGP %s RIB statistics\n",
11425 get_afi_safi_str(afi, safi, false));
019386c2 11426
d62a17ae 11427 /* labeled-unicast routes live in the unicast table */
11428 if (safi == SAFI_LABELED_UNICAST)
11429 safi = SAFI_UNICAST;
019386c2 11430
d62a17ae 11431 memset(&ts, 0, sizeof(ts));
11432 ts.table = bgp->rib[afi][safi];
11433 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 11434
d62a17ae 11435 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
11436 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
11437 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 11438 continue;
11439
11440 switch (i) {
a636c635
DW
11441#if 0
11442 case BGP_STATS_ASPATH_AVGHOPS:
11443 case BGP_STATS_ASPATH_AVGSIZE:
11444 case BGP_STATS_AVGPLEN:
11445 vty_out (vty, "%-30s: ", table_stats_strs[i]);
11446 vty_out (vty, "%12.2f",
11447 (float)ts.counts[i] / (float)TALLY_SIGFIG);
11448 break;
11449#endif
d62a17ae 11450 case BGP_STATS_ASPATH_TOTHOPS:
11451 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 11452 if (!json) {
9ab0cf58
PG
11453 snprintf(
11454 temp_buf, sizeof(temp_buf), "%12.2f",
11455 ts.counts[i]
11456 ? (float)ts.counts[i]
11457 / (float)ts.counts
11458 [BGP_STATS_ASPATH_COUNT]
11459 : 0);
893cccd0 11460 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
11461 table_stats_strs[i]
11462 [TABLE_STATS_IDX_VTY],
893cccd0 11463 temp_buf);
9ab0cf58
PG
11464 } else {
11465 json_object_double_add(
11466 json,
11467 table_stats_strs[i]
11468 [TABLE_STATS_IDX_JSON],
11469 ts.counts[i]
11470 ? (double)ts.counts[i]
11471 / (double)ts.counts
d62a17ae 11472 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
11473 : 0);
11474 }
d62a17ae 11475 break;
11476 case BGP_STATS_TOTPLEN:
6c9d22e2 11477 if (!json) {
9ab0cf58
PG
11478 snprintf(
11479 temp_buf, sizeof(temp_buf), "%12.2f",
11480 ts.counts[i]
11481 ? (float)ts.counts[i]
11482 / (float)ts.counts
11483 [BGP_STATS_PREFIXES]
11484 : 0);
893cccd0 11485 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
11486 table_stats_strs[i]
11487 [TABLE_STATS_IDX_VTY],
893cccd0 11488 temp_buf);
9ab0cf58
PG
11489 } else {
11490 json_object_double_add(
11491 json,
11492 table_stats_strs[i]
11493 [TABLE_STATS_IDX_JSON],
11494 ts.counts[i]
11495 ? (double)ts.counts[i]
11496 / (double)ts.counts
d62a17ae 11497 [BGP_STATS_PREFIXES]
9ab0cf58
PG
11498 : 0);
11499 }
d62a17ae 11500 break;
11501 case BGP_STATS_SPACE:
6c9d22e2
PG
11502 if (!json) {
11503 snprintf(temp_buf, sizeof(temp_buf), "%12g",
11504 ts.total_space);
893cccd0 11505 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
11506 table_stats_strs[i]
11507 [TABLE_STATS_IDX_VTY],
893cccd0 11508 temp_buf);
9ab0cf58
PG
11509 } else {
11510 json_object_double_add(
11511 json,
11512 table_stats_strs[i]
11513 [TABLE_STATS_IDX_JSON],
11514 (double)ts.total_space);
11515 }
8d0ab76d 11516 if (afi == AFI_IP6) {
6c9d22e2
PG
11517 if (!json) {
11518 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
11519 "%12g",
11520 ts.total_space
11521 * pow(2.0, -128 + 32));
6c9d22e2
PG
11522 vty_out(vty, "%30s: %s\n",
11523 "/32 equivalent %s\n",
11524 temp_buf);
9ab0cf58
PG
11525 } else {
11526 json_object_double_add(
11527 json, "/32equivalent",
11528 (double)(ts.total_space
11529 * pow(2.0,
11530 -128 + 32)));
11531 }
6c9d22e2
PG
11532 if (!json) {
11533 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
11534 "%12g",
11535 ts.total_space
11536 * pow(2.0, -128 + 48));
6c9d22e2
PG
11537 vty_out(vty, "%30s: %s\n",
11538 "/48 equivalent %s\n",
11539 temp_buf);
9ab0cf58
PG
11540 } else {
11541 json_object_double_add(
11542 json, "/48equivalent",
11543 (double)(ts.total_space
11544 * pow(2.0,
11545 -128 + 48)));
11546 }
8d0ab76d 11547 } else {
6c9d22e2
PG
11548 if (!json) {
11549 snprintf(temp_buf, sizeof(temp_buf),
11550 "%12.2f",
9ab0cf58
PG
11551 ts.total_space * 100.
11552 * pow(2.0, -32));
6c9d22e2 11553 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
11554 "% announced ", temp_buf);
11555 } else {
11556 json_object_double_add(
11557 json, "%announced",
11558 (double)(ts.total_space * 100.
11559 * pow(2.0, -32)));
11560 }
6c9d22e2
PG
11561 if (!json) {
11562 snprintf(temp_buf, sizeof(temp_buf),
11563 "%12.2f",
9ab0cf58
PG
11564 ts.total_space
11565 * pow(2.0, -32 + 8));
6c9d22e2
PG
11566 vty_out(vty, "%30s: %s\n",
11567 "/8 equivalent ", temp_buf);
9ab0cf58
PG
11568 } else {
11569 json_object_double_add(
11570 json, "/8equivalent",
11571 (double)(ts.total_space
11572 * pow(2.0, -32 + 8)));
11573 }
6c9d22e2
PG
11574 if (!json) {
11575 snprintf(temp_buf, sizeof(temp_buf),
11576 "%12.2f",
9ab0cf58
PG
11577 ts.total_space
11578 * pow(2.0, -32 + 24));
6c9d22e2 11579 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
11580 "/24 equivalent ", temp_buf);
11581 } else {
11582 json_object_double_add(
11583 json, "/24equivalent",
11584 (double)(ts.total_space
11585 * pow(2.0, -32 + 24)));
11586 }
8d0ab76d 11587 }
d62a17ae 11588 break;
11589 default:
6c9d22e2
PG
11590 if (!json) {
11591 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
11592 ts.counts[i]);
893cccd0 11593 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
11594 table_stats_strs[i]
11595 [TABLE_STATS_IDX_VTY],
11596 temp_buf);
11597 } else {
11598 json_object_int_add(
11599 json,
11600 table_stats_strs[i]
11601 [TABLE_STATS_IDX_JSON],
11602 ts.counts[i]);
11603 }
d62a17ae 11604 }
893cccd0
PG
11605 if (!json)
11606 vty_out(vty, "\n");
d62a17ae 11607 }
9ab0cf58 11608end_table_stats:
6c9d22e2
PG
11609 if (json)
11610 json_object_array_add(json_array, json);
893cccd0 11611 return ret;
d62a17ae 11612}
11613
11614enum bgp_pcounts {
11615 PCOUNT_ADJ_IN = 0,
11616 PCOUNT_DAMPED,
11617 PCOUNT_REMOVED,
11618 PCOUNT_HISTORY,
11619 PCOUNT_STALE,
11620 PCOUNT_VALID,
11621 PCOUNT_ALL,
11622 PCOUNT_COUNTED,
11623 PCOUNT_PFCNT, /* the figure we display to users */
11624 PCOUNT_MAX,
a636c635 11625};
718e3744 11626
2b64873d 11627static const char *const pcount_strs[] = {
9d303b37
DL
11628 [PCOUNT_ADJ_IN] = "Adj-in",
11629 [PCOUNT_DAMPED] = "Damped",
11630 [PCOUNT_REMOVED] = "Removed",
11631 [PCOUNT_HISTORY] = "History",
11632 [PCOUNT_STALE] = "Stale",
11633 [PCOUNT_VALID] = "Valid",
11634 [PCOUNT_ALL] = "All RIB",
11635 [PCOUNT_COUNTED] = "PfxCt counted",
11636 [PCOUNT_PFCNT] = "Useable",
11637 [PCOUNT_MAX] = NULL,
a636c635 11638};
718e3744 11639
d62a17ae 11640struct peer_pcounts {
11641 unsigned int count[PCOUNT_MAX];
11642 const struct peer *peer;
11643 const struct bgp_table *table;
54317cba 11644 safi_t safi;
a636c635 11645};
47fc97cc 11646
9bcb3eef 11647static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 11648{
54317cba
JW
11649 const struct bgp_adj_in *ain;
11650 const struct bgp_path_info *pi;
d62a17ae 11651 const struct peer *peer = pc->peer;
11652
54317cba
JW
11653 for (ain = rn->adj_in; ain; ain = ain->next)
11654 if (ain->peer == peer)
11655 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 11656
9bcb3eef 11657 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 11658
54317cba
JW
11659 if (pi->peer != peer)
11660 continue;
d62a17ae 11661
54317cba 11662 pc->count[PCOUNT_ALL]++;
d62a17ae 11663
54317cba
JW
11664 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
11665 pc->count[PCOUNT_DAMPED]++;
11666 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
11667 pc->count[PCOUNT_HISTORY]++;
11668 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
11669 pc->count[PCOUNT_REMOVED]++;
11670 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
11671 pc->count[PCOUNT_STALE]++;
11672 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
11673 pc->count[PCOUNT_VALID]++;
11674 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
11675 pc->count[PCOUNT_PFCNT]++;
11676
11677 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
11678 pc->count[PCOUNT_COUNTED]++;
11679 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
11680 flog_err(
11681 EC_LIB_DEVELOPMENT,
11682 "Attempting to count but flags say it is unusable");
11683 } else {
40381db7 11684 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
11685 flog_err(
11686 EC_LIB_DEVELOPMENT,
11687 "Not counted but flags say we should");
d62a17ae 11688 }
11689 }
54317cba
JW
11690}
11691
11692static int bgp_peer_count_walker(struct thread *t)
11693{
9bcb3eef 11694 struct bgp_dest *rn, *rm;
54317cba
JW
11695 const struct bgp_table *table;
11696 struct peer_pcounts *pc = THREAD_ARG(t);
11697
11698 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
11699 || pc->safi == SAFI_EVPN) {
11700 /* Special handling for 2-level routing tables. */
11701 for (rn = bgp_table_top(pc->table); rn;
11702 rn = bgp_route_next(rn)) {
9bcb3eef 11703 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
11704 if (table != NULL)
11705 for (rm = bgp_table_top(table); rm;
11706 rm = bgp_route_next(rm))
11707 bgp_peer_count_proc(rm, pc);
11708 }
11709 } else
11710 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
11711 bgp_peer_count_proc(rn, pc);
11712
d62a17ae 11713 return 0;
718e3744 11714}
11715
d62a17ae 11716static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 11717 safi_t safi, bool use_json)
856ca177 11718{
d62a17ae 11719 struct peer_pcounts pcounts = {.peer = peer};
11720 unsigned int i;
11721 json_object *json = NULL;
11722 json_object *json_loop = NULL;
856ca177 11723
d62a17ae 11724 if (use_json) {
11725 json = json_object_new_object();
11726 json_loop = json_object_new_object();
11727 }
718e3744 11728
d62a17ae 11729 if (!peer || !peer->bgp || !peer->afc[afi][safi]
11730 || !peer->bgp->rib[afi][safi]) {
11731 if (use_json) {
11732 json_object_string_add(
11733 json, "warning",
11734 "No such neighbor or address family");
11735 vty_out(vty, "%s\n", json_object_to_json_string(json));
11736 json_object_free(json);
11737 } else
11738 vty_out(vty, "%% No such neighbor or address family\n");
11739
11740 return CMD_WARNING;
11741 }
2a71e9ce 11742
d62a17ae 11743 memset(&pcounts, 0, sizeof(pcounts));
11744 pcounts.peer = peer;
11745 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 11746 pcounts.safi = safi;
d62a17ae 11747
11748 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
11749 * stats for the thread-walk (i.e. ensure this can't be blamed on
11750 * on just vty_read()).
11751 */
d62a17ae 11752 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
11753
11754 if (use_json) {
11755 json_object_string_add(json, "prefixCountsFor", peer->host);
11756 json_object_string_add(json, "multiProtocol",
5cb5f4d0 11757 get_afi_safi_str(afi, safi, true));
d62a17ae 11758 json_object_int_add(json, "pfxCounter",
11759 peer->pcount[afi][safi]);
11760
11761 for (i = 0; i < PCOUNT_MAX; i++)
11762 json_object_int_add(json_loop, pcount_strs[i],
11763 pcounts.count[i]);
11764
11765 json_object_object_add(json, "ribTableWalkCounters", json_loop);
11766
11767 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
11768 json_object_string_add(json, "pfxctDriftFor",
11769 peer->host);
11770 json_object_string_add(
11771 json, "recommended",
11772 "Please report this bug, with the above command output");
11773 }
996c9314
LB
11774 vty_out(vty, "%s\n", json_object_to_json_string_ext(
11775 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 11776 json_object_free(json);
11777 } else {
11778
11779 if (peer->hostname
892fedb6 11780 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 11781 vty_out(vty, "Prefix counts for %s/%s, %s\n",
11782 peer->hostname, peer->host,
5cb5f4d0 11783 get_afi_safi_str(afi, safi, false));
d62a17ae 11784 } else {
11785 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 11786 get_afi_safi_str(afi, safi, false));
d62a17ae 11787 }
11788
a0a87037 11789 vty_out(vty, "PfxCt: %" PRIu32 "\n", peer->pcount[afi][safi]);
d62a17ae 11790 vty_out(vty, "\nCounts from RIB table walk:\n\n");
11791
11792 for (i = 0; i < PCOUNT_MAX; i++)
11793 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
11794 pcounts.count[i]);
11795
11796 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
11797 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
11798 vty_out(vty,
11799 "Please report this bug, with the above command output\n");
11800 }
11801 }
11802
11803 return CMD_SUCCESS;
718e3744 11804}
11805
a636c635
DW
11806DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
11807 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 11808 "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 11809 SHOW_STR
11810 IP_STR
11811 BGP_STR
8386ac43 11812 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
11813 BGP_AFI_HELP_STR
11814 BGP_SAFI_HELP_STR
0b16f239
DS
11815 "Detailed information on TCP and BGP neighbor connections\n"
11816 "Neighbor to display information about\n"
11817 "Neighbor to display information about\n"
91d37724 11818 "Neighbor on BGP configured interface\n"
a636c635 11819 "Display detailed prefix count information\n"
9973d184 11820 JSON_STR)
0b16f239 11821{
d62a17ae 11822 afi_t afi = AFI_IP6;
11823 safi_t safi = SAFI_UNICAST;
11824 struct peer *peer;
11825 int idx = 0;
11826 struct bgp *bgp = NULL;
9f049418
DS
11827 bool uj = use_json(argc, argv);
11828
11829 if (uj)
11830 argc--;
856ca177 11831
d62a17ae 11832 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11833 &bgp, uj);
d62a17ae 11834 if (!idx)
11835 return CMD_WARNING;
0b16f239 11836
d62a17ae 11837 argv_find(argv, argc, "neighbors", &idx);
11838 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
11839 if (!peer)
11840 return CMD_WARNING;
bb46e94f 11841
29c8d9da 11842 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 11843}
0b16f239 11844
d6902373
PG
11845#ifdef KEEP_OLD_VPN_COMMANDS
11846DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
11847 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
11848 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
11849 SHOW_STR
11850 IP_STR
11851 BGP_STR
d6902373 11852 BGP_VPNVX_HELP_STR
91d37724 11853 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
11854 "Detailed information on TCP and BGP neighbor connections\n"
11855 "Neighbor to display information about\n"
11856 "Neighbor to display information about\n"
91d37724 11857 "Neighbor on BGP configured interface\n"
a636c635 11858 "Display detailed prefix count information\n"
9973d184 11859 JSON_STR)
a636c635 11860{
d62a17ae 11861 int idx_peer = 6;
11862 struct peer *peer;
9f049418 11863 bool uj = use_json(argc, argv);
a636c635 11864
d62a17ae 11865 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
11866 if (!peer)
11867 return CMD_WARNING;
11868
11869 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
11870}
11871
d6902373
PG
11872DEFUN (show_ip_bgp_vpn_all_route_prefix,
11873 show_ip_bgp_vpn_all_route_prefix_cmd,
11874 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
11875 SHOW_STR
11876 IP_STR
11877 BGP_STR
d6902373 11878 BGP_VPNVX_HELP_STR
91d37724
QY
11879 "Display information about all VPNv4 NLRIs\n"
11880 "Network in the BGP routing table to display\n"
3a2d747c 11881 "Network in the BGP routing table to display\n"
9973d184 11882 JSON_STR)
91d37724 11883{
d62a17ae 11884 int idx = 0;
11885 char *network = NULL;
11886 struct bgp *bgp = bgp_get_default();
11887 if (!bgp) {
11888 vty_out(vty, "Can't find default instance\n");
11889 return CMD_WARNING;
11890 }
87e34b58 11891
d62a17ae 11892 if (argv_find(argv, argc, "A.B.C.D", &idx))
11893 network = argv[idx]->arg;
11894 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
11895 network = argv[idx]->arg;
11896 else {
11897 vty_out(vty, "Unable to figure out Network\n");
11898 return CMD_WARNING;
11899 }
87e34b58 11900
d62a17ae 11901 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 11902 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 11903}
d6902373 11904#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 11905
44c69747
LK
11906DEFUN (show_bgp_l2vpn_evpn_route_prefix,
11907 show_bgp_l2vpn_evpn_route_prefix_cmd,
11908 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 11909 SHOW_STR
4c63a661
PG
11910 BGP_STR
11911 L2VPN_HELP_STR
11912 EVPN_HELP_STR
44c69747
LK
11913 "Network in the BGP routing table to display\n"
11914 "Network in the BGP routing table to display\n"
4c63a661
PG
11915 "Network in the BGP routing table to display\n"
11916 "Network in the BGP routing table to display\n"
11917 JSON_STR)
11918{
d62a17ae 11919 int idx = 0;
11920 char *network = NULL;
44c69747 11921 int prefix_check = 0;
a636c635 11922
44c69747
LK
11923 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
11924 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 11925 network = argv[idx]->arg;
44c69747 11926 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 11927 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 11928 network = argv[idx]->arg;
44c69747
LK
11929 prefix_check = 1;
11930 } else {
d62a17ae 11931 vty_out(vty, "Unable to figure out Network\n");
11932 return CMD_WARNING;
11933 }
44c69747
LK
11934 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
11935 prefix_check, BGP_PATH_SHOW_ALL,
11936 use_json(argc, argv));
d62a17ae 11937}
11938
11939static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 11940 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 11941 const char *rmap_name, bool use_json,
6392aaa6 11942 json_object *json)
d62a17ae 11943{
11944 struct bgp_table *table;
11945 struct bgp_adj_in *ain;
11946 struct bgp_adj_out *adj;
74a630b6
NT
11947 unsigned long output_count = 0;
11948 unsigned long filtered_count = 0;
9bcb3eef 11949 struct bgp_dest *dest;
d62a17ae 11950 int header1 = 1;
11951 struct bgp *bgp;
11952 int header2 = 1;
11953 struct attr attr;
11954 int ret;
11955 struct update_subgroup *subgrp;
11956 json_object *json_scode = NULL;
11957 json_object *json_ocode = NULL;
11958 json_object *json_ar = NULL;
11959 struct peer_af *paf;
f99def61 11960 bool route_filtered;
d62a17ae 11961
11962 if (use_json) {
11963 json_scode = json_object_new_object();
11964 json_ocode = json_object_new_object();
11965 json_ar = json_object_new_object();
11966
11967 json_object_string_add(json_scode, "suppressed", "s");
11968 json_object_string_add(json_scode, "damped", "d");
11969 json_object_string_add(json_scode, "history", "h");
11970 json_object_string_add(json_scode, "valid", "*");
11971 json_object_string_add(json_scode, "best", ">");
11972 json_object_string_add(json_scode, "multipath", "=");
11973 json_object_string_add(json_scode, "internal", "i");
11974 json_object_string_add(json_scode, "ribFailure", "r");
11975 json_object_string_add(json_scode, "stale", "S");
11976 json_object_string_add(json_scode, "removed", "R");
11977
11978 json_object_string_add(json_ocode, "igp", "i");
11979 json_object_string_add(json_ocode, "egp", "e");
11980 json_object_string_add(json_ocode, "incomplete", "?");
11981 }
a636c635 11982
d62a17ae 11983 bgp = peer->bgp;
a636c635 11984
d62a17ae 11985 if (!bgp) {
11986 if (use_json) {
11987 json_object_string_add(json, "alert", "no BGP");
11988 vty_out(vty, "%s\n", json_object_to_json_string(json));
11989 json_object_free(json);
11990 } else
11991 vty_out(vty, "%% No bgp\n");
11992 return;
11993 }
a636c635 11994
c512a642
EDP
11995 /* labeled-unicast routes live in the unicast table */
11996 if (safi == SAFI_LABELED_UNICAST)
11997 table = bgp->rib[afi][SAFI_UNICAST];
11998 else
11999 table = bgp->rib[afi][safi];
d62a17ae 12000
12001 output_count = filtered_count = 0;
12002 subgrp = peer_subgroup(peer, afi, safi);
12003
6392aaa6 12004 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 12005 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
12006 if (use_json) {
12007 json_object_int_add(json, "bgpTableVersion",
12008 table->version);
12009 json_object_string_add(json, "bgpLocalRouterId",
12010 inet_ntoa(bgp->router_id));
01eced22
AD
12011 json_object_int_add(json, "defaultLocPrf",
12012 bgp->default_local_pref);
12013 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 12014 json_object_object_add(json, "bgpStatusCodes",
12015 json_scode);
12016 json_object_object_add(json, "bgpOriginCodes",
12017 json_ocode);
07d0c4ed
DA
12018 json_object_string_add(
12019 json, "bgpOriginatingDefaultNetwork",
12020 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 12021 } else {
996c9314 12022 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 12023 ", local router ID is %s, vrf id ",
d62a17ae 12024 table->version, inet_ntoa(bgp->router_id));
9df8b37c
PZ
12025 if (bgp->vrf_id == VRF_UNKNOWN)
12026 vty_out(vty, "%s", VRFID_NONE_STR);
12027 else
12028 vty_out(vty, "%u", bgp->vrf_id);
12029 vty_out(vty, "\n");
01eced22
AD
12030 vty_out(vty, "Default local pref %u, ",
12031 bgp->default_local_pref);
12032 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 12033 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 12034 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 12035 vty_out(vty, BGP_SHOW_OCODE_HEADER);
12036
07d0c4ed
DA
12037 vty_out(vty, "Originating default network %s\n\n",
12038 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 12039 }
12040 header1 = 0;
12041 }
a636c635 12042
9bcb3eef 12043 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
12044 if (type == bgp_show_adj_route_received
12045 || type == bgp_show_adj_route_filtered) {
9bcb3eef 12046 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 12047 if (ain->peer != peer)
ea47320b 12048 continue;
6392aaa6 12049
ea47320b
DL
12050 if (header1) {
12051 if (use_json) {
12052 json_object_int_add(
60466a63 12053 json, "bgpTableVersion",
ea47320b
DL
12054 0);
12055 json_object_string_add(
12056 json,
12057 "bgpLocalRouterId",
12058 inet_ntoa(
12059 bgp->router_id));
01eced22
AD
12060 json_object_int_add(json,
12061 "defaultLocPrf",
12062 bgp->default_local_pref);
12063 json_object_int_add(json,
12064 "localAS", bgp->as);
ea47320b 12065 json_object_object_add(
60466a63 12066 json, "bgpStatusCodes",
ea47320b
DL
12067 json_scode);
12068 json_object_object_add(
60466a63 12069 json, "bgpOriginCodes",
ea47320b
DL
12070 json_ocode);
12071 } else {
12072 vty_out(vty,
9df8b37c 12073 "BGP table version is 0, local router ID is %s, vrf id ",
ea47320b 12074 inet_ntoa(
9df8b37c
PZ
12075 bgp->router_id));
12076 if (bgp->vrf_id == VRF_UNKNOWN)
12077 vty_out(vty, "%s",
12078 VRFID_NONE_STR);
12079 else
12080 vty_out(vty, "%u",
12081 bgp->vrf_id);
12082 vty_out(vty, "\n");
01eced22
AD
12083 vty_out(vty,
12084 "Default local pref %u, ",
12085 bgp->default_local_pref);
12086 vty_out(vty, "local AS %u\n",
12087 bgp->as);
ea47320b
DL
12088 vty_out(vty,
12089 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
12090 vty_out(vty,
12091 BGP_SHOW_NCODE_HEADER);
ea47320b
DL
12092 vty_out(vty,
12093 BGP_SHOW_OCODE_HEADER);
d62a17ae 12094 }
ea47320b
DL
12095 header1 = 0;
12096 }
12097 if (header2) {
12098 if (!use_json)
12099 vty_out(vty, BGP_SHOW_HEADER);
12100 header2 = 0;
12101 }
6392aaa6 12102
6f4f49b2 12103 attr = *ain->attr;
f99def61
AD
12104 route_filtered = false;
12105
12106 /* Filter prefix using distribute list,
12107 * filter list or prefix list
12108 */
b54892e0 12109 const struct prefix *rn_p =
9bcb3eef 12110 bgp_dest_get_prefix(dest);
b54892e0
DS
12111 if ((bgp_input_filter(peer, rn_p, &attr, afi,
12112 safi))
12113 == FILTER_DENY)
f99def61
AD
12114 route_filtered = true;
12115
12116 /* Filter prefix using route-map */
b54892e0
DS
12117 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
12118 safi, rmap_name, NULL,
12119 0, NULL);
6392aaa6 12120
13c8e163
AD
12121 if (type == bgp_show_adj_route_filtered &&
12122 !route_filtered && ret != RMAP_DENY) {
b755861b 12123 bgp_attr_undup(&attr, ain->attr);
6392aaa6 12124 continue;
d62a17ae 12125 }
6392aaa6 12126
13c8e163
AD
12127 if (type == bgp_show_adj_route_received &&
12128 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
12129 filtered_count++;
12130
b54892e0 12131 route_vty_out_tmp(vty, rn_p, &attr, safi,
6392aaa6 12132 use_json, json_ar);
b755861b 12133 bgp_attr_undup(&attr, ain->attr);
6392aaa6 12134 output_count++;
d62a17ae 12135 }
6392aaa6 12136 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 12137 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 12138 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 12139 if (paf->peer != peer || !adj->attr)
924c3f6a 12140 continue;
d62a17ae 12141
924c3f6a
DS
12142 if (header1) {
12143 if (use_json) {
12144 json_object_int_add(
12145 json,
12146 "bgpTableVersion",
12147 table->version);
12148 json_object_string_add(
12149 json,
12150 "bgpLocalRouterId",
12151 inet_ntoa(
12152 bgp->router_id));
01eced22
AD
12153 json_object_int_add(
12154 json, "defaultLocPrf",
12155 bgp->default_local_pref
12156 );
12157 json_object_int_add(
12158 json, "localAS",
12159 bgp->as);
924c3f6a
DS
12160 json_object_object_add(
12161 json,
12162 "bgpStatusCodes",
12163 json_scode);
12164 json_object_object_add(
12165 json,
12166 "bgpOriginCodes",
12167 json_ocode);
12168 } else {
12169 vty_out(vty,
12170 "BGP table version is %" PRIu64
9df8b37c 12171 ", local router ID is %s, vrf id ",
924c3f6a
DS
12172 table->version,
12173 inet_ntoa(
12174 bgp->router_id));
9df8b37c
PZ
12175 if (bgp->vrf_id ==
12176 VRF_UNKNOWN)
12177 vty_out(vty,
12178 "%s",
12179 VRFID_NONE_STR);
12180 else
12181 vty_out(vty,
12182 "%u",
12183 bgp->vrf_id);
12184 vty_out(vty, "\n");
01eced22
AD
12185 vty_out(vty,
12186 "Default local pref %u, ",
12187 bgp->default_local_pref
12188 );
12189 vty_out(vty,
12190 "local AS %u\n",
12191 bgp->as);
924c3f6a
DS
12192 vty_out(vty,
12193 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
12194 vty_out(vty,
12195 BGP_SHOW_NCODE_HEADER);
924c3f6a
DS
12196 vty_out(vty,
12197 BGP_SHOW_OCODE_HEADER);
a2addae8 12198 }
924c3f6a
DS
12199 header1 = 0;
12200 }
924c3f6a
DS
12201 if (header2) {
12202 if (!use_json)
12203 vty_out(vty,
12204 BGP_SHOW_HEADER);
12205 header2 = 0;
12206 }
d62a17ae 12207
b54892e0 12208 const struct prefix *rn_p =
9bcb3eef 12209 bgp_dest_get_prefix(dest);
b54892e0 12210
6f4f49b2 12211 attr = *adj->attr;
b755861b 12212 ret = bgp_output_modifier(
b54892e0 12213 peer, rn_p, &attr, afi, safi,
b755861b 12214 rmap_name);
f46d8e1e 12215
b755861b 12216 if (ret != RMAP_DENY) {
b54892e0
DS
12217 route_vty_out_tmp(
12218 vty, rn_p, &attr, safi,
12219 use_json, json_ar);
b755861b
PM
12220 output_count++;
12221 } else {
12222 filtered_count++;
a2addae8 12223 }
b755861b
PM
12224
12225 bgp_attr_undup(&attr, adj->attr);
924c3f6a 12226 }
d62a17ae 12227 }
12228 }
d62a17ae 12229
d62a17ae 12230 if (use_json) {
6392aaa6
PM
12231 json_object_object_add(json, "advertisedRoutes", json_ar);
12232 json_object_int_add(json, "totalPrefixCounter", output_count);
12233 json_object_int_add(json, "filteredPrefixCounter",
12234 filtered_count);
12235
996c9314
LB
12236 vty_out(vty, "%s\n", json_object_to_json_string_ext(
12237 json, JSON_C_TO_STRING_PRETTY));
74a630b6
NT
12238
12239 if (!output_count && !filtered_count) {
12240 json_object_free(json_scode);
12241 json_object_free(json_ocode);
12242 }
12243
d62a17ae 12244 json_object_free(json);
6392aaa6
PM
12245 } else if (output_count > 0) {
12246 if (filtered_count > 0)
12247 vty_out(vty,
12248 "\nTotal number of prefixes %ld (%ld filtered)\n",
12249 output_count, filtered_count);
12250 else
12251 vty_out(vty, "\nTotal number of prefixes %ld\n",
12252 output_count);
d62a17ae 12253 }
a636c635 12254}
2a71e9ce 12255
d62a17ae 12256static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 12257 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 12258 const char *rmap_name, bool use_json)
0b16f239 12259{
d62a17ae 12260 json_object *json = NULL;
0b16f239 12261
d62a17ae 12262 if (use_json)
12263 json = json_object_new_object();
0b16f239 12264
d62a17ae 12265 if (!peer || !peer->afc[afi][safi]) {
12266 if (use_json) {
12267 json_object_string_add(
12268 json, "warning",
12269 "No such neighbor or address family");
12270 vty_out(vty, "%s\n", json_object_to_json_string(json));
12271 json_object_free(json);
12272 } else
12273 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 12274
d62a17ae 12275 return CMD_WARNING;
12276 }
12277
6392aaa6
PM
12278 if ((type == bgp_show_adj_route_received
12279 || type == bgp_show_adj_route_filtered)
d62a17ae 12280 && !CHECK_FLAG(peer->af_flags[afi][safi],
12281 PEER_FLAG_SOFT_RECONFIG)) {
12282 if (use_json) {
12283 json_object_string_add(
12284 json, "warning",
12285 "Inbound soft reconfiguration not enabled");
12286 vty_out(vty, "%s\n", json_object_to_json_string(json));
12287 json_object_free(json);
12288 } else
12289 vty_out(vty,
12290 "%% Inbound soft reconfiguration not enabled\n");
12291
12292 return CMD_WARNING;
12293 }
0b16f239 12294
6392aaa6 12295 show_adj_route(vty, peer, afi, safi, type, rmap_name, use_json, json);
0b16f239 12296
d62a17ae 12297 return CMD_SUCCESS;
a636c635 12298}
50ef26d4 12299
a636c635
DW
12300DEFUN (show_ip_bgp_instance_neighbor_advertised_route,
12301 show_ip_bgp_instance_neighbor_advertised_route_cmd,
3efd0893 12302 "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> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
718e3744 12303 SHOW_STR
12304 IP_STR
12305 BGP_STR
a636c635 12306 BGP_INSTANCE_HELP_STR
7395a2c9 12307 BGP_AFI_HELP_STR
4dd6177e 12308 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 12309 "Detailed information on TCP and BGP neighbor connections\n"
12310 "Neighbor to display information about\n"
12311 "Neighbor to display information about\n"
91d37724 12312 "Neighbor on BGP configured interface\n"
a636c635 12313 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
12314 "Display the received routes from neighbor\n"
12315 "Display the filtered routes received from neighbor\n"
a636c635
DW
12316 "Route-map to modify the attributes\n"
12317 "Name of the route map\n"
9973d184 12318 JSON_STR)
718e3744 12319{
d62a17ae 12320 afi_t afi = AFI_IP6;
12321 safi_t safi = SAFI_UNICAST;
12322 char *rmap_name = NULL;
12323 char *peerstr = NULL;
d62a17ae 12324 struct bgp *bgp = NULL;
12325 struct peer *peer;
6392aaa6 12326 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 12327 int idx = 0;
9f049418 12328 bool uj = use_json(argc, argv);
6392aaa6 12329
d62a17ae 12330 if (uj)
12331 argc--;
30a6a167 12332
9f049418
DS
12333 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12334 &bgp, uj);
12335 if (!idx)
12336 return CMD_WARNING;
12337
d62a17ae 12338 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12339 argv_find(argv, argc, "neighbors", &idx);
12340 peerstr = argv[++idx]->arg;
8c3deaae 12341
d62a17ae 12342 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
12343 if (!peer)
12344 return CMD_WARNING;
856ca177 12345
d62a17ae 12346 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
12347 type = bgp_show_adj_route_advertised;
12348 else if (argv_find(argv, argc, "received-routes", &idx))
12349 type = bgp_show_adj_route_received;
12350 else if (argv_find(argv, argc, "filtered-routes", &idx))
12351 type = bgp_show_adj_route_filtered;
12352
d62a17ae 12353 if (argv_find(argv, argc, "route-map", &idx))
12354 rmap_name = argv[++idx]->arg;
95cbbd2a 12355
6392aaa6 12356 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj);
95cbbd2a
ML
12357}
12358
718e3744 12359DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
12360 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 12361 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 12362 SHOW_STR
12363 IP_STR
12364 BGP_STR
8c3deaae
QY
12365 "Address Family\n"
12366 "Address Family\n"
718e3744 12367 "Address Family modifier\n"
12368 "Detailed information on TCP and BGP neighbor connections\n"
12369 "Neighbor to display information about\n"
12370 "Neighbor to display information about\n"
91d37724 12371 "Neighbor on BGP configured interface\n"
718e3744 12372 "Display information received from a BGP neighbor\n"
856ca177 12373 "Display the prefixlist filter\n"
9973d184 12374 JSON_STR)
718e3744 12375{
d62a17ae 12376 afi_t afi = AFI_IP6;
12377 safi_t safi = SAFI_UNICAST;
12378 char *peerstr = NULL;
12379
12380 char name[BUFSIZ];
12381 union sockunion su;
12382 struct peer *peer;
12383 int count, ret;
12384
12385 int idx = 0;
12386
12387 /* show [ip] bgp */
12388 if (argv_find(argv, argc, "ip", &idx))
12389 afi = AFI_IP;
12390 /* [<ipv4|ipv6> [unicast]] */
12391 if (argv_find(argv, argc, "ipv4", &idx))
12392 afi = AFI_IP;
12393 if (argv_find(argv, argc, "ipv6", &idx))
12394 afi = AFI_IP6;
12395 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12396 argv_find(argv, argc, "neighbors", &idx);
12397 peerstr = argv[++idx]->arg;
12398
9f049418 12399 bool uj = use_json(argc, argv);
d62a17ae 12400
12401 ret = str2sockunion(peerstr, &su);
12402 if (ret < 0) {
12403 peer = peer_lookup_by_conf_if(NULL, peerstr);
12404 if (!peer) {
12405 if (uj)
12406 vty_out(vty, "{}\n");
12407 else
12408 vty_out(vty,
12409 "%% Malformed address or name: %s\n",
12410 peerstr);
12411 return CMD_WARNING;
12412 }
12413 } else {
12414 peer = peer_lookup(NULL, &su);
12415 if (!peer) {
12416 if (uj)
12417 vty_out(vty, "{}\n");
12418 else
12419 vty_out(vty, "No peer\n");
12420 return CMD_WARNING;
12421 }
12422 }
718e3744 12423
4ced1a2c 12424 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 12425 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
12426 if (count) {
12427 if (!uj)
12428 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 12429 get_afi_safi_str(afi, safi, false));
d62a17ae 12430 prefix_bgp_show_prefix_list(vty, afi, name, uj);
12431 } else {
12432 if (uj)
12433 vty_out(vty, "{}\n");
12434 else
12435 vty_out(vty, "No functional output\n");
12436 }
718e3744 12437
d62a17ae 12438 return CMD_SUCCESS;
12439}
12440
12441static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
12442 afi_t afi, safi_t safi,
9f049418 12443 enum bgp_show_type type, bool use_json)
d62a17ae 12444{
8a893163
DW
12445 /* labeled-unicast routes live in the unicast table */
12446 if (safi == SAFI_LABELED_UNICAST)
12447 safi = SAFI_UNICAST;
12448
d62a17ae 12449 if (!peer || !peer->afc[afi][safi]) {
12450 if (use_json) {
12451 json_object *json_no = NULL;
12452 json_no = json_object_new_object();
12453 json_object_string_add(
12454 json_no, "warning",
12455 "No such neighbor or address family");
12456 vty_out(vty, "%s\n",
12457 json_object_to_json_string(json_no));
12458 json_object_free(json_no);
12459 } else
12460 vty_out(vty, "%% No such neighbor or address family\n");
12461 return CMD_WARNING;
12462 }
47fc97cc 12463
d62a17ae 12464 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json);
718e3744 12465}
12466
dba3c1d3
PG
12467DEFUN (show_ip_bgp_flowspec_routes_detailed,
12468 show_ip_bgp_flowspec_routes_detailed_cmd,
12469 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
12470 SHOW_STR
12471 IP_STR
12472 BGP_STR
12473 BGP_INSTANCE_HELP_STR
12474 BGP_AFI_HELP_STR
12475 "SAFI Flowspec\n"
12476 "Detailed information on flowspec entries\n"
12477 JSON_STR)
12478{
12479 afi_t afi = AFI_IP;
12480 safi_t safi = SAFI_UNICAST;
12481 struct bgp *bgp = NULL;
12482 int idx = 0;
9f049418
DS
12483 bool uj = use_json(argc, argv);
12484
12485 if (uj)
12486 argc--;
dba3c1d3
PG
12487
12488 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12489 &bgp, uj);
dba3c1d3
PG
12490 if (!idx)
12491 return CMD_WARNING;
12492
9f049418 12493 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL, uj);
dba3c1d3
PG
12494}
12495
718e3744 12496DEFUN (show_ip_bgp_neighbor_routes,
12497 show_ip_bgp_neighbor_routes_cmd,
3efd0893 12498 "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 12499 SHOW_STR
12500 IP_STR
12501 BGP_STR
8386ac43 12502 BGP_INSTANCE_HELP_STR
4f280b15 12503 BGP_AFI_HELP_STR
4dd6177e 12504 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 12505 "Detailed information on TCP and BGP neighbor connections\n"
12506 "Neighbor to display information about\n"
12507 "Neighbor to display information about\n"
91d37724 12508 "Neighbor on BGP configured interface\n"
2525cf39 12509 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
12510 "Display the dampened routes received from neighbor\n"
12511 "Display routes learned from neighbor\n"
9973d184 12512 JSON_STR)
718e3744 12513{
d62a17ae 12514 char *peerstr = NULL;
12515 struct bgp *bgp = NULL;
12516 afi_t afi = AFI_IP6;
12517 safi_t safi = SAFI_UNICAST;
12518 struct peer *peer;
12519 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 12520 int idx = 0;
9f049418
DS
12521 bool uj = use_json(argc, argv);
12522
12523 if (uj)
12524 argc--;
bb46e94f 12525
d62a17ae 12526 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12527 &bgp, uj);
d62a17ae 12528 if (!idx)
12529 return CMD_WARNING;
c493f2d8 12530
d62a17ae 12531 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12532 argv_find(argv, argc, "neighbors", &idx);
12533 peerstr = argv[++idx]->arg;
8c3deaae 12534
d62a17ae 12535 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 12536 if (!peer)
d62a17ae 12537 return CMD_WARNING;
bb46e94f 12538
d62a17ae 12539 if (argv_find(argv, argc, "flap-statistics", &idx))
12540 sh_type = bgp_show_type_flap_neighbor;
12541 else if (argv_find(argv, argc, "dampened-routes", &idx))
12542 sh_type = bgp_show_type_damp_neighbor;
12543 else if (argv_find(argv, argc, "routes", &idx))
12544 sh_type = bgp_show_type_neighbor;
2525cf39 12545
d62a17ae 12546 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 12547}
6b0655a2 12548
734b349e 12549struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 12550
d62a17ae 12551struct bgp_distance {
12552 /* Distance value for the IP source prefix. */
d7c0a89a 12553 uint8_t distance;
718e3744 12554
d62a17ae 12555 /* Name of the access-list to be matched. */
12556 char *access_list;
718e3744 12557};
12558
4f280b15
LB
12559DEFUN (show_bgp_afi_vpn_rd_route,
12560 show_bgp_afi_vpn_rd_route_cmd,
d114b977 12561 "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
12562 SHOW_STR
12563 BGP_STR
12564 BGP_AFI_HELP_STR
12565 "Address Family modifier\n"
12566 "Display information for a route distinguisher\n"
12567 "Route Distinguisher\n"
7395a2c9
DS
12568 "Network in the BGP routing table to display\n"
12569 "Network in the BGP routing table to display\n"
12570 JSON_STR)
4f280b15 12571{
d62a17ae 12572 int ret;
12573 struct prefix_rd prd;
12574 afi_t afi = AFI_MAX;
12575 int idx = 0;
4f280b15 12576
ff6566f3
DS
12577 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
12578 vty_out(vty, "%% Malformed Address Family\n");
12579 return CMD_WARNING;
12580 }
12581
d62a17ae 12582 ret = str2prefix_rd(argv[5]->arg, &prd);
12583 if (!ret) {
12584 vty_out(vty, "%% Malformed Route Distinguisher\n");
12585 return CMD_WARNING;
12586 }
ff6566f3 12587
d62a17ae 12588 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 12589 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
12590}
12591
d62a17ae 12592static struct bgp_distance *bgp_distance_new(void)
718e3744 12593{
d62a17ae 12594 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 12595}
12596
d62a17ae 12597static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 12598{
d62a17ae 12599 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 12600}
12601
d62a17ae 12602static int bgp_distance_set(struct vty *vty, const char *distance_str,
12603 const char *ip_str, const char *access_list_str)
718e3744 12604{
d62a17ae 12605 int ret;
12606 afi_t afi;
12607 safi_t safi;
12608 struct prefix p;
d7c0a89a 12609 uint8_t distance;
9bcb3eef 12610 struct bgp_dest *dest;
d62a17ae 12611 struct bgp_distance *bdistance;
718e3744 12612
d62a17ae 12613 afi = bgp_node_afi(vty);
12614 safi = bgp_node_safi(vty);
734b349e 12615
d62a17ae 12616 ret = str2prefix(ip_str, &p);
12617 if (ret == 0) {
12618 vty_out(vty, "Malformed prefix\n");
12619 return CMD_WARNING_CONFIG_FAILED;
12620 }
718e3744 12621
d62a17ae 12622 distance = atoi(distance_str);
718e3744 12623
d62a17ae 12624 /* Get BGP distance node. */
9bcb3eef
DS
12625 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
12626 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 12627 if (bdistance)
9bcb3eef 12628 bgp_dest_unlock_node(dest);
ca2e160d 12629 else {
d62a17ae 12630 bdistance = bgp_distance_new();
9bcb3eef 12631 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 12632 }
718e3744 12633
d62a17ae 12634 /* Set distance value. */
12635 bdistance->distance = distance;
718e3744 12636
d62a17ae 12637 /* Reset access-list configuration. */
e1b36e13 12638 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 12639 if (access_list_str)
12640 bdistance->access_list =
12641 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 12642
d62a17ae 12643 return CMD_SUCCESS;
718e3744 12644}
12645
d62a17ae 12646static int bgp_distance_unset(struct vty *vty, const char *distance_str,
12647 const char *ip_str, const char *access_list_str)
718e3744 12648{
d62a17ae 12649 int ret;
12650 afi_t afi;
12651 safi_t safi;
12652 struct prefix p;
12653 int distance;
9bcb3eef 12654 struct bgp_dest *dest;
d62a17ae 12655 struct bgp_distance *bdistance;
718e3744 12656
d62a17ae 12657 afi = bgp_node_afi(vty);
12658 safi = bgp_node_safi(vty);
734b349e 12659
d62a17ae 12660 ret = str2prefix(ip_str, &p);
12661 if (ret == 0) {
12662 vty_out(vty, "Malformed prefix\n");
12663 return CMD_WARNING_CONFIG_FAILED;
12664 }
718e3744 12665
9bcb3eef
DS
12666 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
12667 if (!dest) {
d62a17ae 12668 vty_out(vty, "Can't find specified prefix\n");
12669 return CMD_WARNING_CONFIG_FAILED;
12670 }
718e3744 12671
9bcb3eef 12672 bdistance = bgp_dest_get_bgp_distance_info(dest);
d62a17ae 12673 distance = atoi(distance_str);
1f9a9fff 12674
d62a17ae 12675 if (bdistance->distance != distance) {
12676 vty_out(vty, "Distance does not match configured\n");
12677 return CMD_WARNING_CONFIG_FAILED;
12678 }
718e3744 12679
0a22ddfb 12680 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 12681 bgp_distance_free(bdistance);
718e3744 12682
9bcb3eef
DS
12683 bgp_dest_set_bgp_path_info(dest, NULL);
12684 bgp_dest_unlock_node(dest);
12685 bgp_dest_unlock_node(dest);
718e3744 12686
d62a17ae 12687 return CMD_SUCCESS;
718e3744 12688}
12689
718e3744 12690/* Apply BGP information to distance method. */
b8685f9b 12691uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 12692 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 12693{
9bcb3eef 12694 struct bgp_dest *dest;
d62a17ae 12695 struct prefix q;
12696 struct peer *peer;
12697 struct bgp_distance *bdistance;
12698 struct access_list *alist;
12699 struct bgp_static *bgp_static;
12700
12701 if (!bgp)
12702 return 0;
12703
40381db7 12704 peer = pinfo->peer;
d62a17ae 12705
7b7d48e5
DS
12706 if (pinfo->attr->distance)
12707 return pinfo->attr->distance;
12708
d62a17ae 12709 /* Check source address. */
12710 sockunion2hostprefix(&peer->su, &q);
9bcb3eef
DS
12711 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
12712 if (dest) {
12713 bdistance = bgp_dest_get_bgp_distance_info(dest);
12714 bgp_dest_unlock_node(dest);
d62a17ae 12715
12716 if (bdistance->access_list) {
12717 alist = access_list_lookup(afi, bdistance->access_list);
12718 if (alist
12719 && access_list_apply(alist, p) == FILTER_PERMIT)
12720 return bdistance->distance;
12721 } else
12722 return bdistance->distance;
718e3744 12723 }
718e3744 12724
d62a17ae 12725 /* Backdoor check. */
9bcb3eef
DS
12726 dest = bgp_node_lookup(bgp->route[afi][safi], p);
12727 if (dest) {
12728 bgp_static = bgp_dest_get_bgp_static_info(dest);
12729 bgp_dest_unlock_node(dest);
718e3744 12730
d62a17ae 12731 if (bgp_static->backdoor) {
12732 if (bgp->distance_local[afi][safi])
12733 return bgp->distance_local[afi][safi];
12734 else
12735 return ZEBRA_IBGP_DISTANCE_DEFAULT;
12736 }
718e3744 12737 }
718e3744 12738
d62a17ae 12739 if (peer->sort == BGP_PEER_EBGP) {
12740 if (bgp->distance_ebgp[afi][safi])
12741 return bgp->distance_ebgp[afi][safi];
12742 return ZEBRA_EBGP_DISTANCE_DEFAULT;
12743 } else {
12744 if (bgp->distance_ibgp[afi][safi])
12745 return bgp->distance_ibgp[afi][safi];
12746 return ZEBRA_IBGP_DISTANCE_DEFAULT;
12747 }
718e3744 12748}
12749
a612fb77
DA
12750/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
12751 * we should tell ZEBRA update the routes for a specific
12752 * AFI/SAFI to reflect changes in RIB.
12753 */
8b54bc30
DA
12754static void bgp_announce_routes_distance_update(struct bgp *bgp,
12755 afi_t update_afi,
12756 safi_t update_safi)
a612fb77
DA
12757{
12758 afi_t afi;
12759 safi_t safi;
12760
12761 FOREACH_AFI_SAFI (afi, safi) {
12762 if (!bgp_fibupd_safi(safi))
12763 continue;
12764
8b54bc30
DA
12765 if (afi != update_afi && safi != update_safi)
12766 continue;
12767
12768 if (BGP_DEBUG(zebra, ZEBRA))
12769 zlog_debug(
12770 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
12771 __func__, afi, safi);
12772 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
12773 }
12774}
12775
718e3744 12776DEFUN (bgp_distance,
12777 bgp_distance_cmd,
6147e2c6 12778 "distance bgp (1-255) (1-255) (1-255)",
718e3744 12779 "Define an administrative distance\n"
12780 "BGP distance\n"
12781 "Distance for routes external to the AS\n"
12782 "Distance for routes internal to the AS\n"
12783 "Distance for local routes\n")
12784{
d62a17ae 12785 VTY_DECLVAR_CONTEXT(bgp, bgp);
12786 int idx_number = 2;
12787 int idx_number_2 = 3;
12788 int idx_number_3 = 4;
8b54bc30
DA
12789 int distance_ebgp = atoi(argv[idx_number]->arg);
12790 int distance_ibgp = atoi(argv[idx_number_2]->arg);
12791 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 12792 afi_t afi;
12793 safi_t safi;
718e3744 12794
d62a17ae 12795 afi = bgp_node_afi(vty);
12796 safi = bgp_node_safi(vty);
718e3744 12797
8b54bc30
DA
12798 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
12799 || bgp->distance_ibgp[afi][safi] != distance_ibgp
12800 || bgp->distance_local[afi][safi] != distance_local) {
12801 bgp->distance_ebgp[afi][safi] = distance_ebgp;
12802 bgp->distance_ibgp[afi][safi] = distance_ibgp;
12803 bgp->distance_local[afi][safi] = distance_local;
12804 bgp_announce_routes_distance_update(bgp, afi, safi);
12805 }
d62a17ae 12806 return CMD_SUCCESS;
718e3744 12807}
12808
12809DEFUN (no_bgp_distance,
12810 no_bgp_distance_cmd,
a636c635 12811 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 12812 NO_STR
12813 "Define an administrative distance\n"
12814 "BGP distance\n"
12815 "Distance for routes external to the AS\n"
12816 "Distance for routes internal to the AS\n"
12817 "Distance for local routes\n")
12818{
d62a17ae 12819 VTY_DECLVAR_CONTEXT(bgp, bgp);
12820 afi_t afi;
12821 safi_t safi;
718e3744 12822
d62a17ae 12823 afi = bgp_node_afi(vty);
12824 safi = bgp_node_safi(vty);
718e3744 12825
8b54bc30
DA
12826 if (bgp->distance_ebgp[afi][safi] != 0
12827 || bgp->distance_ibgp[afi][safi] != 0
12828 || bgp->distance_local[afi][safi] != 0) {
12829 bgp->distance_ebgp[afi][safi] = 0;
12830 bgp->distance_ibgp[afi][safi] = 0;
12831 bgp->distance_local[afi][safi] = 0;
12832 bgp_announce_routes_distance_update(bgp, afi, safi);
12833 }
d62a17ae 12834 return CMD_SUCCESS;
718e3744 12835}
12836
718e3744 12837
12838DEFUN (bgp_distance_source,
12839 bgp_distance_source_cmd,
6147e2c6 12840 "distance (1-255) A.B.C.D/M",
718e3744 12841 "Define an administrative distance\n"
12842 "Administrative distance\n"
12843 "IP source prefix\n")
12844{
d62a17ae 12845 int idx_number = 1;
12846 int idx_ipv4_prefixlen = 2;
12847 bgp_distance_set(vty, argv[idx_number]->arg,
12848 argv[idx_ipv4_prefixlen]->arg, NULL);
12849 return CMD_SUCCESS;
718e3744 12850}
12851
12852DEFUN (no_bgp_distance_source,
12853 no_bgp_distance_source_cmd,
6147e2c6 12854 "no distance (1-255) A.B.C.D/M",
718e3744 12855 NO_STR
12856 "Define an administrative distance\n"
12857 "Administrative distance\n"
12858 "IP source prefix\n")
12859{
d62a17ae 12860 int idx_number = 2;
12861 int idx_ipv4_prefixlen = 3;
12862 bgp_distance_unset(vty, argv[idx_number]->arg,
12863 argv[idx_ipv4_prefixlen]->arg, NULL);
12864 return CMD_SUCCESS;
718e3744 12865}
12866
12867DEFUN (bgp_distance_source_access_list,
12868 bgp_distance_source_access_list_cmd,
6147e2c6 12869 "distance (1-255) A.B.C.D/M WORD",
718e3744 12870 "Define an administrative distance\n"
12871 "Administrative distance\n"
12872 "IP source prefix\n"
12873 "Access list name\n")
12874{
d62a17ae 12875 int idx_number = 1;
12876 int idx_ipv4_prefixlen = 2;
12877 int idx_word = 3;
12878 bgp_distance_set(vty, argv[idx_number]->arg,
12879 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12880 return CMD_SUCCESS;
718e3744 12881}
12882
12883DEFUN (no_bgp_distance_source_access_list,
12884 no_bgp_distance_source_access_list_cmd,
6147e2c6 12885 "no distance (1-255) A.B.C.D/M WORD",
718e3744 12886 NO_STR
12887 "Define an administrative distance\n"
12888 "Administrative distance\n"
12889 "IP source prefix\n"
12890 "Access list name\n")
12891{
d62a17ae 12892 int idx_number = 2;
12893 int idx_ipv4_prefixlen = 3;
12894 int idx_word = 4;
12895 bgp_distance_unset(vty, argv[idx_number]->arg,
12896 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12897 return CMD_SUCCESS;
718e3744 12898}
6b0655a2 12899
734b349e
MZ
12900DEFUN (ipv6_bgp_distance_source,
12901 ipv6_bgp_distance_source_cmd,
39e92c06 12902 "distance (1-255) X:X::X:X/M",
734b349e
MZ
12903 "Define an administrative distance\n"
12904 "Administrative distance\n"
12905 "IP source prefix\n")
12906{
d62a17ae 12907 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
12908 return CMD_SUCCESS;
734b349e
MZ
12909}
12910
12911DEFUN (no_ipv6_bgp_distance_source,
12912 no_ipv6_bgp_distance_source_cmd,
39e92c06 12913 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
12914 NO_STR
12915 "Define an administrative distance\n"
12916 "Administrative distance\n"
12917 "IP source prefix\n")
12918{
d62a17ae 12919 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
12920 return CMD_SUCCESS;
734b349e
MZ
12921}
12922
12923DEFUN (ipv6_bgp_distance_source_access_list,
12924 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12925 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12926 "Define an administrative distance\n"
12927 "Administrative distance\n"
12928 "IP source prefix\n"
12929 "Access list name\n")
12930{
d62a17ae 12931 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
12932 return CMD_SUCCESS;
734b349e
MZ
12933}
12934
12935DEFUN (no_ipv6_bgp_distance_source_access_list,
12936 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12937 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12938 NO_STR
12939 "Define an administrative distance\n"
12940 "Administrative distance\n"
12941 "IP source prefix\n"
12942 "Access list name\n")
12943{
d62a17ae 12944 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
12945 return CMD_SUCCESS;
734b349e
MZ
12946}
12947
718e3744 12948DEFUN (bgp_damp_set,
12949 bgp_damp_set_cmd,
31500417 12950 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 12951 "BGP Specific commands\n"
12952 "Enable route-flap dampening\n"
12953 "Half-life time for the penalty\n"
12954 "Value to start reusing a route\n"
12955 "Value to start suppressing a route\n"
12956 "Maximum duration to suppress a stable route\n")
12957{
d62a17ae 12958 VTY_DECLVAR_CONTEXT(bgp, bgp);
12959 int idx_half_life = 2;
12960 int idx_reuse = 3;
12961 int idx_suppress = 4;
12962 int idx_max_suppress = 5;
12963 int half = DEFAULT_HALF_LIFE * 60;
12964 int reuse = DEFAULT_REUSE;
12965 int suppress = DEFAULT_SUPPRESS;
12966 int max = 4 * half;
12967
12968 if (argc == 6) {
12969 half = atoi(argv[idx_half_life]->arg) * 60;
12970 reuse = atoi(argv[idx_reuse]->arg);
12971 suppress = atoi(argv[idx_suppress]->arg);
12972 max = atoi(argv[idx_max_suppress]->arg) * 60;
12973 } else if (argc == 3) {
12974 half = atoi(argv[idx_half_life]->arg) * 60;
12975 max = 4 * half;
12976 }
718e3744 12977
6d24b7cc
DS
12978 /*
12979 * These can't be 0 but our SA doesn't understand the
12980 * way our cli is constructed
12981 */
12982 assert(reuse);
12983 assert(half);
d62a17ae 12984 if (suppress < reuse) {
12985 vty_out(vty,
12986 "Suppress value cannot be less than reuse value \n");
12987 return 0;
12988 }
7ebe9748 12989
d62a17ae 12990 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
12991 reuse, suppress, max);
718e3744 12992}
12993
718e3744 12994DEFUN (bgp_damp_unset,
12995 bgp_damp_unset_cmd,
d04c479d 12996 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 12997 NO_STR
12998 "BGP Specific commands\n"
16cedbb0
QY
12999 "Enable route-flap dampening\n"
13000 "Half-life time for the penalty\n"
13001 "Value to start reusing a route\n"
13002 "Value to start suppressing a route\n"
13003 "Maximum duration to suppress a stable route\n")
718e3744 13004{
d62a17ae 13005 VTY_DECLVAR_CONTEXT(bgp, bgp);
13006 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 13007}
13008
718e3744 13009/* Display specified route of BGP table. */
d62a17ae 13010static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
13011 const char *ip_str, afi_t afi, safi_t safi,
13012 struct prefix_rd *prd, int prefix_check)
13013{
13014 int ret;
13015 struct prefix match;
9bcb3eef
DS
13016 struct bgp_dest *dest;
13017 struct bgp_dest *rm;
40381db7
DS
13018 struct bgp_path_info *pi;
13019 struct bgp_path_info *pi_temp;
d62a17ae 13020 struct bgp *bgp;
13021 struct bgp_table *table;
13022
13023 /* BGP structure lookup. */
13024 if (view_name) {
13025 bgp = bgp_lookup_by_name(view_name);
13026 if (bgp == NULL) {
13027 vty_out(vty, "%% Can't find BGP instance %s\n",
13028 view_name);
13029 return CMD_WARNING;
13030 }
13031 } else {
13032 bgp = bgp_get_default();
13033 if (bgp == NULL) {
13034 vty_out(vty, "%% No BGP process is configured\n");
13035 return CMD_WARNING;
13036 }
718e3744 13037 }
718e3744 13038
d62a17ae 13039 /* Check IP address argument. */
13040 ret = str2prefix(ip_str, &match);
13041 if (!ret) {
13042 vty_out(vty, "%% address is malformed\n");
13043 return CMD_WARNING;
13044 }
718e3744 13045
d62a17ae 13046 match.family = afi2family(afi);
13047
13048 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13049 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
13050 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
13051 dest = bgp_route_next(dest)) {
13052 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 13053
9bcb3eef 13054 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 13055 continue;
9bcb3eef 13056 table = bgp_dest_get_bgp_table_info(dest);
67009e22 13057 if (!table)
ea47320b
DL
13058 continue;
13059 if ((rm = bgp_node_match(table, &match)) == NULL)
13060 continue;
d62a17ae 13061
9bcb3eef 13062 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 13063
ea47320b 13064 if (!prefix_check
b54892e0 13065 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 13066 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
13067 while (pi) {
13068 if (pi->extra && pi->extra->damp_info) {
13069 pi_temp = pi->next;
ea47320b 13070 bgp_damp_info_free(
40381db7 13071 pi->extra->damp_info,
a935f597 13072 1, afi, safi);
40381db7 13073 pi = pi_temp;
ea47320b 13074 } else
40381db7 13075 pi = pi->next;
d62a17ae 13076 }
ea47320b
DL
13077 }
13078
9bcb3eef 13079 bgp_dest_unlock_node(rm);
d62a17ae 13080 }
13081 } else {
9bcb3eef 13082 if ((dest = bgp_node_match(bgp->rib[afi][safi], &match))
d62a17ae 13083 != NULL) {
9bcb3eef 13084 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 13085
d62a17ae 13086 if (!prefix_check
9bcb3eef
DS
13087 || dest_p->prefixlen == match.prefixlen) {
13088 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
13089 while (pi) {
13090 if (pi->extra && pi->extra->damp_info) {
13091 pi_temp = pi->next;
d62a17ae 13092 bgp_damp_info_free(
40381db7 13093 pi->extra->damp_info,
a935f597 13094 1, afi, safi);
40381db7 13095 pi = pi_temp;
d62a17ae 13096 } else
40381db7 13097 pi = pi->next;
d62a17ae 13098 }
13099 }
13100
9bcb3eef 13101 bgp_dest_unlock_node(dest);
d62a17ae 13102 }
13103 }
718e3744 13104
d62a17ae 13105 return CMD_SUCCESS;
718e3744 13106}
13107
13108DEFUN (clear_ip_bgp_dampening,
13109 clear_ip_bgp_dampening_cmd,
13110 "clear ip bgp dampening",
13111 CLEAR_STR
13112 IP_STR
13113 BGP_STR
13114 "Clear route flap dampening information\n")
13115{
a935f597 13116 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 13117 return CMD_SUCCESS;
718e3744 13118}
13119
13120DEFUN (clear_ip_bgp_dampening_prefix,
13121 clear_ip_bgp_dampening_prefix_cmd,
13122 "clear ip bgp dampening A.B.C.D/M",
13123 CLEAR_STR
13124 IP_STR
13125 BGP_STR
13126 "Clear route flap dampening information\n"
0c7b1b01 13127 "IPv4 prefix\n")
718e3744 13128{
d62a17ae 13129 int idx_ipv4_prefixlen = 4;
13130 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
13131 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 13132}
13133
13134DEFUN (clear_ip_bgp_dampening_address,
13135 clear_ip_bgp_dampening_address_cmd,
13136 "clear ip bgp dampening A.B.C.D",
13137 CLEAR_STR
13138 IP_STR
13139 BGP_STR
13140 "Clear route flap dampening information\n"
13141 "Network to clear damping information\n")
13142{
d62a17ae 13143 int idx_ipv4 = 4;
13144 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
13145 SAFI_UNICAST, NULL, 0);
718e3744 13146}
13147
13148DEFUN (clear_ip_bgp_dampening_address_mask,
13149 clear_ip_bgp_dampening_address_mask_cmd,
13150 "clear ip bgp dampening A.B.C.D A.B.C.D",
13151 CLEAR_STR
13152 IP_STR
13153 BGP_STR
13154 "Clear route flap dampening information\n"
13155 "Network to clear damping information\n"
13156 "Network mask\n")
13157{
d62a17ae 13158 int idx_ipv4 = 4;
13159 int idx_ipv4_2 = 5;
13160 int ret;
13161 char prefix_str[BUFSIZ];
718e3744 13162
d62a17ae 13163 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
13164 prefix_str);
13165 if (!ret) {
13166 vty_out(vty, "%% Inconsistent address and mask\n");
13167 return CMD_WARNING;
13168 }
718e3744 13169
d62a17ae 13170 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
13171 NULL, 0);
718e3744 13172}
6b0655a2 13173
e3b78da8 13174static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
13175{
13176 struct vty *vty = arg;
e3b78da8 13177 struct peer *peer = bucket->data;
825d9834
DS
13178 char buf[SU_ADDRSTRLEN];
13179
13180 vty_out(vty, "\tPeer: %s %s\n", peer->host,
13181 sockunion2str(&peer->su, buf, sizeof(buf)));
13182}
13183
2a0e69ae
DS
13184DEFUN (show_bgp_listeners,
13185 show_bgp_listeners_cmd,
13186 "show bgp listeners",
13187 SHOW_STR
13188 BGP_STR
13189 "Display Listen Sockets and who created them\n")
13190{
13191 bgp_dump_listener_info(vty);
13192
13193 return CMD_SUCCESS;
13194}
13195
825d9834
DS
13196DEFUN (show_bgp_peerhash,
13197 show_bgp_peerhash_cmd,
13198 "show bgp peerhash",
13199 SHOW_STR
13200 BGP_STR
13201 "Display information about the BGP peerhash\n")
13202{
13203 struct list *instances = bm->bgp;
13204 struct listnode *node;
13205 struct bgp *bgp;
13206
13207 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
13208 vty_out(vty, "BGP: %s\n", bgp->name);
13209 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
13210 vty);
13211 }
13212
13213 return CMD_SUCCESS;
13214}
13215
587ff0fd 13216/* also used for encap safi */
2b791107
DL
13217static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
13218 afi_t afi, safi_t safi)
d62a17ae 13219{
9bcb3eef
DS
13220 struct bgp_dest *pdest;
13221 struct bgp_dest *dest;
d62a17ae 13222 struct bgp_table *table;
b54892e0
DS
13223 const struct prefix *p;
13224 const struct prefix_rd *prd;
d62a17ae 13225 struct bgp_static *bgp_static;
13226 mpls_label_t label;
13227 char buf[SU_ADDRSTRLEN];
13228 char rdbuf[RD_ADDRSTRLEN];
13229
13230 /* Network configuration. */
9bcb3eef
DS
13231 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
13232 pdest = bgp_route_next(pdest)) {
13233 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 13234 if (!table)
ea47320b 13235 continue;
d62a17ae 13236
9bcb3eef
DS
13237 for (dest = bgp_table_top(table); dest;
13238 dest = bgp_route_next(dest)) {
13239 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 13240 if (bgp_static == NULL)
ea47320b 13241 continue;
d62a17ae 13242
9bcb3eef
DS
13243 p = bgp_dest_get_prefix(dest);
13244 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13245 pdest);
d62a17ae 13246
ea47320b 13247 /* "network" configuration display. */
06b9f471 13248 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
13249 label = decode_label(&bgp_static->label);
13250
13251 vty_out(vty, " network %s/%d rd %s",
13252 inet_ntop(p->family, &p->u.prefix, buf,
13253 SU_ADDRSTRLEN),
13254 p->prefixlen, rdbuf);
13255 if (safi == SAFI_MPLS_VPN)
13256 vty_out(vty, " label %u", label);
13257
13258 if (bgp_static->rmap.name)
13259 vty_out(vty, " route-map %s",
13260 bgp_static->rmap.name);
e2a86ad9
DS
13261
13262 if (bgp_static->backdoor)
13263 vty_out(vty, " backdoor");
13264
ea47320b
DL
13265 vty_out(vty, "\n");
13266 }
13267 }
d62a17ae 13268}
13269
2b791107
DL
13270static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
13271 afi_t afi, safi_t safi)
d62a17ae 13272{
9bcb3eef
DS
13273 struct bgp_dest *pdest;
13274 struct bgp_dest *dest;
d62a17ae 13275 struct bgp_table *table;
b54892e0
DS
13276 const struct prefix *p;
13277 const struct prefix_rd *prd;
d62a17ae 13278 struct bgp_static *bgp_static;
ff44f570 13279 char buf[PREFIX_STRLEN * 2];
d62a17ae 13280 char buf2[SU_ADDRSTRLEN];
13281 char rdbuf[RD_ADDRSTRLEN];
13282
13283 /* Network configuration. */
9bcb3eef
DS
13284 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
13285 pdest = bgp_route_next(pdest)) {
13286 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 13287 if (!table)
ea47320b 13288 continue;
d62a17ae 13289
9bcb3eef
DS
13290 for (dest = bgp_table_top(table); dest;
13291 dest = bgp_route_next(dest)) {
13292 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 13293 if (bgp_static == NULL)
ea47320b 13294 continue;
d62a17ae 13295
ea47320b
DL
13296 char *macrouter = NULL;
13297 char *esi = NULL;
d62a17ae 13298
ea47320b
DL
13299 if (bgp_static->router_mac)
13300 macrouter = prefix_mac2str(
13301 bgp_static->router_mac, NULL, 0);
13302 if (bgp_static->eth_s_id)
13303 esi = esi2str(bgp_static->eth_s_id);
9bcb3eef
DS
13304 p = bgp_dest_get_prefix(dest);
13305 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 13306
ea47320b 13307 /* "network" configuration display. */
06b9f471 13308 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
13309 if (p->u.prefix_evpn.route_type == 5) {
13310 char local_buf[PREFIX_STRLEN];
3714a385 13311 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
13312 struct prefix_evpn *)p)
13313 ? AF_INET
13314 : AF_INET6;
3714a385 13315 inet_ntop(family,
13316 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 13317 local_buf, PREFIX_STRLEN);
772270f3
QY
13318 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
13319 p->u.prefix_evpn.prefix_addr
13320 .ip_prefix_length);
197cb530
PG
13321 } else {
13322 prefix2str(p, buf, sizeof(buf));
13323 }
ea47320b 13324
a4d82a8a
PZ
13325 if (bgp_static->gatewayIp.family == AF_INET
13326 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
13327 inet_ntop(bgp_static->gatewayIp.family,
13328 &bgp_static->gatewayIp.u.prefix, buf2,
13329 sizeof(buf2));
ea47320b 13330 vty_out(vty,
7bcc8dac 13331 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 13332 buf, rdbuf,
13333 p->u.prefix_evpn.prefix_addr.eth_tag,
60466a63 13334 decode_label(&bgp_static->label), esi, buf2,
ea47320b
DL
13335 macrouter);
13336
0a22ddfb
QY
13337 XFREE(MTYPE_TMP, macrouter);
13338 XFREE(MTYPE_TMP, esi);
ea47320b
DL
13339 }
13340 }
3da6fcd5
PG
13341}
13342
718e3744 13343/* Configuration of static route announcement and aggregate
13344 information. */
2b791107
DL
13345void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
13346 safi_t safi)
d62a17ae 13347{
9bcb3eef 13348 struct bgp_dest *dest;
b54892e0 13349 const struct prefix *p;
d62a17ae 13350 struct bgp_static *bgp_static;
13351 struct bgp_aggregate *bgp_aggregate;
13352 char buf[SU_ADDRSTRLEN];
13353
2b791107
DL
13354 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
13355 bgp_config_write_network_vpn(vty, bgp, afi, safi);
13356 return;
13357 }
d62a17ae 13358
2b791107
DL
13359 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
13360 bgp_config_write_network_evpn(vty, bgp, afi, safi);
13361 return;
13362 }
d62a17ae 13363
13364 /* Network configuration. */
9bcb3eef
DS
13365 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
13366 dest = bgp_route_next(dest)) {
13367 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 13368 if (bgp_static == NULL)
ea47320b 13369 continue;
d62a17ae 13370
9bcb3eef 13371 p = bgp_dest_get_prefix(dest);
d62a17ae 13372
d8a9922d
DS
13373 vty_out(vty, " network %s/%d",
13374 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
13375 p->prefixlen);
d62a17ae 13376
ea47320b
DL
13377 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
13378 vty_out(vty, " label-index %u",
13379 bgp_static->label_index);
d62a17ae 13380
ea47320b
DL
13381 if (bgp_static->rmap.name)
13382 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
13383
13384 if (bgp_static->backdoor)
13385 vty_out(vty, " backdoor");
718e3744 13386
ea47320b
DL
13387 vty_out(vty, "\n");
13388 }
13389
d62a17ae 13390 /* Aggregate-address configuration. */
9bcb3eef
DS
13391 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
13392 dest = bgp_route_next(dest)) {
13393 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 13394 if (bgp_aggregate == NULL)
ea47320b 13395 continue;
d62a17ae 13396
9bcb3eef 13397 p = bgp_dest_get_prefix(dest);
d62a17ae 13398
d8a9922d
DS
13399 vty_out(vty, " aggregate-address %s/%d",
13400 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
13401 p->prefixlen);
d62a17ae 13402
ea47320b
DL
13403 if (bgp_aggregate->as_set)
13404 vty_out(vty, " as-set");
d62a17ae 13405
ea47320b
DL
13406 if (bgp_aggregate->summary_only)
13407 vty_out(vty, " summary-only");
718e3744 13408
20894f50
DA
13409 if (bgp_aggregate->rmap.name)
13410 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
13411
229757f1
DA
13412 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
13413 vty_out(vty, " origin %s",
13414 bgp_origin2str(bgp_aggregate->origin));
13415
ea47320b
DL
13416 vty_out(vty, "\n");
13417 }
d62a17ae 13418}
734b349e 13419
2b791107 13420void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 13421 safi_t safi)
d62a17ae 13422{
9bcb3eef 13423 struct bgp_dest *dest;
d62a17ae 13424 struct bgp_distance *bdistance;
13425
13426 /* Distance configuration. */
13427 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
13428 && bgp->distance_local[afi][safi]
13429 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
13430 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
13431 || bgp->distance_local[afi][safi]
13432 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 13433 vty_out(vty, " distance bgp %d %d %d\n",
13434 bgp->distance_ebgp[afi][safi],
13435 bgp->distance_ibgp[afi][safi],
13436 bgp->distance_local[afi][safi]);
13437 }
734b349e 13438
9bcb3eef
DS
13439 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
13440 dest = bgp_route_next(dest)) {
13441 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0
DS
13442 if (bdistance != NULL)
13443 vty_out(vty, " distance %d %pRN %s\n",
9bcb3eef 13444 bdistance->distance, dest,
d62a17ae 13445 bdistance->access_list ? bdistance->access_list
13446 : "");
ca2e160d 13447 }
718e3744 13448}
13449
13450/* Allocate routing table structure and install commands. */
d62a17ae 13451void bgp_route_init(void)
13452{
13453 afi_t afi;
13454 safi_t safi;
13455
13456 /* Init BGP distance table. */
05c7a1cc 13457 FOREACH_AFI_SAFI (afi, safi)
960035b2 13458 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 13459
13460 /* IPv4 BGP commands. */
13461 install_element(BGP_NODE, &bgp_table_map_cmd);
13462 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 13463 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 13464
13465 install_element(BGP_NODE, &aggregate_address_cmd);
13466 install_element(BGP_NODE, &aggregate_address_mask_cmd);
13467 install_element(BGP_NODE, &no_aggregate_address_cmd);
13468 install_element(BGP_NODE, &no_aggregate_address_mask_cmd);
13469
13470 /* IPv4 unicast configuration. */
13471 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
13472 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 13473 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 13474
13475 install_element(BGP_IPV4_NODE, &aggregate_address_cmd);
13476 install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd);
13477 install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd);
13478 install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
13479
13480 /* IPv4 multicast configuration. */
13481 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
13482 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 13483 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
d62a17ae 13484 install_element(BGP_IPV4M_NODE, &aggregate_address_cmd);
13485 install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
13486 install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd);
13487 install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
13488
13489 /* IPv4 labeled-unicast configuration. */
fb985e0c
DA
13490 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
13491 install_element(BGP_IPV4L_NODE, &aggregate_address_cmd);
13492 install_element(BGP_IPV4L_NODE, &aggregate_address_mask_cmd);
13493 install_element(BGP_IPV4L_NODE, &no_aggregate_address_cmd);
13494 install_element(BGP_IPV4L_NODE, &no_aggregate_address_mask_cmd);
13495
d62a17ae 13496 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
13497 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 13498 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 13499 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 13500 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 13501 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
13502 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 13503 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 13504
13505 install_element(VIEW_NODE,
13506 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
13507 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
13508 install_element(VIEW_NODE,
13509 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 13510#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 13511 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 13512#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 13513 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
13514 install_element(VIEW_NODE,
44c69747 13515 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 13516
d62a17ae 13517 /* BGP dampening clear commands */
13518 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
13519 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 13520
d62a17ae 13521 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
13522 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
13523
13524 /* prefix count */
13525 install_element(ENABLE_NODE,
13526 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 13527#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 13528 install_element(ENABLE_NODE,
13529 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 13530#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 13531
d62a17ae 13532 /* New config IPv6 BGP commands. */
13533 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
13534 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 13535 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 13536
13537 install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
13538 install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
13539
13540 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 13541
fb985e0c
DA
13542 /* IPv6 labeled unicast address family. */
13543 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
13544 install_element(BGP_IPV6L_NODE, &ipv6_aggregate_address_cmd);
13545 install_element(BGP_IPV6L_NODE, &no_ipv6_aggregate_address_cmd);
13546
d62a17ae 13547 install_element(BGP_NODE, &bgp_distance_cmd);
13548 install_element(BGP_NODE, &no_bgp_distance_cmd);
13549 install_element(BGP_NODE, &bgp_distance_source_cmd);
13550 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
13551 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
13552 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
13553 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
13554 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
13555 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
13556 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
13557 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
13558 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
13559 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
13560 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
13561 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
13562 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
13563 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
13564 install_element(BGP_IPV4M_NODE,
13565 &no_bgp_distance_source_access_list_cmd);
13566 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
13567 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
13568 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
13569 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
13570 install_element(BGP_IPV6_NODE,
13571 &ipv6_bgp_distance_source_access_list_cmd);
13572 install_element(BGP_IPV6_NODE,
13573 &no_ipv6_bgp_distance_source_access_list_cmd);
13574 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
13575 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
13576 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
13577 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
13578 install_element(BGP_IPV6M_NODE,
13579 &ipv6_bgp_distance_source_access_list_cmd);
13580 install_element(BGP_IPV6M_NODE,
13581 &no_ipv6_bgp_distance_source_access_list_cmd);
13582
ef5f4b23 13583 /* BGP dampening */
d62a17ae 13584 install_element(BGP_NODE, &bgp_damp_set_cmd);
13585 install_element(BGP_NODE, &bgp_damp_unset_cmd);
13586 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
13587 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
d62a17ae 13588 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
13589 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
ef5f4b23
DA
13590 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
13591 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
13592 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
13593 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
13594 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
13595 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
13596 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
13597 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 13598
13599 /* Large Communities */
13600 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
13601 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
13602
13603 /* show bgp ipv4 flowspec detailed */
13604 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
13605
2a0e69ae 13606 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 13607 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 13608}
13609
13610void bgp_route_finish(void)
13611{
13612 afi_t afi;
13613 safi_t safi;
13614
05c7a1cc
QY
13615 FOREACH_AFI_SAFI (afi, safi) {
13616 bgp_table_unlock(bgp_distance_table[afi][safi]);
13617 bgp_distance_table[afi][safi] = NULL;
13618 }
228da428 13619}