]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #6833 from donaldsharp/pcount_selected
[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))
6cde4b45 1647 zlog_debug("u%" PRIu64 ":s%" PRIu64" %s/%d is filtered - no label (%p)",
d62a17ae 1648 subgrp->update_group->id, subgrp->id,
1649 inet_ntop(p->family, &p->u.prefix,
1650 buf, SU_ADDRSTRLEN),
1651 p->prefixlen, &label);
3dc339cd 1652 return false;
d62a17ae 1653 }
1654 }
cd1964ff 1655
d62a17ae 1656 /* Do not send back route to sender. */
1657 if (onlypeer && from == onlypeer) {
3dc339cd 1658 return false;
d62a17ae 1659 }
3f9c7369 1660
d62a17ae 1661 /* Do not send the default route in the BGP table if the neighbor is
1662 * configured for default-originate */
1663 if (CHECK_FLAG(peer->af_flags[afi][safi],
1664 PEER_FLAG_DEFAULT_ORIGINATE)) {
1665 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1666 return false;
d62a17ae 1667 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1668 return false;
d62a17ae 1669 }
4125bb67 1670
d62a17ae 1671 /* Transparency check. */
1672 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1673 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1674 transparent = 1;
1675 else
1676 transparent = 0;
1677
1678 /* If community is not disabled check the no-export and local. */
40381db7 1679 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1680 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1681 zlog_debug(
1682 "subgrpannouncecheck: community filter check fail");
3dc339cd 1683 return false;
d62a17ae 1684 }
3f9c7369 1685
d62a17ae 1686 /* If the attribute has originator-id and it is same as remote
1687 peer's id. */
40381db7
DS
1688 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1689 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1690 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1691 zlog_debug(
3efd0893 1692 "%s [Update:SEND] %s originator-id is same as remote router-id",
d62a17ae 1693 onlypeer->host,
1694 prefix2str(p, buf, sizeof(buf)));
3dc339cd 1695 return false;
d62a17ae 1696 }
3f9c7369 1697
d62a17ae 1698 /* ORF prefix-list filter check */
1699 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1700 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1701 || CHECK_FLAG(peer->af_cap[afi][safi],
1702 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1703 if (peer->orf_plist[afi][safi]) {
1704 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1705 == PREFIX_DENY) {
1706 if (bgp_debug_update(NULL, p,
1707 subgrp->update_group, 0))
1708 zlog_debug(
1709 "%s [Update:SEND] %s is filtered via ORF",
1710 peer->host,
1711 prefix2str(p, buf,
1712 sizeof(buf)));
3dc339cd 1713 return false;
d62a17ae 1714 }
1715 }
1716
1717 /* Output filter check. */
40381db7 1718 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1719 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1720 zlog_debug("%s [Update:SEND] %s is filtered",
1721 peer->host, prefix2str(p, buf, sizeof(buf)));
3dc339cd 1722 return false;
d62a17ae 1723 }
3f9c7369 1724
d62a17ae 1725 /* AS path loop check. */
2b31007c
RZ
1726 if (onlypeer && onlypeer->as_path_loop_detection
1727 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1728 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1729 zlog_debug(
3efd0893 1730 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 1731 onlypeer->host, onlypeer->as);
3dc339cd 1732 return false;
d62a17ae 1733 }
3f9c7369 1734
d62a17ae 1735 /* If we're a CONFED we need to loop check the CONFED ID too */
1736 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1737 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1738 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1739 zlog_debug(
3efd0893 1740 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 1741 peer->host, bgp->confed_id);
3dc339cd 1742 return false;
d62a17ae 1743 }
3f9c7369 1744 }
3f9c7369 1745
d62a17ae 1746 /* Route-Reflect check. */
1747 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1748 reflect = 1;
1749 else
1750 reflect = 0;
1751
1752 /* IBGP reflection check. */
1753 if (reflect && !samepeer_safe) {
1754 /* A route from a Client peer. */
1755 if (CHECK_FLAG(from->af_flags[afi][safi],
1756 PEER_FLAG_REFLECTOR_CLIENT)) {
1757 /* Reflect to all the Non-Client peers and also to the
1758 Client peers other than the originator. Originator
1759 check
1760 is already done. So there is noting to do. */
1761 /* no bgp client-to-client reflection check. */
892fedb6
DA
1762 if (CHECK_FLAG(bgp->flags,
1763 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 1764 if (CHECK_FLAG(peer->af_flags[afi][safi],
1765 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1766 return false;
d62a17ae 1767 } else {
1768 /* A route from a Non-client peer. Reflect to all other
1769 clients. */
1770 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1771 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1772 return false;
d62a17ae 1773 }
1774 }
3f9c7369 1775
d62a17ae 1776 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1777 *attr = *piattr;
d62a17ae 1778
1779 /* If local-preference is not set. */
1780 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1781 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1782 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1783 attr->local_pref = bgp->default_local_pref;
3f9c7369 1784 }
3f9c7369 1785
d62a17ae 1786 /* If originator-id is not set and the route is to be reflected,
1787 set the originator id */
1788 if (reflect
1789 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1790 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1791 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1792 }
3f9c7369 1793
d62a17ae 1794 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1795 */
1796 if (peer->sort == BGP_PEER_EBGP
1797 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1798 if (from != bgp->peer_self && !transparent
1799 && !CHECK_FLAG(peer->af_flags[afi][safi],
1800 PEER_FLAG_MED_UNCHANGED))
1801 attr->flag &=
1802 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1803 }
3f9c7369 1804
d62a17ae 1805 /* Since the nexthop attribute can vary per peer, it is not explicitly
1806 * set
1807 * in announce check, only certain flags and length (or number of
1808 * nexthops
1809 * -- for IPv6/MP_REACH) are set here in order to guide the update
1810 * formation
1811 * code in setting the nexthop(s) on a per peer basis in
1812 * reformat_peer().
1813 * Typically, the source nexthop in the attribute is preserved but in
1814 * the
1815 * scenarios where we know it will always be overwritten, we reset the
1816 * nexthop to "0" in an attempt to achieve better Update packing. An
1817 * example of this is when a prefix from each of 2 IBGP peers needs to
1818 * be
1819 * announced to an EBGP peer (and they have the same attributes barring
1820 * their nexthop).
1821 */
1822 if (reflect)
1823 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1824
1825#define NEXTHOP_IS_V6 \
1826 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1827 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1828 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1829 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1830
1831 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1832 * if
1833 * the peer (group) is configured to receive link-local nexthop
1834 * unchanged
c728d027
DA
1835 * and it is available in the prefix OR we're not reflecting the route,
1836 * link-local nexthop address is valid and
d62a17ae 1837 * the peer (group) to whom we're going to announce is on a shared
1838 * network
1839 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
1840 * By checking if nexthop LL address is valid we are sure that
1841 * we do not announce LL address as `::`.
d62a17ae 1842 */
1843 if (NEXTHOP_IS_V6) {
1844 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
1845 if ((CHECK_FLAG(peer->af_flags[afi][safi],
1846 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
1847 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
1848 || (!reflect
1849 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
1850 && peer->shared_network
d62a17ae 1851 && (from == bgp->peer_self
1852 || peer->sort == BGP_PEER_EBGP))) {
1853 attr->mp_nexthop_len =
1854 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
1855 }
3f9c7369 1856
d62a17ae 1857 /* Clear off link-local nexthop in source, whenever it is not
1858 * needed to
1859 * ensure more prefixes share the same attribute for
1860 * announcement.
1861 */
1862 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
1863 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
1864 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
1865 }
3f9c7369 1866
d62a17ae 1867 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
1868 bgp_peer_as_override(bgp, afi, safi, peer, attr);
1869
1870 /* Route map & unsuppress-map apply. */
40381db7 1871 if (ROUTE_MAP_OUT_NAME(filter) || (pi->extra && pi->extra->suppress)) {
b8694ef4
DS
1872 struct bgp_path_info rmap_path = {0};
1873 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
1874 struct attr dummy_attr = {0};
d62a17ae 1875
e34291b8 1876 /* Fill temp path_info */
9bcb3eef
DS
1877 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
1878 pi, peer, attr);
16f7ce2b 1879
d62a17ae 1880 /* don't confuse inbound and outbound setting */
1881 RESET_FLAG(attr->rmap_change_flags);
1882
1883 /*
1884 * The route reflector is not allowed to modify the attributes
1885 * of the reflected IBGP routes unless explicitly allowed.
1886 */
1887 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
1888 && !CHECK_FLAG(bgp->flags,
1889 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 1890 dummy_attr = *attr;
40381db7 1891 rmap_path.attr = &dummy_attr;
d62a17ae 1892 }
3f9c7369 1893
d62a17ae 1894 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 1895
40381db7 1896 if (pi->extra && pi->extra->suppress)
d62a17ae 1897 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
40381db7 1898 RMAP_BGP, &rmap_path);
d62a17ae 1899 else
1900 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
40381db7 1901 RMAP_BGP, &rmap_path);
d62a17ae 1902
1903 peer->rmap_type = 0;
1904
1905 if (ret == RMAP_DENYMATCH) {
778048bf
AD
1906 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1907 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1908 peer->host, prefix2str(p, buf, sizeof(buf)));
1909
d62a17ae 1910 bgp_attr_flush(attr);
3dc339cd 1911 return false;
d62a17ae 1912 }
3f9c7369 1913 }
3f9c7369 1914
9dac9fc8
DA
1915 /* RFC 8212 to prevent route leaks.
1916 * This specification intends to improve this situation by requiring the
1917 * explicit configuration of both BGP Import and Export Policies for any
1918 * External BGP (EBGP) session such as customers, peers, or
1919 * confederation boundaries for all enabled address families. Through
1920 * codification of the aforementioned requirement, operators will
1921 * benefit from consistent behavior across different BGP
1922 * implementations.
1923 */
1d3fdccf 1924 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
9dac9fc8 1925 if (!bgp_outbound_policy_exists(peer, filter))
3dc339cd 1926 return false;
9dac9fc8 1927
fb29348a
DA
1928 /* draft-ietf-idr-deprecate-as-set-confed-set
1929 * Filter routes having AS_SET or AS_CONFED_SET in the path.
1930 * Eventually, This document (if approved) updates RFC 4271
1931 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
1932 * and obsoletes RFC 6472.
1933 */
7f972cd8 1934 if (peer->bgp->reject_as_sets)
fb29348a 1935 if (aspath_check_as_sets(attr->aspath))
3dc339cd 1936 return false;
fb29348a 1937
33d022bc
DA
1938 /* Codification of AS 0 Processing */
1939 if (aspath_check_as_zero(attr->aspath))
e2369003 1940 return false;
33d022bc 1941
892fedb6 1942 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
a4d82a8a
PZ
1943 if (peer->sort == BGP_PEER_IBGP
1944 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
1945 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1946 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1947 } else {
1948 bgp_attr_add_gshut_community(attr);
1949 }
1950 }
1951
d62a17ae 1952 /* After route-map has been applied, we check to see if the nexthop to
1953 * be carried in the attribute (that is used for the announcement) can
1954 * be cleared off or not. We do this in all cases where we would be
1955 * setting the nexthop to "ourselves". For IPv6, we only need to
1956 * consider
1957 * the global nexthop here; the link-local nexthop would have been
1958 * cleared
1959 * already, and if not, it is required by the update formation code.
1960 * Also see earlier comments in this function.
1961 */
1962 /*
1963 * If route-map has performed some operation on the nexthop or the peer
1964 * configuration says to pass it unchanged, we cannot reset the nexthop
1965 * here, so only attempt to do it if these aren't true. Note that the
1966 * route-map handler itself might have cleared the nexthop, if for
1967 * example,
1968 * it is configured as 'peer-address'.
1969 */
1970 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 1971 piattr->rmap_change_flags)
d62a17ae 1972 && !transparent
1973 && !CHECK_FLAG(peer->af_flags[afi][safi],
1974 PEER_FLAG_NEXTHOP_UNCHANGED)) {
1975 /* We can reset the nexthop, if setting (or forcing) it to
1976 * 'self' */
1977 if (CHECK_FLAG(peer->af_flags[afi][safi],
1978 PEER_FLAG_NEXTHOP_SELF)
1979 || CHECK_FLAG(peer->af_flags[afi][safi],
1980 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
1981 if (!reflect
1982 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 1983 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 1984 subgroup_announce_reset_nhop(
1985 (peer_cap_enhe(peer, afi, safi)
1986 ? AF_INET6
1987 : p->family),
1988 attr);
7b651a32 1989 nh_reset = true;
1990 }
d62a17ae 1991 } else if (peer->sort == BGP_PEER_EBGP) {
1992 /* Can also reset the nexthop if announcing to EBGP, but
1993 * only if
1994 * no peer in the subgroup is on a shared subnet.
1995 * Note: 3rd party nexthop currently implemented for
1996 * IPv4 only.
1997 */
737af885
BS
1998 if ((p->family == AF_INET) &&
1999 (!bgp_subgrp_multiaccess_check_v4(
2000 piattr->nexthop,
7b651a32 2001 subgrp, from))) {
d62a17ae 2002 subgroup_announce_reset_nhop(
2003 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2004 ? AF_INET6
2005 : p->family),
737af885 2006 attr);
7b651a32 2007 nh_reset = true;
2008 }
737af885
BS
2009
2010 if ((p->family == AF_INET6) &&
2011 (!bgp_subgrp_multiaccess_check_v6(
2012 piattr->mp_nexthop_global,
7b651a32 2013 subgrp, from))) {
737af885
BS
2014 subgroup_announce_reset_nhop(
2015 (peer_cap_enhe(peer, afi, safi)
2016 ? AF_INET6
2017 : p->family),
2018 attr);
7b651a32 2019 nh_reset = true;
2020 }
737af885
BS
2021
2022
2023
40381db7 2024 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2025 /*
2026 * This flag is used for leaked vpn-vrf routes
2027 */
2028 int family = p->family;
2029
2030 if (peer_cap_enhe(peer, afi, safi))
2031 family = AF_INET6;
2032
2033 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2034 zlog_debug(
1defdda8 2035 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2036 __func__, family2str(family));
2037 subgroup_announce_reset_nhop(family, attr);
7b651a32 2038 nh_reset = true;
d62a17ae 2039 }
63696f1d 2040 }
960035b2 2041
63696f1d 2042 /* If IPv6/MP and nexthop does not have any override and happens
2043 * to
2044 * be a link-local address, reset it so that we don't pass along
2045 * the
2046 * source's link-local IPv6 address to recipients who may not be
2047 * on
2048 * the same interface.
2049 */
2050 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2051 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2052 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2053 nh_reset = true;
2054 }
d62a17ae 2055 }
3f9c7369 2056
7b651a32 2057 /*
2058 * When the next hop is set to ourselves, if all multipaths have
2059 * link-bandwidth announce the cumulative bandwidth as that makes
2060 * the most sense. However, don't modify if the link-bandwidth has
2061 * been explicitly set by user policy.
2062 */
2063 if (nh_reset &&
f7e1c681 2064 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2065 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2066 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2067 attr->ecommunity = ecommunity_replace_linkbw(
2068 bgp->as, attr->ecommunity, cum_bw);
2069
3dc339cd 2070 return true;
3f9c7369
DS
2071}
2072
f009ff26 2073static int bgp_route_select_timer_expire(struct thread *thread)
2074{
2075 struct afi_safi_info *info;
2076 afi_t afi;
2077 safi_t safi;
2078 struct bgp *bgp;
2079
2080 info = THREAD_ARG(thread);
2081 afi = info->afi;
2082 safi = info->safi;
2083 bgp = info->bgp;
2084
2085 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2086 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2087 safi);
f009ff26 2088
2089 bgp->gr_info[afi][safi].t_route_select = NULL;
2090
2091 XFREE(MTYPE_TMP, info);
2092
2093 /* Best path selection */
2094 return bgp_best_path_select_defer(bgp, afi, safi);
2095}
2096
9bcb3eef 2097void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2098 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2099 struct bgp_path_info_pair *result, afi_t afi,
2100 safi_t safi)
2101{
2102 struct bgp_path_info *new_select;
2103 struct bgp_path_info *old_select;
40381db7
DS
2104 struct bgp_path_info *pi;
2105 struct bgp_path_info *pi1;
2106 struct bgp_path_info *pi2;
2107 struct bgp_path_info *nextpi = NULL;
d62a17ae 2108 int paths_eq, do_mpath, debug;
2109 struct list mp_list;
2110 char pfx_buf[PREFIX2STR_BUFFER];
2111 char path_buf[PATH_ADDPATH_STR_BUFFER];
2112
2113 bgp_mp_list_init(&mp_list);
2114 do_mpath =
2115 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2116
9bcb3eef 2117 debug = bgp_debug_bestpath(dest);
d62a17ae 2118
2119 if (debug)
9bcb3eef 2120 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2121
9bcb3eef 2122 dest->reason = bgp_path_selection_none;
d62a17ae 2123 /* bgp deterministic-med */
2124 new_select = NULL;
892fedb6 2125 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2126
1defdda8 2127 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2128 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2129 pi1 = pi1->next)
9bcb3eef 2130 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2131 BGP_PATH_DMED_SELECTED);
d62a17ae 2132
9bcb3eef 2133 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2134 pi1 = pi1->next) {
40381db7 2135 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2136 continue;
40381db7 2137 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2138 continue;
ea8b2282 2139 if (pi1->peer != bgp->peer_self)
40381db7 2140 if (pi1->peer->status != Established)
d62a17ae 2141 continue;
2142
40381db7
DS
2143 new_select = pi1;
2144 if (pi1->next) {
2145 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2146 if (CHECK_FLAG(pi2->flags,
1defdda8 2147 BGP_PATH_DMED_CHECK))
d62a17ae 2148 continue;
40381db7 2149 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2150 continue;
ea8b2282 2151 if (pi2->peer != bgp->peer_self
d62a17ae 2152 && !CHECK_FLAG(
ea8b2282
DS
2153 pi2->peer->sflags,
2154 PEER_STATUS_NSF_WAIT))
40381db7 2155 if (pi2->peer->status
d62a17ae 2156 != Established)
2157 continue;
2158
121e245d
DS
2159 if (!aspath_cmp_left(pi1->attr->aspath,
2160 pi2->attr->aspath)
2161 && !aspath_cmp_left_confed(
40381db7 2162 pi1->attr->aspath,
121e245d
DS
2163 pi2->attr->aspath))
2164 continue;
d62a17ae 2165
121e245d
DS
2166 if (bgp_path_info_cmp(
2167 bgp, pi2, new_select,
2168 &paths_eq, mpath_cfg, debug,
fdf81fa0 2169 pfx_buf, afi, safi,
9bcb3eef 2170 &dest->reason)) {
121e245d 2171 bgp_path_info_unset_flag(
9bcb3eef 2172 dest, new_select,
121e245d
DS
2173 BGP_PATH_DMED_SELECTED);
2174 new_select = pi2;
d62a17ae 2175 }
121e245d
DS
2176
2177 bgp_path_info_set_flag(
9bcb3eef 2178 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2179 }
2180 }
9bcb3eef 2181 bgp_path_info_set_flag(dest, new_select,
18ee8310 2182 BGP_PATH_DMED_CHECK);
9bcb3eef 2183 bgp_path_info_set_flag(dest, new_select,
18ee8310 2184 BGP_PATH_DMED_SELECTED);
d62a17ae 2185
2186 if (debug) {
18ee8310
DS
2187 bgp_path_info_path_with_addpath_rx_str(
2188 new_select, path_buf);
c66faab1 2189 zlog_debug("%s: %s is the bestpath from AS %u",
d62a17ae 2190 pfx_buf, path_buf,
2191 aspath_get_first_as(
2192 new_select->attr->aspath));
2193 }
2194 }
2195 }
96450faf 2196
d62a17ae 2197 /* Check old selected route and new selected route. */
2198 old_select = NULL;
2199 new_select = NULL;
9bcb3eef 2200 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2201 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2202 enum bgp_path_selection_reason reason;
2203
40381db7
DS
2204 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2205 old_select = pi;
d62a17ae 2206
40381db7 2207 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2208 /* reap REMOVED routes, if needs be
2209 * selected route must stay for a while longer though
2210 */
40381db7
DS
2211 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2212 && (pi != old_select))
9bcb3eef 2213 bgp_path_info_reap(dest, pi);
d62a17ae 2214
ddb5b488 2215 if (debug)
40381db7
DS
2216 zlog_debug("%s: pi %p in holddown", __func__,
2217 pi);
ddb5b488 2218
d62a17ae 2219 continue;
2220 }
96450faf 2221
40381db7
DS
2222 if (pi->peer && pi->peer != bgp->peer_self
2223 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2224 if (pi->peer->status != Established) {
ddb5b488
PZ
2225
2226 if (debug)
2227 zlog_debug(
40381db7
DS
2228 "%s: pi %p non self peer %s not estab state",
2229 __func__, pi, pi->peer->host);
ddb5b488 2230
d62a17ae 2231 continue;
ddb5b488 2232 }
9fbdd100 2233
892fedb6 2234 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2235 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2236 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2237 if (debug)
40381db7 2238 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2239 continue;
2240 }
9fbdd100 2241
9bcb3eef 2242 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2243
9bcb3eef 2244 reason = dest->reason;
40381db7 2245 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2246 debug, pfx_buf, afi, safi,
2247 &dest->reason)) {
19ea4cec
DS
2248 if (new_select == NULL &&
2249 reason != bgp_path_selection_none)
9bcb3eef 2250 dest->reason = reason;
40381db7 2251 new_select = pi;
d62a17ae 2252 }
2253 }
718e3744 2254
d62a17ae 2255 /* Now that we know which path is the bestpath see if any of the other
2256 * paths
2257 * qualify as multipaths
2258 */
2259 if (debug) {
2260 if (new_select)
18ee8310
DS
2261 bgp_path_info_path_with_addpath_rx_str(new_select,
2262 path_buf);
d62a17ae 2263 else
772270f3 2264 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2265 zlog_debug(
2266 "%s: After path selection, newbest is %s oldbest was %s",
2267 pfx_buf, path_buf,
2268 old_select ? old_select->peer->host : "NONE");
96450faf 2269 }
9fbdd100 2270
d62a17ae 2271 if (do_mpath && new_select) {
9bcb3eef 2272 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2273 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2274
2275 if (debug)
18ee8310 2276 bgp_path_info_path_with_addpath_rx_str(
40381db7 2277 pi, path_buf);
d62a17ae 2278
40381db7 2279 if (pi == new_select) {
d62a17ae 2280 if (debug)
2281 zlog_debug(
2282 "%s: %s is the bestpath, add to the multipath list",
2283 pfx_buf, path_buf);
40381db7 2284 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2285 continue;
2286 }
2287
40381db7 2288 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2289 continue;
2290
40381db7
DS
2291 if (pi->peer && pi->peer != bgp->peer_self
2292 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2293 PEER_STATUS_NSF_WAIT))
40381db7 2294 if (pi->peer->status != Established)
d62a17ae 2295 continue;
2296
40381db7 2297 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2298 if (debug)
2299 zlog_debug(
2300 "%s: %s has the same nexthop as the bestpath, skip it",
2301 pfx_buf, path_buf);
2302 continue;
2303 }
2304
40381db7 2305 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2306 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2307 &dest->reason);
d62a17ae 2308
2309 if (paths_eq) {
2310 if (debug)
2311 zlog_debug(
2312 "%s: %s is equivalent to the bestpath, add to the multipath list",
2313 pfx_buf, path_buf);
40381db7 2314 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2315 }
2316 }
2317 }
fee0f4c6 2318
9bcb3eef 2319 bgp_path_info_mpath_update(dest, new_select, old_select, &mp_list,
18ee8310
DS
2320 mpath_cfg);
2321 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2322 bgp_mp_list_clear(&mp_list);
96450faf 2323
9bcb3eef 2324 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2325
d62a17ae 2326 result->old = old_select;
2327 result->new = new_select;
96450faf 2328
d62a17ae 2329 return;
fee0f4c6 2330}
2331
3f9c7369
DS
2332/*
2333 * A new route/change in bestpath of an existing route. Evaluate the path
2334 * for advertisement to the subgroup.
2335 */
3dc339cd
DA
2336void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2337 struct bgp_path_info *selected,
9bcb3eef 2338 struct bgp_dest *dest,
3dc339cd 2339 uint32_t addpath_tx_id)
d62a17ae 2340{
b54892e0 2341 const struct prefix *p;
d62a17ae 2342 struct peer *onlypeer;
2343 struct attr attr;
2344 afi_t afi;
2345 safi_t safi;
adbac85e 2346
9bcb3eef 2347 p = bgp_dest_get_prefix(dest);
d62a17ae 2348 afi = SUBGRP_AFI(subgrp);
2349 safi = SUBGRP_SAFI(subgrp);
2350 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2351 : NULL);
2352
e0207895
PZ
2353 if (BGP_DEBUG(update, UPDATE_OUT)) {
2354 char buf_prefix[PREFIX_STRLEN];
2355 prefix2str(p, buf_prefix, sizeof(buf_prefix));
ddb5b488
PZ
2356 zlog_debug("%s: p=%s, selected=%p", __func__, buf_prefix,
2357 selected);
e0207895
PZ
2358 }
2359
d62a17ae 2360 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2361 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2362 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2363 return;
d62a17ae 2364
2365 memset(&attr, 0, sizeof(struct attr));
2366 /* It's initialized in bgp_announce_check() */
2367
2368 /* Announcement to the subgroup. If the route is filtered withdraw it.
2369 */
2370 if (selected) {
9bcb3eef
DS
2371 if (subgroup_announce_check(dest, selected, subgrp, p, &attr))
2372 bgp_adj_out_set_subgroup(dest, subgrp, &attr, selected);
d62a17ae 2373 else
9bcb3eef 2374 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2375 addpath_tx_id);
d62a17ae 2376 }
2377
2378 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2379 else {
9bcb3eef 2380 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2381 }
200df115 2382}
fee0f4c6 2383
3064bf43 2384/*
e1072051 2385 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2386 * This is called at the end of route processing.
3064bf43 2387 */
9bcb3eef 2388void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2389{
40381db7 2390 struct bgp_path_info *pi;
3064bf43 2391
9bcb3eef 2392 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2393 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2394 continue;
40381db7
DS
2395 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2396 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2397 }
3064bf43 2398}
2399
2400/*
2401 * Has the route changed from the RIB's perspective? This is invoked only
2402 * if the route selection returns the same best route as earlier - to
2403 * determine if we need to update zebra or not.
2404 */
9bcb3eef 2405bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2406{
4b7e6066 2407 struct bgp_path_info *mpinfo;
d62a17ae 2408
2bb9eff4
DS
2409 /* If this is multipath, check all selected paths for any nexthop
2410 * change or attribute change. Some attribute changes (e.g., community)
2411 * aren't of relevance to the RIB, but we'll update zebra to ensure
2412 * we handle the case of BGP nexthop change. This is the behavior
2413 * when the best path has an attribute change anyway.
d62a17ae 2414 */
1defdda8 2415 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2416 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2417 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2418 return true;
d62a17ae 2419
2bb9eff4
DS
2420 /*
2421 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2422 */
18ee8310
DS
2423 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2424 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2425 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2426 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2427 return true;
d62a17ae 2428 }
3064bf43 2429
d62a17ae 2430 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2431 return false;
3064bf43 2432}
2433
d62a17ae 2434struct bgp_process_queue {
2435 struct bgp *bgp;
9bcb3eef 2436 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2437#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2438 unsigned int flags;
2439 unsigned int queued;
200df115 2440};
2441
3b0c17e1 2442static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2443 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2444 struct bgp_path_info *new_select,
2445 struct bgp_path_info *old_select)
2446{
9bcb3eef 2447 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2448
2449 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2450 return;
2451
2452 if (advertise_type5_routes(bgp, afi) && new_select
2453 && is_route_injectable_into_evpn(new_select)) {
2454
2455 /* apply the route-map */
2456 if (bgp->adv_cmd_rmap[afi][safi].map) {
2457 route_map_result_t ret;
2458 struct bgp_path_info rmap_path;
2459 struct bgp_path_info_extra rmap_path_extra;
2460 struct attr dummy_attr;
2461
2462 dummy_attr = *new_select->attr;
2463
2464 /* Fill temp path_info */
9bcb3eef 2465 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2466 new_select, new_select->peer,
2467 &dummy_attr);
2468
2469 RESET_FLAG(dummy_attr.rmap_change_flags);
2470
2471 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
2472 p, RMAP_BGP, &rmap_path);
2473
2474 if (ret == RMAP_DENYMATCH) {
2475 bgp_attr_flush(&dummy_attr);
2476 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2477 safi);
2478 } else
2479 bgp_evpn_advertise_type5_route(
2480 bgp, p, &dummy_attr, afi, safi);
2481 } else {
2482 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2483 afi, safi);
2484 }
2485 } else if (advertise_type5_routes(bgp, afi) && old_select
2486 && is_route_injectable_into_evpn(old_select))
2487 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2488}
2489
3103e8d2
DS
2490/*
2491 * old_select = The old best path
2492 * new_select = the new best path
2493 *
2494 * if (!old_select && new_select)
2495 * We are sending new information on.
2496 *
2497 * if (old_select && new_select) {
2498 * if (new_select != old_select)
2499 * We have a new best path send a change
2500 * else
2501 * We've received a update with new attributes that needs
2502 * to be passed on.
2503 * }
2504 *
2505 * if (old_select && !new_select)
2506 * We have no eligible route that we can announce or the rn
2507 * is being removed.
2508 */
9bcb3eef 2509static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2510 afi_t afi, safi_t safi)
d62a17ae 2511{
4b7e6066
DS
2512 struct bgp_path_info *new_select;
2513 struct bgp_path_info *old_select;
2514 struct bgp_path_info_pair old_and_new;
ddb5b488 2515 int debug = 0;
d62a17ae 2516
892fedb6 2517 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2518 if (dest)
2519 debug = bgp_debug_bestpath(dest);
b54892e0 2520 if (debug)
f4c713ae 2521 zlog_debug(
b54892e0 2522 "%s: bgp delete in progress, ignoring event, p=%pRN",
9bcb3eef 2523 __func__, dest);
f4c713ae
LB
2524 return;
2525 }
d62a17ae 2526 /* Is it end of initial update? (after startup) */
9bcb3eef 2527 if (!dest) {
d62a17ae 2528 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2529 sizeof(bgp->update_delay_zebra_resume_time));
2530
2531 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2532 FOREACH_AFI_SAFI (afi, safi) {
2533 if (bgp_fibupd_safi(safi))
2534 bgp_zebra_announce_table(bgp, afi, safi);
2535 }
d62a17ae 2536 bgp->main_peers_update_hold = 0;
2537
2538 bgp_start_routeadv(bgp);
aac24838 2539 return;
d62a17ae 2540 }
cb1faec9 2541
9bcb3eef 2542 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2543
9bcb3eef 2544 debug = bgp_debug_bestpath(dest);
b54892e0 2545 if (debug)
9bcb3eef 2546 zlog_debug("%s: p=%pRN afi=%s, safi=%s start", __func__, dest,
ddb5b488 2547 afi2str(afi), safi2str(safi));
ddb5b488 2548
f009ff26 2549 /* The best path calculation for the route is deferred if
2550 * BGP_NODE_SELECT_DEFER is set
2551 */
9bcb3eef 2552 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2553 if (BGP_DEBUG(update, UPDATE_OUT))
9bcb3eef 2554 zlog_debug("SELECT_DEFER falg set for route %p", dest);
f009ff26 2555 return;
2556 }
2557
d62a17ae 2558 /* Best path selection. */
9bcb3eef 2559 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2560 afi, safi);
2561 old_select = old_and_new.old;
2562 new_select = old_and_new.new;
2563
2564 /* Do we need to allocate or free labels?
2565 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2566 * necessary to do this upon changes to best path. Exceptions:
2567 * - label index has changed -> recalculate resulting label
2568 * - path_info sub_type changed -> switch to/from implicit-null
2569 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2570 */
318cac96 2571 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2572 if (new_select) {
2573 if (!old_select
2574 || bgp_label_index_differs(new_select, old_select)
57592a53 2575 || new_select->sub_type != old_select->sub_type
9bcb3eef 2576 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2577 /* Enforced penultimate hop popping:
2578 * implicit-null for local routes, aggregate
2579 * and redistributed routes
2580 */
d62a17ae 2581 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2582 || new_select->sub_type
2583 == BGP_ROUTE_AGGREGATE
2584 || new_select->sub_type
2585 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2586 if (CHECK_FLAG(
9bcb3eef 2587 dest->flags,
d62a17ae 2588 BGP_NODE_REGISTERED_FOR_LABEL))
9bcb3eef 2589 bgp_unregister_for_label(dest);
70e98a7f 2590 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2591 &dest->local_label);
2592 bgp_set_valid_label(&dest->local_label);
d62a17ae 2593 } else
9bcb3eef
DS
2594 bgp_register_for_label(dest,
2595 new_select);
d62a17ae 2596 }
9bcb3eef 2597 } else if (CHECK_FLAG(dest->flags,
a4d82a8a 2598 BGP_NODE_REGISTERED_FOR_LABEL)) {
9bcb3eef 2599 bgp_unregister_for_label(dest);
318cac96 2600 }
9bcb3eef
DS
2601 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
2602 bgp_unregister_for_label(dest);
d62a17ae 2603 }
cd1964ff 2604
b54892e0 2605 if (debug)
ddb5b488 2606 zlog_debug(
b54892e0 2607 "%s: p=%pRN afi=%s, safi=%s, old_select=%p, new_select=%p",
9bcb3eef 2608 __func__, dest, afi2str(afi), safi2str(safi),
ddb5b488 2609 old_select, new_select);
ddb5b488 2610
d62a17ae 2611 /* If best route remains the same and this is not due to user-initiated
2612 * clear, see exactly what needs to be done.
2613 */
d62a17ae 2614 if (old_select && old_select == new_select
9bcb3eef 2615 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2616 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2617 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2618 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2619#ifdef ENABLE_BGP_VNC
d62a17ae 2620 vnc_import_bgp_add_route(bgp, p, old_select);
2621 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2622#endif
bb744275 2623 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2624 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2625
2626 if (new_select->type == ZEBRA_ROUTE_BGP
2627 && (new_select->sub_type == BGP_ROUTE_NORMAL
2628 || new_select->sub_type
2629 == BGP_ROUTE_IMPORTED))
2630
9bcb3eef 2631 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
2632 bgp, afi, safi);
2633 }
d62a17ae 2634 }
d62a17ae 2635
2636 /* If there is a change of interest to peers, reannounce the
2637 * route. */
1defdda8 2638 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 2639 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
2640 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2641 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2642
2643 /* unicast routes must also be annouced to
2644 * labeled-unicast update-groups */
2645 if (safi == SAFI_UNICAST)
2646 group_announce_route(bgp, afi,
9bcb3eef 2647 SAFI_LABELED_UNICAST, dest,
d62a17ae 2648 new_select);
2649
1defdda8 2650 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 2651 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 2652 }
fee0f4c6 2653
3b0c17e1 2654 /* advertise/withdraw type-5 routes */
2655 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2656 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2657 bgp_process_evpn_route_injection(
9bcb3eef 2658 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 2659
b1875e65 2660 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2661 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
2662 bgp_zebra_clear_route_change_flags(dest);
2663 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2664 return;
d62a17ae 2665 }
8ad7271d 2666
d62a17ae 2667 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2668 */
9bcb3eef 2669 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 2670
2671 /* bestpath has changed; bump version */
2672 if (old_select || new_select) {
9bcb3eef 2673 bgp_bump_version(dest);
d62a17ae 2674
2675 if (!bgp->t_rmap_def_originate_eval) {
2676 bgp_lock(bgp);
2677 thread_add_timer(
2678 bm->master,
2679 update_group_refresh_default_originate_route_map,
2680 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2681 &bgp->t_rmap_def_originate_eval);
2682 }
2683 }
3f9c7369 2684
d62a17ae 2685 if (old_select)
9bcb3eef 2686 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 2687 if (new_select) {
ddb5b488
PZ
2688 if (debug)
2689 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
2690 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2691 bgp_path_info_unset_flag(dest, new_select,
2692 BGP_PATH_ATTR_CHANGED);
1defdda8 2693 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 2694 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 2695 }
338b3424 2696
49e5a4a0 2697#ifdef ENABLE_BGP_VNC
d62a17ae 2698 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2699 if (old_select != new_select) {
2700 if (old_select) {
2701 vnc_import_bgp_exterior_del_route(bgp, p,
2702 old_select);
2703 vnc_import_bgp_del_route(bgp, p, old_select);
2704 }
2705 if (new_select) {
2706 vnc_import_bgp_exterior_add_route(bgp, p,
2707 new_select);
2708 vnc_import_bgp_add_route(bgp, p, new_select);
2709 }
2710 }
2711 }
65efcfce
LB
2712#endif
2713
9bcb3eef 2714 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2715
2716 /* unicast routes must also be annouced to labeled-unicast update-groups
2717 */
2718 if (safi == SAFI_UNICAST)
9bcb3eef 2719 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 2720 new_select);
2721
2722 /* FIB update. */
2723 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2724 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2725 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2726 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2727 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2728 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2729
2730 /* if this is an evpn imported type-5 prefix,
2731 * we need to withdraw the route first to clear
2732 * the nh neigh and the RMAC entry.
2733 */
2734 if (old_select &&
2735 is_route_parent_evpn(old_select))
2736 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2737
9bcb3eef 2738 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 2739 } else {
d62a17ae 2740 /* Withdraw the route from the kernel. */
2741 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2742 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2743 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2744 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2745
568e10ca 2746 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2747 }
718e3744 2748 }
3064bf43 2749
9bcb3eef 2750 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 2751 old_select);
5424b7ba 2752
d62a17ae 2753 /* Clear any route change flags. */
9bcb3eef 2754 bgp_zebra_clear_route_change_flags(dest);
3064bf43 2755
18ee8310 2756 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2757 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 2758 bgp_path_info_reap(dest, old_select);
d62a17ae 2759
9bcb3eef 2760 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2761 return;
718e3744 2762}
2763
f009ff26 2764/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2765int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2766{
9bcb3eef 2767 struct bgp_dest *dest;
f009ff26 2768 int cnt = 0;
2769 struct afi_safi_info *thread_info;
2770 struct listnode *node = NULL, *nnode = NULL;
2771
2772 if (bgp->gr_info[afi][safi].t_route_select)
2773 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
2774
2775 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
2776 zlog_debug("%s: processing route for %s : cnt %d", __func__,
2777 get_afi_safi_str(afi, safi, false),
2778 listcount(bgp->gr_info[afi][safi].route_list));
f009ff26 2779 }
2780
2781 /* Process the route list */
2782 node = listhead(bgp->gr_info[afi][safi].route_list);
f009ff26 2783 while (node) {
9bcb3eef 2784 dest = listgetdata(node);
f009ff26 2785 nnode = node->next;
2786 list_delete_node(bgp->gr_info[afi][safi].route_list, node);
9bcb3eef 2787 dest->rt_node = NULL;
f009ff26 2788
9bcb3eef
DS
2789 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
2790 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
2791 bgp_process_main_one(bgp, dest, afi, safi);
f009ff26 2792 cnt++;
2793 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT)
2794 break;
2795 }
2796 node = nnode;
2797 }
2798
9e3b51a7 2799 /* Send EOR message when all routes are processed */
2800 if (list_isempty(bgp->gr_info[afi][safi].route_list)) {
2801 bgp_send_delayed_eor(bgp);
8c48b3b6 2802 /* Send route processing complete message to RIB */
2803 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 2804 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 2805 return 0;
9e3b51a7 2806 }
f009ff26 2807
2808 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 2809
2810 thread_info->afi = afi;
2811 thread_info->safi = safi;
2812 thread_info->bgp = bgp;
2813
2814 /* If there are more routes to be processed, start the
2815 * selection timer
2816 */
2817 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
2818 BGP_ROUTE_SELECT_DELAY,
2819 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 2820 return 0;
2821}
2822
aac24838 2823static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 2824{
aac24838
JB
2825 struct bgp_process_queue *pqnode = data;
2826 struct bgp *bgp = pqnode->bgp;
d62a17ae 2827 struct bgp_table *table;
9bcb3eef 2828 struct bgp_dest *dest;
aac24838
JB
2829
2830 /* eoiu marker */
2831 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
2832 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
2833 /* should always have dedicated wq call */
2834 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
2835 return WQ_SUCCESS;
2836 }
2837
ac021f40 2838 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 2839 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 2840 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
2841 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
2842 table = bgp_dest_table(dest);
2843 /* note, new DESTs may be added as part of processing */
2844 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 2845
9bcb3eef 2846 bgp_dest_unlock_node(dest);
d62a17ae 2847 bgp_table_unlock(table);
2848 }
aac24838
JB
2849
2850 return WQ_SUCCESS;
2851}
2852
2853static void bgp_processq_del(struct work_queue *wq, void *data)
2854{
2855 struct bgp_process_queue *pqnode = data;
2856
2857 bgp_unlock(pqnode->bgp);
2858
2859 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 2860}
2861
d62a17ae 2862void bgp_process_queue_init(void)
200df115 2863{
0ce1ca80 2864 if (!bm->process_main_queue)
d62a17ae 2865 bm->process_main_queue =
2866 work_queue_new(bm->master, "process_main_queue");
2867
aac24838 2868 bm->process_main_queue->spec.workfunc = &bgp_process_wq;
d62a17ae 2869 bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
2870 bm->process_main_queue->spec.max_retries = 0;
2871 bm->process_main_queue->spec.hold = 50;
2872 /* Use a higher yield value of 50ms for main queue processing */
2873 bm->process_main_queue->spec.yield = 50 * 1000L;
200df115 2874}
2875
cfe8d15a 2876static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
2877{
2878 struct bgp_process_queue *pqnode;
2879
a4d82a8a
PZ
2880 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
2881 sizeof(struct bgp_process_queue));
aac24838
JB
2882
2883 /* unlocked in bgp_processq_del */
2884 pqnode->bgp = bgp_lock(bgp);
2885 STAILQ_INIT(&pqnode->pqueue);
2886
aac24838
JB
2887 return pqnode;
2888}
2889
9bcb3eef 2890void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 2891{
aac24838
JB
2892#define ARBITRARY_PROCESS_QLEN 10000
2893 struct work_queue *wq = bm->process_main_queue;
d62a17ae 2894 struct bgp_process_queue *pqnode;
cfe8d15a 2895 int pqnode_reuse = 0;
495f0b13 2896
d62a17ae 2897 /* already scheduled for processing? */
9bcb3eef 2898 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 2899 return;
2e02b9b2 2900
f009ff26 2901 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
2902 * the workqueue
2903 */
9bcb3eef 2904 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2905 if (BGP_DEBUG(update, UPDATE_OUT))
2906 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 2907 dest);
f009ff26 2908 return;
2909 }
2910
aac24838 2911 if (wq == NULL)
d62a17ae 2912 return;
2913
aac24838 2914 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
2915 limit only if is from the same BGP view and it's not an EOIU marker
2916 */
aac24838
JB
2917 if (work_queue_item_count(wq)) {
2918 struct work_queue_item *item = work_queue_last_item(wq);
2919 pqnode = item->data;
228da428 2920
a4d82a8a
PZ
2921 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
2922 || pqnode->bgp != bgp
2923 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
2924 pqnode = bgp_processq_alloc(bgp);
2925 else
2926 pqnode_reuse = 1;
aac24838 2927 } else
cfe8d15a 2928 pqnode = bgp_processq_alloc(bgp);
aac24838 2929 /* all unlocked in bgp_process_wq */
9bcb3eef 2930 bgp_table_lock(bgp_dest_table(dest));
aac24838 2931
9bcb3eef
DS
2932 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
2933 bgp_dest_lock_node(dest);
aac24838 2934
60466a63 2935 /* can't be enqueued twice */
9bcb3eef
DS
2936 assert(STAILQ_NEXT(dest, pq) == NULL);
2937 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
2938 pqnode->queued++;
2939
cfe8d15a
LB
2940 if (!pqnode_reuse)
2941 work_queue_add(wq, pqnode);
2942
d62a17ae 2943 return;
fee0f4c6 2944}
0a486e5f 2945
d62a17ae 2946void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 2947{
d62a17ae 2948 struct bgp_process_queue *pqnode;
cb1faec9 2949
d62a17ae 2950 if (bm->process_main_queue == NULL)
2951 return;
2e02b9b2 2952
cfe8d15a 2953 pqnode = bgp_processq_alloc(bgp);
cb1faec9 2954
aac24838 2955 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
cfe8d15a 2956 work_queue_add(bm->process_main_queue, pqnode);
cb1faec9
DS
2957}
2958
d62a17ae 2959static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 2960{
d62a17ae 2961 struct peer *peer;
0a486e5f 2962
d62a17ae 2963 peer = THREAD_ARG(thread);
2964 peer->t_pmax_restart = NULL;
0a486e5f 2965
d62a17ae 2966 if (bgp_debug_neighbor_events(peer))
2967 zlog_debug(
2968 "%s Maximum-prefix restart timer expired, restore peering",
2969 peer->host);
0a486e5f 2970
a9bafa95 2971 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 2972 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 2973
d62a17ae 2974 return 0;
0a486e5f 2975}
2976
3dc339cd
DA
2977bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
2978 int always)
718e3744 2979{
d62a17ae 2980 iana_afi_t pkt_afi;
5c525538 2981 iana_safi_t pkt_safi;
9cabb64b 2982
d62a17ae 2983 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 2984 return false;
e0701b79 2985
d62a17ae 2986 if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) {
2987 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2988 PEER_STATUS_PREFIX_LIMIT)
2989 && !always)
3dc339cd 2990 return false;
e0701b79 2991
d62a17ae 2992 zlog_info(
6cde4b45 2993 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
5cb5f4d0 2994 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 2995 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2996 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
2997
2998 if (CHECK_FLAG(peer->af_flags[afi][safi],
2999 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3000 return false;
d62a17ae 3001
3002 /* Convert AFI, SAFI to values for packet. */
3003 pkt_afi = afi_int2iana(afi);
3004 pkt_safi = safi_int2iana(safi);
3005 {
d7c0a89a 3006 uint8_t ndata[7];
d62a17ae 3007
3008 ndata[0] = (pkt_afi >> 8);
3009 ndata[1] = pkt_afi;
3010 ndata[2] = pkt_safi;
3011 ndata[3] = (peer->pmax[afi][safi] >> 24);
3012 ndata[4] = (peer->pmax[afi][safi] >> 16);
3013 ndata[5] = (peer->pmax[afi][safi] >> 8);
3014 ndata[6] = (peer->pmax[afi][safi]);
3015
3016 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3017 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3018 BGP_NOTIFY_CEASE_MAX_PREFIX,
3019 ndata, 7);
3020 }
3021
3022 /* Dynamic peers will just close their connection. */
3023 if (peer_dynamic_neighbor(peer))
3dc339cd 3024 return true;
d62a17ae 3025
3026 /* restart timer start */
3027 if (peer->pmax_restart[afi][safi]) {
3028 peer->v_pmax_restart =
3029 peer->pmax_restart[afi][safi] * 60;
3030
3031 if (bgp_debug_neighbor_events(peer))
3032 zlog_debug(
3033 "%s Maximum-prefix restart timer started for %d secs",
3034 peer->host, peer->v_pmax_restart);
3035
3036 BGP_TIMER_ON(peer->t_pmax_restart,
3037 bgp_maximum_prefix_restart_timer,
3038 peer->v_pmax_restart);
3039 }
3040
3dc339cd 3041 return true;
d62a17ae 3042 } else
3043 UNSET_FLAG(peer->af_sflags[afi][safi],
3044 PEER_STATUS_PREFIX_LIMIT);
3045
3046 if (peer->pcount[afi][safi]
3047 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
3048 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3049 PEER_STATUS_PREFIX_THRESHOLD)
3050 && !always)
3dc339cd 3051 return false;
d62a17ae 3052
3053 zlog_info(
6cde4b45 3054 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
5cb5f4d0 3055 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 3056 peer->pcount[afi][safi], peer->pmax[afi][safi]);
3057 SET_FLAG(peer->af_sflags[afi][safi],
3058 PEER_STATUS_PREFIX_THRESHOLD);
3059 } else
3060 UNSET_FLAG(peer->af_sflags[afi][safi],
3061 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3062 return false;
718e3744 3063}
3064
b40d939b 3065/* Unconditionally remove the route from the RIB, without taking
3066 * damping into consideration (eg, because the session went down)
3067 */
9bcb3eef 3068void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3069 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3070{
f009ff26 3071
3072 struct bgp *bgp = NULL;
3073 bool delete_route = false;
3074
9bcb3eef
DS
3075 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3076 safi);
d62a17ae 3077
f009ff26 3078 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3079 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3080
f009ff26 3081 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3082 * flag
3083 */
3084 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3085 delete_route = true;
9bcb3eef 3086 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3087 delete_route = true;
f009ff26 3088 if (delete_route) {
9bcb3eef
DS
3089 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3090 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3091 bgp = pi->peer->bgp;
9bcb3eef 3092 if ((dest->rt_node)
36235319
QY
3093 && (bgp->gr_info[afi][safi].route_list)) {
3094 list_delete_node(bgp->gr_info[afi][safi]
3095 .route_list,
9bcb3eef
DS
3096 dest->rt_node);
3097 dest->rt_node = NULL;
f009ff26 3098 }
3099 }
3100 }
3101 }
4a11bf2c 3102
9bcb3eef
DS
3103 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3104 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3105}
3106
9bcb3eef 3107static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3108 struct peer *peer, afi_t afi, safi_t safi,
3109 struct prefix_rd *prd)
3110{
9bcb3eef 3111 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3112
d62a17ae 3113 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3114 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3115 */
3116 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3117 && peer->sort == BGP_PEER_EBGP)
9bcb3eef 3118 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
d62a17ae 3119 == BGP_DAMP_SUPPRESSED) {
b54892e0 3120 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
d62a17ae 3121 safi);
3122 return;
3123 }
3124
49e5a4a0 3125#ifdef ENABLE_BGP_VNC
d62a17ae 3126 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3127 struct bgp_dest *pdest = NULL;
d62a17ae 3128 struct bgp_table *table = NULL;
3129
9bcb3eef
DS
3130 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3131 (struct prefix *)prd);
3132 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3133 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3134
3135 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3136 peer->bgp, prd, table, p, pi);
d62a17ae 3137 }
9bcb3eef 3138 bgp_dest_unlock_node(pdest);
d62a17ae 3139 }
3140 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3141 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3142
b54892e0
DS
3143 vnc_import_bgp_del_route(peer->bgp, p, pi);
3144 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3145 }
65efcfce 3146 }
d62a17ae 3147#endif
128ea8ab 3148
d62a17ae 3149 /* If this is an EVPN route, process for un-import. */
3150 if (safi == SAFI_EVPN)
b54892e0 3151 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3152
9bcb3eef 3153 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3154}
3155
4b7e6066
DS
3156struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3157 struct peer *peer, struct attr *attr,
9bcb3eef 3158 struct bgp_dest *dest)
fb018d25 3159{
4b7e6066 3160 struct bgp_path_info *new;
fb018d25 3161
d62a17ae 3162 /* Make new BGP info. */
4b7e6066 3163 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3164 new->type = type;
3165 new->instance = instance;
3166 new->sub_type = sub_type;
3167 new->peer = peer;
3168 new->attr = attr;
3169 new->uptime = bgp_clock();
9bcb3eef 3170 new->net = dest;
d62a17ae 3171 return new;
fb018d25
DS
3172}
3173
d62a17ae 3174static void overlay_index_update(struct attr *attr,
3175 struct eth_segment_id *eth_s_id,
3176 union gw_addr *gw_ip)
684a7227 3177{
d62a17ae 3178 if (!attr)
3179 return;
684a7227 3180
d62a17ae 3181 if (eth_s_id == NULL) {
3182 memset(&(attr->evpn_overlay.eth_s_id), 0,
3183 sizeof(struct eth_segment_id));
3184 } else {
3185 memcpy(&(attr->evpn_overlay.eth_s_id), eth_s_id,
3186 sizeof(struct eth_segment_id));
3187 }
3188 if (gw_ip == NULL) {
3189 memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr));
3190 } else {
3191 memcpy(&(attr->evpn_overlay.gw_ip), gw_ip,
3192 sizeof(union gw_addr));
3193 }
684a7227
PG
3194}
3195
40381db7 3196static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3197 struct eth_segment_id *eth_s_id,
3198 union gw_addr *gw_ip)
3199{
40381db7
DS
3200 struct eth_segment_id *path_eth_s_id, *path_eth_s_id_remote;
3201 union gw_addr *path_gw_ip, *path_gw_ip_remote;
11ebf4ed
DS
3202 union {
3203 struct eth_segment_id esi;
3204 union gw_addr ip;
3205 } temp;
d62a17ae 3206
3207 if (afi != AFI_L2VPN)
3208 return true;
11ebf4ed 3209
05864da7
DS
3210 path_eth_s_id = &(path->attr->evpn_overlay.eth_s_id);
3211 path_gw_ip = &(path->attr->evpn_overlay.gw_ip);
11ebf4ed
DS
3212
3213 if (gw_ip == NULL) {
3214 memset(&temp, 0, sizeof(temp));
40381db7 3215 path_gw_ip_remote = &temp.ip;
11ebf4ed 3216 } else
40381db7 3217 path_gw_ip_remote = gw_ip;
11ebf4ed
DS
3218
3219 if (eth_s_id == NULL) {
3220 memset(&temp, 0, sizeof(temp));
40381db7 3221 path_eth_s_id_remote = &temp.esi;
11ebf4ed 3222 } else
40381db7 3223 path_eth_s_id_remote = eth_s_id;
11ebf4ed 3224
40381db7 3225 if (!memcmp(path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr)))
d62a17ae 3226 return false;
11ebf4ed 3227
40381db7 3228 return !memcmp(path_eth_s_id, path_eth_s_id_remote,
d62a17ae 3229 sizeof(struct eth_segment_id));
684a7227
PG
3230}
3231
c265ee22 3232/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3233bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3234 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3235 struct bgp_dest *dest)
d62a17ae 3236{
2dbe3fa9 3237 bool ret = false;
b099a5c8
DA
3238 bool is_bgp_static_route =
3239 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3240 : false;
d62a17ae 3241
3242 /* Only validated for unicast and multicast currently. */
3243 /* Also valid for EVPN where the nexthop is an IP address. */
3244 if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN)
3dc339cd 3245 return false;
d62a17ae 3246
3247 /* If NEXT_HOP is present, validate it. */
3248 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
b099a5c8 3249 if ((attr->nexthop.s_addr == INADDR_ANY && !is_bgp_static_route)
d62a17ae 3250 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3251 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3252 return true;
d62a17ae 3253 }
c265ee22 3254
d62a17ae 3255 /* If MP_NEXTHOP is present, validate it. */
3256 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3257 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3258 * it is not an IPv6 link-local address.
0355b41d
DA
3259 *
3260 * If we receive an UPDATE with nexthop length set to 32 bytes
3261 * we shouldn't discard an UPDATE if it's set to (::).
3262 * The link-local (2st) is validated along the code path later.
d62a17ae 3263 */
3264 if (attr->mp_nexthop_len) {
3265 switch (attr->mp_nexthop_len) {
3266 case BGP_ATTR_NHLEN_IPV4:
3267 case BGP_ATTR_NHLEN_VPNV4:
b099a5c8
DA
3268 ret = ((attr->mp_nexthop_global_in.s_addr == INADDR_ANY
3269 && !is_bgp_static_route)
975a328e
DA
3270 || IPV4_CLASS_DE(
3271 ntohl(attr->mp_nexthop_global_in.s_addr))
3272 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3273 dest));
d62a17ae 3274 break;
3275
3276 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3277 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
b099a5c8
DA
3278 ret = ((IN6_IS_ADDR_UNSPECIFIED(
3279 &attr->mp_nexthop_global)
3280 && !is_bgp_static_route)
d62a17ae 3281 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3282 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3283 &attr->mp_nexthop_global)
3284 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3285 dest));
d62a17ae 3286 break;
0355b41d
DA
3287 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3288 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3289 || IN6_IS_ADDR_MULTICAST(
3290 &attr->mp_nexthop_global)
3291 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3292 dest));
0355b41d 3293 break;
d62a17ae 3294
3295 default:
3dc339cd 3296 ret = true;
d62a17ae 3297 break;
3298 }
3299 }
c265ee22 3300
d62a17ae 3301 return ret;
3302}
3303
5a1ae2c2 3304int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3305 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3306 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3307 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3308 struct bgp_route_evpn *evpn)
d62a17ae 3309{
3310 int ret;
3311 int aspath_loop_count = 0;
9bcb3eef 3312 struct bgp_dest *dest;
d62a17ae 3313 struct bgp *bgp;
3314 struct attr new_attr;
3315 struct attr *attr_new;
40381db7 3316 struct bgp_path_info *pi;
4b7e6066
DS
3317 struct bgp_path_info *new;
3318 struct bgp_path_info_extra *extra;
d62a17ae 3319 const char *reason;
3320 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3321 int connected = 0;
3322 int do_loop_check = 1;
3323 int has_valid_label = 0;
7c312383 3324 afi_t nh_afi;
949b0f24 3325 uint8_t pi_type = 0;
3326 uint8_t pi_sub_type = 0;
3327
49e5a4a0 3328#ifdef ENABLE_BGP_VNC
d62a17ae 3329 int vnc_implicit_withdraw = 0;
65efcfce 3330#endif
d62a17ae 3331 int same_attr = 0;
718e3744 3332
d62a17ae 3333 memset(&new_attr, 0, sizeof(struct attr));
3334 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3335 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3336
d62a17ae 3337 bgp = peer->bgp;
9bcb3eef 3338 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3339 /* TODO: Check to see if we can get rid of "is_valid_label" */
3340 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3341 has_valid_label = (num_labels > 0) ? 1 : 0;
3342 else
3343 has_valid_label = bgp_is_valid_label(label);
718e3744 3344
d62a17ae 3345 /* When peer's soft reconfiguration enabled. Record input packet in
3346 Adj-RIBs-In. */
3347 if (!soft_reconfig
3348 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3349 && peer != bgp->peer_self)
9bcb3eef 3350 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3351
3352 /* Check previously received route. */
9bcb3eef 3353 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3354 if (pi->peer == peer && pi->type == type
3355 && pi->sub_type == sub_type
3356 && pi->addpath_rx_id == addpath_id)
d62a17ae 3357 break;
3358
3359 /* AS path local-as loop check. */
3360 if (peer->change_local_as) {
c4368918
DW
3361 if (peer->allowas_in[afi][safi])
3362 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3363 else if (!CHECK_FLAG(peer->flags,
3364 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3365 aspath_loop_count = 1;
3366
3367 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3368 > aspath_loop_count) {
b4d46cc9 3369 peer->stat_pfx_aspath_loop++;
9bcb3eef 3370 reason = "as-path contains our own AS A;";
d62a17ae 3371 goto filtered;
3372 }
718e3744 3373 }
718e3744 3374
d62a17ae 3375 /* If the peer is configured for "allowas-in origin" and the last ASN in
3376 * the
3377 * as-path is our ASN then we do not need to call aspath_loop_check
3378 */
3379 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3380 if (aspath_get_last_as(attr->aspath) == bgp->as)
3381 do_loop_check = 0;
3382
3383 /* AS path loop check. */
3384 if (do_loop_check) {
3385 if (aspath_loop_check(attr->aspath, bgp->as)
3386 > peer->allowas_in[afi][safi]
3387 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3388 && aspath_loop_check(attr->aspath, bgp->confed_id)
3389 > peer->allowas_in[afi][safi])) {
b4d46cc9 3390 peer->stat_pfx_aspath_loop++;
d62a17ae 3391 reason = "as-path contains our own AS;";
3392 goto filtered;
3393 }
3394 }
aac9ef6c 3395
d62a17ae 3396 /* Route reflector originator ID check. */
3397 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3398 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3399 peer->stat_pfx_originator_loop++;
d62a17ae 3400 reason = "originator is us;";
3401 goto filtered;
3402 }
718e3744 3403
d62a17ae 3404 /* Route reflector cluster ID check. */
3405 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3406 peer->stat_pfx_cluster_loop++;
d62a17ae 3407 reason = "reflected from the same cluster;";
3408 goto filtered;
3409 }
718e3744 3410
d62a17ae 3411 /* Apply incoming filter. */
3412 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3413 peer->stat_pfx_filter++;
d62a17ae 3414 reason = "filter;";
3415 goto filtered;
3416 }
718e3744 3417
a8b72dc6
DA
3418 /* RFC 8212 to prevent route leaks.
3419 * This specification intends to improve this situation by requiring the
3420 * explicit configuration of both BGP Import and Export Policies for any
3421 * External BGP (EBGP) session such as customers, peers, or
3422 * confederation boundaries for all enabled address families. Through
3423 * codification of the aforementioned requirement, operators will
3424 * benefit from consistent behavior across different BGP
3425 * implementations.
3426 */
1d3fdccf 3427 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3428 if (!bgp_inbound_policy_exists(peer,
3429 &peer->filter[afi][safi])) {
3430 reason = "inbound policy missing";
3431 goto filtered;
3432 }
3433
fb29348a
DA
3434 /* draft-ietf-idr-deprecate-as-set-confed-set
3435 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3436 * Eventually, This document (if approved) updates RFC 4271
3437 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3438 * and obsoletes RFC 6472.
3439 */
7f972cd8 3440 if (peer->bgp->reject_as_sets)
fb29348a
DA
3441 if (aspath_check_as_sets(attr->aspath)) {
3442 reason =
3443 "as-path contains AS_SET or AS_CONFED_SET type;";
3444 goto filtered;
3445 }
3446
6f4f49b2 3447 new_attr = *attr;
d62a17ae 3448
3449 /* Apply incoming route-map.
3450 * NB: new_attr may now contain newly allocated values from route-map
3451 * "set"
3452 * commands, so we need bgp_attr_flush in the error paths, until we
3453 * intern
3454 * the attr (which takes over the memory references) */
9bcb3eef
DS
3455 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3456 num_labels, dest)
3457 == RMAP_DENY) {
b4d46cc9 3458 peer->stat_pfx_filter++;
d62a17ae 3459 reason = "route-map;";
3460 bgp_attr_flush(&new_attr);
3461 goto filtered;
3462 }
718e3744 3463
05864da7 3464 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3465 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3466 /* remove from RIB previous entry */
3467 bgp_zebra_withdraw(p, pi, bgp, safi);
3468 }
3469
7f323236
DW
3470 if (peer->sort == BGP_PEER_EBGP) {
3471
a4d82a8a
PZ
3472 /* If we receive the graceful-shutdown community from an eBGP
3473 * peer we must lower local-preference */
3474 if (new_attr.community
3475 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3476 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3477 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3478
a4d82a8a
PZ
3479 /* If graceful-shutdown is configured then add the GSHUT
3480 * community to all paths received from eBGP peers */
892fedb6
DA
3481 } else if (CHECK_FLAG(peer->bgp->flags,
3482 BGP_FLAG_GRACEFUL_SHUTDOWN))
7f323236 3483 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3484 }
3485
949b0f24 3486 if (pi) {
3487 pi_type = pi->type;
3488 pi_sub_type = pi->sub_type;
3489 }
3490
d62a17ae 3491 /* next hop check. */
a4d82a8a 3492 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3493 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3494 &new_attr, dest)) {
b4d46cc9 3495 peer->stat_pfx_nh_invalid++;
d62a17ae 3496 reason = "martian or self next-hop;";
3497 bgp_attr_flush(&new_attr);
3498 goto filtered;
3499 }
718e3744 3500
5c14a191 3501 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3502 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3503 reason = "self mac;";
3504 goto filtered;
3505 }
3506
d62a17ae 3507 attr_new = bgp_attr_intern(&new_attr);
3508
3509 /* If the update is implicit withdraw. */
40381db7
DS
3510 if (pi) {
3511 pi->uptime = bgp_clock();
3512 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3513
9bcb3eef 3514 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3515
d62a17ae 3516 /* Same attribute comes in. */
40381db7
DS
3517 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3518 && attrhash_cmp(pi->attr, attr_new)
d62a17ae 3519 && (!has_valid_label
40381db7 3520 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3521 num_labels * sizeof(mpls_label_t))
d62a17ae 3522 == 0)
3523 && (overlay_index_equal(
40381db7 3524 afi, pi, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3525 evpn == NULL ? NULL : &evpn->gw_ip))) {
3526 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3527 BGP_CONFIG_DAMPENING)
3528 && peer->sort == BGP_PEER_EBGP
40381db7 3529 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3530 if (bgp_debug_update(peer, p, NULL, 1)) {
3531 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3532 afi, safi, prd, p, label,
3533 num_labels, addpath_id ? 1 : 0,
3534 addpath_id, pfx_buf,
3535 sizeof(pfx_buf));
d62a17ae 3536 zlog_debug("%s rcvd %s", peer->host,
3537 pfx_buf);
3538 }
3539
9bcb3eef 3540 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 3541 != BGP_DAMP_SUPPRESSED) {
40381db7 3542 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3543 safi);
9bcb3eef 3544 bgp_process(bgp, dest, afi, safi);
d62a17ae 3545 }
3546 } else /* Duplicate - odd */
3547 {
3548 if (bgp_debug_update(peer, p, NULL, 1)) {
3549 if (!peer->rcvd_attr_printed) {
3550 zlog_debug(
3551 "%s rcvd UPDATE w/ attr: %s",
3552 peer->host,
3553 peer->rcvd_attr_str);
3554 peer->rcvd_attr_printed = 1;
3555 }
3556
3557 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3558 afi, safi, prd, p, label,
3559 num_labels, addpath_id ? 1 : 0,
3560 addpath_id, pfx_buf,
3561 sizeof(pfx_buf));
d62a17ae 3562 zlog_debug(
3563 "%s rcvd %s...duplicate ignored",
3564 peer->host, pfx_buf);
3565 }
3566
3567 /* graceful restart STALE flag unset. */
40381db7 3568 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3569 bgp_path_info_unset_flag(
9bcb3eef
DS
3570 dest, pi, BGP_PATH_STALE);
3571 bgp_dest_set_defer_flag(dest, false);
3572 bgp_process(bgp, dest, afi, safi);
d62a17ae 3573 }
3574 }
3575
9bcb3eef 3576 bgp_dest_unlock_node(dest);
d62a17ae 3577 bgp_attr_unintern(&attr_new);
3578
3579 return 0;
3580 }
718e3744 3581
d62a17ae 3582 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3583 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3584 if (bgp_debug_update(peer, p, NULL, 1)) {
3585 bgp_debug_rdpfxpath2str(
a4d82a8a 3586 afi, safi, prd, p, label, num_labels,
d62a17ae 3587 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3588 sizeof(pfx_buf));
3589 zlog_debug(
3590 "%s rcvd %s, flapped quicker than processing",
3591 peer->host, pfx_buf);
3592 }
3593
9bcb3eef 3594 bgp_path_info_restore(dest, pi);
d62a17ae 3595 }
718e3744 3596
d62a17ae 3597 /* Received Logging. */
3598 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3599 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3600 num_labels, addpath_id ? 1 : 0,
3601 addpath_id, pfx_buf,
3602 sizeof(pfx_buf));
d62a17ae 3603 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3604 }
718e3744 3605
d62a17ae 3606 /* graceful restart STALE flag unset. */
f009ff26 3607 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
3608 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3609 bgp_dest_set_defer_flag(dest, false);
f009ff26 3610 }
d62a17ae 3611
3612 /* The attribute is changed. */
9bcb3eef 3613 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3614
3615 /* implicit withdraw, decrement aggregate and pcount here.
3616 * only if update is accepted, they'll increment below.
3617 */
40381db7 3618 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3619
3620 /* Update bgp route dampening information. */
3621 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3622 && peer->sort == BGP_PEER_EBGP) {
3623 /* This is implicit withdraw so we should update
3624 dampening
3625 information. */
40381db7 3626 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 3627 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 3628 }
49e5a4a0 3629#ifdef ENABLE_BGP_VNC
d62a17ae 3630 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3631 struct bgp_dest *pdest = NULL;
d62a17ae 3632 struct bgp_table *table = NULL;
3633
9bcb3eef
DS
3634 pdest = bgp_node_get(bgp->rib[afi][safi],
3635 (struct prefix *)prd);
3636 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3637 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3638
3639 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3640 bgp, prd, table, p, pi);
d62a17ae 3641 }
9bcb3eef 3642 bgp_dest_unlock_node(pdest);
d62a17ae 3643 }
3644 if ((afi == AFI_IP || afi == AFI_IP6)
3645 && (safi == SAFI_UNICAST)) {
40381db7 3646 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3647 /*
3648 * Implicit withdraw case.
3649 */
3650 ++vnc_implicit_withdraw;
40381db7
DS
3651 vnc_import_bgp_del_route(bgp, p, pi);
3652 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3653 }
3654 }
65efcfce 3655#endif
128ea8ab 3656
d62a17ae 3657 /* Special handling for EVPN update of an existing route. If the
3658 * extended community attribute has changed, we need to
3659 * un-import
3660 * the route using its existing extended community. It will be
3661 * subsequently processed for import with the new extended
3662 * community.
3663 */
6f8c9c11
PR
3664 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
3665 && !same_attr) {
40381db7 3666 if ((pi->attr->flag
d62a17ae 3667 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3668 && (attr_new->flag
3669 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3670 int cmp;
3671
40381db7 3672 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3673 attr_new->ecommunity);
3674 if (!cmp) {
3675 if (bgp_debug_update(peer, p, NULL, 1))
3676 zlog_debug(
3677 "Change in EXT-COMM, existing %s new %s",
3678 ecommunity_str(
40381db7 3679 pi->attr->ecommunity),
d62a17ae 3680 ecommunity_str(
3681 attr_new->ecommunity));
6f8c9c11
PR
3682 if (safi == SAFI_EVPN)
3683 bgp_evpn_unimport_route(
3684 bgp, afi, safi, p, pi);
3685 else /* SAFI_MPLS_VPN */
3686 vpn_leak_to_vrf_withdraw(bgp,
3687 pi);
d62a17ae 3688 }
3689 }
3690 }
718e3744 3691
d62a17ae 3692 /* Update to new attribute. */
40381db7
DS
3693 bgp_attr_unintern(&pi->attr);
3694 pi->attr = attr_new;
d62a17ae 3695
3696 /* Update MPLS label */
3697 if (has_valid_label) {
40381db7 3698 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3699 if (extra->label != label) {
3700 memcpy(&extra->label, label,
dbd587da 3701 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3702 extra->num_labels = num_labels;
3703 }
b57ba6d2
MK
3704 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3705 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3706 }
718e3744 3707
e496b420
HS
3708 /* Update SRv6 SID */
3709 if (attr->srv6_l3vpn) {
3710 extra = bgp_path_info_extra_get(pi);
3711 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
3712 sid_copy(&extra->sid[0],
3713 &attr->srv6_l3vpn->sid);
3714 extra->num_sids = 1;
3715 }
3716 } else if (attr->srv6_vpn) {
3717 extra = bgp_path_info_extra_get(pi);
3718 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
3719 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3720 extra->num_sids = 1;
3721 }
3722 }
3723
49e5a4a0 3724#ifdef ENABLE_BGP_VNC
d62a17ae 3725 if ((afi == AFI_IP || afi == AFI_IP6)
3726 && (safi == SAFI_UNICAST)) {
3727 if (vnc_implicit_withdraw) {
3728 /*
3729 * Add back the route with its new attributes
3730 * (e.g., nexthop).
3731 * The route is still selected, until the route
3732 * selection
3733 * queued by bgp_process actually runs. We have
3734 * to make this
3735 * update to the VNC side immediately to avoid
3736 * racing against
3737 * configuration changes (e.g., route-map
3738 * changes) which
3739 * trigger re-importation of the entire RIB.
3740 */
40381db7
DS
3741 vnc_import_bgp_add_route(bgp, p, pi);
3742 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 3743 }
3744 }
65efcfce 3745#endif
d62a17ae 3746 /* Update Overlay Index */
3747 if (afi == AFI_L2VPN) {
3748 overlay_index_update(
40381db7 3749 pi->attr, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3750 evpn == NULL ? NULL : &evpn->gw_ip);
3751 }
65efcfce 3752
d62a17ae 3753 /* Update bgp route dampening information. */
3754 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3755 && peer->sort == BGP_PEER_EBGP) {
3756 /* Now we do normal update dampening. */
9bcb3eef 3757 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 3758 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 3759 bgp_dest_unlock_node(dest);
d62a17ae 3760 return 0;
3761 }
3762 }
128ea8ab 3763
d62a17ae 3764 /* Nexthop reachability check - for unicast and
3765 * labeled-unicast.. */
7c312383
AD
3766 if (((afi == AFI_IP || afi == AFI_IP6)
3767 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3768 || (safi == SAFI_EVPN &&
3769 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
3770 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
3771 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 3772 && !CHECK_FLAG(peer->flags,
3773 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
3774 && !CHECK_FLAG(bgp->flags,
3775 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 3776 connected = 1;
3777 else
3778 connected = 0;
3779
960035b2
PZ
3780 struct bgp *bgp_nexthop = bgp;
3781
40381db7
DS
3782 if (pi->extra && pi->extra->bgp_orig)
3783 bgp_nexthop = pi->extra->bgp_orig;
960035b2 3784
7c312383
AD
3785 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
3786
3787 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
3788 pi, NULL, connected)
a4d82a8a 3789 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
3790 bgp_path_info_set_flag(dest, pi,
3791 BGP_PATH_VALID);
d62a17ae 3792 else {
3793 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
3794 zlog_debug("%s(%pI4): NH unresolved",
3795 __func__,
3796 (in_addr_t *)&attr_new->nexthop);
d62a17ae 3797 }
9bcb3eef 3798 bgp_path_info_unset_flag(dest, pi,
18ee8310 3799 BGP_PATH_VALID);
d62a17ae 3800 }
3801 } else
9bcb3eef 3802 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 3803
49e5a4a0 3804#ifdef ENABLE_BGP_VNC
d62a17ae 3805 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3806 struct bgp_dest *pdest = NULL;
d62a17ae 3807 struct bgp_table *table = NULL;
3808
9bcb3eef
DS
3809 pdest = bgp_node_get(bgp->rib[afi][safi],
3810 (struct prefix *)prd);
3811 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3812 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3813
3814 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 3815 bgp, prd, table, p, pi);
d62a17ae 3816 }
9bcb3eef 3817 bgp_dest_unlock_node(pdest);
d62a17ae 3818 }
3819#endif
718e3744 3820
d62a17ae 3821 /* If this is an EVPN route and some attribute has changed,
3822 * process
3823 * route for import. If the extended community has changed, we
3824 * would
3825 * have done the un-import earlier and the import would result
3826 * in the
3827 * route getting injected into appropriate L2 VNIs. If it is
3828 * just
3829 * some other attribute change, the import will result in
3830 * updating
3831 * the attributes for the route in the VNI(s).
3832 */
7c312383
AD
3833 if (safi == SAFI_EVPN && !same_attr &&
3834 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 3835 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 3836
3837 /* Process change. */
40381db7 3838 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 3839
9bcb3eef
DS
3840 bgp_process(bgp, dest, afi, safi);
3841 bgp_dest_unlock_node(dest);
558d1fec 3842
ddb5b488
PZ
3843 if (SAFI_UNICAST == safi
3844 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3845 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3846
40381db7 3847 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3848 }
3849 if ((SAFI_MPLS_VPN == safi)
3850 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3851
40381db7 3852 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
3853 }
3854
49e5a4a0 3855#ifdef ENABLE_BGP_VNC
d62a17ae 3856 if (SAFI_MPLS_VPN == safi) {
3857 mpls_label_t label_decoded = decode_label(label);
28070ee3 3858
d62a17ae 3859 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3860 type, sub_type, &label_decoded);
3861 }
3862 if (SAFI_ENCAP == safi) {
3863 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3864 type, sub_type, NULL);
3865 }
28070ee3
PZ
3866#endif
3867
d62a17ae 3868 return 0;
3869 } // End of implicit withdraw
718e3744 3870
d62a17ae 3871 /* Received Logging. */
3872 if (bgp_debug_update(peer, p, NULL, 1)) {
3873 if (!peer->rcvd_attr_printed) {
3874 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3875 peer->rcvd_attr_str);
3876 peer->rcvd_attr_printed = 1;
3877 }
718e3744 3878
a4d82a8a 3879 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3880 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3881 sizeof(pfx_buf));
3882 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3883 }
718e3744 3884
d62a17ae 3885 /* Make new BGP info. */
9bcb3eef 3886 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 3887
d62a17ae 3888 /* Update MPLS label */
3889 if (has_valid_label) {
18ee8310 3890 extra = bgp_path_info_extra_get(new);
8ba71050 3891 if (extra->label != label) {
dbd587da
QY
3892 memcpy(&extra->label, label,
3893 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3894 extra->num_labels = num_labels;
3895 }
b57ba6d2
MK
3896 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3897 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3898 }
718e3744 3899
e496b420
HS
3900 /* Update SRv6 SID */
3901 if (safi == SAFI_MPLS_VPN) {
3902 extra = bgp_path_info_extra_get(new);
3903 if (attr->srv6_l3vpn) {
3904 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
3905 extra->num_sids = 1;
3906 } else if (attr->srv6_vpn) {
3907 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3908 extra->num_sids = 1;
3909 }
3910 }
3911
d62a17ae 3912 /* Update Overlay Index */
3913 if (afi == AFI_L2VPN) {
3914 overlay_index_update(new->attr,
3915 evpn == NULL ? NULL : &evpn->eth_s_id,
3916 evpn == NULL ? NULL : &evpn->gw_ip);
3917 }
3918 /* Nexthop reachability check. */
7c312383
AD
3919 if (((afi == AFI_IP || afi == AFI_IP6)
3920 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3921 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
3922 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
3923 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 3924 && !CHECK_FLAG(peer->flags,
3925 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
3926 && !CHECK_FLAG(bgp->flags,
3927 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 3928 connected = 1;
3929 else
3930 connected = 0;
3931
7c312383
AD
3932 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
3933
3934 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, new, NULL,
3935 connected)
a4d82a8a 3936 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 3937 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 3938 else {
3939 if (BGP_DEBUG(nht, NHT)) {
3940 char buf1[INET6_ADDRSTRLEN];
3941 inet_ntop(AF_INET,
3942 (const void *)&attr_new->nexthop,
3943 buf1, INET6_ADDRSTRLEN);
15569c58
DA
3944 zlog_debug("%s(%s): NH unresolved", __func__,
3945 buf1);
d62a17ae 3946 }
9bcb3eef 3947 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 3948 }
3949 } else
9bcb3eef 3950 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 3951
d62a17ae 3952 /* Addpath ID */
3953 new->addpath_rx_id = addpath_id;
3954
3955 /* Increment prefix */
3956 bgp_aggregate_increment(bgp, p, new, afi, safi);
3957
3958 /* Register new BGP information. */
9bcb3eef 3959 bgp_path_info_add(dest, new);
d62a17ae 3960
3961 /* route_node_get lock */
9bcb3eef 3962 bgp_dest_unlock_node(dest);
558d1fec 3963
49e5a4a0 3964#ifdef ENABLE_BGP_VNC
d62a17ae 3965 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3966 struct bgp_dest *pdest = NULL;
d62a17ae 3967 struct bgp_table *table = NULL;
3968
9bcb3eef
DS
3969 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
3970 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3971 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3972
3973 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3974 bgp, prd, table, p, new);
3975 }
9bcb3eef 3976 bgp_dest_unlock_node(pdest);
d62a17ae 3977 }
65efcfce
LB
3978#endif
3979
d62a17ae 3980 /* If maximum prefix count is configured and current prefix
3981 count exeed it. */
3982 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3983 return -1;
718e3744 3984
d62a17ae 3985 /* If this is an EVPN route, process for import. */
7c312383 3986 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 3987 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 3988
9bcb3eef 3989 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 3990
d62a17ae 3991 /* Process change. */
9bcb3eef 3992 bgp_process(bgp, dest, afi, safi);
718e3744 3993
ddb5b488
PZ
3994 if (SAFI_UNICAST == safi
3995 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3996 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3997 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
3998 }
3999 if ((SAFI_MPLS_VPN == safi)
4000 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4001
4002 vpn_leak_to_vrf_update(bgp, new);
4003 }
49e5a4a0 4004#ifdef ENABLE_BGP_VNC
d62a17ae 4005 if (SAFI_MPLS_VPN == safi) {
4006 mpls_label_t label_decoded = decode_label(label);
28070ee3 4007
d62a17ae 4008 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4009 sub_type, &label_decoded);
4010 }
4011 if (SAFI_ENCAP == safi) {
4012 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4013 sub_type, NULL);
4014 }
28070ee3
PZ
4015#endif
4016
d62a17ae 4017 return 0;
718e3744 4018
d62a17ae 4019/* This BGP update is filtered. Log the reason then update BGP
4020 entry. */
4021filtered:
9bcb3eef 4022 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4023
d62a17ae 4024 if (bgp_debug_update(peer, p, NULL, 1)) {
4025 if (!peer->rcvd_attr_printed) {
4026 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4027 peer->rcvd_attr_str);
4028 peer->rcvd_attr_printed = 1;
4029 }
718e3744 4030
a4d82a8a 4031 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4032 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4033 sizeof(pfx_buf));
4034 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4035 peer->host, pfx_buf, reason);
4036 }
128ea8ab 4037
40381db7 4038 if (pi) {
d62a17ae 4039 /* If this is an EVPN route, un-import it as it is now filtered.
4040 */
4041 if (safi == SAFI_EVPN)
40381db7 4042 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4043
ddb5b488
PZ
4044 if (SAFI_UNICAST == safi
4045 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4046 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4047
40381db7 4048 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4049 }
4050 if ((SAFI_MPLS_VPN == safi)
4051 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4052
40381db7 4053 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4054 }
4055
9bcb3eef 4056 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4057 }
4058
9bcb3eef 4059 bgp_dest_unlock_node(dest);
558d1fec 4060
49e5a4a0 4061#ifdef ENABLE_BGP_VNC
d62a17ae 4062 /*
4063 * Filtered update is treated as an implicit withdrawal (see
4064 * bgp_rib_remove()
4065 * a few lines above)
4066 */
4067 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4068 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4069 0);
4070 }
97736e32
PZ
4071#endif
4072
d62a17ae 4073 return 0;
718e3744 4074}
4075
26a3ffd6 4076int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4077 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4078 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4079 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4080{
d62a17ae 4081 struct bgp *bgp;
4082 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4083 struct bgp_dest *dest;
40381db7 4084 struct bgp_path_info *pi;
718e3744 4085
49e5a4a0 4086#ifdef ENABLE_BGP_VNC
d62a17ae 4087 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4088 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4089 0);
4090 }
28070ee3
PZ
4091#endif
4092
d62a17ae 4093 bgp = peer->bgp;
4094
4095 /* Lookup node. */
9bcb3eef 4096 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4097
4098 /* If peer is soft reconfiguration enabled. Record input packet for
4099 * further calculation.
4100 *
4101 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4102 * routes that are filtered. This tanks out Quagga RS pretty badly due
4103 * to
4104 * the iteration over all RS clients.
4105 * Since we need to remove the entry from adj_in anyway, do that first
4106 * and
4107 * if there was no entry, we don't need to do anything more.
4108 */
4109 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4110 && peer != bgp->peer_self)
9bcb3eef 4111 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4112 peer->stat_pfx_dup_withdraw++;
4113
d62a17ae 4114 if (bgp_debug_update(peer, p, NULL, 1)) {
4115 bgp_debug_rdpfxpath2str(
a4d82a8a 4116 afi, safi, prd, p, label, num_labels,
d62a17ae 4117 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4118 sizeof(pfx_buf));
4119 zlog_debug(
4120 "%s withdrawing route %s not in adj-in",
4121 peer->host, pfx_buf);
4122 }
9bcb3eef 4123 bgp_dest_unlock_node(dest);
d62a17ae 4124 return 0;
4125 }
cd808e74 4126
d62a17ae 4127 /* Lookup withdrawn route. */
9bcb3eef 4128 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4129 if (pi->peer == peer && pi->type == type
4130 && pi->sub_type == sub_type
4131 && pi->addpath_rx_id == addpath_id)
d62a17ae 4132 break;
4133
4134 /* Logging. */
4135 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4136 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4137 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4138 sizeof(pfx_buf));
4139 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4140 pfx_buf);
4141 }
718e3744 4142
d62a17ae 4143 /* Withdraw specified route from routing table. */
40381db7 4144 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4145 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4146 if (SAFI_UNICAST == safi
4147 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4148 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4149 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4150 }
4151 if ((SAFI_MPLS_VPN == safi)
4152 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4153
40381db7 4154 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4155 }
4156 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4157 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4158 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4159 sizeof(pfx_buf));
4160 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4161 }
718e3744 4162
d62a17ae 4163 /* Unlock bgp_node_get() lock. */
9bcb3eef 4164 bgp_dest_unlock_node(dest);
d62a17ae 4165
4166 return 0;
718e3744 4167}
6b0655a2 4168
d62a17ae 4169void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4170 int withdraw)
718e3744 4171{
d62a17ae 4172 struct update_subgroup *subgrp;
4173 subgrp = peer_subgroup(peer, afi, safi);
4174 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4175}
6182d65b 4176
718e3744 4177
3f9c7369
DS
4178/*
4179 * bgp_stop_announce_route_timer
4180 */
d62a17ae 4181void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4182{
d62a17ae 4183 if (!paf->t_announce_route)
4184 return;
4185
4186 THREAD_TIMER_OFF(paf->t_announce_route);
718e3744 4187}
6b0655a2 4188
3f9c7369
DS
4189/*
4190 * bgp_announce_route_timer_expired
4191 *
4192 * Callback that is invoked when the route announcement timer for a
4193 * peer_af expires.
4194 */
d62a17ae 4195static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4196{
d62a17ae 4197 struct peer_af *paf;
4198 struct peer *peer;
558d1fec 4199
d62a17ae 4200 paf = THREAD_ARG(t);
4201 peer = paf->peer;
718e3744 4202
d62a17ae 4203 if (peer->status != Established)
4204 return 0;
3f9c7369 4205
d62a17ae 4206 if (!peer->afc_nego[paf->afi][paf->safi])
4207 return 0;
3f9c7369 4208
d62a17ae 4209 peer_af_announce_route(paf, 1);
4210 return 0;
718e3744 4211}
4212
3f9c7369
DS
4213/*
4214 * bgp_announce_route
4215 *
4216 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4217 */
d62a17ae 4218void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4219{
4220 struct peer_af *paf;
4221 struct update_subgroup *subgrp;
4222
4223 paf = peer_af_find(peer, afi, safi);
4224 if (!paf)
4225 return;
4226 subgrp = PAF_SUBGRP(paf);
4227
4228 /*
4229 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4230 * or a refresh has already been triggered.
4231 */
4232 if (!subgrp || paf->t_announce_route)
4233 return;
4234
4235 /*
4236 * Start a timer to stagger/delay the announce. This serves
4237 * two purposes - announcement can potentially be combined for
4238 * multiple peers and the announcement doesn't happen in the
4239 * vty context.
4240 */
4241 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4242 (subgrp->peer_count == 1)
4243 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4244 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4245 &paf->t_announce_route);
3f9c7369
DS
4246}
4247
4248/*
4249 * Announce routes from all AF tables to a peer.
4250 *
4251 * This should ONLY be called when there is a need to refresh the
4252 * routes to the peer based on a policy change for this peer alone
4253 * or a route refresh request received from the peer.
4254 * The operation will result in splitting the peer from its existing
4255 * subgroups and putting it in new subgroups.
4256 */
d62a17ae 4257void bgp_announce_route_all(struct peer *peer)
718e3744 4258{
d62a17ae 4259 afi_t afi;
4260 safi_t safi;
4261
05c7a1cc
QY
4262 FOREACH_AFI_SAFI (afi, safi)
4263 bgp_announce_route(peer, afi, safi);
718e3744 4264}
6b0655a2 4265
d62a17ae 4266static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4267 struct bgp_table *table,
4268 struct prefix_rd *prd)
718e3744 4269{
d62a17ae 4270 int ret;
9bcb3eef 4271 struct bgp_dest *dest;
d62a17ae 4272 struct bgp_adj_in *ain;
718e3744 4273
d62a17ae 4274 if (!table)
4275 table = peer->bgp->rib[afi][safi];
718e3744 4276
9bcb3eef
DS
4277 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4278 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4279 if (ain->peer != peer)
4280 continue;
8692c506 4281
d7d15889 4282 struct bgp_path_info *pi;
d7c0a89a 4283 uint32_t num_labels = 0;
b57ba6d2 4284 mpls_label_t *label_pnt = NULL;
8cb687c2 4285 struct bgp_route_evpn evpn;
b57ba6d2 4286
9bcb3eef 4287 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
d7d15889
DS
4288 pi = pi->next)
4289 if (pi->peer == peer)
4290 break;
4291
40381db7
DS
4292 if (pi && pi->extra)
4293 num_labels = pi->extra->num_labels;
b57ba6d2 4294 if (num_labels)
40381db7 4295 label_pnt = &pi->extra->label[0];
8cb687c2
DS
4296 if (pi)
4297 memcpy(&evpn, &pi->attr->evpn_overlay,
4298 sizeof(evpn));
4299 else
4300 memset(&evpn, 0, sizeof(evpn));
8692c506 4301
9bcb3eef
DS
4302 ret = bgp_update(peer, bgp_dest_get_prefix(dest),
4303 ain->addpath_rx_id, ain->attr, afi,
4304 safi, ZEBRA_ROUTE_BGP,
a4d82a8a 4305 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 4306 num_labels, 1, &evpn);
ea47320b
DL
4307
4308 if (ret < 0) {
9bcb3eef 4309 bgp_dest_unlock_node(dest);
ea47320b 4310 return;
d62a17ae 4311 }
4312 }
718e3744 4313}
4314
d62a17ae 4315void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4316{
9bcb3eef 4317 struct bgp_dest *dest;
d62a17ae 4318 struct bgp_table *table;
718e3744 4319
d62a17ae 4320 if (peer->status != Established)
4321 return;
718e3744 4322
d62a17ae 4323 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4324 && (safi != SAFI_EVPN))
4325 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4326 else
9bcb3eef
DS
4327 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4328 dest = bgp_route_next(dest)) {
4329 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4330
b54892e0
DS
4331 if (table == NULL)
4332 continue;
8692c506 4333
9bcb3eef 4334 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
4335 struct prefix_rd prd;
4336
4337 prd.family = AF_UNSPEC;
4338 prd.prefixlen = 64;
4339 memcpy(&prd.val, p->u.val, 8);
4340
4341 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 4342 }
718e3744 4343}
6b0655a2 4344
228da428 4345
d62a17ae 4346struct bgp_clear_node_queue {
9bcb3eef 4347 struct bgp_dest *dest;
228da428
CC
4348};
4349
d62a17ae 4350static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4351{
d62a17ae 4352 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 4353 struct bgp_dest *dest = cnq->dest;
d62a17ae 4354 struct peer *peer = wq->spec.data;
40381db7 4355 struct bgp_path_info *pi;
3103e8d2 4356 struct bgp *bgp;
9bcb3eef
DS
4357 afi_t afi = bgp_dest_table(dest)->afi;
4358 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 4359
9bcb3eef 4360 assert(dest && peer);
3103e8d2 4361 bgp = peer->bgp;
d62a17ae 4362
4363 /* It is possible that we have multiple paths for a prefix from a peer
4364 * if that peer is using AddPath.
4365 */
9bcb3eef 4366 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 4367 if (pi->peer != peer)
ea47320b
DL
4368 continue;
4369
4370 /* graceful restart STALE flag set. */
4371 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4372 && peer->nsf[afi][safi]
40381db7
DS
4373 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4374 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 4375 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
4376 else {
4377 /* If this is an EVPN route, process for
4378 * un-import. */
4379 if (safi == SAFI_EVPN)
9bcb3eef
DS
4380 bgp_evpn_unimport_route(
4381 bgp, afi, safi,
4382 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
4383 /* Handle withdraw for VRF route-leaking and L3VPN */
4384 if (SAFI_UNICAST == safi
4385 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4386 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4387 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4388 bgp, pi);
960035b2 4389 }
3103e8d2 4390 if (SAFI_MPLS_VPN == safi &&
960035b2 4391 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4392 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4393 }
3103e8d2 4394
9bcb3eef 4395 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4396 }
ea47320b 4397 }
d62a17ae 4398 return WQ_SUCCESS;
200df115 4399}
4400
d62a17ae 4401static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4402{
d62a17ae 4403 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
4404 struct bgp_dest *dest = cnq->dest;
4405 struct bgp_table *table = bgp_dest_table(dest);
228da428 4406
9bcb3eef 4407 bgp_dest_unlock_node(dest);
d62a17ae 4408 bgp_table_unlock(table);
4409 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4410}
4411
d62a17ae 4412static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4413{
d62a17ae 4414 struct peer *peer = wq->spec.data;
64e580a7 4415
d62a17ae 4416 /* Tickle FSM to start moving again */
4417 BGP_EVENT_ADD(peer, Clearing_Completed);
4418
4419 peer_unlock(peer); /* bgp_clear_route */
200df115 4420}
718e3744 4421
d62a17ae 4422static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4423{
d62a17ae 4424 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4425
4426 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4427#undef CLEAR_QUEUE_NAME_LEN
4428
0ce1ca80 4429 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4430 peer->clear_node_queue->spec.hold = 10;
4431 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4432 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4433 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4434 peer->clear_node_queue->spec.max_retries = 0;
4435
4436 /* we only 'lock' this peer reference when the queue is actually active
4437 */
4438 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4439}
4440
d62a17ae 4441static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4442 struct bgp_table *table)
65ca75e0 4443{
9bcb3eef 4444 struct bgp_dest *dest;
d62a17ae 4445 int force = bm->process_main_queue ? 0 : 1;
6cf159b9 4446
d62a17ae 4447 if (!table)
4448 table = peer->bgp->rib[afi][safi];
dc83d712 4449
d62a17ae 4450 /* If still no table => afi/safi isn't configured at all or smth. */
4451 if (!table)
4452 return;
dc83d712 4453
9bcb3eef 4454 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 4455 struct bgp_path_info *pi, *next;
d62a17ae 4456 struct bgp_adj_in *ain;
4457 struct bgp_adj_in *ain_next;
4458
4459 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4460 * queued for every clearing peer, regardless of whether it is
4461 * relevant to the peer at hand.
4462 *
4463 * Overview: There are 3 different indices which need to be
4464 * scrubbed, potentially, when a peer is removed:
4465 *
4466 * 1 peer's routes visible via the RIB (ie accepted routes)
4467 * 2 peer's routes visible by the (optional) peer's adj-in index
4468 * 3 other routes visible by the peer's adj-out index
4469 *
4470 * 3 there is no hurry in scrubbing, once the struct peer is
4471 * removed from bgp->peer, we could just GC such deleted peer's
4472 * adj-outs at our leisure.
4473 *
4474 * 1 and 2 must be 'scrubbed' in some way, at least made
4475 * invisible via RIB index before peer session is allowed to be
4476 * brought back up. So one needs to know when such a 'search' is
4477 * complete.
4478 *
4479 * Ideally:
4480 *
4481 * - there'd be a single global queue or a single RIB walker
4482 * - rather than tracking which route_nodes still need to be
4483 * examined on a peer basis, we'd track which peers still
4484 * aren't cleared
4485 *
4486 * Given that our per-peer prefix-counts now should be reliable,
4487 * this may actually be achievable. It doesn't seem to be a huge
4488 * problem at this time,
4489 *
4490 * It is possible that we have multiple paths for a prefix from
4491 * a peer
4492 * if that peer is using AddPath.
4493 */
9bcb3eef 4494 ain = dest->adj_in;
d62a17ae 4495 while (ain) {
4496 ain_next = ain->next;
4497
4498 if (ain->peer == peer) {
9bcb3eef
DS
4499 bgp_adj_in_remove(dest, ain);
4500 bgp_dest_unlock_node(dest);
d62a17ae 4501 }
4502
4503 ain = ain_next;
4504 }
4505
9bcb3eef 4506 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
4507 next = pi->next;
4508 if (pi->peer != peer)
d62a17ae 4509 continue;
4510
4511 if (force)
9bcb3eef 4512 bgp_path_info_reap(dest, pi);
d62a17ae 4513 else {
4514 struct bgp_clear_node_queue *cnq;
4515
4516 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
4517 bgp_table_lock(bgp_dest_table(dest));
4518 bgp_dest_lock_node(dest);
d62a17ae 4519 cnq = XCALLOC(
4520 MTYPE_BGP_CLEAR_NODE_QUEUE,
4521 sizeof(struct bgp_clear_node_queue));
9bcb3eef 4522 cnq->dest = dest;
d62a17ae 4523 work_queue_add(peer->clear_node_queue, cnq);
4524 break;
4525 }
4526 }
4527 }
4528 return;
4529}
4530
4531void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4532{
9bcb3eef 4533 struct bgp_dest *dest;
d62a17ae 4534 struct bgp_table *table;
4535
4536 if (peer->clear_node_queue == NULL)
4537 bgp_clear_node_queue_init(peer);
4538
4539 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4540 * Idle until it receives a Clearing_Completed event. This protects
4541 * against peers which flap faster than we can we clear, which could
4542 * lead to:
4543 *
4544 * a) race with routes from the new session being installed before
4545 * clear_route_node visits the node (to delete the route of that
4546 * peer)
4547 * b) resource exhaustion, clear_route_node likely leads to an entry
4548 * on the process_main queue. Fast-flapping could cause that queue
4549 * to grow and grow.
4550 */
4551
4552 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4553 * the unlock will happen upon work-queue completion; other wise, the
4554 * unlock happens at the end of this function.
4555 */
4556 if (!peer->clear_node_queue->thread)
4557 peer_lock(peer);
4558
4559 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4560 bgp_clear_route_table(peer, afi, safi, NULL);
4561 else
9bcb3eef
DS
4562 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4563 dest = bgp_route_next(dest)) {
4564 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4565 if (!table)
4566 continue;
4567
4568 bgp_clear_route_table(peer, afi, safi, table);
4569 }
d62a17ae 4570
4571 /* unlock if no nodes got added to the clear-node-queue. */
4572 if (!peer->clear_node_queue->thread)
4573 peer_unlock(peer);
718e3744 4574}
d62a17ae 4575
4576void bgp_clear_route_all(struct peer *peer)
718e3744 4577{
d62a17ae 4578 afi_t afi;
4579 safi_t safi;
718e3744 4580
05c7a1cc
QY
4581 FOREACH_AFI_SAFI (afi, safi)
4582 bgp_clear_route(peer, afi, safi);
65efcfce 4583
49e5a4a0 4584#ifdef ENABLE_BGP_VNC
d62a17ae 4585 rfapiProcessPeerDown(peer);
65efcfce 4586#endif
718e3744 4587}
4588
d62a17ae 4589void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4590{
d62a17ae 4591 struct bgp_table *table;
9bcb3eef 4592 struct bgp_dest *dest;
d62a17ae 4593 struct bgp_adj_in *ain;
4594 struct bgp_adj_in *ain_next;
718e3744 4595
d62a17ae 4596 table = peer->bgp->rib[afi][safi];
718e3744 4597
d62a17ae 4598 /* It is possible that we have multiple paths for a prefix from a peer
4599 * if that peer is using AddPath.
4600 */
9bcb3eef
DS
4601 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4602 ain = dest->adj_in;
43143c8f 4603
d62a17ae 4604 while (ain) {
4605 ain_next = ain->next;
43143c8f 4606
d62a17ae 4607 if (ain->peer == peer) {
9bcb3eef
DS
4608 bgp_adj_in_remove(dest, ain);
4609 bgp_dest_unlock_node(dest);
d62a17ae 4610 }
43143c8f 4611
d62a17ae 4612 ain = ain_next;
4613 }
4614 }
718e3744 4615}
93406d87 4616
d62a17ae 4617void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4618{
9bcb3eef 4619 struct bgp_dest *dest;
40381db7 4620 struct bgp_path_info *pi;
d62a17ae 4621 struct bgp_table *table;
4622
4623 if (safi == SAFI_MPLS_VPN) {
9bcb3eef
DS
4624 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4625 dest = bgp_route_next(dest)) {
4626 struct bgp_dest *rm;
d62a17ae 4627
4628 /* look for neighbor in tables */
9bcb3eef 4629 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4630 if (!table)
ea47320b
DL
4631 continue;
4632
4633 for (rm = bgp_table_top(table); rm;
4634 rm = bgp_route_next(rm))
9bcb3eef 4635 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 4636 pi = pi->next) {
40381db7 4637 if (pi->peer != peer)
ea47320b 4638 continue;
40381db7 4639 if (!CHECK_FLAG(pi->flags,
1defdda8 4640 BGP_PATH_STALE))
ea47320b
DL
4641 break;
4642
40381db7 4643 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4644 break;
4645 }
d62a17ae 4646 }
4647 } else {
9bcb3eef
DS
4648 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4649 dest = bgp_route_next(dest))
4650 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 4651 pi = pi->next) {
40381db7 4652 if (pi->peer != peer)
ea47320b 4653 continue;
40381db7 4654 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4655 break;
9bcb3eef 4656 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
4657 break;
4658 }
d62a17ae 4659 }
93406d87 4660}
6b0655a2 4661
3dc339cd 4662bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 4663{
e0df4c04 4664 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 4665 return true;
e0df4c04 4666
9dac9fc8
DA
4667 if (peer->sort == BGP_PEER_EBGP
4668 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
4669 || FILTER_LIST_OUT_NAME(filter)
4670 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
4671 return true;
4672 return false;
9dac9fc8
DA
4673}
4674
3dc339cd 4675bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 4676{
e0df4c04 4677 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 4678 return true;
e0df4c04 4679
9dac9fc8
DA
4680 if (peer->sort == BGP_PEER_EBGP
4681 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
4682 || FILTER_LIST_IN_NAME(filter)
4683 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
4684 return true;
4685 return false;
9dac9fc8
DA
4686}
4687
568e10ca 4688static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
4689 safi_t safi)
bb86c601 4690{
9bcb3eef 4691 struct bgp_dest *dest;
40381db7 4692 struct bgp_path_info *pi;
4b7e6066 4693 struct bgp_path_info *next;
bb86c601 4694
9bcb3eef
DS
4695 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4696 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
4697 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 4698
40381db7 4699 next = pi->next;
1b7bb747
CS
4700
4701 /* Unimport EVPN routes from VRFs */
4702 if (safi == SAFI_EVPN)
4703 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 4704 SAFI_EVPN, p, pi);
1b7bb747 4705
40381db7
DS
4706 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
4707 && pi->type == ZEBRA_ROUTE_BGP
4708 && (pi->sub_type == BGP_ROUTE_NORMAL
4709 || pi->sub_type == BGP_ROUTE_AGGREGATE
4710 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 4711
d62a17ae 4712 if (bgp_fibupd_safi(safi))
b54892e0 4713 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 4714 }
9514b37d 4715
9bcb3eef 4716 bgp_path_info_reap(dest, pi);
d62a17ae 4717 }
bb86c601
LB
4718}
4719
718e3744 4720/* Delete all kernel routes. */
d62a17ae 4721void bgp_cleanup_routes(struct bgp *bgp)
4722{
4723 afi_t afi;
9bcb3eef 4724 struct bgp_dest *dest;
67009e22 4725 struct bgp_table *table;
d62a17ae 4726
4727 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
4728 if (afi == AFI_L2VPN)
4729 continue;
568e10ca 4730 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
4731 SAFI_UNICAST);
d62a17ae 4732 /*
4733 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4734 */
4735 if (afi != AFI_L2VPN) {
4736 safi_t safi;
4737 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
4738 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
4739 dest = bgp_route_next(dest)) {
4740 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4741 if (table != NULL) {
4742 bgp_cleanup_table(bgp, table, safi);
4743 bgp_table_finish(&table);
9bcb3eef
DS
4744 bgp_dest_set_bgp_table_info(dest, NULL);
4745 bgp_dest_unlock_node(dest);
d62a17ae 4746 }
4747 }
4748 safi = SAFI_ENCAP;
9bcb3eef
DS
4749 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
4750 dest = bgp_route_next(dest)) {
4751 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4752 if (table != NULL) {
4753 bgp_cleanup_table(bgp, table, safi);
4754 bgp_table_finish(&table);
9bcb3eef
DS
4755 bgp_dest_set_bgp_table_info(dest, NULL);
4756 bgp_dest_unlock_node(dest);
d62a17ae 4757 }
4758 }
4759 }
4760 }
9bcb3eef
DS
4761 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
4762 dest = bgp_route_next(dest)) {
4763 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4764 if (table != NULL) {
4765 bgp_cleanup_table(bgp, table, SAFI_EVPN);
4766 bgp_table_finish(&table);
9bcb3eef
DS
4767 bgp_dest_set_bgp_table_info(dest, NULL);
4768 bgp_dest_unlock_node(dest);
d62a17ae 4769 }
bb86c601 4770 }
718e3744 4771}
4772
d62a17ae 4773void bgp_reset(void)
718e3744 4774{
d62a17ae 4775 vty_reset();
4776 bgp_zclient_reset();
4777 access_list_reset();
4778 prefix_list_reset();
718e3744 4779}
6b0655a2 4780
d62a17ae 4781static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 4782{
d62a17ae 4783 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
4784 && CHECK_FLAG(peer->af_cap[afi][safi],
4785 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
4786}
4787
718e3744 4788/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4789 value. */
d62a17ae 4790int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
4791 struct bgp_nlri *packet)
4792{
d7c0a89a
QY
4793 uint8_t *pnt;
4794 uint8_t *lim;
d62a17ae 4795 struct prefix p;
4796 int psize;
4797 int ret;
4798 afi_t afi;
4799 safi_t safi;
4800 int addpath_encoded;
d7c0a89a 4801 uint32_t addpath_id;
d62a17ae 4802
d62a17ae 4803 pnt = packet->nlri;
4804 lim = pnt + packet->length;
4805 afi = packet->afi;
4806 safi = packet->safi;
4807 addpath_id = 0;
4808 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
4809
4810 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4811 syntactic validity. If the field is syntactically incorrect,
4812 then the Error Subcode is set to Invalid Network Field. */
4813 for (; pnt < lim; pnt += psize) {
4814 /* Clear prefix structure. */
4815 memset(&p, 0, sizeof(struct prefix));
4816
4817 if (addpath_encoded) {
4818
4819 /* When packet overflow occurs return immediately. */
761ed665 4820 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 4821 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4822
a3a850a1 4823 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 4824 addpath_id = ntohl(addpath_id);
d62a17ae 4825 pnt += BGP_ADDPATH_ID_LEN;
4826 }
718e3744 4827
d62a17ae 4828 /* Fetch prefix length. */
4829 p.prefixlen = *pnt++;
4830 /* afi/safi validity already verified by caller,
4831 * bgp_update_receive */
4832 p.family = afi2family(afi);
4833
4834 /* Prefix length check. */
4835 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 4836 flog_err(
e50f7cfd 4837 EC_BGP_UPDATE_RCV,
14454c9f 4838 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 4839 peer->host, p.prefixlen, packet->afi);
513386b5 4840 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 4841 }
6b0655a2 4842
d62a17ae 4843 /* Packet size overflow check. */
4844 psize = PSIZE(p.prefixlen);
4845
4846 /* When packet overflow occur return immediately. */
4847 if (pnt + psize > lim) {
af4c2728 4848 flog_err(
e50f7cfd 4849 EC_BGP_UPDATE_RCV,
d62a17ae 4850 "%s [Error] Update packet error (prefix length %d overflows packet)",
4851 peer->host, p.prefixlen);
513386b5 4852 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4853 }
4854
4855 /* Defensive coding, double-check the psize fits in a struct
4856 * prefix */
4857 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 4858 flog_err(
e50f7cfd 4859 EC_BGP_UPDATE_RCV,
d62a17ae 4860 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4861 peer->host, p.prefixlen, sizeof(p.u));
513386b5 4862 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4863 }
4864
4865 /* Fetch prefix from NLRI packet. */
a85297a7 4866 memcpy(p.u.val, pnt, psize);
d62a17ae 4867
4868 /* Check address. */
4869 if (afi == AFI_IP && safi == SAFI_UNICAST) {
4870 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
4871 /* From RFC4271 Section 6.3:
4872 *
4873 * If a prefix in the NLRI field is semantically
4874 * incorrect
4875 * (e.g., an unexpected multicast IP address),
4876 * an error SHOULD
4877 * be logged locally, and the prefix SHOULD be
4878 * ignored.
a4d82a8a 4879 */
af4c2728 4880 flog_err(
e50f7cfd 4881 EC_BGP_UPDATE_RCV,
d62a17ae 4882 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4883 peer->host, inet_ntoa(p.u.prefix4));
4884 continue;
4885 }
4886 }
4887
4888 /* Check address. */
4889 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
4890 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4891 char buf[BUFSIZ];
4892
af4c2728 4893 flog_err(
e50f7cfd 4894 EC_BGP_UPDATE_RCV,
d62a17ae 4895 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4896 peer->host,
4897 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4898 BUFSIZ));
4899
4900 continue;
4901 }
4902 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
4903 char buf[BUFSIZ];
4904
af4c2728 4905 flog_err(
e50f7cfd 4906 EC_BGP_UPDATE_RCV,
d62a17ae 4907 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4908 peer->host,
4909 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4910 BUFSIZ));
4911
4912 continue;
4913 }
4914 }
4915
4916 /* Normal process. */
4917 if (attr)
4918 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
4919 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 4920 NULL, NULL, 0, 0, NULL);
d62a17ae 4921 else
4922 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
4923 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
4924 BGP_ROUTE_NORMAL, NULL, NULL, 0,
4925 NULL);
d62a17ae 4926
513386b5
DA
4927 /* Do not send BGP notification twice when maximum-prefix count
4928 * overflow. */
4929 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4930 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
4931
4932 /* Address family configuration mismatch. */
d62a17ae 4933 if (ret < 0)
513386b5 4934 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 4935 }
4936
4937 /* Packet length consistency check. */
4938 if (pnt != lim) {
af4c2728 4939 flog_err(
e50f7cfd 4940 EC_BGP_UPDATE_RCV,
d62a17ae 4941 "%s [Error] Update packet error (prefix length mismatch with total length)",
4942 peer->host);
513386b5 4943 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4944 }
6b0655a2 4945
513386b5 4946 return BGP_NLRI_PARSE_OK;
718e3744 4947}
4948
d62a17ae 4949static struct bgp_static *bgp_static_new(void)
718e3744 4950{
d62a17ae 4951 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 4952}
4953
d62a17ae 4954static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 4955{
0a22ddfb 4956 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 4957 route_map_counter_decrement(bgp_static->rmap.map);
4958
0a22ddfb 4959 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 4960 XFREE(MTYPE_BGP_STATIC, bgp_static);
4961}
4962
5f040085 4963void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 4964 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
4965{
9bcb3eef 4966 struct bgp_dest *dest;
40381db7 4967 struct bgp_path_info *pi;
4b7e6066 4968 struct bgp_path_info *new;
40381db7 4969 struct bgp_path_info rmap_path;
d62a17ae 4970 struct attr attr;
4971 struct attr *attr_new;
b68885f9 4972 route_map_result_t ret;
49e5a4a0 4973#ifdef ENABLE_BGP_VNC
d62a17ae 4974 int vnc_implicit_withdraw = 0;
65efcfce 4975#endif
fee0f4c6 4976
d62a17ae 4977 assert(bgp_static);
dd8103a9 4978
9bcb3eef 4979 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4980
d62a17ae 4981 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 4982
d62a17ae 4983 attr.nexthop = bgp_static->igpnexthop;
4984 attr.med = bgp_static->igpmetric;
4985 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 4986
d62a17ae 4987 if (bgp_static->atomic)
4988 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 4989
d62a17ae 4990 /* Store label index, if required. */
4991 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
4992 attr.label_index = bgp_static->label_index;
4993 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
4994 }
718e3744 4995
d62a17ae 4996 /* Apply route-map. */
4997 if (bgp_static->rmap.name) {
4998 struct attr attr_tmp = attr;
80ced710 4999
40381db7
DS
5000 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5001 rmap_path.peer = bgp->peer_self;
5002 rmap_path.attr = &attr_tmp;
fee0f4c6 5003
d62a17ae 5004 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5005
40381db7
DS
5006 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
5007 &rmap_path);
fee0f4c6 5008
d62a17ae 5009 bgp->peer_self->rmap_type = 0;
718e3744 5010
d62a17ae 5011 if (ret == RMAP_DENYMATCH) {
5012 /* Free uninterned attribute. */
5013 bgp_attr_flush(&attr_tmp);
718e3744 5014
d62a17ae 5015 /* Unintern original. */
5016 aspath_unintern(&attr.aspath);
5017 bgp_static_withdraw(bgp, p, afi, safi);
5018 return;
5019 }
7f323236 5020
892fedb6 5021 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
7f323236
DW
5022 bgp_attr_add_gshut_community(&attr_tmp);
5023
d62a17ae 5024 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5025 } else {
5026
892fedb6 5027 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
7f323236
DW
5028 bgp_attr_add_gshut_community(&attr);
5029
d62a17ae 5030 attr_new = bgp_attr_intern(&attr);
7f323236 5031 }
718e3744 5032
9bcb3eef 5033 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5034 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5035 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5036 break;
5037
40381db7
DS
5038 if (pi) {
5039 if (attrhash_cmp(pi->attr, attr_new)
5040 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5041 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5042 bgp_dest_unlock_node(dest);
d62a17ae 5043 bgp_attr_unintern(&attr_new);
5044 aspath_unintern(&attr.aspath);
5045 return;
5046 } else {
5047 /* The attribute is changed. */
9bcb3eef 5048 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5049
5050 /* Rewrite BGP route information. */
40381db7 5051 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5052 bgp_path_info_restore(dest, pi);
d62a17ae 5053 else
40381db7 5054 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5055#ifdef ENABLE_BGP_VNC
d62a17ae 5056 if ((afi == AFI_IP || afi == AFI_IP6)
5057 && (safi == SAFI_UNICAST)) {
40381db7 5058 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5059 /*
5060 * Implicit withdraw case.
40381db7 5061 * We have to do this before pi is
d62a17ae 5062 * changed
5063 */
5064 ++vnc_implicit_withdraw;
40381db7 5065 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5066 vnc_import_bgp_exterior_del_route(
40381db7 5067 bgp, p, pi);
d62a17ae 5068 }
5069 }
65efcfce 5070#endif
40381db7
DS
5071 bgp_attr_unintern(&pi->attr);
5072 pi->attr = attr_new;
5073 pi->uptime = bgp_clock();
49e5a4a0 5074#ifdef ENABLE_BGP_VNC
d62a17ae 5075 if ((afi == AFI_IP || afi == AFI_IP6)
5076 && (safi == SAFI_UNICAST)) {
5077 if (vnc_implicit_withdraw) {
40381db7 5078 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5079 vnc_import_bgp_exterior_add_route(
40381db7 5080 bgp, p, pi);
d62a17ae 5081 }
5082 }
65efcfce 5083#endif
718e3744 5084
d62a17ae 5085 /* Nexthop reachability check. */
892fedb6 5086 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5087 && (safi == SAFI_UNICAST
5088 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5089
5090 struct bgp *bgp_nexthop = bgp;
5091
40381db7
DS
5092 if (pi->extra && pi->extra->bgp_orig)
5093 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5094
5095 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
40381db7 5096 afi, pi, NULL, 0))
9bcb3eef 5097 bgp_path_info_set_flag(dest, pi,
18ee8310 5098 BGP_PATH_VALID);
d62a17ae 5099 else {
5100 if (BGP_DEBUG(nht, NHT)) {
5101 char buf1[INET6_ADDRSTRLEN];
5102 inet_ntop(p->family,
5103 &p->u.prefix, buf1,
5104 INET6_ADDRSTRLEN);
5105 zlog_debug(
5106 "%s(%s): Route not in table, not advertising",
15569c58 5107 __func__, buf1);
d62a17ae 5108 }
18ee8310 5109 bgp_path_info_unset_flag(
9bcb3eef 5110 dest, pi, BGP_PATH_VALID);
d62a17ae 5111 }
5112 } else {
5113 /* Delete the NHT structure if any, if we're
5114 * toggling between
5115 * enabling/disabling import check. We
5116 * deregister the route
5117 * from NHT to avoid overloading NHT and the
5118 * process interaction
5119 */
40381db7 5120 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5121 bgp_path_info_set_flag(dest, pi,
5122 BGP_PATH_VALID);
d62a17ae 5123 }
5124 /* Process change. */
40381db7 5125 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5126 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5127
5128 if (SAFI_UNICAST == safi
5129 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5130 || bgp->inst_type
5131 == BGP_INSTANCE_TYPE_DEFAULT)) {
5132 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5133 pi);
ddb5b488
PZ
5134 }
5135
9bcb3eef 5136 bgp_dest_unlock_node(dest);
d62a17ae 5137 aspath_unintern(&attr.aspath);
5138 return;
5139 }
718e3744 5140 }
718e3744 5141
d62a17ae 5142 /* Make new BGP info. */
5143 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5144 attr_new, dest);
d62a17ae 5145 /* Nexthop reachability check. */
892fedb6 5146 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5147 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 5148 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
9bcb3eef 5149 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5150 else {
5151 if (BGP_DEBUG(nht, NHT)) {
5152 char buf1[INET6_ADDRSTRLEN];
5153 inet_ntop(p->family, &p->u.prefix, buf1,
5154 INET6_ADDRSTRLEN);
5155 zlog_debug(
5156 "%s(%s): Route not in table, not advertising",
15569c58 5157 __func__, buf1);
d62a17ae 5158 }
9bcb3eef 5159 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5160 }
5161 } else {
5162 /* Delete the NHT structure if any, if we're toggling between
5163 * enabling/disabling import check. We deregister the route
5164 * from NHT to avoid overloading NHT and the process interaction
5165 */
5166 bgp_unlink_nexthop(new);
5167
9bcb3eef 5168 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 5169 }
078430f6 5170
d62a17ae 5171 /* Aggregate address increment. */
5172 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5173
d62a17ae 5174 /* Register new BGP information. */
9bcb3eef 5175 bgp_path_info_add(dest, new);
718e3744 5176
d62a17ae 5177 /* route_node_get lock */
9bcb3eef 5178 bgp_dest_unlock_node(dest);
d62a17ae 5179
5180 /* Process change. */
9bcb3eef 5181 bgp_process(bgp, dest, afi, safi);
d62a17ae 5182
ddb5b488
PZ
5183 if (SAFI_UNICAST == safi
5184 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5185 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5186 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5187 }
5188
d62a17ae 5189 /* Unintern original. */
5190 aspath_unintern(&attr.aspath);
718e3744 5191}
5192
5f040085 5193void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 5194 safi_t safi)
718e3744 5195{
9bcb3eef 5196 struct bgp_dest *dest;
40381db7 5197 struct bgp_path_info *pi;
718e3744 5198
9bcb3eef 5199 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5200
d62a17ae 5201 /* Check selected route and self inserted route. */
9bcb3eef 5202 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5203 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5204 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5205 break;
5206
5207 /* Withdraw static BGP route from routing table. */
40381db7 5208 if (pi) {
ddb5b488
PZ
5209 if (SAFI_UNICAST == safi
5210 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5211 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5212 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5213 }
40381db7
DS
5214 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5215 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5216 bgp_path_info_delete(dest, pi);
5217 bgp_process(bgp, dest, afi, safi);
d62a17ae 5218 }
718e3744 5219
d62a17ae 5220 /* Unlock bgp_node_lookup. */
9bcb3eef 5221 bgp_dest_unlock_node(dest);
718e3744 5222}
5223
137446f9
LB
5224/*
5225 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5226 */
5f040085 5227static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5228 afi_t afi, safi_t safi,
5229 struct prefix_rd *prd)
718e3744 5230{
9bcb3eef 5231 struct bgp_dest *dest;
40381db7 5232 struct bgp_path_info *pi;
718e3744 5233
9bcb3eef 5234 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5235
d62a17ae 5236 /* Check selected route and self inserted route. */
9bcb3eef 5237 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5238 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5239 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5240 break;
718e3744 5241
d62a17ae 5242 /* Withdraw static BGP route from routing table. */
40381db7 5243 if (pi) {
49e5a4a0 5244#ifdef ENABLE_BGP_VNC
d62a17ae 5245 rfapiProcessWithdraw(
40381db7 5246 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5247 1); /* Kill, since it is an administrative change */
65efcfce 5248#endif
ddb5b488
PZ
5249 if (SAFI_MPLS_VPN == safi
5250 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5251 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5252 }
40381db7 5253 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
5254 bgp_path_info_delete(dest, pi);
5255 bgp_process(bgp, dest, afi, safi);
d62a17ae 5256 }
718e3744 5257
d62a17ae 5258 /* Unlock bgp_node_lookup. */
9bcb3eef 5259 bgp_dest_unlock_node(dest);
718e3744 5260}
5261
5f040085 5262static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5263 struct bgp_static *bgp_static, afi_t afi,
5264 safi_t safi)
137446f9 5265{
9bcb3eef 5266 struct bgp_dest *dest;
4b7e6066 5267 struct bgp_path_info *new;
d62a17ae 5268 struct attr *attr_new;
5269 struct attr attr = {0};
40381db7 5270 struct bgp_path_info *pi;
49e5a4a0 5271#ifdef ENABLE_BGP_VNC
d62a17ae 5272 mpls_label_t label = 0;
65efcfce 5273#endif
d7c0a89a 5274 uint32_t num_labels = 0;
d62a17ae 5275 union gw_addr add;
137446f9 5276
d62a17ae 5277 assert(bgp_static);
137446f9 5278
b57ba6d2
MK
5279 if (bgp_static->label != MPLS_INVALID_LABEL)
5280 num_labels = 1;
9bcb3eef
DS
5281 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5282 &bgp_static->prd);
137446f9 5283
d62a17ae 5284 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5285
d62a17ae 5286 attr.nexthop = bgp_static->igpnexthop;
5287 attr.med = bgp_static->igpmetric;
5288 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5289
d62a17ae 5290 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5291 || (safi == SAFI_ENCAP)) {
5292 if (afi == AFI_IP) {
5293 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5294 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5295 }
5296 }
5297 if (afi == AFI_L2VPN) {
5298 if (bgp_static->gatewayIp.family == AF_INET)
5299 add.ipv4.s_addr =
5300 bgp_static->gatewayIp.u.prefix4.s_addr;
5301 else if (bgp_static->gatewayIp.family == AF_INET6)
5302 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5303 sizeof(struct in6_addr));
5304 overlay_index_update(&attr, bgp_static->eth_s_id, &add);
5305 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5306 struct bgp_encap_type_vxlan bet;
5307 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5308 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5309 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5310 }
5311 if (bgp_static->router_mac) {
5312 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5313 }
5314 }
5315 /* Apply route-map. */
5316 if (bgp_static->rmap.name) {
5317 struct attr attr_tmp = attr;
40381db7 5318 struct bgp_path_info rmap_path;
b68885f9 5319 route_map_result_t ret;
137446f9 5320
40381db7
DS
5321 rmap_path.peer = bgp->peer_self;
5322 rmap_path.attr = &attr_tmp;
137446f9 5323
d62a17ae 5324 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5325
40381db7
DS
5326 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
5327 &rmap_path);
137446f9 5328
d62a17ae 5329 bgp->peer_self->rmap_type = 0;
137446f9 5330
d62a17ae 5331 if (ret == RMAP_DENYMATCH) {
5332 /* Free uninterned attribute. */
5333 bgp_attr_flush(&attr_tmp);
137446f9 5334
d62a17ae 5335 /* Unintern original. */
5336 aspath_unintern(&attr.aspath);
5337 bgp_static_withdraw_safi(bgp, p, afi, safi,
5338 &bgp_static->prd);
5339 return;
5340 }
137446f9 5341
d62a17ae 5342 attr_new = bgp_attr_intern(&attr_tmp);
5343 } else {
5344 attr_new = bgp_attr_intern(&attr);
5345 }
137446f9 5346
9bcb3eef 5347 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5348 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5349 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5350 break;
5351
40381db7 5352 if (pi) {
d62a17ae 5353 memset(&add, 0, sizeof(union gw_addr));
40381db7
DS
5354 if (attrhash_cmp(pi->attr, attr_new)
5355 && overlay_index_equal(afi, pi, bgp_static->eth_s_id, &add)
5356 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 5357 bgp_dest_unlock_node(dest);
d62a17ae 5358 bgp_attr_unintern(&attr_new);
5359 aspath_unintern(&attr.aspath);
5360 return;
5361 } else {
5362 /* The attribute is changed. */
9bcb3eef 5363 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5364
5365 /* Rewrite BGP route information. */
40381db7 5366 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5367 bgp_path_info_restore(dest, pi);
d62a17ae 5368 else
40381db7
DS
5369 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5370 bgp_attr_unintern(&pi->attr);
5371 pi->attr = attr_new;
5372 pi->uptime = bgp_clock();
49e5a4a0 5373#ifdef ENABLE_BGP_VNC
40381db7
DS
5374 if (pi->extra)
5375 label = decode_label(&pi->extra->label[0]);
65efcfce 5376#endif
137446f9 5377
d62a17ae 5378 /* Process change. */
40381db7 5379 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5380 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5381
5382 if (SAFI_MPLS_VPN == safi
5383 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5384 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5385 }
49e5a4a0 5386#ifdef ENABLE_BGP_VNC
40381db7
DS
5387 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5388 pi->attr, afi, safi, pi->type,
5389 pi->sub_type, &label);
65efcfce 5390#endif
9bcb3eef 5391 bgp_dest_unlock_node(dest);
d62a17ae 5392 aspath_unintern(&attr.aspath);
5393 return;
5394 }
5395 }
137446f9
LB
5396
5397
d62a17ae 5398 /* Make new BGP info. */
5399 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5400 attr_new, dest);
1defdda8 5401 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5402 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5403 if (num_labels) {
5404 new->extra->label[0] = bgp_static->label;
5405 new->extra->num_labels = num_labels;
5406 }
49e5a4a0 5407#ifdef ENABLE_BGP_VNC
d62a17ae 5408 label = decode_label(&bgp_static->label);
65efcfce 5409#endif
137446f9 5410
d62a17ae 5411 /* Aggregate address increment. */
5412 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5413
d62a17ae 5414 /* Register new BGP information. */
9bcb3eef 5415 bgp_path_info_add(dest, new);
d62a17ae 5416 /* route_node_get lock */
9bcb3eef 5417 bgp_dest_unlock_node(dest);
137446f9 5418
d62a17ae 5419 /* Process change. */
9bcb3eef 5420 bgp_process(bgp, dest, afi, safi);
137446f9 5421
ddb5b488
PZ
5422 if (SAFI_MPLS_VPN == safi
5423 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5424 vpn_leak_to_vrf_update(bgp, new);
5425 }
49e5a4a0 5426#ifdef ENABLE_BGP_VNC
d62a17ae 5427 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5428 safi, new->type, new->sub_type, &label);
65efcfce
LB
5429#endif
5430
d62a17ae 5431 /* Unintern original. */
5432 aspath_unintern(&attr.aspath);
137446f9
LB
5433}
5434
718e3744 5435/* Configure static BGP network. When user don't run zebra, static
5436 route should be installed as valid. */
e2a86ad9
DS
5437static int bgp_static_set(struct vty *vty, const char *negate,
5438 const char *ip_str, afi_t afi, safi_t safi,
d7c0a89a 5439 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 5440{
5441 VTY_DECLVAR_CONTEXT(bgp, bgp);
5442 int ret;
5443 struct prefix p;
5444 struct bgp_static *bgp_static;
9bcb3eef 5445 struct bgp_dest *dest;
d7c0a89a 5446 uint8_t need_update = 0;
d62a17ae 5447
5448 /* Convert IP prefix string to struct prefix. */
5449 ret = str2prefix(ip_str, &p);
5450 if (!ret) {
5451 vty_out(vty, "%% Malformed prefix\n");
5452 return CMD_WARNING_CONFIG_FAILED;
5453 }
5454 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5455 vty_out(vty, "%% Malformed prefix (link-local address)\n");
5456 return CMD_WARNING_CONFIG_FAILED;
5457 }
718e3744 5458
d62a17ae 5459 apply_mask(&p);
718e3744 5460
e2a86ad9 5461 if (negate) {
718e3744 5462
e2a86ad9 5463 /* Set BGP static route configuration. */
9bcb3eef 5464 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5465
9bcb3eef 5466 if (!dest) {
a4d82a8a 5467 vty_out(vty, "%% Can't find static route specified\n");
d62a17ae 5468 return CMD_WARNING_CONFIG_FAILED;
5469 }
5470
9bcb3eef 5471 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 5472
e2a86ad9
DS
5473 if ((label_index != BGP_INVALID_LABEL_INDEX)
5474 && (label_index != bgp_static->label_index)) {
5475 vty_out(vty,
5476 "%% label-index doesn't match static route\n");
5477 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5478 }
d62a17ae 5479
e2a86ad9
DS
5480 if ((rmap && bgp_static->rmap.name)
5481 && strcmp(rmap, bgp_static->rmap.name)) {
5482 vty_out(vty,
5483 "%% route-map name doesn't match static route\n");
5484 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5485 }
718e3744 5486
e2a86ad9
DS
5487 /* Update BGP RIB. */
5488 if (!bgp_static->backdoor)
5489 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5490
e2a86ad9
DS
5491 /* Clear configuration. */
5492 bgp_static_free(bgp_static);
9bcb3eef
DS
5493 bgp_dest_set_bgp_static_info(dest, NULL);
5494 bgp_dest_unlock_node(dest);
5495 bgp_dest_unlock_node(dest);
e2a86ad9 5496 } else {
718e3744 5497
e2a86ad9 5498 /* Set BGP static route configuration. */
9bcb3eef
DS
5499 dest = bgp_node_get(bgp->route[afi][safi], &p);
5500 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 5501 if (bgp_static) {
e2a86ad9 5502 /* Configuration change. */
e2a86ad9
DS
5503 /* Label index cannot be changed. */
5504 if (bgp_static->label_index != label_index) {
5505 vty_out(vty, "%% cannot change label-index\n");
5506 return CMD_WARNING_CONFIG_FAILED;
5507 }
d62a17ae 5508
e2a86ad9 5509 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5510 if (bgp_static->valid
5511 && bgp_static->backdoor != backdoor)
e2a86ad9 5512 need_update = 1;
718e3744 5513
e2a86ad9 5514 bgp_static->backdoor = backdoor;
718e3744 5515
e2a86ad9 5516 if (rmap) {
0a22ddfb
QY
5517 XFREE(MTYPE_ROUTE_MAP_NAME,
5518 bgp_static->rmap.name);
b4897fa5 5519 route_map_counter_decrement(
5520 bgp_static->rmap.map);
e2a86ad9
DS
5521 bgp_static->rmap.name =
5522 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5523 bgp_static->rmap.map =
5524 route_map_lookup_by_name(rmap);
b4897fa5 5525 route_map_counter_increment(
5526 bgp_static->rmap.map);
e2a86ad9 5527 } else {
0a22ddfb
QY
5528 XFREE(MTYPE_ROUTE_MAP_NAME,
5529 bgp_static->rmap.name);
b4897fa5 5530 route_map_counter_decrement(
5531 bgp_static->rmap.map);
e2a86ad9
DS
5532 bgp_static->rmap.map = NULL;
5533 bgp_static->valid = 0;
5534 }
9bcb3eef 5535 bgp_dest_unlock_node(dest);
e2a86ad9
DS
5536 } else {
5537 /* New configuration. */
5538 bgp_static = bgp_static_new();
5539 bgp_static->backdoor = backdoor;
5540 bgp_static->valid = 0;
5541 bgp_static->igpmetric = 0;
975a328e 5542 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 5543 bgp_static->label_index = label_index;
718e3744 5544
e2a86ad9 5545 if (rmap) {
0a22ddfb
QY
5546 XFREE(MTYPE_ROUTE_MAP_NAME,
5547 bgp_static->rmap.name);
b4897fa5 5548 route_map_counter_decrement(
5549 bgp_static->rmap.map);
e2a86ad9
DS
5550 bgp_static->rmap.name =
5551 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5552 bgp_static->rmap.map =
5553 route_map_lookup_by_name(rmap);
b4897fa5 5554 route_map_counter_increment(
5555 bgp_static->rmap.map);
e2a86ad9 5556 }
9bcb3eef 5557 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 5558 }
d62a17ae 5559
e2a86ad9
DS
5560 bgp_static->valid = 1;
5561 if (need_update)
5562 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5563
e2a86ad9
DS
5564 if (!bgp_static->backdoor)
5565 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5566 }
d62a17ae 5567
5568 return CMD_SUCCESS;
5569}
5570
5571void bgp_static_add(struct bgp *bgp)
5572{
5573 afi_t afi;
5574 safi_t safi;
9bcb3eef
DS
5575 struct bgp_dest *dest;
5576 struct bgp_dest *rm;
d62a17ae 5577 struct bgp_table *table;
5578 struct bgp_static *bgp_static;
5579
05c7a1cc 5580 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5581 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5582 dest = bgp_route_next(dest)) {
5583 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5584 continue;
ea47320b 5585
05c7a1cc
QY
5586 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5587 || (safi == SAFI_EVPN)) {
9bcb3eef 5588 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5589
5590 for (rm = bgp_table_top(table); rm;
5591 rm = bgp_route_next(rm)) {
a78beeb5 5592 bgp_static =
9bcb3eef 5593 bgp_dest_get_bgp_static_info(
5a8ba9fc 5594 rm);
9bcb3eef
DS
5595 bgp_static_update_safi(
5596 bgp, bgp_dest_get_prefix(rm),
5597 bgp_static, afi, safi);
d62a17ae 5598 }
05c7a1cc 5599 } else {
5a8ba9fc 5600 bgp_static_update(
9bcb3eef
DS
5601 bgp, bgp_dest_get_prefix(dest),
5602 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 5603 safi);
ea47320b 5604 }
05c7a1cc 5605 }
6aeb9e78
DS
5606}
5607
718e3744 5608/* Called from bgp_delete(). Delete all static routes from the BGP
5609 instance. */
d62a17ae 5610void bgp_static_delete(struct bgp *bgp)
5611{
5612 afi_t afi;
5613 safi_t safi;
9bcb3eef
DS
5614 struct bgp_dest *dest;
5615 struct bgp_dest *rm;
d62a17ae 5616 struct bgp_table *table;
5617 struct bgp_static *bgp_static;
5618
05c7a1cc 5619 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5620 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5621 dest = bgp_route_next(dest)) {
5622 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5623 continue;
ea47320b 5624
05c7a1cc
QY
5625 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5626 || (safi == SAFI_EVPN)) {
9bcb3eef 5627 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5628
5629 for (rm = bgp_table_top(table); rm;
5630 rm = bgp_route_next(rm)) {
a78beeb5 5631 bgp_static =
9bcb3eef 5632 bgp_dest_get_bgp_static_info(
5a8ba9fc 5633 rm);
c7d14ba6
PG
5634 if (!bgp_static)
5635 continue;
5636
05c7a1cc 5637 bgp_static_withdraw_safi(
9bcb3eef 5638 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
5639 AFI_IP, safi,
5640 (struct prefix_rd *)
9bcb3eef
DS
5641 bgp_dest_get_prefix(
5642 dest));
ea47320b 5643 bgp_static_free(bgp_static);
9bcb3eef
DS
5644 bgp_dest_set_bgp_static_info(dest,
5645 NULL);
5646 bgp_dest_unlock_node(dest);
d62a17ae 5647 }
05c7a1cc 5648 } else {
9bcb3eef 5649 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 5650 bgp_static_withdraw(bgp,
9bcb3eef 5651 bgp_dest_get_prefix(dest),
b54892e0 5652 afi, safi);
05c7a1cc 5653 bgp_static_free(bgp_static);
9bcb3eef
DS
5654 bgp_dest_set_bgp_static_info(dest, NULL);
5655 bgp_dest_unlock_node(dest);
ea47320b 5656 }
05c7a1cc 5657 }
d62a17ae 5658}
5659
5660void bgp_static_redo_import_check(struct bgp *bgp)
5661{
5662 afi_t afi;
5663 safi_t safi;
9bcb3eef
DS
5664 struct bgp_dest *dest;
5665 struct bgp_dest *rm;
d62a17ae 5666 struct bgp_table *table;
5667 struct bgp_static *bgp_static;
5668
5669 /* Use this flag to force reprocessing of the route */
892fedb6 5670 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 5671 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
5672 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5673 dest = bgp_route_next(dest)) {
5674 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5675 continue;
ea47320b 5676
05c7a1cc
QY
5677 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5678 || (safi == SAFI_EVPN)) {
9bcb3eef 5679 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5680
5681 for (rm = bgp_table_top(table); rm;
5682 rm = bgp_route_next(rm)) {
a78beeb5 5683 bgp_static =
9bcb3eef 5684 bgp_dest_get_bgp_static_info(
5a8ba9fc 5685 rm);
9bcb3eef
DS
5686 bgp_static_update_safi(
5687 bgp, bgp_dest_get_prefix(rm),
5688 bgp_static, afi, safi);
d62a17ae 5689 }
05c7a1cc 5690 } else {
9bcb3eef
DS
5691 bgp_static = bgp_dest_get_bgp_static_info(dest);
5692 bgp_static_update(bgp,
5693 bgp_dest_get_prefix(dest),
5694 bgp_static, afi, safi);
ea47320b 5695 }
05c7a1cc
QY
5696 }
5697 }
892fedb6 5698 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 5699}
5700
5701static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
5702 safi_t safi)
5703{
5704 struct bgp_table *table;
9bcb3eef 5705 struct bgp_dest *dest;
40381db7 5706 struct bgp_path_info *pi;
d62a17ae 5707
dfb6fd1d
NT
5708 /* Do not install the aggregate route if BGP is in the
5709 * process of termination.
5710 */
892fedb6
DA
5711 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
5712 || (bgp->peer_self == NULL))
dfb6fd1d
NT
5713 return;
5714
d62a17ae 5715 table = bgp->rib[afi][safi];
9bcb3eef
DS
5716 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5717 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
5718 if (pi->peer == bgp->peer_self
5719 && ((pi->type == ZEBRA_ROUTE_BGP
5720 && pi->sub_type == BGP_ROUTE_STATIC)
5721 || (pi->type != ZEBRA_ROUTE_BGP
5722 && pi->sub_type
d62a17ae 5723 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
5724 bgp_aggregate_decrement(
5725 bgp, bgp_dest_get_prefix(dest), pi, afi,
5726 safi);
40381db7 5727 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5728 bgp_path_info_delete(dest, pi);
5729 bgp_process(bgp, dest, afi, safi);
d62a17ae 5730 }
5731 }
5732 }
ad4cbda1 5733}
5734
5735/*
5736 * Purge all networks and redistributed routes from routing table.
5737 * Invoked upon the instance going down.
5738 */
d62a17ae 5739void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 5740{
d62a17ae 5741 afi_t afi;
5742 safi_t safi;
ad4cbda1 5743
05c7a1cc
QY
5744 FOREACH_AFI_SAFI (afi, safi)
5745 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 5746}
5747
137446f9
LB
5748/*
5749 * gpz 110624
5750 * Currently this is used to set static routes for VPN and ENCAP.
5751 * I think it can probably be factored with bgp_static_set.
5752 */
d62a17ae 5753int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
5754 const char *ip_str, const char *rd_str,
5755 const char *label_str, const char *rmap_str,
5756 int evpn_type, const char *esi, const char *gwip,
5757 const char *ethtag, const char *routermac)
5758{
5759 VTY_DECLVAR_CONTEXT(bgp, bgp);
5760 int ret;
5761 struct prefix p;
5762 struct prefix_rd prd;
9bcb3eef
DS
5763 struct bgp_dest *pdest;
5764 struct bgp_dest *dest;
d62a17ae 5765 struct bgp_table *table;
5766 struct bgp_static *bgp_static;
5767 mpls_label_t label = MPLS_INVALID_LABEL;
5768 struct prefix gw_ip;
5769
5770 /* validate ip prefix */
5771 ret = str2prefix(ip_str, &p);
5772 if (!ret) {
5773 vty_out(vty, "%% Malformed prefix\n");
5774 return CMD_WARNING_CONFIG_FAILED;
5775 }
5776 apply_mask(&p);
5777 if ((afi == AFI_L2VPN)
5778 && (bgp_build_evpn_prefix(evpn_type,
5779 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5780 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5781 return CMD_WARNING_CONFIG_FAILED;
5782 }
718e3744 5783
d62a17ae 5784 ret = str2prefix_rd(rd_str, &prd);
5785 if (!ret) {
5786 vty_out(vty, "%% Malformed rd\n");
5787 return CMD_WARNING_CONFIG_FAILED;
5788 }
718e3744 5789
d62a17ae 5790 if (label_str) {
5791 unsigned long label_val;
5792 label_val = strtoul(label_str, NULL, 10);
5793 encode_label(label_val, &label);
5794 }
9bedbb1e 5795
d62a17ae 5796 if (safi == SAFI_EVPN) {
5797 if (esi && str2esi(esi, NULL) == 0) {
5798 vty_out(vty, "%% Malformed ESI\n");
5799 return CMD_WARNING_CONFIG_FAILED;
5800 }
5801 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
5802 vty_out(vty, "%% Malformed Router MAC\n");
5803 return CMD_WARNING_CONFIG_FAILED;
5804 }
5805 if (gwip) {
5806 memset(&gw_ip, 0, sizeof(struct prefix));
5807 ret = str2prefix(gwip, &gw_ip);
5808 if (!ret) {
5809 vty_out(vty, "%% Malformed GatewayIp\n");
5810 return CMD_WARNING_CONFIG_FAILED;
5811 }
5812 if ((gw_ip.family == AF_INET
3714a385 5813 && is_evpn_prefix_ipaddr_v6(
d62a17ae 5814 (struct prefix_evpn *)&p))
5815 || (gw_ip.family == AF_INET6
3714a385 5816 && is_evpn_prefix_ipaddr_v4(
d62a17ae 5817 (struct prefix_evpn *)&p))) {
5818 vty_out(vty,
5819 "%% GatewayIp family differs with IP prefix\n");
5820 return CMD_WARNING_CONFIG_FAILED;
5821 }
5822 }
5823 }
9bcb3eef
DS
5824 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
5825 if (!bgp_dest_has_bgp_path_info_data(pdest))
5826 bgp_dest_set_bgp_table_info(pdest,
67009e22 5827 bgp_table_init(bgp, afi, safi));
9bcb3eef 5828 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 5829
9bcb3eef 5830 dest = bgp_node_get(table, &p);
d62a17ae 5831
9bcb3eef 5832 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 5833 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 5834 bgp_dest_unlock_node(dest);
d62a17ae 5835 } else {
5836 /* New configuration. */
5837 bgp_static = bgp_static_new();
5838 bgp_static->backdoor = 0;
5839 bgp_static->valid = 0;
5840 bgp_static->igpmetric = 0;
975a328e 5841 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 5842 bgp_static->label = label;
5843 bgp_static->prd = prd;
5844
5845 if (rmap_str) {
0a22ddfb 5846 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5847 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 5848 bgp_static->rmap.name =
5849 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
5850 bgp_static->rmap.map =
5851 route_map_lookup_by_name(rmap_str);
b4897fa5 5852 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 5853 }
718e3744 5854
d62a17ae 5855 if (safi == SAFI_EVPN) {
5856 if (esi) {
5857 bgp_static->eth_s_id =
5858 XCALLOC(MTYPE_ATTR,
5859 sizeof(struct eth_segment_id));
5860 str2esi(esi, bgp_static->eth_s_id);
5861 }
5862 if (routermac) {
5863 bgp_static->router_mac =
28328ea9 5864 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
5865 (void)prefix_str2mac(routermac,
5866 bgp_static->router_mac);
d62a17ae 5867 }
5868 if (gwip)
5869 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
5870 }
9bcb3eef 5871 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 5872
d62a17ae 5873 bgp_static->valid = 1;
5874 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
5875 }
718e3744 5876
d62a17ae 5877 return CMD_SUCCESS;
718e3744 5878}
5879
5880/* Configure static BGP network. */
d62a17ae 5881int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
5882 const char *ip_str, const char *rd_str,
5883 const char *label_str, int evpn_type, const char *esi,
5884 const char *gwip, const char *ethtag)
5885{
5886 VTY_DECLVAR_CONTEXT(bgp, bgp);
5887 int ret;
5888 struct prefix p;
5889 struct prefix_rd prd;
9bcb3eef
DS
5890 struct bgp_dest *pdest;
5891 struct bgp_dest *dest;
d62a17ae 5892 struct bgp_table *table;
5893 struct bgp_static *bgp_static;
5894 mpls_label_t label = MPLS_INVALID_LABEL;
5895
5896 /* Convert IP prefix string to struct prefix. */
5897 ret = str2prefix(ip_str, &p);
5898 if (!ret) {
5899 vty_out(vty, "%% Malformed prefix\n");
5900 return CMD_WARNING_CONFIG_FAILED;
5901 }
5902 apply_mask(&p);
5903 if ((afi == AFI_L2VPN)
5904 && (bgp_build_evpn_prefix(evpn_type,
5905 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5906 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5907 return CMD_WARNING_CONFIG_FAILED;
5908 }
5909 ret = str2prefix_rd(rd_str, &prd);
5910 if (!ret) {
5911 vty_out(vty, "%% Malformed rd\n");
5912 return CMD_WARNING_CONFIG_FAILED;
5913 }
718e3744 5914
d62a17ae 5915 if (label_str) {
5916 unsigned long label_val;
5917 label_val = strtoul(label_str, NULL, 10);
5918 encode_label(label_val, &label);
5919 }
718e3744 5920
9bcb3eef
DS
5921 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
5922 if (!bgp_dest_has_bgp_path_info_data(pdest))
5923 bgp_dest_set_bgp_table_info(pdest,
67009e22 5924 bgp_table_init(bgp, afi, safi));
d62a17ae 5925 else
9bcb3eef
DS
5926 bgp_dest_unlock_node(pdest);
5927 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 5928
9bcb3eef 5929 dest = bgp_node_lookup(table, &p);
6b0655a2 5930
9bcb3eef 5931 if (dest) {
d62a17ae 5932 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 5933
9bcb3eef 5934 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 5935 bgp_static_free(bgp_static);
9bcb3eef
DS
5936 bgp_dest_set_bgp_static_info(dest, NULL);
5937 bgp_dest_unlock_node(dest);
5938 bgp_dest_unlock_node(dest);
d62a17ae 5939 } else
5940 vty_out(vty, "%% Can't find the route\n");
5941
5942 return CMD_SUCCESS;
5943}
5944
5945static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
5946 const char *rmap_name)
5947{
5948 VTY_DECLVAR_CONTEXT(bgp, bgp);
5949 struct bgp_rmap *rmap;
5950
5951 rmap = &bgp->table_map[afi][safi];
5952 if (rmap_name) {
0a22ddfb 5953 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5954 route_map_counter_decrement(rmap->map);
d62a17ae 5955 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
5956 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 5957 route_map_counter_increment(rmap->map);
d62a17ae 5958 } else {
0a22ddfb 5959 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5960 route_map_counter_decrement(rmap->map);
d62a17ae 5961 rmap->map = NULL;
5962 }
73ac8160 5963
d62a17ae 5964 if (bgp_fibupd_safi(safi))
5965 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5966
d62a17ae 5967 return CMD_SUCCESS;
73ac8160
DS
5968}
5969
d62a17ae 5970static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
5971 const char *rmap_name)
73ac8160 5972{
d62a17ae 5973 VTY_DECLVAR_CONTEXT(bgp, bgp);
5974 struct bgp_rmap *rmap;
73ac8160 5975
d62a17ae 5976 rmap = &bgp->table_map[afi][safi];
0a22ddfb 5977 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5978 route_map_counter_decrement(rmap->map);
d62a17ae 5979 rmap->map = NULL;
73ac8160 5980
d62a17ae 5981 if (bgp_fibupd_safi(safi))
5982 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5983
d62a17ae 5984 return CMD_SUCCESS;
73ac8160
DS
5985}
5986
2b791107 5987void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 5988 safi_t safi)
73ac8160 5989{
d62a17ae 5990 if (bgp->table_map[afi][safi].name) {
d62a17ae 5991 vty_out(vty, " table-map %s\n",
5992 bgp->table_map[afi][safi].name);
5993 }
73ac8160
DS
5994}
5995
73ac8160
DS
5996DEFUN (bgp_table_map,
5997 bgp_table_map_cmd,
5998 "table-map WORD",
5999 "BGP table to RIB route download filter\n"
6000 "Name of the route map\n")
6001{
d62a17ae 6002 int idx_word = 1;
6003 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6004 argv[idx_word]->arg);
73ac8160
DS
6005}
6006DEFUN (no_bgp_table_map,
6007 no_bgp_table_map_cmd,
6008 "no table-map WORD",
3a2d747c 6009 NO_STR
73ac8160
DS
6010 "BGP table to RIB route download filter\n"
6011 "Name of the route map\n")
6012{
d62a17ae 6013 int idx_word = 2;
6014 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6015 argv[idx_word]->arg);
73ac8160
DS
6016}
6017
e2a86ad9
DS
6018DEFPY(bgp_network,
6019 bgp_network_cmd,
6020 "[no] network \
6021 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6022 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6023 backdoor$backdoor}]",
6024 NO_STR
6025 "Specify a network to announce via BGP\n"
6026 "IPv4 prefix\n"
6027 "Network number\n"
6028 "Network mask\n"
6029 "Network mask\n"
6030 "Route-map to modify the attributes\n"
6031 "Name of the route map\n"
6032 "Label index to associate with the prefix\n"
6033 "Label index value\n"
6034 "Specify a BGP backdoor route\n")
6035{
6036 char addr_prefix_str[BUFSIZ];
6037
6038 if (address_str) {
6039 int ret;
718e3744 6040
e2a86ad9
DS
6041 ret = netmask_str2prefix_str(address_str, netmask_str,
6042 addr_prefix_str);
6043 if (!ret) {
6044 vty_out(vty, "%% Inconsistent address and mask\n");
6045 return CMD_WARNING_CONFIG_FAILED;
6046 }
d62a17ae 6047 }
718e3744 6048
a4d82a8a
PZ
6049 return bgp_static_set(
6050 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
6051 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
6052 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 6053}
6054
e2a86ad9
DS
6055DEFPY(ipv6_bgp_network,
6056 ipv6_bgp_network_cmd,
6057 "[no] network X:X::X:X/M$prefix \
6058 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6059 NO_STR
6060 "Specify a network to announce via BGP\n"
6061 "IPv6 prefix\n"
6062 "Route-map to modify the attributes\n"
6063 "Name of the route map\n"
6064 "Label index to associate with the prefix\n"
6065 "Label index value\n")
718e3744 6066{
a4d82a8a
PZ
6067 return bgp_static_set(
6068 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
6069 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
6070}
6071
d62a17ae 6072static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6073{
d62a17ae 6074 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6075}
6076
d62a17ae 6077static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6078{
20894f50
DA
6079 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6080 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6081 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6082}
718e3744 6083
3dc339cd
DA
6084static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6085 struct aspath *aspath,
6086 struct community *comm,
6087 struct ecommunity *ecomm,
6088 struct lcommunity *lcomm)
eaaf8adb
DS
6089{
6090 static struct aspath *ae = NULL;
6091
6092 if (!ae)
6093 ae = aspath_empty();
6094
40381db7 6095 if (!pi)
3dc339cd 6096 return false;
eaaf8adb 6097
40381db7 6098 if (origin != pi->attr->origin)
3dc339cd 6099 return false;
eaaf8adb 6100
40381db7 6101 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 6102 return false;
29f7d023 6103
40381db7 6104 if (!community_cmp(pi->attr->community, comm))
3dc339cd 6105 return false;
eaaf8adb 6106
3da2cc32 6107 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
3dc339cd 6108 return false;
eaaf8adb 6109
dd18c5a9 6110 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 6111 return false;
dd18c5a9 6112
40381db7 6113 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 6114 return false;
7ce8a8e0 6115
3dc339cd 6116 return true;
eaaf8adb
DS
6117}
6118
5f040085
DS
6119static void bgp_aggregate_install(
6120 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6121 uint8_t origin, struct aspath *aspath, struct community *community,
6122 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6123 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 6124{
9bcb3eef 6125 struct bgp_dest *dest;
c701010e 6126 struct bgp_table *table;
6f94b685 6127 struct bgp_path_info *pi, *orig, *new;
20894f50 6128 struct attr *attr;
c701010e
DS
6129
6130 table = bgp->rib[afi][safi];
6131
9bcb3eef 6132 dest = bgp_node_get(table, p);
eaaf8adb 6133
9bcb3eef 6134 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6135 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6136 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6137 break;
6138
c701010e 6139 if (aggregate->count > 0) {
eaaf8adb
DS
6140 /*
6141 * If the aggregate information has not changed
6142 * no need to re-install it again.
6143 */
6f94b685 6144 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6145 ecommunity, lcommunity)) {
9bcb3eef 6146 bgp_dest_unlock_node(dest);
eaaf8adb
DS
6147
6148 if (aspath)
6149 aspath_free(aspath);
6150 if (community)
3c1f53de 6151 community_free(&community);
3da2cc32
DS
6152 if (ecommunity)
6153 ecommunity_free(&ecommunity);
dd18c5a9
DS
6154 if (lcommunity)
6155 lcommunity_free(&lcommunity);
eaaf8adb
DS
6156
6157 return;
6158 }
6159
6160 /*
6161 * Mark the old as unusable
6162 */
40381db7 6163 if (pi)
9bcb3eef 6164 bgp_path_info_delete(dest, pi);
eaaf8adb 6165
20894f50
DA
6166 attr = bgp_attr_aggregate_intern(
6167 bgp, origin, aspath, community, ecommunity, lcommunity,
6168 aggregate, atomic_aggregate, p);
6169
6170 if (!attr) {
6171 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
6172 return;
6173 }
6174
3da2cc32 6175 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 6176 bgp->peer_self, attr, dest);
20894f50 6177
1defdda8 6178 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6179
9bcb3eef
DS
6180 bgp_path_info_add(dest, new);
6181 bgp_process(bgp, dest, afi, safi);
c701010e 6182 } else {
6f94b685 6183 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6184 if (pi->peer == bgp->peer_self
6185 && pi->type == ZEBRA_ROUTE_BGP
6186 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6187 break;
6188
6189 /* Withdraw static BGP route from routing table. */
40381db7 6190 if (pi) {
9bcb3eef
DS
6191 bgp_path_info_delete(dest, pi);
6192 bgp_process(bgp, dest, afi, safi);
c701010e
DS
6193 }
6194 }
6195
9bcb3eef 6196 bgp_dest_unlock_node(dest);
c701010e
DS
6197}
6198
b5d58c32 6199/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
6200void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
6201 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 6202{
6203 struct bgp_table *table;
9bcb3eef
DS
6204 struct bgp_dest *top;
6205 struct bgp_dest *dest;
d7c0a89a 6206 uint8_t origin;
d62a17ae 6207 struct aspath *aspath = NULL;
d62a17ae 6208 struct community *community = NULL;
3da2cc32 6209 struct ecommunity *ecommunity = NULL;
dd18c5a9 6210 struct lcommunity *lcommunity = NULL;
40381db7 6211 struct bgp_path_info *pi;
d62a17ae 6212 unsigned long match = 0;
d7c0a89a 6213 uint8_t atomic_aggregate = 0;
d62a17ae 6214
9f822fa2
S
6215 /* If the bgp instance is being deleted or self peer is deleted
6216 * then do not create aggregate route
6217 */
892fedb6
DA
6218 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6219 || (bgp->peer_self == NULL))
9f822fa2
S
6220 return;
6221
d62a17ae 6222 /* ORIGIN attribute: If at least one route among routes that are
6223 aggregated has ORIGIN with the value INCOMPLETE, then the
6224 aggregated route must have the ORIGIN attribute with the value
6225 INCOMPLETE. Otherwise, if at least one route among routes that
6226 are aggregated has ORIGIN with the value EGP, then the aggregated
6227 route must have the origin attribute with the value EGP. In all
6228 other case the value of the ORIGIN attribute of the aggregated
6229 route is INTERNAL. */
6230 origin = BGP_ORIGIN_IGP;
718e3744 6231
d62a17ae 6232 table = bgp->rib[afi][safi];
718e3744 6233
d62a17ae 6234 top = bgp_node_get(table, p);
9bcb3eef
DS
6235 for (dest = bgp_node_get(table, p); dest;
6236 dest = bgp_route_next_until(dest, top)) {
6237 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6238
9bcb3eef 6239 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 6240 continue;
d62a17ae 6241
c2ff8b3e 6242 match = 0;
d62a17ae 6243
9bcb3eef 6244 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 6245 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 6246 continue;
718e3744 6247
40381db7 6248 if (pi->attr->flag
c2ff8b3e
DS
6249 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
6250 atomic_aggregate = 1;
d62a17ae 6251
40381db7 6252 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 6253 continue;
d62a17ae 6254
f273fef1
DS
6255 /*
6256 * summary-only aggregate route suppress
6257 * aggregated route announcements.
6258 */
c2ff8b3e 6259 if (aggregate->summary_only) {
40381db7 6260 (bgp_path_info_extra_get(pi))->suppress++;
9bcb3eef 6261 bgp_path_info_set_flag(dest, pi,
18ee8310 6262 BGP_PATH_ATTR_CHANGED);
c2ff8b3e 6263 match++;
d62a17ae 6264 }
c2ff8b3e
DS
6265
6266 aggregate->count++;
6267
f273fef1
DS
6268 /*
6269 * If at least one route among routes that are
6270 * aggregated has ORIGIN with the value INCOMPLETE,
6271 * then the aggregated route MUST have the ORIGIN
6272 * attribute with the value INCOMPLETE. Otherwise, if
6273 * at least one route among routes that are aggregated
6274 * has ORIGIN with the value EGP, then the aggregated
6275 * route MUST have the ORIGIN attribute with the value
6276 * EGP.
6277 */
fc968841
NT
6278 switch (pi->attr->origin) {
6279 case BGP_ORIGIN_INCOMPLETE:
6280 aggregate->incomplete_origin_count++;
6281 break;
6282 case BGP_ORIGIN_EGP:
6283 aggregate->egp_origin_count++;
6284 break;
6285 default:
6286 /*Do nothing.
6287 */
6288 break;
6289 }
c2ff8b3e
DS
6290
6291 if (!aggregate->as_set)
6292 continue;
6293
f273fef1
DS
6294 /*
6295 * as-set aggregate route generate origin, as path,
6296 * and community aggregation.
6297 */
fc968841
NT
6298 /* Compute aggregate route's as-path.
6299 */
ef51a7d8 6300 bgp_compute_aggregate_aspath_hash(aggregate,
6301 pi->attr->aspath);
c2ff8b3e 6302
fc968841
NT
6303 /* Compute aggregate route's community.
6304 */
6305 if (pi->attr->community)
21fec674 6306 bgp_compute_aggregate_community_hash(
fc968841
NT
6307 aggregate,
6308 pi->attr->community);
dd18c5a9 6309
fc968841
NT
6310 /* Compute aggregate route's extended community.
6311 */
6312 if (pi->attr->ecommunity)
4edd83f9 6313 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
6314 aggregate,
6315 pi->attr->ecommunity);
6316
6317 /* Compute aggregate route's large community.
6318 */
6319 if (pi->attr->lcommunity)
f1eb1f05 6320 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
6321 aggregate,
6322 pi->attr->lcommunity);
d62a17ae 6323 }
c2ff8b3e 6324 if (match)
9bcb3eef 6325 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 6326 }
21fec674 6327 if (aggregate->as_set) {
ef51a7d8 6328 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 6329 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 6330 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 6331 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 6332 }
6333
f1eb1f05 6334
9bcb3eef 6335 bgp_dest_unlock_node(top);
718e3744 6336
718e3744 6337
fc968841
NT
6338 if (aggregate->incomplete_origin_count > 0)
6339 origin = BGP_ORIGIN_INCOMPLETE;
6340 else if (aggregate->egp_origin_count > 0)
6341 origin = BGP_ORIGIN_EGP;
d62a17ae 6342
229757f1
DA
6343 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6344 origin = aggregate->origin;
6345
fc968841
NT
6346 if (aggregate->as_set) {
6347 if (aggregate->aspath)
6348 /* Retrieve aggregate route's as-path.
6349 */
6350 aspath = aspath_dup(aggregate->aspath);
d62a17ae 6351
fc968841
NT
6352 if (aggregate->community)
6353 /* Retrieve aggregate route's community.
6354 */
6355 community = community_dup(aggregate->community);
3da2cc32 6356
fc968841
NT
6357 if (aggregate->ecommunity)
6358 /* Retrieve aggregate route's ecommunity.
6359 */
6360 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 6361
fc968841
NT
6362 if (aggregate->lcommunity)
6363 /* Retrieve aggregate route's lcommunity.
6364 */
6365 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 6366 }
718e3744 6367
c701010e 6368 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
6369 ecommunity, lcommunity, atomic_aggregate,
6370 aggregate);
718e3744 6371}
6372
5f040085
DS
6373void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
6374 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
6375{
6376 struct bgp_table *table;
9bcb3eef
DS
6377 struct bgp_dest *top;
6378 struct bgp_dest *dest;
40381db7 6379 struct bgp_path_info *pi;
3b7db173
DS
6380 unsigned long match;
6381
6382 table = bgp->rib[afi][safi];
6383
6384 /* If routes exists below this node, generate aggregate routes. */
6385 top = bgp_node_get(table, p);
9bcb3eef
DS
6386 for (dest = bgp_node_get(table, p); dest;
6387 dest = bgp_route_next_until(dest, top)) {
6388 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6389
9bcb3eef 6390 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
6391 continue;
6392 match = 0;
6393
9bcb3eef 6394 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 6395 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
6396 continue;
6397
40381db7 6398 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
6399 continue;
6400
40381db7
DS
6401 if (aggregate->summary_only && pi->extra) {
6402 pi->extra->suppress--;
3b7db173 6403
40381db7 6404 if (pi->extra->suppress == 0) {
18ee8310 6405 bgp_path_info_set_flag(
9bcb3eef
DS
6406 dest, pi,
6407 BGP_PATH_ATTR_CHANGED);
3b7db173
DS
6408 match++;
6409 }
6410 }
6411 aggregate->count--;
fc968841
NT
6412
6413 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6414 aggregate->incomplete_origin_count--;
6415 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6416 aggregate->egp_origin_count--;
6417
6418 if (aggregate->as_set) {
6419 /* Remove as-path from aggregate.
6420 */
ef51a7d8 6421 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
6422 aggregate,
6423 pi->attr->aspath);
6424
6425 if (pi->attr->community)
6426 /* Remove community from aggregate.
6427 */
21fec674 6428 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
6429 aggregate,
6430 pi->attr->community);
6431
6432 if (pi->attr->ecommunity)
6433 /* Remove ecommunity from aggregate.
6434 */
4edd83f9 6435 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
6436 aggregate,
6437 pi->attr->ecommunity);
6438
6439 if (pi->attr->lcommunity)
6440 /* Remove lcommunity from aggregate.
6441 */
f1eb1f05 6442 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
6443 aggregate,
6444 pi->attr->lcommunity);
6445 }
3b7db173
DS
6446 }
6447
6448 /* If this node was suppressed, process the change. */
6449 if (match)
9bcb3eef 6450 bgp_process(bgp, dest, afi, safi);
3b7db173 6451 }
f1eb1f05 6452 if (aggregate->as_set) {
ef51a7d8 6453 aspath_free(aggregate->aspath);
6454 aggregate->aspath = NULL;
21fec674 6455 if (aggregate->community)
6456 community_free(&aggregate->community);
4edd83f9 6457 if (aggregate->ecommunity)
6458 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 6459 if (aggregate->lcommunity)
6460 lcommunity_free(&aggregate->lcommunity);
6461 }
6462
9bcb3eef 6463 bgp_dest_unlock_node(top);
3b7db173 6464}
718e3744 6465
5f040085
DS
6466static void bgp_add_route_to_aggregate(struct bgp *bgp,
6467 const struct prefix *aggr_p,
fc968841
NT
6468 struct bgp_path_info *pinew, afi_t afi,
6469 safi_t safi,
6470 struct bgp_aggregate *aggregate)
6471{
6472 uint8_t origin;
6473 struct aspath *aspath = NULL;
6474 uint8_t atomic_aggregate = 0;
6475 struct community *community = NULL;
6476 struct ecommunity *ecommunity = NULL;
6477 struct lcommunity *lcommunity = NULL;
6478
6479 /* ORIGIN attribute: If at least one route among routes that are
6480 * aggregated has ORIGIN with the value INCOMPLETE, then the
6481 * aggregated route must have the ORIGIN attribute with the value
6482 * INCOMPLETE. Otherwise, if at least one route among routes that
6483 * are aggregated has ORIGIN with the value EGP, then the aggregated
6484 * route must have the origin attribute with the value EGP. In all
6485 * other case the value of the ORIGIN attribute of the aggregated
6486 * route is INTERNAL.
6487 */
6488 origin = BGP_ORIGIN_IGP;
6489
6490 aggregate->count++;
6491
6492 if (aggregate->summary_only)
6493 (bgp_path_info_extra_get(pinew))->suppress++;
6494
6495 switch (pinew->attr->origin) {
6496 case BGP_ORIGIN_INCOMPLETE:
6497 aggregate->incomplete_origin_count++;
6498 break;
6499 case BGP_ORIGIN_EGP:
6500 aggregate->egp_origin_count++;
6501 break;
6502 default:
6503 /* Do nothing.
6504 */
6505 break;
6506 }
6507
6508 if (aggregate->incomplete_origin_count > 0)
6509 origin = BGP_ORIGIN_INCOMPLETE;
6510 else if (aggregate->egp_origin_count > 0)
6511 origin = BGP_ORIGIN_EGP;
6512
229757f1
DA
6513 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6514 origin = aggregate->origin;
6515
fc968841
NT
6516 if (aggregate->as_set) {
6517 /* Compute aggregate route's as-path.
6518 */
6519 bgp_compute_aggregate_aspath(aggregate,
6520 pinew->attr->aspath);
6521
6522 /* Compute aggregate route's community.
6523 */
6524 if (pinew->attr->community)
6525 bgp_compute_aggregate_community(
6526 aggregate,
6527 pinew->attr->community);
6528
6529 /* Compute aggregate route's extended community.
6530 */
6531 if (pinew->attr->ecommunity)
6532 bgp_compute_aggregate_ecommunity(
6533 aggregate,
6534 pinew->attr->ecommunity);
6535
6536 /* Compute aggregate route's large community.
6537 */
6538 if (pinew->attr->lcommunity)
6539 bgp_compute_aggregate_lcommunity(
6540 aggregate,
6541 pinew->attr->lcommunity);
6542
6543 /* Retrieve aggregate route's as-path.
6544 */
6545 if (aggregate->aspath)
6546 aspath = aspath_dup(aggregate->aspath);
6547
6548 /* Retrieve aggregate route's community.
6549 */
6550 if (aggregate->community)
6551 community = community_dup(aggregate->community);
6552
6553 /* Retrieve aggregate route's ecommunity.
6554 */
6555 if (aggregate->ecommunity)
6556 ecommunity = ecommunity_dup(aggregate->ecommunity);
6557
6558 /* Retrieve aggregate route's lcommunity.
6559 */
6560 if (aggregate->lcommunity)
6561 lcommunity = lcommunity_dup(aggregate->lcommunity);
6562 }
6563
6564 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6565 aspath, community, ecommunity,
6566 lcommunity, atomic_aggregate, aggregate);
6567}
6568
6569static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
6570 safi_t safi,
6571 struct bgp_path_info *pi,
6572 struct bgp_aggregate *aggregate,
5f040085 6573 const struct prefix *aggr_p)
fc968841
NT
6574{
6575 uint8_t origin;
6576 struct aspath *aspath = NULL;
6577 uint8_t atomic_aggregate = 0;
6578 struct community *community = NULL;
6579 struct ecommunity *ecommunity = NULL;
6580 struct lcommunity *lcommunity = NULL;
6581 unsigned long match = 0;
6582
6583 if (BGP_PATH_HOLDDOWN(pi))
6584 return;
6585
6586 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6587 return;
6588
6589 if (aggregate->summary_only
6590 && pi->extra
6591 && pi->extra->suppress > 0) {
6592 pi->extra->suppress--;
6593
6594 if (pi->extra->suppress == 0) {
6595 bgp_path_info_set_flag(pi->net, pi,
6596 BGP_PATH_ATTR_CHANGED);
6597 match++;
6598 }
6599 }
6600
6601 if (aggregate->count > 0)
6602 aggregate->count--;
6603
6604 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6605 aggregate->incomplete_origin_count--;
6606 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6607 aggregate->egp_origin_count--;
6608
6609 if (aggregate->as_set) {
6610 /* Remove as-path from aggregate.
6611 */
6612 bgp_remove_aspath_from_aggregate(aggregate,
6613 pi->attr->aspath);
6614
6615 if (pi->attr->community)
6616 /* Remove community from aggregate.
6617 */
6618 bgp_remove_community_from_aggregate(
6619 aggregate,
6620 pi->attr->community);
6621
6622 if (pi->attr->ecommunity)
6623 /* Remove ecommunity from aggregate.
6624 */
6625 bgp_remove_ecommunity_from_aggregate(
6626 aggregate,
6627 pi->attr->ecommunity);
6628
6629 if (pi->attr->lcommunity)
6630 /* Remove lcommunity from aggregate.
6631 */
6632 bgp_remove_lcommunity_from_aggregate(
6633 aggregate,
6634 pi->attr->lcommunity);
6635 }
6636
6637 /* If this node was suppressed, process the change. */
6638 if (match)
6639 bgp_process(bgp, pi->net, afi, safi);
6640
6641 origin = BGP_ORIGIN_IGP;
6642 if (aggregate->incomplete_origin_count > 0)
6643 origin = BGP_ORIGIN_INCOMPLETE;
6644 else if (aggregate->egp_origin_count > 0)
6645 origin = BGP_ORIGIN_EGP;
6646
229757f1
DA
6647 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6648 origin = aggregate->origin;
6649
fc968841
NT
6650 if (aggregate->as_set) {
6651 /* Retrieve aggregate route's as-path.
6652 */
6653 if (aggregate->aspath)
6654 aspath = aspath_dup(aggregate->aspath);
6655
6656 /* Retrieve aggregate route's community.
6657 */
6658 if (aggregate->community)
6659 community = community_dup(aggregate->community);
6660
6661 /* Retrieve aggregate route's ecommunity.
6662 */
6663 if (aggregate->ecommunity)
6664 ecommunity = ecommunity_dup(aggregate->ecommunity);
6665
6666 /* Retrieve aggregate route's lcommunity.
6667 */
6668 if (aggregate->lcommunity)
6669 lcommunity = lcommunity_dup(aggregate->lcommunity);
6670 }
6671
6672 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6673 aspath, community, ecommunity,
6674 lcommunity, atomic_aggregate, aggregate);
6675}
6676
5a1ae2c2 6677void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 6678 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 6679{
9bcb3eef
DS
6680 struct bgp_dest *child;
6681 struct bgp_dest *dest;
d62a17ae 6682 struct bgp_aggregate *aggregate;
6683 struct bgp_table *table;
718e3744 6684
d62a17ae 6685 table = bgp->aggregate[afi][safi];
f018db83 6686
d62a17ae 6687 /* No aggregates configured. */
6688 if (bgp_table_top_nolock(table) == NULL)
6689 return;
f018db83 6690
d62a17ae 6691 if (p->prefixlen == 0)
6692 return;
718e3744 6693
40381db7 6694 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 6695 return;
718e3744 6696
d62a17ae 6697 child = bgp_node_get(table, p);
718e3744 6698
d62a17ae 6699 /* Aggregate address configuration check. */
9bcb3eef
DS
6700 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
6701 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6702
9bcb3eef
DS
6703 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
6704 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
6705 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 6706 aggregate);
d62a17ae 6707 }
b1e62edd 6708 }
9bcb3eef 6709 bgp_dest_unlock_node(child);
718e3744 6710}
6711
5a1ae2c2 6712void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 6713 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 6714{
9bcb3eef
DS
6715 struct bgp_dest *child;
6716 struct bgp_dest *dest;
d62a17ae 6717 struct bgp_aggregate *aggregate;
6718 struct bgp_table *table;
718e3744 6719
d62a17ae 6720 table = bgp->aggregate[afi][safi];
718e3744 6721
d62a17ae 6722 /* No aggregates configured. */
6723 if (bgp_table_top_nolock(table) == NULL)
6724 return;
718e3744 6725
d62a17ae 6726 if (p->prefixlen == 0)
6727 return;
718e3744 6728
d62a17ae 6729 child = bgp_node_get(table, p);
718e3744 6730
d62a17ae 6731 /* Aggregate address configuration check. */
9bcb3eef
DS
6732 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
6733 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6734
9bcb3eef
DS
6735 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
6736 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 6737 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 6738 aggregate, dest_p);
d62a17ae 6739 }
b1e62edd 6740 }
9bcb3eef 6741 bgp_dest_unlock_node(child);
d62a17ae 6742}
718e3744 6743
718e3744 6744/* Aggregate route attribute. */
6745#define AGGREGATE_SUMMARY_ONLY 1
6746#define AGGREGATE_AS_SET 1
fb29348a 6747#define AGGREGATE_AS_UNSET 0
718e3744 6748
229757f1
DA
6749static const char *bgp_origin2str(uint8_t origin)
6750{
6751 switch (origin) {
6752 case BGP_ORIGIN_IGP:
6753 return "igp";
6754 case BGP_ORIGIN_EGP:
6755 return "egp";
6756 case BGP_ORIGIN_INCOMPLETE:
6757 return "incomplete";
6758 }
6759 return "n/a";
6760}
6761
d62a17ae 6762static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
6763 afi_t afi, safi_t safi)
718e3744 6764{
d62a17ae 6765 VTY_DECLVAR_CONTEXT(bgp, bgp);
6766 int ret;
6767 struct prefix p;
9bcb3eef 6768 struct bgp_dest *dest;
d62a17ae 6769 struct bgp_aggregate *aggregate;
718e3744 6770
d62a17ae 6771 /* Convert string to prefix structure. */
6772 ret = str2prefix(prefix_str, &p);
6773 if (!ret) {
6774 vty_out(vty, "Malformed prefix\n");
6775 return CMD_WARNING_CONFIG_FAILED;
6776 }
6777 apply_mask(&p);
6778
6779 /* Old configuration check. */
9bcb3eef
DS
6780 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
6781 if (!dest) {
d62a17ae 6782 vty_out(vty,
6783 "%% There is no aggregate-address configuration.\n");
6784 return CMD_WARNING_CONFIG_FAILED;
6785 }
f6269b4f 6786
9bcb3eef 6787 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
09990cdd 6788 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
dd18c5a9
DS
6789 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
6790 NULL, NULL, 0, aggregate);
d62a17ae 6791
6792 /* Unlock aggregate address configuration. */
9bcb3eef 6793 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
6794
6795 if (aggregate->community)
6796 community_free(&aggregate->community);
6797
6798 if (aggregate->community_hash) {
6799 /* Delete all communities in the hash.
6800 */
6801 hash_clean(aggregate->community_hash,
6802 bgp_aggr_community_remove);
6803 /* Free up the community_hash.
6804 */
6805 hash_free(aggregate->community_hash);
6806 }
6807
6808 if (aggregate->ecommunity)
6809 ecommunity_free(&aggregate->ecommunity);
6810
6811 if (aggregate->ecommunity_hash) {
6812 /* Delete all ecommunities in the hash.
6813 */
6814 hash_clean(aggregate->ecommunity_hash,
6815 bgp_aggr_ecommunity_remove);
6816 /* Free up the ecommunity_hash.
6817 */
6818 hash_free(aggregate->ecommunity_hash);
6819 }
6820
6821 if (aggregate->lcommunity)
6822 lcommunity_free(&aggregate->lcommunity);
6823
6824 if (aggregate->lcommunity_hash) {
6825 /* Delete all lcommunities in the hash.
6826 */
6827 hash_clean(aggregate->lcommunity_hash,
6828 bgp_aggr_lcommunity_remove);
6829 /* Free up the lcommunity_hash.
6830 */
6831 hash_free(aggregate->lcommunity_hash);
6832 }
6833
6834 if (aggregate->aspath)
6835 aspath_free(aggregate->aspath);
6836
6837 if (aggregate->aspath_hash) {
6838 /* Delete all as-paths in the hash.
6839 */
6840 hash_clean(aggregate->aspath_hash,
6841 bgp_aggr_aspath_remove);
6842 /* Free up the aspath_hash.
6843 */
6844 hash_free(aggregate->aspath_hash);
6845 }
6846
d62a17ae 6847 bgp_aggregate_free(aggregate);
9bcb3eef
DS
6848 bgp_dest_unlock_node(dest);
6849 bgp_dest_unlock_node(dest);
d62a17ae 6850
6851 return CMD_SUCCESS;
6852}
6853
6854static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
229757f1
DA
6855 safi_t safi, const char *rmap,
6856 uint8_t summary_only, uint8_t as_set,
6857 uint8_t origin)
d62a17ae 6858{
6859 VTY_DECLVAR_CONTEXT(bgp, bgp);
6860 int ret;
6861 struct prefix p;
9bcb3eef 6862 struct bgp_dest *dest;
d62a17ae 6863 struct bgp_aggregate *aggregate;
fb29348a 6864 uint8_t as_set_new = as_set;
d62a17ae 6865
6866 /* Convert string to prefix structure. */
6867 ret = str2prefix(prefix_str, &p);
6868 if (!ret) {
6869 vty_out(vty, "Malformed prefix\n");
6870 return CMD_WARNING_CONFIG_FAILED;
6871 }
6872 apply_mask(&p);
6873
3624ac81
DS
6874 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
6875 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
6876 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6877 prefix_str);
6878 return CMD_WARNING_CONFIG_FAILED;
6879 }
6880
d62a17ae 6881 /* Old configuration check. */
9bcb3eef
DS
6882 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
6883 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 6884
20894f50 6885 if (aggregate) {
d62a17ae 6886 vty_out(vty, "There is already same aggregate network.\n");
6887 /* try to remove the old entry */
6888 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
6889 if (ret) {
6890 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 6891 bgp_dest_unlock_node(dest);
d62a17ae 6892 return CMD_WARNING_CONFIG_FAILED;
6893 }
6894 }
718e3744 6895
d62a17ae 6896 /* Make aggregate address structure. */
6897 aggregate = bgp_aggregate_new();
6898 aggregate->summary_only = summary_only;
fb29348a
DA
6899
6900 /* Network operators MUST NOT locally generate any new
6901 * announcements containing AS_SET or AS_CONFED_SET. If they have
6902 * announced routes with AS_SET or AS_CONFED_SET in them, then they
6903 * SHOULD withdraw those routes and re-announce routes for the
6904 * aggregate or component prefixes (i.e., the more-specific routes
6905 * subsumed by the previously aggregated route) without AS_SET
6906 * or AS_CONFED_SET in the updates.
6907 */
7f972cd8 6908 if (bgp->reject_as_sets) {
fb29348a
DA
6909 if (as_set == AGGREGATE_AS_SET) {
6910 as_set_new = AGGREGATE_AS_UNSET;
6911 zlog_warn(
63efca0e 6912 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a
DA
6913 __func__);
6914 vty_out(vty,
6915 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
6916 }
6917 }
6918
6919 aggregate->as_set = as_set_new;
d62a17ae 6920 aggregate->safi = safi;
229757f1
DA
6921 /* Override ORIGIN attribute if defined.
6922 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
6923 * to IGP which is not what rfc4271 says.
6924 * This enables the same behavior, optionally.
6925 */
6926 aggregate->origin = origin;
20894f50
DA
6927
6928 if (rmap) {
6929 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6930 route_map_counter_decrement(aggregate->rmap.map);
6931 aggregate->rmap.name =
6932 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6933 aggregate->rmap.map = route_map_lookup_by_name(rmap);
6934 route_map_counter_increment(aggregate->rmap.map);
6935 }
9bcb3eef 6936 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 6937
d62a17ae 6938 /* Aggregate address insert into BGP routing table. */
fc968841 6939 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 6940
d62a17ae 6941 return CMD_SUCCESS;
718e3744 6942}
6943
6944DEFUN (aggregate_address,
6945 aggregate_address_cmd,
229757f1 6946 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 6947 "Configure BGP aggregate entries\n"
6948 "Aggregate prefix\n"
6949 "Generate AS set path information\n"
a636c635
DW
6950 "Filter more specific routes from updates\n"
6951 "Filter more specific routes from updates\n"
20894f50
DA
6952 "Generate AS set path information\n"
6953 "Apply route map to aggregate network\n"
229757f1
DA
6954 "Name of route map\n"
6955 "BGP origin code\n"
6956 "Remote EGP\n"
6957 "Local IGP\n"
6958 "Unknown heritage\n")
718e3744 6959{
d62a17ae 6960 int idx = 0;
6961 argv_find(argv, argc, "A.B.C.D/M", &idx);
6962 char *prefix = argv[idx]->arg;
20894f50 6963 char *rmap = NULL;
229757f1 6964 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
fb29348a
DA
6965 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
6966 : AGGREGATE_AS_UNSET;
d62a17ae 6967 idx = 0;
6968 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6969 ? AGGREGATE_SUMMARY_ONLY
6970 : 0;
e3e6107d 6971
20894f50
DA
6972 idx = 0;
6973 argv_find(argv, argc, "WORD", &idx);
6974 if (idx)
6975 rmap = argv[idx]->arg;
6976
229757f1
DA
6977 idx = 0;
6978 if (argv_find(argv, argc, "origin", &idx)) {
6979 if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
6980 origin = BGP_ORIGIN_IGP;
6981 if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
6982 origin = BGP_ORIGIN_EGP;
6983 if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
6984 origin = BGP_ORIGIN_INCOMPLETE;
6985 }
6986
6987 return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty), rmap,
6988 summary_only, as_set, origin);
718e3744 6989}
6990
e3e6107d
QY
6991DEFUN (aggregate_address_mask,
6992 aggregate_address_mask_cmd,
229757f1 6993 "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 6994 "Configure BGP aggregate entries\n"
6995 "Aggregate address\n"
6996 "Aggregate mask\n"
6997 "Generate AS set path information\n"
a636c635
DW
6998 "Filter more specific routes from updates\n"
6999 "Filter more specific routes from updates\n"
20894f50
DA
7000 "Generate AS set path information\n"
7001 "Apply route map to aggregate network\n"
229757f1
DA
7002 "Name of route map\n"
7003 "BGP origin code\n"
7004 "Remote EGP\n"
7005 "Local IGP\n"
7006 "Unknown heritage\n")
718e3744 7007{
d62a17ae 7008 int idx = 0;
7009 argv_find(argv, argc, "A.B.C.D", &idx);
7010 char *prefix = argv[idx]->arg;
7011 char *mask = argv[idx + 1]->arg;
cf40d052 7012 bool rmap_found;
20894f50 7013 char *rmap = NULL;
229757f1 7014 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
fb29348a
DA
7015 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
7016 : AGGREGATE_AS_UNSET;
d62a17ae 7017 idx = 0;
7018 int summary_only = argv_find(argv, argc, "summary-only", &idx)
7019 ? AGGREGATE_SUMMARY_ONLY
7020 : 0;
7021
cf40d052
DS
7022 rmap_found = argv_find(argv, argc, "WORD", &idx);
7023 if (rmap_found)
20894f50
DA
7024 rmap = argv[idx]->arg;
7025
d62a17ae 7026 char prefix_str[BUFSIZ];
7027 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
7028
7029 if (!ret) {
7030 vty_out(vty, "%% Inconsistent address and mask\n");
7031 return CMD_WARNING_CONFIG_FAILED;
7032 }
718e3744 7033
229757f1
DA
7034 idx = 0;
7035 if (argv_find(argv, argc, "origin", &idx)) {
7036 if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
7037 origin = BGP_ORIGIN_IGP;
7038 if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
7039 origin = BGP_ORIGIN_EGP;
7040 if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
7041 origin = BGP_ORIGIN_INCOMPLETE;
7042 }
7043
d62a17ae 7044 return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
229757f1 7045 rmap, summary_only, as_set, origin);
718e3744 7046}
7047
718e3744 7048DEFUN (no_aggregate_address,
7049 no_aggregate_address_cmd,
229757f1 7050 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 7051 NO_STR
7052 "Configure BGP aggregate entries\n"
a636c635
DW
7053 "Aggregate prefix\n"
7054 "Generate AS set path information\n"
e3e6107d
QY
7055 "Filter more specific routes from updates\n"
7056 "Filter more specific routes from updates\n"
b84da0db
DA
7057 "Generate AS set path information\n"
7058 "Apply route map to aggregate network\n"
229757f1
DA
7059 "Name of route map\n"
7060 "BGP origin code\n"
7061 "Remote EGP\n"
7062 "Local IGP\n"
7063 "Unknown heritage\n")
718e3744 7064{
d62a17ae 7065 int idx = 0;
7066 argv_find(argv, argc, "A.B.C.D/M", &idx);
7067 char *prefix = argv[idx]->arg;
7068 return bgp_aggregate_unset(vty, prefix, AFI_IP, bgp_node_safi(vty));
718e3744 7069}
7070
718e3744 7071DEFUN (no_aggregate_address_mask,
7072 no_aggregate_address_mask_cmd,
229757f1 7073 "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 7074 NO_STR
7075 "Configure BGP aggregate entries\n"
7076 "Aggregate address\n"
a636c635
DW
7077 "Aggregate mask\n"
7078 "Generate AS set path information\n"
e3e6107d
QY
7079 "Filter more specific routes from updates\n"
7080 "Filter more specific routes from updates\n"
b84da0db
DA
7081 "Generate AS set path information\n"
7082 "Apply route map to aggregate network\n"
229757f1
DA
7083 "Name of route map\n"
7084 "BGP origin code\n"
7085 "Remote EGP\n"
7086 "Local IGP\n"
7087 "Unknown heritage\n")
718e3744 7088{
d62a17ae 7089 int idx = 0;
7090 argv_find(argv, argc, "A.B.C.D", &idx);
7091 char *prefix = argv[idx]->arg;
7092 char *mask = argv[idx + 1]->arg;
718e3744 7093
d62a17ae 7094 char prefix_str[BUFSIZ];
7095 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
718e3744 7096
d62a17ae 7097 if (!ret) {
7098 vty_out(vty, "%% Inconsistent address and mask\n");
7099 return CMD_WARNING_CONFIG_FAILED;
7100 }
718e3744 7101
d62a17ae 7102 return bgp_aggregate_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
718e3744 7103}
7104
718e3744 7105DEFUN (ipv6_aggregate_address,
7106 ipv6_aggregate_address_cmd,
229757f1 7107 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 7108 "Configure BGP aggregate entries\n"
7109 "Aggregate prefix\n"
5101fece 7110 "Generate AS set path information\n"
7111 "Filter more specific routes from updates\n"
7112 "Filter more specific routes from updates\n"
20894f50
DA
7113 "Generate AS set path information\n"
7114 "Apply route map to aggregate network\n"
229757f1
DA
7115 "Name of route map\n"
7116 "BGP origin code\n"
7117 "Remote EGP\n"
7118 "Local IGP\n"
7119 "Unknown heritage\n")
718e3744 7120{
d62a17ae 7121 int idx = 0;
7122 argv_find(argv, argc, "X:X::X:X/M", &idx);
7123 char *prefix = argv[idx]->arg;
20894f50 7124 char *rmap = NULL;
273fae13 7125 bool rmap_found;
229757f1 7126 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
fb29348a
DA
7127 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
7128 : AGGREGATE_AS_UNSET;
5101fece 7129
7130 idx = 0;
d62a17ae 7131 int sum_only = argv_find(argv, argc, "summary-only", &idx)
7132 ? AGGREGATE_SUMMARY_ONLY
7133 : 0;
20894f50 7134
273fae13
DA
7135 rmap_found = argv_find(argv, argc, "WORD", &idx);
7136 if (rmap_found)
20894f50
DA
7137 rmap = argv[idx]->arg;
7138
229757f1
DA
7139 idx = 0;
7140 if (argv_find(argv, argc, "origin", &idx)) {
7141 if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
7142 origin = BGP_ORIGIN_IGP;
7143 if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
7144 origin = BGP_ORIGIN_EGP;
7145 if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
7146 origin = BGP_ORIGIN_INCOMPLETE;
7147 }
7148
20894f50 7149 return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, rmap,
229757f1 7150 sum_only, as_set, origin);
718e3744 7151}
7152
7153DEFUN (no_ipv6_aggregate_address,
7154 no_ipv6_aggregate_address_cmd,
229757f1 7155 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 7156 NO_STR
7157 "Configure BGP aggregate entries\n"
16cedbb0 7158 "Aggregate prefix\n"
5101fece 7159 "Generate AS set path information\n"
7160 "Filter more specific routes from updates\n"
7161 "Filter more specific routes from updates\n"
b84da0db
DA
7162 "Generate AS set path information\n"
7163 "Apply route map to aggregate network\n"
229757f1
DA
7164 "Name of route map\n"
7165 "BGP origin code\n"
7166 "Remote EGP\n"
7167 "Local IGP\n"
7168 "Unknown heritage\n")
718e3744 7169{
d62a17ae 7170 int idx = 0;
7171 argv_find(argv, argc, "X:X::X:X/M", &idx);
7172 char *prefix = argv[idx]->arg;
7173 return bgp_aggregate_unset(vty, prefix, AFI_IP6, SAFI_UNICAST);
718e3744 7174}
7175
718e3744 7176/* Redistribute route treatment. */
d62a17ae 7177void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
7178 const union g_addr *nexthop, ifindex_t ifindex,
7179 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
7180 uint8_t type, unsigned short instance,
7181 route_tag_t tag)
d62a17ae 7182{
4b7e6066 7183 struct bgp_path_info *new;
40381db7
DS
7184 struct bgp_path_info *bpi;
7185 struct bgp_path_info rmap_path;
9bcb3eef 7186 struct bgp_dest *bn;
d62a17ae 7187 struct attr attr;
7188 struct attr *new_attr;
7189 afi_t afi;
b68885f9 7190 route_map_result_t ret;
d62a17ae 7191 struct bgp_redist *red;
7192
7193 /* Make default attribute. */
7194 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
7195 /*
7196 * This must not be NULL to satisfy Coverity SA
7197 */
7198 assert(attr.aspath);
9de1f7ff 7199
a4d82a8a 7200 switch (nhtype) {
9de1f7ff
DS
7201 case NEXTHOP_TYPE_IFINDEX:
7202 break;
7203 case NEXTHOP_TYPE_IPV4:
7204 case NEXTHOP_TYPE_IPV4_IFINDEX:
7205 attr.nexthop = nexthop->ipv4;
7206 break;
7207 case NEXTHOP_TYPE_IPV6:
7208 case NEXTHOP_TYPE_IPV6_IFINDEX:
7209 attr.mp_nexthop_global = nexthop->ipv6;
7210 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
7211 break;
7212 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
7213 switch (p->family) {
7214 case AF_INET:
9de1f7ff 7215 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
7216 break;
7217 case AF_INET6:
9de1f7ff
DS
7218 memset(&attr.mp_nexthop_global, 0,
7219 sizeof(attr.mp_nexthop_global));
74489921 7220 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 7221 break;
74489921 7222 }
9de1f7ff 7223 break;
d62a17ae 7224 }
74489921 7225 attr.nh_ifindex = ifindex;
f04a80a5 7226
d62a17ae 7227 attr.med = metric;
7228 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
7229 attr.tag = tag;
718e3744 7230
d62a17ae 7231 afi = family2afi(p->family);
6aeb9e78 7232
d62a17ae 7233 red = bgp_redist_lookup(bgp, afi, type, instance);
7234 if (red) {
7235 struct attr attr_new;
718e3744 7236
d62a17ae 7237 /* Copy attribute for modification. */
6f4f49b2 7238 attr_new = attr;
718e3744 7239
d62a17ae 7240 if (red->redist_metric_flag)
7241 attr_new.med = red->redist_metric;
718e3744 7242
d62a17ae 7243 /* Apply route-map. */
7244 if (red->rmap.name) {
40381db7
DS
7245 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
7246 rmap_path.peer = bgp->peer_self;
7247 rmap_path.attr = &attr_new;
718e3744 7248
d62a17ae 7249 SET_FLAG(bgp->peer_self->rmap_type,
7250 PEER_RMAP_TYPE_REDISTRIBUTE);
7251
7252 ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
40381db7 7253 &rmap_path);
d62a17ae 7254
7255 bgp->peer_self->rmap_type = 0;
7256
7257 if (ret == RMAP_DENYMATCH) {
7258 /* Free uninterned attribute. */
7259 bgp_attr_flush(&attr_new);
7260
7261 /* Unintern original. */
7262 aspath_unintern(&attr.aspath);
7263 bgp_redistribute_delete(bgp, p, type, instance);
7264 return;
7265 }
7266 }
7267
892fedb6 7268 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
7f323236
DW
7269 bgp_attr_add_gshut_community(&attr_new);
7270
d62a17ae 7271 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7272 SAFI_UNICAST, p, NULL);
7273
7274 new_attr = bgp_attr_intern(&attr_new);
7275
9bcb3eef 7276 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
7277 if (bpi->peer == bgp->peer_self
7278 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 7279 break;
7280
40381db7 7281 if (bpi) {
d62a17ae 7282 /* Ensure the (source route) type is updated. */
40381db7
DS
7283 bpi->type = type;
7284 if (attrhash_cmp(bpi->attr, new_attr)
7285 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 7286 bgp_attr_unintern(&new_attr);
7287 aspath_unintern(&attr.aspath);
9bcb3eef 7288 bgp_dest_unlock_node(bn);
d62a17ae 7289 return;
7290 } else {
7291 /* The attribute is changed. */
40381db7 7292 bgp_path_info_set_flag(bn, bpi,
18ee8310 7293 BGP_PATH_ATTR_CHANGED);
d62a17ae 7294
7295 /* Rewrite BGP route information. */
40381db7
DS
7296 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
7297 bgp_path_info_restore(bn, bpi);
d62a17ae 7298 else
40381db7
DS
7299 bgp_aggregate_decrement(
7300 bgp, p, bpi, afi, SAFI_UNICAST);
7301 bgp_attr_unintern(&bpi->attr);
7302 bpi->attr = new_attr;
7303 bpi->uptime = bgp_clock();
d62a17ae 7304
7305 /* Process change. */
40381db7 7306 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 7307 SAFI_UNICAST);
7308 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 7309 bgp_dest_unlock_node(bn);
d62a17ae 7310 aspath_unintern(&attr.aspath);
ddb5b488
PZ
7311
7312 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7313 || (bgp->inst_type
7314 == BGP_INSTANCE_TYPE_DEFAULT)) {
7315
7316 vpn_leak_from_vrf_update(
40381db7 7317 bgp_get_default(), bgp, bpi);
ddb5b488 7318 }
d62a17ae 7319 return;
7320 }
7321 }
7322
7323 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
7324 bgp->peer_self, new_attr, bn);
1defdda8 7325 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 7326
7327 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 7328 bgp_path_info_add(bn, new);
9bcb3eef 7329 bgp_dest_unlock_node(bn);
d62a17ae 7330 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
7331
7332 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7333 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7334
7335 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
7336 }
d62a17ae 7337 }
7338
7339 /* Unintern original. */
7340 aspath_unintern(&attr.aspath);
718e3744 7341}
7342
d7c0a89a
QY
7343void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
7344 unsigned short instance)
718e3744 7345{
d62a17ae 7346 afi_t afi;
9bcb3eef 7347 struct bgp_dest *dest;
40381db7 7348 struct bgp_path_info *pi;
d62a17ae 7349 struct bgp_redist *red;
718e3744 7350
d62a17ae 7351 afi = family2afi(p->family);
718e3744 7352
d62a17ae 7353 red = bgp_redist_lookup(bgp, afi, type, instance);
7354 if (red) {
9bcb3eef
DS
7355 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7356 SAFI_UNICAST, p, NULL);
d62a17ae 7357
9bcb3eef 7358 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 7359 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 7360 break;
7361
40381db7 7362 if (pi) {
ddb5b488
PZ
7363 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7364 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7365
7366 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7367 bgp, pi);
ddb5b488 7368 }
40381db7 7369 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
7370 bgp_path_info_delete(dest, pi);
7371 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 7372 }
9bcb3eef 7373 bgp_dest_unlock_node(dest);
d62a17ae 7374 }
7375}
7376
7377/* Withdraw specified route type's route. */
7378void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 7379 unsigned short instance)
d62a17ae 7380{
9bcb3eef 7381 struct bgp_dest *dest;
40381db7 7382 struct bgp_path_info *pi;
d62a17ae 7383 struct bgp_table *table;
7384
7385 table = bgp->rib[afi][SAFI_UNICAST];
7386
9bcb3eef
DS
7387 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
7388 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7389 if (pi->peer == bgp->peer_self && pi->type == type
7390 && pi->instance == instance)
d62a17ae 7391 break;
7392
40381db7 7393 if (pi) {
ddb5b488
PZ
7394 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7395 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7396
7397 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7398 bgp, pi);
ddb5b488 7399 }
9bcb3eef 7400 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 7401 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
7402 bgp_path_info_delete(dest, pi);
7403 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 7404 }
718e3744 7405 }
718e3744 7406}
6b0655a2 7407
718e3744 7408/* Static function to display route. */
bd494ec5 7409static void route_vty_out_route(const struct prefix *p, struct vty *vty,
ae248832 7410 json_object *json, bool wide)
718e3744 7411{
be054588 7412 int len = 0;
d62a17ae 7413 char buf[BUFSIZ];
50e05855 7414 char buf2[BUFSIZ];
718e3744 7415
d62a17ae 7416 if (p->family == AF_INET) {
c6462ff4 7417 if (!json) {
89e5e9f0
PM
7418 len = vty_out(
7419 vty, "%s/%d",
7420 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
7421 p->prefixlen);
c6462ff4
MK
7422 } else {
7423 json_object_string_add(json, "prefix",
7424 inet_ntop(p->family,
7425 &p->u.prefix, buf,
7426 BUFSIZ));
7427 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 7428 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 7429 json_object_string_add(json, "network", buf2);
c6462ff4 7430 }
d62a17ae 7431 } else if (p->family == AF_ETHERNET) {
b03b8898
DS
7432 prefix2str(p, buf, PREFIX_STRLEN);
7433 len = vty_out(vty, "%s", buf);
7434 } else if (p->family == AF_EVPN) {
57f7feb6 7435 if (!json)
60466a63
QY
7436 len = vty_out(
7437 vty, "%s",
7438 bgp_evpn_route2str((struct prefix_evpn *)p, buf,
7439 BUFSIZ));
57f7feb6 7440 else
60466a63 7441 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
7442 } else if (p->family == AF_FLOWSPEC) {
7443 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
7444 json ?
7445 NLRI_STRING_FORMAT_JSON_SIMPLE :
7446 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 7447 } else {
c6462ff4 7448 if (!json)
60466a63
QY
7449 len = vty_out(
7450 vty, "%s/%d",
7451 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
7452 p->prefixlen);
50e05855
AD
7453 else {
7454 json_object_string_add(json, "prefix",
7455 inet_ntop(p->family,
7456 &p->u.prefix, buf,
7457 BUFSIZ));
7458 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
7459 prefix2str(p, buf2, PREFIX_STRLEN);
7460 json_object_string_add(json, "network", buf2);
7461 }
9c92b5f7 7462 }
d62a17ae 7463
9c92b5f7 7464 if (!json) {
ae248832 7465 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
7466 if (len < 1)
7467 vty_out(vty, "\n%*s", 20, " ");
7468 else
7469 vty_out(vty, "%*s", len, " ");
7470 }
718e3744 7471}
7472
d62a17ae 7473enum bgp_display_type {
7474 normal_list,
718e3744 7475};
7476
18ee8310 7477/* Print the short form route status for a bgp_path_info */
4b7e6066 7478static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 7479 struct bgp_path_info *path,
d62a17ae 7480 json_object *json_path)
718e3744 7481{
d62a17ae 7482 if (json_path) {
b05a1c8b 7483
d62a17ae 7484 /* Route status display. */
9b6d8fcf 7485 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7486 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 7487
9b6d8fcf 7488 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7489 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 7490
9b6d8fcf 7491 if (path->extra && path->extra->suppress)
d62a17ae 7492 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 7493
9b6d8fcf
DS
7494 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7495 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7496 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 7497
d62a17ae 7498 /* Selected */
9b6d8fcf 7499 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7500 json_object_boolean_true_add(json_path, "history");
b05a1c8b 7501
9b6d8fcf 7502 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7503 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 7504
9b6d8fcf 7505 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7506 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b 7507
9b6d8fcf 7508 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7509 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 7510
d62a17ae 7511 /* Internal route. */
9b6d8fcf
DS
7512 if ((path->peer->as)
7513 && (path->peer->as == path->peer->local_as))
d62a17ae 7514 json_object_string_add(json_path, "pathFrom",
7515 "internal");
7516 else
7517 json_object_string_add(json_path, "pathFrom",
7518 "external");
b05a1c8b 7519
d62a17ae 7520 return;
7521 }
b05a1c8b 7522
d62a17ae 7523 /* Route status display. */
9b6d8fcf 7524 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7525 vty_out(vty, "R");
9b6d8fcf 7526 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7527 vty_out(vty, "S");
9b6d8fcf 7528 else if (path->extra && path->extra->suppress)
d62a17ae 7529 vty_out(vty, "s");
9b6d8fcf
DS
7530 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7531 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7532 vty_out(vty, "*");
7533 else
7534 vty_out(vty, " ");
7535
7536 /* Selected */
9b6d8fcf 7537 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7538 vty_out(vty, "h");
9b6d8fcf 7539 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7540 vty_out(vty, "d");
9b6d8fcf 7541 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7542 vty_out(vty, ">");
9b6d8fcf 7543 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7544 vty_out(vty, "=");
7545 else
7546 vty_out(vty, " ");
718e3744 7547
d62a17ae 7548 /* Internal route. */
9b6d8fcf
DS
7549 if (path->peer && (path->peer->as)
7550 && (path->peer->as == path->peer->local_as))
d62a17ae 7551 vty_out(vty, "i");
7552 else
7553 vty_out(vty, " ");
b40d939b 7554}
7555
2ba93fd6
DA
7556static char *bgp_nexthop_hostname(struct peer *peer,
7557 struct bgp_nexthop_cache *bnc)
25b5da8d 7558{
892fedb6 7559 if (peer->hostname
aef999a2 7560 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
7561 return peer->hostname;
7562 return NULL;
7563}
7564
b40d939b 7565/* called from terminal list command */
bd494ec5 7566void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 7567 struct bgp_path_info *path, int display, safi_t safi,
ae248832 7568 json_object *json_paths, bool wide)
d62a17ae 7569{
aef999a2 7570 int len;
515c2602 7571 struct attr *attr = path->attr;
d62a17ae 7572 json_object *json_path = NULL;
7573 json_object *json_nexthops = NULL;
7574 json_object *json_nexthop_global = NULL;
7575 json_object *json_nexthop_ll = NULL;
6f214dd3 7576 json_object *json_ext_community = NULL;
9df8b37c 7577 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 7578 bool nexthop_self =
9b6d8fcf 7579 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 7580 bool nexthop_othervrf = false;
43089216 7581 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 7582 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
7583 char *nexthop_hostname =
7584 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 7585
7586 if (json_paths)
7587 json_path = json_object_new_object();
7588
7589 /* short status lead text */
9b6d8fcf 7590 route_vty_short_status_out(vty, path, json_path);
d62a17ae 7591
7592 if (!json_paths) {
7593 /* print prefix and mask */
7594 if (!display)
ae248832 7595 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 7596 else
ae248832 7597 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 7598 } else {
ae248832 7599 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 7600 }
47fc97cc 7601
9df8b37c
PZ
7602 /*
7603 * If vrf id of nexthop is different from that of prefix,
7604 * set up printable string to append
7605 */
9b6d8fcf 7606 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
7607 const char *self = "";
7608
7609 if (nexthop_self)
7610 self = "<";
7611
7612 nexthop_othervrf = true;
9b6d8fcf 7613 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 7614
9b6d8fcf 7615 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
7616 snprintf(vrf_id_str, sizeof(vrf_id_str),
7617 "@%s%s", VRFID_NONE_STR, self);
7618 else
7619 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 7620 path->extra->bgp_orig->vrf_id, self);
9df8b37c 7621
9b6d8fcf
DS
7622 if (path->extra->bgp_orig->inst_type
7623 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 7624
9b6d8fcf 7625 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
7626 } else {
7627 const char *self = "";
7628
7629 if (nexthop_self)
7630 self = "<";
7631
7632 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
7633 }
7634
445c2480
DS
7635 /*
7636 * For ENCAP and EVPN routes, nexthop address family is not
7637 * neccessarily the same as the prefix address family.
7638 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7639 * EVPN routes are also exchanged with a MP nexthop. Currently,
7640 * this
7641 * is only IPv4, the value will be present in either
7642 * attr->nexthop or
7643 * attr->mp_nexthop_global_in
7644 */
7645 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
7646 char buf[BUFSIZ];
7647 char nexthop[128];
7648 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
7649
7650 switch (af) {
7651 case AF_INET:
772270f3
QY
7652 snprintf(nexthop, sizeof(nexthop), "%s",
7653 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
7654 BUFSIZ));
445c2480
DS
7655 break;
7656 case AF_INET6:
772270f3
QY
7657 snprintf(nexthop, sizeof(nexthop), "%s",
7658 inet_ntop(af, &attr->mp_nexthop_global, buf,
7659 BUFSIZ));
445c2480
DS
7660 break;
7661 default:
772270f3 7662 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 7663 break;
d62a17ae 7664 }
d62a17ae 7665
445c2480
DS
7666 if (json_paths) {
7667 json_nexthop_global = json_object_new_object();
7668
515c2602
DA
7669 json_object_string_add(json_nexthop_global, "ip",
7670 nexthop);
7671
939a97f4 7672 if (path->peer->hostname)
515c2602
DA
7673 json_object_string_add(json_nexthop_global,
7674 "hostname",
939a97f4 7675 path->peer->hostname);
515c2602
DA
7676
7677 json_object_string_add(json_nexthop_global, "afi",
7678 (af == AF_INET) ? "ipv4"
7679 : "ipv6");
445c2480
DS
7680 json_object_boolean_true_add(json_nexthop_global,
7681 "used");
aef999a2
DA
7682 } else {
7683 if (nexthop_hostname)
7684 len = vty_out(vty, "%s(%s)%s", nexthop,
7685 nexthop_hostname, vrf_id_str);
7686 else
7687 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
7688
ae248832 7689 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
7690 if (len < 1)
7691 vty_out(vty, "\n%*s", 36, " ");
7692 else
7693 vty_out(vty, "%*s", len, " ");
7694 }
445c2480
DS
7695 } else if (safi == SAFI_EVPN) {
7696 if (json_paths) {
7697 json_nexthop_global = json_object_new_object();
7698
515c2602
DA
7699 json_object_string_add(json_nexthop_global, "ip",
7700 inet_ntoa(attr->nexthop));
7701
939a97f4 7702 if (path->peer->hostname)
515c2602
DA
7703 json_object_string_add(json_nexthop_global,
7704 "hostname",
939a97f4 7705 path->peer->hostname);
515c2602 7706
a4d82a8a
PZ
7707 json_object_string_add(json_nexthop_global, "afi",
7708 "ipv4");
445c2480
DS
7709 json_object_boolean_true_add(json_nexthop_global,
7710 "used");
aef999a2
DA
7711 } else {
7712 if (nexthop_hostname)
7713 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
7714 nexthop_hostname, vrf_id_str);
7715 else
7716 len = vty_out(vty, "%pI4%s", &attr->nexthop,
7717 vrf_id_str);
7718
ae248832 7719 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
7720 if (len < 1)
7721 vty_out(vty, "\n%*s", 36, " ");
7722 else
7723 vty_out(vty, "%*s", len, " ");
7724 }
d33fc23b 7725 } else if (safi == SAFI_FLOWSPEC) {
975a328e 7726 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
7727 if (json_paths) {
7728 json_nexthop_global = json_object_new_object();
515c2602 7729
026b914a
PG
7730 json_object_string_add(json_nexthop_global,
7731 "afi", "ipv4");
515c2602
DA
7732 json_object_string_add(
7733 json_nexthop_global, "ip",
7734 inet_ntoa(attr->nexthop));
7735
939a97f4 7736 if (path->peer->hostname)
515c2602
DA
7737 json_object_string_add(
7738 json_nexthop_global, "hostname",
939a97f4 7739 path->peer->hostname);
515c2602 7740
50e05855
AD
7741 json_object_boolean_true_add(
7742 json_nexthop_global,
026b914a
PG
7743 "used");
7744 } else {
aef999a2
DA
7745 if (nexthop_hostname)
7746 len = vty_out(vty, "%pI4(%s)%s",
7747 &attr->nexthop,
7748 nexthop_hostname,
7749 vrf_id_str);
7750 else
7751 len = vty_out(vty, "%pI4%s",
7752 &attr->nexthop,
7753 vrf_id_str);
7754
ae248832 7755 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
7756 if (len < 1)
7757 vty_out(vty, "\n%*s", 36, " ");
7758 else
7759 vty_out(vty, "%*s", len, " ");
026b914a
PG
7760 }
7761 }
d33fc23b 7762 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
7763 if (json_paths) {
7764 json_nexthop_global = json_object_new_object();
d62a17ae 7765
515c2602
DA
7766 json_object_string_add(json_nexthop_global, "ip",
7767 inet_ntoa(attr->nexthop));
7768
939a97f4 7769 if (path->peer->hostname)
515c2602
DA
7770 json_object_string_add(json_nexthop_global,
7771 "hostname",
939a97f4 7772 path->peer->hostname);
445c2480 7773
a4d82a8a
PZ
7774 json_object_string_add(json_nexthop_global, "afi",
7775 "ipv4");
445c2480
DS
7776 json_object_boolean_true_add(json_nexthop_global,
7777 "used");
7778 } else {
aef999a2
DA
7779 if (nexthop_hostname)
7780 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
7781 nexthop_hostname, vrf_id_str);
7782 else
7783 len = vty_out(vty, "%pI4%s", &attr->nexthop,
7784 vrf_id_str);
9df8b37c 7785
ae248832 7786 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
7787 if (len < 1)
7788 vty_out(vty, "\n%*s", 36, " ");
7789 else
7790 vty_out(vty, "%*s", len, " ");
d62a17ae 7791 }
445c2480 7792 }
b05a1c8b 7793
445c2480 7794 /* IPv6 Next Hop */
a4d82a8a 7795 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 7796 char buf[BUFSIZ];
d62a17ae 7797
445c2480
DS
7798 if (json_paths) {
7799 json_nexthop_global = json_object_new_object();
a4d82a8a 7800 json_object_string_add(
515c2602
DA
7801 json_nexthop_global, "ip",
7802 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
7803 buf, BUFSIZ));
7804
939a97f4 7805 if (path->peer->hostname)
515c2602
DA
7806 json_object_string_add(json_nexthop_global,
7807 "hostname",
939a97f4 7808 path->peer->hostname);
515c2602 7809
a4d82a8a
PZ
7810 json_object_string_add(json_nexthop_global, "afi",
7811 "ipv6");
7812 json_object_string_add(json_nexthop_global, "scope",
7813 "global");
445c2480
DS
7814
7815 /* We display both LL & GL if both have been
7816 * received */
0606039c
DA
7817 if ((attr->mp_nexthop_len
7818 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 7819 || (path->peer->conf_if)) {
a4d82a8a 7820 json_nexthop_ll = json_object_new_object();
d62a17ae 7821 json_object_string_add(
515c2602
DA
7822 json_nexthop_ll, "ip",
7823 inet_ntop(AF_INET6,
7824 &attr->mp_nexthop_local, buf,
7825 BUFSIZ));
7826
939a97f4 7827 if (path->peer->hostname)
515c2602
DA
7828 json_object_string_add(
7829 json_nexthop_ll, "hostname",
939a97f4 7830 path->peer->hostname);
515c2602 7831
a4d82a8a
PZ
7832 json_object_string_add(json_nexthop_ll, "afi",
7833 "ipv6");
7834 json_object_string_add(json_nexthop_ll, "scope",
445c2480 7835 "link-local");
d62a17ae 7836
a4d82a8a
PZ
7837 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
7838 &attr->mp_nexthop_local)
445c2480
DS
7839 != 0)
7840 && !attr->mp_nexthop_prefer_global)
d62a17ae 7841 json_object_boolean_true_add(
a4d82a8a 7842 json_nexthop_ll, "used");
445c2480
DS
7843 else
7844 json_object_boolean_true_add(
a4d82a8a 7845 json_nexthop_global, "used");
445c2480
DS
7846 } else
7847 json_object_boolean_true_add(
7848 json_nexthop_global, "used");
7849 } else {
7850 /* Display LL if LL/Global both in table unless
7851 * prefer-global is set */
0606039c
DA
7852 if (((attr->mp_nexthop_len
7853 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 7854 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
7855 || (path->peer->conf_if)) {
7856 if (path->peer->conf_if) {
a4d82a8a 7857 len = vty_out(vty, "%s",
9b6d8fcf 7858 path->peer->conf_if);
ae248832
MK
7859 /* len of IPv6 addr + max len of def
7860 * ifname */
7861 len = wide ? (41 - len) : (16 - len);
445c2480
DS
7862
7863 if (len < 1)
a4d82a8a 7864 vty_out(vty, "\n%*s", 36, " ");
445c2480 7865 else
a4d82a8a 7866 vty_out(vty, "%*s", len, " ");
d62a17ae 7867 } else {
aef999a2
DA
7868 if (nexthop_hostname)
7869 len = vty_out(
7870 vty, "%pI6(%s)%s",
7871 &attr->mp_nexthop_local,
7872 nexthop_hostname,
7873 vrf_id_str);
7874 else
7875 len = vty_out(
7876 vty, "%pI6%s",
7877 &attr->mp_nexthop_local,
7878 vrf_id_str);
7879
ae248832 7880 len = wide ? (41 - len) : (16 - len);
d62a17ae 7881
7882 if (len < 1)
a4d82a8a 7883 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 7884 else
a4d82a8a 7885 vty_out(vty, "%*s", len, " ");
d62a17ae 7886 }
445c2480 7887 } else {
aef999a2
DA
7888 if (nexthop_hostname)
7889 len = vty_out(vty, "%pI6(%s)%s",
7890 &attr->mp_nexthop_global,
7891 nexthop_hostname,
7892 vrf_id_str);
7893 else
7894 len = vty_out(vty, "%pI6%s",
7895 &attr->mp_nexthop_global,
7896 vrf_id_str);
7897
ae248832 7898 len = wide ? (41 - len) : (16 - len);
445c2480
DS
7899
7900 if (len < 1)
7901 vty_out(vty, "\n%*s", 36, " ");
7902 else
7903 vty_out(vty, "%*s", len, " ");
d62a17ae 7904 }
7905 }
445c2480 7906 }
718e3744 7907
445c2480
DS
7908 /* MED/Metric */
7909 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 7910 if (json_paths)
50e05855 7911 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
7912 else if (wide)
7913 vty_out(vty, "%7u", attr->med);
0fbac0b4 7914 else
445c2480 7915 vty_out(vty, "%10u", attr->med);
ae248832
MK
7916 else if (!json_paths) {
7917 if (wide)
7918 vty_out(vty, "%*s", 7, " ");
7919 else
7920 vty_out(vty, "%*s", 10, " ");
7921 }
d62a17ae 7922
445c2480
DS
7923 /* Local Pref */
7924 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 7925 if (json_paths)
50e05855 7926 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
7927 attr->local_pref);
7928 else
445c2480
DS
7929 vty_out(vty, "%7u", attr->local_pref);
7930 else if (!json_paths)
7931 vty_out(vty, " ");
d62a17ae 7932
445c2480
DS
7933 if (json_paths)
7934 json_object_int_add(json_path, "weight", attr->weight);
7935 else
7936 vty_out(vty, "%7u ", attr->weight);
47fc97cc 7937
445c2480
DS
7938 if (json_paths) {
7939 char buf[BUFSIZ];
a4d82a8a
PZ
7940 json_object_string_add(
7941 json_path, "peerId",
9b6d8fcf 7942 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 7943 }
b05a1c8b 7944
445c2480
DS
7945 /* Print aspath */
7946 if (attr->aspath) {
0fbac0b4 7947 if (json_paths)
50e05855 7948 json_object_string_add(json_path, "path",
0fbac0b4
DA
7949 attr->aspath->str);
7950 else
445c2480 7951 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 7952 }
f1aa5d8a 7953
445c2480
DS
7954 /* Print origin */
7955 if (json_paths)
a4d82a8a
PZ
7956 json_object_string_add(json_path, "origin",
7957 bgp_origin_long_str[attr->origin]);
445c2480
DS
7958 else
7959 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7960
9df8b37c 7961 if (json_paths) {
6f214dd3
CS
7962 if (safi == SAFI_EVPN &&
7963 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7964 json_ext_community = json_object_new_object();
7965 json_object_string_add(json_ext_community,
7966 "string",
7967 attr->ecommunity->str);
7968 json_object_object_add(json_path,
7969 "extendedCommunity",
7970 json_ext_community);
7971 }
7972
9df8b37c
PZ
7973 if (nexthop_self)
7974 json_object_boolean_true_add(json_path,
7975 "announceNexthopSelf");
7976 if (nexthop_othervrf) {
7977 json_object_string_add(json_path, "nhVrfName",
7978 nexthop_vrfname);
7979
7980 json_object_int_add(json_path, "nhVrfId",
7981 ((nexthop_vrfid == VRF_UNKNOWN)
7982 ? -1
7983 : (int)nexthop_vrfid));
7984 }
7985 }
7986
d62a17ae 7987 if (json_paths) {
7988 if (json_nexthop_global || json_nexthop_ll) {
7989 json_nexthops = json_object_new_array();
f1aa5d8a 7990
d62a17ae 7991 if (json_nexthop_global)
7992 json_object_array_add(json_nexthops,
7993 json_nexthop_global);
f1aa5d8a 7994
d62a17ae 7995 if (json_nexthop_ll)
7996 json_object_array_add(json_nexthops,
7997 json_nexthop_ll);
f1aa5d8a 7998
d62a17ae 7999 json_object_object_add(json_path, "nexthops",
8000 json_nexthops);
8001 }
8002
8003 json_object_array_add(json_paths, json_path);
8004 } else {
8005 vty_out(vty, "\n");
6f214dd3
CS
8006
8007 if (safi == SAFI_EVPN &&
8008 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8009 vty_out(vty, "%*s", 20, " ");
8010 vty_out(vty, "%s\n", attr->ecommunity->str);
8011 }
8012
49e5a4a0 8013#ifdef ENABLE_BGP_VNC
d62a17ae 8014 /* prints an additional line, indented, with VNC info, if
8015 * present */
8016 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 8017 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 8018#endif
d62a17ae 8019 }
8020}
718e3744 8021
8022/* called from terminal list command */
5f040085
DS
8023void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
8024 struct attr *attr, safi_t safi, bool use_json,
ae248832 8025 json_object *json_ar, bool wide)
d62a17ae 8026{
8027 json_object *json_status = NULL;
8028 json_object *json_net = NULL;
aef999a2 8029 int len;
d62a17ae 8030 char buff[BUFSIZ];
dc387b0f 8031
d62a17ae 8032 /* Route status display. */
8033 if (use_json) {
8034 json_status = json_object_new_object();
8035 json_net = json_object_new_object();
8036 } else {
8037 vty_out(vty, "*");
8038 vty_out(vty, ">");
8039 vty_out(vty, " ");
8040 }
718e3744 8041
d62a17ae 8042 /* print prefix and mask */
50e05855 8043 if (use_json) {
dc387b0f
LK
8044 if (safi == SAFI_EVPN)
8045 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
8046 else if (p->family == AF_INET || p->family == AF_INET6) {
8047 json_object_string_add(
8048 json_net, "addrPrefix",
8049 inet_ntop(p->family, &p->u.prefix, buff,
8050 BUFSIZ));
8051 json_object_int_add(json_net, "prefixLen",
8052 p->prefixlen);
8053 prefix2str(p, buff, PREFIX_STRLEN);
8054 json_object_string_add(json_net, "network", buff);
8055 }
50e05855 8056 } else
ae248832 8057 route_vty_out_route(p, vty, NULL, wide);
d62a17ae 8058
8059 /* Print attribute */
8060 if (attr) {
8061 if (use_json) {
8062 if (p->family == AF_INET
8063 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 8064 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 8065 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 8066 json_object_string_add(
8067 json_net, "nextHop",
8068 inet_ntoa(
8069 attr->mp_nexthop_global_in));
8070 else
8071 json_object_string_add(
8072 json_net, "nextHop",
8073 inet_ntoa(attr->nexthop));
8074 } else if (p->family == AF_INET6
8075 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8076 char buf[BUFSIZ];
8077
8078 json_object_string_add(
aa0a10fc 8079 json_net, "nextHopGlobal",
d62a17ae 8080 inet_ntop(AF_INET6,
8081 &attr->mp_nexthop_global, buf,
8082 BUFSIZ));
dc387b0f
LK
8083 } else if (p->family == AF_EVPN &&
8084 !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8085 json_object_string_add(json_net,
8086 "nextHop", inet_ntoa(
8087 attr->mp_nexthop_global_in));
d62a17ae 8088
8089 if (attr->flag
8090 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8091 json_object_int_add(json_net, "metric",
8092 attr->med);
8093
0fbac0b4 8094 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 8095 json_object_int_add(json_net, "locPrf",
0fbac0b4 8096 attr->local_pref);
d62a17ae 8097
8098 json_object_int_add(json_net, "weight", attr->weight);
8099
8100 /* Print aspath */
0fbac0b4 8101 if (attr->aspath)
50e05855 8102 json_object_string_add(json_net, "path",
0fbac0b4 8103 attr->aspath->str);
d62a17ae 8104
8105 /* Print origin */
8106 json_object_string_add(json_net, "bgpOriginCode",
8107 bgp_origin_str[attr->origin]);
8108 } else {
8109 if (p->family == AF_INET
8110 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8111 || safi == SAFI_EVPN
8112 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8113 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8114 || safi == SAFI_EVPN)
8115 vty_out(vty, "%-16s",
8116 inet_ntoa(
8117 attr->mp_nexthop_global_in));
ae248832
MK
8118 else if (wide)
8119 vty_out(vty, "%-41s",
8120 inet_ntoa(attr->nexthop));
d62a17ae 8121 else
8122 vty_out(vty, "%-16s",
8123 inet_ntoa(attr->nexthop));
8124 } else if (p->family == AF_INET6
8125 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 8126 char buf[BUFSIZ];
8127
8128 len = vty_out(
8129 vty, "%s",
8130 inet_ntop(AF_INET6,
8131 &attr->mp_nexthop_global, buf,
8132 BUFSIZ));
ae248832 8133 len = wide ? (41 - len) : (16 - len);
d62a17ae 8134 if (len < 1)
8135 vty_out(vty, "\n%*s", 36, " ");
8136 else
8137 vty_out(vty, "%*s", len, " ");
8138 }
8139 if (attr->flag
8140 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
8141 if (wide)
8142 vty_out(vty, "%7u", attr->med);
8143 else
8144 vty_out(vty, "%10u", attr->med);
8145 else if (wide)
8146 vty_out(vty, " ");
d62a17ae 8147 else
8148 vty_out(vty, " ");
718e3744 8149
d62a17ae 8150 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
8151 vty_out(vty, "%7u", attr->local_pref);
8152 else
8153 vty_out(vty, " ");
8154
8155 vty_out(vty, "%7u ", attr->weight);
8156
8157 /* Print aspath */
8158 if (attr->aspath)
8159 aspath_print_vty(vty, "%s", attr->aspath, " ");
8160
8161 /* Print origin */
8162 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8163 }
8164 }
8165 if (use_json) {
8166 json_object_boolean_true_add(json_status, "*");
8167 json_object_boolean_true_add(json_status, ">");
8168 json_object_object_add(json_net, "appliedStatusSymbols",
8169 json_status);
1608ff77 8170
dc387b0f
LK
8171 prefix2str(p, buff, PREFIX_STRLEN);
8172 json_object_object_add(json_ar, buff, json_net);
d62a17ae 8173 } else
8174 vty_out(vty, "\n");
8175}
8176
bd494ec5 8177void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 8178 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 8179 json_object *json)
8180{
8181 json_object *json_out = NULL;
8182 struct attr *attr;
8183 mpls_label_t label = MPLS_INVALID_LABEL;
8184
9b6d8fcf 8185 if (!path->extra)
d62a17ae 8186 return;
8187
8188 if (json)
8189 json_out = json_object_new_object();
8190
8191 /* short status lead text */
9b6d8fcf 8192 route_vty_short_status_out(vty, path, json_out);
d62a17ae 8193
8194 /* print prefix and mask */
8195 if (json == NULL) {
8196 if (!display)
ae248832 8197 route_vty_out_route(p, vty, NULL, false);
d62a17ae 8198 else
8199 vty_out(vty, "%*s", 17, " ");
8200 }
8201
8202 /* Print attribute */
9b6d8fcf 8203 attr = path->attr;
05864da7
DS
8204 if (((p->family == AF_INET)
8205 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8206 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8207 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8208 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8209 || safi == SAFI_EVPN) {
8210 if (json)
8211 json_object_string_add(
8212 json_out, "mpNexthopGlobalIn",
8213 inet_ntoa(attr->mp_nexthop_global_in));
8214 else
8215 vty_out(vty, "%-16s",
8216 inet_ntoa(attr->mp_nexthop_global_in));
8217 } else {
8218 if (json)
8219 json_object_string_add(
8220 json_out, "nexthop",
8221 inet_ntoa(attr->nexthop));
8222 else
8223 vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
8224 }
8225 } else if (((p->family == AF_INET6)
8226 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8227 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8228 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8229 char buf_a[512];
8230
8231 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
8232 if (json)
8233 json_object_string_add(
8234 json_out, "mpNexthopGlobalIn",
8235 inet_ntop(AF_INET6,
8236 &attr->mp_nexthop_global,
8237 buf_a, sizeof(buf_a)));
8238 else
8239 vty_out(vty, "%s",
8240 inet_ntop(AF_INET6,
8241 &attr->mp_nexthop_global,
8242 buf_a, sizeof(buf_a)));
8243 } else if (attr->mp_nexthop_len
8244 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
8245 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
8246 &attr->mp_nexthop_global,
8247 &attr->mp_nexthop_local);
8248 if (json)
8249 json_object_string_add(json_out,
8250 "mpNexthopGlobalLocal",
8251 buf_a);
8252 else
8253 vty_out(vty, "%s", buf_a);
d62a17ae 8254 }
8255 }
8256
9b6d8fcf 8257 label = decode_label(&path->extra->label[0]);
d62a17ae 8258
8259 if (bgp_is_valid_label(&label)) {
8260 if (json) {
8261 json_object_int_add(json_out, "notag", label);
8262 json_object_array_add(json, json_out);
8263 } else {
8264 vty_out(vty, "notag/%d", label);
8265 vty_out(vty, "\n");
8266 }
8267 }
8268}
718e3744 8269
bd494ec5 8270void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 8271 struct bgp_path_info *path, int display,
d62a17ae 8272 json_object *json_paths)
718e3744 8273{
d62a17ae 8274 struct attr *attr;
14f51eba 8275 char buf[BUFSIZ] = {0};
d62a17ae 8276 json_object *json_path = NULL;
14f51eba
LK
8277 json_object *json_nexthop = NULL;
8278 json_object *json_overlay = NULL;
856ca177 8279
9b6d8fcf 8280 if (!path->extra)
d62a17ae 8281 return;
718e3744 8282
14f51eba
LK
8283 if (json_paths) {
8284 json_path = json_object_new_object();
8285 json_overlay = json_object_new_object();
8286 json_nexthop = json_object_new_object();
8287 }
8288
d62a17ae 8289 /* short status lead text */
9b6d8fcf 8290 route_vty_short_status_out(vty, path, json_path);
856ca177 8291
d62a17ae 8292 /* print prefix and mask */
8293 if (!display)
ae248832 8294 route_vty_out_route(p, vty, json_path, false);
d62a17ae 8295 else
8296 vty_out(vty, "%*s", 17, " ");
8297
8298 /* Print attribute */
9b6d8fcf 8299 attr = path->attr;
05864da7
DS
8300 char buf1[BUFSIZ];
8301 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 8302
05864da7
DS
8303 switch (af) {
8304 case AF_INET:
8305 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
8306 if (!json_path) {
8307 vty_out(vty, "%-16s", buf);
8308 } else {
8309 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 8310
05864da7 8311 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 8312
05864da7
DS
8313 json_object_object_add(json_path, "nexthop",
8314 json_nexthop);
8315 }
8316 break;
8317 case AF_INET6:
8318 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
8319 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
8320 if (!json_path) {
8321 vty_out(vty, "%s(%s)", buf, buf1);
8322 } else {
8323 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 8324
05864da7
DS
8325 json_object_string_add(json_nexthop, "ipv6LinkLocal",
8326 buf1);
14f51eba 8327
05864da7 8328 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 8329
05864da7
DS
8330 json_object_object_add(json_path, "nexthop",
8331 json_nexthop);
8332 }
8333 break;
8334 default:
8335 if (!json_path) {
8336 vty_out(vty, "?");
8337 } else {
8338 json_object_string_add(json_nexthop, "Error",
8339 "Unsupported address-family");
d62a17ae 8340 }
05864da7 8341 }
988258b4 8342
05864da7 8343 char *str = esi2str(&(attr->evpn_overlay.eth_s_id));
988258b4 8344
05864da7
DS
8345 if (!json_path)
8346 vty_out(vty, "%s", str);
8347 else
8348 json_object_string_add(json_overlay, "esi", str);
25b5da8d 8349
05864da7 8350 XFREE(MTYPE_TMP, str);
988258b4 8351
05864da7
DS
8352 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
8353 inet_ntop(AF_INET, &(attr->evpn_overlay.gw_ip.ipv4), buf,
8354 BUFSIZ);
8355 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
8356 inet_ntop(AF_INET6, &(attr->evpn_overlay.gw_ip.ipv6), buf,
8357 BUFSIZ);
8358 }
14f51eba 8359
05864da7
DS
8360 if (!json_path)
8361 vty_out(vty, "/%s", buf);
8362 else
8363 json_object_string_add(json_overlay, "gw", buf);
8364
8365 if (attr->ecommunity) {
8366 char *mac = NULL;
8367 struct ecommunity_val *routermac = ecommunity_lookup(
8368 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
8369 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
8370
8371 if (routermac)
8372 mac = ecom_mac2str((char *)routermac->val);
8373 if (mac) {
8374 if (!json_path) {
c4efd0f4 8375 vty_out(vty, "/%s", mac);
05864da7
DS
8376 } else {
8377 json_object_string_add(json_overlay, "rmac",
8378 mac);
988258b4 8379 }
05864da7 8380 XFREE(MTYPE_TMP, mac);
988258b4 8381 }
05864da7 8382 }
718e3744 8383
05864da7
DS
8384 if (!json_path) {
8385 vty_out(vty, "\n");
8386 } else {
8387 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 8388
05864da7 8389 json_object_array_add(json_paths, json_path);
14f51eba 8390 }
d62a17ae 8391}
718e3744 8392
d62a17ae 8393/* dampening route */
5f040085
DS
8394static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
8395 struct bgp_path_info *path, int display,
8396 afi_t afi, safi_t safi, bool use_json,
8397 json_object *json)
d62a17ae 8398{
8399 struct attr *attr;
8400 int len;
8401 char timebuf[BGP_UPTIME_LEN];
8402
8403 /* short status lead text */
9b6d8fcf 8404 route_vty_short_status_out(vty, path, json);
d62a17ae 8405
8406 /* print prefix and mask */
8407 if (!use_json) {
8408 if (!display)
ae248832 8409 route_vty_out_route(p, vty, NULL, false);
d62a17ae 8410 else
8411 vty_out(vty, "%*s", 17, " ");
8412 }
8413
9b6d8fcf 8414 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 8415 len = 17 - len;
8416 if (len < 1) {
8417 if (!use_json)
8418 vty_out(vty, "\n%*s", 34, " ");
8419 } else {
8420 if (use_json)
8421 json_object_int_add(json, "peerHost", len);
8422 else
8423 vty_out(vty, "%*s", len, " ");
8424 }
8425
8426 if (use_json)
a935f597
DA
8427 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
8428 safi, use_json, json);
d62a17ae 8429 else
9b6d8fcf
DS
8430 vty_out(vty, "%s ",
8431 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8432 BGP_UPTIME_LEN, afi, safi,
8433 use_json, json));
d62a17ae 8434
8435 /* Print attribute */
9b6d8fcf 8436 attr = path->attr;
d62a17ae 8437
05864da7
DS
8438 /* Print aspath */
8439 if (attr->aspath) {
d62a17ae 8440 if (use_json)
05864da7
DS
8441 json_object_string_add(json, "asPath",
8442 attr->aspath->str);
d62a17ae 8443 else
05864da7 8444 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8445 }
05864da7
DS
8446
8447 /* Print origin */
8448 if (use_json)
8449 json_object_string_add(json, "origin",
8450 bgp_origin_str[attr->origin]);
8451 else
8452 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8453
d62a17ae 8454 if (!use_json)
8455 vty_out(vty, "\n");
8456}
718e3744 8457
d62a17ae 8458/* flap route */
5f040085
DS
8459static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
8460 struct bgp_path_info *path, int display,
8461 afi_t afi, safi_t safi, bool use_json,
8462 json_object *json)
784d3a42 8463{
d62a17ae 8464 struct attr *attr;
8465 struct bgp_damp_info *bdi;
8466 char timebuf[BGP_UPTIME_LEN];
8467 int len;
784d3a42 8468
9b6d8fcf 8469 if (!path->extra)
d62a17ae 8470 return;
784d3a42 8471
9b6d8fcf 8472 bdi = path->extra->damp_info;
784d3a42 8473
d62a17ae 8474 /* short status lead text */
9b6d8fcf 8475 route_vty_short_status_out(vty, path, json);
784d3a42 8476
d62a17ae 8477 /* print prefix and mask */
8478 if (!use_json) {
8479 if (!display)
ae248832 8480 route_vty_out_route(p, vty, NULL, false);
d62a17ae 8481 else
8482 vty_out(vty, "%*s", 17, " ");
8483 }
784d3a42 8484
9b6d8fcf 8485 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 8486 len = 16 - len;
8487 if (len < 1) {
8488 if (!use_json)
8489 vty_out(vty, "\n%*s", 33, " ");
8490 } else {
8491 if (use_json)
8492 json_object_int_add(json, "peerHost", len);
8493 else
8494 vty_out(vty, "%*s", len, " ");
8495 }
784d3a42 8496
d62a17ae 8497 len = vty_out(vty, "%d", bdi->flap);
8498 len = 5 - len;
8499 if (len < 1) {
8500 if (!use_json)
8501 vty_out(vty, " ");
8502 } else {
8503 if (use_json)
8504 json_object_int_add(json, "bdiFlap", len);
8505 else
8506 vty_out(vty, "%*s", len, " ");
8507 }
8508
8509 if (use_json)
8510 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
8511 json);
8512 else
996c9314
LB
8513 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
8514 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 8515
9b6d8fcf
DS
8516 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
8517 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 8518 if (use_json)
9b6d8fcf 8519 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8520 BGP_UPTIME_LEN, afi, safi,
8521 use_json, json);
d62a17ae 8522 else
8523 vty_out(vty, "%s ",
9b6d8fcf 8524 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8525 BGP_UPTIME_LEN, afi,
8526 safi, use_json, json));
d62a17ae 8527 } else {
8528 if (!use_json)
8529 vty_out(vty, "%*s ", 8, " ");
8530 }
8531
8532 /* Print attribute */
9b6d8fcf 8533 attr = path->attr;
d62a17ae 8534
05864da7
DS
8535 /* Print aspath */
8536 if (attr->aspath) {
d62a17ae 8537 if (use_json)
05864da7
DS
8538 json_object_string_add(json, "asPath",
8539 attr->aspath->str);
d62a17ae 8540 else
05864da7 8541 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8542 }
05864da7
DS
8543
8544 /* Print origin */
8545 if (use_json)
8546 json_object_string_add(json, "origin",
8547 bgp_origin_str[attr->origin]);
8548 else
8549 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8550
d62a17ae 8551 if (!use_json)
8552 vty_out(vty, "\n");
8553}
8554
8555static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
8556 int *first, const char *header,
8557 json_object *json_adv_to)
8558{
8559 char buf1[INET6_ADDRSTRLEN];
8560 json_object *json_peer = NULL;
8561
8562 if (json_adv_to) {
8563 /* 'advertised-to' is a dictionary of peers we have advertised
8564 * this
8565 * prefix too. The key is the peer's IP or swpX, the value is
8566 * the
8567 * hostname if we know it and "" if not.
8568 */
8569 json_peer = json_object_new_object();
8570
8571 if (peer->hostname)
8572 json_object_string_add(json_peer, "hostname",
8573 peer->hostname);
8574
8575 if (peer->conf_if)
8576 json_object_object_add(json_adv_to, peer->conf_if,
8577 json_peer);
8578 else
8579 json_object_object_add(
8580 json_adv_to,
8581 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
8582 json_peer);
8583 } else {
8584 if (*first) {
8585 vty_out(vty, "%s", header);
8586 *first = 0;
8587 }
8588
8589 if (peer->hostname
892fedb6 8590 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 8591 if (peer->conf_if)
8592 vty_out(vty, " %s(%s)", peer->hostname,
8593 peer->conf_if);
8594 else
8595 vty_out(vty, " %s(%s)", peer->hostname,
8596 sockunion2str(&peer->su, buf1,
8597 SU_ADDRSTRLEN));
8598 } else {
8599 if (peer->conf_if)
8600 vty_out(vty, " %s", peer->conf_if);
8601 else
8602 vty_out(vty, " %s",
8603 sockunion2str(&peer->su, buf1,
8604 SU_ADDRSTRLEN));
8605 }
8606 }
784d3a42
PG
8607}
8608
dcc68b5e
MS
8609static void route_vty_out_tx_ids(struct vty *vty,
8610 struct bgp_addpath_info_data *d)
8611{
8612 int i;
8613
8614 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
8615 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
8616 d->addpath_tx_id[i],
8617 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
8618 }
8619}
8620
0dc8ee70
DS
8621static const char *bgp_path_selection_reason2str(
8622 enum bgp_path_selection_reason reason)
8623{
8624 switch (reason) {
8625 case bgp_path_selection_none:
8626 return "Nothing to Select";
0dc8ee70
DS
8627 case bgp_path_selection_first:
8628 return "First path received";
0dc8ee70
DS
8629 case bgp_path_selection_evpn_sticky_mac:
8630 return "EVPN Sticky Mac";
0dc8ee70
DS
8631 case bgp_path_selection_evpn_seq:
8632 return "EVPN sequence number";
0dc8ee70
DS
8633 case bgp_path_selection_evpn_lower_ip:
8634 return "EVPN lower IP";
0dc8ee70
DS
8635 case bgp_path_selection_weight:
8636 return "Weight";
0dc8ee70
DS
8637 case bgp_path_selection_local_pref:
8638 return "Local Pref";
0dc8ee70
DS
8639 case bgp_path_selection_local_route:
8640 return "Local Route";
0dc8ee70
DS
8641 case bgp_path_selection_confed_as_path:
8642 return "Confederation based AS Path";
0dc8ee70
DS
8643 case bgp_path_selection_as_path:
8644 return "AS Path";
0dc8ee70
DS
8645 case bgp_path_selection_origin:
8646 return "Origin";
0dc8ee70
DS
8647 case bgp_path_selection_med:
8648 return "MED";
0dc8ee70
DS
8649 case bgp_path_selection_peer:
8650 return "Peer Type";
0dc8ee70
DS
8651 case bgp_path_selection_confed:
8652 return "Confed Peer Type";
0dc8ee70
DS
8653 case bgp_path_selection_igp_metric:
8654 return "IGP Metric";
0dc8ee70
DS
8655 case bgp_path_selection_older:
8656 return "Older Path";
0dc8ee70
DS
8657 case bgp_path_selection_router_id:
8658 return "Router ID";
0dc8ee70
DS
8659 case bgp_path_selection_cluster_length:
8660 return "Cluser length";
0dc8ee70
DS
8661 case bgp_path_selection_stale:
8662 return "Path Staleness";
0dc8ee70
DS
8663 case bgp_path_selection_local_configured:
8664 return "Locally configured route";
0dc8ee70
DS
8665 case bgp_path_selection_neighbor_ip:
8666 return "Neighbor IP";
0dc8ee70
DS
8667 case bgp_path_selection_default:
8668 return "Nothing left to compare";
0dc8ee70 8669 }
a74879b2 8670 return "Invalid (internal error)";
0dc8ee70
DS
8671}
8672
9bcb3eef
DS
8673void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
8674 struct bgp_path_info *path, afi_t afi, safi_t safi,
8675 json_object *json_paths)
d62a17ae 8676{
8677 char buf[INET6_ADDRSTRLEN];
8678 char buf1[BUFSIZ];
d62a17ae 8679 char buf2[EVPN_ROUTE_STRLEN];
515c2602 8680 struct attr *attr = path->attr;
d62a17ae 8681 int sockunion_vty_out(struct vty *, union sockunion *);
8682 time_t tbuf;
8683 json_object *json_bestpath = NULL;
8684 json_object *json_cluster_list = NULL;
8685 json_object *json_cluster_list_list = NULL;
8686 json_object *json_ext_community = NULL;
8687 json_object *json_last_update = NULL;
7fd077aa 8688 json_object *json_pmsi = NULL;
d62a17ae 8689 json_object *json_nexthop_global = NULL;
8690 json_object *json_nexthop_ll = NULL;
8691 json_object *json_nexthops = NULL;
8692 json_object *json_path = NULL;
8693 json_object *json_peer = NULL;
8694 json_object *json_string = NULL;
8695 json_object *json_adv_to = NULL;
8696 int first = 0;
8697 struct listnode *node, *nnode;
8698 struct peer *peer;
8699 int addpath_capable;
8700 int has_adj;
8701 unsigned int first_as;
1defdda8 8702 bool nexthop_self =
9b6d8fcf 8703 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 8704 int i;
2ba93fd6
DA
8705 char *nexthop_hostname =
8706 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 8707
8708 if (json_paths) {
8709 json_path = json_object_new_object();
8710 json_peer = json_object_new_object();
8711 json_nexthop_global = json_object_new_object();
8712 }
8713
44c69747 8714 if (path->extra) {
b57ba6d2 8715 char tag_buf[30];
d62a17ae 8716
d7325ee7 8717 buf2[0] = '\0';
d62a17ae 8718 tag_buf[0] = '\0';
9b6d8fcf
DS
8719 if (path->extra && path->extra->num_labels) {
8720 bgp_evpn_label2str(path->extra->label,
8721 path->extra->num_labels, tag_buf,
a4d82a8a 8722 sizeof(tag_buf));
d62a17ae 8723 }
d7325ee7 8724 if (safi == SAFI_EVPN) {
44c69747 8725 if (!json_paths) {
b54892e0
DS
8726 bgp_evpn_route2str(
8727 (struct prefix_evpn *)
9bcb3eef 8728 bgp_dest_get_prefix(bn),
b54892e0 8729 buf2, sizeof(buf2));
44c69747
LK
8730 vty_out(vty, " Route %s", buf2);
8731 if (tag_buf[0] != '\0')
8732 vty_out(vty, " VNI %s", tag_buf);
8733 vty_out(vty, "\n");
8734 } else {
8735 if (tag_buf[0])
8736 json_object_string_add(json_path, "VNI",
8737 tag_buf);
8738 }
d7325ee7
DD
8739 }
8740
44c69747 8741 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 8742 struct bgp_path_info *parent_ri;
9bcb3eef 8743 struct bgp_dest *dest, *pdest;
d62a17ae 8744
9b6d8fcf 8745 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
8746 dest = parent_ri->net;
8747 if (dest && dest->pdest) {
8748 pdest = dest->pdest;
8749 prefix_rd2str(
8750 (struct prefix_rd *)bgp_dest_get_prefix(
8751 pdest),
8752 buf1, sizeof(buf1));
d7325ee7 8753 if (is_pi_family_evpn(parent_ri)) {
b54892e0
DS
8754 bgp_evpn_route2str(
8755 (struct prefix_evpn *)
9bcb3eef
DS
8756 bgp_dest_get_prefix(
8757 dest),
b54892e0 8758 buf2, sizeof(buf2));
d7325ee7
DD
8759 vty_out(vty, " Imported from %s:%s, VNI %s\n", buf1, buf2, tag_buf);
8760 } else
8761 vty_out(vty, " Imported from %s:%s\n", buf1, buf2);
d62a17ae 8762 }
8763 }
8764 }
d62a17ae 8765
05864da7
DS
8766 /* Line1 display AS-path, Aggregator */
8767 if (attr->aspath) {
8768 if (json_paths) {
8769 if (!attr->aspath->json)
8770 aspath_str_update(attr->aspath, true);
8771 json_object_lock(attr->aspath->json);
8772 json_object_object_add(json_path, "aspath",
8773 attr->aspath->json);
8774 } else {
8775 if (attr->aspath->segments)
8776 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 8777 else
05864da7 8778 vty_out(vty, " Local");
d62a17ae 8779 }
05864da7 8780 }
d62a17ae 8781
05864da7
DS
8782 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
8783 if (json_paths)
8784 json_object_boolean_true_add(json_path, "removed");
8785 else
8786 vty_out(vty, ", (removed)");
8787 }
d62a17ae 8788
05864da7
DS
8789 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
8790 if (json_paths)
8791 json_object_boolean_true_add(json_path, "stale");
8792 else
8793 vty_out(vty, ", (stale)");
8794 }
d62a17ae 8795
05864da7
DS
8796 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
8797 if (json_paths) {
8798 json_object_int_add(json_path, "aggregatorAs",
8799 attr->aggregator_as);
8800 json_object_string_add(
8801 json_path, "aggregatorId",
8802 inet_ntoa(attr->aggregator_addr));
87c82131
DA
8803 if (attr->aggregator_as == BGP_AS_ZERO)
8804 json_object_boolean_true_add(
8805 json_path, "aggregatorAsMalformed");
8806 else
8807 json_object_boolean_false_add(
8808 json_path, "aggregatorAsMalformed");
05864da7 8809 } else {
87c82131
DA
8810 if (attr->aggregator_as == BGP_AS_ZERO)
8811 vty_out(vty,
8812 ", (aggregated by %u(malformed) %s)",
8813 attr->aggregator_as,
8814 inet_ntoa(attr->aggregator_addr));
8815 else
8816 vty_out(vty, ", (aggregated by %u %s)",
8817 attr->aggregator_as,
8818 inet_ntoa(attr->aggregator_addr));
d62a17ae 8819 }
05864da7 8820 }
d62a17ae 8821
05864da7
DS
8822 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
8823 PEER_FLAG_REFLECTOR_CLIENT)) {
8824 if (json_paths)
8825 json_object_boolean_true_add(json_path,
8826 "rxedFromRrClient");
8827 else
8828 vty_out(vty, ", (Received from a RR-client)");
8829 }
d62a17ae 8830
05864da7
DS
8831 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
8832 PEER_FLAG_RSERVER_CLIENT)) {
8833 if (json_paths)
8834 json_object_boolean_true_add(json_path,
8835 "rxedFromRsClient");
8836 else
8837 vty_out(vty, ", (Received from a RS-client)");
8838 }
d62a17ae 8839
05864da7
DS
8840 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
8841 if (json_paths)
8842 json_object_boolean_true_add(json_path,
8843 "dampeningHistoryEntry");
8844 else
8845 vty_out(vty, ", (history entry)");
8846 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
8847 if (json_paths)
8848 json_object_boolean_true_add(json_path,
8849 "dampeningSuppressed");
8850 else
8851 vty_out(vty, ", (suppressed due to dampening)");
8852 }
d62a17ae 8853
05864da7
DS
8854 if (!json_paths)
8855 vty_out(vty, "\n");
d62a17ae 8856
05864da7
DS
8857 /* Line2 display Next-hop, Neighbor, Router-id */
8858 /* Display the nexthop */
9bcb3eef 8859 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
8860
8861 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
8862 || bn_p->family == AF_EVPN)
05864da7
DS
8863 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
8864 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8865 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8866 || safi == SAFI_EVPN) {
515c2602 8867 if (json_paths) {
d62a17ae 8868 json_object_string_add(
515c2602
DA
8869 json_nexthop_global, "ip",
8870 inet_ntoa(attr->mp_nexthop_global_in));
8871
939a97f4 8872 if (path->peer->hostname)
515c2602
DA
8873 json_object_string_add(
8874 json_nexthop_global, "hostname",
939a97f4 8875 path->peer->hostname);
aef999a2
DA
8876 } else {
8877 if (nexthop_hostname)
8878 vty_out(vty, " %pI4(%s)",
8879 &attr->mp_nexthop_global_in,
8880 nexthop_hostname);
8881 else
8882 vty_out(vty, " %pI4",
8883 &attr->mp_nexthop_global_in);
8884 }
d62a17ae 8885 } else {
515c2602 8886 if (json_paths) {
05864da7 8887 json_object_string_add(
515c2602
DA
8888 json_nexthop_global, "ip",
8889 inet_ntoa(attr->nexthop));
8890
939a97f4 8891 if (path->peer->hostname)
515c2602
DA
8892 json_object_string_add(
8893 json_nexthop_global, "hostname",
939a97f4 8894 path->peer->hostname);
aef999a2
DA
8895 } else {
8896 if (nexthop_hostname)
8897 vty_out(vty, " %pI4(%s)",
8898 &attr->nexthop,
8899 nexthop_hostname);
8900 else
8901 vty_out(vty, " %pI4",
8902 &attr->nexthop);
8903 }
d62a17ae 8904 }
8905
05864da7
DS
8906 if (json_paths)
8907 json_object_string_add(json_nexthop_global, "afi",
8908 "ipv4");
8909 } else {
8910 if (json_paths) {
8911 json_object_string_add(
515c2602
DA
8912 json_nexthop_global, "ip",
8913 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8914 buf, INET6_ADDRSTRLEN));
8915
939a97f4 8916 if (path->peer->hostname)
515c2602
DA
8917 json_object_string_add(json_nexthop_global,
8918 "hostname",
939a97f4 8919 path->peer->hostname);
515c2602 8920
05864da7
DS
8921 json_object_string_add(json_nexthop_global, "afi",
8922 "ipv6");
8923 json_object_string_add(json_nexthop_global, "scope",
8924 "global");
8925 } else {
aef999a2
DA
8926 if (nexthop_hostname)
8927 vty_out(vty, " %pI6(%s)",
8928 &attr->mp_nexthop_global,
8929 nexthop_hostname);
8930 else
8931 vty_out(vty, " %pI6",
8932 &attr->mp_nexthop_global);
d62a17ae 8933 }
05864da7 8934 }
d62a17ae 8935
05864da7
DS
8936 /* Display the IGP cost or 'inaccessible' */
8937 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
8938 if (json_paths)
8939 json_object_boolean_false_add(json_nexthop_global,
8940 "accessible");
8941 else
8942 vty_out(vty, " (inaccessible)");
8943 } else {
8944 if (path->extra && path->extra->igpmetric) {
d62a17ae 8945 if (json_paths)
05864da7
DS
8946 json_object_int_add(json_nexthop_global,
8947 "metric",
8948 path->extra->igpmetric);
d62a17ae 8949 else
05864da7
DS
8950 vty_out(vty, " (metric %u)",
8951 path->extra->igpmetric);
d62a17ae 8952 }
8953
05864da7 8954 /* IGP cost is 0, display this only for json */
d62a17ae 8955 else {
d62a17ae 8956 if (json_paths)
05864da7
DS
8957 json_object_int_add(json_nexthop_global,
8958 "metric", 0);
d62a17ae 8959 }
d62a17ae 8960
05864da7
DS
8961 if (json_paths)
8962 json_object_boolean_true_add(json_nexthop_global,
8963 "accessible");
8964 }
d62a17ae 8965
05864da7
DS
8966 /* Display peer "from" output */
8967 /* This path was originated locally */
8968 if (path->peer == bgp->peer_self) {
d62a17ae 8969
05864da7 8970 if (safi == SAFI_EVPN
b54892e0 8971 || (bn_p->family == AF_INET
05864da7 8972 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 8973 if (json_paths)
05864da7
DS
8974 json_object_string_add(json_peer, "peerId",
8975 "0.0.0.0");
d62a17ae 8976 else
05864da7
DS
8977 vty_out(vty, " from 0.0.0.0 ");
8978 } else {
d62a17ae 8979 if (json_paths)
05864da7
DS
8980 json_object_string_add(json_peer, "peerId",
8981 "::");
d62a17ae 8982 else
05864da7 8983 vty_out(vty, " from :: ");
d62a17ae 8984 }
d62a17ae 8985
05864da7
DS
8986 if (json_paths)
8987 json_object_string_add(json_peer, "routerId",
8988 inet_ntoa(bgp->router_id));
8989 else
8990 vty_out(vty, "(%s)", inet_ntoa(bgp->router_id));
8991 }
d62a17ae 8992
05864da7
DS
8993 /* We RXed this path from one of our peers */
8994 else {
8995
8996 if (json_paths) {
8997 json_object_string_add(json_peer, "peerId",
8998 sockunion2str(&path->peer->su,
8999 buf,
9000 SU_ADDRSTRLEN));
9001 json_object_string_add(json_peer, "routerId",
9002 inet_ntop(AF_INET,
9003 &path->peer->remote_id,
9004 buf1, sizeof(buf1)));
9005
9006 if (path->peer->hostname)
9007 json_object_string_add(json_peer, "hostname",
9008 path->peer->hostname);
9009
9010 if (path->peer->domainname)
9011 json_object_string_add(json_peer, "domainname",
9012 path->peer->domainname);
9013
9014 if (path->peer->conf_if)
9015 json_object_string_add(json_peer, "interface",
9016 path->peer->conf_if);
9017 } else {
9018 if (path->peer->conf_if) {
9019 if (path->peer->hostname
892fedb6
DA
9020 && CHECK_FLAG(path->peer->bgp->flags,
9021 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9022 vty_out(vty, " from %s(%s)",
9023 path->peer->hostname,
9024 path->peer->conf_if);
d62a17ae 9025 else
05864da7 9026 vty_out(vty, " from %s",
9b6d8fcf 9027 path->peer->conf_if);
d62a17ae 9028 } else {
05864da7 9029 if (path->peer->hostname
892fedb6
DA
9030 && CHECK_FLAG(path->peer->bgp->flags,
9031 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9032 vty_out(vty, " from %s(%s)",
9033 path->peer->hostname,
9034 path->peer->host);
d62a17ae 9035 else
05864da7
DS
9036 vty_out(vty, " from %s",
9037 sockunion2str(&path->peer->su,
9038 buf,
9039 SU_ADDRSTRLEN));
d62a17ae 9040 }
d62a17ae 9041
05864da7
DS
9042 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
9043 vty_out(vty, " (%s)",
9044 inet_ntoa(attr->originator_id));
9045 else
9046 vty_out(vty, " (%s)",
9047 inet_ntop(AF_INET,
9048 &path->peer->remote_id, buf1,
9049 sizeof(buf1)));
d62a17ae 9050 }
05864da7 9051 }
9df8b37c 9052
05864da7
DS
9053 /*
9054 * Note when vrfid of nexthop is different from that of prefix
9055 */
9056 if (path->extra && path->extra->bgp_orig) {
9057 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9058
05864da7
DS
9059 if (json_paths) {
9060 const char *vn;
9df8b37c 9061
05864da7
DS
9062 if (path->extra->bgp_orig->inst_type
9063 == BGP_INSTANCE_TYPE_DEFAULT)
9064 vn = VRF_DEFAULT_NAME;
9065 else
9066 vn = path->extra->bgp_orig->name;
9df8b37c 9067
05864da7 9068 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 9069
05864da7
DS
9070 if (nexthop_vrfid == VRF_UNKNOWN) {
9071 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 9072 } else {
05864da7
DS
9073 json_object_int_add(json_path, "nhVrfId",
9074 (int)nexthop_vrfid);
9df8b37c 9075 }
05864da7
DS
9076 } else {
9077 if (nexthop_vrfid == VRF_UNKNOWN)
9078 vty_out(vty, " vrf ?");
137147c6
DS
9079 else {
9080 struct vrf *vrf;
9081
9082 vrf = vrf_lookup_by_id(nexthop_vrfid);
9083 vty_out(vty, " vrf %s(%u)",
9084 VRF_LOGNAME(vrf), nexthop_vrfid);
9085 }
9df8b37c 9086 }
05864da7 9087 }
9df8b37c 9088
05864da7
DS
9089 if (nexthop_self) {
9090 if (json_paths) {
9091 json_object_boolean_true_add(json_path,
9092 "announceNexthopSelf");
9093 } else {
9094 vty_out(vty, " announce-nh-self");
9df8b37c 9095 }
05864da7 9096 }
9df8b37c 9097
05864da7
DS
9098 if (!json_paths)
9099 vty_out(vty, "\n");
d62a17ae 9100
05864da7
DS
9101 /* display the link-local nexthop */
9102 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9103 if (json_paths) {
9104 json_nexthop_ll = json_object_new_object();
9105 json_object_string_add(
515c2602
DA
9106 json_nexthop_ll, "ip",
9107 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9108 buf, INET6_ADDRSTRLEN));
9109
939a97f4 9110 if (path->peer->hostname)
515c2602
DA
9111 json_object_string_add(json_nexthop_ll,
9112 "hostname",
939a97f4 9113 path->peer->hostname);
515c2602 9114
05864da7
DS
9115 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
9116 json_object_string_add(json_nexthop_ll, "scope",
9117 "link-local");
d62a17ae 9118
05864da7
DS
9119 json_object_boolean_true_add(json_nexthop_ll,
9120 "accessible");
d62a17ae 9121
05864da7 9122 if (!attr->mp_nexthop_prefer_global)
d62a17ae 9123 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
9124 "used");
9125 else
9126 json_object_boolean_true_add(
9127 json_nexthop_global, "used");
9128 } else {
9129 vty_out(vty, " (%s) %s\n",
9130 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9131 buf, INET6_ADDRSTRLEN),
9132 attr->mp_nexthop_prefer_global
9133 ? "(prefer-global)"
9134 : "(used)");
d62a17ae 9135 }
05864da7
DS
9136 }
9137 /* If we do not have a link-local nexthop then we must flag the
9138 global as "used" */
9139 else {
9140 if (json_paths)
9141 json_object_boolean_true_add(json_nexthop_global,
9142 "used");
9143 }
d62a17ae 9144
05864da7
DS
9145 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
9146 * Int/Ext/Local, Atomic, best */
9147 if (json_paths)
9148 json_object_string_add(json_path, "origin",
9149 bgp_origin_long_str[attr->origin]);
9150 else
9151 vty_out(vty, " Origin %s",
9152 bgp_origin_long_str[attr->origin]);
9df8b37c 9153
05864da7 9154 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 9155 if (json_paths)
05864da7 9156 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 9157 else
05864da7
DS
9158 vty_out(vty, ", metric %u", attr->med);
9159 }
9df8b37c 9160
05864da7
DS
9161 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
9162 if (json_paths)
0fbac0b4 9163 json_object_int_add(json_path, "locPrf",
05864da7
DS
9164 attr->local_pref);
9165 else
9166 vty_out(vty, ", localpref %u", attr->local_pref);
9167 }
9df8b37c 9168
05864da7
DS
9169 if (attr->weight != 0) {
9170 if (json_paths)
9171 json_object_int_add(json_path, "weight", attr->weight);
9172 else
9173 vty_out(vty, ", weight %u", attr->weight);
9174 }
9df8b37c 9175
05864da7
DS
9176 if (attr->tag != 0) {
9177 if (json_paths)
9178 json_object_int_add(json_path, "tag", attr->tag);
9179 else
9180 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
9181 }
9df8b37c 9182
05864da7
DS
9183 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9184 if (json_paths)
9185 json_object_boolean_false_add(json_path, "valid");
9186 else
9187 vty_out(vty, ", invalid");
9188 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9189 if (json_paths)
9190 json_object_boolean_true_add(json_path, "valid");
9191 else
9192 vty_out(vty, ", valid");
9193 }
9df8b37c 9194
05864da7
DS
9195 if (path->peer != bgp->peer_self) {
9196 if (path->peer->as == path->peer->local_as) {
9197 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
9198 if (json_paths)
9199 json_object_string_add(
9200 json_peer, "type",
9201 "confed-internal");
d62a17ae 9202 else
05864da7 9203 vty_out(vty, ", confed-internal");
d62a17ae 9204 } else {
05864da7
DS
9205 if (json_paths)
9206 json_object_string_add(
9207 json_peer, "type", "internal");
9208 else
9209 vty_out(vty, ", internal");
9df8b37c 9210 }
05864da7
DS
9211 } else {
9212 if (bgp_confederation_peers_check(bgp,
9213 path->peer->as)) {
9214 if (json_paths)
9215 json_object_string_add(
9216 json_peer, "type",
9217 "confed-external");
d62a17ae 9218 else
05864da7 9219 vty_out(vty, ", confed-external");
d62a17ae 9220 } else {
05864da7
DS
9221 if (json_paths)
9222 json_object_string_add(
9223 json_peer, "type", "external");
9224 else
9225 vty_out(vty, ", external");
d62a17ae 9226 }
9227 }
05864da7
DS
9228 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
9229 if (json_paths) {
9230 json_object_boolean_true_add(json_path, "aggregated");
9231 json_object_boolean_true_add(json_path, "local");
9232 } else {
9233 vty_out(vty, ", aggregated, local");
9234 }
9235 } else if (path->type != ZEBRA_ROUTE_BGP) {
9236 if (json_paths)
9237 json_object_boolean_true_add(json_path, "sourced");
9238 else
9239 vty_out(vty, ", sourced");
9240 } else {
9241 if (json_paths) {
9242 json_object_boolean_true_add(json_path, "sourced");
9243 json_object_boolean_true_add(json_path, "local");
9244 } else {
9245 vty_out(vty, ", sourced, local");
d62a17ae 9246 }
05864da7 9247 }
718e3744 9248
05864da7 9249 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 9250 if (json_paths)
05864da7
DS
9251 json_object_boolean_true_add(json_path,
9252 "atomicAggregate");
d62a17ae 9253 else
05864da7
DS
9254 vty_out(vty, ", atomic-aggregate");
9255 }
d62a17ae 9256
05864da7
DS
9257 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
9258 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
9259 && bgp_path_info_mpath_count(path))) {
9260 if (json_paths)
9261 json_object_boolean_true_add(json_path, "multipath");
9262 else
9263 vty_out(vty, ", multipath");
9264 }
50e05855 9265
05864da7
DS
9266 // Mark the bestpath(s)
9267 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
9268 first_as = aspath_get_first_as(attr->aspath);
718e3744 9269
05864da7
DS
9270 if (json_paths) {
9271 if (!json_bestpath)
9272 json_bestpath = json_object_new_object();
9273 json_object_int_add(json_bestpath, "bestpathFromAs",
9274 first_as);
9275 } else {
9276 if (first_as)
9277 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 9278 else
05864da7 9279 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 9280 }
05864da7 9281 }
718e3744 9282
05864da7
DS
9283 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
9284 if (json_paths) {
9285 if (!json_bestpath)
9286 json_bestpath = json_object_new_object();
9287 json_object_boolean_true_add(json_bestpath, "overall");
9288 json_object_string_add(
9289 json_bestpath, "selectionReason",
9290 bgp_path_selection_reason2str(bn->reason));
9291 } else {
9292 vty_out(vty, ", best");
9293 vty_out(vty, " (%s)",
9294 bgp_path_selection_reason2str(bn->reason));
d62a17ae 9295 }
05864da7 9296 }
718e3744 9297
05864da7
DS
9298 if (json_bestpath)
9299 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 9300
05864da7
DS
9301 if (!json_paths)
9302 vty_out(vty, "\n");
9303
9304 /* Line 4 display Community */
9305 if (attr->community) {
9306 if (json_paths) {
9307 if (!attr->community->json)
9308 community_str(attr->community, true);
9309 json_object_lock(attr->community->json);
9310 json_object_object_add(json_path, "community",
9311 attr->community->json);
9312 } else {
9313 vty_out(vty, " Community: %s\n",
9314 attr->community->str);
d62a17ae 9315 }
05864da7 9316 }
718e3744 9317
05864da7
DS
9318 /* Line 5 display Extended-community */
9319 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9320 if (json_paths) {
9321 json_ext_community = json_object_new_object();
9322 json_object_string_add(json_ext_community, "string",
9323 attr->ecommunity->str);
9324 json_object_object_add(json_path, "extendedCommunity",
9325 json_ext_community);
d62a17ae 9326 } else {
05864da7
DS
9327 vty_out(vty, " Extended Community: %s\n",
9328 attr->ecommunity->str);
d62a17ae 9329 }
05864da7 9330 }
718e3744 9331
05864da7
DS
9332 /* Line 6 display Large community */
9333 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
9334 if (json_paths) {
9335 if (!attr->lcommunity->json)
9336 lcommunity_str(attr->lcommunity, true);
9337 json_object_lock(attr->lcommunity->json);
9338 json_object_object_add(json_path, "largeCommunity",
9339 attr->lcommunity->json);
9340 } else {
9341 vty_out(vty, " Large Community: %s\n",
9342 attr->lcommunity->str);
d62a17ae 9343 }
05864da7 9344 }
718e3744 9345
05864da7
DS
9346 /* Line 7 display Originator, Cluster-id */
9347 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
9348 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
9349 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 9350 if (json_paths)
05864da7
DS
9351 json_object_string_add(
9352 json_path, "originatorId",
9353 inet_ntoa(attr->originator_id));
d62a17ae 9354 else
05864da7
DS
9355 vty_out(vty, " Originator: %s",
9356 inet_ntoa(attr->originator_id));
d62a17ae 9357 }
856ca177 9358
05864da7
DS
9359 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
9360 int i;
d62a17ae 9361
9362 if (json_paths) {
05864da7
DS
9363 json_cluster_list = json_object_new_object();
9364 json_cluster_list_list =
9365 json_object_new_array();
9366
9367 for (i = 0; i < attr->cluster->length / 4;
9368 i++) {
9369 json_string = json_object_new_string(
9370 inet_ntoa(attr->cluster
9371 ->list[i]));
9372 json_object_array_add(
9373 json_cluster_list_list,
9374 json_string);
9375 }
718e3744 9376
05864da7
DS
9377 /*
9378 * struct cluster_list does not have
9379 * "str" variable like aspath and community
9380 * do. Add this someday if someone asks
9381 * for it.
9382 * json_object_string_add(json_cluster_list,
9383 * "string", attr->cluster->str);
9384 */
9385 json_object_object_add(json_cluster_list,
9386 "list",
9387 json_cluster_list_list);
9388 json_object_object_add(json_path, "clusterList",
9389 json_cluster_list);
0dc8ee70 9390 } else {
05864da7
DS
9391 vty_out(vty, ", Cluster list: ");
9392
9393 for (i = 0; i < attr->cluster->length / 4;
9394 i++) {
9395 vty_out(vty, "%s ",
9396 inet_ntoa(attr->cluster
9397 ->list[i]));
9398 }
0dc8ee70 9399 }
d62a17ae 9400 }
718e3744 9401
d62a17ae 9402 if (!json_paths)
9403 vty_out(vty, "\n");
05864da7 9404 }
d62a17ae 9405
05864da7 9406 if (path->extra && path->extra->damp_info)
a935f597 9407 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 9408
05864da7
DS
9409 /* Remote Label */
9410 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
9411 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
9412 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 9413
05864da7
DS
9414 if (json_paths)
9415 json_object_int_add(json_path, "remoteLabel", label);
9416 else
9417 vty_out(vty, " Remote label: %d\n", label);
9418 }
d62a17ae 9419
e496b420
HS
9420 /* Remote SID */
9421 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
9422 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
9423 if (json_paths)
9424 json_object_string_add(json_path, "remoteSid", buf);
9425 else
9426 vty_out(vty, " Remote SID: %s\n", buf);
9427 }
9428
05864da7
DS
9429 /* Label Index */
9430 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
9431 if (json_paths)
9432 json_object_int_add(json_path, "labelIndex",
9433 attr->label_index);
9434 else
9435 vty_out(vty, " Label Index: %d\n",
9436 attr->label_index);
9437 }
d62a17ae 9438
05864da7
DS
9439 /* Line 8 display Addpath IDs */
9440 if (path->addpath_rx_id
9441 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
9442 if (json_paths) {
9443 json_object_int_add(json_path, "addpathRxId",
9444 path->addpath_rx_id);
d62a17ae 9445
05864da7
DS
9446 /* Keep backwards compatibility with the old API
9447 * by putting TX All's ID in the old field
9448 */
9449 json_object_int_add(
9450 json_path, "addpathTxId",
9451 path->tx_addpath
9452 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 9453
05864da7
DS
9454 /* ... but create a specific field for each
9455 * strategy
9456 */
9457 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9458 json_object_int_add(
9459 json_path,
9460 bgp_addpath_names(i)->id_json_name,
9461 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 9462 }
05864da7
DS
9463 } else {
9464 vty_out(vty, " AddPath ID: RX %u, ",
9465 path->addpath_rx_id);
d62a17ae 9466
05864da7 9467 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 9468 }
05864da7 9469 }
520d5d76 9470
05864da7
DS
9471 /* If we used addpath to TX a non-bestpath we need to display
9472 * "Advertised to" on a path-by-path basis
9473 */
9474 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9475 first = 1;
dcc68b5e 9476
05864da7
DS
9477 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9478 addpath_capable =
9479 bgp_addpath_encode_tx(peer, afi, safi);
9480 has_adj = bgp_adj_out_lookup(
9481 peer, path->net,
9482 bgp_addpath_id_for_peer(peer, afi, safi,
9483 &path->tx_addpath));
9484
9485 if ((addpath_capable && has_adj)
9486 || (!addpath_capable && has_adj
9487 && CHECK_FLAG(path->flags,
9488 BGP_PATH_SELECTED))) {
9489 if (json_path && !json_adv_to)
9490 json_adv_to = json_object_new_object();
dcc68b5e 9491
05864da7
DS
9492 route_vty_out_advertised_to(
9493 vty, peer, &first,
9494 " Advertised to:", json_adv_to);
d62a17ae 9495 }
9496 }
718e3744 9497
05864da7
DS
9498 if (json_path) {
9499 if (json_adv_to) {
9500 json_object_object_add(
9501 json_path, "advertisedTo", json_adv_to);
d62a17ae 9502 }
05864da7
DS
9503 } else {
9504 if (!first) {
9505 vty_out(vty, "\n");
d62a17ae 9506 }
9507 }
05864da7 9508 }
b05a1c8b 9509
05864da7
DS
9510 /* Line 9 display Uptime */
9511 tbuf = time(NULL) - (bgp_clock() - path->uptime);
9512 if (json_paths) {
9513 json_last_update = json_object_new_object();
9514 json_object_int_add(json_last_update, "epoch", tbuf);
9515 json_object_string_add(json_last_update, "string",
9516 ctime(&tbuf));
9517 json_object_object_add(json_path, "lastUpdate",
9518 json_last_update);
9519 } else
9520 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 9521
05864da7
DS
9522 /* Line 10 display PMSI tunnel attribute, if present */
9523 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
9524 const char *str =
9525 lookup_msg(bgp_pmsi_tnltype_str, attr->pmsi_tnl_type,
9526 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 9527
05864da7
DS
9528 if (json_paths) {
9529 json_pmsi = json_object_new_object();
9530 json_object_string_add(json_pmsi, "tunnelType", str);
9531 json_object_int_add(json_pmsi, "label",
9532 label2vni(&attr->label));
9533 json_object_object_add(json_path, "pmsi", json_pmsi);
9534 } else
9535 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
9536 str, label2vni(&attr->label));
d62a17ae 9537 }
f1aa5d8a 9538
d62a17ae 9539 /* We've constructed the json object for this path, add it to the json
9540 * array of paths
9541 */
9542 if (json_paths) {
9543 if (json_nexthop_global || json_nexthop_ll) {
9544 json_nexthops = json_object_new_array();
f1aa5d8a 9545
d62a17ae 9546 if (json_nexthop_global)
9547 json_object_array_add(json_nexthops,
9548 json_nexthop_global);
f1aa5d8a 9549
d62a17ae 9550 if (json_nexthop_ll)
9551 json_object_array_add(json_nexthops,
9552 json_nexthop_ll);
f1aa5d8a 9553
d62a17ae 9554 json_object_object_add(json_path, "nexthops",
9555 json_nexthops);
9556 }
9557
9558 json_object_object_add(json_path, "peer", json_peer);
9559 json_object_array_add(json_paths, json_path);
05864da7 9560 }
b366b518
BB
9561}
9562
96ade3ed 9563#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
9564#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9565#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 9566
d62a17ae 9567static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
9568 const char *prefix_list_str, afi_t afi,
9569 safi_t safi, enum bgp_show_type type);
9570static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
9571 const char *filter, afi_t afi, safi_t safi,
9572 enum bgp_show_type type);
9573static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
9574 const char *rmap_str, afi_t afi, safi_t safi,
9575 enum bgp_show_type type);
9576static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
9577 const char *com, int exact, afi_t afi,
9578 safi_t safi);
9579static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
9580 const char *prefix, afi_t afi, safi_t safi,
9581 enum bgp_show_type type);
a4d82a8a 9582static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
9583 afi_t afi, safi_t safi, enum bgp_show_type type,
9584 bool use_json);
7f323236
DW
9585static int bgp_show_community(struct vty *vty, struct bgp *bgp,
9586 const char *comstr, int exact, afi_t afi,
9f049418 9587 safi_t safi, bool use_json);
d62a17ae 9588
1ae44dfc
LB
9589
9590static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 9591 struct bgp_table *table, enum bgp_show_type type,
9f049418 9592 void *output_arg, bool use_json, char *rd,
a4d82a8a
PZ
9593 int is_last, unsigned long *output_cum,
9594 unsigned long *total_cum,
ae248832 9595 unsigned long *json_header_depth, bool wide)
d62a17ae 9596{
40381db7 9597 struct bgp_path_info *pi;
9bcb3eef 9598 struct bgp_dest *dest;
d62a17ae 9599 int header = 1;
9600 int display;
1ae44dfc
LB
9601 unsigned long output_count = 0;
9602 unsigned long total_count = 0;
d62a17ae 9603 struct prefix *p;
d62a17ae 9604 json_object *json_paths = NULL;
9605 int first = 1;
9606
1ae44dfc
LB
9607 if (output_cum && *output_cum != 0)
9608 header = 0;
9609
9386b588 9610 if (use_json && !*json_header_depth) {
d62a17ae 9611 vty_out(vty,
6cde4b45 9612 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
01eced22 9613 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 9614 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b
DS
9615 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
9616 ? VRF_DEFAULT_NAME
9617 : bgp->name,
01eced22
AD
9618 table->version, inet_ntoa(bgp->router_id),
9619 bgp->default_local_pref, bgp->as);
9386b588
PZ
9620 *json_header_depth = 2;
9621 if (rd) {
445c2480 9622 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
9623 ++*json_header_depth;
9624 }
d62a17ae 9625 }
718e3744 9626
445c2480
DS
9627 if (use_json && rd) {
9628 vty_out(vty, " \"%s\" : { ", rd);
9629 }
9630
d62a17ae 9631 /* Start processing of routes. */
9bcb3eef
DS
9632 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
9633 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 9634
9bcb3eef 9635 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 9636 if (pi == NULL)
98ce9a06 9637 continue;
d62a17ae 9638
98ce9a06 9639 display = 0;
98ce9a06
DS
9640 if (use_json)
9641 json_paths = json_object_new_array();
9642 else
9643 json_paths = NULL;
d62a17ae 9644
6f94b685 9645 for (; pi; pi = pi->next) {
98ce9a06
DS
9646 total_count++;
9647 if (type == bgp_show_type_flap_statistics
9648 || type == bgp_show_type_flap_neighbor
9649 || type == bgp_show_type_dampend_paths
9650 || type == bgp_show_type_damp_neighbor) {
40381db7 9651 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
9652 continue;
9653 }
9654 if (type == bgp_show_type_regexp) {
9655 regex_t *regex = output_arg;
d62a17ae 9656
40381db7 9657 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
9658 == REG_NOMATCH)
9659 continue;
9660 }
9661 if (type == bgp_show_type_prefix_list) {
9662 struct prefix_list *plist = output_arg;
d62a17ae 9663
9bcb3eef 9664 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
9665 != PREFIX_PERMIT)
9666 continue;
9667 }
9668 if (type == bgp_show_type_filter_list) {
9669 struct as_list *as_list = output_arg;
d62a17ae 9670
40381db7 9671 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
9672 != AS_FILTER_PERMIT)
9673 continue;
9674 }
9675 if (type == bgp_show_type_route_map) {
9676 struct route_map *rmap = output_arg;
9b6d8fcf 9677 struct bgp_path_info path;
98ce9a06 9678 struct attr dummy_attr;
b68885f9 9679 route_map_result_t ret;
d62a17ae 9680
6f4f49b2 9681 dummy_attr = *pi->attr;
d62a17ae 9682
40381db7 9683 path.peer = pi->peer;
9b6d8fcf 9684 path.attr = &dummy_attr;
d62a17ae 9685
9bcb3eef 9686 ret = route_map_apply(rmap, dest_p, RMAP_BGP,
9b6d8fcf 9687 &path);
98ce9a06
DS
9688 if (ret == RMAP_DENYMATCH)
9689 continue;
9690 }
9691 if (type == bgp_show_type_neighbor
9692 || type == bgp_show_type_flap_neighbor
9693 || type == bgp_show_type_damp_neighbor) {
9694 union sockunion *su = output_arg;
9695
40381db7
DS
9696 if (pi->peer == NULL
9697 || pi->peer->su_remote == NULL
9698 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
9699 continue;
9700 }
9701 if (type == bgp_show_type_cidr_only) {
d7c0a89a 9702 uint32_t destination;
d62a17ae 9703
9bcb3eef 9704 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 9705 if (IN_CLASSC(destination)
9bcb3eef 9706 && dest_p->prefixlen == 24)
98ce9a06
DS
9707 continue;
9708 if (IN_CLASSB(destination)
9bcb3eef 9709 && dest_p->prefixlen == 16)
98ce9a06
DS
9710 continue;
9711 if (IN_CLASSA(destination)
9bcb3eef 9712 && dest_p->prefixlen == 8)
98ce9a06
DS
9713 continue;
9714 }
9715 if (type == bgp_show_type_prefix_longer) {
f7813c7c 9716 p = output_arg;
9bcb3eef 9717 if (!prefix_match(p, dest_p))
98ce9a06
DS
9718 continue;
9719 }
9720 if (type == bgp_show_type_community_all) {
40381db7 9721 if (!pi->attr->community)
98ce9a06
DS
9722 continue;
9723 }
9724 if (type == bgp_show_type_community) {
9725 struct community *com = output_arg;
d62a17ae 9726
40381db7
DS
9727 if (!pi->attr->community
9728 || !community_match(pi->attr->community,
98ce9a06
DS
9729 com))
9730 continue;
9731 }
9732 if (type == bgp_show_type_community_exact) {
9733 struct community *com = output_arg;
d62a17ae 9734
40381db7
DS
9735 if (!pi->attr->community
9736 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
9737 continue;
9738 }
9739 if (type == bgp_show_type_community_list) {
9740 struct community_list *list = output_arg;
d62a17ae 9741
40381db7 9742 if (!community_list_match(pi->attr->community,
a4d82a8a 9743 list))
98ce9a06
DS
9744 continue;
9745 }
a4d82a8a 9746 if (type == bgp_show_type_community_list_exact) {
98ce9a06 9747 struct community_list *list = output_arg;
d62a17ae 9748
98ce9a06 9749 if (!community_list_exact_match(
40381db7 9750 pi->attr->community, list))
98ce9a06
DS
9751 continue;
9752 }
9753 if (type == bgp_show_type_lcommunity) {
9754 struct lcommunity *lcom = output_arg;
d62a17ae 9755
40381db7
DS
9756 if (!pi->attr->lcommunity
9757 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
9758 lcom))
9759 continue;
9760 }
36a206db 9761
9762 if (type == bgp_show_type_lcommunity_exact) {
9763 struct lcommunity *lcom = output_arg;
9764
9765 if (!pi->attr->lcommunity
9766 || !lcommunity_cmp(pi->attr->lcommunity,
9767 lcom))
9768 continue;
9769 }
98ce9a06
DS
9770 if (type == bgp_show_type_lcommunity_list) {
9771 struct community_list *list = output_arg;
d62a17ae 9772
40381db7 9773 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 9774 list))
98ce9a06
DS
9775 continue;
9776 }
36a206db 9777 if (type
9778 == bgp_show_type_lcommunity_list_exact) {
9779 struct community_list *list = output_arg;
9780
9781 if (!lcommunity_list_exact_match(
9782 pi->attr->lcommunity, list))
9783 continue;
9784 }
98ce9a06 9785 if (type == bgp_show_type_lcommunity_all) {
40381db7 9786 if (!pi->attr->lcommunity)
98ce9a06
DS
9787 continue;
9788 }
9789 if (type == bgp_show_type_dampend_paths
9790 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
9791 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
9792 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
9793 continue;
9794 }
9795
9796 if (!use_json && header) {
6cde4b45 9797 vty_out(vty, "BGP table version is %" PRIu64", local router ID is %s, vrf id ",
98ce9a06
DS
9798 table->version,
9799 inet_ntoa(bgp->router_id));
9df8b37c
PZ
9800 if (bgp->vrf_id == VRF_UNKNOWN)
9801 vty_out(vty, "%s", VRFID_NONE_STR);
9802 else
9803 vty_out(vty, "%u", bgp->vrf_id);
9804 vty_out(vty, "\n");
01eced22
AD
9805 vty_out(vty, "Default local pref %u, ",
9806 bgp->default_local_pref);
9807 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 9808 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 9809 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 9810 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 9811 if (type == bgp_show_type_dampend_paths
9812 || type == bgp_show_type_damp_neighbor)
98ce9a06 9813 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
9814 else if (type == bgp_show_type_flap_statistics
9815 || type == bgp_show_type_flap_neighbor)
98ce9a06 9816 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 9817 else
ae248832
MK
9818 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
9819 : BGP_SHOW_HEADER));
98ce9a06 9820 header = 0;
d62a17ae 9821 }
98ce9a06
DS
9822 if (rd != NULL && !display && !output_count) {
9823 if (!use_json)
9824 vty_out(vty,
9825 "Route Distinguisher: %s\n",
9826 rd);
d62a17ae 9827 }
98ce9a06
DS
9828 if (type == bgp_show_type_dampend_paths
9829 || type == bgp_show_type_damp_neighbor)
9bcb3eef 9830 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
9831 AFI_IP, safi, use_json,
9832 json_paths);
98ce9a06
DS
9833 else if (type == bgp_show_type_flap_statistics
9834 || type == bgp_show_type_flap_neighbor)
9bcb3eef 9835 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
9836 AFI_IP, safi, use_json,
9837 json_paths);
98ce9a06 9838 else
9bcb3eef 9839 route_vty_out(vty, dest_p, pi, display, safi,
ae248832 9840 json_paths, wide);
98ce9a06 9841 display++;
d62a17ae 9842 }
9843
98ce9a06
DS
9844 if (display) {
9845 output_count++;
9846 if (!use_json)
9847 continue;
9848
625d2931 9849 /* encode prefix */
9bcb3eef 9850 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
9851 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
9852
b54892e0
DS
9853 bgp_fs_nlri_get_string(
9854 (unsigned char *)
9bcb3eef
DS
9855 dest_p->u.prefix_flowspec.ptr,
9856 dest_p->u.prefix_flowspec.prefixlen,
b54892e0 9857 retstr, NLRI_STRING_FORMAT_MIN, NULL);
625d2931 9858 if (first)
b54892e0 9859 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 9860 dest_p->u.prefix_flowspec
b54892e0 9861 .prefixlen);
625d2931 9862 else
b54892e0 9863 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 9864 dest_p->u.prefix_flowspec
b54892e0 9865 .prefixlen);
625d2931 9866 } else {
625d2931 9867 if (first)
1b78780b 9868 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 9869 else
1b78780b 9870 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 9871 }
98ce9a06 9872 vty_out(vty, "%s",
f4ec52f7
DA
9873 json_object_to_json_string_ext(
9874 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 9875 json_object_free(json_paths);
449feb8e 9876 json_paths = NULL;
98ce9a06 9877 first = 0;
1f83ed02
DS
9878 } else
9879 json_object_free(json_paths);
98ce9a06
DS
9880 }
9881
1ae44dfc
LB
9882 if (output_cum) {
9883 output_count += *output_cum;
9884 *output_cum = output_count;
9885 }
9886 if (total_cum) {
9887 total_count += *total_cum;
9888 *total_cum = total_count;
9889 }
d62a17ae 9890 if (use_json) {
9386b588 9891 if (rd) {
a4d82a8a 9892 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
9893 }
9894 if (is_last) {
a4d82a8a
PZ
9895 unsigned long i;
9896 for (i = 0; i < *json_header_depth; ++i)
9897 vty_out(vty, " } ");
faf6559a 9898 vty_out(vty, "\n");
9386b588 9899 }
d62a17ae 9900 } else {
1ae44dfc
LB
9901 if (is_last) {
9902 /* No route is displayed */
9903 if (output_count == 0) {
9904 if (type == bgp_show_type_normal)
9905 vty_out(vty,
9906 "No BGP prefixes displayed, %ld exist\n",
9907 total_count);
9908 } else
d62a17ae 9909 vty_out(vty,
1ae44dfc
LB
9910 "\nDisplayed %ld routes and %ld total paths\n",
9911 output_count, total_count);
9912 }
d62a17ae 9913 }
718e3744 9914
d62a17ae 9915 return CMD_SUCCESS;
718e3744 9916}
9917
1ae44dfc
LB
9918int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
9919 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 9920 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 9921{
9bcb3eef 9922 struct bgp_dest *dest, *next;
1ae44dfc
LB
9923 unsigned long output_cum = 0;
9924 unsigned long total_cum = 0;
9386b588 9925 unsigned long json_header_depth = 0;
67009e22 9926 struct bgp_table *itable;
0136788c
LB
9927 bool show_msg;
9928
9929 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 9930
9bcb3eef
DS
9931 for (dest = bgp_table_top(table); dest; dest = next) {
9932 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 9933
9bcb3eef
DS
9934 next = bgp_route_next(dest);
9935 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 9936 continue;
67009e22 9937
9bcb3eef 9938 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 9939 if (itable != NULL) {
1ae44dfc 9940 struct prefix_rd prd;
06b9f471 9941 char rd[RD_ADDRSTRLEN];
1ae44dfc 9942
9bcb3eef 9943 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 9944 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22
DS
9945 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
9946 use_json, rd, next == NULL, &output_cum,
ae248832 9947 &total_cum, &json_header_depth, false);
0136788c
LB
9948 if (next == NULL)
9949 show_msg = false;
1ae44dfc
LB
9950 }
9951 }
0136788c
LB
9952 if (show_msg) {
9953 if (output_cum == 0)
9954 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
9955 total_cum);
9956 else
9957 vty_out(vty,
9958 "\nDisplayed %ld routes and %ld total paths\n",
9959 output_cum, total_cum);
9960 }
1ae44dfc
LB
9961 return CMD_SUCCESS;
9962}
d62a17ae 9963static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
ae248832
MK
9964 enum bgp_show_type type, void *output_arg, bool use_json,
9965 bool wide)
fee0f4c6 9966{
d62a17ae 9967 struct bgp_table *table;
9386b588 9968 unsigned long json_header_depth = 0;
fee0f4c6 9969
d62a17ae 9970 if (bgp == NULL) {
9971 bgp = bgp_get_default();
9972 }
fee0f4c6 9973
d62a17ae 9974 if (bgp == NULL) {
9975 if (!use_json)
9976 vty_out(vty, "No BGP process is configured\n");
16307668
RW
9977 else
9978 vty_out(vty, "{}\n");
d62a17ae 9979 return CMD_WARNING;
9980 }
4dd6177e 9981
1ae44dfc 9982 table = bgp->rib[afi][safi];
d62a17ae 9983 /* use MPLS and ENCAP specific shows until they are merged */
9984 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
9985 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
9986 output_arg, use_json);
d62a17ae 9987 }
dba3c1d3
PG
9988
9989 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
9990 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
9991 output_arg, use_json,
9992 1, NULL, NULL);
9993 }
d62a17ae 9994 /* labeled-unicast routes live in the unicast table */
9995 else if (safi == SAFI_LABELED_UNICAST)
9996 safi = SAFI_UNICAST;
fee0f4c6 9997
1ae44dfc 9998 return bgp_show_table(vty, bgp, safi, table, type, output_arg, use_json,
ae248832 9999 NULL, 1, NULL, NULL, &json_header_depth, wide);
fee0f4c6 10000}
10001
d62a17ae 10002static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
ae248832
MK
10003 safi_t safi, bool use_json,
10004 bool wide)
f186de26 10005{
d62a17ae 10006 struct listnode *node, *nnode;
10007 struct bgp *bgp;
10008 int is_first = 1;
9f049418 10009 bool route_output = false;
f186de26 10010
d62a17ae 10011 if (use_json)
10012 vty_out(vty, "{\n");
9f689658 10013
d62a17ae 10014 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 10015 route_output = true;
d62a17ae 10016 if (use_json) {
10017 if (!is_first)
10018 vty_out(vty, ",\n");
10019 else
10020 is_first = 0;
10021
10022 vty_out(vty, "\"%s\":",
10023 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10024 ? VRF_DEFAULT_NAME
d62a17ae 10025 : bgp->name);
10026 } else {
10027 vty_out(vty, "\nInstance %s:\n",
10028 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10029 ? VRF_DEFAULT_NAME
d62a17ae 10030 : bgp->name);
10031 }
10032 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
ae248832 10033 use_json, wide);
d62a17ae 10034 }
9f689658 10035
d62a17ae 10036 if (use_json)
10037 vty_out(vty, "}\n");
9f049418
DS
10038 else if (!route_output)
10039 vty_out(vty, "%% BGP instance not found\n");
f186de26 10040}
10041
718e3744 10042/* Header of detailed BGP route information */
d62a17ae 10043void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9bcb3eef 10044 struct bgp_dest *dest, struct prefix_rd *prd,
d62a17ae 10045 afi_t afi, safi_t safi, json_object *json)
10046{
40381db7 10047 struct bgp_path_info *pi;
b54892e0 10048 const struct prefix *p;
d62a17ae 10049 struct peer *peer;
10050 struct listnode *node, *nnode;
06b9f471 10051 char buf1[RD_ADDRSTRLEN];
d62a17ae 10052 char buf2[INET6_ADDRSTRLEN];
d62a17ae 10053 char buf3[EVPN_ROUTE_STRLEN];
0291c246 10054 char prefix_str[BUFSIZ];
d62a17ae 10055 int count = 0;
10056 int best = 0;
10057 int suppress = 0;
c5f1e1b2
C
10058 int accept_own = 0;
10059 int route_filter_translated_v4 = 0;
10060 int route_filter_v4 = 0;
10061 int route_filter_translated_v6 = 0;
10062 int route_filter_v6 = 0;
10063 int llgr_stale = 0;
10064 int no_llgr = 0;
10065 int accept_own_nexthop = 0;
10066 int blackhole = 0;
d62a17ae 10067 int no_export = 0;
10068 int no_advertise = 0;
10069 int local_as = 0;
c5f1e1b2 10070 int no_peer = 0;
d62a17ae 10071 int first = 1;
10072 int has_valid_label = 0;
10073 mpls_label_t label = 0;
10074 json_object *json_adv_to = NULL;
9bedbb1e 10075
9bcb3eef
DS
10076 p = bgp_dest_get_prefix(dest);
10077 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 10078
10079 if (has_valid_label)
9bcb3eef 10080 label = label_pton(&dest->local_label);
d62a17ae 10081
44c69747 10082 if (safi == SAFI_EVPN) {
d62a17ae 10083
44c69747 10084 if (!json) {
d62a17ae 10085 vty_out(vty, "BGP routing table entry for %s%s%s\n",
06b9f471 10086 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
44c69747 10087 : "", prd ? ":" : "",
d62a17ae 10088 bgp_evpn_route2str((struct prefix_evpn *)p,
44c69747
LK
10089 buf3, sizeof(buf3)));
10090 } else {
10091 json_object_string_add(json, "rd",
10092 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
10093 "");
10094 bgp_evpn_route2json((struct prefix_evpn *)p, json);
10095 }
10096 } else {
10097 if (!json) {
d62a17ae 10098 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
10099 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
44c69747
LK
10100 ? prefix_rd2str(prd, buf1,
10101 sizeof(buf1))
10102 : ""),
d62a17ae 10103 safi == SAFI_MPLS_VPN ? ":" : "",
10104 inet_ntop(p->family, &p->u.prefix, buf2,
44c69747 10105 INET6_ADDRSTRLEN),
d62a17ae 10106 p->prefixlen);
cd1964ff 10107
44c69747
LK
10108 } else
10109 json_object_string_add(json, "prefix",
10110 prefix2str(p, prefix_str, sizeof(prefix_str)));
10111 }
10112
10113 if (has_valid_label) {
10114 if (json)
10115 json_object_int_add(json, "localLabel", label);
10116 else
d62a17ae 10117 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
10118 }
10119
10120 if (!json)
d62a17ae 10121 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 10122 vty_out(vty, "not allocated\n");
718e3744 10123
9bcb3eef 10124 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 10125 count++;
40381db7 10126 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 10127 best = count;
40381db7 10128 if (pi->extra && pi->extra->suppress)
d62a17ae 10129 suppress = 1;
cee9c031 10130
40381db7 10131 if (pi->attr->community == NULL)
cee9c031
QY
10132 continue;
10133
10134 no_advertise += community_include(
40381db7
DS
10135 pi->attr->community, COMMUNITY_NO_ADVERTISE);
10136 no_export += community_include(pi->attr->community,
cee9c031 10137 COMMUNITY_NO_EXPORT);
40381db7 10138 local_as += community_include(pi->attr->community,
cee9c031 10139 COMMUNITY_LOCAL_AS);
40381db7 10140 accept_own += community_include(pi->attr->community,
cee9c031
QY
10141 COMMUNITY_ACCEPT_OWN);
10142 route_filter_translated_v4 += community_include(
40381db7 10143 pi->attr->community,
cee9c031
QY
10144 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
10145 route_filter_translated_v6 += community_include(
40381db7 10146 pi->attr->community,
cee9c031
QY
10147 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
10148 route_filter_v4 += community_include(
40381db7 10149 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 10150 route_filter_v6 += community_include(
40381db7
DS
10151 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
10152 llgr_stale += community_include(pi->attr->community,
cee9c031 10153 COMMUNITY_LLGR_STALE);
40381db7 10154 no_llgr += community_include(pi->attr->community,
cee9c031
QY
10155 COMMUNITY_NO_LLGR);
10156 accept_own_nexthop +=
40381db7 10157 community_include(pi->attr->community,
cee9c031 10158 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 10159 blackhole += community_include(pi->attr->community,
cee9c031 10160 COMMUNITY_BLACKHOLE);
40381db7 10161 no_peer += community_include(pi->attr->community,
cee9c031 10162 COMMUNITY_NO_PEER);
d62a17ae 10163 }
718e3744 10164 }
718e3744 10165
d62a17ae 10166 if (!json) {
10167 vty_out(vty, "Paths: (%d available", count);
10168 if (best) {
10169 vty_out(vty, ", best #%d", best);
b84060bb
PG
10170 if (safi == SAFI_UNICAST) {
10171 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
10172 vty_out(vty, ", table %s",
10173 VRF_DEFAULT_NAME);
10174 else
10175 vty_out(vty, ", vrf %s",
10176 bgp->name);
10177 }
d62a17ae 10178 } else
10179 vty_out(vty, ", no best path");
10180
c5f1e1b2
C
10181 if (accept_own)
10182 vty_out(vty,
10183 ", accept own local route exported and imported in different VRF");
10184 else if (route_filter_translated_v4)
10185 vty_out(vty,
10186 ", mark translated RTs for VPNv4 route filtering");
10187 else if (route_filter_v4)
10188 vty_out(vty,
10189 ", attach RT as-is for VPNv4 route filtering");
10190 else if (route_filter_translated_v6)
10191 vty_out(vty,
10192 ", mark translated RTs for VPNv6 route filtering");
10193 else if (route_filter_v6)
10194 vty_out(vty,
10195 ", attach RT as-is for VPNv6 route filtering");
10196 else if (llgr_stale)
10197 vty_out(vty,
10198 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
10199 else if (no_llgr)
10200 vty_out(vty,
10201 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
10202 else if (accept_own_nexthop)
10203 vty_out(vty,
10204 ", accept local nexthop");
10205 else if (blackhole)
10206 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 10207 else if (no_export)
10208 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
10209 else if (no_advertise)
10210 vty_out(vty, ", not advertised to any peer");
d62a17ae 10211 else if (local_as)
10212 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
10213 else if (no_peer)
10214 vty_out(vty,
10215 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 10216
10217 if (suppress)
10218 vty_out(vty,
10219 ", Advertisements suppressed by an aggregate.");
10220 vty_out(vty, ")\n");
10221 }
718e3744 10222
d62a17ae 10223 /* If we are not using addpath then we can display Advertised to and
10224 * that will
10225 * show what peers we advertised the bestpath to. If we are using
10226 * addpath
10227 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 10228 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 10229 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 10230 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 10231 if (json && !json_adv_to)
10232 json_adv_to = json_object_new_object();
10233
10234 route_vty_out_advertised_to(
10235 vty, peer, &first,
10236 " Advertised to non peer-group peers:\n ",
10237 json_adv_to);
10238 }
10239 }
10240
10241 if (json) {
10242 if (json_adv_to) {
10243 json_object_object_add(json, "advertisedTo",
10244 json_adv_to);
10245 }
10246 } else {
10247 if (first)
10248 vty_out(vty, " Not advertised to any peer");
10249 vty_out(vty, "\n");
10250 }
10251 }
718e3744 10252}
10253
44c69747 10254static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9bcb3eef
DS
10255 struct bgp_dest *bgp_node, struct vty *vty,
10256 struct bgp *bgp, afi_t afi, safi_t safi,
10257 json_object *json, enum bgp_path_type pathtype,
10258 int *display)
44c69747
LK
10259{
10260 struct bgp_path_info *pi;
10261 int header = 1;
10262 char rdbuf[RD_ADDRSTRLEN];
10263 json_object *json_header = NULL;
10264 json_object *json_paths = NULL;
10265
9bcb3eef 10266 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
44c69747
LK
10267
10268 if (json && !json_paths) {
10269 /* Instantiate json_paths only if path is valid */
10270 json_paths = json_object_new_array();
10271 if (pfx_rd) {
10272 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
10273 json_header = json_object_new_object();
10274 } else
10275 json_header = json;
10276 }
10277
10278 if (header) {
10279 route_vty_out_detail_header(
10280 vty, bgp, bgp_node, pfx_rd,
10281 AFI_IP, safi, json_header);
10282 header = 0;
10283 }
10284 (*display)++;
10285
10286 if (pathtype == BGP_PATH_SHOW_ALL
10287 || (pathtype == BGP_PATH_SHOW_BESTPATH
10288 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
10289 || (pathtype == BGP_PATH_SHOW_MULTIPATH
10290 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
10291 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
10292 route_vty_out_detail(vty, bgp, bgp_node,
10293 pi, AFI_IP, safi,
10294 json_paths);
10295 }
10296
10297 if (json && json_paths) {
10298 json_object_object_add(json_header, "paths", json_paths);
10299
10300 if (pfx_rd)
10301 json_object_object_add(json, rdbuf, json_header);
10302 }
10303}
10304
718e3744 10305/* Display specified route of BGP table. */
d62a17ae 10306static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
10307 struct bgp_table *rib, const char *ip_str,
10308 afi_t afi, safi_t safi,
10309 struct prefix_rd *prd, int prefix_check,
9f049418 10310 enum bgp_path_type pathtype, bool use_json)
d62a17ae 10311{
10312 int ret;
d62a17ae 10313 int display = 0;
10314 struct prefix match;
9bcb3eef
DS
10315 struct bgp_dest *dest;
10316 struct bgp_dest *rm;
d62a17ae 10317 struct bgp_table *table;
10318 json_object *json = NULL;
10319 json_object *json_paths = NULL;
10320
10321 /* Check IP address argument. */
10322 ret = str2prefix(ip_str, &match);
10323 if (!ret) {
10324 vty_out(vty, "address is malformed\n");
10325 return CMD_WARNING;
10326 }
718e3744 10327
d62a17ae 10328 match.family = afi2family(afi);
b05a1c8b 10329
44c69747 10330 if (use_json)
d62a17ae 10331 json = json_object_new_object();
718e3744 10332
44c69747 10333 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
10334 for (dest = bgp_table_top(rib); dest;
10335 dest = bgp_route_next(dest)) {
10336 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10337
9bcb3eef 10338 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 10339 continue;
9bcb3eef 10340 table = bgp_dest_get_bgp_table_info(dest);
67009e22 10341 if (!table)
ea47320b 10342 continue;
d62a17ae 10343
ea47320b
DL
10344 if ((rm = bgp_node_match(table, &match)) == NULL)
10345 continue;
d62a17ae 10346
9bcb3eef 10347 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 10348 if (prefix_check
b54892e0 10349 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 10350 bgp_dest_unlock_node(rm);
ea47320b
DL
10351 continue;
10352 }
d62a17ae 10353
9bcb3eef 10354 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
10355 bgp, afi, safi, json, pathtype,
10356 &display);
44c69747 10357
9bcb3eef 10358 bgp_dest_unlock_node(rm);
44c69747
LK
10359 }
10360 } else if (safi == SAFI_EVPN) {
9bcb3eef 10361 struct bgp_dest *longest_pfx;
cded3b72 10362 bool is_exact_pfxlen_match = false;
44c69747 10363
9bcb3eef
DS
10364 for (dest = bgp_table_top(rib); dest;
10365 dest = bgp_route_next(dest)) {
10366 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10367
9bcb3eef 10368 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 10369 continue;
9bcb3eef 10370 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
10371 if (!table)
10372 continue;
10373
10374 longest_pfx = NULL;
cded3b72 10375 is_exact_pfxlen_match = false;
44c69747
LK
10376 /*
10377 * Search through all the prefixes for a match. The
10378 * pfx's are enumerated in ascending order of pfxlens.
10379 * So, the last pfx match is the longest match. Set
10380 * is_exact_pfxlen_match when we get exact pfxlen match
10381 */
10382 for (rm = bgp_table_top(table); rm;
10383 rm = bgp_route_next(rm)) {
b54892e0 10384 const struct prefix *rm_p =
9bcb3eef 10385 bgp_dest_get_prefix(rm);
44c69747
LK
10386 /*
10387 * Get prefixlen of the ip-prefix within type5
10388 * evpn route
10389 */
b54892e0
DS
10390 if (evpn_type5_prefix_match(rm_p, &match)
10391 && rm->info) {
44c69747
LK
10392 longest_pfx = rm;
10393 int type5_pfxlen =
b54892e0
DS
10394 bgp_evpn_get_type5_prefixlen(
10395 rm_p);
44c69747 10396 if (type5_pfxlen == match.prefixlen) {
cded3b72 10397 is_exact_pfxlen_match = true;
9bcb3eef 10398 bgp_dest_unlock_node(rm);
44c69747
LK
10399 break;
10400 }
d62a17ae 10401 }
10402 }
ea47320b 10403
44c69747
LK
10404 if (!longest_pfx)
10405 continue;
10406
10407 if (prefix_check && !is_exact_pfxlen_match)
10408 continue;
10409
10410 rm = longest_pfx;
9bcb3eef 10411 bgp_dest_lock_node(rm);
44c69747 10412
9bcb3eef 10413 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
10414 bgp, afi, safi, json, pathtype,
10415 &display);
44c69747 10416
9bcb3eef 10417 bgp_dest_unlock_node(rm);
d62a17ae 10418 }
98a9dbc7 10419 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
10420 if (use_json)
10421 json_paths = json_object_new_array();
10422
63a0b7a9
PG
10423 display = bgp_flowspec_display_match_per_ip(afi, rib,
10424 &match, prefix_check,
10425 vty,
10426 use_json,
10427 json_paths);
44c69747
LK
10428 if (use_json && display)
10429 json_object_object_add(json, "paths", json_paths);
d62a17ae 10430 } else {
9bcb3eef
DS
10431 if ((dest = bgp_node_match(rib, &match)) != NULL) {
10432 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 10433 if (!prefix_check
9bcb3eef
DS
10434 || dest_p->prefixlen == match.prefixlen) {
10435 bgp_show_path_info(NULL, dest, vty, bgp, afi,
10436 safi, json, pathtype,
10437 &display);
d62a17ae 10438 }
10439
9bcb3eef 10440 bgp_dest_unlock_node(dest);
d62a17ae 10441 }
10442 }
e5eee9af 10443
d62a17ae 10444 if (use_json) {
996c9314 10445 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
10446 json, JSON_C_TO_STRING_PRETTY |
10447 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 10448 json_object_free(json);
10449 } else {
10450 if (!display) {
10451 vty_out(vty, "%% Network not in table\n");
10452 return CMD_WARNING;
10453 }
10454 }
b05a1c8b 10455
d62a17ae 10456 return CMD_SUCCESS;
718e3744 10457}
10458
fee0f4c6 10459/* Display specified route of Main RIB */
d62a17ae 10460static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
10461 afi_t afi, safi_t safi, struct prefix_rd *prd,
10462 int prefix_check, enum bgp_path_type pathtype,
9f049418 10463 bool use_json)
d62a17ae 10464{
9b86009a 10465 if (!bgp) {
d62a17ae 10466 bgp = bgp_get_default();
9b86009a
RW
10467 if (!bgp) {
10468 if (!use_json)
10469 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10470 else
10471 vty_out(vty, "{}\n");
9b86009a
RW
10472 return CMD_WARNING;
10473 }
10474 }
d62a17ae 10475
10476 /* labeled-unicast routes live in the unicast table */
10477 if (safi == SAFI_LABELED_UNICAST)
10478 safi = SAFI_UNICAST;
10479
10480 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
10481 afi, safi, prd, prefix_check, pathtype,
10482 use_json);
10483}
10484
10485static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 10486 struct cmd_token **argv, bool exact, afi_t afi,
10487 safi_t safi, bool uj)
d62a17ae 10488{
10489 struct lcommunity *lcom;
10490 struct buffer *b;
10491 int i;
10492 char *str;
10493 int first = 0;
10494
10495 b = buffer_new(1024);
10496 for (i = 0; i < argc; i++) {
10497 if (first)
10498 buffer_putc(b, ' ');
10499 else {
10500 if (strmatch(argv[i]->text, "AA:BB:CC")) {
10501 first = 1;
10502 buffer_putstr(b, argv[i]->arg);
10503 }
10504 }
10505 }
10506 buffer_putc(b, '\0');
57d187bc 10507
d62a17ae 10508 str = buffer_getstr(b);
10509 buffer_free(b);
57d187bc 10510
d62a17ae 10511 lcom = lcommunity_str2com(str);
10512 XFREE(MTYPE_TMP, str);
10513 if (!lcom) {
10514 vty_out(vty, "%% Large-community malformed\n");
10515 return CMD_WARNING;
10516 }
57d187bc 10517
36a206db 10518 return bgp_show(vty, bgp, afi, safi,
10519 (exact ? bgp_show_type_lcommunity_exact
ae248832
MK
10520 : bgp_show_type_lcommunity),
10521 lcom, uj, false);
57d187bc
JS
10522}
10523
d62a17ae 10524static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 10525 const char *lcom, bool exact, afi_t afi,
10526 safi_t safi, bool uj)
57d187bc 10527{
d62a17ae 10528 struct community_list *list;
57d187bc 10529
e237b0d2 10530 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 10531 LARGE_COMMUNITY_LIST_MASTER);
10532 if (list == NULL) {
10533 vty_out(vty, "%% %s is not a valid large-community-list name\n",
10534 lcom);
10535 return CMD_WARNING;
10536 }
57d187bc 10537
36a206db 10538 return bgp_show(vty, bgp, afi, safi,
10539 (exact ? bgp_show_type_lcommunity_list_exact
ae248832
MK
10540 : bgp_show_type_lcommunity_list),
10541 list, uj, false);
fee0f4c6 10542}
10543
52951b63
DS
10544DEFUN (show_ip_bgp_large_community_list,
10545 show_ip_bgp_large_community_list_cmd,
36a206db 10546 "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
10547 SHOW_STR
10548 IP_STR
10549 BGP_STR
10550 BGP_INSTANCE_HELP_STR
9bedbb1e 10551 BGP_AFI_HELP_STR
4dd6177e 10552 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10553 "Display routes matching the large-community-list\n"
10554 "large-community-list number\n"
10555 "large-community-list name\n"
36a206db 10556 "Exact match of the large-communities\n"
52951b63
DS
10557 JSON_STR)
10558{
d62a17ae 10559 afi_t afi = AFI_IP6;
10560 safi_t safi = SAFI_UNICAST;
10561 int idx = 0;
36a206db 10562 bool exact_match = 0;
4d678463 10563 struct bgp *bgp = NULL;
9f049418 10564 bool uj = use_json(argc, argv);
d62a17ae 10565
4d678463
KA
10566 if (uj)
10567 argc--;
10568
10569 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10570 &bgp, uj);
10571 if (!idx)
10572 return CMD_WARNING;
d62a17ae 10573
10574 argv_find(argv, argc, "large-community-list", &idx);
36a206db 10575
10576 const char *clist_number_or_name = argv[++idx]->arg;
10577
10578 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10579 exact_match = 1;
10580
10581 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
10582 exact_match, afi, safi, uj);
52951b63
DS
10583}
10584DEFUN (show_ip_bgp_large_community,
10585 show_ip_bgp_large_community_cmd,
36a206db 10586 "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
10587 SHOW_STR
10588 IP_STR
10589 BGP_STR
10590 BGP_INSTANCE_HELP_STR
9bedbb1e 10591 BGP_AFI_HELP_STR
4dd6177e 10592 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10593 "Display routes matching the large-communities\n"
10594 "List of large-community numbers\n"
36a206db 10595 "Exact match of the large-communities\n"
52951b63
DS
10596 JSON_STR)
10597{
d62a17ae 10598 afi_t afi = AFI_IP6;
10599 safi_t safi = SAFI_UNICAST;
10600 int idx = 0;
36a206db 10601 bool exact_match = 0;
4d678463 10602 struct bgp *bgp = NULL;
9f049418 10603 bool uj = use_json(argc, argv);
d62a17ae 10604
4d678463
KA
10605 if (uj)
10606 argc--;
10607
10608 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10609 &bgp, uj);
10610 if (!idx)
10611 return CMD_WARNING;
d62a17ae 10612
36a206db 10613 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
10614 if (argv_find(argv, argc, "exact-match", &idx))
10615 exact_match = 1;
10616 return bgp_show_lcommunity(vty, bgp, argc, argv,
10617 exact_match, afi, safi, uj);
10618 } else
d62a17ae 10619 return bgp_show(vty, bgp, afi, safi,
ae248832 10620 bgp_show_type_lcommunity_all, NULL, uj, false);
52951b63
DS
10621}
10622
71f1613a
DA
10623static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
10624 safi_t safi, struct json_object *json_array);
d62a17ae 10625static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 10626 safi_t safi, struct json_object *json);
e01ca200 10627
7b2ff250 10628
9ab0cf58
PG
10629DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
10630 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
10631 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
10632 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
10633{
10634 bool uj = use_json(argc, argv);
10635 struct bgp *bgp = NULL;
ec76a1d1
DA
10636 safi_t safi = SAFI_UNICAST;
10637 afi_t afi = AFI_IP6;
4265b261 10638 int idx = 0;
6c9d22e2
PG
10639 struct json_object *json_all = NULL;
10640 struct json_object *json_afi_safi = NULL;
4265b261
PG
10641
10642 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10643 &bgp, false);
71f1613a 10644 if (!idx)
4265b261 10645 return CMD_WARNING;
6c9d22e2 10646
4265b261 10647 if (uj)
6c9d22e2 10648 json_all = json_object_new_object();
4265b261 10649
9ab0cf58
PG
10650 FOREACH_AFI_SAFI (afi, safi) {
10651 /*
10652 * So limit output to those afi/safi pairs that
10653 * actually have something interesting in them
10654 */
10655 if (strmatch(get_afi_safi_str(afi, safi, true),
10656 "Unknown")) {
10657 continue;
10658 }
10659 if (uj) {
10660 json_afi_safi = json_object_new_array();
10661 json_object_object_add(
10662 json_all,
10663 get_afi_safi_str(afi, safi, true),
10664 json_afi_safi);
10665 } else {
10666 json_afi_safi = NULL;
6c9d22e2 10667 }
9ab0cf58
PG
10668
10669 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 10670 }
6c9d22e2
PG
10671
10672 if (uj) {
9ab0cf58
PG
10673 vty_out(vty, "%s",
10674 json_object_to_json_string_ext(
10675 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 10676 json_object_free(json_all);
4265b261 10677 }
6c9d22e2 10678
4265b261
PG
10679 return CMD_SUCCESS;
10680}
10681
7b2ff250 10682/* BGP route print out function without JSON */
14718643
PG
10683DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
10684 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 10685 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
10686 SHOW_STR
10687 IP_STR
10688 BGP_STR
10689 BGP_INSTANCE_HELP_STR
10690 L2VPN_HELP_STR
10691 EVPN_HELP_STR
10692 "BGP RIB advertisement statistics\n"
10693 JSON_STR)
10694{
ec76a1d1
DA
10695 afi_t afi = AFI_IP6;
10696 safi_t safi = SAFI_UNICAST;
14718643
PG
10697 struct bgp *bgp = NULL;
10698 int idx = 0, ret;
10699 bool uj = use_json(argc, argv);
10700 struct json_object *json_afi_safi = NULL, *json = NULL;
10701
10702 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10703 &bgp, false);
10704 if (!idx)
10705 return CMD_WARNING;
10706
10707 if (uj)
10708 json_afi_safi = json_object_new_array();
10709 else
10710 json_afi_safi = NULL;
10711
10712 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
10713
10714 if (uj) {
10715 json = json_object_new_object();
10716 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
10717 json_afi_safi);
10718 vty_out(vty, "%s", json_object_to_json_string_ext(
10719 json, JSON_C_TO_STRING_PRETTY));
10720 json_object_free(json);
10721 }
10722 return ret;
10723}
10724
893cccd0 10725/* BGP route print out function without JSON */
9ab0cf58
PG
10726DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
10727 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
10728 " [" BGP_SAFI_WITH_LABEL_CMD_STR
10729 "]]\
893cccd0 10730 statistics [json]",
9ab0cf58
PG
10731 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
10732 BGP_SAFI_WITH_LABEL_HELP_STR
10733 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 10734{
ec76a1d1
DA
10735 afi_t afi = AFI_IP6;
10736 safi_t safi = SAFI_UNICAST;
893cccd0
PG
10737 struct bgp *bgp = NULL;
10738 int idx = 0, ret;
10739 bool uj = use_json(argc, argv);
6c9d22e2 10740 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
10741
10742 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10743 &bgp, false);
10744 if (!idx)
10745 return CMD_WARNING;
6c9d22e2 10746
893cccd0 10747 if (uj)
6c9d22e2
PG
10748 json_afi_safi = json_object_new_array();
10749 else
10750 json_afi_safi = NULL;
10751
10752 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
10753
10754 if (uj) {
10755 json = json_object_new_object();
10756 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
10757 json_afi_safi);
9ab0cf58
PG
10758 vty_out(vty, "%s",
10759 json_object_to_json_string_ext(
10760 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
10761 json_object_free(json);
10762 }
10763 return ret;
893cccd0 10764}
7b2ff250
DW
10765
10766/* BGP route print out function without JSON */
9ab0cf58
PG
10767DEFUN(show_ip_bgp, show_ip_bgp_cmd,
10768 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
10769 " [" BGP_SAFI_WITH_LABEL_CMD_STR
10770 "]]\
7b2ff250
DW
10771 <dampening <parameters>\
10772 |route-map WORD\
10773 |prefix-list WORD\
10774 |filter-list WORD\
7b2ff250
DW
10775 |community-list <(1-500)|WORD> [exact-match]\
10776 |A.B.C.D/M longer-prefixes\
10777 |X:X::X:X/M longer-prefixes\
893cccd0 10778 >",
9ab0cf58
PG
10779 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
10780 BGP_SAFI_WITH_LABEL_HELP_STR
10781 "Display detailed information about dampening\n"
10782 "Display detail of configured dampening parameters\n"
10783 "Display routes matching the route-map\n"
10784 "A route-map to match on\n"
10785 "Display routes conforming to the prefix-list\n"
10786 "Prefix-list name\n"
10787 "Display routes conforming to the filter-list\n"
10788 "Regular expression access list name\n"
10789 "Display routes matching the community-list\n"
10790 "community-list number\n"
10791 "community-list name\n"
10792 "Exact match of the communities\n"
10793 "IPv4 prefix\n"
10794 "Display route and more specific routes\n"
10795 "IPv6 prefix\n"
10796 "Display route and more specific routes\n")
718e3744 10797{
d62a17ae 10798 afi_t afi = AFI_IP6;
10799 safi_t safi = SAFI_UNICAST;
10800 int exact_match = 0;
d62a17ae 10801 struct bgp *bgp = NULL;
10802 int idx = 0;
10803
10804 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10805 &bgp, false);
d62a17ae 10806 if (!idx)
10807 return CMD_WARNING;
10808
d62a17ae 10809 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 10810 if (argv_find(argv, argc, "parameters", &idx))
d62a17ae 10811 return bgp_show_dampening_parameters(vty, afi, safi);
10812 }
c016b6c7 10813
d62a17ae 10814 if (argv_find(argv, argc, "prefix-list", &idx))
10815 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
10816 safi, bgp_show_type_prefix_list);
10817
10818 if (argv_find(argv, argc, "filter-list", &idx))
10819 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
10820 safi, bgp_show_type_filter_list);
10821
d62a17ae 10822 if (argv_find(argv, argc, "route-map", &idx))
10823 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
10824 safi, bgp_show_type_route_map);
10825
d62a17ae 10826 if (argv_find(argv, argc, "community-list", &idx)) {
10827 const char *clist_number_or_name = argv[++idx]->arg;
10828 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10829 exact_match = 1;
10830 return bgp_show_community_list(vty, bgp, clist_number_or_name,
10831 exact_match, afi, safi);
10832 }
10833 /* prefix-longer */
10834 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10835 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10836 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
10837 safi,
10838 bgp_show_type_prefix_longer);
10839
7b2ff250
DW
10840 return CMD_WARNING;
10841}
10842
10843/* BGP route print out function with JSON */
ae248832 10844DEFPY (show_ip_bgp_json,
7b2ff250
DW
10845 show_ip_bgp_json_cmd,
10846 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
cf4898bc
QY
10847 [cidr-only\
10848 |dampening <flap-statistics|dampened-paths>\
10849 |community [AA:NN|local-AS|no-advertise|no-export\
10850 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10851 |accept-own|accept-own-nexthop|route-filter-v6\
10852 |route-filter-v4|route-filter-translated-v6\
10853 |route-filter-translated-v4] [exact-match]\
ae248832 10854 ] [json$uj | wide$wide]",
7b2ff250
DW
10855 SHOW_STR
10856 IP_STR
10857 BGP_STR
10858 BGP_INSTANCE_HELP_STR
10859 BGP_AFI_HELP_STR
10860 BGP_SAFI_WITH_LABEL_HELP_STR
10861 "Display only routes with non-natural netmasks\n"
10862 "Display detailed information about dampening\n"
10863 "Display flap statistics of routes\n"
10864 "Display paths suppressed due to dampening\n"
10865 "Display routes matching the communities\n"
d0086e8e
AD
10866 COMMUNITY_AANN_STR
10867 "Do not send outside local AS (well-known community)\n"
10868 "Do not advertise to any peer (well-known community)\n"
10869 "Do not export to next AS (well-known community)\n"
10870 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
10871 "Do not export to any peer (well-known community)\n"
10872 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10873 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10874 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10875 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10876 "Should accept VPN route with local nexthop (well-known community)\n"
10877 "RT VPNv6 route filtering (well-known community)\n"
10878 "RT VPNv4 route filtering (well-known community)\n"
10879 "RT translated VPNv6 route filtering (well-known community)\n"
10880 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 10881 "Exact match of the communities\n"
ae248832
MK
10882 JSON_STR
10883 "Increase table width for longer prefixes\n")
7b2ff250
DW
10884{
10885 afi_t afi = AFI_IP6;
10886 safi_t safi = SAFI_UNICAST;
10887 enum bgp_show_type sh_type = bgp_show_type_normal;
10888 struct bgp *bgp = NULL;
10889 int idx = 0;
d0086e8e 10890 int exact_match = 0;
9f049418
DS
10891
10892 if (uj)
10893 argc--;
7b2ff250
DW
10894
10895 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10896 &bgp, uj);
7b2ff250
DW
10897 if (!idx)
10898 return CMD_WARNING;
10899
7b2ff250
DW
10900 if (argv_find(argv, argc, "cidr-only", &idx))
10901 return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
ae248832 10902 NULL, uj, wide);
7b2ff250
DW
10903
10904 if (argv_find(argv, argc, "dampening", &idx)) {
10905 if (argv_find(argv, argc, "dampened-paths", &idx))
10906 return bgp_show(vty, bgp, afi, safi,
ae248832
MK
10907 bgp_show_type_dampend_paths, NULL, uj,
10908 wide);
7b2ff250
DW
10909 else if (argv_find(argv, argc, "flap-statistics", &idx))
10910 return bgp_show(vty, bgp, afi, safi,
ae248832
MK
10911 bgp_show_type_flap_statistics, NULL, uj,
10912 wide);
7b2ff250
DW
10913 }
10914
10915 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 10916 char *maybecomm = NULL;
cf4898bc 10917 char *community = NULL;
d0086e8e 10918
79bc257a
RW
10919 if (idx + 1 < argc) {
10920 if (argv[idx + 1]->type == VARIABLE_TKN)
10921 maybecomm = argv[idx + 1]->arg;
10922 else
10923 maybecomm = argv[idx + 1]->text;
10924 }
10925
cf4898bc
QY
10926 if (maybecomm && !strmatch(maybecomm, "json")
10927 && !strmatch(maybecomm, "exact-match"))
10928 community = maybecomm;
d0086e8e 10929
cf4898bc
QY
10930 if (argv_find(argv, argc, "exact-match", &idx))
10931 exact_match = 1;
d0086e8e 10932
cf4898bc
QY
10933 if (community)
10934 return bgp_show_community(vty, bgp, community,
10935 exact_match, afi, safi, uj);
10936 else
d0086e8e 10937 return (bgp_show(vty, bgp, afi, safi,
ae248832
MK
10938 bgp_show_type_community_all, NULL, uj,
10939 wide));
7b2ff250 10940 }
d0086e8e 10941
ae248832 10942 return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj, wide);
a636c635 10943}
47fc97cc 10944
718e3744 10945DEFUN (show_ip_bgp_route,
10946 show_ip_bgp_route_cmd,
3efd0893 10947 "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 10948 SHOW_STR
10949 IP_STR
10950 BGP_STR
a636c635 10951 BGP_INSTANCE_HELP_STR
4f280b15 10952 BGP_AFI_HELP_STR
4dd6177e 10953 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 10954 "Network in the BGP routing table to display\n"
0c7b1b01 10955 "IPv4 prefix\n"
8c3deaae 10956 "Network in the BGP routing table to display\n"
0c7b1b01 10957 "IPv6 prefix\n"
4092b06c 10958 "Display only the bestpath\n"
b05a1c8b 10959 "Display only multipaths\n"
9973d184 10960 JSON_STR)
4092b06c 10961{
d62a17ae 10962 int prefix_check = 0;
ae19d7dd 10963
d62a17ae 10964 afi_t afi = AFI_IP6;
10965 safi_t safi = SAFI_UNICAST;
10966 char *prefix = NULL;
10967 struct bgp *bgp = NULL;
10968 enum bgp_path_type path_type;
9f049418 10969 bool uj = use_json(argc, argv);
b05a1c8b 10970
d62a17ae 10971 int idx = 0;
ae19d7dd 10972
d62a17ae 10973 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10974 &bgp, uj);
d62a17ae 10975 if (!idx)
10976 return CMD_WARNING;
c41247f5 10977
d62a17ae 10978 if (!bgp) {
10979 vty_out(vty,
10980 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10981 return CMD_WARNING;
10982 }
a636c635 10983
d62a17ae 10984 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10985 if (argv_find(argv, argc, "A.B.C.D", &idx)
10986 || argv_find(argv, argc, "X:X::X:X", &idx))
10987 prefix_check = 0;
10988 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10989 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10990 prefix_check = 1;
10991
10992 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
10993 && afi != AFI_IP6) {
10994 vty_out(vty,
10995 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10996 return CMD_WARNING;
10997 }
10998 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
10999 && afi != AFI_IP) {
11000 vty_out(vty,
11001 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
11002 return CMD_WARNING;
11003 }
11004
11005 prefix = argv[idx]->arg;
11006
11007 /* [<bestpath|multipath>] */
11008 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 11009 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 11010 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 11011 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 11012 else
360660c6 11013 path_type = BGP_PATH_SHOW_ALL;
a636c635 11014
d62a17ae 11015 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
11016 path_type, uj);
4092b06c
DS
11017}
11018
8c3deaae
QY
11019DEFUN (show_ip_bgp_regexp,
11020 show_ip_bgp_regexp_cmd,
3e5b31b3 11021 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
11022 SHOW_STR
11023 IP_STR
11024 BGP_STR
b00b230a 11025 BGP_INSTANCE_HELP_STR
4f280b15 11026 BGP_AFI_HELP_STR
4dd6177e 11027 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 11028 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
11029 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
11030 JSON_STR)
8c3deaae 11031{
d62a17ae 11032 afi_t afi = AFI_IP6;
11033 safi_t safi = SAFI_UNICAST;
11034 struct bgp *bgp = NULL;
3e5b31b3
DA
11035 bool uj = use_json(argc, argv);
11036 char *regstr = NULL;
8c3deaae 11037
d62a17ae 11038 int idx = 0;
11039 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11040 &bgp, false);
d62a17ae 11041 if (!idx)
11042 return CMD_WARNING;
8c3deaae 11043
d62a17ae 11044 // get index of regex
3e5b31b3
DA
11045 if (argv_find(argv, argc, "REGEX", &idx))
11046 regstr = argv[idx]->arg;
8c3deaae 11047
5f71d11c 11048 assert(regstr);
3e5b31b3
DA
11049 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
11050 bgp_show_type_regexp, uj);
8c3deaae
QY
11051}
11052
ae248832 11053DEFPY (show_ip_bgp_instance_all,
a636c635 11054 show_ip_bgp_instance_all_cmd,
ae248832 11055 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 11056 SHOW_STR
a636c635 11057 IP_STR
4092b06c 11058 BGP_STR
a636c635 11059 BGP_INSTANCE_ALL_HELP_STR
4f280b15 11060 BGP_AFI_HELP_STR
4dd6177e 11061 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
11062 JSON_STR
11063 "Increase table width for longer prefixes\n")
4092b06c 11064{
d62a17ae 11065 afi_t afi = AFI_IP;
11066 safi_t safi = SAFI_UNICAST;
11067 struct bgp *bgp = NULL;
d62a17ae 11068 int idx = 0;
ae19d7dd 11069
d62a17ae 11070 if (uj)
11071 argc--;
e3e29b32 11072
9f049418
DS
11073 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11074 &bgp, uj);
11075 if (!idx)
11076 return CMD_WARNING;
11077
ae248832 11078 bgp_show_all_instances_routes_vty(vty, afi, safi, uj, wide);
d62a17ae 11079 return CMD_SUCCESS;
e3e29b32
LB
11080}
11081
a4d82a8a 11082static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11083 afi_t afi, safi_t safi, enum bgp_show_type type,
11084 bool use_json)
718e3744 11085{
d62a17ae 11086 regex_t *regex;
11087 int rc;
e3e29b32 11088
c3900853 11089 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 11090 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
11091 regstr);
11092 return CMD_WARNING_CONFIG_FAILED;
11093 }
11094
d62a17ae 11095 regex = bgp_regcomp(regstr);
11096 if (!regex) {
11097 vty_out(vty, "Can't compile regexp %s\n", regstr);
11098 return CMD_WARNING;
11099 }
a636c635 11100
ae248832 11101 rc = bgp_show(vty, bgp, afi, safi, type, regex, use_json, false);
d62a17ae 11102 bgp_regex_free(regex);
11103 return rc;
e3e29b32
LB
11104}
11105
d62a17ae 11106static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
11107 const char *prefix_list_str, afi_t afi,
11108 safi_t safi, enum bgp_show_type type)
e3e29b32 11109{
d62a17ae 11110 struct prefix_list *plist;
718e3744 11111
d62a17ae 11112 plist = prefix_list_lookup(afi, prefix_list_str);
11113 if (plist == NULL) {
11114 vty_out(vty, "%% %s is not a valid prefix-list name\n",
11115 prefix_list_str);
11116 return CMD_WARNING;
11117 }
718e3744 11118
ae248832 11119 return bgp_show(vty, bgp, afi, safi, type, plist, 0, false);
4092b06c
DS
11120}
11121
d62a17ae 11122static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
11123 const char *filter, afi_t afi, safi_t safi,
11124 enum bgp_show_type type)
4092b06c 11125{
d62a17ae 11126 struct as_list *as_list;
718e3744 11127
d62a17ae 11128 as_list = as_list_lookup(filter);
11129 if (as_list == NULL) {
11130 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
11131 filter);
11132 return CMD_WARNING;
11133 }
a636c635 11134
ae248832 11135 return bgp_show(vty, bgp, afi, safi, type, as_list, 0, false);
718e3744 11136}
11137
d62a17ae 11138static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
11139 const char *rmap_str, afi_t afi, safi_t safi,
11140 enum bgp_show_type type)
718e3744 11141{
d62a17ae 11142 struct route_map *rmap;
bb46e94f 11143
d62a17ae 11144 rmap = route_map_lookup_by_name(rmap_str);
11145 if (!rmap) {
11146 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
11147 return CMD_WARNING;
11148 }
11149
ae248832 11150 return bgp_show(vty, bgp, afi, safi, type, rmap, 0, false);
d62a17ae 11151}
11152
7f323236
DW
11153static int bgp_show_community(struct vty *vty, struct bgp *bgp,
11154 const char *comstr, int exact, afi_t afi,
9f049418 11155 safi_t safi, bool use_json)
d62a17ae 11156{
11157 struct community *com;
d62a17ae 11158 int ret = 0;
11159
7f323236 11160 com = community_str2com(comstr);
d62a17ae 11161 if (!com) {
7f323236 11162 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 11163 return CMD_WARNING;
11164 }
11165
11166 ret = bgp_show(vty, bgp, afi, safi,
11167 (exact ? bgp_show_type_community_exact
11168 : bgp_show_type_community),
ae248832 11169 com, use_json, false);
3c1f53de 11170 community_free(&com);
46c3ce83 11171
d62a17ae 11172 return ret;
718e3744 11173}
11174
d62a17ae 11175static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
11176 const char *com, int exact, afi_t afi,
11177 safi_t safi)
50ef26d4 11178{
d62a17ae 11179 struct community_list *list;
50ef26d4 11180
e237b0d2 11181 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 11182 if (list == NULL) {
11183 vty_out(vty, "%% %s is not a valid community-list name\n", com);
11184 return CMD_WARNING;
11185 }
718e3744 11186
d62a17ae 11187 return bgp_show(vty, bgp, afi, safi,
11188 (exact ? bgp_show_type_community_list_exact
11189 : bgp_show_type_community_list),
ae248832 11190 list, 0, false);
50ef26d4 11191}
11192
d62a17ae 11193static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
11194 const char *prefix, afi_t afi, safi_t safi,
11195 enum bgp_show_type type)
718e3744 11196{
d62a17ae 11197 int ret;
11198 struct prefix *p;
47fc97cc 11199
d62a17ae 11200 p = prefix_new();
95cbbd2a 11201
d62a17ae 11202 ret = str2prefix(prefix, p);
11203 if (!ret) {
11204 vty_out(vty, "%% Malformed Prefix\n");
11205 return CMD_WARNING;
11206 }
47e9b292 11207
ae248832 11208 ret = bgp_show(vty, bgp, afi, safi, type, p, 0, false);
63265b5c 11209 prefix_free(&p);
d62a17ae 11210 return ret;
11211}
11212
d62a17ae 11213enum bgp_stats {
11214 BGP_STATS_MAXBITLEN = 0,
11215 BGP_STATS_RIB,
11216 BGP_STATS_PREFIXES,
11217 BGP_STATS_TOTPLEN,
11218 BGP_STATS_UNAGGREGATEABLE,
11219 BGP_STATS_MAX_AGGREGATEABLE,
11220 BGP_STATS_AGGREGATES,
11221 BGP_STATS_SPACE,
11222 BGP_STATS_ASPATH_COUNT,
11223 BGP_STATS_ASPATH_MAXHOPS,
11224 BGP_STATS_ASPATH_TOTHOPS,
11225 BGP_STATS_ASPATH_MAXSIZE,
11226 BGP_STATS_ASPATH_TOTSIZE,
11227 BGP_STATS_ASN_HIGHEST,
11228 BGP_STATS_MAX,
a636c635 11229};
2815e61f 11230
9ab0cf58 11231#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
11232#define TABLE_STATS_IDX_JSON 1
11233
11234static const char *table_stats_strs[][2] = {
6c9d22e2
PG
11235 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
11236 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
11237 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
11238 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
11239 "unaggregateablePrefixes"},
11240 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
11241 "maximumAggregateablePrefixes"},
11242 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
11243 "bgpAggregateAdvertisements"},
6c9d22e2
PG
11244 [BGP_STATS_SPACE] = {"Address space advertised",
11245 "addressSpaceAdvertised"},
9ab0cf58
PG
11246 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
11247 "advertisementsWithPaths"},
11248 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
11249 "longestAsPath"},
11250 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
11251 "largestAsPath"},
11252 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
11253 "averageAsPathLengthHops"},
11254 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
11255 "averageAsPathSizeBytes"},
11256 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 11257 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 11258};
2815e61f 11259
d62a17ae 11260struct bgp_table_stats {
11261 struct bgp_table *table;
11262 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 11263 double total_space;
ff7924f6
PJ
11264};
11265
a636c635
DW
11266#if 0
11267#define TALLY_SIGFIG 100000
11268static unsigned long
11269ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 11270{
a636c635
DW
11271 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
11272 unsigned long res = (newtot * TALLY_SIGFIG) / count;
11273 unsigned long ret = newtot / count;
07d0c4ed 11274
a636c635
DW
11275 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
11276 return ret + 1;
11277 else
11278 return ret;
11279}
11280#endif
ff7924f6 11281
9bcb3eef 11282static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 11283 struct bgp_table_stats *ts, unsigned int space)
2815e61f 11284{
9bcb3eef 11285 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 11286 struct bgp_path_info *pi;
b54892e0 11287 const struct prefix *rn_p;
d62a17ae 11288
9bcb3eef 11289 if (dest == top)
9c14ec72 11290 return;
d62a17ae 11291
9bcb3eef 11292 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 11293 return;
d62a17ae 11294
9bcb3eef 11295 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 11296 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 11297 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 11298
a636c635
DW
11299#if 0
11300 ts->counts[BGP_STATS_AVGPLEN]
11301 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
11302 ts->counts[BGP_STATS_AVGPLEN],
b54892e0 11303 rn_p->prefixlen);
a636c635 11304#endif
d62a17ae 11305
9c14ec72 11306 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
11307 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
11308 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 11309
9bcb3eef 11310 if (pdest == NULL || pdest == top) {
9c14ec72
RW
11311 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
11312 /* announced address space */
11313 if (space)
b54892e0 11314 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 11315 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 11316 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 11317
9c14ec72 11318
9bcb3eef 11319 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
11320 ts->counts[BGP_STATS_RIB]++;
11321
05864da7
DS
11322 if (CHECK_FLAG(pi->attr->flag,
11323 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
11324 ts->counts[BGP_STATS_AGGREGATES]++;
11325
11326 /* as-path stats */
05864da7 11327 if (pi->attr->aspath) {
9c14ec72
RW
11328 unsigned int hops = aspath_count_hops(pi->attr->aspath);
11329 unsigned int size = aspath_size(pi->attr->aspath);
11330 as_t highest = aspath_highest(pi->attr->aspath);
11331
11332 ts->counts[BGP_STATS_ASPATH_COUNT]++;
11333
11334 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
11335 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
11336
11337 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
11338 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
11339
11340 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
11341 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 11342#if 0
07d0c4ed 11343 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
11344 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
11345 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
11346 hops);
11347 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
11348 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
11349 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
11350 size);
11351#endif
9c14ec72
RW
11352 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
11353 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
11354 }
11355 }
11356}
11357
11358static int bgp_table_stats_walker(struct thread *t)
11359{
9bcb3eef
DS
11360 struct bgp_dest *dest, *ndest;
11361 struct bgp_dest *top;
9c14ec72
RW
11362 struct bgp_table_stats *ts = THREAD_ARG(t);
11363 unsigned int space = 0;
11364
11365 if (!(top = bgp_table_top(ts->table)))
11366 return 0;
11367
11368 switch (ts->table->afi) {
11369 case AFI_IP:
11370 space = IPV4_MAX_BITLEN;
11371 break;
11372 case AFI_IP6:
11373 space = IPV6_MAX_BITLEN;
11374 break;
11375 default:
11376 return 0;
11377 }
11378
11379 ts->counts[BGP_STATS_MAXBITLEN] = space;
11380
9bcb3eef 11381 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
11382 if (ts->table->safi == SAFI_MPLS_VPN
11383 || ts->table->safi == SAFI_ENCAP
11384 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
11385 struct bgp_table *table;
11386
9bcb3eef 11387 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
11388 if (!table)
11389 continue;
11390
11391 top = bgp_table_top(table);
9bcb3eef
DS
11392 for (ndest = bgp_table_top(table); ndest;
11393 ndest = bgp_route_next(ndest))
11394 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 11395 } else {
9bcb3eef 11396 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 11397 }
11398 }
9c14ec72 11399
d62a17ae 11400 return 0;
2815e61f 11401}
ff7924f6 11402
71f1613a
DA
11403static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
11404 struct json_object *json_array)
11405{
11406 struct listnode *node, *nnode;
11407 struct bgp *bgp;
11408
11409 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
11410 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
11411}
11412
11413static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11414 safi_t safi, struct json_object *json_array)
2815e61f 11415{
d62a17ae 11416 struct bgp_table_stats ts;
11417 unsigned int i;
893cccd0
PG
11418 int ret = CMD_SUCCESS;
11419 char temp_buf[20];
6c9d22e2
PG
11420 struct json_object *json = NULL;
11421
11422 if (json_array)
11423 json = json_object_new_object();
019386c2 11424
d62a17ae 11425 if (!bgp->rib[afi][safi]) {
893cccd0
PG
11426 char warning_msg[50];
11427
11428 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
11429 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
11430 safi);
6c9d22e2
PG
11431
11432 if (!json)
893cccd0
PG
11433 vty_out(vty, "%s\n", warning_msg);
11434 else
9ab0cf58 11435 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 11436
893cccd0
PG
11437 ret = CMD_WARNING;
11438 goto end_table_stats;
d62a17ae 11439 }
019386c2 11440
893cccd0 11441 if (!json)
5290ceab
DA
11442 vty_out(vty, "BGP %s RIB statistics (%s)\n",
11443 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
11444 else
11445 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 11446
d62a17ae 11447 /* labeled-unicast routes live in the unicast table */
11448 if (safi == SAFI_LABELED_UNICAST)
11449 safi = SAFI_UNICAST;
019386c2 11450
d62a17ae 11451 memset(&ts, 0, sizeof(ts));
11452 ts.table = bgp->rib[afi][safi];
11453 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 11454
d62a17ae 11455 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
11456 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
11457 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 11458 continue;
11459
11460 switch (i) {
a636c635
DW
11461#if 0
11462 case BGP_STATS_ASPATH_AVGHOPS:
11463 case BGP_STATS_ASPATH_AVGSIZE:
11464 case BGP_STATS_AVGPLEN:
11465 vty_out (vty, "%-30s: ", table_stats_strs[i]);
11466 vty_out (vty, "%12.2f",
11467 (float)ts.counts[i] / (float)TALLY_SIGFIG);
11468 break;
11469#endif
d62a17ae 11470 case BGP_STATS_ASPATH_TOTHOPS:
11471 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 11472 if (!json) {
9ab0cf58
PG
11473 snprintf(
11474 temp_buf, sizeof(temp_buf), "%12.2f",
11475 ts.counts[i]
11476 ? (float)ts.counts[i]
11477 / (float)ts.counts
11478 [BGP_STATS_ASPATH_COUNT]
11479 : 0);
893cccd0 11480 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
11481 table_stats_strs[i]
11482 [TABLE_STATS_IDX_VTY],
893cccd0 11483 temp_buf);
9ab0cf58
PG
11484 } else {
11485 json_object_double_add(
11486 json,
11487 table_stats_strs[i]
11488 [TABLE_STATS_IDX_JSON],
11489 ts.counts[i]
11490 ? (double)ts.counts[i]
11491 / (double)ts.counts
d62a17ae 11492 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
11493 : 0);
11494 }
d62a17ae 11495 break;
11496 case BGP_STATS_TOTPLEN:
6c9d22e2 11497 if (!json) {
9ab0cf58
PG
11498 snprintf(
11499 temp_buf, sizeof(temp_buf), "%12.2f",
11500 ts.counts[i]
11501 ? (float)ts.counts[i]
11502 / (float)ts.counts
11503 [BGP_STATS_PREFIXES]
11504 : 0);
893cccd0 11505 vty_out(vty, "%-30s: %s",
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 ts.counts[i]
11515 ? (double)ts.counts[i]
11516 / (double)ts.counts
d62a17ae 11517 [BGP_STATS_PREFIXES]
9ab0cf58
PG
11518 : 0);
11519 }
d62a17ae 11520 break;
11521 case BGP_STATS_SPACE:
6c9d22e2
PG
11522 if (!json) {
11523 snprintf(temp_buf, sizeof(temp_buf), "%12g",
11524 ts.total_space);
893cccd0 11525 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
11526 table_stats_strs[i]
11527 [TABLE_STATS_IDX_VTY],
893cccd0 11528 temp_buf);
9ab0cf58
PG
11529 } else {
11530 json_object_double_add(
11531 json,
11532 table_stats_strs[i]
11533 [TABLE_STATS_IDX_JSON],
11534 (double)ts.total_space);
11535 }
8d0ab76d 11536 if (afi == AFI_IP6) {
6c9d22e2
PG
11537 if (!json) {
11538 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
11539 "%12g",
11540 ts.total_space
11541 * pow(2.0, -128 + 32));
6c9d22e2
PG
11542 vty_out(vty, "%30s: %s\n",
11543 "/32 equivalent %s\n",
11544 temp_buf);
9ab0cf58
PG
11545 } else {
11546 json_object_double_add(
11547 json, "/32equivalent",
11548 (double)(ts.total_space
11549 * pow(2.0,
11550 -128 + 32)));
11551 }
6c9d22e2
PG
11552 if (!json) {
11553 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
11554 "%12g",
11555 ts.total_space
11556 * pow(2.0, -128 + 48));
6c9d22e2
PG
11557 vty_out(vty, "%30s: %s\n",
11558 "/48 equivalent %s\n",
11559 temp_buf);
9ab0cf58
PG
11560 } else {
11561 json_object_double_add(
11562 json, "/48equivalent",
11563 (double)(ts.total_space
11564 * pow(2.0,
11565 -128 + 48)));
11566 }
8d0ab76d 11567 } else {
6c9d22e2
PG
11568 if (!json) {
11569 snprintf(temp_buf, sizeof(temp_buf),
11570 "%12.2f",
9ab0cf58
PG
11571 ts.total_space * 100.
11572 * pow(2.0, -32));
6c9d22e2 11573 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
11574 "% announced ", temp_buf);
11575 } else {
11576 json_object_double_add(
11577 json, "%announced",
11578 (double)(ts.total_space * 100.
11579 * pow(2.0, -32)));
11580 }
6c9d22e2
PG
11581 if (!json) {
11582 snprintf(temp_buf, sizeof(temp_buf),
11583 "%12.2f",
9ab0cf58
PG
11584 ts.total_space
11585 * pow(2.0, -32 + 8));
6c9d22e2
PG
11586 vty_out(vty, "%30s: %s\n",
11587 "/8 equivalent ", temp_buf);
9ab0cf58
PG
11588 } else {
11589 json_object_double_add(
11590 json, "/8equivalent",
11591 (double)(ts.total_space
11592 * pow(2.0, -32 + 8)));
11593 }
6c9d22e2
PG
11594 if (!json) {
11595 snprintf(temp_buf, sizeof(temp_buf),
11596 "%12.2f",
9ab0cf58
PG
11597 ts.total_space
11598 * pow(2.0, -32 + 24));
6c9d22e2 11599 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
11600 "/24 equivalent ", temp_buf);
11601 } else {
11602 json_object_double_add(
11603 json, "/24equivalent",
11604 (double)(ts.total_space
11605 * pow(2.0, -32 + 24)));
11606 }
8d0ab76d 11607 }
d62a17ae 11608 break;
11609 default:
6c9d22e2
PG
11610 if (!json) {
11611 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
11612 ts.counts[i]);
893cccd0 11613 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
11614 table_stats_strs[i]
11615 [TABLE_STATS_IDX_VTY],
11616 temp_buf);
11617 } else {
11618 json_object_int_add(
11619 json,
11620 table_stats_strs[i]
11621 [TABLE_STATS_IDX_JSON],
11622 ts.counts[i]);
11623 }
d62a17ae 11624 }
893cccd0
PG
11625 if (!json)
11626 vty_out(vty, "\n");
d62a17ae 11627 }
9ab0cf58 11628end_table_stats:
6c9d22e2
PG
11629 if (json)
11630 json_object_array_add(json_array, json);
893cccd0 11631 return ret;
d62a17ae 11632}
11633
71f1613a
DA
11634static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
11635 safi_t safi, struct json_object *json_array)
11636{
11637 if (!bgp) {
11638 bgp_table_stats_all(vty, afi, safi, json_array);
11639 return CMD_SUCCESS;
11640 }
11641
11642 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
11643}
11644
d62a17ae 11645enum bgp_pcounts {
11646 PCOUNT_ADJ_IN = 0,
11647 PCOUNT_DAMPED,
11648 PCOUNT_REMOVED,
11649 PCOUNT_HISTORY,
11650 PCOUNT_STALE,
11651 PCOUNT_VALID,
11652 PCOUNT_ALL,
11653 PCOUNT_COUNTED,
7e3d9632 11654 PCOUNT_BPATH_SELECTED,
d62a17ae 11655 PCOUNT_PFCNT, /* the figure we display to users */
11656 PCOUNT_MAX,
a636c635 11657};
718e3744 11658
2b64873d 11659static const char *const pcount_strs[] = {
9d303b37
DL
11660 [PCOUNT_ADJ_IN] = "Adj-in",
11661 [PCOUNT_DAMPED] = "Damped",
11662 [PCOUNT_REMOVED] = "Removed",
11663 [PCOUNT_HISTORY] = "History",
11664 [PCOUNT_STALE] = "Stale",
11665 [PCOUNT_VALID] = "Valid",
11666 [PCOUNT_ALL] = "All RIB",
11667 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 11668 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
11669 [PCOUNT_PFCNT] = "Useable",
11670 [PCOUNT_MAX] = NULL,
a636c635 11671};
718e3744 11672
d62a17ae 11673struct peer_pcounts {
11674 unsigned int count[PCOUNT_MAX];
11675 const struct peer *peer;
11676 const struct bgp_table *table;
54317cba 11677 safi_t safi;
a636c635 11678};
47fc97cc 11679
9bcb3eef 11680static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 11681{
54317cba
JW
11682 const struct bgp_adj_in *ain;
11683 const struct bgp_path_info *pi;
d62a17ae 11684 const struct peer *peer = pc->peer;
11685
54317cba
JW
11686 for (ain = rn->adj_in; ain; ain = ain->next)
11687 if (ain->peer == peer)
11688 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 11689
9bcb3eef 11690 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 11691
54317cba
JW
11692 if (pi->peer != peer)
11693 continue;
d62a17ae 11694
54317cba 11695 pc->count[PCOUNT_ALL]++;
d62a17ae 11696
54317cba
JW
11697 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
11698 pc->count[PCOUNT_DAMPED]++;
11699 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
11700 pc->count[PCOUNT_HISTORY]++;
11701 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
11702 pc->count[PCOUNT_REMOVED]++;
11703 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
11704 pc->count[PCOUNT_STALE]++;
11705 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
11706 pc->count[PCOUNT_VALID]++;
11707 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
11708 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
11709 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11710 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
11711
11712 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
11713 pc->count[PCOUNT_COUNTED]++;
11714 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
11715 flog_err(
11716 EC_LIB_DEVELOPMENT,
11717 "Attempting to count but flags say it is unusable");
11718 } else {
40381db7 11719 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
11720 flog_err(
11721 EC_LIB_DEVELOPMENT,
11722 "Not counted but flags say we should");
d62a17ae 11723 }
11724 }
54317cba
JW
11725}
11726
11727static int bgp_peer_count_walker(struct thread *t)
11728{
9bcb3eef 11729 struct bgp_dest *rn, *rm;
54317cba
JW
11730 const struct bgp_table *table;
11731 struct peer_pcounts *pc = THREAD_ARG(t);
11732
11733 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
11734 || pc->safi == SAFI_EVPN) {
11735 /* Special handling for 2-level routing tables. */
11736 for (rn = bgp_table_top(pc->table); rn;
11737 rn = bgp_route_next(rn)) {
9bcb3eef 11738 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
11739 if (table != NULL)
11740 for (rm = bgp_table_top(table); rm;
11741 rm = bgp_route_next(rm))
11742 bgp_peer_count_proc(rm, pc);
11743 }
11744 } else
11745 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
11746 bgp_peer_count_proc(rn, pc);
11747
d62a17ae 11748 return 0;
718e3744 11749}
11750
d62a17ae 11751static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 11752 safi_t safi, bool use_json)
856ca177 11753{
d62a17ae 11754 struct peer_pcounts pcounts = {.peer = peer};
11755 unsigned int i;
11756 json_object *json = NULL;
11757 json_object *json_loop = NULL;
856ca177 11758
d62a17ae 11759 if (use_json) {
11760 json = json_object_new_object();
11761 json_loop = json_object_new_object();
11762 }
718e3744 11763
d62a17ae 11764 if (!peer || !peer->bgp || !peer->afc[afi][safi]
11765 || !peer->bgp->rib[afi][safi]) {
11766 if (use_json) {
11767 json_object_string_add(
11768 json, "warning",
11769 "No such neighbor or address family");
11770 vty_out(vty, "%s\n", json_object_to_json_string(json));
11771 json_object_free(json);
11772 } else
11773 vty_out(vty, "%% No such neighbor or address family\n");
11774
11775 return CMD_WARNING;
11776 }
2a71e9ce 11777
d62a17ae 11778 memset(&pcounts, 0, sizeof(pcounts));
11779 pcounts.peer = peer;
11780 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 11781 pcounts.safi = safi;
d62a17ae 11782
11783 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
11784 * stats for the thread-walk (i.e. ensure this can't be blamed on
11785 * on just vty_read()).
11786 */
d62a17ae 11787 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
11788
11789 if (use_json) {
11790 json_object_string_add(json, "prefixCountsFor", peer->host);
11791 json_object_string_add(json, "multiProtocol",
5cb5f4d0 11792 get_afi_safi_str(afi, safi, true));
d62a17ae 11793 json_object_int_add(json, "pfxCounter",
11794 peer->pcount[afi][safi]);
11795
11796 for (i = 0; i < PCOUNT_MAX; i++)
11797 json_object_int_add(json_loop, pcount_strs[i],
11798 pcounts.count[i]);
11799
11800 json_object_object_add(json, "ribTableWalkCounters", json_loop);
11801
11802 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
11803 json_object_string_add(json, "pfxctDriftFor",
11804 peer->host);
11805 json_object_string_add(
11806 json, "recommended",
11807 "Please report this bug, with the above command output");
11808 }
996c9314
LB
11809 vty_out(vty, "%s\n", json_object_to_json_string_ext(
11810 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 11811 json_object_free(json);
11812 } else {
11813
11814 if (peer->hostname
892fedb6 11815 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 11816 vty_out(vty, "Prefix counts for %s/%s, %s\n",
11817 peer->hostname, peer->host,
5cb5f4d0 11818 get_afi_safi_str(afi, safi, false));
d62a17ae 11819 } else {
11820 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 11821 get_afi_safi_str(afi, safi, false));
d62a17ae 11822 }
11823
6cde4b45 11824 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 11825 vty_out(vty, "\nCounts from RIB table walk:\n\n");
11826
11827 for (i = 0; i < PCOUNT_MAX; i++)
11828 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
11829 pcounts.count[i]);
11830
11831 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
11832 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
11833 vty_out(vty,
11834 "Please report this bug, with the above command output\n");
11835 }
11836 }
11837
11838 return CMD_SUCCESS;
718e3744 11839}
11840
a636c635
DW
11841DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
11842 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 11843 "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 11844 SHOW_STR
11845 IP_STR
11846 BGP_STR
8386ac43 11847 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
11848 BGP_AFI_HELP_STR
11849 BGP_SAFI_HELP_STR
0b16f239
DS
11850 "Detailed information on TCP and BGP neighbor connections\n"
11851 "Neighbor to display information about\n"
11852 "Neighbor to display information about\n"
91d37724 11853 "Neighbor on BGP configured interface\n"
a636c635 11854 "Display detailed prefix count information\n"
9973d184 11855 JSON_STR)
0b16f239 11856{
d62a17ae 11857 afi_t afi = AFI_IP6;
11858 safi_t safi = SAFI_UNICAST;
11859 struct peer *peer;
11860 int idx = 0;
11861 struct bgp *bgp = NULL;
9f049418
DS
11862 bool uj = use_json(argc, argv);
11863
11864 if (uj)
11865 argc--;
856ca177 11866
d62a17ae 11867 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11868 &bgp, uj);
d62a17ae 11869 if (!idx)
11870 return CMD_WARNING;
0b16f239 11871
d62a17ae 11872 argv_find(argv, argc, "neighbors", &idx);
11873 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
11874 if (!peer)
11875 return CMD_WARNING;
bb46e94f 11876
29c8d9da 11877 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 11878}
0b16f239 11879
d6902373
PG
11880#ifdef KEEP_OLD_VPN_COMMANDS
11881DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
11882 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
11883 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
11884 SHOW_STR
11885 IP_STR
11886 BGP_STR
d6902373 11887 BGP_VPNVX_HELP_STR
91d37724 11888 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
11889 "Detailed information on TCP and BGP neighbor connections\n"
11890 "Neighbor to display information about\n"
11891 "Neighbor to display information about\n"
91d37724 11892 "Neighbor on BGP configured interface\n"
a636c635 11893 "Display detailed prefix count information\n"
9973d184 11894 JSON_STR)
a636c635 11895{
d62a17ae 11896 int idx_peer = 6;
11897 struct peer *peer;
9f049418 11898 bool uj = use_json(argc, argv);
a636c635 11899
d62a17ae 11900 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
11901 if (!peer)
11902 return CMD_WARNING;
11903
11904 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
11905}
11906
d6902373
PG
11907DEFUN (show_ip_bgp_vpn_all_route_prefix,
11908 show_ip_bgp_vpn_all_route_prefix_cmd,
11909 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
11910 SHOW_STR
11911 IP_STR
11912 BGP_STR
d6902373 11913 BGP_VPNVX_HELP_STR
91d37724
QY
11914 "Display information about all VPNv4 NLRIs\n"
11915 "Network in the BGP routing table to display\n"
3a2d747c 11916 "Network in the BGP routing table to display\n"
9973d184 11917 JSON_STR)
91d37724 11918{
d62a17ae 11919 int idx = 0;
11920 char *network = NULL;
11921 struct bgp *bgp = bgp_get_default();
11922 if (!bgp) {
11923 vty_out(vty, "Can't find default instance\n");
11924 return CMD_WARNING;
11925 }
87e34b58 11926
d62a17ae 11927 if (argv_find(argv, argc, "A.B.C.D", &idx))
11928 network = argv[idx]->arg;
11929 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
11930 network = argv[idx]->arg;
11931 else {
11932 vty_out(vty, "Unable to figure out Network\n");
11933 return CMD_WARNING;
11934 }
87e34b58 11935
d62a17ae 11936 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 11937 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 11938}
d6902373 11939#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 11940
44c69747
LK
11941DEFUN (show_bgp_l2vpn_evpn_route_prefix,
11942 show_bgp_l2vpn_evpn_route_prefix_cmd,
11943 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 11944 SHOW_STR
4c63a661
PG
11945 BGP_STR
11946 L2VPN_HELP_STR
11947 EVPN_HELP_STR
44c69747
LK
11948 "Network in the BGP routing table to display\n"
11949 "Network in the BGP routing table to display\n"
4c63a661
PG
11950 "Network in the BGP routing table to display\n"
11951 "Network in the BGP routing table to display\n"
11952 JSON_STR)
11953{
d62a17ae 11954 int idx = 0;
11955 char *network = NULL;
44c69747 11956 int prefix_check = 0;
a636c635 11957
44c69747
LK
11958 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
11959 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 11960 network = argv[idx]->arg;
44c69747 11961 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 11962 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 11963 network = argv[idx]->arg;
44c69747
LK
11964 prefix_check = 1;
11965 } else {
d62a17ae 11966 vty_out(vty, "Unable to figure out Network\n");
11967 return CMD_WARNING;
11968 }
44c69747
LK
11969 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
11970 prefix_check, BGP_PATH_SHOW_ALL,
11971 use_json(argc, argv));
d62a17ae 11972}
11973
11974static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 11975 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 11976 const char *rmap_name, bool use_json,
ae248832 11977 json_object *json, bool wide)
d62a17ae 11978{
11979 struct bgp_table *table;
11980 struct bgp_adj_in *ain;
11981 struct bgp_adj_out *adj;
74a630b6
NT
11982 unsigned long output_count = 0;
11983 unsigned long filtered_count = 0;
9bcb3eef 11984 struct bgp_dest *dest;
d62a17ae 11985 int header1 = 1;
11986 struct bgp *bgp;
11987 int header2 = 1;
11988 struct attr attr;
11989 int ret;
11990 struct update_subgroup *subgrp;
11991 json_object *json_scode = NULL;
11992 json_object *json_ocode = NULL;
11993 json_object *json_ar = NULL;
11994 struct peer_af *paf;
f99def61 11995 bool route_filtered;
d62a17ae 11996
11997 if (use_json) {
11998 json_scode = json_object_new_object();
11999 json_ocode = json_object_new_object();
12000 json_ar = json_object_new_object();
12001
12002 json_object_string_add(json_scode, "suppressed", "s");
12003 json_object_string_add(json_scode, "damped", "d");
12004 json_object_string_add(json_scode, "history", "h");
12005 json_object_string_add(json_scode, "valid", "*");
12006 json_object_string_add(json_scode, "best", ">");
12007 json_object_string_add(json_scode, "multipath", "=");
12008 json_object_string_add(json_scode, "internal", "i");
12009 json_object_string_add(json_scode, "ribFailure", "r");
12010 json_object_string_add(json_scode, "stale", "S");
12011 json_object_string_add(json_scode, "removed", "R");
12012
12013 json_object_string_add(json_ocode, "igp", "i");
12014 json_object_string_add(json_ocode, "egp", "e");
12015 json_object_string_add(json_ocode, "incomplete", "?");
12016 }
a636c635 12017
d62a17ae 12018 bgp = peer->bgp;
a636c635 12019
d62a17ae 12020 if (!bgp) {
12021 if (use_json) {
12022 json_object_string_add(json, "alert", "no BGP");
12023 vty_out(vty, "%s\n", json_object_to_json_string(json));
12024 json_object_free(json);
12025 } else
12026 vty_out(vty, "%% No bgp\n");
12027 return;
12028 }
a636c635 12029
c512a642
EDP
12030 /* labeled-unicast routes live in the unicast table */
12031 if (safi == SAFI_LABELED_UNICAST)
12032 table = bgp->rib[afi][SAFI_UNICAST];
12033 else
12034 table = bgp->rib[afi][safi];
d62a17ae 12035
12036 output_count = filtered_count = 0;
12037 subgrp = peer_subgroup(peer, afi, safi);
12038
6392aaa6 12039 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 12040 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
12041 if (use_json) {
12042 json_object_int_add(json, "bgpTableVersion",
12043 table->version);
12044 json_object_string_add(json, "bgpLocalRouterId",
12045 inet_ntoa(bgp->router_id));
01eced22
AD
12046 json_object_int_add(json, "defaultLocPrf",
12047 bgp->default_local_pref);
12048 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 12049 json_object_object_add(json, "bgpStatusCodes",
12050 json_scode);
12051 json_object_object_add(json, "bgpOriginCodes",
12052 json_ocode);
07d0c4ed
DA
12053 json_object_string_add(
12054 json, "bgpOriginatingDefaultNetwork",
12055 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 12056 } else {
6cde4b45 12057 vty_out(vty, "BGP table version is %" PRIu64", local router ID is %s, vrf id ",
d62a17ae 12058 table->version, inet_ntoa(bgp->router_id));
9df8b37c
PZ
12059 if (bgp->vrf_id == VRF_UNKNOWN)
12060 vty_out(vty, "%s", VRFID_NONE_STR);
12061 else
12062 vty_out(vty, "%u", bgp->vrf_id);
12063 vty_out(vty, "\n");
01eced22
AD
12064 vty_out(vty, "Default local pref %u, ",
12065 bgp->default_local_pref);
12066 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 12067 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 12068 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 12069 vty_out(vty, BGP_SHOW_OCODE_HEADER);
12070
07d0c4ed
DA
12071 vty_out(vty, "Originating default network %s\n\n",
12072 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 12073 }
12074 header1 = 0;
12075 }
a636c635 12076
9bcb3eef 12077 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
12078 if (type == bgp_show_adj_route_received
12079 || type == bgp_show_adj_route_filtered) {
9bcb3eef 12080 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 12081 if (ain->peer != peer)
ea47320b 12082 continue;
6392aaa6 12083
ea47320b
DL
12084 if (header1) {
12085 if (use_json) {
12086 json_object_int_add(
60466a63 12087 json, "bgpTableVersion",
ea47320b
DL
12088 0);
12089 json_object_string_add(
12090 json,
12091 "bgpLocalRouterId",
12092 inet_ntoa(
12093 bgp->router_id));
01eced22
AD
12094 json_object_int_add(json,
12095 "defaultLocPrf",
12096 bgp->default_local_pref);
12097 json_object_int_add(json,
12098 "localAS", bgp->as);
ea47320b 12099 json_object_object_add(
60466a63 12100 json, "bgpStatusCodes",
ea47320b
DL
12101 json_scode);
12102 json_object_object_add(
60466a63 12103 json, "bgpOriginCodes",
ea47320b
DL
12104 json_ocode);
12105 } else {
12106 vty_out(vty,
9df8b37c 12107 "BGP table version is 0, local router ID is %s, vrf id ",
ea47320b 12108 inet_ntoa(
9df8b37c
PZ
12109 bgp->router_id));
12110 if (bgp->vrf_id == VRF_UNKNOWN)
12111 vty_out(vty, "%s",
12112 VRFID_NONE_STR);
12113 else
12114 vty_out(vty, "%u",
12115 bgp->vrf_id);
12116 vty_out(vty, "\n");
01eced22
AD
12117 vty_out(vty,
12118 "Default local pref %u, ",
12119 bgp->default_local_pref);
12120 vty_out(vty, "local AS %u\n",
12121 bgp->as);
ea47320b
DL
12122 vty_out(vty,
12123 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
12124 vty_out(vty,
12125 BGP_SHOW_NCODE_HEADER);
ea47320b
DL
12126 vty_out(vty,
12127 BGP_SHOW_OCODE_HEADER);
d62a17ae 12128 }
ea47320b
DL
12129 header1 = 0;
12130 }
12131 if (header2) {
12132 if (!use_json)
ae248832
MK
12133 vty_out(vty,
12134 (wide ? BGP_SHOW_HEADER_WIDE
12135 : BGP_SHOW_HEADER));
ea47320b
DL
12136 header2 = 0;
12137 }
6392aaa6 12138
6f4f49b2 12139 attr = *ain->attr;
f99def61
AD
12140 route_filtered = false;
12141
12142 /* Filter prefix using distribute list,
12143 * filter list or prefix list
12144 */
b54892e0 12145 const struct prefix *rn_p =
9bcb3eef 12146 bgp_dest_get_prefix(dest);
b54892e0
DS
12147 if ((bgp_input_filter(peer, rn_p, &attr, afi,
12148 safi))
12149 == FILTER_DENY)
f99def61
AD
12150 route_filtered = true;
12151
12152 /* Filter prefix using route-map */
b54892e0
DS
12153 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
12154 safi, rmap_name, NULL,
12155 0, NULL);
6392aaa6 12156
13c8e163
AD
12157 if (type == bgp_show_adj_route_filtered &&
12158 !route_filtered && ret != RMAP_DENY) {
b755861b 12159 bgp_attr_undup(&attr, ain->attr);
6392aaa6 12160 continue;
d62a17ae 12161 }
6392aaa6 12162
13c8e163
AD
12163 if (type == bgp_show_adj_route_received &&
12164 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
12165 filtered_count++;
12166
b54892e0 12167 route_vty_out_tmp(vty, rn_p, &attr, safi,
ae248832 12168 use_json, json_ar, wide);
b755861b 12169 bgp_attr_undup(&attr, ain->attr);
6392aaa6 12170 output_count++;
d62a17ae 12171 }
6392aaa6 12172 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 12173 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 12174 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 12175 if (paf->peer != peer || !adj->attr)
924c3f6a 12176 continue;
d62a17ae 12177
924c3f6a
DS
12178 if (header1) {
12179 if (use_json) {
12180 json_object_int_add(
12181 json,
12182 "bgpTableVersion",
12183 table->version);
12184 json_object_string_add(
12185 json,
12186 "bgpLocalRouterId",
12187 inet_ntoa(
12188 bgp->router_id));
01eced22
AD
12189 json_object_int_add(
12190 json, "defaultLocPrf",
12191 bgp->default_local_pref
12192 );
12193 json_object_int_add(
12194 json, "localAS",
12195 bgp->as);
924c3f6a
DS
12196 json_object_object_add(
12197 json,
12198 "bgpStatusCodes",
12199 json_scode);
12200 json_object_object_add(
12201 json,
12202 "bgpOriginCodes",
12203 json_ocode);
12204 } else {
12205 vty_out(vty,
6cde4b45 12206 "BGP table version is %" PRIu64", local router ID is %s, vrf id ",
924c3f6a
DS
12207 table->version,
12208 inet_ntoa(
12209 bgp->router_id));
9df8b37c
PZ
12210 if (bgp->vrf_id ==
12211 VRF_UNKNOWN)
12212 vty_out(vty,
12213 "%s",
12214 VRFID_NONE_STR);
12215 else
12216 vty_out(vty,
12217 "%u",
12218 bgp->vrf_id);
12219 vty_out(vty, "\n");
01eced22
AD
12220 vty_out(vty,
12221 "Default local pref %u, ",
12222 bgp->default_local_pref
12223 );
12224 vty_out(vty,
12225 "local AS %u\n",
12226 bgp->as);
924c3f6a
DS
12227 vty_out(vty,
12228 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
12229 vty_out(vty,
12230 BGP_SHOW_NCODE_HEADER);
924c3f6a
DS
12231 vty_out(vty,
12232 BGP_SHOW_OCODE_HEADER);
a2addae8 12233 }
924c3f6a
DS
12234 header1 = 0;
12235 }
924c3f6a
DS
12236 if (header2) {
12237 if (!use_json)
12238 vty_out(vty,
ae248832
MK
12239 (wide ? BGP_SHOW_HEADER_WIDE
12240 : BGP_SHOW_HEADER));
924c3f6a
DS
12241 header2 = 0;
12242 }
d62a17ae 12243
b54892e0 12244 const struct prefix *rn_p =
9bcb3eef 12245 bgp_dest_get_prefix(dest);
b54892e0 12246
6f4f49b2 12247 attr = *adj->attr;
b755861b 12248 ret = bgp_output_modifier(
b54892e0 12249 peer, rn_p, &attr, afi, safi,
b755861b 12250 rmap_name);
f46d8e1e 12251
b755861b 12252 if (ret != RMAP_DENY) {
b54892e0
DS
12253 route_vty_out_tmp(
12254 vty, rn_p, &attr, safi,
ae248832
MK
12255 use_json, json_ar,
12256 wide);
b755861b
PM
12257 output_count++;
12258 } else {
12259 filtered_count++;
a2addae8 12260 }
b755861b
PM
12261
12262 bgp_attr_undup(&attr, adj->attr);
924c3f6a 12263 }
d62a17ae 12264 }
12265 }
d62a17ae 12266
d62a17ae 12267 if (use_json) {
6392aaa6
PM
12268 json_object_object_add(json, "advertisedRoutes", json_ar);
12269 json_object_int_add(json, "totalPrefixCounter", output_count);
12270 json_object_int_add(json, "filteredPrefixCounter",
12271 filtered_count);
12272
996c9314
LB
12273 vty_out(vty, "%s\n", json_object_to_json_string_ext(
12274 json, JSON_C_TO_STRING_PRETTY));
74a630b6
NT
12275
12276 if (!output_count && !filtered_count) {
12277 json_object_free(json_scode);
12278 json_object_free(json_ocode);
12279 }
12280
d62a17ae 12281 json_object_free(json);
6392aaa6
PM
12282 } else if (output_count > 0) {
12283 if (filtered_count > 0)
12284 vty_out(vty,
12285 "\nTotal number of prefixes %ld (%ld filtered)\n",
12286 output_count, filtered_count);
12287 else
12288 vty_out(vty, "\nTotal number of prefixes %ld\n",
12289 output_count);
d62a17ae 12290 }
a636c635 12291}
2a71e9ce 12292
d62a17ae 12293static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 12294 safi_t safi, enum bgp_show_adj_route_type type,
ae248832 12295 const char *rmap_name, bool use_json, bool wide)
0b16f239 12296{
d62a17ae 12297 json_object *json = NULL;
0b16f239 12298
d62a17ae 12299 if (use_json)
12300 json = json_object_new_object();
0b16f239 12301
d62a17ae 12302 if (!peer || !peer->afc[afi][safi]) {
12303 if (use_json) {
12304 json_object_string_add(
12305 json, "warning",
12306 "No such neighbor or address family");
12307 vty_out(vty, "%s\n", json_object_to_json_string(json));
12308 json_object_free(json);
12309 } else
12310 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 12311
d62a17ae 12312 return CMD_WARNING;
12313 }
12314
6392aaa6
PM
12315 if ((type == bgp_show_adj_route_received
12316 || type == bgp_show_adj_route_filtered)
d62a17ae 12317 && !CHECK_FLAG(peer->af_flags[afi][safi],
12318 PEER_FLAG_SOFT_RECONFIG)) {
12319 if (use_json) {
12320 json_object_string_add(
12321 json, "warning",
12322 "Inbound soft reconfiguration not enabled");
12323 vty_out(vty, "%s\n", json_object_to_json_string(json));
12324 json_object_free(json);
12325 } else
12326 vty_out(vty,
12327 "%% Inbound soft reconfiguration not enabled\n");
12328
12329 return CMD_WARNING;
12330 }
0b16f239 12331
ae248832
MK
12332 show_adj_route(vty, peer, afi, safi, type, rmap_name, use_json, json,
12333 wide);
0b16f239 12334
d62a17ae 12335 return CMD_SUCCESS;
a636c635 12336}
50ef26d4 12337
ae248832 12338DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 12339 show_ip_bgp_instance_neighbor_advertised_route_cmd,
ae248832 12340 "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$uj | wide$wide]",
718e3744 12341 SHOW_STR
12342 IP_STR
12343 BGP_STR
a636c635 12344 BGP_INSTANCE_HELP_STR
7395a2c9 12345 BGP_AFI_HELP_STR
4dd6177e 12346 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 12347 "Detailed information on TCP and BGP neighbor connections\n"
12348 "Neighbor to display information about\n"
12349 "Neighbor to display information about\n"
91d37724 12350 "Neighbor on BGP configured interface\n"
a636c635 12351 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
12352 "Display the received routes from neighbor\n"
12353 "Display the filtered routes received from neighbor\n"
a636c635
DW
12354 "Route-map to modify the attributes\n"
12355 "Name of the route map\n"
ae248832
MK
12356 JSON_STR
12357 "Increase table width for longer prefixes\n")
718e3744 12358{
d62a17ae 12359 afi_t afi = AFI_IP6;
12360 safi_t safi = SAFI_UNICAST;
12361 char *rmap_name = NULL;
12362 char *peerstr = NULL;
d62a17ae 12363 struct bgp *bgp = NULL;
12364 struct peer *peer;
6392aaa6 12365 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 12366 int idx = 0;
6392aaa6 12367
d62a17ae 12368 if (uj)
12369 argc--;
30a6a167 12370
9f049418
DS
12371 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12372 &bgp, uj);
12373 if (!idx)
12374 return CMD_WARNING;
12375
d62a17ae 12376 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12377 argv_find(argv, argc, "neighbors", &idx);
12378 peerstr = argv[++idx]->arg;
8c3deaae 12379
d62a17ae 12380 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
12381 if (!peer)
12382 return CMD_WARNING;
856ca177 12383
d62a17ae 12384 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
12385 type = bgp_show_adj_route_advertised;
12386 else if (argv_find(argv, argc, "received-routes", &idx))
12387 type = bgp_show_adj_route_received;
12388 else if (argv_find(argv, argc, "filtered-routes", &idx))
12389 type = bgp_show_adj_route_filtered;
12390
d62a17ae 12391 if (argv_find(argv, argc, "route-map", &idx))
12392 rmap_name = argv[++idx]->arg;
95cbbd2a 12393
ae248832 12394 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj, wide);
95cbbd2a
ML
12395}
12396
718e3744 12397DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
12398 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 12399 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 12400 SHOW_STR
12401 IP_STR
12402 BGP_STR
8c3deaae
QY
12403 "Address Family\n"
12404 "Address Family\n"
718e3744 12405 "Address Family modifier\n"
12406 "Detailed information on TCP and BGP neighbor connections\n"
12407 "Neighbor to display information about\n"
12408 "Neighbor to display information about\n"
91d37724 12409 "Neighbor on BGP configured interface\n"
718e3744 12410 "Display information received from a BGP neighbor\n"
856ca177 12411 "Display the prefixlist filter\n"
9973d184 12412 JSON_STR)
718e3744 12413{
d62a17ae 12414 afi_t afi = AFI_IP6;
12415 safi_t safi = SAFI_UNICAST;
12416 char *peerstr = NULL;
12417
12418 char name[BUFSIZ];
12419 union sockunion su;
12420 struct peer *peer;
12421 int count, ret;
12422
12423 int idx = 0;
12424
12425 /* show [ip] bgp */
12426 if (argv_find(argv, argc, "ip", &idx))
12427 afi = AFI_IP;
12428 /* [<ipv4|ipv6> [unicast]] */
12429 if (argv_find(argv, argc, "ipv4", &idx))
12430 afi = AFI_IP;
12431 if (argv_find(argv, argc, "ipv6", &idx))
12432 afi = AFI_IP6;
12433 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12434 argv_find(argv, argc, "neighbors", &idx);
12435 peerstr = argv[++idx]->arg;
12436
9f049418 12437 bool uj = use_json(argc, argv);
d62a17ae 12438
12439 ret = str2sockunion(peerstr, &su);
12440 if (ret < 0) {
12441 peer = peer_lookup_by_conf_if(NULL, peerstr);
12442 if (!peer) {
12443 if (uj)
12444 vty_out(vty, "{}\n");
12445 else
12446 vty_out(vty,
12447 "%% Malformed address or name: %s\n",
12448 peerstr);
12449 return CMD_WARNING;
12450 }
12451 } else {
12452 peer = peer_lookup(NULL, &su);
12453 if (!peer) {
12454 if (uj)
12455 vty_out(vty, "{}\n");
12456 else
12457 vty_out(vty, "No peer\n");
12458 return CMD_WARNING;
12459 }
12460 }
718e3744 12461
4ced1a2c 12462 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 12463 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
12464 if (count) {
12465 if (!uj)
12466 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 12467 get_afi_safi_str(afi, safi, false));
d62a17ae 12468 prefix_bgp_show_prefix_list(vty, afi, name, uj);
12469 } else {
12470 if (uj)
12471 vty_out(vty, "{}\n");
12472 else
12473 vty_out(vty, "No functional output\n");
12474 }
718e3744 12475
d62a17ae 12476 return CMD_SUCCESS;
12477}
12478
12479static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
12480 afi_t afi, safi_t safi,
9f049418 12481 enum bgp_show_type type, bool use_json)
d62a17ae 12482{
8a893163
DW
12483 /* labeled-unicast routes live in the unicast table */
12484 if (safi == SAFI_LABELED_UNICAST)
12485 safi = SAFI_UNICAST;
12486
d62a17ae 12487 if (!peer || !peer->afc[afi][safi]) {
12488 if (use_json) {
12489 json_object *json_no = NULL;
12490 json_no = json_object_new_object();
12491 json_object_string_add(
12492 json_no, "warning",
12493 "No such neighbor or address family");
12494 vty_out(vty, "%s\n",
12495 json_object_to_json_string(json_no));
12496 json_object_free(json_no);
12497 } else
12498 vty_out(vty, "%% No such neighbor or address family\n");
12499 return CMD_WARNING;
12500 }
47fc97cc 12501
ae248832
MK
12502 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json,
12503 false);
718e3744 12504}
12505
dba3c1d3
PG
12506DEFUN (show_ip_bgp_flowspec_routes_detailed,
12507 show_ip_bgp_flowspec_routes_detailed_cmd,
12508 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
12509 SHOW_STR
12510 IP_STR
12511 BGP_STR
12512 BGP_INSTANCE_HELP_STR
12513 BGP_AFI_HELP_STR
12514 "SAFI Flowspec\n"
12515 "Detailed information on flowspec entries\n"
12516 JSON_STR)
12517{
12518 afi_t afi = AFI_IP;
12519 safi_t safi = SAFI_UNICAST;
12520 struct bgp *bgp = NULL;
12521 int idx = 0;
9f049418
DS
12522 bool uj = use_json(argc, argv);
12523
12524 if (uj)
12525 argc--;
dba3c1d3
PG
12526
12527 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12528 &bgp, uj);
dba3c1d3
PG
12529 if (!idx)
12530 return CMD_WARNING;
12531
ae248832
MK
12532 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL, uj,
12533 false);
dba3c1d3
PG
12534}
12535
718e3744 12536DEFUN (show_ip_bgp_neighbor_routes,
12537 show_ip_bgp_neighbor_routes_cmd,
3efd0893 12538 "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 12539 SHOW_STR
12540 IP_STR
12541 BGP_STR
8386ac43 12542 BGP_INSTANCE_HELP_STR
4f280b15 12543 BGP_AFI_HELP_STR
4dd6177e 12544 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 12545 "Detailed information on TCP and BGP neighbor connections\n"
12546 "Neighbor to display information about\n"
12547 "Neighbor to display information about\n"
91d37724 12548 "Neighbor on BGP configured interface\n"
2525cf39 12549 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
12550 "Display the dampened routes received from neighbor\n"
12551 "Display routes learned from neighbor\n"
9973d184 12552 JSON_STR)
718e3744 12553{
d62a17ae 12554 char *peerstr = NULL;
12555 struct bgp *bgp = NULL;
12556 afi_t afi = AFI_IP6;
12557 safi_t safi = SAFI_UNICAST;
12558 struct peer *peer;
12559 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 12560 int idx = 0;
9f049418
DS
12561 bool uj = use_json(argc, argv);
12562
12563 if (uj)
12564 argc--;
bb46e94f 12565
d62a17ae 12566 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12567 &bgp, uj);
d62a17ae 12568 if (!idx)
12569 return CMD_WARNING;
c493f2d8 12570
d62a17ae 12571 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12572 argv_find(argv, argc, "neighbors", &idx);
12573 peerstr = argv[++idx]->arg;
8c3deaae 12574
d62a17ae 12575 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 12576 if (!peer)
d62a17ae 12577 return CMD_WARNING;
bb46e94f 12578
d62a17ae 12579 if (argv_find(argv, argc, "flap-statistics", &idx))
12580 sh_type = bgp_show_type_flap_neighbor;
12581 else if (argv_find(argv, argc, "dampened-routes", &idx))
12582 sh_type = bgp_show_type_damp_neighbor;
12583 else if (argv_find(argv, argc, "routes", &idx))
12584 sh_type = bgp_show_type_neighbor;
2525cf39 12585
d62a17ae 12586 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 12587}
6b0655a2 12588
734b349e 12589struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 12590
d62a17ae 12591struct bgp_distance {
12592 /* Distance value for the IP source prefix. */
d7c0a89a 12593 uint8_t distance;
718e3744 12594
d62a17ae 12595 /* Name of the access-list to be matched. */
12596 char *access_list;
718e3744 12597};
12598
4f280b15
LB
12599DEFUN (show_bgp_afi_vpn_rd_route,
12600 show_bgp_afi_vpn_rd_route_cmd,
d114b977 12601 "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
12602 SHOW_STR
12603 BGP_STR
12604 BGP_AFI_HELP_STR
12605 "Address Family modifier\n"
12606 "Display information for a route distinguisher\n"
12607 "Route Distinguisher\n"
7395a2c9
DS
12608 "Network in the BGP routing table to display\n"
12609 "Network in the BGP routing table to display\n"
12610 JSON_STR)
4f280b15 12611{
d62a17ae 12612 int ret;
12613 struct prefix_rd prd;
12614 afi_t afi = AFI_MAX;
12615 int idx = 0;
4f280b15 12616
ff6566f3
DS
12617 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
12618 vty_out(vty, "%% Malformed Address Family\n");
12619 return CMD_WARNING;
12620 }
12621
d62a17ae 12622 ret = str2prefix_rd(argv[5]->arg, &prd);
12623 if (!ret) {
12624 vty_out(vty, "%% Malformed Route Distinguisher\n");
12625 return CMD_WARNING;
12626 }
ff6566f3 12627
d62a17ae 12628 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 12629 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
12630}
12631
d62a17ae 12632static struct bgp_distance *bgp_distance_new(void)
718e3744 12633{
d62a17ae 12634 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 12635}
12636
d62a17ae 12637static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 12638{
d62a17ae 12639 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 12640}
12641
d62a17ae 12642static int bgp_distance_set(struct vty *vty, const char *distance_str,
12643 const char *ip_str, const char *access_list_str)
718e3744 12644{
d62a17ae 12645 int ret;
12646 afi_t afi;
12647 safi_t safi;
12648 struct prefix p;
d7c0a89a 12649 uint8_t distance;
9bcb3eef 12650 struct bgp_dest *dest;
d62a17ae 12651 struct bgp_distance *bdistance;
718e3744 12652
d62a17ae 12653 afi = bgp_node_afi(vty);
12654 safi = bgp_node_safi(vty);
734b349e 12655
d62a17ae 12656 ret = str2prefix(ip_str, &p);
12657 if (ret == 0) {
12658 vty_out(vty, "Malformed prefix\n");
12659 return CMD_WARNING_CONFIG_FAILED;
12660 }
718e3744 12661
d62a17ae 12662 distance = atoi(distance_str);
718e3744 12663
d62a17ae 12664 /* Get BGP distance node. */
9bcb3eef
DS
12665 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
12666 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 12667 if (bdistance)
9bcb3eef 12668 bgp_dest_unlock_node(dest);
ca2e160d 12669 else {
d62a17ae 12670 bdistance = bgp_distance_new();
9bcb3eef 12671 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 12672 }
718e3744 12673
d62a17ae 12674 /* Set distance value. */
12675 bdistance->distance = distance;
718e3744 12676
d62a17ae 12677 /* Reset access-list configuration. */
e1b36e13 12678 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 12679 if (access_list_str)
12680 bdistance->access_list =
12681 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 12682
d62a17ae 12683 return CMD_SUCCESS;
718e3744 12684}
12685
d62a17ae 12686static int bgp_distance_unset(struct vty *vty, const char *distance_str,
12687 const char *ip_str, const char *access_list_str)
718e3744 12688{
d62a17ae 12689 int ret;
12690 afi_t afi;
12691 safi_t safi;
12692 struct prefix p;
12693 int distance;
9bcb3eef 12694 struct bgp_dest *dest;
d62a17ae 12695 struct bgp_distance *bdistance;
718e3744 12696
d62a17ae 12697 afi = bgp_node_afi(vty);
12698 safi = bgp_node_safi(vty);
734b349e 12699
d62a17ae 12700 ret = str2prefix(ip_str, &p);
12701 if (ret == 0) {
12702 vty_out(vty, "Malformed prefix\n");
12703 return CMD_WARNING_CONFIG_FAILED;
12704 }
718e3744 12705
9bcb3eef
DS
12706 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
12707 if (!dest) {
d62a17ae 12708 vty_out(vty, "Can't find specified prefix\n");
12709 return CMD_WARNING_CONFIG_FAILED;
12710 }
718e3744 12711
9bcb3eef 12712 bdistance = bgp_dest_get_bgp_distance_info(dest);
d62a17ae 12713 distance = atoi(distance_str);
1f9a9fff 12714
d62a17ae 12715 if (bdistance->distance != distance) {
12716 vty_out(vty, "Distance does not match configured\n");
12717 return CMD_WARNING_CONFIG_FAILED;
12718 }
718e3744 12719
0a22ddfb 12720 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 12721 bgp_distance_free(bdistance);
718e3744 12722
9bcb3eef
DS
12723 bgp_dest_set_bgp_path_info(dest, NULL);
12724 bgp_dest_unlock_node(dest);
12725 bgp_dest_unlock_node(dest);
718e3744 12726
d62a17ae 12727 return CMD_SUCCESS;
718e3744 12728}
12729
718e3744 12730/* Apply BGP information to distance method. */
b8685f9b 12731uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 12732 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 12733{
9bcb3eef 12734 struct bgp_dest *dest;
d62a17ae 12735 struct prefix q;
12736 struct peer *peer;
12737 struct bgp_distance *bdistance;
12738 struct access_list *alist;
12739 struct bgp_static *bgp_static;
12740
12741 if (!bgp)
12742 return 0;
12743
40381db7 12744 peer = pinfo->peer;
d62a17ae 12745
7b7d48e5
DS
12746 if (pinfo->attr->distance)
12747 return pinfo->attr->distance;
12748
d62a17ae 12749 /* Check source address. */
12750 sockunion2hostprefix(&peer->su, &q);
9bcb3eef
DS
12751 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
12752 if (dest) {
12753 bdistance = bgp_dest_get_bgp_distance_info(dest);
12754 bgp_dest_unlock_node(dest);
d62a17ae 12755
12756 if (bdistance->access_list) {
12757 alist = access_list_lookup(afi, bdistance->access_list);
12758 if (alist
12759 && access_list_apply(alist, p) == FILTER_PERMIT)
12760 return bdistance->distance;
12761 } else
12762 return bdistance->distance;
718e3744 12763 }
718e3744 12764
d62a17ae 12765 /* Backdoor check. */
9bcb3eef
DS
12766 dest = bgp_node_lookup(bgp->route[afi][safi], p);
12767 if (dest) {
12768 bgp_static = bgp_dest_get_bgp_static_info(dest);
12769 bgp_dest_unlock_node(dest);
718e3744 12770
d62a17ae 12771 if (bgp_static->backdoor) {
12772 if (bgp->distance_local[afi][safi])
12773 return bgp->distance_local[afi][safi];
12774 else
12775 return ZEBRA_IBGP_DISTANCE_DEFAULT;
12776 }
718e3744 12777 }
718e3744 12778
d62a17ae 12779 if (peer->sort == BGP_PEER_EBGP) {
12780 if (bgp->distance_ebgp[afi][safi])
12781 return bgp->distance_ebgp[afi][safi];
12782 return ZEBRA_EBGP_DISTANCE_DEFAULT;
12783 } else {
12784 if (bgp->distance_ibgp[afi][safi])
12785 return bgp->distance_ibgp[afi][safi];
12786 return ZEBRA_IBGP_DISTANCE_DEFAULT;
12787 }
718e3744 12788}
12789
a612fb77
DA
12790/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
12791 * we should tell ZEBRA update the routes for a specific
12792 * AFI/SAFI to reflect changes in RIB.
12793 */
8b54bc30
DA
12794static void bgp_announce_routes_distance_update(struct bgp *bgp,
12795 afi_t update_afi,
12796 safi_t update_safi)
a612fb77
DA
12797{
12798 afi_t afi;
12799 safi_t safi;
12800
12801 FOREACH_AFI_SAFI (afi, safi) {
12802 if (!bgp_fibupd_safi(safi))
12803 continue;
12804
8b54bc30
DA
12805 if (afi != update_afi && safi != update_safi)
12806 continue;
12807
12808 if (BGP_DEBUG(zebra, ZEBRA))
12809 zlog_debug(
12810 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
12811 __func__, afi, safi);
12812 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
12813 }
12814}
12815
718e3744 12816DEFUN (bgp_distance,
12817 bgp_distance_cmd,
6147e2c6 12818 "distance bgp (1-255) (1-255) (1-255)",
718e3744 12819 "Define an administrative distance\n"
12820 "BGP distance\n"
12821 "Distance for routes external to the AS\n"
12822 "Distance for routes internal to the AS\n"
12823 "Distance for local routes\n")
12824{
d62a17ae 12825 VTY_DECLVAR_CONTEXT(bgp, bgp);
12826 int idx_number = 2;
12827 int idx_number_2 = 3;
12828 int idx_number_3 = 4;
8b54bc30
DA
12829 int distance_ebgp = atoi(argv[idx_number]->arg);
12830 int distance_ibgp = atoi(argv[idx_number_2]->arg);
12831 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 12832 afi_t afi;
12833 safi_t safi;
718e3744 12834
d62a17ae 12835 afi = bgp_node_afi(vty);
12836 safi = bgp_node_safi(vty);
718e3744 12837
8b54bc30
DA
12838 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
12839 || bgp->distance_ibgp[afi][safi] != distance_ibgp
12840 || bgp->distance_local[afi][safi] != distance_local) {
12841 bgp->distance_ebgp[afi][safi] = distance_ebgp;
12842 bgp->distance_ibgp[afi][safi] = distance_ibgp;
12843 bgp->distance_local[afi][safi] = distance_local;
12844 bgp_announce_routes_distance_update(bgp, afi, safi);
12845 }
d62a17ae 12846 return CMD_SUCCESS;
718e3744 12847}
12848
12849DEFUN (no_bgp_distance,
12850 no_bgp_distance_cmd,
a636c635 12851 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 12852 NO_STR
12853 "Define an administrative distance\n"
12854 "BGP distance\n"
12855 "Distance for routes external to the AS\n"
12856 "Distance for routes internal to the AS\n"
12857 "Distance for local routes\n")
12858{
d62a17ae 12859 VTY_DECLVAR_CONTEXT(bgp, bgp);
12860 afi_t afi;
12861 safi_t safi;
718e3744 12862
d62a17ae 12863 afi = bgp_node_afi(vty);
12864 safi = bgp_node_safi(vty);
718e3744 12865
8b54bc30
DA
12866 if (bgp->distance_ebgp[afi][safi] != 0
12867 || bgp->distance_ibgp[afi][safi] != 0
12868 || bgp->distance_local[afi][safi] != 0) {
12869 bgp->distance_ebgp[afi][safi] = 0;
12870 bgp->distance_ibgp[afi][safi] = 0;
12871 bgp->distance_local[afi][safi] = 0;
12872 bgp_announce_routes_distance_update(bgp, afi, safi);
12873 }
d62a17ae 12874 return CMD_SUCCESS;
718e3744 12875}
12876
718e3744 12877
12878DEFUN (bgp_distance_source,
12879 bgp_distance_source_cmd,
6147e2c6 12880 "distance (1-255) A.B.C.D/M",
718e3744 12881 "Define an administrative distance\n"
12882 "Administrative distance\n"
12883 "IP source prefix\n")
12884{
d62a17ae 12885 int idx_number = 1;
12886 int idx_ipv4_prefixlen = 2;
12887 bgp_distance_set(vty, argv[idx_number]->arg,
12888 argv[idx_ipv4_prefixlen]->arg, NULL);
12889 return CMD_SUCCESS;
718e3744 12890}
12891
12892DEFUN (no_bgp_distance_source,
12893 no_bgp_distance_source_cmd,
6147e2c6 12894 "no distance (1-255) A.B.C.D/M",
718e3744 12895 NO_STR
12896 "Define an administrative distance\n"
12897 "Administrative distance\n"
12898 "IP source prefix\n")
12899{
d62a17ae 12900 int idx_number = 2;
12901 int idx_ipv4_prefixlen = 3;
12902 bgp_distance_unset(vty, argv[idx_number]->arg,
12903 argv[idx_ipv4_prefixlen]->arg, NULL);
12904 return CMD_SUCCESS;
718e3744 12905}
12906
12907DEFUN (bgp_distance_source_access_list,
12908 bgp_distance_source_access_list_cmd,
6147e2c6 12909 "distance (1-255) A.B.C.D/M WORD",
718e3744 12910 "Define an administrative distance\n"
12911 "Administrative distance\n"
12912 "IP source prefix\n"
12913 "Access list name\n")
12914{
d62a17ae 12915 int idx_number = 1;
12916 int idx_ipv4_prefixlen = 2;
12917 int idx_word = 3;
12918 bgp_distance_set(vty, argv[idx_number]->arg,
12919 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12920 return CMD_SUCCESS;
718e3744 12921}
12922
12923DEFUN (no_bgp_distance_source_access_list,
12924 no_bgp_distance_source_access_list_cmd,
6147e2c6 12925 "no distance (1-255) A.B.C.D/M WORD",
718e3744 12926 NO_STR
12927 "Define an administrative distance\n"
12928 "Administrative distance\n"
12929 "IP source prefix\n"
12930 "Access list name\n")
12931{
d62a17ae 12932 int idx_number = 2;
12933 int idx_ipv4_prefixlen = 3;
12934 int idx_word = 4;
12935 bgp_distance_unset(vty, argv[idx_number]->arg,
12936 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12937 return CMD_SUCCESS;
718e3744 12938}
6b0655a2 12939
734b349e
MZ
12940DEFUN (ipv6_bgp_distance_source,
12941 ipv6_bgp_distance_source_cmd,
39e92c06 12942 "distance (1-255) X:X::X:X/M",
734b349e
MZ
12943 "Define an administrative distance\n"
12944 "Administrative distance\n"
12945 "IP source prefix\n")
12946{
d62a17ae 12947 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
12948 return CMD_SUCCESS;
734b349e
MZ
12949}
12950
12951DEFUN (no_ipv6_bgp_distance_source,
12952 no_ipv6_bgp_distance_source_cmd,
39e92c06 12953 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
12954 NO_STR
12955 "Define an administrative distance\n"
12956 "Administrative distance\n"
12957 "IP source prefix\n")
12958{
d62a17ae 12959 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
12960 return CMD_SUCCESS;
734b349e
MZ
12961}
12962
12963DEFUN (ipv6_bgp_distance_source_access_list,
12964 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12965 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12966 "Define an administrative distance\n"
12967 "Administrative distance\n"
12968 "IP source prefix\n"
12969 "Access list name\n")
12970{
d62a17ae 12971 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
12972 return CMD_SUCCESS;
734b349e
MZ
12973}
12974
12975DEFUN (no_ipv6_bgp_distance_source_access_list,
12976 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12977 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12978 NO_STR
12979 "Define an administrative distance\n"
12980 "Administrative distance\n"
12981 "IP source prefix\n"
12982 "Access list name\n")
12983{
d62a17ae 12984 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
12985 return CMD_SUCCESS;
734b349e
MZ
12986}
12987
718e3744 12988DEFUN (bgp_damp_set,
12989 bgp_damp_set_cmd,
31500417 12990 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 12991 "BGP Specific commands\n"
12992 "Enable route-flap dampening\n"
12993 "Half-life time for the penalty\n"
12994 "Value to start reusing a route\n"
12995 "Value to start suppressing a route\n"
12996 "Maximum duration to suppress a stable route\n")
12997{
d62a17ae 12998 VTY_DECLVAR_CONTEXT(bgp, bgp);
12999 int idx_half_life = 2;
13000 int idx_reuse = 3;
13001 int idx_suppress = 4;
13002 int idx_max_suppress = 5;
13003 int half = DEFAULT_HALF_LIFE * 60;
13004 int reuse = DEFAULT_REUSE;
13005 int suppress = DEFAULT_SUPPRESS;
13006 int max = 4 * half;
13007
13008 if (argc == 6) {
13009 half = atoi(argv[idx_half_life]->arg) * 60;
13010 reuse = atoi(argv[idx_reuse]->arg);
13011 suppress = atoi(argv[idx_suppress]->arg);
13012 max = atoi(argv[idx_max_suppress]->arg) * 60;
13013 } else if (argc == 3) {
13014 half = atoi(argv[idx_half_life]->arg) * 60;
13015 max = 4 * half;
13016 }
718e3744 13017
6d24b7cc
DS
13018 /*
13019 * These can't be 0 but our SA doesn't understand the
13020 * way our cli is constructed
13021 */
13022 assert(reuse);
13023 assert(half);
d62a17ae 13024 if (suppress < reuse) {
13025 vty_out(vty,
13026 "Suppress value cannot be less than reuse value \n");
13027 return 0;
13028 }
7ebe9748 13029
d62a17ae 13030 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
13031 reuse, suppress, max);
718e3744 13032}
13033
718e3744 13034DEFUN (bgp_damp_unset,
13035 bgp_damp_unset_cmd,
d04c479d 13036 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 13037 NO_STR
13038 "BGP Specific commands\n"
16cedbb0
QY
13039 "Enable route-flap dampening\n"
13040 "Half-life time for the penalty\n"
13041 "Value to start reusing a route\n"
13042 "Value to start suppressing a route\n"
13043 "Maximum duration to suppress a stable route\n")
718e3744 13044{
d62a17ae 13045 VTY_DECLVAR_CONTEXT(bgp, bgp);
13046 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 13047}
13048
718e3744 13049/* Display specified route of BGP table. */
d62a17ae 13050static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
13051 const char *ip_str, afi_t afi, safi_t safi,
13052 struct prefix_rd *prd, int prefix_check)
13053{
13054 int ret;
13055 struct prefix match;
9bcb3eef
DS
13056 struct bgp_dest *dest;
13057 struct bgp_dest *rm;
40381db7
DS
13058 struct bgp_path_info *pi;
13059 struct bgp_path_info *pi_temp;
d62a17ae 13060 struct bgp *bgp;
13061 struct bgp_table *table;
13062
13063 /* BGP structure lookup. */
13064 if (view_name) {
13065 bgp = bgp_lookup_by_name(view_name);
13066 if (bgp == NULL) {
13067 vty_out(vty, "%% Can't find BGP instance %s\n",
13068 view_name);
13069 return CMD_WARNING;
13070 }
13071 } else {
13072 bgp = bgp_get_default();
13073 if (bgp == NULL) {
13074 vty_out(vty, "%% No BGP process is configured\n");
13075 return CMD_WARNING;
13076 }
718e3744 13077 }
718e3744 13078
d62a17ae 13079 /* Check IP address argument. */
13080 ret = str2prefix(ip_str, &match);
13081 if (!ret) {
13082 vty_out(vty, "%% address is malformed\n");
13083 return CMD_WARNING;
13084 }
718e3744 13085
d62a17ae 13086 match.family = afi2family(afi);
13087
13088 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13089 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
13090 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
13091 dest = bgp_route_next(dest)) {
13092 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 13093
9bcb3eef 13094 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 13095 continue;
9bcb3eef 13096 table = bgp_dest_get_bgp_table_info(dest);
67009e22 13097 if (!table)
ea47320b
DL
13098 continue;
13099 if ((rm = bgp_node_match(table, &match)) == NULL)
13100 continue;
d62a17ae 13101
9bcb3eef 13102 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 13103
ea47320b 13104 if (!prefix_check
b54892e0 13105 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 13106 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
13107 while (pi) {
13108 if (pi->extra && pi->extra->damp_info) {
13109 pi_temp = pi->next;
ea47320b 13110 bgp_damp_info_free(
40381db7 13111 pi->extra->damp_info,
a935f597 13112 1, afi, safi);
40381db7 13113 pi = pi_temp;
ea47320b 13114 } else
40381db7 13115 pi = pi->next;
d62a17ae 13116 }
ea47320b
DL
13117 }
13118
9bcb3eef 13119 bgp_dest_unlock_node(rm);
d62a17ae 13120 }
13121 } else {
9bcb3eef 13122 if ((dest = bgp_node_match(bgp->rib[afi][safi], &match))
d62a17ae 13123 != NULL) {
9bcb3eef 13124 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 13125
d62a17ae 13126 if (!prefix_check
9bcb3eef
DS
13127 || dest_p->prefixlen == match.prefixlen) {
13128 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
13129 while (pi) {
13130 if (pi->extra && pi->extra->damp_info) {
13131 pi_temp = pi->next;
d62a17ae 13132 bgp_damp_info_free(
40381db7 13133 pi->extra->damp_info,
a935f597 13134 1, afi, safi);
40381db7 13135 pi = pi_temp;
d62a17ae 13136 } else
40381db7 13137 pi = pi->next;
d62a17ae 13138 }
13139 }
13140
9bcb3eef 13141 bgp_dest_unlock_node(dest);
d62a17ae 13142 }
13143 }
718e3744 13144
d62a17ae 13145 return CMD_SUCCESS;
718e3744 13146}
13147
13148DEFUN (clear_ip_bgp_dampening,
13149 clear_ip_bgp_dampening_cmd,
13150 "clear ip bgp dampening",
13151 CLEAR_STR
13152 IP_STR
13153 BGP_STR
13154 "Clear route flap dampening information\n")
13155{
a935f597 13156 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 13157 return CMD_SUCCESS;
718e3744 13158}
13159
13160DEFUN (clear_ip_bgp_dampening_prefix,
13161 clear_ip_bgp_dampening_prefix_cmd,
13162 "clear ip bgp dampening A.B.C.D/M",
13163 CLEAR_STR
13164 IP_STR
13165 BGP_STR
13166 "Clear route flap dampening information\n"
0c7b1b01 13167 "IPv4 prefix\n")
718e3744 13168{
d62a17ae 13169 int idx_ipv4_prefixlen = 4;
13170 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
13171 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 13172}
13173
13174DEFUN (clear_ip_bgp_dampening_address,
13175 clear_ip_bgp_dampening_address_cmd,
13176 "clear ip bgp dampening A.B.C.D",
13177 CLEAR_STR
13178 IP_STR
13179 BGP_STR
13180 "Clear route flap dampening information\n"
13181 "Network to clear damping information\n")
13182{
d62a17ae 13183 int idx_ipv4 = 4;
13184 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
13185 SAFI_UNICAST, NULL, 0);
718e3744 13186}
13187
13188DEFUN (clear_ip_bgp_dampening_address_mask,
13189 clear_ip_bgp_dampening_address_mask_cmd,
13190 "clear ip bgp dampening A.B.C.D A.B.C.D",
13191 CLEAR_STR
13192 IP_STR
13193 BGP_STR
13194 "Clear route flap dampening information\n"
13195 "Network to clear damping information\n"
13196 "Network mask\n")
13197{
d62a17ae 13198 int idx_ipv4 = 4;
13199 int idx_ipv4_2 = 5;
13200 int ret;
13201 char prefix_str[BUFSIZ];
718e3744 13202
d62a17ae 13203 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
13204 prefix_str);
13205 if (!ret) {
13206 vty_out(vty, "%% Inconsistent address and mask\n");
13207 return CMD_WARNING;
13208 }
718e3744 13209
d62a17ae 13210 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
13211 NULL, 0);
718e3744 13212}
6b0655a2 13213
e3b78da8 13214static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
13215{
13216 struct vty *vty = arg;
e3b78da8 13217 struct peer *peer = bucket->data;
825d9834
DS
13218 char buf[SU_ADDRSTRLEN];
13219
13220 vty_out(vty, "\tPeer: %s %s\n", peer->host,
13221 sockunion2str(&peer->su, buf, sizeof(buf)));
13222}
13223
2a0e69ae
DS
13224DEFUN (show_bgp_listeners,
13225 show_bgp_listeners_cmd,
13226 "show bgp listeners",
13227 SHOW_STR
13228 BGP_STR
13229 "Display Listen Sockets and who created them\n")
13230{
13231 bgp_dump_listener_info(vty);
13232
13233 return CMD_SUCCESS;
13234}
13235
825d9834
DS
13236DEFUN (show_bgp_peerhash,
13237 show_bgp_peerhash_cmd,
13238 "show bgp peerhash",
13239 SHOW_STR
13240 BGP_STR
13241 "Display information about the BGP peerhash\n")
13242{
13243 struct list *instances = bm->bgp;
13244 struct listnode *node;
13245 struct bgp *bgp;
13246
13247 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
13248 vty_out(vty, "BGP: %s\n", bgp->name);
13249 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
13250 vty);
13251 }
13252
13253 return CMD_SUCCESS;
13254}
13255
587ff0fd 13256/* also used for encap safi */
2b791107
DL
13257static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
13258 afi_t afi, safi_t safi)
d62a17ae 13259{
9bcb3eef
DS
13260 struct bgp_dest *pdest;
13261 struct bgp_dest *dest;
d62a17ae 13262 struct bgp_table *table;
b54892e0
DS
13263 const struct prefix *p;
13264 const struct prefix_rd *prd;
d62a17ae 13265 struct bgp_static *bgp_static;
13266 mpls_label_t label;
13267 char buf[SU_ADDRSTRLEN];
13268 char rdbuf[RD_ADDRSTRLEN];
13269
13270 /* Network configuration. */
9bcb3eef
DS
13271 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
13272 pdest = bgp_route_next(pdest)) {
13273 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 13274 if (!table)
ea47320b 13275 continue;
d62a17ae 13276
9bcb3eef
DS
13277 for (dest = bgp_table_top(table); dest;
13278 dest = bgp_route_next(dest)) {
13279 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 13280 if (bgp_static == NULL)
ea47320b 13281 continue;
d62a17ae 13282
9bcb3eef
DS
13283 p = bgp_dest_get_prefix(dest);
13284 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13285 pdest);
d62a17ae 13286
ea47320b 13287 /* "network" configuration display. */
06b9f471 13288 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
13289 label = decode_label(&bgp_static->label);
13290
13291 vty_out(vty, " network %s/%d rd %s",
13292 inet_ntop(p->family, &p->u.prefix, buf,
13293 SU_ADDRSTRLEN),
13294 p->prefixlen, rdbuf);
13295 if (safi == SAFI_MPLS_VPN)
13296 vty_out(vty, " label %u", label);
13297
13298 if (bgp_static->rmap.name)
13299 vty_out(vty, " route-map %s",
13300 bgp_static->rmap.name);
e2a86ad9
DS
13301
13302 if (bgp_static->backdoor)
13303 vty_out(vty, " backdoor");
13304
ea47320b
DL
13305 vty_out(vty, "\n");
13306 }
13307 }
d62a17ae 13308}
13309
2b791107
DL
13310static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
13311 afi_t afi, safi_t safi)
d62a17ae 13312{
9bcb3eef
DS
13313 struct bgp_dest *pdest;
13314 struct bgp_dest *dest;
d62a17ae 13315 struct bgp_table *table;
b54892e0
DS
13316 const struct prefix *p;
13317 const struct prefix_rd *prd;
d62a17ae 13318 struct bgp_static *bgp_static;
ff44f570 13319 char buf[PREFIX_STRLEN * 2];
d62a17ae 13320 char buf2[SU_ADDRSTRLEN];
13321 char rdbuf[RD_ADDRSTRLEN];
13322
13323 /* Network configuration. */
9bcb3eef
DS
13324 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
13325 pdest = bgp_route_next(pdest)) {
13326 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 13327 if (!table)
ea47320b 13328 continue;
d62a17ae 13329
9bcb3eef
DS
13330 for (dest = bgp_table_top(table); dest;
13331 dest = bgp_route_next(dest)) {
13332 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 13333 if (bgp_static == NULL)
ea47320b 13334 continue;
d62a17ae 13335
ea47320b
DL
13336 char *macrouter = NULL;
13337 char *esi = NULL;
d62a17ae 13338
ea47320b
DL
13339 if (bgp_static->router_mac)
13340 macrouter = prefix_mac2str(
13341 bgp_static->router_mac, NULL, 0);
13342 if (bgp_static->eth_s_id)
13343 esi = esi2str(bgp_static->eth_s_id);
9bcb3eef
DS
13344 p = bgp_dest_get_prefix(dest);
13345 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 13346
ea47320b 13347 /* "network" configuration display. */
06b9f471 13348 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
13349 if (p->u.prefix_evpn.route_type == 5) {
13350 char local_buf[PREFIX_STRLEN];
3714a385 13351 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
13352 struct prefix_evpn *)p)
13353 ? AF_INET
13354 : AF_INET6;
3714a385 13355 inet_ntop(family,
13356 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 13357 local_buf, PREFIX_STRLEN);
772270f3
QY
13358 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
13359 p->u.prefix_evpn.prefix_addr
13360 .ip_prefix_length);
197cb530
PG
13361 } else {
13362 prefix2str(p, buf, sizeof(buf));
13363 }
ea47320b 13364
a4d82a8a
PZ
13365 if (bgp_static->gatewayIp.family == AF_INET
13366 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
13367 inet_ntop(bgp_static->gatewayIp.family,
13368 &bgp_static->gatewayIp.u.prefix, buf2,
13369 sizeof(buf2));
ea47320b 13370 vty_out(vty,
7bcc8dac 13371 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 13372 buf, rdbuf,
13373 p->u.prefix_evpn.prefix_addr.eth_tag,
60466a63 13374 decode_label(&bgp_static->label), esi, buf2,
ea47320b
DL
13375 macrouter);
13376
0a22ddfb
QY
13377 XFREE(MTYPE_TMP, macrouter);
13378 XFREE(MTYPE_TMP, esi);
ea47320b
DL
13379 }
13380 }
3da6fcd5
PG
13381}
13382
718e3744 13383/* Configuration of static route announcement and aggregate
13384 information. */
2b791107
DL
13385void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
13386 safi_t safi)
d62a17ae 13387{
9bcb3eef 13388 struct bgp_dest *dest;
b54892e0 13389 const struct prefix *p;
d62a17ae 13390 struct bgp_static *bgp_static;
13391 struct bgp_aggregate *bgp_aggregate;
13392 char buf[SU_ADDRSTRLEN];
13393
2b791107
DL
13394 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
13395 bgp_config_write_network_vpn(vty, bgp, afi, safi);
13396 return;
13397 }
d62a17ae 13398
2b791107
DL
13399 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
13400 bgp_config_write_network_evpn(vty, bgp, afi, safi);
13401 return;
13402 }
d62a17ae 13403
13404 /* Network configuration. */
9bcb3eef
DS
13405 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
13406 dest = bgp_route_next(dest)) {
13407 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 13408 if (bgp_static == NULL)
ea47320b 13409 continue;
d62a17ae 13410
9bcb3eef 13411 p = bgp_dest_get_prefix(dest);
d62a17ae 13412
d8a9922d
DS
13413 vty_out(vty, " network %s/%d",
13414 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
13415 p->prefixlen);
d62a17ae 13416
ea47320b
DL
13417 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
13418 vty_out(vty, " label-index %u",
13419 bgp_static->label_index);
d62a17ae 13420
ea47320b
DL
13421 if (bgp_static->rmap.name)
13422 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
13423
13424 if (bgp_static->backdoor)
13425 vty_out(vty, " backdoor");
718e3744 13426
ea47320b
DL
13427 vty_out(vty, "\n");
13428 }
13429
d62a17ae 13430 /* Aggregate-address configuration. */
9bcb3eef
DS
13431 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
13432 dest = bgp_route_next(dest)) {
13433 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 13434 if (bgp_aggregate == NULL)
ea47320b 13435 continue;
d62a17ae 13436
9bcb3eef 13437 p = bgp_dest_get_prefix(dest);
d62a17ae 13438
d8a9922d
DS
13439 vty_out(vty, " aggregate-address %s/%d",
13440 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
13441 p->prefixlen);
d62a17ae 13442
ea47320b
DL
13443 if (bgp_aggregate->as_set)
13444 vty_out(vty, " as-set");
d62a17ae 13445
ea47320b
DL
13446 if (bgp_aggregate->summary_only)
13447 vty_out(vty, " summary-only");
718e3744 13448
20894f50
DA
13449 if (bgp_aggregate->rmap.name)
13450 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
13451
229757f1
DA
13452 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
13453 vty_out(vty, " origin %s",
13454 bgp_origin2str(bgp_aggregate->origin));
13455
ea47320b
DL
13456 vty_out(vty, "\n");
13457 }
d62a17ae 13458}
734b349e 13459
2b791107 13460void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 13461 safi_t safi)
d62a17ae 13462{
9bcb3eef 13463 struct bgp_dest *dest;
d62a17ae 13464 struct bgp_distance *bdistance;
13465
13466 /* Distance configuration. */
13467 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
13468 && bgp->distance_local[afi][safi]
13469 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
13470 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
13471 || bgp->distance_local[afi][safi]
13472 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 13473 vty_out(vty, " distance bgp %d %d %d\n",
13474 bgp->distance_ebgp[afi][safi],
13475 bgp->distance_ibgp[afi][safi],
13476 bgp->distance_local[afi][safi]);
13477 }
734b349e 13478
9bcb3eef
DS
13479 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
13480 dest = bgp_route_next(dest)) {
13481 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0
DS
13482 if (bdistance != NULL)
13483 vty_out(vty, " distance %d %pRN %s\n",
9bcb3eef 13484 bdistance->distance, dest,
d62a17ae 13485 bdistance->access_list ? bdistance->access_list
13486 : "");
ca2e160d 13487 }
718e3744 13488}
13489
13490/* Allocate routing table structure and install commands. */
d62a17ae 13491void bgp_route_init(void)
13492{
13493 afi_t afi;
13494 safi_t safi;
13495
13496 /* Init BGP distance table. */
05c7a1cc 13497 FOREACH_AFI_SAFI (afi, safi)
960035b2 13498 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 13499
13500 /* IPv4 BGP commands. */
13501 install_element(BGP_NODE, &bgp_table_map_cmd);
13502 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 13503 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 13504
13505 install_element(BGP_NODE, &aggregate_address_cmd);
13506 install_element(BGP_NODE, &aggregate_address_mask_cmd);
13507 install_element(BGP_NODE, &no_aggregate_address_cmd);
13508 install_element(BGP_NODE, &no_aggregate_address_mask_cmd);
13509
13510 /* IPv4 unicast configuration. */
13511 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
13512 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 13513 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 13514
13515 install_element(BGP_IPV4_NODE, &aggregate_address_cmd);
13516 install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd);
13517 install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd);
13518 install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
13519
13520 /* IPv4 multicast configuration. */
13521 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
13522 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 13523 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
d62a17ae 13524 install_element(BGP_IPV4M_NODE, &aggregate_address_cmd);
13525 install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
13526 install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd);
13527 install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
13528
13529 /* IPv4 labeled-unicast configuration. */
fb985e0c
DA
13530 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
13531 install_element(BGP_IPV4L_NODE, &aggregate_address_cmd);
13532 install_element(BGP_IPV4L_NODE, &aggregate_address_mask_cmd);
13533 install_element(BGP_IPV4L_NODE, &no_aggregate_address_cmd);
13534 install_element(BGP_IPV4L_NODE, &no_aggregate_address_mask_cmd);
13535
d62a17ae 13536 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
13537 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 13538 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 13539 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 13540 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 13541 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
13542 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 13543 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 13544
13545 install_element(VIEW_NODE,
13546 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
13547 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
13548 install_element(VIEW_NODE,
13549 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 13550#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 13551 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 13552#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 13553 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
13554 install_element(VIEW_NODE,
44c69747 13555 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 13556
d62a17ae 13557 /* BGP dampening clear commands */
13558 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
13559 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 13560
d62a17ae 13561 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
13562 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
13563
13564 /* prefix count */
13565 install_element(ENABLE_NODE,
13566 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 13567#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 13568 install_element(ENABLE_NODE,
13569 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 13570#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 13571
d62a17ae 13572 /* New config IPv6 BGP commands. */
13573 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
13574 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 13575 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 13576
13577 install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
13578 install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
13579
13580 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 13581
fb985e0c
DA
13582 /* IPv6 labeled unicast address family. */
13583 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
13584 install_element(BGP_IPV6L_NODE, &ipv6_aggregate_address_cmd);
13585 install_element(BGP_IPV6L_NODE, &no_ipv6_aggregate_address_cmd);
13586
d62a17ae 13587 install_element(BGP_NODE, &bgp_distance_cmd);
13588 install_element(BGP_NODE, &no_bgp_distance_cmd);
13589 install_element(BGP_NODE, &bgp_distance_source_cmd);
13590 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
13591 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
13592 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
13593 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
13594 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
13595 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
13596 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
13597 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
13598 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
13599 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
13600 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
13601 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
13602 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
13603 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
13604 install_element(BGP_IPV4M_NODE,
13605 &no_bgp_distance_source_access_list_cmd);
13606 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
13607 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
13608 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
13609 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
13610 install_element(BGP_IPV6_NODE,
13611 &ipv6_bgp_distance_source_access_list_cmd);
13612 install_element(BGP_IPV6_NODE,
13613 &no_ipv6_bgp_distance_source_access_list_cmd);
13614 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
13615 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
13616 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
13617 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
13618 install_element(BGP_IPV6M_NODE,
13619 &ipv6_bgp_distance_source_access_list_cmd);
13620 install_element(BGP_IPV6M_NODE,
13621 &no_ipv6_bgp_distance_source_access_list_cmd);
13622
ef5f4b23 13623 /* BGP dampening */
d62a17ae 13624 install_element(BGP_NODE, &bgp_damp_set_cmd);
13625 install_element(BGP_NODE, &bgp_damp_unset_cmd);
13626 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
13627 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
d62a17ae 13628 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
13629 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
ef5f4b23
DA
13630 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
13631 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
13632 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
13633 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
13634 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
13635 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
13636 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
13637 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 13638
13639 /* Large Communities */
13640 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
13641 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
13642
13643 /* show bgp ipv4 flowspec detailed */
13644 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
13645
2a0e69ae 13646 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 13647 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 13648}
13649
13650void bgp_route_finish(void)
13651{
13652 afi_t afi;
13653 safi_t safi;
13654
05c7a1cc
QY
13655 FOREACH_AFI_SAFI (afi, safi) {
13656 bgp_table_unlock(bgp_distance_table[afi][safi]);
13657 bgp_distance_table[afi][safi] = NULL;
13658 }
228da428 13659}