]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #7412 from donaldsharp/ospf6_stuff
[mirror_frr.git] / bgpd / bgp_route.c
CommitLineData
718e3744 1/* BGP routing information
896014f4
DL
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
718e3744 21
22#include <zebra.h>
8d0ab76d 23#include <math.h>
718e3744 24
2618a52e 25#include "printfrr.h"
718e3744 26#include "prefix.h"
27#include "linklist.h"
28#include "memory.h"
29#include "command.h"
30#include "stream.h"
31#include "filter.h"
718e3744 32#include "log.h"
33#include "routemap.h"
34#include "buffer.h"
35#include "sockunion.h"
36#include "plist.h"
37#include "thread.h"
200df115 38#include "workqueue.h"
3f9c7369 39#include "queue.h"
6e919709 40#include "memory.h"
e496b420 41#include "srv6.h"
4dcadbef 42#include "lib/json.h"
d8d084d9 43#include "lib_errors.h"
8c48b3b6 44#include "zclient.h"
718e3744 45#include "bgpd/bgpd.h"
46#include "bgpd/bgp_table.h"
47#include "bgpd/bgp_route.h"
48#include "bgpd/bgp_attr.h"
49#include "bgpd/bgp_debug.h"
14454c9f 50#include "bgpd/bgp_errors.h"
718e3744 51#include "bgpd/bgp_aspath.h"
52#include "bgpd/bgp_regex.h"
53#include "bgpd/bgp_community.h"
54#include "bgpd/bgp_ecommunity.h"
57d187bc 55#include "bgpd/bgp_lcommunity.h"
718e3744 56#include "bgpd/bgp_clist.h"
57#include "bgpd/bgp_packet.h"
58#include "bgpd/bgp_filter.h"
59#include "bgpd/bgp_fsm.h"
60#include "bgpd/bgp_mplsvpn.h"
61#include "bgpd/bgp_nexthop.h"
62#include "bgpd/bgp_damp.h"
63#include "bgpd/bgp_advertise.h"
64#include "bgpd/bgp_zebra.h"
0a486e5f 65#include "bgpd/bgp_vty.h"
96450faf 66#include "bgpd/bgp_mpath.h"
fc9a856f 67#include "bgpd/bgp_nht.h"
3f9c7369 68#include "bgpd/bgp_updgrp.h"
cd1964ff 69#include "bgpd/bgp_label.h"
dcc68b5e 70#include "bgpd/bgp_addpath.h"
4e802e66 71#include "bgpd/bgp_mac.h"
2a0e69ae 72#include "bgpd/bgp_network.h"
6401252f 73#include "bgpd/bgp_trace.h"
718e3744 74
49e5a4a0 75#ifdef ENABLE_BGP_VNC
f8b6f499
LB
76#include "bgpd/rfapi/rfapi_backend.h"
77#include "bgpd/rfapi/vnc_import_bgp.h"
78#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 79#endif
aee875b5
PG
80#include "bgpd/bgp_encap_types.h"
81#include "bgpd/bgp_encap_tlv.h"
684a7227 82#include "bgpd/bgp_evpn.h"
0a50c248 83#include "bgpd/bgp_evpn_mh.h"
3da6fcd5 84#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 85#include "bgpd/bgp_flowspec.h"
98a9dbc7 86#include "bgpd/bgp_flowspec_util.h"
45918cfb 87#include "bgpd/bgp_pbr.h"
37a87b8f
CS
88#include "northbound.h"
89#include "northbound_cli.h"
90#include "bgpd/bgp_nb.h"
65efcfce 91
e2a86ad9
DS
92#ifndef VTYSH_EXTRACT_PL
93#include "bgpd/bgp_route_clippy.c"
94#endif
aee875b5 95
718e3744 96/* Extern from bgp_dump.c */
dde72586
SH
97extern const char *bgp_origin_str[];
98extern const char *bgp_origin_long_str[];
36235319 99const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json);
b7d08f5a 100/* PMSI strings. */
101#define PMSI_TNLTYPE_STR_NO_INFO "No info"
102#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
103static const struct message bgp_pmsi_tnltype_str[] = {
104 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
105 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
106 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
107 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
108 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
109 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
110 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
111 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 112 {0}
113};
b7d08f5a 114
9df8b37c
PZ
115#define VRFID_NONE_STR "-"
116
4a11bf2c 117DEFINE_HOOK(bgp_process,
9bcb3eef
DS
118 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
119 struct peer *peer, bool withdraw),
120 (bgp, afi, safi, bn, peer, withdraw))
4a11bf2c 121
4056a5f6
RZ
122/** Test if path is suppressed. */
123static bool bgp_path_suppressed(struct bgp_path_info *pi)
124{
125 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
126 return false;
127
128 return listcount(pi->extra->aggr_suppressors) > 0;
129}
4a11bf2c 130
9bcb3eef 131struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 132 safi_t safi, const struct prefix *p,
d62a17ae 133 struct prefix_rd *prd)
134{
9bcb3eef
DS
135 struct bgp_dest *dest;
136 struct bgp_dest *pdest = NULL;
d62a17ae 137
138 assert(table);
d62a17ae 139
140 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
141 || (safi == SAFI_EVPN)) {
9bcb3eef 142 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 143
9bcb3eef
DS
144 if (!bgp_dest_has_bgp_path_info_data(pdest))
145 bgp_dest_set_bgp_table_info(
146 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 147 else
9bcb3eef
DS
148 bgp_dest_unlock_node(pdest);
149 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 150 }
718e3744 151
9bcb3eef 152 dest = bgp_node_get(table, p);
718e3744 153
d62a17ae 154 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
155 || (safi == SAFI_EVPN))
9bcb3eef 156 dest->pdest = pdest;
718e3744 157
9bcb3eef 158 return dest;
718e3744 159}
6b0655a2 160
9bcb3eef 161struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 162 safi_t safi, const struct prefix *p,
d62a17ae 163 struct prefix_rd *prd)
128ea8ab 164{
9bcb3eef
DS
165 struct bgp_dest *dest;
166 struct bgp_dest *pdest = NULL;
128ea8ab 167
d62a17ae 168 if (!table)
169 return NULL;
128ea8ab 170
d62a17ae 171 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
172 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
173 pdest = bgp_node_lookup(table, (struct prefix *)prd);
174 if (!pdest)
d62a17ae 175 return NULL;
128ea8ab 176
9bcb3eef
DS
177 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
178 bgp_dest_unlock_node(pdest);
d62a17ae 179 return NULL;
180 }
128ea8ab 181
9bcb3eef 182 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 183 }
128ea8ab 184
9bcb3eef 185 dest = bgp_node_lookup(table, p);
128ea8ab 186
9bcb3eef 187 return dest;
128ea8ab 188}
189
18ee8310
DS
190/* Allocate bgp_path_info_extra */
191static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 192{
4b7e6066
DS
193 struct bgp_path_info_extra *new;
194 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
195 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
196 new->label[0] = MPLS_INVALID_LABEL;
197 new->num_labels = 0;
3e3708cb
PG
198 new->bgp_fs_pbr = NULL;
199 new->bgp_fs_iprule = NULL;
d62a17ae 200 return new;
fb982c25
PJ
201}
202
a2e219fe 203void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 204{
4b7e6066 205 struct bgp_path_info_extra *e;
d62a17ae 206
c93a3b77
DS
207 if (!extra || !*extra)
208 return;
d62a17ae 209
c93a3b77
DS
210 e = *extra;
211 if (e->damp_info)
a935f597
DA
212 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
213 e->damp_info->safi);
d62a17ae 214
c93a3b77
DS
215 e->damp_info = NULL;
216 if (e->parent) {
40381db7 217 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 218
40381db7 219 if (bpi->net) {
0e70e6c8
DL
220 /* FIXME: since multiple e may have the same e->parent
221 * and e->parent->net is holding a refcount for each
222 * of them, we need to do some fudging here.
223 *
40381db7
DS
224 * WARNING: if bpi->net->lock drops to 0, bpi may be
225 * freed as well (because bpi->net was holding the
226 * last reference to bpi) => write after free!
0e70e6c8
DL
227 */
228 unsigned refcount;
229
40381db7 230 bpi = bgp_path_info_lock(bpi);
c10e14e9 231 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 232 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 233 if (!refcount)
40381db7
DS
234 bpi->net = NULL;
235 bgp_path_info_unlock(bpi);
0e70e6c8 236 }
18ee8310 237 bgp_path_info_unlock(e->parent);
c93a3b77 238 e->parent = NULL;
d62a17ae 239 }
c93a3b77
DS
240
241 if (e->bgp_orig)
242 bgp_unlock(e->bgp_orig);
c26edcda 243
ce3c0614
PG
244 if ((*extra)->bgp_fs_iprule)
245 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 246 if ((*extra)->bgp_fs_pbr)
6a154c88 247 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 248 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
249}
250
18ee8310
DS
251/* Get bgp_path_info extra information for the given bgp_path_info, lazy
252 * allocated if required.
fb982c25 253 */
40381db7 254struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 255{
40381db7
DS
256 if (!pi->extra)
257 pi->extra = bgp_path_info_extra_new();
258 return pi->extra;
fb982c25
PJ
259}
260
718e3744 261/* Free bgp route information. */
9b6d8fcf 262static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 263{
05864da7 264 bgp_attr_unintern(&path->attr);
fb018d25 265
9b6d8fcf
DS
266 bgp_unlink_nexthop(path);
267 bgp_path_info_extra_free(&path->extra);
268 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
269 if (path->net)
270 bgp_addpath_free_info_data(&path->tx_addpath,
271 &path->net->tx_addpath);
718e3744 272
9b6d8fcf 273 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 274
9b6d8fcf 275 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 276}
277
9b6d8fcf 278struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 279{
9b6d8fcf
DS
280 path->lock++;
281 return path;
200df115 282}
283
9b6d8fcf 284struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 285{
9b6d8fcf
DS
286 assert(path && path->lock > 0);
287 path->lock--;
d62a17ae 288
9b6d8fcf 289 if (path->lock == 0) {
200df115 290#if 0
291 zlog_debug ("%s: unlocked and freeing", __func__);
292 zlog_backtrace (LOG_DEBUG);
293#endif
9b6d8fcf 294 bgp_path_info_free(path);
d62a17ae 295 return NULL;
296 }
200df115 297
298#if 0
9b6d8fcf 299 if (path->lock == 1)
200df115 300 {
301 zlog_debug ("%s: unlocked to 1", __func__);
302 zlog_backtrace (LOG_DEBUG);
303 }
304#endif
d62a17ae 305
9b6d8fcf 306 return path;
200df115 307}
308
f009ff26 309/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 310static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 311{
312 struct peer *peer;
313 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 314 bool set_flag = false;
f009ff26 315 struct bgp *bgp = NULL;
316 struct bgp_table *table = NULL;
317 afi_t afi = 0;
318 safi_t safi = 0;
f009ff26 319
320 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
321 * then the route selection is deferred
322 */
9bcb3eef 323 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 324 return 0;
325
9bcb3eef 326 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 327 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 328 zlog_debug(
56ca3b5b
DL
329 "Route %pBD is in workqueue and being processed, not deferred.",
330 dest);
b54892e0 331
5f9c1aa2 332 return 0;
333 }
334
9bcb3eef 335 table = bgp_dest_table(dest);
f009ff26 336 if (table) {
337 bgp = table->bgp;
338 afi = table->afi;
339 safi = table->safi;
340 }
341
9bcb3eef 342 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 343 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
344 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
345 continue;
346
347 /* Route selection is deferred if there is a stale path which
348 * which indicates peer is in restart mode
349 */
36235319
QY
350 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
351 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 352 set_flag = true;
f009ff26 353 } else {
354 /* If the peer is graceful restart capable and peer is
355 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
356 */
357 peer = old_pi->peer;
36235319
QY
358 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
359 && BGP_PEER_RESTARTING_MODE(peer)
360 && (old_pi
361 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 362 set_flag = true;
f009ff26 363 }
364 }
365 if (set_flag)
366 break;
367 }
368
369 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
370 * is active
371 */
2ba1fe69 372 if (set_flag && table) {
f009ff26 373 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
9bcb3eef
DS
374 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
375 if (dest->rt_node == NULL)
376 dest->rt_node = listnode_add(
377 bgp->gr_info[afi][safi].route_list,
378 dest);
f009ff26 379 if (BGP_DEBUG(update, UPDATE_OUT))
56ca3b5b 380 zlog_debug("DEFER route %pBD, dest %p, node %p",
9bcb3eef 381 dest, dest, dest->rt_node);
f009ff26 382 return 0;
383 }
384 }
385 return -1;
386}
387
9bcb3eef 388void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 389{
4b7e6066 390 struct bgp_path_info *top;
718e3744 391
9bcb3eef 392 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 393
6f94b685 394 pi->next = top;
40381db7 395 pi->prev = NULL;
d62a17ae 396 if (top)
40381db7 397 top->prev = pi;
9bcb3eef 398 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 399
40381db7 400 bgp_path_info_lock(pi);
9bcb3eef 401 bgp_dest_lock_node(dest);
40381db7 402 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 403 bgp_dest_set_defer_flag(dest, false);
718e3744 404}
405
d62a17ae 406/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 407 completion callback *only* */
9bcb3eef 408void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 409{
40381db7
DS
410 if (pi->next)
411 pi->next->prev = pi->prev;
412 if (pi->prev)
413 pi->prev->next = pi->next;
d62a17ae 414 else
9bcb3eef 415 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 416
40381db7
DS
417 bgp_path_info_mpath_dequeue(pi);
418 bgp_path_info_unlock(pi);
9bcb3eef 419 bgp_dest_unlock_node(dest);
718e3744 420}
421
9bcb3eef 422void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 423{
9bcb3eef 424 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 425 /* set of previous already took care of pcount */
40381db7 426 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 427}
428
18ee8310 429/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
430 called when a route is deleted and then quickly re-added before the
431 deletion has been processed */
9bcb3eef 432void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 433{
9bcb3eef 434 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 435 /* unset of previous already took care of pcount */
40381db7 436 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
437}
438
d62a17ae 439/* Adjust pcount as required */
9bcb3eef 440static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 441{
d62a17ae 442 struct bgp_table *table;
67174041 443
9bcb3eef 444 assert(dest && bgp_dest_table(dest));
40381db7 445 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 446
9bcb3eef 447 table = bgp_dest_table(dest);
67174041 448
40381db7 449 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 450 return;
451
40381db7
DS
452 if (!BGP_PATH_COUNTABLE(pi)
453 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 454
40381db7 455 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 456
457 /* slight hack, but more robust against errors. */
40381db7
DS
458 if (pi->peer->pcount[table->afi][table->safi])
459 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 460 else
450971aa 461 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 462 "Asked to decrement 0 prefix count for peer");
40381db7
DS
463 } else if (BGP_PATH_COUNTABLE(pi)
464 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
465 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
466 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 467 }
1a392d46
PJ
468}
469
40381db7
DS
470static int bgp_label_index_differs(struct bgp_path_info *pi1,
471 struct bgp_path_info *pi2)
28d58fd7 472{
40381db7 473 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 474}
1a392d46 475
18ee8310 476/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
477 * This is here primarily to keep prefix-count in check.
478 */
9bcb3eef 479void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 480 uint32_t flag)
1a392d46 481{
40381db7 482 SET_FLAG(pi->flags, flag);
d62a17ae 483
484 /* early bath if we know it's not a flag that changes countability state
485 */
486 if (!CHECK_FLAG(flag,
1defdda8 487 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 488 return;
489
9bcb3eef 490 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
491}
492
9bcb3eef 493void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 494 uint32_t flag)
1a392d46 495{
40381db7 496 UNSET_FLAG(pi->flags, flag);
d62a17ae 497
498 /* early bath if we know it's not a flag that changes countability state
499 */
500 if (!CHECK_FLAG(flag,
1defdda8 501 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 502 return;
503
9bcb3eef 504 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
505}
506
718e3744 507/* Get MED value. If MED value is missing and "bgp bestpath
508 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 509static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 510{
511 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
512 return attr->med;
513 else {
892fedb6 514 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 515 return BGP_MED_MAX;
516 else
517 return 0;
518 }
718e3744 519}
520
40381db7 521void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf)
2ec1e66f 522{
40381db7
DS
523 if (pi->addpath_rx_id)
524 sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
525 pi->addpath_rx_id);
d62a17ae 526 else
40381db7 527 sprintf(buf, "path %s", pi->peer->host);
d62a17ae 528}
9fbdd100 529
d62a17ae 530/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
531 */
18ee8310
DS
532static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
533 struct bgp_path_info *exist, int *paths_eq,
534 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
535 char *pfx_buf, afi_t afi, safi_t safi,
536 enum bgp_path_selection_reason *reason)
d62a17ae 537{
538 struct attr *newattr, *existattr;
539 bgp_peer_sort_t new_sort;
540 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
541 uint32_t new_pref;
542 uint32_t exist_pref;
543 uint32_t new_med;
544 uint32_t exist_med;
545 uint32_t new_weight;
546 uint32_t exist_weight;
d62a17ae 547 uint32_t newm, existm;
548 struct in_addr new_id;
549 struct in_addr exist_id;
550 int new_cluster;
551 int exist_cluster;
552 int internal_as_route;
553 int confed_as_route;
04d14c8b 554 int ret = 0;
d62a17ae 555 char new_buf[PATH_ADDPATH_STR_BUFFER];
556 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
557 uint32_t new_mm_seq;
558 uint32_t exist_mm_seq;
6d8c603a 559 int nh_cmp;
d071f237
AK
560 esi_t *exist_esi;
561 esi_t *new_esi;
562 bool same_esi;
563 bool old_proxy;
564 bool new_proxy;
d62a17ae 565
566 *paths_eq = 0;
567
568 /* 0. Null check. */
569 if (new == NULL) {
fdf81fa0 570 *reason = bgp_path_selection_none;
d62a17ae 571 if (debug)
572 zlog_debug("%s: new is NULL", pfx_buf);
573 return 0;
574 }
2ec1e66f 575
d62a17ae 576 if (debug)
18ee8310 577 bgp_path_info_path_with_addpath_rx_str(new, new_buf);
718e3744 578
d62a17ae 579 if (exist == NULL) {
fdf81fa0 580 *reason = bgp_path_selection_first;
d62a17ae 581 if (debug)
582 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
583 new_buf);
584 return 1;
585 }
2ec1e66f 586
d62a17ae 587 if (debug) {
18ee8310 588 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
d62a17ae 589 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
590 pfx_buf, new_buf, new->flags, exist_buf,
591 exist->flags);
592 }
8ff56318 593
d62a17ae 594 newattr = new->attr;
595 existattr = exist->attr;
596
597 /* For EVPN routes, we cannot just go by local vs remote, we have to
598 * look at the MAC mobility sequence number, if present.
599 */
600 if (safi == SAFI_EVPN) {
601 /* This is an error condition described in RFC 7432 Section
602 * 15.2. The RFC
603 * states that in this scenario "the PE MUST alert the operator"
604 * but it
605 * does not state what other action to take. In order to provide
606 * some
607 * consistency in this scenario we are going to prefer the path
608 * with the
609 * sticky flag.
610 */
611 if (newattr->sticky != existattr->sticky) {
612 if (!debug) {
9bcb3eef
DS
613 prefix2str(
614 bgp_dest_get_prefix(new->net), pfx_buf,
615 sizeof(*pfx_buf) * PREFIX2STR_BUFFER);
18ee8310
DS
616 bgp_path_info_path_with_addpath_rx_str(new,
617 new_buf);
618 bgp_path_info_path_with_addpath_rx_str(
619 exist, exist_buf);
d62a17ae 620 }
621
622 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 623 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
624 if (debug)
625 zlog_debug(
626 "%s: %s wins over %s due to sticky MAC flag",
627 pfx_buf, new_buf, exist_buf);
d62a17ae 628 return 1;
629 }
630
631 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 632 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
633 if (debug)
634 zlog_debug(
635 "%s: %s loses to %s due to sticky MAC flag",
636 pfx_buf, new_buf, exist_buf);
d62a17ae 637 return 0;
638 }
639 }
128ea8ab 640
d071f237
AK
641 new_esi = bgp_evpn_attr_get_esi(newattr);
642 exist_esi = bgp_evpn_attr_get_esi(existattr);
643 if (bgp_evpn_is_esi_valid(new_esi) &&
644 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
645 same_esi = true;
646 } else {
647 same_esi = false;
648 }
649
650 /* If both paths have the same non-zero ES and
651 * one path is local it wins.
652 * PS: Note the local path wins even if the remote
653 * has the higher MM seq. The local path's
654 * MM seq will be fixed up to match the highest
655 * rem seq, subsequently.
656 */
657 if (same_esi) {
658 char esi_buf[ESI_STR_LEN];
659
660 if (bgp_evpn_is_path_local(bgp, new)) {
661 *reason = bgp_path_selection_evpn_local_path;
662 if (debug)
663 zlog_debug(
664 "%s: %s wins over %s as ES %s is same and local",
665 pfx_buf, new_buf, exist_buf,
666 esi_to_str(new_esi, esi_buf,
667 sizeof(esi_buf)));
668 return 1;
669 }
670 if (bgp_evpn_is_path_local(bgp, exist)) {
671 *reason = bgp_path_selection_evpn_local_path;
672 if (debug)
673 zlog_debug(
674 "%s: %s loses to %s as ES %s is same and local",
675 pfx_buf, new_buf, exist_buf,
676 esi_to_str(new_esi, esi_buf,
677 sizeof(esi_buf)));
678 return 0;
679 }
680 }
681
d62a17ae 682 new_mm_seq = mac_mobility_seqnum(newattr);
683 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 684
d62a17ae 685 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 686 *reason = bgp_path_selection_evpn_seq;
d62a17ae 687 if (debug)
688 zlog_debug(
689 "%s: %s wins over %s due to MM seq %u > %u",
690 pfx_buf, new_buf, exist_buf, new_mm_seq,
691 exist_mm_seq);
692 return 1;
693 }
8ff56318 694
d62a17ae 695 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 696 *reason = bgp_path_selection_evpn_seq;
d62a17ae 697 if (debug)
698 zlog_debug(
699 "%s: %s loses to %s due to MM seq %u < %u",
700 pfx_buf, new_buf, exist_buf, new_mm_seq,
701 exist_mm_seq);
702 return 0;
703 }
6d8c603a 704
d071f237
AK
705 /* if the sequence numbers and ESI are the same and one path
706 * is non-proxy it wins (over proxy)
707 */
708 new_proxy = bgp_evpn_attr_is_proxy(newattr);
709 old_proxy = bgp_evpn_attr_is_proxy(existattr);
710 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
711 old_proxy != new_proxy) {
712 if (!new_proxy) {
713 *reason = bgp_path_selection_evpn_non_proxy;
714 if (debug)
715 zlog_debug(
716 "%s: %s wins over %s, same seq/es and non-proxy",
717 pfx_buf, new_buf, exist_buf);
718 return 1;
719 }
720
721 *reason = bgp_path_selection_evpn_non_proxy;
722 if (debug)
723 zlog_debug(
724 "%s: %s loses to %s, same seq/es and non-proxy",
725 pfx_buf, new_buf, exist_buf);
726 return 0;
727 }
728
6d8c603a
AK
729 /*
730 * if sequence numbers are the same path with the lowest IP
731 * wins
732 */
733 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
734 if (nh_cmp < 0) {
fdf81fa0 735 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
736 if (debug)
737 zlog_debug(
23d0a753 738 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 739 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 740 &new->attr->nexthop);
6d8c603a
AK
741 return 1;
742 }
743 if (nh_cmp > 0) {
fdf81fa0 744 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
745 if (debug)
746 zlog_debug(
23d0a753 747 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 748 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 749 &new->attr->nexthop);
6d8c603a
AK
750 return 0;
751 }
d62a17ae 752 }
9fbdd100 753
d62a17ae 754 /* 1. Weight check. */
d62a17ae 755 new_weight = newattr->weight;
756 exist_weight = existattr->weight;
8ff56318 757
d62a17ae 758 if (new_weight > exist_weight) {
fdf81fa0 759 *reason = bgp_path_selection_weight;
d62a17ae 760 if (debug)
761 zlog_debug("%s: %s wins over %s due to weight %d > %d",
762 pfx_buf, new_buf, exist_buf, new_weight,
763 exist_weight);
764 return 1;
765 }
718e3744 766
d62a17ae 767 if (new_weight < exist_weight) {
fdf81fa0 768 *reason = bgp_path_selection_weight;
d62a17ae 769 if (debug)
770 zlog_debug("%s: %s loses to %s due to weight %d < %d",
771 pfx_buf, new_buf, exist_buf, new_weight,
772 exist_weight);
773 return 0;
774 }
9fbdd100 775
d62a17ae 776 /* 2. Local preference check. */
777 new_pref = exist_pref = bgp->default_local_pref;
778
779 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
780 new_pref = newattr->local_pref;
781 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
782 exist_pref = existattr->local_pref;
783
784 if (new_pref > exist_pref) {
fdf81fa0 785 *reason = bgp_path_selection_local_pref;
d62a17ae 786 if (debug)
787 zlog_debug(
788 "%s: %s wins over %s due to localpref %d > %d",
789 pfx_buf, new_buf, exist_buf, new_pref,
790 exist_pref);
791 return 1;
792 }
718e3744 793
d62a17ae 794 if (new_pref < exist_pref) {
fdf81fa0 795 *reason = bgp_path_selection_local_pref;
d62a17ae 796 if (debug)
797 zlog_debug(
798 "%s: %s loses to %s due to localpref %d < %d",
799 pfx_buf, new_buf, exist_buf, new_pref,
800 exist_pref);
801 return 0;
802 }
9fbdd100 803
d62a17ae 804 /* 3. Local route check. We prefer:
805 * - BGP_ROUTE_STATIC
806 * - BGP_ROUTE_AGGREGATE
807 * - BGP_ROUTE_REDISTRIBUTE
808 */
90f4f482 809 if (!(new->sub_type == BGP_ROUTE_NORMAL ||
810 new->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 811 *reason = bgp_path_selection_local_route;
d62a17ae 812 if (debug)
813 zlog_debug(
814 "%s: %s wins over %s due to preferred BGP_ROUTE type",
815 pfx_buf, new_buf, exist_buf);
816 return 1;
817 }
718e3744 818
90f4f482 819 if (!(exist->sub_type == BGP_ROUTE_NORMAL ||
88493076 820 exist->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 821 *reason = bgp_path_selection_local_route;
d62a17ae 822 if (debug)
823 zlog_debug(
824 "%s: %s loses to %s due to preferred BGP_ROUTE type",
825 pfx_buf, new_buf, exist_buf);
826 return 0;
6811845b 827 }
718e3744 828
d62a17ae 829 /* 4. AS path length check. */
892fedb6 830 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 831 int exist_hops = aspath_count_hops(existattr->aspath);
832 int exist_confeds = aspath_count_confeds(existattr->aspath);
833
892fedb6 834 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 835 int aspath_hops;
836
837 aspath_hops = aspath_count_hops(newattr->aspath);
838 aspath_hops += aspath_count_confeds(newattr->aspath);
839
840 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 841 *reason = bgp_path_selection_confed_as_path;
d62a17ae 842 if (debug)
843 zlog_debug(
844 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
845 pfx_buf, new_buf, exist_buf,
846 aspath_hops,
847 (exist_hops + exist_confeds));
848 return 1;
849 }
850
851 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 852 *reason = bgp_path_selection_confed_as_path;
d62a17ae 853 if (debug)
854 zlog_debug(
855 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
856 pfx_buf, new_buf, exist_buf,
857 aspath_hops,
858 (exist_hops + exist_confeds));
859 return 0;
860 }
861 } else {
862 int newhops = aspath_count_hops(newattr->aspath);
863
864 if (newhops < exist_hops) {
fdf81fa0 865 *reason = bgp_path_selection_as_path;
d62a17ae 866 if (debug)
867 zlog_debug(
868 "%s: %s wins over %s due to aspath hopcount %d < %d",
869 pfx_buf, new_buf, exist_buf,
870 newhops, exist_hops);
871 return 1;
872 }
873
874 if (newhops > exist_hops) {
fdf81fa0 875 *reason = bgp_path_selection_as_path;
d62a17ae 876 if (debug)
877 zlog_debug(
878 "%s: %s loses to %s due to aspath hopcount %d > %d",
879 pfx_buf, new_buf, exist_buf,
880 newhops, exist_hops);
881 return 0;
882 }
883 }
884 }
9fbdd100 885
d62a17ae 886 /* 5. Origin check. */
887 if (newattr->origin < existattr->origin) {
fdf81fa0 888 *reason = bgp_path_selection_origin;
d62a17ae 889 if (debug)
890 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
891 pfx_buf, new_buf, exist_buf,
892 bgp_origin_long_str[newattr->origin],
893 bgp_origin_long_str[existattr->origin]);
894 return 1;
895 }
718e3744 896
d62a17ae 897 if (newattr->origin > existattr->origin) {
fdf81fa0 898 *reason = bgp_path_selection_origin;
d62a17ae 899 if (debug)
900 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
901 pfx_buf, new_buf, exist_buf,
902 bgp_origin_long_str[newattr->origin],
903 bgp_origin_long_str[existattr->origin]);
904 return 0;
905 }
718e3744 906
d62a17ae 907 /* 6. MED check. */
908 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
909 && aspath_count_hops(existattr->aspath) == 0);
910 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
911 && aspath_count_confeds(existattr->aspath) > 0
912 && aspath_count_hops(newattr->aspath) == 0
913 && aspath_count_hops(existattr->aspath) == 0);
914
892fedb6
DA
915 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
916 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 917 || aspath_cmp_left(newattr->aspath, existattr->aspath)
918 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
919 || internal_as_route) {
920 new_med = bgp_med_value(new->attr, bgp);
921 exist_med = bgp_med_value(exist->attr, bgp);
922
923 if (new_med < exist_med) {
fdf81fa0 924 *reason = bgp_path_selection_med;
d62a17ae 925 if (debug)
926 zlog_debug(
927 "%s: %s wins over %s due to MED %d < %d",
928 pfx_buf, new_buf, exist_buf, new_med,
929 exist_med);
930 return 1;
931 }
8ff56318 932
d62a17ae 933 if (new_med > exist_med) {
fdf81fa0 934 *reason = bgp_path_selection_med;
d62a17ae 935 if (debug)
936 zlog_debug(
937 "%s: %s loses to %s due to MED %d > %d",
938 pfx_buf, new_buf, exist_buf, new_med,
939 exist_med);
940 return 0;
941 }
942 }
9fbdd100 943
d62a17ae 944 /* 7. Peer type check. */
945 new_sort = new->peer->sort;
946 exist_sort = exist->peer->sort;
947
948 if (new_sort == BGP_PEER_EBGP
949 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 950 *reason = bgp_path_selection_peer;
d62a17ae 951 if (debug)
952 zlog_debug(
953 "%s: %s wins over %s due to eBGP peer > iBGP peer",
954 pfx_buf, new_buf, exist_buf);
955 return 1;
956 }
718e3744 957
d62a17ae 958 if (exist_sort == BGP_PEER_EBGP
959 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 960 *reason = bgp_path_selection_peer;
d62a17ae 961 if (debug)
962 zlog_debug(
963 "%s: %s loses to %s due to iBGP peer < eBGP peer",
964 pfx_buf, new_buf, exist_buf);
965 return 0;
966 }
8ff56318 967
d62a17ae 968 /* 8. IGP metric check. */
969 newm = existm = 0;
8ff56318 970
d62a17ae 971 if (new->extra)
972 newm = new->extra->igpmetric;
973 if (exist->extra)
974 existm = exist->extra->igpmetric;
9fbdd100 975
d62a17ae 976 if (newm < existm) {
977 if (debug)
978 zlog_debug(
979 "%s: %s wins over %s due to IGP metric %d < %d",
980 pfx_buf, new_buf, exist_buf, newm, existm);
981 ret = 1;
982 }
718e3744 983
d62a17ae 984 if (newm > existm) {
985 if (debug)
986 zlog_debug(
987 "%s: %s loses to %s due to IGP metric %d > %d",
988 pfx_buf, new_buf, exist_buf, newm, existm);
989 ret = 0;
5e242b0d 990 }
5e242b0d 991
d62a17ae 992 /* 9. Same IGP metric. Compare the cluster list length as
993 representative of IGP hops metric. Rewrite the metric value
994 pair (newm, existm) with the cluster list length. Prefer the
995 path with smaller cluster list length. */
996 if (newm == existm) {
bf0d28dc
DS
997 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
998 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
d62a17ae 999 && (mpath_cfg == NULL
1000 || CHECK_FLAG(
1001 mpath_cfg->ibgp_flags,
1002 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
1003 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1004 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1005
1006 if (newm < existm) {
1007 if (debug)
1008 zlog_debug(
1009 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1010 pfx_buf, new_buf, exist_buf,
1011 newm, existm);
1012 ret = 1;
1013 }
1014
1015 if (newm > existm) {
1016 if (debug)
1017 zlog_debug(
1018 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1019 pfx_buf, new_buf, exist_buf,
1020 newm, existm);
1021 ret = 0;
1022 }
1023 }
1024 }
31a4638f 1025
d62a17ae 1026 /* 10. confed-external vs. confed-internal */
1027 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1028 if (new_sort == BGP_PEER_CONFED
1029 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1030 *reason = bgp_path_selection_confed;
d62a17ae 1031 if (debug)
1032 zlog_debug(
1033 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1034 pfx_buf, new_buf, exist_buf);
1035 return 1;
1036 }
718e3744 1037
d62a17ae 1038 if (exist_sort == BGP_PEER_CONFED
1039 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1040 *reason = bgp_path_selection_confed;
d62a17ae 1041 if (debug)
1042 zlog_debug(
1043 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1044 pfx_buf, new_buf, exist_buf);
1045 return 0;
1046 }
1047 }
718e3744 1048
d62a17ae 1049 /* 11. Maximum path check. */
1050 if (newm == existm) {
1051 /* If one path has a label but the other does not, do not treat
1052 * them as equals for multipath
1053 */
a4d82a8a 1054 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1055 != (exist->extra
b57ba6d2 1056 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1057 if (debug)
1058 zlog_debug(
1059 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1060 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1061 } else if (CHECK_FLAG(bgp->flags,
1062 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1063
1064 /*
1065 * For the two paths, all comparison steps till IGP
1066 * metric
1067 * have succeeded - including AS_PATH hop count. Since
1068 * 'bgp
1069 * bestpath as-path multipath-relax' knob is on, we
1070 * don't need
1071 * an exact match of AS_PATH. Thus, mark the paths are
1072 * equal.
1073 * That will trigger both these paths to get into the
1074 * multipath
1075 * array.
1076 */
1077 *paths_eq = 1;
1078
1079 if (debug)
1080 zlog_debug(
1081 "%s: %s and %s are equal via multipath-relax",
1082 pfx_buf, new_buf, exist_buf);
1083 } else if (new->peer->sort == BGP_PEER_IBGP) {
1084 if (aspath_cmp(new->attr->aspath,
1085 exist->attr->aspath)) {
1086 *paths_eq = 1;
1087
1088 if (debug)
1089 zlog_debug(
1090 "%s: %s and %s are equal via matching aspaths",
1091 pfx_buf, new_buf, exist_buf);
1092 }
1093 } else if (new->peer->as == exist->peer->as) {
1094 *paths_eq = 1;
1095
1096 if (debug)
1097 zlog_debug(
1098 "%s: %s and %s are equal via same remote-as",
1099 pfx_buf, new_buf, exist_buf);
1100 }
1101 } else {
1102 /*
1103 * TODO: If unequal cost ibgp multipath is enabled we can
1104 * mark the paths as equal here instead of returning
1105 */
1106 if (debug) {
1107 if (ret == 1)
1108 zlog_debug(
1109 "%s: %s wins over %s after IGP metric comparison",
1110 pfx_buf, new_buf, exist_buf);
1111 else
1112 zlog_debug(
1113 "%s: %s loses to %s after IGP metric comparison",
1114 pfx_buf, new_buf, exist_buf);
1115 }
fdf81fa0 1116 *reason = bgp_path_selection_igp_metric;
d62a17ae 1117 return ret;
1118 }
718e3744 1119
d62a17ae 1120 /* 12. If both paths are external, prefer the path that was received
1121 first (the oldest one). This step minimizes route-flap, since a
1122 newer path won't displace an older one, even if it was the
1123 preferred route based on the additional decision criteria below. */
892fedb6 1124 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1125 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1126 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1127 *reason = bgp_path_selection_older;
d62a17ae 1128 if (debug)
1129 zlog_debug(
1130 "%s: %s wins over %s due to oldest external",
1131 pfx_buf, new_buf, exist_buf);
1132 return 1;
1133 }
9fbdd100 1134
1defdda8 1135 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1136 *reason = bgp_path_selection_older;
d62a17ae 1137 if (debug)
1138 zlog_debug(
1139 "%s: %s loses to %s due to oldest external",
1140 pfx_buf, new_buf, exist_buf);
1141 return 0;
1142 }
1143 }
718e3744 1144
d62a17ae 1145 /* 13. Router-ID comparision. */
1146 /* If one of the paths is "stale", the corresponding peer router-id will
1147 * be 0 and would always win over the other path. If originator id is
1148 * used for the comparision, it will decide which path is better.
1149 */
1150 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1151 new_id.s_addr = newattr->originator_id.s_addr;
1152 else
1153 new_id.s_addr = new->peer->remote_id.s_addr;
1154 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1155 exist_id.s_addr = existattr->originator_id.s_addr;
1156 else
1157 exist_id.s_addr = exist->peer->remote_id.s_addr;
1158
1159 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1160 *reason = bgp_path_selection_router_id;
d62a17ae 1161 if (debug)
1162 zlog_debug(
1163 "%s: %s wins over %s due to Router-ID comparison",
1164 pfx_buf, new_buf, exist_buf);
1165 return 1;
1166 }
718e3744 1167
d62a17ae 1168 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1169 *reason = bgp_path_selection_router_id;
d62a17ae 1170 if (debug)
1171 zlog_debug(
1172 "%s: %s loses to %s due to Router-ID comparison",
1173 pfx_buf, new_buf, exist_buf);
1174 return 0;
1175 }
9fbdd100 1176
d62a17ae 1177 /* 14. Cluster length comparision. */
1178 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1179 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1180
1181 if (new_cluster < exist_cluster) {
fdf81fa0 1182 *reason = bgp_path_selection_cluster_length;
d62a17ae 1183 if (debug)
1184 zlog_debug(
1185 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1186 pfx_buf, new_buf, exist_buf, new_cluster,
1187 exist_cluster);
1188 return 1;
1189 }
718e3744 1190
d62a17ae 1191 if (new_cluster > exist_cluster) {
fdf81fa0 1192 *reason = bgp_path_selection_cluster_length;
d62a17ae 1193 if (debug)
1194 zlog_debug(
1195 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1196 pfx_buf, new_buf, exist_buf, new_cluster,
1197 exist_cluster);
1198 return 0;
1199 }
9fbdd100 1200
d62a17ae 1201 /* 15. Neighbor address comparision. */
1202 /* Do this only if neither path is "stale" as stale paths do not have
1203 * valid peer information (as the connection may or may not be up).
1204 */
1defdda8 1205 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1206 *reason = bgp_path_selection_stale;
d62a17ae 1207 if (debug)
1208 zlog_debug(
1209 "%s: %s wins over %s due to latter path being STALE",
1210 pfx_buf, new_buf, exist_buf);
1211 return 1;
1212 }
0de5153c 1213
1defdda8 1214 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1215 *reason = bgp_path_selection_stale;
d62a17ae 1216 if (debug)
1217 zlog_debug(
1218 "%s: %s loses to %s due to former path being STALE",
1219 pfx_buf, new_buf, exist_buf);
1220 return 0;
1221 }
718e3744 1222
d62a17ae 1223 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1224 if (new->peer->su_remote == NULL) {
1225 *reason = bgp_path_selection_local_configured;
d62a17ae 1226 return 0;
fdf81fa0
DS
1227 }
1228 if (exist->peer->su_remote == NULL) {
1229 *reason = bgp_path_selection_local_configured;
d62a17ae 1230 return 1;
fdf81fa0 1231 }
9fbdd100 1232
d62a17ae 1233 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1234
1235 if (ret == 1) {
fdf81fa0 1236 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1237 if (debug)
1238 zlog_debug(
1239 "%s: %s loses to %s due to Neighor IP comparison",
1240 pfx_buf, new_buf, exist_buf);
1241 return 0;
1242 }
1243
1244 if (ret == -1) {
fdf81fa0 1245 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1246 if (debug)
1247 zlog_debug(
1248 "%s: %s wins over %s due to Neighor IP comparison",
1249 pfx_buf, new_buf, exist_buf);
1250 return 1;
1251 }
9fbdd100 1252
fdf81fa0 1253 *reason = bgp_path_selection_default;
d62a17ae 1254 if (debug)
1255 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1256 pfx_buf, new_buf, exist_buf);
718e3744 1257
d62a17ae 1258 return 1;
718e3744 1259}
1260
d071f237
AK
1261
1262int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1263 struct bgp_path_info *exist, int *paths_eq)
1264{
1265 enum bgp_path_selection_reason reason;
1266 char pfx_buf[PREFIX2STR_BUFFER];
1267
1268 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1269 AFI_L2VPN, SAFI_EVPN, &reason);
1270}
1271
65efcfce
LB
1272/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1273 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1274 * multipath is enabled
65efcfce 1275 * This version is compatible with */
18ee8310
DS
1276int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1277 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1278 afi_t afi, safi_t safi,
1279 enum bgp_path_selection_reason *reason)
d62a17ae 1280{
1281 int paths_eq;
1282 int ret;
18ee8310 1283 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1284 afi, safi, reason);
d62a17ae 1285
1286 if (paths_eq)
1287 ret = 0;
1288 else {
1289 if (ret == 1)
1290 ret = -1;
1291 else
1292 ret = 1;
1293 }
1294 return ret;
65efcfce
LB
1295}
1296
5a1ae2c2
DS
1297static enum filter_type bgp_input_filter(struct peer *peer,
1298 const struct prefix *p,
d62a17ae 1299 struct attr *attr, afi_t afi,
1300 safi_t safi)
718e3744 1301{
d62a17ae 1302 struct bgp_filter *filter;
6401252f 1303 enum filter_type ret = FILTER_PERMIT;
718e3744 1304
d62a17ae 1305 filter = &peer->filter[afi][safi];
718e3744 1306
d62a17ae 1307#define FILTER_EXIST_WARN(F, f, filter) \
1308 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1309 zlog_debug("%s: Could not find configured input %s-list %s!", \
1310 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1311
1312 if (DISTRIBUTE_IN_NAME(filter)) {
1313 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1314
6401252f
QY
1315 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1316 == FILTER_DENY) {
1317 ret = FILTER_DENY;
1318 goto done;
1319 }
d62a17ae 1320 }
1321
1322 if (PREFIX_LIST_IN_NAME(filter)) {
1323 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1324
6401252f
QY
1325 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1326 == PREFIX_DENY) {
1327 ret = FILTER_DENY;
1328 goto done;
1329 }
d62a17ae 1330 }
1331
1332 if (FILTER_LIST_IN_NAME(filter)) {
1333 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1334
1335 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1336 == AS_FILTER_DENY) {
1337 ret = FILTER_DENY;
1338 goto done;
1339 }
d62a17ae 1340 }
1341
6401252f 1342done:
c7bb4f00 1343 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1344 char pfxprint[PREFIX2STR_BUFFER];
1345
1346 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1347 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1348 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1349 }
1350
1351 return ret;
650f76c2 1352#undef FILTER_EXIST_WARN
718e3744 1353}
1354
b8685f9b
DS
1355static enum filter_type bgp_output_filter(struct peer *peer,
1356 const struct prefix *p,
d62a17ae 1357 struct attr *attr, afi_t afi,
1358 safi_t safi)
718e3744 1359{
d62a17ae 1360 struct bgp_filter *filter;
6401252f 1361 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1362
1363 filter = &peer->filter[afi][safi];
1364
1365#define FILTER_EXIST_WARN(F, f, filter) \
1366 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1367 zlog_debug("%s: Could not find configured output %s-list %s!", \
1368 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1369
d62a17ae 1370 if (DISTRIBUTE_OUT_NAME(filter)) {
1371 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1372
6401252f
QY
1373 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1374 == FILTER_DENY) {
1375 ret = FILTER_DENY;
1376 goto done;
1377 }
d62a17ae 1378 }
1379
1380 if (PREFIX_LIST_OUT_NAME(filter)) {
1381 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1382
d62a17ae 1383 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1384 == PREFIX_DENY) {
1385 ret = FILTER_DENY;
1386 goto done;
1387 }
d62a17ae 1388 }
718e3744 1389
d62a17ae 1390 if (FILTER_LIST_OUT_NAME(filter)) {
1391 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1392
d62a17ae 1393 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1394 == AS_FILTER_DENY) {
1395 ret = FILTER_DENY;
1396 goto done;
1397 }
1398 }
1399
c7bb4f00 1400 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1401 char pfxprint[PREFIX2STR_BUFFER];
1402
1403 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1404 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1405 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1406 }
718e3744 1407
6401252f
QY
1408done:
1409 return ret;
650f76c2 1410#undef FILTER_EXIST_WARN
718e3744 1411}
1412
1413/* If community attribute includes no_export then return 1. */
3dc339cd 1414static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1415{
1416 if (attr->community) {
1417 /* NO_ADVERTISE check. */
1418 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
3dc339cd 1419 return true;
d62a17ae 1420
1421 /* NO_EXPORT check. */
1422 if (peer->sort == BGP_PEER_EBGP
1423 && community_include(attr->community, COMMUNITY_NO_EXPORT))
3dc339cd 1424 return true;
d62a17ae 1425
1426 /* NO_EXPORT_SUBCONFED check. */
1427 if (peer->sort == BGP_PEER_EBGP
1428 || peer->sort == BGP_PEER_CONFED)
1429 if (community_include(attr->community,
1430 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1431 return true;
d62a17ae 1432 }
3dc339cd 1433 return false;
718e3744 1434}
1435
1436/* Route reflection loop check. */
3dc339cd 1437static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1438{
d62a17ae 1439 struct in_addr cluster_id;
718e3744 1440
d62a17ae 1441 if (attr->cluster) {
1442 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1443 cluster_id = peer->bgp->cluster_id;
1444 else
1445 cluster_id = peer->bgp->router_id;
1446
1447 if (cluster_loop_check(attr->cluster, cluster_id))
3dc339cd 1448 return true;
d62a17ae 1449 }
3dc339cd 1450 return false;
718e3744 1451}
6b0655a2 1452
5a1ae2c2 1453static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1454 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1455 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1456 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1457{
d62a17ae 1458 struct bgp_filter *filter;
82b692c0
LK
1459 struct bgp_path_info rmap_path = { 0 };
1460 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1461 route_map_result_t ret;
1462 struct route_map *rmap = NULL;
718e3744 1463
d62a17ae 1464 filter = &peer->filter[afi][safi];
718e3744 1465
d62a17ae 1466 /* Apply default weight value. */
1467 if (peer->weight[afi][safi])
1468 attr->weight = peer->weight[afi][safi];
718e3744 1469
d62a17ae 1470 if (rmap_name) {
1471 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1472
d62a17ae 1473 if (rmap == NULL)
1474 return RMAP_DENY;
1475 } else {
1476 if (ROUTE_MAP_IN_NAME(filter)) {
1477 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1478
d62a17ae 1479 if (rmap == NULL)
1480 return RMAP_DENY;
1481 }
1482 }
0b16f239 1483
d62a17ae 1484 /* Route map apply. */
1485 if (rmap) {
40381db7 1486 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1487 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1488 rmap_path.peer = peer;
1489 rmap_path.attr = attr;
82b692c0 1490 rmap_path.extra = &extra;
9bcb3eef 1491 rmap_path.net = dest;
196c6b09 1492
82b692c0
LK
1493 extra.num_labels = num_labels;
1494 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1495 memcpy(extra.label, label,
1496 num_labels * sizeof(mpls_label_t));
718e3744 1497
d62a17ae 1498 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1499
d62a17ae 1500 /* Apply BGP route map to the attribute. */
40381db7 1501 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
0b16f239 1502
d62a17ae 1503 peer->rmap_type = 0;
0b16f239 1504
1f2263be 1505 if (ret == RMAP_DENYMATCH)
d62a17ae 1506 return RMAP_DENY;
0b16f239 1507 }
d62a17ae 1508 return RMAP_PERMIT;
0b16f239
DS
1509}
1510
5f040085 1511static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1512 struct attr *attr, afi_t afi, safi_t safi,
1513 const char *rmap_name)
0b16f239 1514{
40381db7 1515 struct bgp_path_info rmap_path;
d62a17ae 1516 route_map_result_t ret;
1517 struct route_map *rmap = NULL;
d7c0a89a 1518 uint8_t rmap_type;
0b16f239 1519
b787157a
DS
1520 /*
1521 * So if we get to this point and have no rmap_name
1522 * we want to just show the output as it currently
1523 * exists.
1524 */
1525 if (!rmap_name)
1526 return RMAP_PERMIT;
0b16f239 1527
d62a17ae 1528 /* Apply default weight value. */
1529 if (peer->weight[afi][safi])
1530 attr->weight = peer->weight[afi][safi];
0b16f239 1531
b787157a 1532 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1533
b787157a
DS
1534 /*
1535 * If we have a route map name and we do not find
1536 * the routemap that means we have an implicit
1537 * deny.
1538 */
1539 if (rmap == NULL)
1540 return RMAP_DENY;
0b16f239 1541
40381db7 1542 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1543 /* Route map apply. */
b787157a 1544 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1545 rmap_path.peer = peer;
1546 rmap_path.attr = attr;
0b16f239 1547
0f672529 1548 rmap_type = peer->rmap_type;
b787157a 1549 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1550
b787157a 1551 /* Apply BGP route map to the attribute. */
40381db7 1552 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
ac41b2a2 1553
0f672529 1554 peer->rmap_type = rmap_type;
b787157a
DS
1555
1556 if (ret == RMAP_DENYMATCH)
1557 /*
1558 * caller has multiple error paths with bgp_attr_flush()
1559 */
1560 return RMAP_DENY;
ac41b2a2 1561
d62a17ae 1562 return RMAP_PERMIT;
718e3744 1563}
6b0655a2 1564
5000f21c 1565/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1566static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1567 struct peer *peer, struct attr *attr)
1568{
1569 if (peer->sort == BGP_PEER_EBGP
1570 && (peer_af_flag_check(peer, afi, safi,
1571 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1572 || peer_af_flag_check(peer, afi, safi,
1573 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1574 || peer_af_flag_check(peer, afi, safi,
1575 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1576 || peer_af_flag_check(peer, afi, safi,
1577 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1578 // Take action on the entire aspath
1579 if (peer_af_flag_check(peer, afi, safi,
1580 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1581 || peer_af_flag_check(peer, afi, safi,
1582 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1583 if (peer_af_flag_check(
1584 peer, afi, safi,
1585 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1586 attr->aspath = aspath_replace_private_asns(
bf26b80e 1587 attr->aspath, bgp->as, peer->as);
d62a17ae 1588
1589 // The entire aspath consists of private ASNs so create
1590 // an empty aspath
1591 else if (aspath_private_as_check(attr->aspath))
1592 attr->aspath = aspath_empty_get();
1593
1594 // There are some public and some private ASNs, remove
1595 // the private ASNs
1596 else
1597 attr->aspath = aspath_remove_private_asns(
bf26b80e 1598 attr->aspath, peer->as);
d62a17ae 1599 }
1600
1601 // 'all' was not specified so the entire aspath must be private
1602 // ASNs
1603 // for us to do anything
1604 else if (aspath_private_as_check(attr->aspath)) {
1605 if (peer_af_flag_check(
1606 peer, afi, safi,
1607 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1608 attr->aspath = aspath_replace_private_asns(
bf26b80e 1609 attr->aspath, bgp->as, peer->as);
d62a17ae 1610 else
1611 attr->aspath = aspath_empty_get();
1612 }
1613 }
5000f21c
DS
1614}
1615
c7122e14 1616/* If this is an EBGP peer with as-override */
d62a17ae 1617static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1618 struct peer *peer, struct attr *attr)
1619{
1620 if (peer->sort == BGP_PEER_EBGP
1621 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1622 if (aspath_single_asn_check(attr->aspath, peer->as))
1623 attr->aspath = aspath_replace_specific_asn(
1624 attr->aspath, peer->as, bgp->as);
1625 }
1626}
1627
7f323236
DW
1628void bgp_attr_add_gshut_community(struct attr *attr)
1629{
1630 struct community *old;
1631 struct community *new;
1632 struct community *merge;
1633 struct community *gshut;
1634
1635 old = attr->community;
1636 gshut = community_str2com("graceful-shutdown");
1637
990f4f91 1638 assert(gshut);
1639
7f323236
DW
1640 if (old) {
1641 merge = community_merge(community_dup(old), gshut);
1642
a4d82a8a 1643 if (old->refcnt == 0)
3c1f53de 1644 community_free(&old);
7f323236
DW
1645
1646 new = community_uniq_sort(merge);
3c1f53de 1647 community_free(&merge);
7f323236
DW
1648 } else {
1649 new = community_dup(gshut);
1650 }
1651
3c1f53de 1652 community_free(&gshut);
7f323236
DW
1653 attr->community = new;
1654 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1655
1656 /* When we add the graceful-shutdown community we must also
1657 * lower the local-preference */
1658 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1659 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1660}
1661
1662
e73c112e
MK
1663/* Notify BGP Conditional advertisement scanner process. */
1664void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1665{
1666 struct peer *temp_peer;
1667 struct peer *peer = SUBGRP_PEER(subgrp);
1668 struct listnode *temp_node, *temp_nnode = NULL;
1669 afi_t afi = SUBGRP_AFI(subgrp);
1670 safi_t safi = SUBGRP_SAFI(subgrp);
1671 struct bgp *bgp = SUBGRP_INST(subgrp);
1672 struct bgp_filter *filter = &peer->filter[afi][safi];
1673
1674 if (!ADVERTISE_MAP_NAME(filter))
1675 return;
1676
1677 for (ALL_LIST_ELEMENTS(bgp->peer, temp_node, temp_nnode, temp_peer)) {
1678 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1679 continue;
1680
1681 if (peer != temp_peer)
1682 continue;
1683
1684 temp_peer->advmap_table_change = true;
1685 break;
1686 }
1687}
1688
1689
d7c0a89a 1690static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1691{
960035b2 1692 if (family == AF_INET) {
975a328e
DA
1693 attr->nexthop.s_addr = INADDR_ANY;
1694 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1695 }
d62a17ae 1696 if (family == AF_INET6)
1697 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1698 if (family == AF_EVPN)
1699 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1700}
1701
9bcb3eef 1702bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1703 struct update_subgroup *subgrp,
7f7940e6
MK
1704 const struct prefix *p, struct attr *attr,
1705 bool skip_rmap_check)
d62a17ae 1706{
1707 struct bgp_filter *filter;
1708 struct peer *from;
1709 struct peer *peer;
1710 struct peer *onlypeer;
1711 struct bgp *bgp;
40381db7 1712 struct attr *piattr;
b68885f9 1713 route_map_result_t ret;
d62a17ae 1714 int transparent;
1715 int reflect;
1716 afi_t afi;
1717 safi_t safi;
1718 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1719 bool nh_reset = false;
1720 uint64_t cum_bw;
d62a17ae 1721
1722 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1723 return false;
d62a17ae 1724
1725 afi = SUBGRP_AFI(subgrp);
1726 safi = SUBGRP_SAFI(subgrp);
1727 peer = SUBGRP_PEER(subgrp);
1728 onlypeer = NULL;
1729 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1730 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1731
40381db7 1732 from = pi->peer;
d62a17ae 1733 filter = &peer->filter[afi][safi];
1734 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1735 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1736 : pi->attr;
3f9c7369 1737
49e5a4a0 1738#ifdef ENABLE_BGP_VNC
d62a17ae 1739 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1740 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1741 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1742
1743 /*
1744 * direct and direct_ext type routes originate internally even
1745 * though they can have peer pointers that reference other
1746 * systems
1747 */
8228a9a7
DS
1748 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1749 __func__, p);
d62a17ae 1750 samepeer_safe = 1;
1751 }
65efcfce
LB
1752#endif
1753
ddb5b488
PZ
1754 if (((afi == AFI_IP) || (afi == AFI_IP6))
1755 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1756 && (pi->type == ZEBRA_ROUTE_BGP)
1757 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1758
1759 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1760
1761 samepeer_safe = 1;
1762 }
1763
d62a17ae 1764 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1765 * pi is valid */
1766 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1767 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1768 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1769 return false;
d62a17ae 1770 }
adbac85e 1771
d62a17ae 1772 /* If this is not the bestpath then check to see if there is an enabled
1773 * addpath
1774 * feature that requires us to advertise it */
40381db7 1775 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1776 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1777 return false;
d62a17ae 1778 }
1779 }
06370dac 1780
d62a17ae 1781 /* Aggregate-address suppress check. */
4056a5f6
RZ
1782 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1783 return false;
3f9c7369 1784
13b7e7f0
DS
1785 /*
1786 * If we are doing VRF 2 VRF leaking via the import
1787 * statement, we want to prevent the route going
1788 * off box as that the RT and RD created are localy
1789 * significant and globaly useless.
1790 */
40381db7
DS
1791 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1792 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1793 return false;
13b7e7f0 1794
d62a17ae 1795 /* If it's labeled safi, make sure the route has a valid label. */
1796 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1797 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1798 if (!bgp_is_valid_label(&label)) {
1799 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1800 zlog_debug("u%" PRIu64 ":s%" PRIu64
1801 " %pFX is filtered - no label (%p)",
d62a17ae 1802 subgrp->update_group->id, subgrp->id,
8228a9a7 1803 p, &label);
3dc339cd 1804 return false;
d62a17ae 1805 }
1806 }
cd1964ff 1807
d62a17ae 1808 /* Do not send back route to sender. */
1809 if (onlypeer && from == onlypeer) {
3dc339cd 1810 return false;
d62a17ae 1811 }
3f9c7369 1812
d62a17ae 1813 /* Do not send the default route in the BGP table if the neighbor is
1814 * configured for default-originate */
1815 if (CHECK_FLAG(peer->af_flags[afi][safi],
1816 PEER_FLAG_DEFAULT_ORIGINATE)) {
1817 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1818 return false;
d62a17ae 1819 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1820 return false;
d62a17ae 1821 }
4125bb67 1822
d62a17ae 1823 /* Transparency check. */
1824 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1825 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1826 transparent = 1;
1827 else
1828 transparent = 0;
1829
1830 /* If community is not disabled check the no-export and local. */
40381db7 1831 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1832 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1833 zlog_debug(
1834 "subgrpannouncecheck: community filter check fail");
3dc339cd 1835 return false;
d62a17ae 1836 }
3f9c7369 1837
d62a17ae 1838 /* If the attribute has originator-id and it is same as remote
1839 peer's id. */
40381db7
DS
1840 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1841 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1842 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1843 zlog_debug(
8228a9a7
DS
1844 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1845 onlypeer->host, p);
3dc339cd 1846 return false;
d62a17ae 1847 }
3f9c7369 1848
d62a17ae 1849 /* ORF prefix-list filter check */
1850 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1851 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1852 || CHECK_FLAG(peer->af_cap[afi][safi],
1853 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1854 if (peer->orf_plist[afi][safi]) {
1855 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1856 == PREFIX_DENY) {
1857 if (bgp_debug_update(NULL, p,
1858 subgrp->update_group, 0))
1859 zlog_debug(
8228a9a7
DS
1860 "%s [Update:SEND] %pFX is filtered via ORF",
1861 peer->host, p);
3dc339cd 1862 return false;
d62a17ae 1863 }
1864 }
1865
1866 /* Output filter check. */
40381db7 1867 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1868 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1869 zlog_debug("%s [Update:SEND] %pFX is filtered",
1870 peer->host, p);
3dc339cd 1871 return false;
d62a17ae 1872 }
3f9c7369 1873
d62a17ae 1874 /* AS path loop check. */
2b31007c
RZ
1875 if (onlypeer && onlypeer->as_path_loop_detection
1876 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1877 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1878 zlog_debug(
3efd0893 1879 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 1880 onlypeer->host, onlypeer->as);
3dc339cd 1881 return false;
d62a17ae 1882 }
3f9c7369 1883
d62a17ae 1884 /* If we're a CONFED we need to loop check the CONFED ID too */
1885 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1886 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1887 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1888 zlog_debug(
3efd0893 1889 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 1890 peer->host, bgp->confed_id);
3dc339cd 1891 return false;
d62a17ae 1892 }
3f9c7369 1893 }
3f9c7369 1894
d62a17ae 1895 /* Route-Reflect check. */
1896 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1897 reflect = 1;
1898 else
1899 reflect = 0;
1900
1901 /* IBGP reflection check. */
1902 if (reflect && !samepeer_safe) {
1903 /* A route from a Client peer. */
1904 if (CHECK_FLAG(from->af_flags[afi][safi],
1905 PEER_FLAG_REFLECTOR_CLIENT)) {
1906 /* Reflect to all the Non-Client peers and also to the
1907 Client peers other than the originator. Originator
1908 check
1909 is already done. So there is noting to do. */
1910 /* no bgp client-to-client reflection check. */
892fedb6
DA
1911 if (CHECK_FLAG(bgp->flags,
1912 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 1913 if (CHECK_FLAG(peer->af_flags[afi][safi],
1914 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1915 return false;
d62a17ae 1916 } else {
1917 /* A route from a Non-client peer. Reflect to all other
1918 clients. */
1919 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1920 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1921 return false;
d62a17ae 1922 }
1923 }
3f9c7369 1924
d62a17ae 1925 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1926 *attr = *piattr;
d62a17ae 1927
1928 /* If local-preference is not set. */
1929 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1930 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1931 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1932 attr->local_pref = bgp->default_local_pref;
3f9c7369 1933 }
3f9c7369 1934
d62a17ae 1935 /* If originator-id is not set and the route is to be reflected,
1936 set the originator id */
1937 if (reflect
1938 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1939 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1940 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1941 }
3f9c7369 1942
d62a17ae 1943 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1944 */
1945 if (peer->sort == BGP_PEER_EBGP
1946 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1947 if (from != bgp->peer_self && !transparent
1948 && !CHECK_FLAG(peer->af_flags[afi][safi],
1949 PEER_FLAG_MED_UNCHANGED))
1950 attr->flag &=
1951 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1952 }
3f9c7369 1953
d62a17ae 1954 /* Since the nexthop attribute can vary per peer, it is not explicitly
1955 * set
1956 * in announce check, only certain flags and length (or number of
1957 * nexthops
1958 * -- for IPv6/MP_REACH) are set here in order to guide the update
1959 * formation
1960 * code in setting the nexthop(s) on a per peer basis in
1961 * reformat_peer().
1962 * Typically, the source nexthop in the attribute is preserved but in
1963 * the
1964 * scenarios where we know it will always be overwritten, we reset the
1965 * nexthop to "0" in an attempt to achieve better Update packing. An
1966 * example of this is when a prefix from each of 2 IBGP peers needs to
1967 * be
1968 * announced to an EBGP peer (and they have the same attributes barring
1969 * their nexthop).
1970 */
1971 if (reflect)
1972 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1973
1974#define NEXTHOP_IS_V6 \
1975 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1976 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1977 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1978 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1979
1980 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1981 * if
1982 * the peer (group) is configured to receive link-local nexthop
1983 * unchanged
c728d027
DA
1984 * and it is available in the prefix OR we're not reflecting the route,
1985 * link-local nexthop address is valid and
d62a17ae 1986 * the peer (group) to whom we're going to announce is on a shared
1987 * network
1988 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
1989 * By checking if nexthop LL address is valid we are sure that
1990 * we do not announce LL address as `::`.
d62a17ae 1991 */
1992 if (NEXTHOP_IS_V6) {
1993 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
1994 if ((CHECK_FLAG(peer->af_flags[afi][safi],
1995 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
1996 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
1997 || (!reflect
1998 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
1999 && peer->shared_network
d62a17ae 2000 && (from == bgp->peer_self
2001 || peer->sort == BGP_PEER_EBGP))) {
2002 attr->mp_nexthop_len =
2003 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2004 }
3f9c7369 2005
d62a17ae 2006 /* Clear off link-local nexthop in source, whenever it is not
2007 * needed to
2008 * ensure more prefixes share the same attribute for
2009 * announcement.
2010 */
2011 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2012 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2013 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2014 }
3f9c7369 2015
d62a17ae 2016 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2017 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2018
2019 /* Route map & unsuppress-map apply. */
7f7940e6 2020 if (!skip_rmap_check
e73c112e 2021 && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2022 struct bgp_path_info rmap_path = {0};
2023 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2024 struct attr dummy_attr = {0};
d62a17ae 2025
e34291b8 2026 /* Fill temp path_info */
9bcb3eef
DS
2027 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2028 pi, peer, attr);
16f7ce2b 2029
d62a17ae 2030 /* don't confuse inbound and outbound setting */
2031 RESET_FLAG(attr->rmap_change_flags);
2032
2033 /*
2034 * The route reflector is not allowed to modify the attributes
2035 * of the reflected IBGP routes unless explicitly allowed.
2036 */
2037 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2038 && !CHECK_FLAG(bgp->flags,
2039 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2040 dummy_attr = *attr;
40381db7 2041 rmap_path.attr = &dummy_attr;
d62a17ae 2042 }
3f9c7369 2043
d62a17ae 2044 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2045
4056a5f6 2046 if (bgp_path_suppressed(pi))
d62a17ae 2047 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
40381db7 2048 RMAP_BGP, &rmap_path);
d62a17ae 2049 else
2050 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
40381db7 2051 RMAP_BGP, &rmap_path);
d62a17ae 2052
2053 peer->rmap_type = 0;
2054
2055 if (ret == RMAP_DENYMATCH) {
778048bf 2056 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2057 zlog_debug(
2058 "%s [Update:SEND] %pFX is filtered by route-map",
2059 peer->host, p);
778048bf 2060
d62a17ae 2061 bgp_attr_flush(attr);
3dc339cd 2062 return false;
d62a17ae 2063 }
3f9c7369 2064 }
3f9c7369 2065
9dac9fc8
DA
2066 /* RFC 8212 to prevent route leaks.
2067 * This specification intends to improve this situation by requiring the
2068 * explicit configuration of both BGP Import and Export Policies for any
2069 * External BGP (EBGP) session such as customers, peers, or
2070 * confederation boundaries for all enabled address families. Through
2071 * codification of the aforementioned requirement, operators will
2072 * benefit from consistent behavior across different BGP
2073 * implementations.
2074 */
1d3fdccf 2075 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
9dac9fc8 2076 if (!bgp_outbound_policy_exists(peer, filter))
3dc339cd 2077 return false;
9dac9fc8 2078
fb29348a
DA
2079 /* draft-ietf-idr-deprecate-as-set-confed-set
2080 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2081 * Eventually, This document (if approved) updates RFC 4271
2082 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2083 * and obsoletes RFC 6472.
2084 */
7f972cd8 2085 if (peer->bgp->reject_as_sets)
fb29348a 2086 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2087 return false;
fb29348a 2088
33d022bc
DA
2089 /* Codification of AS 0 Processing */
2090 if (aspath_check_as_zero(attr->aspath))
e2369003 2091 return false;
33d022bc 2092
637e5ba4 2093 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2094 if (peer->sort == BGP_PEER_IBGP
2095 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2096 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2097 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2098 } else {
2099 bgp_attr_add_gshut_community(attr);
2100 }
2101 }
2102
d62a17ae 2103 /* After route-map has been applied, we check to see if the nexthop to
2104 * be carried in the attribute (that is used for the announcement) can
2105 * be cleared off or not. We do this in all cases where we would be
2106 * setting the nexthop to "ourselves". For IPv6, we only need to
2107 * consider
2108 * the global nexthop here; the link-local nexthop would have been
2109 * cleared
2110 * already, and if not, it is required by the update formation code.
2111 * Also see earlier comments in this function.
2112 */
2113 /*
2114 * If route-map has performed some operation on the nexthop or the peer
2115 * configuration says to pass it unchanged, we cannot reset the nexthop
2116 * here, so only attempt to do it if these aren't true. Note that the
2117 * route-map handler itself might have cleared the nexthop, if for
2118 * example,
2119 * it is configured as 'peer-address'.
2120 */
2121 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2122 piattr->rmap_change_flags)
d62a17ae 2123 && !transparent
2124 && !CHECK_FLAG(peer->af_flags[afi][safi],
2125 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2126 /* We can reset the nexthop, if setting (or forcing) it to
2127 * 'self' */
2128 if (CHECK_FLAG(peer->af_flags[afi][safi],
2129 PEER_FLAG_NEXTHOP_SELF)
2130 || CHECK_FLAG(peer->af_flags[afi][safi],
2131 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2132 if (!reflect
2133 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2134 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2135 subgroup_announce_reset_nhop(
2136 (peer_cap_enhe(peer, afi, safi)
2137 ? AF_INET6
2138 : p->family),
2139 attr);
7b651a32 2140 nh_reset = true;
2141 }
d62a17ae 2142 } else if (peer->sort == BGP_PEER_EBGP) {
2143 /* Can also reset the nexthop if announcing to EBGP, but
2144 * only if
2145 * no peer in the subgroup is on a shared subnet.
2146 * Note: 3rd party nexthop currently implemented for
2147 * IPv4 only.
2148 */
737af885
BS
2149 if ((p->family == AF_INET) &&
2150 (!bgp_subgrp_multiaccess_check_v4(
2151 piattr->nexthop,
7b651a32 2152 subgrp, from))) {
d62a17ae 2153 subgroup_announce_reset_nhop(
2154 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2155 ? AF_INET6
2156 : p->family),
737af885 2157 attr);
7b651a32 2158 nh_reset = true;
2159 }
737af885
BS
2160
2161 if ((p->family == AF_INET6) &&
2162 (!bgp_subgrp_multiaccess_check_v6(
2163 piattr->mp_nexthop_global,
7b651a32 2164 subgrp, from))) {
737af885
BS
2165 subgroup_announce_reset_nhop(
2166 (peer_cap_enhe(peer, afi, safi)
2167 ? AF_INET6
2168 : p->family),
2169 attr);
7b651a32 2170 nh_reset = true;
2171 }
737af885
BS
2172
2173
2174
40381db7 2175 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2176 /*
2177 * This flag is used for leaked vpn-vrf routes
2178 */
2179 int family = p->family;
2180
2181 if (peer_cap_enhe(peer, afi, safi))
2182 family = AF_INET6;
2183
2184 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2185 zlog_debug(
1defdda8 2186 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2187 __func__, family2str(family));
2188 subgroup_announce_reset_nhop(family, attr);
7b651a32 2189 nh_reset = true;
d62a17ae 2190 }
63696f1d 2191 }
960035b2 2192
63696f1d 2193 /* If IPv6/MP and nexthop does not have any override and happens
2194 * to
2195 * be a link-local address, reset it so that we don't pass along
2196 * the
2197 * source's link-local IPv6 address to recipients who may not be
2198 * on
2199 * the same interface.
2200 */
2201 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2202 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2203 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2204 nh_reset = true;
2205 }
d62a17ae 2206 }
3f9c7369 2207
7b651a32 2208 /*
2209 * When the next hop is set to ourselves, if all multipaths have
2210 * link-bandwidth announce the cumulative bandwidth as that makes
2211 * the most sense. However, don't modify if the link-bandwidth has
2212 * been explicitly set by user policy.
2213 */
2214 if (nh_reset &&
f7e1c681 2215 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2216 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2217 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2218 attr->ecommunity = ecommunity_replace_linkbw(
2219 bgp->as, attr->ecommunity, cum_bw);
2220
3dc339cd 2221 return true;
3f9c7369
DS
2222}
2223
f009ff26 2224static int bgp_route_select_timer_expire(struct thread *thread)
2225{
2226 struct afi_safi_info *info;
2227 afi_t afi;
2228 safi_t safi;
2229 struct bgp *bgp;
2230
2231 info = THREAD_ARG(thread);
2232 afi = info->afi;
2233 safi = info->safi;
2234 bgp = info->bgp;
2235
2236 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2237 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2238 safi);
f009ff26 2239
2240 bgp->gr_info[afi][safi].t_route_select = NULL;
2241
2242 XFREE(MTYPE_TMP, info);
2243
2244 /* Best path selection */
2245 return bgp_best_path_select_defer(bgp, afi, safi);
2246}
2247
9bcb3eef 2248void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2249 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2250 struct bgp_path_info_pair *result, afi_t afi,
2251 safi_t safi)
2252{
2253 struct bgp_path_info *new_select;
2254 struct bgp_path_info *old_select;
40381db7
DS
2255 struct bgp_path_info *pi;
2256 struct bgp_path_info *pi1;
2257 struct bgp_path_info *pi2;
2258 struct bgp_path_info *nextpi = NULL;
d62a17ae 2259 int paths_eq, do_mpath, debug;
2260 struct list mp_list;
2261 char pfx_buf[PREFIX2STR_BUFFER];
2262 char path_buf[PATH_ADDPATH_STR_BUFFER];
2263
2264 bgp_mp_list_init(&mp_list);
2265 do_mpath =
2266 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2267
9bcb3eef 2268 debug = bgp_debug_bestpath(dest);
d62a17ae 2269
2270 if (debug)
9bcb3eef 2271 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2272
9bcb3eef 2273 dest->reason = bgp_path_selection_none;
d62a17ae 2274 /* bgp deterministic-med */
2275 new_select = NULL;
892fedb6 2276 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2277
1defdda8 2278 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2279 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2280 pi1 = pi1->next)
9bcb3eef 2281 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2282 BGP_PATH_DMED_SELECTED);
d62a17ae 2283
9bcb3eef 2284 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2285 pi1 = pi1->next) {
40381db7 2286 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2287 continue;
40381db7 2288 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2289 continue;
ea8b2282 2290 if (pi1->peer != bgp->peer_self)
40381db7 2291 if (pi1->peer->status != Established)
d62a17ae 2292 continue;
2293
40381db7
DS
2294 new_select = pi1;
2295 if (pi1->next) {
2296 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2297 if (CHECK_FLAG(pi2->flags,
1defdda8 2298 BGP_PATH_DMED_CHECK))
d62a17ae 2299 continue;
40381db7 2300 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2301 continue;
ea8b2282 2302 if (pi2->peer != bgp->peer_self
d62a17ae 2303 && !CHECK_FLAG(
ea8b2282
DS
2304 pi2->peer->sflags,
2305 PEER_STATUS_NSF_WAIT))
40381db7 2306 if (pi2->peer->status
d62a17ae 2307 != Established)
2308 continue;
2309
121e245d
DS
2310 if (!aspath_cmp_left(pi1->attr->aspath,
2311 pi2->attr->aspath)
2312 && !aspath_cmp_left_confed(
40381db7 2313 pi1->attr->aspath,
121e245d
DS
2314 pi2->attr->aspath))
2315 continue;
d62a17ae 2316
121e245d
DS
2317 if (bgp_path_info_cmp(
2318 bgp, pi2, new_select,
2319 &paths_eq, mpath_cfg, debug,
fdf81fa0 2320 pfx_buf, afi, safi,
9bcb3eef 2321 &dest->reason)) {
121e245d 2322 bgp_path_info_unset_flag(
9bcb3eef 2323 dest, new_select,
121e245d
DS
2324 BGP_PATH_DMED_SELECTED);
2325 new_select = pi2;
d62a17ae 2326 }
121e245d
DS
2327
2328 bgp_path_info_set_flag(
9bcb3eef 2329 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2330 }
2331 }
9bcb3eef 2332 bgp_path_info_set_flag(dest, new_select,
18ee8310 2333 BGP_PATH_DMED_CHECK);
9bcb3eef 2334 bgp_path_info_set_flag(dest, new_select,
18ee8310 2335 BGP_PATH_DMED_SELECTED);
d62a17ae 2336
2337 if (debug) {
18ee8310
DS
2338 bgp_path_info_path_with_addpath_rx_str(
2339 new_select, path_buf);
8228a9a7
DS
2340 zlog_debug(
2341 "%pBD: %s is the bestpath from AS %u",
2342 dest, path_buf,
2343 aspath_get_first_as(
2344 new_select->attr->aspath));
d62a17ae 2345 }
2346 }
2347 }
96450faf 2348
d62a17ae 2349 /* Check old selected route and new selected route. */
2350 old_select = NULL;
2351 new_select = NULL;
9bcb3eef 2352 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2353 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2354 enum bgp_path_selection_reason reason;
2355
40381db7
DS
2356 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2357 old_select = pi;
d62a17ae 2358
40381db7 2359 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2360 /* reap REMOVED routes, if needs be
2361 * selected route must stay for a while longer though
2362 */
40381db7
DS
2363 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2364 && (pi != old_select))
9bcb3eef 2365 bgp_path_info_reap(dest, pi);
d62a17ae 2366
ddb5b488 2367 if (debug)
40381db7
DS
2368 zlog_debug("%s: pi %p in holddown", __func__,
2369 pi);
ddb5b488 2370
d62a17ae 2371 continue;
2372 }
96450faf 2373
40381db7
DS
2374 if (pi->peer && pi->peer != bgp->peer_self
2375 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2376 if (pi->peer->status != Established) {
ddb5b488
PZ
2377
2378 if (debug)
2379 zlog_debug(
40381db7
DS
2380 "%s: pi %p non self peer %s not estab state",
2381 __func__, pi, pi->peer->host);
ddb5b488 2382
d62a17ae 2383 continue;
ddb5b488 2384 }
9fbdd100 2385
892fedb6 2386 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2387 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2388 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2389 if (debug)
40381db7 2390 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2391 continue;
2392 }
9fbdd100 2393
9bcb3eef 2394 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2395
9bcb3eef 2396 reason = dest->reason;
40381db7 2397 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2398 debug, pfx_buf, afi, safi,
2399 &dest->reason)) {
19ea4cec
DS
2400 if (new_select == NULL &&
2401 reason != bgp_path_selection_none)
9bcb3eef 2402 dest->reason = reason;
40381db7 2403 new_select = pi;
d62a17ae 2404 }
2405 }
718e3744 2406
d62a17ae 2407 /* Now that we know which path is the bestpath see if any of the other
2408 * paths
2409 * qualify as multipaths
2410 */
2411 if (debug) {
2412 if (new_select)
18ee8310
DS
2413 bgp_path_info_path_with_addpath_rx_str(new_select,
2414 path_buf);
d62a17ae 2415 else
772270f3 2416 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2417 zlog_debug(
8228a9a7
DS
2418 "%pBD: After path selection, newbest is %s oldbest was %s",
2419 dest, path_buf,
d62a17ae 2420 old_select ? old_select->peer->host : "NONE");
96450faf 2421 }
9fbdd100 2422
d62a17ae 2423 if (do_mpath && new_select) {
9bcb3eef 2424 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2425 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2426
2427 if (debug)
18ee8310 2428 bgp_path_info_path_with_addpath_rx_str(
40381db7 2429 pi, path_buf);
d62a17ae 2430
40381db7 2431 if (pi == new_select) {
d62a17ae 2432 if (debug)
2433 zlog_debug(
8228a9a7
DS
2434 "%pBD: %s is the bestpath, add to the multipath list",
2435 dest, path_buf);
40381db7 2436 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2437 continue;
2438 }
2439
40381db7 2440 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2441 continue;
2442
40381db7
DS
2443 if (pi->peer && pi->peer != bgp->peer_self
2444 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2445 PEER_STATUS_NSF_WAIT))
40381db7 2446 if (pi->peer->status != Established)
d62a17ae 2447 continue;
2448
40381db7 2449 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2450 if (debug)
2451 zlog_debug(
8228a9a7
DS
2452 "%pBD: %s has the same nexthop as the bestpath, skip it",
2453 dest, path_buf);
d62a17ae 2454 continue;
2455 }
2456
40381db7 2457 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2458 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2459 &dest->reason);
d62a17ae 2460
2461 if (paths_eq) {
2462 if (debug)
2463 zlog_debug(
8228a9a7
DS
2464 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2465 dest, path_buf);
40381db7 2466 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2467 }
2468 }
2469 }
fee0f4c6 2470
9bcb3eef 2471 bgp_path_info_mpath_update(dest, new_select, old_select, &mp_list,
18ee8310
DS
2472 mpath_cfg);
2473 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2474 bgp_mp_list_clear(&mp_list);
96450faf 2475
9bcb3eef 2476 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2477
d62a17ae 2478 result->old = old_select;
2479 result->new = new_select;
96450faf 2480
d62a17ae 2481 return;
fee0f4c6 2482}
2483
3f9c7369
DS
2484/*
2485 * A new route/change in bestpath of an existing route. Evaluate the path
2486 * for advertisement to the subgroup.
2487 */
3dc339cd
DA
2488void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2489 struct bgp_path_info *selected,
9bcb3eef 2490 struct bgp_dest *dest,
3dc339cd 2491 uint32_t addpath_tx_id)
d62a17ae 2492{
b54892e0 2493 const struct prefix *p;
d62a17ae 2494 struct peer *onlypeer;
2495 struct attr attr;
2496 afi_t afi;
2497 safi_t safi;
adbac85e 2498
9bcb3eef 2499 p = bgp_dest_get_prefix(dest);
d62a17ae 2500 afi = SUBGRP_AFI(subgrp);
2501 safi = SUBGRP_SAFI(subgrp);
2502 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2503 : NULL);
2504
2dbe669b
DA
2505 if (BGP_DEBUG(update, UPDATE_OUT))
2506 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2507
d62a17ae 2508 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2509 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2510 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2511 return;
d62a17ae 2512
2513 memset(&attr, 0, sizeof(struct attr));
2514 /* It's initialized in bgp_announce_check() */
2515
2516 /* Announcement to the subgroup. If the route is filtered withdraw it.
2517 */
2518 if (selected) {
7f7940e6
MK
2519 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
2520 false))
9bcb3eef 2521 bgp_adj_out_set_subgroup(dest, subgrp, &attr, selected);
d62a17ae 2522 else
9bcb3eef 2523 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2524 addpath_tx_id);
d62a17ae 2525 }
2526
2527 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2528 else {
9bcb3eef 2529 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2530 }
200df115 2531}
fee0f4c6 2532
3064bf43 2533/*
e1072051 2534 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2535 * This is called at the end of route processing.
3064bf43 2536 */
9bcb3eef 2537void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2538{
40381db7 2539 struct bgp_path_info *pi;
3064bf43 2540
9bcb3eef 2541 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2542 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2543 continue;
40381db7
DS
2544 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2545 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2546 }
3064bf43 2547}
2548
2549/*
2550 * Has the route changed from the RIB's perspective? This is invoked only
2551 * if the route selection returns the same best route as earlier - to
2552 * determine if we need to update zebra or not.
2553 */
9bcb3eef 2554bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2555{
4b7e6066 2556 struct bgp_path_info *mpinfo;
d62a17ae 2557
2bb9eff4
DS
2558 /* If this is multipath, check all selected paths for any nexthop
2559 * change or attribute change. Some attribute changes (e.g., community)
2560 * aren't of relevance to the RIB, but we'll update zebra to ensure
2561 * we handle the case of BGP nexthop change. This is the behavior
2562 * when the best path has an attribute change anyway.
d62a17ae 2563 */
1defdda8 2564 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2565 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2566 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2567 return true;
d62a17ae 2568
2bb9eff4
DS
2569 /*
2570 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2571 */
18ee8310
DS
2572 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2573 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2574 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2575 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2576 return true;
d62a17ae 2577 }
3064bf43 2578
d62a17ae 2579 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2580 return false;
3064bf43 2581}
2582
d62a17ae 2583struct bgp_process_queue {
2584 struct bgp *bgp;
9bcb3eef 2585 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2586#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2587 unsigned int flags;
2588 unsigned int queued;
200df115 2589};
2590
3b0c17e1 2591static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2592 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2593 struct bgp_path_info *new_select,
2594 struct bgp_path_info *old_select)
2595{
9bcb3eef 2596 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2597
2598 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2599 return;
2600
2601 if (advertise_type5_routes(bgp, afi) && new_select
2602 && is_route_injectable_into_evpn(new_select)) {
2603
2604 /* apply the route-map */
2605 if (bgp->adv_cmd_rmap[afi][safi].map) {
2606 route_map_result_t ret;
2607 struct bgp_path_info rmap_path;
2608 struct bgp_path_info_extra rmap_path_extra;
2609 struct attr dummy_attr;
2610
2611 dummy_attr = *new_select->attr;
2612
2613 /* Fill temp path_info */
9bcb3eef 2614 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2615 new_select, new_select->peer,
2616 &dummy_attr);
2617
2618 RESET_FLAG(dummy_attr.rmap_change_flags);
2619
2620 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
2621 p, RMAP_BGP, &rmap_path);
2622
2623 if (ret == RMAP_DENYMATCH) {
2624 bgp_attr_flush(&dummy_attr);
2625 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2626 safi);
2627 } else
2628 bgp_evpn_advertise_type5_route(
2629 bgp, p, &dummy_attr, afi, safi);
2630 } else {
2631 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2632 afi, safi);
2633 }
2634 } else if (advertise_type5_routes(bgp, afi) && old_select
2635 && is_route_injectable_into_evpn(old_select))
2636 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2637}
2638
3103e8d2
DS
2639/*
2640 * old_select = The old best path
2641 * new_select = the new best path
2642 *
2643 * if (!old_select && new_select)
2644 * We are sending new information on.
2645 *
2646 * if (old_select && new_select) {
2647 * if (new_select != old_select)
2648 * We have a new best path send a change
2649 * else
2650 * We've received a update with new attributes that needs
2651 * to be passed on.
2652 * }
2653 *
2654 * if (old_select && !new_select)
2655 * We have no eligible route that we can announce or the rn
2656 * is being removed.
2657 */
9bcb3eef 2658static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2659 afi_t afi, safi_t safi)
d62a17ae 2660{
4b7e6066
DS
2661 struct bgp_path_info *new_select;
2662 struct bgp_path_info *old_select;
2663 struct bgp_path_info_pair old_and_new;
ddb5b488 2664 int debug = 0;
d62a17ae 2665
892fedb6 2666 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2667 if (dest)
2668 debug = bgp_debug_bestpath(dest);
b54892e0 2669 if (debug)
f4c713ae 2670 zlog_debug(
56ca3b5b 2671 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2672 __func__, dest);
f4c713ae
LB
2673 return;
2674 }
d62a17ae 2675 /* Is it end of initial update? (after startup) */
9bcb3eef 2676 if (!dest) {
d62a17ae 2677 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2678 sizeof(bgp->update_delay_zebra_resume_time));
2679
2680 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2681 FOREACH_AFI_SAFI (afi, safi) {
2682 if (bgp_fibupd_safi(safi))
2683 bgp_zebra_announce_table(bgp, afi, safi);
2684 }
d62a17ae 2685 bgp->main_peers_update_hold = 0;
2686
2687 bgp_start_routeadv(bgp);
aac24838 2688 return;
d62a17ae 2689 }
cb1faec9 2690
9bcb3eef 2691 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2692
9bcb3eef 2693 debug = bgp_debug_bestpath(dest);
b54892e0 2694 if (debug)
56ca3b5b 2695 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__, dest,
ddb5b488 2696 afi2str(afi), safi2str(safi));
ddb5b488 2697
f009ff26 2698 /* The best path calculation for the route is deferred if
2699 * BGP_NODE_SELECT_DEFER is set
2700 */
9bcb3eef 2701 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2702 if (BGP_DEBUG(update, UPDATE_OUT))
9bcb3eef 2703 zlog_debug("SELECT_DEFER falg set for route %p", dest);
f009ff26 2704 return;
2705 }
2706
d62a17ae 2707 /* Best path selection. */
9bcb3eef 2708 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2709 afi, safi);
2710 old_select = old_and_new.old;
2711 new_select = old_and_new.new;
2712
2713 /* Do we need to allocate or free labels?
2714 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2715 * necessary to do this upon changes to best path. Exceptions:
2716 * - label index has changed -> recalculate resulting label
2717 * - path_info sub_type changed -> switch to/from implicit-null
2718 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2719 */
318cac96 2720 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2721 if (new_select) {
2722 if (!old_select
2723 || bgp_label_index_differs(new_select, old_select)
57592a53 2724 || new_select->sub_type != old_select->sub_type
9bcb3eef 2725 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2726 /* Enforced penultimate hop popping:
2727 * implicit-null for local routes, aggregate
2728 * and redistributed routes
2729 */
d62a17ae 2730 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2731 || new_select->sub_type
2732 == BGP_ROUTE_AGGREGATE
2733 || new_select->sub_type
2734 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2735 if (CHECK_FLAG(
9bcb3eef 2736 dest->flags,
d62a17ae 2737 BGP_NODE_REGISTERED_FOR_LABEL))
9bcb3eef 2738 bgp_unregister_for_label(dest);
70e98a7f 2739 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2740 &dest->local_label);
2741 bgp_set_valid_label(&dest->local_label);
d62a17ae 2742 } else
9bcb3eef
DS
2743 bgp_register_for_label(dest,
2744 new_select);
d62a17ae 2745 }
9bcb3eef 2746 } else if (CHECK_FLAG(dest->flags,
a4d82a8a 2747 BGP_NODE_REGISTERED_FOR_LABEL)) {
9bcb3eef 2748 bgp_unregister_for_label(dest);
318cac96 2749 }
9bcb3eef
DS
2750 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
2751 bgp_unregister_for_label(dest);
d62a17ae 2752 }
cd1964ff 2753
b54892e0 2754 if (debug)
ddb5b488 2755 zlog_debug(
56ca3b5b 2756 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
9bcb3eef 2757 __func__, dest, afi2str(afi), safi2str(safi),
ddb5b488 2758 old_select, new_select);
ddb5b488 2759
d62a17ae 2760 /* If best route remains the same and this is not due to user-initiated
2761 * clear, see exactly what needs to be done.
2762 */
d62a17ae 2763 if (old_select && old_select == new_select
9bcb3eef 2764 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2765 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2766 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2767 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2768#ifdef ENABLE_BGP_VNC
d62a17ae 2769 vnc_import_bgp_add_route(bgp, p, old_select);
2770 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2771#endif
bb744275 2772 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2773 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2774
2775 if (new_select->type == ZEBRA_ROUTE_BGP
2776 && (new_select->sub_type == BGP_ROUTE_NORMAL
2777 || new_select->sub_type
2778 == BGP_ROUTE_IMPORTED))
2779
9bcb3eef 2780 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
2781 bgp, afi, safi);
2782 }
d62a17ae 2783 }
d62a17ae 2784
2785 /* If there is a change of interest to peers, reannounce the
2786 * route. */
1defdda8 2787 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 2788 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
2789 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2790 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2791
2792 /* unicast routes must also be annouced to
2793 * labeled-unicast update-groups */
2794 if (safi == SAFI_UNICAST)
2795 group_announce_route(bgp, afi,
9bcb3eef 2796 SAFI_LABELED_UNICAST, dest,
d62a17ae 2797 new_select);
2798
1defdda8 2799 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 2800 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 2801 }
fee0f4c6 2802
3b0c17e1 2803 /* advertise/withdraw type-5 routes */
2804 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2805 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2806 bgp_process_evpn_route_injection(
9bcb3eef 2807 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 2808
b1875e65 2809 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2810 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
2811 bgp_zebra_clear_route_change_flags(dest);
2812 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2813 return;
d62a17ae 2814 }
8ad7271d 2815
d62a17ae 2816 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2817 */
9bcb3eef 2818 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 2819
2820 /* bestpath has changed; bump version */
2821 if (old_select || new_select) {
9bcb3eef 2822 bgp_bump_version(dest);
d62a17ae 2823
2824 if (!bgp->t_rmap_def_originate_eval) {
2825 bgp_lock(bgp);
2826 thread_add_timer(
2827 bm->master,
2828 update_group_refresh_default_originate_route_map,
2829 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2830 &bgp->t_rmap_def_originate_eval);
2831 }
2832 }
3f9c7369 2833
d62a17ae 2834 if (old_select)
9bcb3eef 2835 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 2836 if (new_select) {
ddb5b488
PZ
2837 if (debug)
2838 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
2839 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2840 bgp_path_info_unset_flag(dest, new_select,
2841 BGP_PATH_ATTR_CHANGED);
1defdda8 2842 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 2843 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 2844 }
338b3424 2845
49e5a4a0 2846#ifdef ENABLE_BGP_VNC
d62a17ae 2847 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2848 if (old_select != new_select) {
2849 if (old_select) {
2850 vnc_import_bgp_exterior_del_route(bgp, p,
2851 old_select);
2852 vnc_import_bgp_del_route(bgp, p, old_select);
2853 }
2854 if (new_select) {
2855 vnc_import_bgp_exterior_add_route(bgp, p,
2856 new_select);
2857 vnc_import_bgp_add_route(bgp, p, new_select);
2858 }
2859 }
2860 }
65efcfce
LB
2861#endif
2862
9bcb3eef 2863 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2864
2865 /* unicast routes must also be annouced to labeled-unicast update-groups
2866 */
2867 if (safi == SAFI_UNICAST)
9bcb3eef 2868 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 2869 new_select);
2870
2871 /* FIB update. */
2872 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2873 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2874 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2875 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2876 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2877 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2878
2879 /* if this is an evpn imported type-5 prefix,
2880 * we need to withdraw the route first to clear
2881 * the nh neigh and the RMAC entry.
2882 */
2883 if (old_select &&
2884 is_route_parent_evpn(old_select))
2885 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2886
9bcb3eef 2887 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 2888 } else {
d62a17ae 2889 /* Withdraw the route from the kernel. */
2890 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2891 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2892 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2893 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2894
568e10ca 2895 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2896 }
718e3744 2897 }
3064bf43 2898
9bcb3eef 2899 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 2900 old_select);
5424b7ba 2901
d62a17ae 2902 /* Clear any route change flags. */
9bcb3eef 2903 bgp_zebra_clear_route_change_flags(dest);
3064bf43 2904
18ee8310 2905 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2906 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 2907 bgp_path_info_reap(dest, old_select);
d62a17ae 2908
9bcb3eef 2909 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2910 return;
718e3744 2911}
2912
f009ff26 2913/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2914int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2915{
9bcb3eef 2916 struct bgp_dest *dest;
f009ff26 2917 int cnt = 0;
2918 struct afi_safi_info *thread_info;
2919 struct listnode *node = NULL, *nnode = NULL;
2920
2921 if (bgp->gr_info[afi][safi].t_route_select)
2922 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
2923
2924 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
2925 zlog_debug("%s: processing route for %s : cnt %d", __func__,
2926 get_afi_safi_str(afi, safi, false),
2927 listcount(bgp->gr_info[afi][safi].route_list));
f009ff26 2928 }
2929
2930 /* Process the route list */
2931 node = listhead(bgp->gr_info[afi][safi].route_list);
f009ff26 2932 while (node) {
9bcb3eef 2933 dest = listgetdata(node);
f009ff26 2934 nnode = node->next;
2935 list_delete_node(bgp->gr_info[afi][safi].route_list, node);
9bcb3eef 2936 dest->rt_node = NULL;
f009ff26 2937
9bcb3eef
DS
2938 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
2939 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
2940 bgp_process_main_one(bgp, dest, afi, safi);
f009ff26 2941 cnt++;
2942 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT)
2943 break;
2944 }
2945 node = nnode;
2946 }
2947
9e3b51a7 2948 /* Send EOR message when all routes are processed */
2949 if (list_isempty(bgp->gr_info[afi][safi].route_list)) {
2950 bgp_send_delayed_eor(bgp);
8c48b3b6 2951 /* Send route processing complete message to RIB */
2952 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 2953 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 2954 return 0;
9e3b51a7 2955 }
f009ff26 2956
2957 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 2958
2959 thread_info->afi = afi;
2960 thread_info->safi = safi;
2961 thread_info->bgp = bgp;
2962
2963 /* If there are more routes to be processed, start the
2964 * selection timer
2965 */
2966 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
2967 BGP_ROUTE_SELECT_DELAY,
2968 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 2969 return 0;
2970}
2971
aac24838 2972static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 2973{
aac24838
JB
2974 struct bgp_process_queue *pqnode = data;
2975 struct bgp *bgp = pqnode->bgp;
d62a17ae 2976 struct bgp_table *table;
9bcb3eef 2977 struct bgp_dest *dest;
aac24838
JB
2978
2979 /* eoiu marker */
2980 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
2981 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
2982 /* should always have dedicated wq call */
2983 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
2984 return WQ_SUCCESS;
2985 }
2986
ac021f40 2987 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 2988 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 2989 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
2990 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
2991 table = bgp_dest_table(dest);
2992 /* note, new DESTs may be added as part of processing */
2993 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 2994
9bcb3eef 2995 bgp_dest_unlock_node(dest);
d62a17ae 2996 bgp_table_unlock(table);
2997 }
aac24838
JB
2998
2999 return WQ_SUCCESS;
3000}
3001
3002static void bgp_processq_del(struct work_queue *wq, void *data)
3003{
3004 struct bgp_process_queue *pqnode = data;
3005
3006 bgp_unlock(pqnode->bgp);
3007
3008 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3009}
3010
b6c386bb 3011void bgp_process_queue_init(struct bgp *bgp)
200df115 3012{
b6c386bb
DS
3013 if (!bgp->process_queue) {
3014 char name[BUFSIZ];
3015
3016 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3017 bgp->process_queue = work_queue_new(bm->master, name);
3018 }
3019
3020 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3021 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3022 bgp->process_queue->spec.max_retries = 0;
3023 bgp->process_queue->spec.hold = 50;
d62a17ae 3024 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3025 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3026}
3027
cfe8d15a 3028static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3029{
3030 struct bgp_process_queue *pqnode;
3031
a4d82a8a
PZ
3032 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3033 sizeof(struct bgp_process_queue));
aac24838
JB
3034
3035 /* unlocked in bgp_processq_del */
3036 pqnode->bgp = bgp_lock(bgp);
3037 STAILQ_INIT(&pqnode->pqueue);
3038
aac24838
JB
3039 return pqnode;
3040}
3041
9bcb3eef 3042void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3043{
aac24838 3044#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3045 struct work_queue *wq = bgp->process_queue;
d62a17ae 3046 struct bgp_process_queue *pqnode;
cfe8d15a 3047 int pqnode_reuse = 0;
495f0b13 3048
d62a17ae 3049 /* already scheduled for processing? */
9bcb3eef 3050 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3051 return;
2e02b9b2 3052
f009ff26 3053 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3054 * the workqueue
3055 */
9bcb3eef 3056 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3057 if (BGP_DEBUG(update, UPDATE_OUT))
3058 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3059 dest);
f009ff26 3060 return;
3061 }
3062
aac24838 3063 if (wq == NULL)
d62a17ae 3064 return;
3065
aac24838 3066 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3067 limit only if is from the same BGP view and it's not an EOIU marker
3068 */
aac24838
JB
3069 if (work_queue_item_count(wq)) {
3070 struct work_queue_item *item = work_queue_last_item(wq);
3071 pqnode = item->data;
228da428 3072
a4d82a8a
PZ
3073 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3074 || pqnode->bgp != bgp
3075 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3076 pqnode = bgp_processq_alloc(bgp);
3077 else
3078 pqnode_reuse = 1;
aac24838 3079 } else
cfe8d15a 3080 pqnode = bgp_processq_alloc(bgp);
aac24838 3081 /* all unlocked in bgp_process_wq */
9bcb3eef 3082 bgp_table_lock(bgp_dest_table(dest));
aac24838 3083
9bcb3eef
DS
3084 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3085 bgp_dest_lock_node(dest);
aac24838 3086
60466a63 3087 /* can't be enqueued twice */
9bcb3eef
DS
3088 assert(STAILQ_NEXT(dest, pq) == NULL);
3089 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3090 pqnode->queued++;
3091
cfe8d15a
LB
3092 if (!pqnode_reuse)
3093 work_queue_add(wq, pqnode);
3094
d62a17ae 3095 return;
fee0f4c6 3096}
0a486e5f 3097
d62a17ae 3098void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3099{
d62a17ae 3100 struct bgp_process_queue *pqnode;
cb1faec9 3101
b6c386bb 3102 if (bgp->process_queue == NULL)
d62a17ae 3103 return;
2e02b9b2 3104
cfe8d15a 3105 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3106
aac24838 3107 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3108 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3109}
3110
d62a17ae 3111static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3112{
d62a17ae 3113 struct peer *peer;
0a486e5f 3114
d62a17ae 3115 peer = THREAD_ARG(thread);
3116 peer->t_pmax_restart = NULL;
0a486e5f 3117
d62a17ae 3118 if (bgp_debug_neighbor_events(peer))
3119 zlog_debug(
3120 "%s Maximum-prefix restart timer expired, restore peering",
3121 peer->host);
0a486e5f 3122
a9bafa95 3123 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3124 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3125
d62a17ae 3126 return 0;
0a486e5f 3127}
3128
9cbd06e0
DA
3129static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3130 safi_t safi)
3131{
3132 uint32_t count = 0;
f41b0459 3133 bool filtered = false;
9cbd06e0
DA
3134 struct bgp_dest *dest;
3135 struct bgp_adj_in *ain;
40bb2ccf 3136 struct attr attr = {};
9cbd06e0
DA
3137 struct bgp_table *table = peer->bgp->rib[afi][safi];
3138
3139 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3140 for (ain = dest->adj_in; ain; ain = ain->next) {
3141 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3142
3143 attr = *ain->attr;
9cbd06e0
DA
3144
3145 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3146 == FILTER_DENY)
f41b0459
DA
3147 filtered = true;
3148
3149 if (bgp_input_modifier(
3150 peer, rn_p, &attr, afi, safi,
3151 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3152 NULL, 0, NULL)
3153 == RMAP_DENY)
3154 filtered = true;
3155
3156 if (filtered)
9cbd06e0 3157 count++;
f41b0459
DA
3158
3159 bgp_attr_undup(&attr, ain->attr);
9cbd06e0
DA
3160 }
3161 }
3162
3163 return count;
3164}
3165
3dc339cd
DA
3166bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3167 int always)
718e3744 3168{
d62a17ae 3169 iana_afi_t pkt_afi;
5c525538 3170 iana_safi_t pkt_safi;
9cbd06e0
DA
3171 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3172 PEER_FLAG_MAX_PREFIX_FORCE))
3173 ? bgp_filtered_routes_count(peer, afi, safi)
3174 + peer->pcount[afi][safi]
3175 : peer->pcount[afi][safi];
9cabb64b 3176
d62a17ae 3177 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3178 return false;
e0701b79 3179
9cbd06e0 3180 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3181 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3182 PEER_STATUS_PREFIX_LIMIT)
3183 && !always)
3dc339cd 3184 return false;
e0701b79 3185
d62a17ae 3186 zlog_info(
6cde4b45 3187 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
9cbd06e0
DA
3188 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3189 peer->pmax[afi][safi]);
d62a17ae 3190 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3191
3192 if (CHECK_FLAG(peer->af_flags[afi][safi],
3193 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3194 return false;
d62a17ae 3195
3196 /* Convert AFI, SAFI to values for packet. */
3197 pkt_afi = afi_int2iana(afi);
3198 pkt_safi = safi_int2iana(safi);
3199 {
d7c0a89a 3200 uint8_t ndata[7];
d62a17ae 3201
3202 ndata[0] = (pkt_afi >> 8);
3203 ndata[1] = pkt_afi;
3204 ndata[2] = pkt_safi;
3205 ndata[3] = (peer->pmax[afi][safi] >> 24);
3206 ndata[4] = (peer->pmax[afi][safi] >> 16);
3207 ndata[5] = (peer->pmax[afi][safi] >> 8);
3208 ndata[6] = (peer->pmax[afi][safi]);
3209
3210 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3211 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3212 BGP_NOTIFY_CEASE_MAX_PREFIX,
3213 ndata, 7);
3214 }
3215
3216 /* Dynamic peers will just close their connection. */
3217 if (peer_dynamic_neighbor(peer))
3dc339cd 3218 return true;
d62a17ae 3219
3220 /* restart timer start */
3221 if (peer->pmax_restart[afi][safi]) {
3222 peer->v_pmax_restart =
3223 peer->pmax_restart[afi][safi] * 60;
3224
3225 if (bgp_debug_neighbor_events(peer))
3226 zlog_debug(
3227 "%s Maximum-prefix restart timer started for %d secs",
3228 peer->host, peer->v_pmax_restart);
3229
3230 BGP_TIMER_ON(peer->t_pmax_restart,
3231 bgp_maximum_prefix_restart_timer,
3232 peer->v_pmax_restart);
3233 }
3234
3dc339cd 3235 return true;
d62a17ae 3236 } else
3237 UNSET_FLAG(peer->af_sflags[afi][safi],
3238 PEER_STATUS_PREFIX_LIMIT);
3239
b1823b69
DS
3240 if (pcount
3241 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3242 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3243 PEER_STATUS_PREFIX_THRESHOLD)
3244 && !always)
3dc339cd 3245 return false;
d62a17ae 3246
3247 zlog_info(
6cde4b45 3248 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
9cbd06e0
DA
3249 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3250 peer->pmax[afi][safi]);
d62a17ae 3251 SET_FLAG(peer->af_sflags[afi][safi],
3252 PEER_STATUS_PREFIX_THRESHOLD);
3253 } else
3254 UNSET_FLAG(peer->af_sflags[afi][safi],
3255 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3256 return false;
718e3744 3257}
3258
b40d939b 3259/* Unconditionally remove the route from the RIB, without taking
3260 * damping into consideration (eg, because the session went down)
3261 */
9bcb3eef 3262void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3263 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3264{
f009ff26 3265
3266 struct bgp *bgp = NULL;
3267 bool delete_route = false;
3268
9bcb3eef
DS
3269 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3270 safi);
d62a17ae 3271
f009ff26 3272 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3273 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3274
f009ff26 3275 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3276 * flag
3277 */
3278 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3279 delete_route = true;
9bcb3eef 3280 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3281 delete_route = true;
f009ff26 3282 if (delete_route) {
9bcb3eef
DS
3283 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3284 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3285 bgp = pi->peer->bgp;
9bcb3eef 3286 if ((dest->rt_node)
36235319
QY
3287 && (bgp->gr_info[afi][safi].route_list)) {
3288 list_delete_node(bgp->gr_info[afi][safi]
3289 .route_list,
9bcb3eef
DS
3290 dest->rt_node);
3291 dest->rt_node = NULL;
f009ff26 3292 }
3293 }
3294 }
3295 }
4a11bf2c 3296
9bcb3eef
DS
3297 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3298 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3299}
3300
9bcb3eef 3301static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3302 struct peer *peer, afi_t afi, safi_t safi,
3303 struct prefix_rd *prd)
3304{
9bcb3eef 3305 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3306
d62a17ae 3307 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3308 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3309 */
3310 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3311 && peer->sort == BGP_PEER_EBGP)
9bcb3eef 3312 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
d62a17ae 3313 == BGP_DAMP_SUPPRESSED) {
b54892e0 3314 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
d62a17ae 3315 safi);
3316 return;
3317 }
3318
49e5a4a0 3319#ifdef ENABLE_BGP_VNC
d62a17ae 3320 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3321 struct bgp_dest *pdest = NULL;
d62a17ae 3322 struct bgp_table *table = NULL;
3323
9bcb3eef
DS
3324 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3325 (struct prefix *)prd);
3326 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3327 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3328
3329 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3330 peer->bgp, prd, table, p, pi);
d62a17ae 3331 }
9bcb3eef 3332 bgp_dest_unlock_node(pdest);
d62a17ae 3333 }
3334 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3335 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3336
b54892e0
DS
3337 vnc_import_bgp_del_route(peer->bgp, p, pi);
3338 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3339 }
65efcfce 3340 }
d62a17ae 3341#endif
128ea8ab 3342
d62a17ae 3343 /* If this is an EVPN route, process for un-import. */
3344 if (safi == SAFI_EVPN)
b54892e0 3345 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3346
9bcb3eef 3347 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3348}
3349
4b7e6066
DS
3350struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3351 struct peer *peer, struct attr *attr,
9bcb3eef 3352 struct bgp_dest *dest)
fb018d25 3353{
4b7e6066 3354 struct bgp_path_info *new;
fb018d25 3355
d62a17ae 3356 /* Make new BGP info. */
4b7e6066 3357 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3358 new->type = type;
3359 new->instance = instance;
3360 new->sub_type = sub_type;
3361 new->peer = peer;
3362 new->attr = attr;
3363 new->uptime = bgp_clock();
9bcb3eef 3364 new->net = dest;
d62a17ae 3365 return new;
fb018d25
DS
3366}
3367
d62a17ae 3368static void overlay_index_update(struct attr *attr,
d62a17ae 3369 union gw_addr *gw_ip)
684a7227 3370{
d62a17ae 3371 if (!attr)
3372 return;
d62a17ae 3373 if (gw_ip == NULL) {
3374 memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr));
3375 } else {
3376 memcpy(&(attr->evpn_overlay.gw_ip), gw_ip,
3377 sizeof(union gw_addr));
3378 }
684a7227
PG
3379}
3380
40381db7 3381static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3382 union gw_addr *gw_ip)
3383{
40381db7 3384 union gw_addr *path_gw_ip, *path_gw_ip_remote;
11ebf4ed 3385 union {
0a50c248 3386 esi_t esi;
11ebf4ed
DS
3387 union gw_addr ip;
3388 } temp;
d62a17ae 3389
3390 if (afi != AFI_L2VPN)
3391 return true;
11ebf4ed 3392
05864da7 3393 path_gw_ip = &(path->attr->evpn_overlay.gw_ip);
11ebf4ed
DS
3394
3395 if (gw_ip == NULL) {
3396 memset(&temp, 0, sizeof(temp));
40381db7 3397 path_gw_ip_remote = &temp.ip;
11ebf4ed 3398 } else
40381db7 3399 path_gw_ip_remote = gw_ip;
11ebf4ed 3400
0a50c248 3401 return !!memcmp(path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
684a7227
PG
3402}
3403
c265ee22 3404/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3405bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3406 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3407 struct bgp_dest *dest)
d62a17ae 3408{
2dbe3fa9 3409 bool ret = false;
b099a5c8
DA
3410 bool is_bgp_static_route =
3411 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3412 : false;
d62a17ae 3413
e8442016
DS
3414 /*
3415 * Only validated for unicast and multicast currently.
3416 * Also valid for EVPN where the nexthop is an IP address.
3417 * If we are a bgp static route being checked then there is
3418 * no need to check to see if the nexthop is martian as
3419 * that it should be ok.
3420 */
3421 if (is_bgp_static_route ||
3422 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3423 return false;
d62a17ae 3424
3425 /* If NEXT_HOP is present, validate it. */
3426 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e8442016 3427 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3428 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3429 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3430 return true;
d62a17ae 3431 }
c265ee22 3432
d62a17ae 3433 /* If MP_NEXTHOP is present, validate it. */
3434 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3435 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3436 * it is not an IPv6 link-local address.
0355b41d
DA
3437 *
3438 * If we receive an UPDATE with nexthop length set to 32 bytes
3439 * we shouldn't discard an UPDATE if it's set to (::).
3440 * The link-local (2st) is validated along the code path later.
d62a17ae 3441 */
3442 if (attr->mp_nexthop_len) {
3443 switch (attr->mp_nexthop_len) {
3444 case BGP_ATTR_NHLEN_IPV4:
3445 case BGP_ATTR_NHLEN_VPNV4:
e8442016 3446 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
975a328e
DA
3447 || IPV4_CLASS_DE(
3448 ntohl(attr->mp_nexthop_global_in.s_addr))
3449 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3450 dest));
d62a17ae 3451 break;
3452
3453 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3454 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3455 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3456 &attr->mp_nexthop_global)
d62a17ae 3457 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3458 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3459 &attr->mp_nexthop_global)
3460 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3461 dest));
d62a17ae 3462 break;
0355b41d
DA
3463 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3464 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3465 || IN6_IS_ADDR_MULTICAST(
3466 &attr->mp_nexthop_global)
3467 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3468 dest));
0355b41d 3469 break;
d62a17ae 3470
3471 default:
3dc339cd 3472 ret = true;
d62a17ae 3473 break;
3474 }
3475 }
c265ee22 3476
d62a17ae 3477 return ret;
3478}
3479
5a1ae2c2 3480int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3481 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3482 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3483 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3484 struct bgp_route_evpn *evpn)
d62a17ae 3485{
3486 int ret;
3487 int aspath_loop_count = 0;
9bcb3eef 3488 struct bgp_dest *dest;
d62a17ae 3489 struct bgp *bgp;
3490 struct attr new_attr;
3491 struct attr *attr_new;
40381db7 3492 struct bgp_path_info *pi;
4b7e6066
DS
3493 struct bgp_path_info *new;
3494 struct bgp_path_info_extra *extra;
d62a17ae 3495 const char *reason;
3496 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3497 int connected = 0;
3498 int do_loop_check = 1;
3499 int has_valid_label = 0;
7c312383 3500 afi_t nh_afi;
949b0f24 3501 uint8_t pi_type = 0;
3502 uint8_t pi_sub_type = 0;
3503
c7bb4f00 3504 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3505 char pfxprint[PREFIX2STR_BUFFER];
3506
3507 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3508 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3509 afi, safi, attr);
6401252f
QY
3510 }
3511
49e5a4a0 3512#ifdef ENABLE_BGP_VNC
d62a17ae 3513 int vnc_implicit_withdraw = 0;
65efcfce 3514#endif
d62a17ae 3515 int same_attr = 0;
718e3744 3516
d62a17ae 3517 memset(&new_attr, 0, sizeof(struct attr));
3518 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3519 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3520
d62a17ae 3521 bgp = peer->bgp;
9bcb3eef 3522 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3523 /* TODO: Check to see if we can get rid of "is_valid_label" */
3524 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3525 has_valid_label = (num_labels > 0) ? 1 : 0;
3526 else
3527 has_valid_label = bgp_is_valid_label(label);
718e3744 3528
d62a17ae 3529 /* When peer's soft reconfiguration enabled. Record input packet in
3530 Adj-RIBs-In. */
3531 if (!soft_reconfig
3532 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3533 && peer != bgp->peer_self)
9bcb3eef 3534 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3535
3536 /* Check previously received route. */
9bcb3eef 3537 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3538 if (pi->peer == peer && pi->type == type
3539 && pi->sub_type == sub_type
3540 && pi->addpath_rx_id == addpath_id)
d62a17ae 3541 break;
3542
3543 /* AS path local-as loop check. */
3544 if (peer->change_local_as) {
c4368918
DW
3545 if (peer->allowas_in[afi][safi])
3546 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3547 else if (!CHECK_FLAG(peer->flags,
3548 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3549 aspath_loop_count = 1;
3550
3551 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3552 > aspath_loop_count) {
b4d46cc9 3553 peer->stat_pfx_aspath_loop++;
9bcb3eef 3554 reason = "as-path contains our own AS A;";
d62a17ae 3555 goto filtered;
3556 }
718e3744 3557 }
718e3744 3558
d62a17ae 3559 /* If the peer is configured for "allowas-in origin" and the last ASN in
3560 * the
3561 * as-path is our ASN then we do not need to call aspath_loop_check
3562 */
3563 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3564 if (aspath_get_last_as(attr->aspath) == bgp->as)
3565 do_loop_check = 0;
3566
3567 /* AS path loop check. */
3568 if (do_loop_check) {
3569 if (aspath_loop_check(attr->aspath, bgp->as)
3570 > peer->allowas_in[afi][safi]
3571 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3572 && aspath_loop_check(attr->aspath, bgp->confed_id)
3573 > peer->allowas_in[afi][safi])) {
b4d46cc9 3574 peer->stat_pfx_aspath_loop++;
d62a17ae 3575 reason = "as-path contains our own AS;";
3576 goto filtered;
3577 }
3578 }
aac9ef6c 3579
d62a17ae 3580 /* Route reflector originator ID check. */
3581 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3582 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3583 peer->stat_pfx_originator_loop++;
d62a17ae 3584 reason = "originator is us;";
3585 goto filtered;
3586 }
718e3744 3587
d62a17ae 3588 /* Route reflector cluster ID check. */
3589 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3590 peer->stat_pfx_cluster_loop++;
d62a17ae 3591 reason = "reflected from the same cluster;";
3592 goto filtered;
3593 }
718e3744 3594
d62a17ae 3595 /* Apply incoming filter. */
3596 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3597 peer->stat_pfx_filter++;
d62a17ae 3598 reason = "filter;";
3599 goto filtered;
3600 }
718e3744 3601
a8b72dc6
DA
3602 /* RFC 8212 to prevent route leaks.
3603 * This specification intends to improve this situation by requiring the
3604 * explicit configuration of both BGP Import and Export Policies for any
3605 * External BGP (EBGP) session such as customers, peers, or
3606 * confederation boundaries for all enabled address families. Through
3607 * codification of the aforementioned requirement, operators will
3608 * benefit from consistent behavior across different BGP
3609 * implementations.
3610 */
1d3fdccf 3611 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3612 if (!bgp_inbound_policy_exists(peer,
3613 &peer->filter[afi][safi])) {
3614 reason = "inbound policy missing";
3615 goto filtered;
3616 }
3617
fb29348a
DA
3618 /* draft-ietf-idr-deprecate-as-set-confed-set
3619 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3620 * Eventually, This document (if approved) updates RFC 4271
3621 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3622 * and obsoletes RFC 6472.
3623 */
7f972cd8 3624 if (peer->bgp->reject_as_sets)
fb29348a
DA
3625 if (aspath_check_as_sets(attr->aspath)) {
3626 reason =
3627 "as-path contains AS_SET or AS_CONFED_SET type;";
3628 goto filtered;
3629 }
3630
6f4f49b2 3631 new_attr = *attr;
d62a17ae 3632
3633 /* Apply incoming route-map.
3634 * NB: new_attr may now contain newly allocated values from route-map
3635 * "set"
3636 * commands, so we need bgp_attr_flush in the error paths, until we
3637 * intern
3638 * the attr (which takes over the memory references) */
9bcb3eef
DS
3639 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3640 num_labels, dest)
3641 == RMAP_DENY) {
b4d46cc9 3642 peer->stat_pfx_filter++;
d62a17ae 3643 reason = "route-map;";
3644 bgp_attr_flush(&new_attr);
3645 goto filtered;
3646 }
718e3744 3647
05864da7 3648 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3649 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3650 /* remove from RIB previous entry */
3651 bgp_zebra_withdraw(p, pi, bgp, safi);
3652 }
3653
7f323236
DW
3654 if (peer->sort == BGP_PEER_EBGP) {
3655
a4d82a8a
PZ
3656 /* If we receive the graceful-shutdown community from an eBGP
3657 * peer we must lower local-preference */
3658 if (new_attr.community
3659 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3660 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3661 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3662
a4d82a8a
PZ
3663 /* If graceful-shutdown is configured then add the GSHUT
3664 * community to all paths received from eBGP peers */
637e5ba4 3665 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3666 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3667 }
3668
949b0f24 3669 if (pi) {
3670 pi_type = pi->type;
3671 pi_sub_type = pi->sub_type;
3672 }
3673
d62a17ae 3674 /* next hop check. */
a4d82a8a 3675 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3676 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3677 &new_attr, dest)) {
b4d46cc9 3678 peer->stat_pfx_nh_invalid++;
d62a17ae 3679 reason = "martian or self next-hop;";
3680 bgp_attr_flush(&new_attr);
3681 goto filtered;
3682 }
718e3744 3683
5c14a191 3684 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3685 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3686 reason = "self mac;";
3687 goto filtered;
3688 }
3689
1e9be514
QY
3690 /* Update Overlay Index */
3691 if (afi == AFI_L2VPN) {
3692 overlay_index_update(&new_attr,
3693 evpn == NULL ? NULL : &evpn->gw_ip);
3694 }
3695
d62a17ae 3696 attr_new = bgp_attr_intern(&new_attr);
3697
9cbd06e0
DA
3698 /* If maximum prefix count is configured and current prefix
3699 * count exeed it.
3700 */
3701 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3702 return -1;
3703
d62a17ae 3704 /* If the update is implicit withdraw. */
40381db7
DS
3705 if (pi) {
3706 pi->uptime = bgp_clock();
3707 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3708
9bcb3eef 3709 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3710
d62a17ae 3711 /* Same attribute comes in. */
40381db7
DS
3712 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3713 && attrhash_cmp(pi->attr, attr_new)
d62a17ae 3714 && (!has_valid_label
40381db7 3715 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3716 num_labels * sizeof(mpls_label_t))
d62a17ae 3717 == 0)
3718 && (overlay_index_equal(
0a50c248 3719 afi, pi,
d62a17ae 3720 evpn == NULL ? NULL : &evpn->gw_ip))) {
3721 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3722 BGP_CONFIG_DAMPENING)
3723 && peer->sort == BGP_PEER_EBGP
40381db7 3724 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3725 if (bgp_debug_update(peer, p, NULL, 1)) {
3726 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3727 afi, safi, prd, p, label,
3728 num_labels, addpath_id ? 1 : 0,
3729 addpath_id, pfx_buf,
3730 sizeof(pfx_buf));
d62a17ae 3731 zlog_debug("%s rcvd %s", peer->host,
3732 pfx_buf);
3733 }
3734
9bcb3eef 3735 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 3736 != BGP_DAMP_SUPPRESSED) {
40381db7 3737 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3738 safi);
9bcb3eef 3739 bgp_process(bgp, dest, afi, safi);
d62a17ae 3740 }
3741 } else /* Duplicate - odd */
3742 {
3743 if (bgp_debug_update(peer, p, NULL, 1)) {
3744 if (!peer->rcvd_attr_printed) {
3745 zlog_debug(
3746 "%s rcvd UPDATE w/ attr: %s",
3747 peer->host,
3748 peer->rcvd_attr_str);
3749 peer->rcvd_attr_printed = 1;
3750 }
3751
3752 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3753 afi, safi, prd, p, label,
3754 num_labels, addpath_id ? 1 : 0,
3755 addpath_id, pfx_buf,
3756 sizeof(pfx_buf));
d62a17ae 3757 zlog_debug(
3758 "%s rcvd %s...duplicate ignored",
3759 peer->host, pfx_buf);
3760 }
3761
3762 /* graceful restart STALE flag unset. */
40381db7 3763 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3764 bgp_path_info_unset_flag(
9bcb3eef
DS
3765 dest, pi, BGP_PATH_STALE);
3766 bgp_dest_set_defer_flag(dest, false);
3767 bgp_process(bgp, dest, afi, safi);
d62a17ae 3768 }
3769 }
3770
9bcb3eef 3771 bgp_dest_unlock_node(dest);
d62a17ae 3772 bgp_attr_unintern(&attr_new);
3773
3774 return 0;
3775 }
718e3744 3776
d62a17ae 3777 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3778 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3779 if (bgp_debug_update(peer, p, NULL, 1)) {
3780 bgp_debug_rdpfxpath2str(
a4d82a8a 3781 afi, safi, prd, p, label, num_labels,
d62a17ae 3782 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3783 sizeof(pfx_buf));
3784 zlog_debug(
3785 "%s rcvd %s, flapped quicker than processing",
3786 peer->host, pfx_buf);
3787 }
3788
9bcb3eef 3789 bgp_path_info_restore(dest, pi);
d62a17ae 3790 }
718e3744 3791
d62a17ae 3792 /* Received Logging. */
3793 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3794 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3795 num_labels, addpath_id ? 1 : 0,
3796 addpath_id, pfx_buf,
3797 sizeof(pfx_buf));
d62a17ae 3798 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3799 }
718e3744 3800
d62a17ae 3801 /* graceful restart STALE flag unset. */
f009ff26 3802 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
3803 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3804 bgp_dest_set_defer_flag(dest, false);
f009ff26 3805 }
d62a17ae 3806
3807 /* The attribute is changed. */
9bcb3eef 3808 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3809
3810 /* implicit withdraw, decrement aggregate and pcount here.
3811 * only if update is accepted, they'll increment below.
3812 */
40381db7 3813 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3814
3815 /* Update bgp route dampening information. */
3816 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3817 && peer->sort == BGP_PEER_EBGP) {
3818 /* This is implicit withdraw so we should update
3819 dampening
3820 information. */
40381db7 3821 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 3822 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 3823 }
49e5a4a0 3824#ifdef ENABLE_BGP_VNC
d62a17ae 3825 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3826 struct bgp_dest *pdest = NULL;
d62a17ae 3827 struct bgp_table *table = NULL;
3828
9bcb3eef
DS
3829 pdest = bgp_node_get(bgp->rib[afi][safi],
3830 (struct prefix *)prd);
3831 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3832 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3833
3834 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3835 bgp, prd, table, p, pi);
d62a17ae 3836 }
9bcb3eef 3837 bgp_dest_unlock_node(pdest);
d62a17ae 3838 }
3839 if ((afi == AFI_IP || afi == AFI_IP6)
3840 && (safi == SAFI_UNICAST)) {
40381db7 3841 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3842 /*
3843 * Implicit withdraw case.
3844 */
3845 ++vnc_implicit_withdraw;
40381db7
DS
3846 vnc_import_bgp_del_route(bgp, p, pi);
3847 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3848 }
3849 }
65efcfce 3850#endif
128ea8ab 3851
d62a17ae 3852 /* Special handling for EVPN update of an existing route. If the
3853 * extended community attribute has changed, we need to
3854 * un-import
3855 * the route using its existing extended community. It will be
3856 * subsequently processed for import with the new extended
3857 * community.
3858 */
6f8c9c11
PR
3859 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
3860 && !same_attr) {
40381db7 3861 if ((pi->attr->flag
d62a17ae 3862 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3863 && (attr_new->flag
3864 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3865 int cmp;
3866
40381db7 3867 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3868 attr_new->ecommunity);
3869 if (!cmp) {
3870 if (bgp_debug_update(peer, p, NULL, 1))
3871 zlog_debug(
3872 "Change in EXT-COMM, existing %s new %s",
3873 ecommunity_str(
40381db7 3874 pi->attr->ecommunity),
d62a17ae 3875 ecommunity_str(
3876 attr_new->ecommunity));
6f8c9c11
PR
3877 if (safi == SAFI_EVPN)
3878 bgp_evpn_unimport_route(
3879 bgp, afi, safi, p, pi);
3880 else /* SAFI_MPLS_VPN */
3881 vpn_leak_to_vrf_withdraw(bgp,
3882 pi);
d62a17ae 3883 }
3884 }
3885 }
718e3744 3886
d62a17ae 3887 /* Update to new attribute. */
40381db7
DS
3888 bgp_attr_unintern(&pi->attr);
3889 pi->attr = attr_new;
d62a17ae 3890
3891 /* Update MPLS label */
3892 if (has_valid_label) {
40381db7 3893 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3894 if (extra->label != label) {
3895 memcpy(&extra->label, label,
dbd587da 3896 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3897 extra->num_labels = num_labels;
3898 }
b57ba6d2
MK
3899 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3900 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3901 }
718e3744 3902
e496b420
HS
3903 /* Update SRv6 SID */
3904 if (attr->srv6_l3vpn) {
3905 extra = bgp_path_info_extra_get(pi);
3906 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
3907 sid_copy(&extra->sid[0],
3908 &attr->srv6_l3vpn->sid);
3909 extra->num_sids = 1;
3910 }
3911 } else if (attr->srv6_vpn) {
3912 extra = bgp_path_info_extra_get(pi);
3913 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
3914 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3915 extra->num_sids = 1;
3916 }
3917 }
3918
49e5a4a0 3919#ifdef ENABLE_BGP_VNC
d62a17ae 3920 if ((afi == AFI_IP || afi == AFI_IP6)
3921 && (safi == SAFI_UNICAST)) {
3922 if (vnc_implicit_withdraw) {
3923 /*
3924 * Add back the route with its new attributes
3925 * (e.g., nexthop).
3926 * The route is still selected, until the route
3927 * selection
3928 * queued by bgp_process actually runs. We have
3929 * to make this
3930 * update to the VNC side immediately to avoid
3931 * racing against
3932 * configuration changes (e.g., route-map
3933 * changes) which
3934 * trigger re-importation of the entire RIB.
3935 */
40381db7
DS
3936 vnc_import_bgp_add_route(bgp, p, pi);
3937 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 3938 }
3939 }
65efcfce
LB
3940#endif
3941
d62a17ae 3942 /* Update bgp route dampening information. */
3943 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3944 && peer->sort == BGP_PEER_EBGP) {
3945 /* Now we do normal update dampening. */
9bcb3eef 3946 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 3947 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 3948 bgp_dest_unlock_node(dest);
d62a17ae 3949 return 0;
3950 }
3951 }
128ea8ab 3952
d62a17ae 3953 /* Nexthop reachability check - for unicast and
3954 * labeled-unicast.. */
7c312383
AD
3955 if (((afi == AFI_IP || afi == AFI_IP6)
3956 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3957 || (safi == SAFI_EVPN &&
3958 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
3959 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
3960 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 3961 && !CHECK_FLAG(peer->flags,
3962 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
3963 && !CHECK_FLAG(bgp->flags,
3964 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 3965 connected = 1;
3966 else
3967 connected = 0;
3968
960035b2
PZ
3969 struct bgp *bgp_nexthop = bgp;
3970
40381db7
DS
3971 if (pi->extra && pi->extra->bgp_orig)
3972 bgp_nexthop = pi->extra->bgp_orig;
960035b2 3973
7c312383
AD
3974 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
3975
3976 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
3977 pi, NULL, connected)
a4d82a8a 3978 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
3979 bgp_path_info_set_flag(dest, pi,
3980 BGP_PATH_VALID);
d62a17ae 3981 else {
3982 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
3983 zlog_debug("%s(%pI4): NH unresolved",
3984 __func__,
3985 (in_addr_t *)&attr_new->nexthop);
d62a17ae 3986 }
9bcb3eef 3987 bgp_path_info_unset_flag(dest, pi,
18ee8310 3988 BGP_PATH_VALID);
d62a17ae 3989 }
3990 } else
9bcb3eef 3991 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 3992
49e5a4a0 3993#ifdef ENABLE_BGP_VNC
d62a17ae 3994 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3995 struct bgp_dest *pdest = NULL;
d62a17ae 3996 struct bgp_table *table = NULL;
3997
9bcb3eef
DS
3998 pdest = bgp_node_get(bgp->rib[afi][safi],
3999 (struct prefix *)prd);
4000 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4001 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4002
4003 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4004 bgp, prd, table, p, pi);
d62a17ae 4005 }
9bcb3eef 4006 bgp_dest_unlock_node(pdest);
d62a17ae 4007 }
4008#endif
718e3744 4009
d62a17ae 4010 /* If this is an EVPN route and some attribute has changed,
4011 * process
4012 * route for import. If the extended community has changed, we
4013 * would
4014 * have done the un-import earlier and the import would result
4015 * in the
4016 * route getting injected into appropriate L2 VNIs. If it is
4017 * just
4018 * some other attribute change, the import will result in
4019 * updating
4020 * the attributes for the route in the VNI(s).
4021 */
7c312383
AD
4022 if (safi == SAFI_EVPN && !same_attr &&
4023 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4024 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4025
4026 /* Process change. */
40381db7 4027 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4028
9bcb3eef
DS
4029 bgp_process(bgp, dest, afi, safi);
4030 bgp_dest_unlock_node(dest);
558d1fec 4031
ddb5b488
PZ
4032 if (SAFI_UNICAST == safi
4033 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4034 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4035
40381db7 4036 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4037 }
4038 if ((SAFI_MPLS_VPN == safi)
4039 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4040
40381db7 4041 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4042 }
4043
49e5a4a0 4044#ifdef ENABLE_BGP_VNC
d62a17ae 4045 if (SAFI_MPLS_VPN == safi) {
4046 mpls_label_t label_decoded = decode_label(label);
28070ee3 4047
d62a17ae 4048 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4049 type, sub_type, &label_decoded);
4050 }
4051 if (SAFI_ENCAP == safi) {
4052 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4053 type, sub_type, NULL);
4054 }
28070ee3
PZ
4055#endif
4056
d62a17ae 4057 return 0;
4058 } // End of implicit withdraw
718e3744 4059
d62a17ae 4060 /* Received Logging. */
4061 if (bgp_debug_update(peer, p, NULL, 1)) {
4062 if (!peer->rcvd_attr_printed) {
4063 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4064 peer->rcvd_attr_str);
4065 peer->rcvd_attr_printed = 1;
4066 }
718e3744 4067
a4d82a8a 4068 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4069 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4070 sizeof(pfx_buf));
4071 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4072 }
718e3744 4073
d62a17ae 4074 /* Make new BGP info. */
9bcb3eef 4075 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4076
d62a17ae 4077 /* Update MPLS label */
4078 if (has_valid_label) {
18ee8310 4079 extra = bgp_path_info_extra_get(new);
8ba71050 4080 if (extra->label != label) {
dbd587da
QY
4081 memcpy(&extra->label, label,
4082 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4083 extra->num_labels = num_labels;
4084 }
b57ba6d2
MK
4085 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4086 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4087 }
718e3744 4088
e496b420
HS
4089 /* Update SRv6 SID */
4090 if (safi == SAFI_MPLS_VPN) {
4091 extra = bgp_path_info_extra_get(new);
4092 if (attr->srv6_l3vpn) {
4093 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
4094 extra->num_sids = 1;
4095 } else if (attr->srv6_vpn) {
4096 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4097 extra->num_sids = 1;
4098 }
4099 }
4100
d62a17ae 4101 /* Update Overlay Index */
4102 if (afi == AFI_L2VPN) {
4103 overlay_index_update(new->attr,
d62a17ae 4104 evpn == NULL ? NULL : &evpn->gw_ip);
4105 }
4106 /* Nexthop reachability check. */
7c312383
AD
4107 if (((afi == AFI_IP || afi == AFI_IP6)
4108 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4109 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4110 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4111 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4112 && !CHECK_FLAG(peer->flags,
4113 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4114 && !CHECK_FLAG(bgp->flags,
4115 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4116 connected = 1;
4117 else
4118 connected = 0;
4119
7c312383
AD
4120 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4121
4122 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, new, NULL,
4123 connected)
a4d82a8a 4124 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4125 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4126 else {
4127 if (BGP_DEBUG(nht, NHT)) {
4128 char buf1[INET6_ADDRSTRLEN];
4129 inet_ntop(AF_INET,
4130 (const void *)&attr_new->nexthop,
4131 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4132 zlog_debug("%s(%s): NH unresolved", __func__,
4133 buf1);
d62a17ae 4134 }
9bcb3eef 4135 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4136 }
4137 } else
9bcb3eef 4138 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4139
d62a17ae 4140 /* Addpath ID */
4141 new->addpath_rx_id = addpath_id;
4142
4143 /* Increment prefix */
4144 bgp_aggregate_increment(bgp, p, new, afi, safi);
4145
4146 /* Register new BGP information. */
9bcb3eef 4147 bgp_path_info_add(dest, new);
d62a17ae 4148
4149 /* route_node_get lock */
9bcb3eef 4150 bgp_dest_unlock_node(dest);
558d1fec 4151
49e5a4a0 4152#ifdef ENABLE_BGP_VNC
d62a17ae 4153 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4154 struct bgp_dest *pdest = NULL;
d62a17ae 4155 struct bgp_table *table = NULL;
4156
9bcb3eef
DS
4157 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4158 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4159 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4160
4161 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4162 bgp, prd, table, p, new);
4163 }
9bcb3eef 4164 bgp_dest_unlock_node(pdest);
d62a17ae 4165 }
65efcfce
LB
4166#endif
4167
d62a17ae 4168 /* If this is an EVPN route, process for import. */
7c312383 4169 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4170 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4171
9bcb3eef 4172 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4173
d62a17ae 4174 /* Process change. */
9bcb3eef 4175 bgp_process(bgp, dest, afi, safi);
718e3744 4176
ddb5b488
PZ
4177 if (SAFI_UNICAST == safi
4178 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4179 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4180 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4181 }
4182 if ((SAFI_MPLS_VPN == safi)
4183 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4184
4185 vpn_leak_to_vrf_update(bgp, new);
4186 }
49e5a4a0 4187#ifdef ENABLE_BGP_VNC
d62a17ae 4188 if (SAFI_MPLS_VPN == safi) {
4189 mpls_label_t label_decoded = decode_label(label);
28070ee3 4190
d62a17ae 4191 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4192 sub_type, &label_decoded);
4193 }
4194 if (SAFI_ENCAP == safi) {
4195 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4196 sub_type, NULL);
4197 }
28070ee3
PZ
4198#endif
4199
d62a17ae 4200 return 0;
718e3744 4201
d62a17ae 4202/* This BGP update is filtered. Log the reason then update BGP
4203 entry. */
4204filtered:
9bcb3eef 4205 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4206
d62a17ae 4207 if (bgp_debug_update(peer, p, NULL, 1)) {
4208 if (!peer->rcvd_attr_printed) {
4209 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4210 peer->rcvd_attr_str);
4211 peer->rcvd_attr_printed = 1;
4212 }
718e3744 4213
a4d82a8a 4214 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4215 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4216 sizeof(pfx_buf));
4217 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4218 peer->host, pfx_buf, reason);
4219 }
128ea8ab 4220
40381db7 4221 if (pi) {
d62a17ae 4222 /* If this is an EVPN route, un-import it as it is now filtered.
4223 */
4224 if (safi == SAFI_EVPN)
40381db7 4225 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4226
ddb5b488
PZ
4227 if (SAFI_UNICAST == safi
4228 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4229 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4230
40381db7 4231 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4232 }
4233 if ((SAFI_MPLS_VPN == safi)
4234 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4235
40381db7 4236 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4237 }
4238
9bcb3eef 4239 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4240 }
4241
9bcb3eef 4242 bgp_dest_unlock_node(dest);
558d1fec 4243
49e5a4a0 4244#ifdef ENABLE_BGP_VNC
d62a17ae 4245 /*
4246 * Filtered update is treated as an implicit withdrawal (see
4247 * bgp_rib_remove()
4248 * a few lines above)
4249 */
4250 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4251 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4252 0);
4253 }
97736e32
PZ
4254#endif
4255
d62a17ae 4256 return 0;
718e3744 4257}
4258
26a3ffd6 4259int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4260 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4261 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4262 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4263{
d62a17ae 4264 struct bgp *bgp;
4265 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4266 struct bgp_dest *dest;
40381db7 4267 struct bgp_path_info *pi;
718e3744 4268
49e5a4a0 4269#ifdef ENABLE_BGP_VNC
d62a17ae 4270 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4271 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4272 0);
4273 }
28070ee3
PZ
4274#endif
4275
d62a17ae 4276 bgp = peer->bgp;
4277
4278 /* Lookup node. */
9bcb3eef 4279 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4280
4281 /* If peer is soft reconfiguration enabled. Record input packet for
4282 * further calculation.
4283 *
4284 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4285 * routes that are filtered. This tanks out Quagga RS pretty badly due
4286 * to
4287 * the iteration over all RS clients.
4288 * Since we need to remove the entry from adj_in anyway, do that first
4289 * and
4290 * if there was no entry, we don't need to do anything more.
4291 */
4292 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4293 && peer != bgp->peer_self)
9bcb3eef 4294 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4295 peer->stat_pfx_dup_withdraw++;
4296
d62a17ae 4297 if (bgp_debug_update(peer, p, NULL, 1)) {
4298 bgp_debug_rdpfxpath2str(
a4d82a8a 4299 afi, safi, prd, p, label, num_labels,
d62a17ae 4300 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4301 sizeof(pfx_buf));
4302 zlog_debug(
4303 "%s withdrawing route %s not in adj-in",
4304 peer->host, pfx_buf);
4305 }
9bcb3eef 4306 bgp_dest_unlock_node(dest);
d62a17ae 4307 return 0;
4308 }
cd808e74 4309
d62a17ae 4310 /* Lookup withdrawn route. */
9bcb3eef 4311 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4312 if (pi->peer == peer && pi->type == type
4313 && pi->sub_type == sub_type
4314 && pi->addpath_rx_id == addpath_id)
d62a17ae 4315 break;
4316
4317 /* Logging. */
4318 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4319 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4320 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4321 sizeof(pfx_buf));
4322 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4323 pfx_buf);
4324 }
718e3744 4325
d62a17ae 4326 /* Withdraw specified route from routing table. */
40381db7 4327 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4328 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4329 if (SAFI_UNICAST == safi
4330 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4331 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4332 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4333 }
4334 if ((SAFI_MPLS_VPN == safi)
4335 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4336
40381db7 4337 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4338 }
4339 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4340 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4341 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4342 sizeof(pfx_buf));
4343 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4344 }
718e3744 4345
d62a17ae 4346 /* Unlock bgp_node_get() lock. */
9bcb3eef 4347 bgp_dest_unlock_node(dest);
d62a17ae 4348
4349 return 0;
718e3744 4350}
6b0655a2 4351
d62a17ae 4352void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4353 int withdraw)
718e3744 4354{
d62a17ae 4355 struct update_subgroup *subgrp;
4356 subgrp = peer_subgroup(peer, afi, safi);
4357 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4358}
6182d65b 4359
718e3744 4360
3f9c7369
DS
4361/*
4362 * bgp_stop_announce_route_timer
4363 */
d62a17ae 4364void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4365{
d62a17ae 4366 if (!paf->t_announce_route)
4367 return;
4368
50478845 4369 thread_cancel(&paf->t_announce_route);
718e3744 4370}
6b0655a2 4371
3f9c7369
DS
4372/*
4373 * bgp_announce_route_timer_expired
4374 *
4375 * Callback that is invoked when the route announcement timer for a
4376 * peer_af expires.
4377 */
d62a17ae 4378static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4379{
d62a17ae 4380 struct peer_af *paf;
4381 struct peer *peer;
558d1fec 4382
d62a17ae 4383 paf = THREAD_ARG(t);
4384 peer = paf->peer;
718e3744 4385
d62a17ae 4386 if (peer->status != Established)
4387 return 0;
3f9c7369 4388
d62a17ae 4389 if (!peer->afc_nego[paf->afi][paf->safi])
4390 return 0;
3f9c7369 4391
d62a17ae 4392 peer_af_announce_route(paf, 1);
c5aec50b
MK
4393
4394 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4395 peer->advmap_config_change[paf->afi][paf->safi] = true;
c5aec50b 4396
d62a17ae 4397 return 0;
718e3744 4398}
4399
3f9c7369
DS
4400/*
4401 * bgp_announce_route
4402 *
4403 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4404 */
d62a17ae 4405void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4406{
4407 struct peer_af *paf;
4408 struct update_subgroup *subgrp;
4409
4410 paf = peer_af_find(peer, afi, safi);
4411 if (!paf)
4412 return;
4413 subgrp = PAF_SUBGRP(paf);
4414
4415 /*
4416 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4417 * or a refresh has already been triggered.
4418 */
4419 if (!subgrp || paf->t_announce_route)
4420 return;
4421
4422 /*
4423 * Start a timer to stagger/delay the announce. This serves
4424 * two purposes - announcement can potentially be combined for
4425 * multiple peers and the announcement doesn't happen in the
4426 * vty context.
4427 */
4428 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4429 (subgrp->peer_count == 1)
4430 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4431 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4432 &paf->t_announce_route);
3f9c7369
DS
4433}
4434
4435/*
4436 * Announce routes from all AF tables to a peer.
4437 *
4438 * This should ONLY be called when there is a need to refresh the
4439 * routes to the peer based on a policy change for this peer alone
4440 * or a route refresh request received from the peer.
4441 * The operation will result in splitting the peer from its existing
4442 * subgroups and putting it in new subgroups.
4443 */
d62a17ae 4444void bgp_announce_route_all(struct peer *peer)
718e3744 4445{
d62a17ae 4446 afi_t afi;
4447 safi_t safi;
4448
05c7a1cc
QY
4449 FOREACH_AFI_SAFI (afi, safi)
4450 bgp_announce_route(peer, afi, safi);
718e3744 4451}
6b0655a2 4452
d62a17ae 4453static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4454 struct bgp_table *table,
4455 struct prefix_rd *prd)
718e3744 4456{
d62a17ae 4457 int ret;
9bcb3eef 4458 struct bgp_dest *dest;
d62a17ae 4459 struct bgp_adj_in *ain;
718e3744 4460
d62a17ae 4461 if (!table)
4462 table = peer->bgp->rib[afi][safi];
718e3744 4463
9bcb3eef
DS
4464 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4465 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4466 if (ain->peer != peer)
4467 continue;
8692c506 4468
d7d15889 4469 struct bgp_path_info *pi;
d7c0a89a 4470 uint32_t num_labels = 0;
b57ba6d2 4471 mpls_label_t *label_pnt = NULL;
8cb687c2 4472 struct bgp_route_evpn evpn;
b57ba6d2 4473
9bcb3eef 4474 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
d7d15889
DS
4475 pi = pi->next)
4476 if (pi->peer == peer)
4477 break;
4478
40381db7
DS
4479 if (pi && pi->extra)
4480 num_labels = pi->extra->num_labels;
b57ba6d2 4481 if (num_labels)
40381db7 4482 label_pnt = &pi->extra->label[0];
8cb687c2
DS
4483 if (pi)
4484 memcpy(&evpn, &pi->attr->evpn_overlay,
4485 sizeof(evpn));
4486 else
4487 memset(&evpn, 0, sizeof(evpn));
8692c506 4488
9bcb3eef
DS
4489 ret = bgp_update(peer, bgp_dest_get_prefix(dest),
4490 ain->addpath_rx_id, ain->attr, afi,
4491 safi, ZEBRA_ROUTE_BGP,
a4d82a8a 4492 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 4493 num_labels, 1, &evpn);
ea47320b
DL
4494
4495 if (ret < 0) {
9bcb3eef 4496 bgp_dest_unlock_node(dest);
ea47320b 4497 return;
d62a17ae 4498 }
4499 }
718e3744 4500}
4501
d62a17ae 4502void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4503{
9bcb3eef 4504 struct bgp_dest *dest;
d62a17ae 4505 struct bgp_table *table;
718e3744 4506
d62a17ae 4507 if (peer->status != Established)
4508 return;
718e3744 4509
d62a17ae 4510 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4511 && (safi != SAFI_EVPN))
4512 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4513 else
9bcb3eef
DS
4514 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4515 dest = bgp_route_next(dest)) {
4516 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4517
b54892e0
DS
4518 if (table == NULL)
4519 continue;
8692c506 4520
9bcb3eef 4521 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
4522 struct prefix_rd prd;
4523
4524 prd.family = AF_UNSPEC;
4525 prd.prefixlen = 64;
4526 memcpy(&prd.val, p->u.val, 8);
4527
4528 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 4529 }
718e3744 4530}
6b0655a2 4531
228da428 4532
d62a17ae 4533struct bgp_clear_node_queue {
9bcb3eef 4534 struct bgp_dest *dest;
228da428
CC
4535};
4536
d62a17ae 4537static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4538{
d62a17ae 4539 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 4540 struct bgp_dest *dest = cnq->dest;
d62a17ae 4541 struct peer *peer = wq->spec.data;
40381db7 4542 struct bgp_path_info *pi;
3103e8d2 4543 struct bgp *bgp;
9bcb3eef
DS
4544 afi_t afi = bgp_dest_table(dest)->afi;
4545 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 4546
9bcb3eef 4547 assert(dest && peer);
3103e8d2 4548 bgp = peer->bgp;
d62a17ae 4549
4550 /* It is possible that we have multiple paths for a prefix from a peer
4551 * if that peer is using AddPath.
4552 */
9bcb3eef 4553 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 4554 if (pi->peer != peer)
ea47320b
DL
4555 continue;
4556
4557 /* graceful restart STALE flag set. */
4558 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4559 && peer->nsf[afi][safi]
40381db7
DS
4560 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4561 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 4562 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
4563 else {
4564 /* If this is an EVPN route, process for
4565 * un-import. */
4566 if (safi == SAFI_EVPN)
9bcb3eef
DS
4567 bgp_evpn_unimport_route(
4568 bgp, afi, safi,
4569 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
4570 /* Handle withdraw for VRF route-leaking and L3VPN */
4571 if (SAFI_UNICAST == safi
4572 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4573 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4574 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4575 bgp, pi);
960035b2 4576 }
3103e8d2 4577 if (SAFI_MPLS_VPN == safi &&
960035b2 4578 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4579 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4580 }
3103e8d2 4581
9bcb3eef 4582 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4583 }
ea47320b 4584 }
d62a17ae 4585 return WQ_SUCCESS;
200df115 4586}
4587
d62a17ae 4588static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4589{
d62a17ae 4590 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
4591 struct bgp_dest *dest = cnq->dest;
4592 struct bgp_table *table = bgp_dest_table(dest);
228da428 4593
9bcb3eef 4594 bgp_dest_unlock_node(dest);
d62a17ae 4595 bgp_table_unlock(table);
4596 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4597}
4598
d62a17ae 4599static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4600{
d62a17ae 4601 struct peer *peer = wq->spec.data;
64e580a7 4602
d62a17ae 4603 /* Tickle FSM to start moving again */
4604 BGP_EVENT_ADD(peer, Clearing_Completed);
4605
4606 peer_unlock(peer); /* bgp_clear_route */
200df115 4607}
718e3744 4608
d62a17ae 4609static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4610{
d62a17ae 4611 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4612
4613 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4614#undef CLEAR_QUEUE_NAME_LEN
4615
0ce1ca80 4616 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4617 peer->clear_node_queue->spec.hold = 10;
4618 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4619 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4620 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4621 peer->clear_node_queue->spec.max_retries = 0;
4622
4623 /* we only 'lock' this peer reference when the queue is actually active
4624 */
4625 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4626}
4627
d62a17ae 4628static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4629 struct bgp_table *table)
65ca75e0 4630{
9bcb3eef 4631 struct bgp_dest *dest;
b6c386bb 4632 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 4633
d62a17ae 4634 if (!table)
4635 table = peer->bgp->rib[afi][safi];
dc83d712 4636
d62a17ae 4637 /* If still no table => afi/safi isn't configured at all or smth. */
4638 if (!table)
4639 return;
dc83d712 4640
9bcb3eef 4641 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 4642 struct bgp_path_info *pi, *next;
d62a17ae 4643 struct bgp_adj_in *ain;
4644 struct bgp_adj_in *ain_next;
4645
4646 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4647 * queued for every clearing peer, regardless of whether it is
4648 * relevant to the peer at hand.
4649 *
4650 * Overview: There are 3 different indices which need to be
4651 * scrubbed, potentially, when a peer is removed:
4652 *
4653 * 1 peer's routes visible via the RIB (ie accepted routes)
4654 * 2 peer's routes visible by the (optional) peer's adj-in index
4655 * 3 other routes visible by the peer's adj-out index
4656 *
4657 * 3 there is no hurry in scrubbing, once the struct peer is
4658 * removed from bgp->peer, we could just GC such deleted peer's
4659 * adj-outs at our leisure.
4660 *
4661 * 1 and 2 must be 'scrubbed' in some way, at least made
4662 * invisible via RIB index before peer session is allowed to be
4663 * brought back up. So one needs to know when such a 'search' is
4664 * complete.
4665 *
4666 * Ideally:
4667 *
4668 * - there'd be a single global queue or a single RIB walker
4669 * - rather than tracking which route_nodes still need to be
4670 * examined on a peer basis, we'd track which peers still
4671 * aren't cleared
4672 *
4673 * Given that our per-peer prefix-counts now should be reliable,
4674 * this may actually be achievable. It doesn't seem to be a huge
4675 * problem at this time,
4676 *
4677 * It is possible that we have multiple paths for a prefix from
4678 * a peer
4679 * if that peer is using AddPath.
4680 */
9bcb3eef 4681 ain = dest->adj_in;
d62a17ae 4682 while (ain) {
4683 ain_next = ain->next;
4684
4685 if (ain->peer == peer) {
9bcb3eef
DS
4686 bgp_adj_in_remove(dest, ain);
4687 bgp_dest_unlock_node(dest);
d62a17ae 4688 }
4689
4690 ain = ain_next;
4691 }
4692
9bcb3eef 4693 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
4694 next = pi->next;
4695 if (pi->peer != peer)
d62a17ae 4696 continue;
4697
4698 if (force)
9bcb3eef 4699 bgp_path_info_reap(dest, pi);
d62a17ae 4700 else {
4701 struct bgp_clear_node_queue *cnq;
4702
4703 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
4704 bgp_table_lock(bgp_dest_table(dest));
4705 bgp_dest_lock_node(dest);
d62a17ae 4706 cnq = XCALLOC(
4707 MTYPE_BGP_CLEAR_NODE_QUEUE,
4708 sizeof(struct bgp_clear_node_queue));
9bcb3eef 4709 cnq->dest = dest;
d62a17ae 4710 work_queue_add(peer->clear_node_queue, cnq);
4711 break;
4712 }
4713 }
4714 }
4715 return;
4716}
4717
4718void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4719{
9bcb3eef 4720 struct bgp_dest *dest;
d62a17ae 4721 struct bgp_table *table;
4722
4723 if (peer->clear_node_queue == NULL)
4724 bgp_clear_node_queue_init(peer);
4725
4726 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4727 * Idle until it receives a Clearing_Completed event. This protects
4728 * against peers which flap faster than we can we clear, which could
4729 * lead to:
4730 *
4731 * a) race with routes from the new session being installed before
4732 * clear_route_node visits the node (to delete the route of that
4733 * peer)
4734 * b) resource exhaustion, clear_route_node likely leads to an entry
4735 * on the process_main queue. Fast-flapping could cause that queue
4736 * to grow and grow.
4737 */
4738
4739 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4740 * the unlock will happen upon work-queue completion; other wise, the
4741 * unlock happens at the end of this function.
4742 */
4743 if (!peer->clear_node_queue->thread)
4744 peer_lock(peer);
4745
4746 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4747 bgp_clear_route_table(peer, afi, safi, NULL);
4748 else
9bcb3eef
DS
4749 for (dest = bgp_table_top(peer->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)
4753 continue;
4754
4755 bgp_clear_route_table(peer, afi, safi, table);
4756 }
d62a17ae 4757
4758 /* unlock if no nodes got added to the clear-node-queue. */
4759 if (!peer->clear_node_queue->thread)
4760 peer_unlock(peer);
718e3744 4761}
d62a17ae 4762
4763void bgp_clear_route_all(struct peer *peer)
718e3744 4764{
d62a17ae 4765 afi_t afi;
4766 safi_t safi;
718e3744 4767
05c7a1cc
QY
4768 FOREACH_AFI_SAFI (afi, safi)
4769 bgp_clear_route(peer, afi, safi);
65efcfce 4770
49e5a4a0 4771#ifdef ENABLE_BGP_VNC
d62a17ae 4772 rfapiProcessPeerDown(peer);
65efcfce 4773#endif
718e3744 4774}
4775
d62a17ae 4776void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4777{
d62a17ae 4778 struct bgp_table *table;
9bcb3eef 4779 struct bgp_dest *dest;
d62a17ae 4780 struct bgp_adj_in *ain;
4781 struct bgp_adj_in *ain_next;
718e3744 4782
d62a17ae 4783 table = peer->bgp->rib[afi][safi];
718e3744 4784
d62a17ae 4785 /* It is possible that we have multiple paths for a prefix from a peer
4786 * if that peer is using AddPath.
4787 */
9bcb3eef
DS
4788 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4789 ain = dest->adj_in;
43143c8f 4790
d62a17ae 4791 while (ain) {
4792 ain_next = ain->next;
43143c8f 4793
d62a17ae 4794 if (ain->peer == peer) {
9bcb3eef
DS
4795 bgp_adj_in_remove(dest, ain);
4796 bgp_dest_unlock_node(dest);
d62a17ae 4797 }
43143c8f 4798
d62a17ae 4799 ain = ain_next;
4800 }
4801 }
718e3744 4802}
93406d87 4803
d62a17ae 4804void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4805{
9bcb3eef 4806 struct bgp_dest *dest;
40381db7 4807 struct bgp_path_info *pi;
d62a17ae 4808 struct bgp_table *table;
4809
4810 if (safi == SAFI_MPLS_VPN) {
9bcb3eef
DS
4811 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4812 dest = bgp_route_next(dest)) {
4813 struct bgp_dest *rm;
d62a17ae 4814
4815 /* look for neighbor in tables */
9bcb3eef 4816 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4817 if (!table)
ea47320b
DL
4818 continue;
4819
4820 for (rm = bgp_table_top(table); rm;
4821 rm = bgp_route_next(rm))
9bcb3eef 4822 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 4823 pi = pi->next) {
40381db7 4824 if (pi->peer != peer)
ea47320b 4825 continue;
40381db7 4826 if (!CHECK_FLAG(pi->flags,
1defdda8 4827 BGP_PATH_STALE))
ea47320b
DL
4828 break;
4829
40381db7 4830 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4831 break;
4832 }
d62a17ae 4833 }
4834 } else {
9bcb3eef
DS
4835 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4836 dest = bgp_route_next(dest))
4837 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 4838 pi = pi->next) {
40381db7 4839 if (pi->peer != peer)
ea47320b 4840 continue;
40381db7 4841 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4842 break;
9bcb3eef 4843 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
4844 break;
4845 }
d62a17ae 4846 }
93406d87 4847}
6b0655a2 4848
3dc339cd 4849bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 4850{
e0df4c04 4851 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 4852 return true;
e0df4c04 4853
9dac9fc8
DA
4854 if (peer->sort == BGP_PEER_EBGP
4855 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
4856 || FILTER_LIST_OUT_NAME(filter)
4857 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
4858 return true;
4859 return false;
9dac9fc8
DA
4860}
4861
3dc339cd 4862bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 4863{
e0df4c04 4864 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 4865 return true;
e0df4c04 4866
9dac9fc8
DA
4867 if (peer->sort == BGP_PEER_EBGP
4868 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
4869 || FILTER_LIST_IN_NAME(filter)
4870 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
4871 return true;
4872 return false;
9dac9fc8
DA
4873}
4874
568e10ca 4875static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
4876 safi_t safi)
bb86c601 4877{
9bcb3eef 4878 struct bgp_dest *dest;
40381db7 4879 struct bgp_path_info *pi;
4b7e6066 4880 struct bgp_path_info *next;
bb86c601 4881
9bcb3eef
DS
4882 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4883 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
4884 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 4885
40381db7 4886 next = pi->next;
1b7bb747
CS
4887
4888 /* Unimport EVPN routes from VRFs */
4889 if (safi == SAFI_EVPN)
4890 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 4891 SAFI_EVPN, p, pi);
1b7bb747 4892
40381db7
DS
4893 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
4894 && pi->type == ZEBRA_ROUTE_BGP
4895 && (pi->sub_type == BGP_ROUTE_NORMAL
4896 || pi->sub_type == BGP_ROUTE_AGGREGATE
4897 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 4898
d62a17ae 4899 if (bgp_fibupd_safi(safi))
b54892e0 4900 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 4901 }
9514b37d 4902
9bcb3eef 4903 bgp_path_info_reap(dest, pi);
d62a17ae 4904 }
bb86c601
LB
4905}
4906
718e3744 4907/* Delete all kernel routes. */
d62a17ae 4908void bgp_cleanup_routes(struct bgp *bgp)
4909{
4910 afi_t afi;
9bcb3eef 4911 struct bgp_dest *dest;
67009e22 4912 struct bgp_table *table;
d62a17ae 4913
4914 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
4915 if (afi == AFI_L2VPN)
4916 continue;
568e10ca 4917 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
4918 SAFI_UNICAST);
d62a17ae 4919 /*
4920 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4921 */
4922 if (afi != AFI_L2VPN) {
4923 safi_t safi;
4924 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
4925 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
4926 dest = bgp_route_next(dest)) {
4927 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4928 if (table != NULL) {
4929 bgp_cleanup_table(bgp, table, safi);
4930 bgp_table_finish(&table);
9bcb3eef
DS
4931 bgp_dest_set_bgp_table_info(dest, NULL);
4932 bgp_dest_unlock_node(dest);
d62a17ae 4933 }
4934 }
4935 safi = SAFI_ENCAP;
9bcb3eef
DS
4936 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
4937 dest = bgp_route_next(dest)) {
4938 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4939 if (table != NULL) {
4940 bgp_cleanup_table(bgp, table, safi);
4941 bgp_table_finish(&table);
9bcb3eef
DS
4942 bgp_dest_set_bgp_table_info(dest, NULL);
4943 bgp_dest_unlock_node(dest);
d62a17ae 4944 }
4945 }
4946 }
4947 }
9bcb3eef
DS
4948 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
4949 dest = bgp_route_next(dest)) {
4950 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4951 if (table != NULL) {
4952 bgp_cleanup_table(bgp, table, SAFI_EVPN);
4953 bgp_table_finish(&table);
9bcb3eef
DS
4954 bgp_dest_set_bgp_table_info(dest, NULL);
4955 bgp_dest_unlock_node(dest);
d62a17ae 4956 }
bb86c601 4957 }
718e3744 4958}
4959
d62a17ae 4960void bgp_reset(void)
718e3744 4961{
d62a17ae 4962 vty_reset();
4963 bgp_zclient_reset();
4964 access_list_reset();
4965 prefix_list_reset();
718e3744 4966}
6b0655a2 4967
d62a17ae 4968static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 4969{
d62a17ae 4970 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
4971 && CHECK_FLAG(peer->af_cap[afi][safi],
4972 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
4973}
4974
718e3744 4975/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4976 value. */
d62a17ae 4977int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
4978 struct bgp_nlri *packet)
4979{
d7c0a89a
QY
4980 uint8_t *pnt;
4981 uint8_t *lim;
d62a17ae 4982 struct prefix p;
4983 int psize;
4984 int ret;
4985 afi_t afi;
4986 safi_t safi;
4987 int addpath_encoded;
d7c0a89a 4988 uint32_t addpath_id;
d62a17ae 4989
d62a17ae 4990 pnt = packet->nlri;
4991 lim = pnt + packet->length;
4992 afi = packet->afi;
4993 safi = packet->safi;
4994 addpath_id = 0;
4995 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
4996
4997 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4998 syntactic validity. If the field is syntactically incorrect,
4999 then the Error Subcode is set to Invalid Network Field. */
5000 for (; pnt < lim; pnt += psize) {
5001 /* Clear prefix structure. */
5002 memset(&p, 0, sizeof(struct prefix));
5003
5004 if (addpath_encoded) {
5005
5006 /* When packet overflow occurs return immediately. */
761ed665 5007 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5008 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5009
a3a850a1 5010 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5011 addpath_id = ntohl(addpath_id);
d62a17ae 5012 pnt += BGP_ADDPATH_ID_LEN;
5013 }
718e3744 5014
d62a17ae 5015 /* Fetch prefix length. */
5016 p.prefixlen = *pnt++;
5017 /* afi/safi validity already verified by caller,
5018 * bgp_update_receive */
5019 p.family = afi2family(afi);
5020
5021 /* Prefix length check. */
5022 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5023 flog_err(
e50f7cfd 5024 EC_BGP_UPDATE_RCV,
14454c9f 5025 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5026 peer->host, p.prefixlen, packet->afi);
513386b5 5027 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5028 }
6b0655a2 5029
d62a17ae 5030 /* Packet size overflow check. */
5031 psize = PSIZE(p.prefixlen);
5032
5033 /* When packet overflow occur return immediately. */
5034 if (pnt + psize > lim) {
af4c2728 5035 flog_err(
e50f7cfd 5036 EC_BGP_UPDATE_RCV,
d62a17ae 5037 "%s [Error] Update packet error (prefix length %d overflows packet)",
5038 peer->host, p.prefixlen);
513386b5 5039 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5040 }
5041
5042 /* Defensive coding, double-check the psize fits in a struct
5043 * prefix */
5044 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 5045 flog_err(
e50f7cfd 5046 EC_BGP_UPDATE_RCV,
d62a17ae 5047 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5048 peer->host, p.prefixlen, sizeof(p.u));
513386b5 5049 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5050 }
5051
5052 /* Fetch prefix from NLRI packet. */
a85297a7 5053 memcpy(p.u.val, pnt, psize);
d62a17ae 5054
5055 /* Check address. */
5056 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5057 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5058 /* From RFC4271 Section 6.3:
5059 *
5060 * If a prefix in the NLRI field is semantically
5061 * incorrect
5062 * (e.g., an unexpected multicast IP address),
5063 * an error SHOULD
5064 * be logged locally, and the prefix SHOULD be
5065 * ignored.
a4d82a8a 5066 */
af4c2728 5067 flog_err(
e50f7cfd 5068 EC_BGP_UPDATE_RCV,
23d0a753
DA
5069 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5070 peer->host, &p.u.prefix4);
d62a17ae 5071 continue;
5072 }
5073 }
5074
5075 /* Check address. */
5076 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5077 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5078 char buf[BUFSIZ];
5079
af4c2728 5080 flog_err(
e50f7cfd 5081 EC_BGP_UPDATE_RCV,
d62a17ae 5082 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
5083 peer->host,
5084 inet_ntop(AF_INET6, &p.u.prefix6, buf,
5085 BUFSIZ));
5086
5087 continue;
5088 }
5089 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
5090 char buf[BUFSIZ];
5091
af4c2728 5092 flog_err(
e50f7cfd 5093 EC_BGP_UPDATE_RCV,
d62a17ae 5094 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
5095 peer->host,
5096 inet_ntop(AF_INET6, &p.u.prefix6, buf,
5097 BUFSIZ));
5098
5099 continue;
5100 }
5101 }
5102
5103 /* Normal process. */
5104 if (attr)
5105 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5106 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5107 NULL, NULL, 0, 0, NULL);
d62a17ae 5108 else
5109 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5110 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5111 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5112 NULL);
d62a17ae 5113
513386b5
DA
5114 /* Do not send BGP notification twice when maximum-prefix count
5115 * overflow. */
5116 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5117 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5118
5119 /* Address family configuration mismatch. */
d62a17ae 5120 if (ret < 0)
513386b5 5121 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5122 }
5123
5124 /* Packet length consistency check. */
5125 if (pnt != lim) {
af4c2728 5126 flog_err(
e50f7cfd 5127 EC_BGP_UPDATE_RCV,
d62a17ae 5128 "%s [Error] Update packet error (prefix length mismatch with total length)",
5129 peer->host);
513386b5 5130 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5131 }
6b0655a2 5132
513386b5 5133 return BGP_NLRI_PARSE_OK;
718e3744 5134}
5135
d62a17ae 5136static struct bgp_static *bgp_static_new(void)
718e3744 5137{
d62a17ae 5138 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5139}
5140
d62a17ae 5141static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5142{
0a22ddfb 5143 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5144 route_map_counter_decrement(bgp_static->rmap.map);
5145
0a22ddfb 5146 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5147 XFREE(MTYPE_BGP_STATIC, bgp_static);
5148}
5149
5f040085 5150void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5151 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5152{
9bcb3eef 5153 struct bgp_dest *dest;
40381db7 5154 struct bgp_path_info *pi;
4b7e6066 5155 struct bgp_path_info *new;
40381db7 5156 struct bgp_path_info rmap_path;
d62a17ae 5157 struct attr attr;
5158 struct attr *attr_new;
b68885f9 5159 route_map_result_t ret;
49e5a4a0 5160#ifdef ENABLE_BGP_VNC
d62a17ae 5161 int vnc_implicit_withdraw = 0;
65efcfce 5162#endif
fee0f4c6 5163
d62a17ae 5164 assert(bgp_static);
dd8103a9 5165
9bcb3eef 5166 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5167
d62a17ae 5168 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 5169
d62a17ae 5170 attr.nexthop = bgp_static->igpnexthop;
5171 attr.med = bgp_static->igpmetric;
5172 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5173
d62a17ae 5174 if (bgp_static->atomic)
5175 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5176
d62a17ae 5177 /* Store label index, if required. */
5178 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5179 attr.label_index = bgp_static->label_index;
5180 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5181 }
718e3744 5182
d62a17ae 5183 /* Apply route-map. */
5184 if (bgp_static->rmap.name) {
5185 struct attr attr_tmp = attr;
80ced710 5186
40381db7
DS
5187 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5188 rmap_path.peer = bgp->peer_self;
5189 rmap_path.attr = &attr_tmp;
fee0f4c6 5190
d62a17ae 5191 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5192
40381db7
DS
5193 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
5194 &rmap_path);
fee0f4c6 5195
d62a17ae 5196 bgp->peer_self->rmap_type = 0;
718e3744 5197
d62a17ae 5198 if (ret == RMAP_DENYMATCH) {
5199 /* Free uninterned attribute. */
5200 bgp_attr_flush(&attr_tmp);
718e3744 5201
d62a17ae 5202 /* Unintern original. */
5203 aspath_unintern(&attr.aspath);
5204 bgp_static_withdraw(bgp, p, afi, safi);
5205 return;
5206 }
7f323236 5207
637e5ba4 5208 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5209 bgp_attr_add_gshut_community(&attr_tmp);
5210
d62a17ae 5211 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5212 } else {
5213
637e5ba4 5214 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5215 bgp_attr_add_gshut_community(&attr);
5216
d62a17ae 5217 attr_new = bgp_attr_intern(&attr);
7f323236 5218 }
718e3744 5219
9bcb3eef 5220 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5221 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5222 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5223 break;
5224
40381db7
DS
5225 if (pi) {
5226 if (attrhash_cmp(pi->attr, attr_new)
5227 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5228 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5229 bgp_dest_unlock_node(dest);
d62a17ae 5230 bgp_attr_unintern(&attr_new);
5231 aspath_unintern(&attr.aspath);
5232 return;
5233 } else {
5234 /* The attribute is changed. */
9bcb3eef 5235 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5236
5237 /* Rewrite BGP route information. */
40381db7 5238 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5239 bgp_path_info_restore(dest, pi);
d62a17ae 5240 else
40381db7 5241 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5242#ifdef ENABLE_BGP_VNC
d62a17ae 5243 if ((afi == AFI_IP || afi == AFI_IP6)
5244 && (safi == SAFI_UNICAST)) {
40381db7 5245 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5246 /*
5247 * Implicit withdraw case.
40381db7 5248 * We have to do this before pi is
d62a17ae 5249 * changed
5250 */
5251 ++vnc_implicit_withdraw;
40381db7 5252 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5253 vnc_import_bgp_exterior_del_route(
40381db7 5254 bgp, p, pi);
d62a17ae 5255 }
5256 }
65efcfce 5257#endif
40381db7
DS
5258 bgp_attr_unintern(&pi->attr);
5259 pi->attr = attr_new;
5260 pi->uptime = bgp_clock();
49e5a4a0 5261#ifdef ENABLE_BGP_VNC
d62a17ae 5262 if ((afi == AFI_IP || afi == AFI_IP6)
5263 && (safi == SAFI_UNICAST)) {
5264 if (vnc_implicit_withdraw) {
40381db7 5265 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5266 vnc_import_bgp_exterior_add_route(
40381db7 5267 bgp, p, pi);
d62a17ae 5268 }
5269 }
65efcfce 5270#endif
718e3744 5271
d62a17ae 5272 /* Nexthop reachability check. */
892fedb6 5273 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5274 && (safi == SAFI_UNICAST
5275 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5276
5277 struct bgp *bgp_nexthop = bgp;
5278
40381db7
DS
5279 if (pi->extra && pi->extra->bgp_orig)
5280 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5281
5282 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
40381db7 5283 afi, pi, NULL, 0))
9bcb3eef 5284 bgp_path_info_set_flag(dest, pi,
18ee8310 5285 BGP_PATH_VALID);
d62a17ae 5286 else {
5287 if (BGP_DEBUG(nht, NHT)) {
5288 char buf1[INET6_ADDRSTRLEN];
5289 inet_ntop(p->family,
5290 &p->u.prefix, buf1,
5291 INET6_ADDRSTRLEN);
5292 zlog_debug(
5293 "%s(%s): Route not in table, not advertising",
15569c58 5294 __func__, buf1);
d62a17ae 5295 }
18ee8310 5296 bgp_path_info_unset_flag(
9bcb3eef 5297 dest, pi, BGP_PATH_VALID);
d62a17ae 5298 }
5299 } else {
5300 /* Delete the NHT structure if any, if we're
5301 * toggling between
5302 * enabling/disabling import check. We
5303 * deregister the route
5304 * from NHT to avoid overloading NHT and the
5305 * process interaction
5306 */
40381db7 5307 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5308 bgp_path_info_set_flag(dest, pi,
5309 BGP_PATH_VALID);
d62a17ae 5310 }
5311 /* Process change. */
40381db7 5312 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5313 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5314
5315 if (SAFI_UNICAST == safi
5316 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5317 || bgp->inst_type
5318 == BGP_INSTANCE_TYPE_DEFAULT)) {
5319 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5320 pi);
ddb5b488
PZ
5321 }
5322
9bcb3eef 5323 bgp_dest_unlock_node(dest);
d62a17ae 5324 aspath_unintern(&attr.aspath);
5325 return;
5326 }
718e3744 5327 }
718e3744 5328
d62a17ae 5329 /* Make new BGP info. */
5330 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5331 attr_new, dest);
d62a17ae 5332 /* Nexthop reachability check. */
892fedb6 5333 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5334 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 5335 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
9bcb3eef 5336 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5337 else {
5338 if (BGP_DEBUG(nht, NHT)) {
5339 char buf1[INET6_ADDRSTRLEN];
5340 inet_ntop(p->family, &p->u.prefix, buf1,
5341 INET6_ADDRSTRLEN);
5342 zlog_debug(
5343 "%s(%s): Route not in table, not advertising",
15569c58 5344 __func__, buf1);
d62a17ae 5345 }
9bcb3eef 5346 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5347 }
5348 } else {
5349 /* Delete the NHT structure if any, if we're toggling between
5350 * enabling/disabling import check. We deregister the route
5351 * from NHT to avoid overloading NHT and the process interaction
5352 */
5353 bgp_unlink_nexthop(new);
5354
9bcb3eef 5355 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 5356 }
078430f6 5357
d62a17ae 5358 /* Aggregate address increment. */
5359 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5360
d62a17ae 5361 /* Register new BGP information. */
9bcb3eef 5362 bgp_path_info_add(dest, new);
718e3744 5363
d62a17ae 5364 /* route_node_get lock */
9bcb3eef 5365 bgp_dest_unlock_node(dest);
d62a17ae 5366
5367 /* Process change. */
9bcb3eef 5368 bgp_process(bgp, dest, afi, safi);
d62a17ae 5369
ddb5b488
PZ
5370 if (SAFI_UNICAST == safi
5371 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5372 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5373 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5374 }
5375
d62a17ae 5376 /* Unintern original. */
5377 aspath_unintern(&attr.aspath);
718e3744 5378}
5379
5f040085 5380void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 5381 safi_t safi)
718e3744 5382{
9bcb3eef 5383 struct bgp_dest *dest;
40381db7 5384 struct bgp_path_info *pi;
718e3744 5385
9bcb3eef 5386 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5387
d62a17ae 5388 /* Check selected route and self inserted route. */
9bcb3eef 5389 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5390 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5391 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5392 break;
5393
5394 /* Withdraw static BGP route from routing table. */
40381db7 5395 if (pi) {
ddb5b488
PZ
5396 if (SAFI_UNICAST == safi
5397 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5398 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5399 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5400 }
40381db7
DS
5401 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5402 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5403 bgp_path_info_delete(dest, pi);
5404 bgp_process(bgp, dest, afi, safi);
d62a17ae 5405 }
718e3744 5406
d62a17ae 5407 /* Unlock bgp_node_lookup. */
9bcb3eef 5408 bgp_dest_unlock_node(dest);
718e3744 5409}
5410
137446f9
LB
5411/*
5412 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5413 */
5f040085 5414static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5415 afi_t afi, safi_t safi,
5416 struct prefix_rd *prd)
718e3744 5417{
9bcb3eef 5418 struct bgp_dest *dest;
40381db7 5419 struct bgp_path_info *pi;
718e3744 5420
9bcb3eef 5421 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5422
d62a17ae 5423 /* Check selected route and self inserted route. */
9bcb3eef 5424 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5425 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5426 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5427 break;
718e3744 5428
d62a17ae 5429 /* Withdraw static BGP route from routing table. */
40381db7 5430 if (pi) {
49e5a4a0 5431#ifdef ENABLE_BGP_VNC
d62a17ae 5432 rfapiProcessWithdraw(
40381db7 5433 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5434 1); /* Kill, since it is an administrative change */
65efcfce 5435#endif
ddb5b488
PZ
5436 if (SAFI_MPLS_VPN == safi
5437 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5438 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5439 }
40381db7 5440 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
5441 bgp_path_info_delete(dest, pi);
5442 bgp_process(bgp, dest, afi, safi);
d62a17ae 5443 }
718e3744 5444
d62a17ae 5445 /* Unlock bgp_node_lookup. */
9bcb3eef 5446 bgp_dest_unlock_node(dest);
718e3744 5447}
5448
5f040085 5449static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5450 struct bgp_static *bgp_static, afi_t afi,
5451 safi_t safi)
137446f9 5452{
9bcb3eef 5453 struct bgp_dest *dest;
4b7e6066 5454 struct bgp_path_info *new;
d62a17ae 5455 struct attr *attr_new;
5456 struct attr attr = {0};
40381db7 5457 struct bgp_path_info *pi;
49e5a4a0 5458#ifdef ENABLE_BGP_VNC
d62a17ae 5459 mpls_label_t label = 0;
65efcfce 5460#endif
d7c0a89a 5461 uint32_t num_labels = 0;
d62a17ae 5462 union gw_addr add;
137446f9 5463
d62a17ae 5464 assert(bgp_static);
137446f9 5465
b57ba6d2
MK
5466 if (bgp_static->label != MPLS_INVALID_LABEL)
5467 num_labels = 1;
9bcb3eef
DS
5468 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5469 &bgp_static->prd);
137446f9 5470
d62a17ae 5471 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5472
d62a17ae 5473 attr.nexthop = bgp_static->igpnexthop;
5474 attr.med = bgp_static->igpmetric;
5475 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5476
d62a17ae 5477 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5478 || (safi == SAFI_ENCAP)) {
5479 if (afi == AFI_IP) {
5480 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5481 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5482 }
5483 }
5484 if (afi == AFI_L2VPN) {
5485 if (bgp_static->gatewayIp.family == AF_INET)
5486 add.ipv4.s_addr =
5487 bgp_static->gatewayIp.u.prefix4.s_addr;
5488 else if (bgp_static->gatewayIp.family == AF_INET6)
5489 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5490 sizeof(struct in6_addr));
0a50c248 5491 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 5492 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5493 struct bgp_encap_type_vxlan bet;
5494 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5495 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5496 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5497 }
5498 if (bgp_static->router_mac) {
5499 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5500 }
5501 }
5502 /* Apply route-map. */
5503 if (bgp_static->rmap.name) {
5504 struct attr attr_tmp = attr;
40381db7 5505 struct bgp_path_info rmap_path;
b68885f9 5506 route_map_result_t ret;
137446f9 5507
40381db7
DS
5508 rmap_path.peer = bgp->peer_self;
5509 rmap_path.attr = &attr_tmp;
137446f9 5510
d62a17ae 5511 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5512
40381db7
DS
5513 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
5514 &rmap_path);
137446f9 5515
d62a17ae 5516 bgp->peer_self->rmap_type = 0;
137446f9 5517
d62a17ae 5518 if (ret == RMAP_DENYMATCH) {
5519 /* Free uninterned attribute. */
5520 bgp_attr_flush(&attr_tmp);
137446f9 5521
d62a17ae 5522 /* Unintern original. */
5523 aspath_unintern(&attr.aspath);
5524 bgp_static_withdraw_safi(bgp, p, afi, safi,
5525 &bgp_static->prd);
5526 return;
5527 }
137446f9 5528
d62a17ae 5529 attr_new = bgp_attr_intern(&attr_tmp);
5530 } else {
5531 attr_new = bgp_attr_intern(&attr);
5532 }
137446f9 5533
9bcb3eef 5534 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5535 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5536 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5537 break;
5538
40381db7 5539 if (pi) {
d62a17ae 5540 memset(&add, 0, sizeof(union gw_addr));
40381db7 5541 if (attrhash_cmp(pi->attr, attr_new)
0a50c248 5542 && overlay_index_equal(afi, pi, &add)
40381db7 5543 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 5544 bgp_dest_unlock_node(dest);
d62a17ae 5545 bgp_attr_unintern(&attr_new);
5546 aspath_unintern(&attr.aspath);
5547 return;
5548 } else {
5549 /* The attribute is changed. */
9bcb3eef 5550 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5551
5552 /* Rewrite BGP route information. */
40381db7 5553 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5554 bgp_path_info_restore(dest, pi);
d62a17ae 5555 else
40381db7
DS
5556 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5557 bgp_attr_unintern(&pi->attr);
5558 pi->attr = attr_new;
5559 pi->uptime = bgp_clock();
49e5a4a0 5560#ifdef ENABLE_BGP_VNC
40381db7
DS
5561 if (pi->extra)
5562 label = decode_label(&pi->extra->label[0]);
65efcfce 5563#endif
137446f9 5564
d62a17ae 5565 /* Process change. */
40381db7 5566 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5567 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5568
5569 if (SAFI_MPLS_VPN == safi
5570 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5571 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5572 }
49e5a4a0 5573#ifdef ENABLE_BGP_VNC
40381db7
DS
5574 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5575 pi->attr, afi, safi, pi->type,
5576 pi->sub_type, &label);
65efcfce 5577#endif
9bcb3eef 5578 bgp_dest_unlock_node(dest);
d62a17ae 5579 aspath_unintern(&attr.aspath);
5580 return;
5581 }
5582 }
137446f9
LB
5583
5584
d62a17ae 5585 /* Make new BGP info. */
5586 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5587 attr_new, dest);
1defdda8 5588 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5589 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5590 if (num_labels) {
5591 new->extra->label[0] = bgp_static->label;
5592 new->extra->num_labels = num_labels;
5593 }
49e5a4a0 5594#ifdef ENABLE_BGP_VNC
d62a17ae 5595 label = decode_label(&bgp_static->label);
65efcfce 5596#endif
137446f9 5597
d62a17ae 5598 /* Aggregate address increment. */
5599 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5600
d62a17ae 5601 /* Register new BGP information. */
9bcb3eef 5602 bgp_path_info_add(dest, new);
d62a17ae 5603 /* route_node_get lock */
9bcb3eef 5604 bgp_dest_unlock_node(dest);
137446f9 5605
d62a17ae 5606 /* Process change. */
9bcb3eef 5607 bgp_process(bgp, dest, afi, safi);
137446f9 5608
ddb5b488
PZ
5609 if (SAFI_MPLS_VPN == safi
5610 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5611 vpn_leak_to_vrf_update(bgp, new);
5612 }
49e5a4a0 5613#ifdef ENABLE_BGP_VNC
d62a17ae 5614 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5615 safi, new->type, new->sub_type, &label);
65efcfce
LB
5616#endif
5617
d62a17ae 5618 /* Unintern original. */
5619 aspath_unintern(&attr.aspath);
137446f9
LB
5620}
5621
718e3744 5622/* Configure static BGP network. When user don't run zebra, static
5623 route should be installed as valid. */
37a87b8f
CS
5624int bgp_static_set(struct bgp *bgp, const char *negate, struct prefix *pfx,
5625 afi_t afi, safi_t safi, const char *rmap, int backdoor,
5626 uint32_t label_index, char *errmsg, size_t errmsg_len)
d62a17ae 5627{
d62a17ae 5628 struct prefix p;
5629 struct bgp_static *bgp_static;
9bcb3eef 5630 struct bgp_dest *dest;
d7c0a89a 5631 uint8_t need_update = 0;
d62a17ae 5632
37a87b8f 5633 prefix_copy(&p, pfx);
d62a17ae 5634 apply_mask(&p);
718e3744 5635
e2a86ad9 5636 if (negate) {
718e3744 5637
e2a86ad9 5638 /* Set BGP static route configuration. */
9bcb3eef 5639 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5640
9bcb3eef 5641 if (!dest) {
37a87b8f
CS
5642 snprintf(errmsg, errmsg_len,
5643 "Can't find static route specified\n");
5644 return -1;
d62a17ae 5645 }
5646
9bcb3eef 5647 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 5648
e2a86ad9
DS
5649 if ((label_index != BGP_INVALID_LABEL_INDEX)
5650 && (label_index != bgp_static->label_index)) {
37a87b8f
CS
5651 snprintf(errmsg, errmsg_len,
5652 "label-index doesn't match static route\n");
5653 return -1;
d62a17ae 5654 }
d62a17ae 5655
e2a86ad9
DS
5656 if ((rmap && bgp_static->rmap.name)
5657 && strcmp(rmap, bgp_static->rmap.name)) {
37a87b8f
CS
5658 snprintf(errmsg, errmsg_len,
5659 "route-map name doesn't match static route\n");
5660 return -1;
d62a17ae 5661 }
718e3744 5662
e2a86ad9
DS
5663 /* Update BGP RIB. */
5664 if (!bgp_static->backdoor)
5665 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5666
e2a86ad9
DS
5667 /* Clear configuration. */
5668 bgp_static_free(bgp_static);
9bcb3eef
DS
5669 bgp_dest_set_bgp_static_info(dest, NULL);
5670 bgp_dest_unlock_node(dest);
5671 bgp_dest_unlock_node(dest);
e2a86ad9 5672 } else {
718e3744 5673
e2a86ad9 5674 /* Set BGP static route configuration. */
9bcb3eef
DS
5675 dest = bgp_node_get(bgp->route[afi][safi], &p);
5676 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 5677 if (bgp_static) {
e2a86ad9 5678 /* Configuration change. */
e2a86ad9
DS
5679 /* Label index cannot be changed. */
5680 if (bgp_static->label_index != label_index) {
37a87b8f
CS
5681 snprintf(errmsg, errmsg_len,
5682 "cannot change label-index\n");
5683 return -1;
e2a86ad9 5684 }
d62a17ae 5685
e2a86ad9 5686 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5687 if (bgp_static->valid
5688 && bgp_static->backdoor != backdoor)
e2a86ad9 5689 need_update = 1;
718e3744 5690
e2a86ad9 5691 bgp_static->backdoor = backdoor;
718e3744 5692
e2a86ad9 5693 if (rmap) {
0a22ddfb
QY
5694 XFREE(MTYPE_ROUTE_MAP_NAME,
5695 bgp_static->rmap.name);
b4897fa5 5696 route_map_counter_decrement(
5697 bgp_static->rmap.map);
e2a86ad9
DS
5698 bgp_static->rmap.name =
5699 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5700 bgp_static->rmap.map =
5701 route_map_lookup_by_name(rmap);
b4897fa5 5702 route_map_counter_increment(
5703 bgp_static->rmap.map);
e2a86ad9 5704 } else {
0a22ddfb
QY
5705 XFREE(MTYPE_ROUTE_MAP_NAME,
5706 bgp_static->rmap.name);
b4897fa5 5707 route_map_counter_decrement(
5708 bgp_static->rmap.map);
e2a86ad9
DS
5709 bgp_static->rmap.map = NULL;
5710 bgp_static->valid = 0;
5711 }
9bcb3eef 5712 bgp_dest_unlock_node(dest);
e2a86ad9
DS
5713 } else {
5714 /* New configuration. */
5715 bgp_static = bgp_static_new();
5716 bgp_static->backdoor = backdoor;
5717 bgp_static->valid = 0;
5718 bgp_static->igpmetric = 0;
975a328e 5719 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 5720 bgp_static->label_index = label_index;
718e3744 5721
e2a86ad9 5722 if (rmap) {
0a22ddfb
QY
5723 XFREE(MTYPE_ROUTE_MAP_NAME,
5724 bgp_static->rmap.name);
b4897fa5 5725 route_map_counter_decrement(
5726 bgp_static->rmap.map);
e2a86ad9
DS
5727 bgp_static->rmap.name =
5728 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5729 bgp_static->rmap.map =
5730 route_map_lookup_by_name(rmap);
b4897fa5 5731 route_map_counter_increment(
5732 bgp_static->rmap.map);
e2a86ad9 5733 }
9bcb3eef 5734 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 5735 }
d62a17ae 5736
e2a86ad9
DS
5737 bgp_static->valid = 1;
5738 if (need_update)
5739 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5740
e2a86ad9
DS
5741 if (!bgp_static->backdoor)
5742 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5743 }
d62a17ae 5744
37a87b8f 5745 return 0;
d62a17ae 5746}
5747
5748void bgp_static_add(struct bgp *bgp)
5749{
5750 afi_t afi;
5751 safi_t safi;
9bcb3eef
DS
5752 struct bgp_dest *dest;
5753 struct bgp_dest *rm;
d62a17ae 5754 struct bgp_table *table;
5755 struct bgp_static *bgp_static;
5756
05c7a1cc 5757 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5758 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5759 dest = bgp_route_next(dest)) {
5760 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5761 continue;
ea47320b 5762
05c7a1cc
QY
5763 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5764 || (safi == SAFI_EVPN)) {
9bcb3eef 5765 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5766
5767 for (rm = bgp_table_top(table); rm;
5768 rm = bgp_route_next(rm)) {
a78beeb5 5769 bgp_static =
9bcb3eef 5770 bgp_dest_get_bgp_static_info(
5a8ba9fc 5771 rm);
9bcb3eef
DS
5772 bgp_static_update_safi(
5773 bgp, bgp_dest_get_prefix(rm),
5774 bgp_static, afi, safi);
d62a17ae 5775 }
05c7a1cc 5776 } else {
5a8ba9fc 5777 bgp_static_update(
9bcb3eef
DS
5778 bgp, bgp_dest_get_prefix(dest),
5779 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 5780 safi);
ea47320b 5781 }
05c7a1cc 5782 }
6aeb9e78
DS
5783}
5784
718e3744 5785/* Called from bgp_delete(). Delete all static routes from the BGP
5786 instance. */
d62a17ae 5787void bgp_static_delete(struct bgp *bgp)
5788{
5789 afi_t afi;
5790 safi_t safi;
9bcb3eef
DS
5791 struct bgp_dest *dest;
5792 struct bgp_dest *rm;
d62a17ae 5793 struct bgp_table *table;
5794 struct bgp_static *bgp_static;
5795
05c7a1cc 5796 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5797 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5798 dest = bgp_route_next(dest)) {
5799 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5800 continue;
ea47320b 5801
05c7a1cc
QY
5802 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5803 || (safi == SAFI_EVPN)) {
9bcb3eef 5804 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5805
5806 for (rm = bgp_table_top(table); rm;
5807 rm = bgp_route_next(rm)) {
a78beeb5 5808 bgp_static =
9bcb3eef 5809 bgp_dest_get_bgp_static_info(
5a8ba9fc 5810 rm);
c7d14ba6
PG
5811 if (!bgp_static)
5812 continue;
5813
05c7a1cc 5814 bgp_static_withdraw_safi(
9bcb3eef 5815 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
5816 AFI_IP, safi,
5817 (struct prefix_rd *)
9bcb3eef
DS
5818 bgp_dest_get_prefix(
5819 dest));
ea47320b 5820 bgp_static_free(bgp_static);
811c6797 5821 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 5822 NULL);
811c6797 5823 bgp_dest_unlock_node(rm);
d62a17ae 5824 }
05c7a1cc 5825 } else {
9bcb3eef 5826 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 5827 bgp_static_withdraw(bgp,
9bcb3eef 5828 bgp_dest_get_prefix(dest),
b54892e0 5829 afi, safi);
05c7a1cc 5830 bgp_static_free(bgp_static);
9bcb3eef
DS
5831 bgp_dest_set_bgp_static_info(dest, NULL);
5832 bgp_dest_unlock_node(dest);
ea47320b 5833 }
05c7a1cc 5834 }
d62a17ae 5835}
5836
5837void bgp_static_redo_import_check(struct bgp *bgp)
5838{
5839 afi_t afi;
5840 safi_t safi;
9bcb3eef
DS
5841 struct bgp_dest *dest;
5842 struct bgp_dest *rm;
d62a17ae 5843 struct bgp_table *table;
5844 struct bgp_static *bgp_static;
5845
5846 /* Use this flag to force reprocessing of the route */
892fedb6 5847 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 5848 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
5849 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5850 dest = bgp_route_next(dest)) {
5851 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5852 continue;
ea47320b 5853
05c7a1cc
QY
5854 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5855 || (safi == SAFI_EVPN)) {
9bcb3eef 5856 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5857
5858 for (rm = bgp_table_top(table); rm;
5859 rm = bgp_route_next(rm)) {
a78beeb5 5860 bgp_static =
9bcb3eef 5861 bgp_dest_get_bgp_static_info(
5a8ba9fc 5862 rm);
9bcb3eef
DS
5863 bgp_static_update_safi(
5864 bgp, bgp_dest_get_prefix(rm),
5865 bgp_static, afi, safi);
d62a17ae 5866 }
05c7a1cc 5867 } else {
9bcb3eef
DS
5868 bgp_static = bgp_dest_get_bgp_static_info(dest);
5869 bgp_static_update(bgp,
5870 bgp_dest_get_prefix(dest),
5871 bgp_static, afi, safi);
ea47320b 5872 }
05c7a1cc
QY
5873 }
5874 }
892fedb6 5875 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 5876}
5877
5878static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
5879 safi_t safi)
5880{
5881 struct bgp_table *table;
9bcb3eef 5882 struct bgp_dest *dest;
40381db7 5883 struct bgp_path_info *pi;
d62a17ae 5884
dfb6fd1d
NT
5885 /* Do not install the aggregate route if BGP is in the
5886 * process of termination.
5887 */
892fedb6
DA
5888 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
5889 || (bgp->peer_self == NULL))
dfb6fd1d
NT
5890 return;
5891
d62a17ae 5892 table = bgp->rib[afi][safi];
9bcb3eef
DS
5893 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5894 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
5895 if (pi->peer == bgp->peer_self
5896 && ((pi->type == ZEBRA_ROUTE_BGP
5897 && pi->sub_type == BGP_ROUTE_STATIC)
5898 || (pi->type != ZEBRA_ROUTE_BGP
5899 && pi->sub_type
d62a17ae 5900 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
5901 bgp_aggregate_decrement(
5902 bgp, bgp_dest_get_prefix(dest), pi, afi,
5903 safi);
40381db7 5904 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5905 bgp_path_info_delete(dest, pi);
5906 bgp_process(bgp, dest, afi, safi);
d62a17ae 5907 }
5908 }
5909 }
ad4cbda1 5910}
5911
5912/*
5913 * Purge all networks and redistributed routes from routing table.
5914 * Invoked upon the instance going down.
5915 */
d62a17ae 5916void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 5917{
d62a17ae 5918 afi_t afi;
5919 safi_t safi;
ad4cbda1 5920
05c7a1cc
QY
5921 FOREACH_AFI_SAFI (afi, safi)
5922 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 5923}
5924
137446f9
LB
5925/*
5926 * gpz 110624
5927 * Currently this is used to set static routes for VPN and ENCAP.
5928 * I think it can probably be factored with bgp_static_set.
5929 */
d62a17ae 5930int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
5931 const char *ip_str, const char *rd_str,
5932 const char *label_str, const char *rmap_str,
5933 int evpn_type, const char *esi, const char *gwip,
5934 const char *ethtag, const char *routermac)
5935{
5936 VTY_DECLVAR_CONTEXT(bgp, bgp);
5937 int ret;
5938 struct prefix p;
5939 struct prefix_rd prd;
9bcb3eef
DS
5940 struct bgp_dest *pdest;
5941 struct bgp_dest *dest;
d62a17ae 5942 struct bgp_table *table;
5943 struct bgp_static *bgp_static;
5944 mpls_label_t label = MPLS_INVALID_LABEL;
5945 struct prefix gw_ip;
5946
5947 /* validate ip prefix */
5948 ret = str2prefix(ip_str, &p);
5949 if (!ret) {
5950 vty_out(vty, "%% Malformed prefix\n");
5951 return CMD_WARNING_CONFIG_FAILED;
5952 }
5953 apply_mask(&p);
5954 if ((afi == AFI_L2VPN)
5955 && (bgp_build_evpn_prefix(evpn_type,
5956 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5957 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5958 return CMD_WARNING_CONFIG_FAILED;
5959 }
718e3744 5960
d62a17ae 5961 ret = str2prefix_rd(rd_str, &prd);
5962 if (!ret) {
5963 vty_out(vty, "%% Malformed rd\n");
5964 return CMD_WARNING_CONFIG_FAILED;
5965 }
718e3744 5966
d62a17ae 5967 if (label_str) {
5968 unsigned long label_val;
5969 label_val = strtoul(label_str, NULL, 10);
5970 encode_label(label_val, &label);
5971 }
9bedbb1e 5972
d62a17ae 5973 if (safi == SAFI_EVPN) {
5974 if (esi && str2esi(esi, NULL) == 0) {
5975 vty_out(vty, "%% Malformed ESI\n");
5976 return CMD_WARNING_CONFIG_FAILED;
5977 }
5978 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
5979 vty_out(vty, "%% Malformed Router MAC\n");
5980 return CMD_WARNING_CONFIG_FAILED;
5981 }
5982 if (gwip) {
5983 memset(&gw_ip, 0, sizeof(struct prefix));
5984 ret = str2prefix(gwip, &gw_ip);
5985 if (!ret) {
5986 vty_out(vty, "%% Malformed GatewayIp\n");
5987 return CMD_WARNING_CONFIG_FAILED;
5988 }
5989 if ((gw_ip.family == AF_INET
3714a385 5990 && is_evpn_prefix_ipaddr_v6(
d62a17ae 5991 (struct prefix_evpn *)&p))
5992 || (gw_ip.family == AF_INET6
3714a385 5993 && is_evpn_prefix_ipaddr_v4(
d62a17ae 5994 (struct prefix_evpn *)&p))) {
5995 vty_out(vty,
5996 "%% GatewayIp family differs with IP prefix\n");
5997 return CMD_WARNING_CONFIG_FAILED;
5998 }
5999 }
6000 }
9bcb3eef
DS
6001 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6002 if (!bgp_dest_has_bgp_path_info_data(pdest))
6003 bgp_dest_set_bgp_table_info(pdest,
67009e22 6004 bgp_table_init(bgp, afi, safi));
9bcb3eef 6005 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6006
9bcb3eef 6007 dest = bgp_node_get(table, &p);
d62a17ae 6008
9bcb3eef 6009 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6010 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6011 bgp_dest_unlock_node(dest);
d62a17ae 6012 } else {
6013 /* New configuration. */
6014 bgp_static = bgp_static_new();
6015 bgp_static->backdoor = 0;
6016 bgp_static->valid = 0;
6017 bgp_static->igpmetric = 0;
975a328e 6018 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6019 bgp_static->label = label;
6020 bgp_static->prd = prd;
6021
6022 if (rmap_str) {
0a22ddfb 6023 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6024 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6025 bgp_static->rmap.name =
6026 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6027 bgp_static->rmap.map =
6028 route_map_lookup_by_name(rmap_str);
b4897fa5 6029 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6030 }
718e3744 6031
d62a17ae 6032 if (safi == SAFI_EVPN) {
6033 if (esi) {
6034 bgp_static->eth_s_id =
6035 XCALLOC(MTYPE_ATTR,
0a50c248 6036 sizeof(esi_t));
d62a17ae 6037 str2esi(esi, bgp_static->eth_s_id);
6038 }
6039 if (routermac) {
6040 bgp_static->router_mac =
28328ea9 6041 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6042 (void)prefix_str2mac(routermac,
6043 bgp_static->router_mac);
d62a17ae 6044 }
6045 if (gwip)
6046 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6047 }
9bcb3eef 6048 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6049
d62a17ae 6050 bgp_static->valid = 1;
6051 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6052 }
718e3744 6053
d62a17ae 6054 return CMD_SUCCESS;
718e3744 6055}
6056
6057/* Configure static BGP network. */
d62a17ae 6058int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6059 const char *ip_str, const char *rd_str,
6060 const char *label_str, int evpn_type, const char *esi,
6061 const char *gwip, const char *ethtag)
6062{
6063 VTY_DECLVAR_CONTEXT(bgp, bgp);
6064 int ret;
6065 struct prefix p;
6066 struct prefix_rd prd;
9bcb3eef
DS
6067 struct bgp_dest *pdest;
6068 struct bgp_dest *dest;
d62a17ae 6069 struct bgp_table *table;
6070 struct bgp_static *bgp_static;
6071 mpls_label_t label = MPLS_INVALID_LABEL;
6072
6073 /* Convert IP prefix string to struct prefix. */
6074 ret = str2prefix(ip_str, &p);
6075 if (!ret) {
6076 vty_out(vty, "%% Malformed prefix\n");
6077 return CMD_WARNING_CONFIG_FAILED;
6078 }
6079 apply_mask(&p);
6080 if ((afi == AFI_L2VPN)
6081 && (bgp_build_evpn_prefix(evpn_type,
6082 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6083 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6084 return CMD_WARNING_CONFIG_FAILED;
6085 }
6086 ret = str2prefix_rd(rd_str, &prd);
6087 if (!ret) {
6088 vty_out(vty, "%% Malformed rd\n");
6089 return CMD_WARNING_CONFIG_FAILED;
6090 }
718e3744 6091
d62a17ae 6092 if (label_str) {
6093 unsigned long label_val;
6094 label_val = strtoul(label_str, NULL, 10);
6095 encode_label(label_val, &label);
6096 }
718e3744 6097
9bcb3eef
DS
6098 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6099 if (!bgp_dest_has_bgp_path_info_data(pdest))
6100 bgp_dest_set_bgp_table_info(pdest,
67009e22 6101 bgp_table_init(bgp, afi, safi));
d62a17ae 6102 else
9bcb3eef
DS
6103 bgp_dest_unlock_node(pdest);
6104 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6105
9bcb3eef 6106 dest = bgp_node_lookup(table, &p);
6b0655a2 6107
9bcb3eef 6108 if (dest) {
d62a17ae 6109 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6110
9bcb3eef 6111 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6112 bgp_static_free(bgp_static);
9bcb3eef
DS
6113 bgp_dest_set_bgp_static_info(dest, NULL);
6114 bgp_dest_unlock_node(dest);
6115 bgp_dest_unlock_node(dest);
d62a17ae 6116 } else
6117 vty_out(vty, "%% Can't find the route\n");
6118
6119 return CMD_SUCCESS;
6120}
6121
6122static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6123 const char *rmap_name)
6124{
6125 VTY_DECLVAR_CONTEXT(bgp, bgp);
6126 struct bgp_rmap *rmap;
6127
6128 rmap = &bgp->table_map[afi][safi];
6129 if (rmap_name) {
0a22ddfb 6130 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6131 route_map_counter_decrement(rmap->map);
d62a17ae 6132 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6133 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6134 route_map_counter_increment(rmap->map);
d62a17ae 6135 } else {
0a22ddfb 6136 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6137 route_map_counter_decrement(rmap->map);
d62a17ae 6138 rmap->map = NULL;
6139 }
73ac8160 6140
d62a17ae 6141 if (bgp_fibupd_safi(safi))
6142 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6143
d62a17ae 6144 return CMD_SUCCESS;
73ac8160
DS
6145}
6146
d62a17ae 6147static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6148 const char *rmap_name)
73ac8160 6149{
d62a17ae 6150 VTY_DECLVAR_CONTEXT(bgp, bgp);
6151 struct bgp_rmap *rmap;
73ac8160 6152
d62a17ae 6153 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6154 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6155 route_map_counter_decrement(rmap->map);
d62a17ae 6156 rmap->map = NULL;
73ac8160 6157
d62a17ae 6158 if (bgp_fibupd_safi(safi))
6159 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6160
d62a17ae 6161 return CMD_SUCCESS;
73ac8160
DS
6162}
6163
2b791107 6164void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6165 safi_t safi)
73ac8160 6166{
d62a17ae 6167 if (bgp->table_map[afi][safi].name) {
d62a17ae 6168 vty_out(vty, " table-map %s\n",
6169 bgp->table_map[afi][safi].name);
6170 }
73ac8160
DS
6171}
6172
73ac8160
DS
6173DEFUN (bgp_table_map,
6174 bgp_table_map_cmd,
6175 "table-map WORD",
6176 "BGP table to RIB route download filter\n"
6177 "Name of the route map\n")
6178{
d62a17ae 6179 int idx_word = 1;
6180 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6181 argv[idx_word]->arg);
73ac8160
DS
6182}
6183DEFUN (no_bgp_table_map,
6184 no_bgp_table_map_cmd,
6185 "no table-map WORD",
3a2d747c 6186 NO_STR
73ac8160
DS
6187 "BGP table to RIB route download filter\n"
6188 "Name of the route map\n")
6189{
d62a17ae 6190 int idx_word = 2;
6191 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6192 argv[idx_word]->arg);
73ac8160
DS
6193}
6194
37a87b8f
CS
6195DEFPY_YANG (bgp_network, bgp_network_cmd,
6196 "[no] network \
6197 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6198 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6199 backdoor$backdoor}]",
6200 NO_STR
6201 "Specify a network to announce via BGP\n"
6202 "IPv4 prefix\n"
6203 "Network number\n"
6204 "Network mask\n"
6205 "Network mask\n"
6206 "Route-map to modify the attributes\n"
6207 "Name of the route map\n"
6208 "Label index to associate with the prefix\n"
6209 "Label index value\n"
6210 "Specify a BGP backdoor route\n")
6211{
6212 char addr_prefix_str[PREFIX_STRLEN];
6213 char base_xpath[XPATH_MAXLEN];
6214 afi_t afi;
6215 safi_t safi;
e2a86ad9
DS
6216
6217 if (address_str) {
6218 int ret;
718e3744 6219
e2a86ad9
DS
6220 ret = netmask_str2prefix_str(address_str, netmask_str,
6221 addr_prefix_str);
6222 if (!ret) {
6223 vty_out(vty, "%% Inconsistent address and mask\n");
6224 return CMD_WARNING_CONFIG_FAILED;
6225 }
d62a17ae 6226 }
718e3744 6227
37a87b8f
CS
6228 afi = bgp_node_afi(vty);
6229 safi = bgp_node_safi(vty);
6230
6231 if (no) {
6232 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6233 } else {
6234 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6235
6236 if (map_name)
6237 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6238 NB_OP_CREATE, map_name);
6239 else
6240 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6241 NB_OP_DESTROY, NULL);
6242
6243 if (label_index_str)
6244 nb_cli_enqueue_change(vty, "./label-index",
6245 NB_OP_MODIFY, label_index_str);
6246
6247 nb_cli_enqueue_change(vty, "./backdoor", NB_OP_MODIFY,
6248 backdoor ? "true" : "false");
6249 }
6250
6251 snprintf(
6252 base_xpath, sizeof(base_xpath),
6253 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6254 yang_afi_safi_value2identity(afi, safi),
6255 bgp_afi_safi_get_container_str(afi, safi),
6256 address_str ? addr_prefix_str : prefix_str);
6257
6258 return nb_cli_apply_changes(vty, base_xpath);
718e3744 6259}
6260
37a87b8f
CS
6261DEFPY_YANG (ipv6_bgp_network,
6262 ipv6_bgp_network_cmd,
6263 "[no] network X:X::X:X/M$prefix \
6264 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6265 NO_STR
6266 "Specify a network to announce via BGP\n"
6267 "IPv6 prefix\n"
6268 "Route-map to modify the attributes\n"
6269 "Name of the route map\n"
6270 "Label index to associate with the prefix\n"
6271 "Label index value\n")
6272{
6273 char base_xpath[XPATH_MAXLEN];
6274 afi_t afi;
6275 safi_t safi;
6276
6277 afi = bgp_node_afi(vty);
6278 safi = bgp_node_safi(vty);
6279
6280 if (no) {
6281 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6282 } else {
6283 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6284
6285 if (map_name)
6286 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6287 NB_OP_MODIFY, map_name);
6288 else
6289 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6290 NB_OP_DESTROY, NULL);
6291
6292 if (label_index_str)
6293 nb_cli_enqueue_change(vty, "./label-index",
6294 NB_OP_MODIFY, label_index_str);
6295 }
6296
6297 snprintf(
6298 base_xpath, sizeof(base_xpath),
6299 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6300 yang_afi_safi_value2identity(afi, safi),
6301 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
6302
6303 return nb_cli_apply_changes(vty, base_xpath);
6304}
6305
6306void cli_show_bgp_global_afi_safi_network_config(struct vty *vty,
6307 struct lyd_node *dnode,
6308 bool show_defaults)
718e3744 6309{
37a87b8f
CS
6310 vty_out(vty, " network %s", yang_dnode_get_string(dnode, "./prefix"));
6311
6312 if (yang_dnode_exists(dnode, "./label-index"))
6313 vty_out(vty, " label-index %s",
6314 yang_dnode_get_string(dnode, "./label-index"));
6315
6316 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
6317 vty_out(vty, " route-map %s",
6318 yang_dnode_get_string(dnode, "./rmap-policy-export"));
6319
6320 if (yang_dnode_get_bool(dnode, "./backdoor"))
6321 vty_out(vty, " backdoor");
6322
6323 vty_out(vty, "\n");
1b6d5c7e
VV
6324}
6325
d62a17ae 6326static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6327{
d62a17ae 6328 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6329}
6330
d62a17ae 6331static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6332{
365ab2e7
RZ
6333 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6334 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6335 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6336 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6337 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6338}
718e3744 6339
365ab2e7
RZ
6340/**
6341 * Helper function to avoid repeated code: prepare variables for a
6342 * `route_map_apply` call.
6343 *
6344 * \returns `true` on route map match, otherwise `false`.
6345 */
6346static bool aggr_suppress_map_test(struct bgp *bgp,
6347 struct bgp_aggregate *aggregate,
6348 struct bgp_path_info *pi)
6349{
6350 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6351 route_map_result_t rmr = RMAP_DENYMATCH;
6352 struct bgp_path_info rmap_path = {};
6353 struct attr attr = {};
6354
6355 /* No route map entries created, just don't match. */
6356 if (aggregate->suppress_map == NULL)
6357 return false;
6358
6359 /* Call route map matching and return result. */
6360 attr.aspath = aspath_empty();
6361 rmap_path.peer = bgp->peer_self;
6362 rmap_path.attr = &attr;
6363
6364 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
6365 rmr = route_map_apply(aggregate->suppress_map, p, RMAP_BGP, &rmap_path);
6366 bgp->peer_self->rmap_type = 0;
6367
6368 bgp_attr_flush(&attr);
6369
6370 return rmr == RMAP_PERMITMATCH;
6371}
6372
4056a5f6
RZ
6373/** Test whether the aggregation has suppressed this path or not. */
6374static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6375 struct bgp_path_info *pi)
6376{
6377 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6378 return false;
6379
6380 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6381}
6382
6383/**
6384 * Suppress this path and keep the reference.
6385 *
6386 * \returns `true` if needs processing otherwise `false`.
6387 */
6388static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6389 struct bgp_path_info *pi)
6390{
6391 struct bgp_path_info_extra *pie;
6392
6393 /* Path is already suppressed by this aggregation. */
6394 if (aggr_suppress_exists(aggregate, pi))
6395 return false;
6396
6397 pie = bgp_path_info_extra_get(pi);
6398
6399 /* This is the first suppression, allocate memory and list it. */
6400 if (pie->aggr_suppressors == NULL)
6401 pie->aggr_suppressors = list_new();
6402
6403 listnode_add(pie->aggr_suppressors, aggregate);
6404
6405 /* Only mark for processing if suppressed. */
6406 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
6407 if (BGP_DEBUG(update, UPDATE_OUT))
6408 zlog_debug("aggregate-address suppressing: %pFX",
6409 bgp_dest_get_prefix(pi->net));
6410
4056a5f6
RZ
6411 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6412 return true;
6413 }
6414
6415 return false;
6416}
6417
6418/**
6419 * Unsuppress this path and remove the reference.
6420 *
6421 * \returns `true` if needs processing otherwise `false`.
6422 */
6423static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
6424 struct bgp_path_info *pi)
6425{
6426 /* Path wasn't suppressed. */
6427 if (!aggr_suppress_exists(aggregate, pi))
6428 return false;
6429
6430 listnode_delete(pi->extra->aggr_suppressors, aggregate);
6431
6432 /* Unsuppress and free extra memory if last item. */
6433 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
6434 if (BGP_DEBUG(update, UPDATE_OUT))
6435 zlog_debug("aggregate-address unsuppressing: %pFX",
6436 bgp_dest_get_prefix(pi->net));
6437
4056a5f6
RZ
6438 list_delete(&pi->extra->aggr_suppressors);
6439 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6440 return true;
6441 }
6442
6443 return false;
6444}
6445
3dc339cd
DA
6446static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6447 struct aspath *aspath,
6448 struct community *comm,
6449 struct ecommunity *ecomm,
6450 struct lcommunity *lcomm)
eaaf8adb
DS
6451{
6452 static struct aspath *ae = NULL;
6453
6454 if (!ae)
6455 ae = aspath_empty();
6456
40381db7 6457 if (!pi)
3dc339cd 6458 return false;
eaaf8adb 6459
40381db7 6460 if (origin != pi->attr->origin)
3dc339cd 6461 return false;
eaaf8adb 6462
40381db7 6463 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 6464 return false;
29f7d023 6465
40381db7 6466 if (!community_cmp(pi->attr->community, comm))
3dc339cd 6467 return false;
eaaf8adb 6468
3da2cc32 6469 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
3dc339cd 6470 return false;
eaaf8adb 6471
dd18c5a9 6472 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 6473 return false;
dd18c5a9 6474
40381db7 6475 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 6476 return false;
7ce8a8e0 6477
3dc339cd 6478 return true;
eaaf8adb
DS
6479}
6480
5f040085
DS
6481static void bgp_aggregate_install(
6482 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6483 uint8_t origin, struct aspath *aspath, struct community *community,
6484 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6485 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 6486{
9bcb3eef 6487 struct bgp_dest *dest;
c701010e 6488 struct bgp_table *table;
6f94b685 6489 struct bgp_path_info *pi, *orig, *new;
20894f50 6490 struct attr *attr;
c701010e
DS
6491
6492 table = bgp->rib[afi][safi];
6493
9bcb3eef 6494 dest = bgp_node_get(table, p);
eaaf8adb 6495
9bcb3eef 6496 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6497 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6498 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6499 break;
6500
6aabb15d
RZ
6501 /*
6502 * If we have paths with different MEDs, then don't install
6503 * (or uninstall) the aggregate route.
6504 */
6505 if (aggregate->match_med && aggregate->med_mismatched)
6506 goto uninstall_aggregate_route;
6507
c701010e 6508 if (aggregate->count > 0) {
eaaf8adb
DS
6509 /*
6510 * If the aggregate information has not changed
6511 * no need to re-install it again.
6512 */
6f94b685 6513 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6514 ecommunity, lcommunity)) {
9bcb3eef 6515 bgp_dest_unlock_node(dest);
eaaf8adb
DS
6516
6517 if (aspath)
6518 aspath_free(aspath);
6519 if (community)
3c1f53de 6520 community_free(&community);
3da2cc32
DS
6521 if (ecommunity)
6522 ecommunity_free(&ecommunity);
dd18c5a9
DS
6523 if (lcommunity)
6524 lcommunity_free(&lcommunity);
eaaf8adb
DS
6525
6526 return;
6527 }
6528
6529 /*
6530 * Mark the old as unusable
6531 */
40381db7 6532 if (pi)
9bcb3eef 6533 bgp_path_info_delete(dest, pi);
eaaf8adb 6534
20894f50
DA
6535 attr = bgp_attr_aggregate_intern(
6536 bgp, origin, aspath, community, ecommunity, lcommunity,
6537 aggregate, atomic_aggregate, p);
6538
6539 if (!attr) {
6540 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
6541 return;
6542 }
6543
3da2cc32 6544 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 6545 bgp->peer_self, attr, dest);
20894f50 6546
1defdda8 6547 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6548
9bcb3eef
DS
6549 bgp_path_info_add(dest, new);
6550 bgp_process(bgp, dest, afi, safi);
c701010e 6551 } else {
6aabb15d 6552 uninstall_aggregate_route:
6f94b685 6553 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6554 if (pi->peer == bgp->peer_self
6555 && pi->type == ZEBRA_ROUTE_BGP
6556 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6557 break;
6558
6559 /* Withdraw static BGP route from routing table. */
40381db7 6560 if (pi) {
9bcb3eef
DS
6561 bgp_path_info_delete(dest, pi);
6562 bgp_process(bgp, dest, afi, safi);
c701010e
DS
6563 }
6564 }
6565
9bcb3eef 6566 bgp_dest_unlock_node(dest);
c701010e
DS
6567}
6568
6aabb15d
RZ
6569/**
6570 * Check if the current path has different MED than other known paths.
6571 *
6572 * \returns `true` if the MED matched the others else `false`.
6573 */
6574static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
6575 struct bgp *bgp, struct bgp_path_info *pi)
6576{
6577 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
6578
6579 /* This is the first route being analyzed. */
6580 if (!aggregate->med_initialized) {
6581 aggregate->med_initialized = true;
6582 aggregate->med_mismatched = false;
6583 aggregate->med_matched_value = cur_med;
6584 } else {
6585 /* Check if routes with different MED showed up. */
6586 if (cur_med != aggregate->med_matched_value)
6587 aggregate->med_mismatched = true;
6588 }
6589
6590 return !aggregate->med_mismatched;
6591}
6592
6593/**
6594 * Initializes and tests all routes in the aggregate address path for MED
6595 * values.
6596 *
6597 * \returns `true` if all MEDs are the same otherwise `false`.
6598 */
6599static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
6600 struct bgp *bgp, const struct prefix *p,
6601 afi_t afi, safi_t safi)
6602{
6603 struct bgp_table *table = bgp->rib[afi][safi];
6604 const struct prefix *dest_p;
6605 struct bgp_dest *dest, *top;
6606 struct bgp_path_info *pi;
6607 bool med_matched = true;
6608
6609 aggregate->med_initialized = false;
6610
6611 top = bgp_node_get(table, p);
6612 for (dest = bgp_node_get(table, p); dest;
6613 dest = bgp_route_next_until(dest, top)) {
6614 dest_p = bgp_dest_get_prefix(dest);
6615 if (dest_p->prefixlen <= p->prefixlen)
6616 continue;
6617
6618 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6619 if (BGP_PATH_HOLDDOWN(pi))
6620 continue;
6621 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6622 continue;
6623 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
6624 med_matched = false;
6625 break;
6626 }
6627 }
6628 if (!med_matched)
6629 break;
6630 }
6631 bgp_dest_unlock_node(top);
6632
6633 return med_matched;
6634}
6635
6636/**
6637 * Toggles the route suppression status for this aggregate address
6638 * configuration.
6639 */
4056a5f6
RZ
6640void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
6641 struct bgp *bgp, const struct prefix *p,
6642 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
6643{
6644 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
6645 const struct prefix *dest_p;
6646 struct bgp_dest *dest, *top;
6647 struct bgp_path_info *pi;
6648 bool toggle_suppression;
6649
6650 /* We've found a different MED we must revert any suppressed routes. */
6651 top = bgp_node_get(table, p);
6652 for (dest = bgp_node_get(table, p); dest;
6653 dest = bgp_route_next_until(dest, top)) {
6654 dest_p = bgp_dest_get_prefix(dest);
6655 if (dest_p->prefixlen <= p->prefixlen)
6656 continue;
6657
6658 toggle_suppression = false;
6659 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6660 if (BGP_PATH_HOLDDOWN(pi))
6661 continue;
6662 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6663 continue;
6664
6aabb15d
RZ
6665 /* We are toggling suppression back. */
6666 if (suppress) {
6aabb15d 6667 /* Suppress route if not suppressed already. */
4056a5f6
RZ
6668 if (aggr_suppress_path(aggregate, pi))
6669 toggle_suppression = true;
6aabb15d
RZ
6670 continue;
6671 }
6672
6aabb15d 6673 /* Install route if there is no more suppression. */
4056a5f6 6674 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 6675 toggle_suppression = true;
6aabb15d
RZ
6676 }
6677
6678 if (toggle_suppression)
6679 bgp_process(bgp, dest, afi, safi);
6680 }
6681 bgp_dest_unlock_node(top);
6682}
6683
6684/**
6685 * Aggregate address MED matching incremental test: this function is called
6686 * when the initial aggregation occurred and we are only testing a single
6687 * new path.
6688 *
6689 * In addition to testing and setting the MED validity it also installs back
6690 * suppressed routes (if summary is configured).
6691 *
6692 * Must not be called in `bgp_aggregate_route`.
6693 */
6694static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
6695 struct bgp *bgp, const struct prefix *p,
6696 afi_t afi, safi_t safi,
6697 struct bgp_path_info *pi, bool is_adding)
6698{
6699 /* MED matching disabled. */
6700 if (!aggregate->match_med)
6701 return;
6702
6703 /* Aggregation with different MED, nothing to do. */
6704 if (aggregate->med_mismatched)
6705 return;
6706
6707 /*
6708 * Test the current entry:
6709 *
6710 * is_adding == true: if the new entry doesn't match then we must
6711 * install all suppressed routes.
6712 *
6713 * is_adding == false: if the entry being removed was the last
6714 * unmatching entry then we can suppress all routes.
6715 */
6716 if (!is_adding) {
6717 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
6718 && aggregate->summary_only)
6719 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
6720 safi, true);
6721 } else
6722 bgp_aggregate_med_match(aggregate, bgp, pi);
6723
6724 /* No mismatches, just quit. */
6725 if (!aggregate->med_mismatched)
6726 return;
6727
6728 /* Route summarization is disabled. */
6729 if (!aggregate->summary_only)
6730 return;
6731
6732 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
6733}
6734
b5d58c32 6735/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
6736void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
6737 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 6738{
6739 struct bgp_table *table;
9bcb3eef
DS
6740 struct bgp_dest *top;
6741 struct bgp_dest *dest;
d7c0a89a 6742 uint8_t origin;
d62a17ae 6743 struct aspath *aspath = NULL;
d62a17ae 6744 struct community *community = NULL;
3da2cc32 6745 struct ecommunity *ecommunity = NULL;
dd18c5a9 6746 struct lcommunity *lcommunity = NULL;
40381db7 6747 struct bgp_path_info *pi;
d62a17ae 6748 unsigned long match = 0;
d7c0a89a 6749 uint8_t atomic_aggregate = 0;
d62a17ae 6750
9f822fa2
S
6751 /* If the bgp instance is being deleted or self peer is deleted
6752 * then do not create aggregate route
6753 */
892fedb6
DA
6754 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6755 || (bgp->peer_self == NULL))
9f822fa2
S
6756 return;
6757
6aabb15d
RZ
6758 /* Initialize and test routes for MED difference. */
6759 if (aggregate->match_med)
6760 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
6761
4056a5f6
RZ
6762 /*
6763 * Reset aggregate count: we might've been called from route map
6764 * update so in that case we must retest all more specific routes.
6765 *
6766 * \see `bgp_route_map_process_update`.
6767 */
6768 aggregate->count = 0;
6769 aggregate->incomplete_origin_count = 0;
6770 aggregate->incomplete_origin_count = 0;
6771 aggregate->egp_origin_count = 0;
6772
d62a17ae 6773 /* ORIGIN attribute: If at least one route among routes that are
6774 aggregated has ORIGIN with the value INCOMPLETE, then the
6775 aggregated route must have the ORIGIN attribute with the value
6776 INCOMPLETE. Otherwise, if at least one route among routes that
6777 are aggregated has ORIGIN with the value EGP, then the aggregated
6778 route must have the origin attribute with the value EGP. In all
6779 other case the value of the ORIGIN attribute of the aggregated
6780 route is INTERNAL. */
6781 origin = BGP_ORIGIN_IGP;
718e3744 6782
d62a17ae 6783 table = bgp->rib[afi][safi];
718e3744 6784
d62a17ae 6785 top = bgp_node_get(table, p);
9bcb3eef
DS
6786 for (dest = bgp_node_get(table, p); dest;
6787 dest = bgp_route_next_until(dest, top)) {
6788 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6789
9bcb3eef 6790 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 6791 continue;
d62a17ae 6792
c2ff8b3e 6793 match = 0;
d62a17ae 6794
9bcb3eef 6795 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 6796 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 6797 continue;
718e3744 6798
40381db7 6799 if (pi->attr->flag
c2ff8b3e
DS
6800 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
6801 atomic_aggregate = 1;
d62a17ae 6802
40381db7 6803 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 6804 continue;
d62a17ae 6805
f273fef1
DS
6806 /*
6807 * summary-only aggregate route suppress
6808 * aggregated route announcements.
6aabb15d
RZ
6809 *
6810 * MED matching:
6811 * Don't create summaries if MED didn't match
6812 * otherwise neither the specific routes and the
6813 * aggregation will be announced.
f273fef1 6814 */
6aabb15d
RZ
6815 if (aggregate->summary_only
6816 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
6817 if (aggr_suppress_path(aggregate, pi))
6818 match++;
d62a17ae 6819 }
c2ff8b3e 6820
365ab2e7
RZ
6821 /*
6822 * Suppress more specific routes that match the route
6823 * map results.
6824 *
6825 * MED matching:
6826 * Don't suppress routes if MED matching is enabled and
6827 * it mismatched otherwise we might end up with no
6828 * routes for this path.
6829 */
6830 if (aggregate->suppress_map_name
6831 && AGGREGATE_MED_VALID(aggregate)
6832 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
6833 if (aggr_suppress_path(aggregate, pi))
6834 match++;
d62a17ae 6835 }
c2ff8b3e
DS
6836
6837 aggregate->count++;
6838
f273fef1
DS
6839 /*
6840 * If at least one route among routes that are
6841 * aggregated has ORIGIN with the value INCOMPLETE,
6842 * then the aggregated route MUST have the ORIGIN
6843 * attribute with the value INCOMPLETE. Otherwise, if
6844 * at least one route among routes that are aggregated
6845 * has ORIGIN with the value EGP, then the aggregated
6846 * route MUST have the ORIGIN attribute with the value
6847 * EGP.
6848 */
fc968841
NT
6849 switch (pi->attr->origin) {
6850 case BGP_ORIGIN_INCOMPLETE:
6851 aggregate->incomplete_origin_count++;
6852 break;
6853 case BGP_ORIGIN_EGP:
6854 aggregate->egp_origin_count++;
6855 break;
6856 default:
6857 /*Do nothing.
6858 */
6859 break;
6860 }
c2ff8b3e
DS
6861
6862 if (!aggregate->as_set)
6863 continue;
6864
f273fef1
DS
6865 /*
6866 * as-set aggregate route generate origin, as path,
6867 * and community aggregation.
6868 */
fc968841
NT
6869 /* Compute aggregate route's as-path.
6870 */
ef51a7d8 6871 bgp_compute_aggregate_aspath_hash(aggregate,
6872 pi->attr->aspath);
c2ff8b3e 6873
fc968841
NT
6874 /* Compute aggregate route's community.
6875 */
6876 if (pi->attr->community)
21fec674 6877 bgp_compute_aggregate_community_hash(
fc968841
NT
6878 aggregate,
6879 pi->attr->community);
dd18c5a9 6880
fc968841
NT
6881 /* Compute aggregate route's extended community.
6882 */
6883 if (pi->attr->ecommunity)
4edd83f9 6884 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
6885 aggregate,
6886 pi->attr->ecommunity);
6887
6888 /* Compute aggregate route's large community.
6889 */
6890 if (pi->attr->lcommunity)
f1eb1f05 6891 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
6892 aggregate,
6893 pi->attr->lcommunity);
d62a17ae 6894 }
c2ff8b3e 6895 if (match)
9bcb3eef 6896 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 6897 }
21fec674 6898 if (aggregate->as_set) {
ef51a7d8 6899 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 6900 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 6901 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 6902 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 6903 }
6904
f1eb1f05 6905
9bcb3eef 6906 bgp_dest_unlock_node(top);
718e3744 6907
718e3744 6908
fc968841
NT
6909 if (aggregate->incomplete_origin_count > 0)
6910 origin = BGP_ORIGIN_INCOMPLETE;
6911 else if (aggregate->egp_origin_count > 0)
6912 origin = BGP_ORIGIN_EGP;
d62a17ae 6913
229757f1
DA
6914 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6915 origin = aggregate->origin;
6916
fc968841
NT
6917 if (aggregate->as_set) {
6918 if (aggregate->aspath)
6919 /* Retrieve aggregate route's as-path.
6920 */
6921 aspath = aspath_dup(aggregate->aspath);
d62a17ae 6922
fc968841
NT
6923 if (aggregate->community)
6924 /* Retrieve aggregate route's community.
6925 */
6926 community = community_dup(aggregate->community);
3da2cc32 6927
fc968841
NT
6928 if (aggregate->ecommunity)
6929 /* Retrieve aggregate route's ecommunity.
6930 */
6931 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 6932
fc968841
NT
6933 if (aggregate->lcommunity)
6934 /* Retrieve aggregate route's lcommunity.
6935 */
6936 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 6937 }
718e3744 6938
c701010e 6939 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
6940 ecommunity, lcommunity, atomic_aggregate,
6941 aggregate);
718e3744 6942}
6943
5f040085
DS
6944void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
6945 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
6946{
6947 struct bgp_table *table;
9bcb3eef
DS
6948 struct bgp_dest *top;
6949 struct bgp_dest *dest;
40381db7 6950 struct bgp_path_info *pi;
3b7db173
DS
6951 unsigned long match;
6952
6953 table = bgp->rib[afi][safi];
6954
6955 /* If routes exists below this node, generate aggregate routes. */
6956 top = bgp_node_get(table, p);
9bcb3eef
DS
6957 for (dest = bgp_node_get(table, p); dest;
6958 dest = bgp_route_next_until(dest, top)) {
6959 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6960
9bcb3eef 6961 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
6962 continue;
6963 match = 0;
6964
9bcb3eef 6965 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 6966 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
6967 continue;
6968
40381db7 6969 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
6970 continue;
6971
6aabb15d
RZ
6972 if (aggregate->summary_only && pi->extra
6973 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6 6974 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 6975 match++;
3b7db173 6976 }
3b7db173 6977
365ab2e7
RZ
6978 if (aggregate->suppress_map_name
6979 && AGGREGATE_MED_VALID(aggregate)
6980 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6 6981 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 6982 match++;
3b7db173 6983 }
365ab2e7 6984
3b7db173 6985 aggregate->count--;
fc968841
NT
6986
6987 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6988 aggregate->incomplete_origin_count--;
6989 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6990 aggregate->egp_origin_count--;
6991
6992 if (aggregate->as_set) {
6993 /* Remove as-path from aggregate.
6994 */
ef51a7d8 6995 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
6996 aggregate,
6997 pi->attr->aspath);
6998
6999 if (pi->attr->community)
7000 /* Remove community from aggregate.
7001 */
21fec674 7002 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
7003 aggregate,
7004 pi->attr->community);
7005
7006 if (pi->attr->ecommunity)
7007 /* Remove ecommunity from aggregate.
7008 */
4edd83f9 7009 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
7010 aggregate,
7011 pi->attr->ecommunity);
7012
7013 if (pi->attr->lcommunity)
7014 /* Remove lcommunity from aggregate.
7015 */
f1eb1f05 7016 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
7017 aggregate,
7018 pi->attr->lcommunity);
7019 }
3b7db173
DS
7020 }
7021
7022 /* If this node was suppressed, process the change. */
7023 if (match)
9bcb3eef 7024 bgp_process(bgp, dest, afi, safi);
3b7db173 7025 }
f1eb1f05 7026 if (aggregate->as_set) {
ef51a7d8 7027 aspath_free(aggregate->aspath);
7028 aggregate->aspath = NULL;
21fec674 7029 if (aggregate->community)
7030 community_free(&aggregate->community);
4edd83f9 7031 if (aggregate->ecommunity)
7032 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7033 if (aggregate->lcommunity)
7034 lcommunity_free(&aggregate->lcommunity);
7035 }
7036
9bcb3eef 7037 bgp_dest_unlock_node(top);
3b7db173 7038}
718e3744 7039
5f040085
DS
7040static void bgp_add_route_to_aggregate(struct bgp *bgp,
7041 const struct prefix *aggr_p,
fc968841
NT
7042 struct bgp_path_info *pinew, afi_t afi,
7043 safi_t safi,
7044 struct bgp_aggregate *aggregate)
7045{
7046 uint8_t origin;
7047 struct aspath *aspath = NULL;
7048 uint8_t atomic_aggregate = 0;
7049 struct community *community = NULL;
7050 struct ecommunity *ecommunity = NULL;
7051 struct lcommunity *lcommunity = NULL;
7052
7053 /* ORIGIN attribute: If at least one route among routes that are
7054 * aggregated has ORIGIN with the value INCOMPLETE, then the
7055 * aggregated route must have the ORIGIN attribute with the value
7056 * INCOMPLETE. Otherwise, if at least one route among routes that
7057 * are aggregated has ORIGIN with the value EGP, then the aggregated
7058 * route must have the origin attribute with the value EGP. In all
7059 * other case the value of the ORIGIN attribute of the aggregated
7060 * route is INTERNAL.
7061 */
7062 origin = BGP_ORIGIN_IGP;
7063
7064 aggregate->count++;
7065
6aabb15d
RZ
7066 /*
7067 * This must be called before `summary` check to avoid
7068 * "suppressing" twice.
7069 */
7070 if (aggregate->match_med)
7071 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7072 pinew, true);
7073
7074 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7075 aggr_suppress_path(aggregate, pinew);
fc968841 7076
365ab2e7
RZ
7077 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7078 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7079 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7080
7081 switch (pinew->attr->origin) {
7082 case BGP_ORIGIN_INCOMPLETE:
7083 aggregate->incomplete_origin_count++;
7084 break;
7085 case BGP_ORIGIN_EGP:
7086 aggregate->egp_origin_count++;
7087 break;
7088 default:
7089 /* Do nothing.
7090 */
7091 break;
7092 }
7093
7094 if (aggregate->incomplete_origin_count > 0)
7095 origin = BGP_ORIGIN_INCOMPLETE;
7096 else if (aggregate->egp_origin_count > 0)
7097 origin = BGP_ORIGIN_EGP;
7098
229757f1
DA
7099 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7100 origin = aggregate->origin;
7101
fc968841
NT
7102 if (aggregate->as_set) {
7103 /* Compute aggregate route's as-path.
7104 */
7105 bgp_compute_aggregate_aspath(aggregate,
7106 pinew->attr->aspath);
7107
7108 /* Compute aggregate route's community.
7109 */
7110 if (pinew->attr->community)
7111 bgp_compute_aggregate_community(
7112 aggregate,
7113 pinew->attr->community);
7114
7115 /* Compute aggregate route's extended community.
7116 */
7117 if (pinew->attr->ecommunity)
7118 bgp_compute_aggregate_ecommunity(
7119 aggregate,
7120 pinew->attr->ecommunity);
7121
7122 /* Compute aggregate route's large community.
7123 */
7124 if (pinew->attr->lcommunity)
7125 bgp_compute_aggregate_lcommunity(
7126 aggregate,
7127 pinew->attr->lcommunity);
7128
7129 /* Retrieve aggregate route's as-path.
7130 */
7131 if (aggregate->aspath)
7132 aspath = aspath_dup(aggregate->aspath);
7133
7134 /* Retrieve aggregate route's community.
7135 */
7136 if (aggregate->community)
7137 community = community_dup(aggregate->community);
7138
7139 /* Retrieve aggregate route's ecommunity.
7140 */
7141 if (aggregate->ecommunity)
7142 ecommunity = ecommunity_dup(aggregate->ecommunity);
7143
7144 /* Retrieve aggregate route's lcommunity.
7145 */
7146 if (aggregate->lcommunity)
7147 lcommunity = lcommunity_dup(aggregate->lcommunity);
7148 }
7149
7150 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7151 aspath, community, ecommunity,
7152 lcommunity, atomic_aggregate, aggregate);
7153}
7154
7155static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7156 safi_t safi,
7157 struct bgp_path_info *pi,
7158 struct bgp_aggregate *aggregate,
5f040085 7159 const struct prefix *aggr_p)
fc968841
NT
7160{
7161 uint8_t origin;
7162 struct aspath *aspath = NULL;
7163 uint8_t atomic_aggregate = 0;
7164 struct community *community = NULL;
7165 struct ecommunity *ecommunity = NULL;
7166 struct lcommunity *lcommunity = NULL;
7167 unsigned long match = 0;
7168
7169 if (BGP_PATH_HOLDDOWN(pi))
7170 return;
7171
7172 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7173 return;
7174
4056a5f6
RZ
7175 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7176 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7177 match++;
fc968841 7178
365ab2e7 7179 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7180 && aggr_suppress_map_test(bgp, aggregate, pi))
7181 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7182 match++;
fc968841 7183
6aabb15d 7184 /*
365ab2e7 7185 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7186 * "unsuppressing" twice.
7187 */
7188 if (aggregate->match_med)
7189 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7190 true);
7191
fc968841
NT
7192 if (aggregate->count > 0)
7193 aggregate->count--;
7194
7195 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7196 aggregate->incomplete_origin_count--;
7197 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7198 aggregate->egp_origin_count--;
7199
7200 if (aggregate->as_set) {
7201 /* Remove as-path from aggregate.
7202 */
7203 bgp_remove_aspath_from_aggregate(aggregate,
7204 pi->attr->aspath);
7205
7206 if (pi->attr->community)
7207 /* Remove community from aggregate.
7208 */
7209 bgp_remove_community_from_aggregate(
7210 aggregate,
7211 pi->attr->community);
7212
7213 if (pi->attr->ecommunity)
7214 /* Remove ecommunity from aggregate.
7215 */
7216 bgp_remove_ecommunity_from_aggregate(
7217 aggregate,
7218 pi->attr->ecommunity);
7219
7220 if (pi->attr->lcommunity)
7221 /* Remove lcommunity from aggregate.
7222 */
7223 bgp_remove_lcommunity_from_aggregate(
7224 aggregate,
7225 pi->attr->lcommunity);
7226 }
7227
7228 /* If this node was suppressed, process the change. */
7229 if (match)
7230 bgp_process(bgp, pi->net, afi, safi);
7231
7232 origin = BGP_ORIGIN_IGP;
7233 if (aggregate->incomplete_origin_count > 0)
7234 origin = BGP_ORIGIN_INCOMPLETE;
7235 else if (aggregate->egp_origin_count > 0)
7236 origin = BGP_ORIGIN_EGP;
7237
229757f1
DA
7238 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7239 origin = aggregate->origin;
7240
fc968841
NT
7241 if (aggregate->as_set) {
7242 /* Retrieve aggregate route's as-path.
7243 */
7244 if (aggregate->aspath)
7245 aspath = aspath_dup(aggregate->aspath);
7246
7247 /* Retrieve aggregate route's community.
7248 */
7249 if (aggregate->community)
7250 community = community_dup(aggregate->community);
7251
7252 /* Retrieve aggregate route's ecommunity.
7253 */
7254 if (aggregate->ecommunity)
7255 ecommunity = ecommunity_dup(aggregate->ecommunity);
7256
7257 /* Retrieve aggregate route's lcommunity.
7258 */
7259 if (aggregate->lcommunity)
7260 lcommunity = lcommunity_dup(aggregate->lcommunity);
7261 }
7262
7263 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7264 aspath, community, ecommunity,
7265 lcommunity, atomic_aggregate, aggregate);
7266}
7267
5a1ae2c2 7268void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7269 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7270{
9bcb3eef
DS
7271 struct bgp_dest *child;
7272 struct bgp_dest *dest;
d62a17ae 7273 struct bgp_aggregate *aggregate;
7274 struct bgp_table *table;
718e3744 7275
d62a17ae 7276 table = bgp->aggregate[afi][safi];
f018db83 7277
d62a17ae 7278 /* No aggregates configured. */
7279 if (bgp_table_top_nolock(table) == NULL)
7280 return;
f018db83 7281
d62a17ae 7282 if (p->prefixlen == 0)
7283 return;
718e3744 7284
40381db7 7285 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7286 return;
718e3744 7287
d62a17ae 7288 child = bgp_node_get(table, p);
718e3744 7289
d62a17ae 7290 /* Aggregate address configuration check. */
9bcb3eef
DS
7291 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7292 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7293
9bcb3eef
DS
7294 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7295 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7296 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7297 aggregate);
d62a17ae 7298 }
b1e62edd 7299 }
9bcb3eef 7300 bgp_dest_unlock_node(child);
718e3744 7301}
7302
5a1ae2c2 7303void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7304 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7305{
9bcb3eef
DS
7306 struct bgp_dest *child;
7307 struct bgp_dest *dest;
d62a17ae 7308 struct bgp_aggregate *aggregate;
7309 struct bgp_table *table;
718e3744 7310
d62a17ae 7311 table = bgp->aggregate[afi][safi];
718e3744 7312
d62a17ae 7313 /* No aggregates configured. */
7314 if (bgp_table_top_nolock(table) == NULL)
7315 return;
718e3744 7316
d62a17ae 7317 if (p->prefixlen == 0)
7318 return;
718e3744 7319
d62a17ae 7320 child = bgp_node_get(table, p);
718e3744 7321
d62a17ae 7322 /* Aggregate address configuration check. */
9bcb3eef
DS
7323 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7324 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7325
9bcb3eef
DS
7326 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7327 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 7328 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 7329 aggregate, dest_p);
d62a17ae 7330 }
b1e62edd 7331 }
9bcb3eef 7332 bgp_dest_unlock_node(child);
d62a17ae 7333}
718e3744 7334
718e3744 7335/* Aggregate route attribute. */
7336#define AGGREGATE_SUMMARY_ONLY 1
7337#define AGGREGATE_AS_SET 1
fb29348a 7338#define AGGREGATE_AS_UNSET 0
718e3744 7339
229757f1
DA
7340static const char *bgp_origin2str(uint8_t origin)
7341{
7342 switch (origin) {
7343 case BGP_ORIGIN_IGP:
7344 return "igp";
7345 case BGP_ORIGIN_EGP:
7346 return "egp";
7347 case BGP_ORIGIN_INCOMPLETE:
7348 return "incomplete";
7349 }
7350 return "n/a";
7351}
7352
37a87b8f
CS
7353int bgp_aggregate_unset(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7354 safi_t safi, char *errmsg, size_t errmsg_len)
718e3744 7355{
9bcb3eef 7356 struct bgp_dest *dest;
d62a17ae 7357 struct bgp_aggregate *aggregate;
718e3744 7358
37a87b8f 7359 apply_mask(prefix);
d62a17ae 7360 /* Old configuration check. */
37a87b8f 7361 dest = bgp_node_lookup(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7362 if (!dest) {
37a87b8f
CS
7363 snprintf(errmsg, errmsg_len,
7364 "There is no aggregate-address configuration.\n");
7365 return -1;
d62a17ae 7366 }
f6269b4f 7367
9bcb3eef 7368 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
37a87b8f
CS
7369 bgp_aggregate_delete(bgp, prefix, afi, safi, aggregate);
7370 bgp_aggregate_install(bgp, afi, safi, prefix, 0, NULL, NULL, NULL, NULL,
7371 0, aggregate);
d62a17ae 7372
7373 /* Unlock aggregate address configuration. */
9bcb3eef 7374 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
7375
7376 if (aggregate->community)
7377 community_free(&aggregate->community);
7378
7379 if (aggregate->community_hash) {
7380 /* Delete all communities in the hash.
7381 */
7382 hash_clean(aggregate->community_hash,
7383 bgp_aggr_community_remove);
7384 /* Free up the community_hash.
7385 */
7386 hash_free(aggregate->community_hash);
7387 }
7388
7389 if (aggregate->ecommunity)
7390 ecommunity_free(&aggregate->ecommunity);
7391
7392 if (aggregate->ecommunity_hash) {
7393 /* Delete all ecommunities in the hash.
7394 */
7395 hash_clean(aggregate->ecommunity_hash,
7396 bgp_aggr_ecommunity_remove);
7397 /* Free up the ecommunity_hash.
7398 */
7399 hash_free(aggregate->ecommunity_hash);
7400 }
7401
7402 if (aggregate->lcommunity)
7403 lcommunity_free(&aggregate->lcommunity);
7404
7405 if (aggregate->lcommunity_hash) {
7406 /* Delete all lcommunities in the hash.
7407 */
7408 hash_clean(aggregate->lcommunity_hash,
7409 bgp_aggr_lcommunity_remove);
7410 /* Free up the lcommunity_hash.
7411 */
7412 hash_free(aggregate->lcommunity_hash);
7413 }
7414
7415 if (aggregate->aspath)
7416 aspath_free(aggregate->aspath);
7417
7418 if (aggregate->aspath_hash) {
7419 /* Delete all as-paths in the hash.
7420 */
7421 hash_clean(aggregate->aspath_hash,
7422 bgp_aggr_aspath_remove);
7423 /* Free up the aspath_hash.
7424 */
7425 hash_free(aggregate->aspath_hash);
7426 }
7427
d62a17ae 7428 bgp_aggregate_free(aggregate);
9bcb3eef
DS
7429 bgp_dest_unlock_node(dest);
7430 bgp_dest_unlock_node(dest);
d62a17ae 7431
37a87b8f 7432 return 0;
d62a17ae 7433}
7434
37a87b8f
CS
7435int bgp_aggregate_set(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7436 safi_t safi, const char *rmap, uint8_t summary_only,
7437 uint8_t as_set, uint8_t origin, bool match_med,
7438 const char *suppress_map,
7439 char *errmsg, size_t errmsg_len)
d62a17ae 7440{
d62a17ae 7441 int ret;
9bcb3eef 7442 struct bgp_dest *dest;
d62a17ae 7443 struct bgp_aggregate *aggregate;
fb29348a 7444 uint8_t as_set_new = as_set;
37a87b8f 7445 char buf[PREFIX2STR_BUFFER];
d62a17ae 7446
365ab2e7 7447 if (suppress_map && summary_only) {
37a87b8f 7448 snprintf(errmsg, errmsg_len,
365ab2e7 7449 "'summary-only' and 'suppress-map' can't be used at the same time\n");
37a87b8f 7450 return -1;
365ab2e7
RZ
7451 }
7452
37a87b8f 7453 apply_mask(prefix);
d62a17ae 7454
37a87b8f
CS
7455 if ((afi == AFI_IP && prefix->prefixlen == IPV4_MAX_BITLEN)
7456 || (afi == AFI_IP6 && prefix->prefixlen == IPV6_MAX_BITLEN)) {
7457 snprintf(
7458 errmsg, errmsg_len,
7459 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7460 prefix2str(prefix, buf, PREFIX_STRLEN));
7461 return -1;
3624ac81
DS
7462 }
7463
d62a17ae 7464 /* Old configuration check. */
37a87b8f 7465 dest = bgp_node_get(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7466 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 7467
20894f50 7468 if (aggregate) {
37a87b8f
CS
7469 snprintf(errmsg, errmsg_len,
7470 "There is already same aggregate network.\n");
d62a17ae 7471 /* try to remove the old entry */
37a87b8f
CS
7472 ret = bgp_aggregate_unset(bgp, prefix, afi, safi, errmsg,
7473 errmsg_len);
d62a17ae 7474 if (ret) {
37a87b8f
CS
7475 snprintf(errmsg, errmsg_len,
7476 "Error deleting aggregate.\n");
9bcb3eef 7477 bgp_dest_unlock_node(dest);
37a87b8f 7478 return -1;
d62a17ae 7479 }
7480 }
718e3744 7481
d62a17ae 7482 /* Make aggregate address structure. */
7483 aggregate = bgp_aggregate_new();
7484 aggregate->summary_only = summary_only;
6aabb15d 7485 aggregate->match_med = match_med;
fb29348a
DA
7486
7487 /* Network operators MUST NOT locally generate any new
7488 * announcements containing AS_SET or AS_CONFED_SET. If they have
7489 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7490 * SHOULD withdraw those routes and re-announce routes for the
7491 * aggregate or component prefixes (i.e., the more-specific routes
7492 * subsumed by the previously aggregated route) without AS_SET
7493 * or AS_CONFED_SET in the updates.
7494 */
7f972cd8 7495 if (bgp->reject_as_sets) {
fb29348a
DA
7496 if (as_set == AGGREGATE_AS_SET) {
7497 as_set_new = AGGREGATE_AS_UNSET;
7498 zlog_warn(
63efca0e 7499 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 7500 __func__);
37a87b8f
CS
7501 snprintf(
7502 errmsg, errmsg_len,
fb29348a
DA
7503 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7504 }
7505 }
7506
7507 aggregate->as_set = as_set_new;
d62a17ae 7508 aggregate->safi = safi;
229757f1
DA
7509 /* Override ORIGIN attribute if defined.
7510 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7511 * to IGP which is not what rfc4271 says.
7512 * This enables the same behavior, optionally.
7513 */
7514 aggregate->origin = origin;
20894f50
DA
7515
7516 if (rmap) {
7517 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7518 route_map_counter_decrement(aggregate->rmap.map);
7519 aggregate->rmap.name =
7520 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
7521 aggregate->rmap.map = route_map_lookup_by_name(rmap);
7522 route_map_counter_increment(aggregate->rmap.map);
7523 }
365ab2e7
RZ
7524
7525 if (suppress_map) {
7526 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7527 route_map_counter_decrement(aggregate->suppress_map);
7528
7529 aggregate->suppress_map_name =
7530 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
7531 aggregate->suppress_map =
7532 route_map_lookup_by_name(aggregate->suppress_map_name);
7533 route_map_counter_increment(aggregate->suppress_map);
7534 }
7535
9bcb3eef 7536 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 7537
d62a17ae 7538 /* Aggregate address insert into BGP routing table. */
37a87b8f 7539 bgp_aggregate_route(bgp, prefix, afi, safi, aggregate);
718e3744 7540
37a87b8f 7541 return 0;
718e3744 7542}
7543
37a87b8f
CS
7544DEFPY_YANG(
7545 aggregate_addressv4, aggregate_addressv4_cmd,
7546 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
7547 "as-set$as_set_s"
7548 "|summary-only$summary_only"
7549 "|route-map WORD$rmap_name"
7550 "|origin <egp|igp|incomplete>$origin_s"
7551 "|matching-MED-only$match_med"
90e21f35 7552 "|suppress-map WORD$suppress_map"
37a87b8f
CS
7553 "}",
7554 NO_STR
7555 "Configure BGP aggregate entries\n"
7556 "Aggregate prefix\n"
7557 "Aggregate address\n"
7558 "Aggregate mask\n"
7559 "Generate AS set path information\n"
7560 "Filter more specific routes from updates\n"
7561 "Apply route map to aggregate network\n"
7562 "Route map name\n"
7563 "BGP origin code\n"
7564 "Remote EGP\n"
7565 "Local IGP\n"
7566 "Unknown heritage\n"
7567 "Only aggregate routes with matching MED\n"
90e21f35
CS
7568 "Suppress the selected more specific routes\n"
7569 "Route map with the route selectors\n")
37a87b8f
CS
7570{
7571 char base_xpath[XPATH_MAXLEN];
554b3b10 7572 safi_t safi = bgp_node_safi(vty);
554b3b10 7573 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 7574
554b3b10
RZ
7575 if (addr_str) {
7576 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf)
7577 == 0) {
7578 vty_out(vty, "%% Inconsistent address and mask\n");
7579 return CMD_WARNING_CONFIG_FAILED;
7580 }
37a87b8f
CS
7581 } else {
7582 strlcpy(prefix_buf, prefix_str, sizeof(prefix_buf));
229757f1
DA
7583 }
7584
37a87b8f
CS
7585 if (!no && origin_s)
7586 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7587
7588 if (!no && as_set_s)
7589 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7590 else
7591 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7592
7593 if (!no && summary_only)
7594 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7595 "true");
7596 else
7597 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7598 "false");
7599
fa423774
CS
7600 if (!no && match_med)
7601 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7602 else
7603 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7604 "false");
7605
37a87b8f
CS
7606 if (rmap_name)
7607 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7608 rmap_name);
7609 else
7610 nb_cli_enqueue_change(vty, "./rmap-policy-export",
7611 NB_OP_DESTROY, NULL);
7612
90e21f35
CS
7613 if (suppress_map)
7614 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7615 suppress_map);
7616 else
7617 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7618 NULL);
7619
37a87b8f
CS
7620 snprintf(
7621 base_xpath, sizeof(base_xpath),
7622 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7623 yang_afi_safi_value2identity(AFI_IP, safi),
7624 bgp_afi_safi_get_container_str(AFI_IP, safi), prefix_buf);
554b3b10 7625
554b3b10 7626 if (no)
37a87b8f
CS
7627 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7628 else
7629 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
7630
7631 return nb_cli_apply_changes(vty, base_xpath);
7632}
7633
7634DEFPY_YANG(aggregate_addressv6, aggregate_addressv6_cmd,
7635 "[no] aggregate-address X:X::X:X/M$prefix {"
7636 "as-set$as_set_s"
7637 "|summary-only$summary_only"
7638 "|route-map WORD$rmap_name"
7639 "|origin <egp|igp|incomplete>$origin_s"
7640 "|matching-MED-only$match_med"
90e21f35 7641 "|suppress-map WORD$suppress_map"
37a87b8f
CS
7642 "}",
7643 NO_STR
7644 "Configure BGP aggregate entries\n"
7645 "Aggregate prefix\n"
7646 "Generate AS set path information\n"
7647 "Filter more specific routes from updates\n"
7648 "Apply route map to aggregate network\n"
7649 "Route map name\n"
7650 "BGP origin code\n"
7651 "Remote EGP\n"
7652 "Local IGP\n"
7653 "Unknown heritage\n"
7654 "Only aggregate routes with matching MED\n"
7655 "Suppress the selected more specific routes\n"
90e21f35 7656 "Route map with the route selectors\n")
37a87b8f
CS
7657{
7658 char base_xpath[XPATH_MAXLEN];
7659 safi_t safi = bgp_node_safi(vty);
7660
7661 if (!no && origin_s)
7662 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7663
7664 if (!no && as_set_s)
7665 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7666 else
7667 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7668
7669 if (!no && summary_only)
7670 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7671 "true");
7672 else
7673 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7674 "false");
7675
fa423774
CS
7676 if (!no && match_med)
7677 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7678 else
7679 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7680 "false");
7681
37a87b8f
CS
7682 if (rmap_name)
7683 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7684 rmap_name);
7685
90e21f35
CS
7686 if (suppress_map)
7687 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7688 suppress_map);
7689 else
7690 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7691 NULL);
7692
37a87b8f
CS
7693 snprintf(
7694 base_xpath, sizeof(base_xpath),
7695 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7696 yang_afi_safi_value2identity(AFI_IP6, safi),
7697 bgp_afi_safi_get_container_str(AFI_IP6, safi), prefix_str);
7698
554b3b10 7699 if (no)
37a87b8f
CS
7700 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7701 else
7702 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
554b3b10 7703
37a87b8f
CS
7704 return nb_cli_apply_changes(vty, base_xpath);
7705}
7706
7707void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
7708 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
7709{
7710 uint8_t origin;
7711
7712 vty_out(vty, " aggregate-address %s",
7713 yang_dnode_get_string(dnode, "./prefix"));
7714
7715 if (yang_dnode_get_bool(dnode, "./as-set"))
7716 vty_out(vty, " as-set");
7717
7718 if (yang_dnode_get_bool(dnode, "./summary-only"))
7719 vty_out(vty, " summary-only");
7720
7721 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
7722 vty_out(vty, " route-map %s",
7723 yang_dnode_get_string(dnode, "./rmap-policy-export"));
7724
7725 origin = yang_dnode_get_enum(dnode, "./origin");
7726 if (origin != BGP_ORIGIN_UNSPECIFIED)
7727 vty_out(vty, " origin %s", bgp_origin2str(origin));
7728
fa423774
CS
7729 if (yang_dnode_get_bool(dnode, "./match-med"))
7730 vty_out(vty, " matching-MED-only");
7731
37a87b8f 7732 vty_out(vty, "\n");
718e3744 7733}
7734
718e3744 7735/* Redistribute route treatment. */
d62a17ae 7736void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
7737 const union g_addr *nexthop, ifindex_t ifindex,
7738 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
7739 uint8_t type, unsigned short instance,
7740 route_tag_t tag)
d62a17ae 7741{
4b7e6066 7742 struct bgp_path_info *new;
40381db7
DS
7743 struct bgp_path_info *bpi;
7744 struct bgp_path_info rmap_path;
9bcb3eef 7745 struct bgp_dest *bn;
d62a17ae 7746 struct attr attr;
7747 struct attr *new_attr;
7748 afi_t afi;
b68885f9 7749 route_map_result_t ret;
d62a17ae 7750 struct bgp_redist *red;
7751
7752 /* Make default attribute. */
7753 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
7754 /*
7755 * This must not be NULL to satisfy Coverity SA
7756 */
7757 assert(attr.aspath);
9de1f7ff 7758
a4d82a8a 7759 switch (nhtype) {
9de1f7ff
DS
7760 case NEXTHOP_TYPE_IFINDEX:
7761 break;
7762 case NEXTHOP_TYPE_IPV4:
7763 case NEXTHOP_TYPE_IPV4_IFINDEX:
7764 attr.nexthop = nexthop->ipv4;
7765 break;
7766 case NEXTHOP_TYPE_IPV6:
7767 case NEXTHOP_TYPE_IPV6_IFINDEX:
7768 attr.mp_nexthop_global = nexthop->ipv6;
7769 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
7770 break;
7771 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
7772 switch (p->family) {
7773 case AF_INET:
9de1f7ff 7774 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
7775 break;
7776 case AF_INET6:
9de1f7ff
DS
7777 memset(&attr.mp_nexthop_global, 0,
7778 sizeof(attr.mp_nexthop_global));
74489921 7779 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 7780 break;
74489921 7781 }
9de1f7ff 7782 break;
d62a17ae 7783 }
74489921 7784 attr.nh_ifindex = ifindex;
f04a80a5 7785
d62a17ae 7786 attr.med = metric;
7787 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
7788 attr.tag = tag;
718e3744 7789
d62a17ae 7790 afi = family2afi(p->family);
6aeb9e78 7791
d62a17ae 7792 red = bgp_redist_lookup(bgp, afi, type, instance);
7793 if (red) {
7794 struct attr attr_new;
718e3744 7795
d62a17ae 7796 /* Copy attribute for modification. */
6f4f49b2 7797 attr_new = attr;
718e3744 7798
d62a17ae 7799 if (red->redist_metric_flag)
7800 attr_new.med = red->redist_metric;
718e3744 7801
d62a17ae 7802 /* Apply route-map. */
7803 if (red->rmap.name) {
40381db7
DS
7804 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
7805 rmap_path.peer = bgp->peer_self;
7806 rmap_path.attr = &attr_new;
718e3744 7807
d62a17ae 7808 SET_FLAG(bgp->peer_self->rmap_type,
7809 PEER_RMAP_TYPE_REDISTRIBUTE);
7810
7811 ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
40381db7 7812 &rmap_path);
d62a17ae 7813
7814 bgp->peer_self->rmap_type = 0;
7815
7816 if (ret == RMAP_DENYMATCH) {
7817 /* Free uninterned attribute. */
7818 bgp_attr_flush(&attr_new);
7819
7820 /* Unintern original. */
7821 aspath_unintern(&attr.aspath);
7822 bgp_redistribute_delete(bgp, p, type, instance);
7823 return;
7824 }
7825 }
7826
637e5ba4 7827 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
7828 bgp_attr_add_gshut_community(&attr_new);
7829
d62a17ae 7830 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7831 SAFI_UNICAST, p, NULL);
7832
7833 new_attr = bgp_attr_intern(&attr_new);
7834
9bcb3eef 7835 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
7836 if (bpi->peer == bgp->peer_self
7837 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 7838 break;
7839
40381db7 7840 if (bpi) {
d62a17ae 7841 /* Ensure the (source route) type is updated. */
40381db7
DS
7842 bpi->type = type;
7843 if (attrhash_cmp(bpi->attr, new_attr)
7844 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 7845 bgp_attr_unintern(&new_attr);
7846 aspath_unintern(&attr.aspath);
9bcb3eef 7847 bgp_dest_unlock_node(bn);
d62a17ae 7848 return;
7849 } else {
7850 /* The attribute is changed. */
40381db7 7851 bgp_path_info_set_flag(bn, bpi,
18ee8310 7852 BGP_PATH_ATTR_CHANGED);
d62a17ae 7853
7854 /* Rewrite BGP route information. */
40381db7
DS
7855 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
7856 bgp_path_info_restore(bn, bpi);
d62a17ae 7857 else
40381db7
DS
7858 bgp_aggregate_decrement(
7859 bgp, p, bpi, afi, SAFI_UNICAST);
7860 bgp_attr_unintern(&bpi->attr);
7861 bpi->attr = new_attr;
7862 bpi->uptime = bgp_clock();
d62a17ae 7863
7864 /* Process change. */
40381db7 7865 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 7866 SAFI_UNICAST);
7867 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 7868 bgp_dest_unlock_node(bn);
d62a17ae 7869 aspath_unintern(&attr.aspath);
ddb5b488
PZ
7870
7871 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7872 || (bgp->inst_type
7873 == BGP_INSTANCE_TYPE_DEFAULT)) {
7874
7875 vpn_leak_from_vrf_update(
40381db7 7876 bgp_get_default(), bgp, bpi);
ddb5b488 7877 }
d62a17ae 7878 return;
7879 }
7880 }
7881
7882 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
7883 bgp->peer_self, new_attr, bn);
1defdda8 7884 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 7885
7886 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 7887 bgp_path_info_add(bn, new);
9bcb3eef 7888 bgp_dest_unlock_node(bn);
d62a17ae 7889 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
7890
7891 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7892 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7893
7894 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
7895 }
d62a17ae 7896 }
7897
7898 /* Unintern original. */
7899 aspath_unintern(&attr.aspath);
718e3744 7900}
7901
d7c0a89a
QY
7902void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
7903 unsigned short instance)
718e3744 7904{
d62a17ae 7905 afi_t afi;
9bcb3eef 7906 struct bgp_dest *dest;
40381db7 7907 struct bgp_path_info *pi;
d62a17ae 7908 struct bgp_redist *red;
718e3744 7909
d62a17ae 7910 afi = family2afi(p->family);
718e3744 7911
d62a17ae 7912 red = bgp_redist_lookup(bgp, afi, type, instance);
7913 if (red) {
9bcb3eef
DS
7914 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7915 SAFI_UNICAST, p, NULL);
d62a17ae 7916
9bcb3eef 7917 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 7918 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 7919 break;
7920
40381db7 7921 if (pi) {
ddb5b488
PZ
7922 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7923 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7924
7925 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7926 bgp, pi);
ddb5b488 7927 }
40381db7 7928 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
7929 bgp_path_info_delete(dest, pi);
7930 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 7931 }
9bcb3eef 7932 bgp_dest_unlock_node(dest);
d62a17ae 7933 }
7934}
7935
7936/* Withdraw specified route type's route. */
7937void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 7938 unsigned short instance)
d62a17ae 7939{
9bcb3eef 7940 struct bgp_dest *dest;
40381db7 7941 struct bgp_path_info *pi;
d62a17ae 7942 struct bgp_table *table;
7943
7944 table = bgp->rib[afi][SAFI_UNICAST];
7945
9bcb3eef
DS
7946 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
7947 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7948 if (pi->peer == bgp->peer_self && pi->type == type
7949 && pi->instance == instance)
d62a17ae 7950 break;
7951
40381db7 7952 if (pi) {
ddb5b488
PZ
7953 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7954 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7955
7956 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7957 bgp, pi);
ddb5b488 7958 }
9bcb3eef 7959 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 7960 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
7961 bgp_path_info_delete(dest, pi);
7962 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 7963 }
718e3744 7964 }
718e3744 7965}
6b0655a2 7966
718e3744 7967/* Static function to display route. */
bd494ec5 7968static void route_vty_out_route(const struct prefix *p, struct vty *vty,
ae248832 7969 json_object *json, bool wide)
718e3744 7970{
be054588 7971 int len = 0;
d62a17ae 7972 char buf[BUFSIZ];
50e05855 7973 char buf2[BUFSIZ];
718e3744 7974
d62a17ae 7975 if (p->family == AF_INET) {
c6462ff4 7976 if (!json) {
8228a9a7 7977 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
7978 } else {
7979 json_object_string_add(json, "prefix",
7980 inet_ntop(p->family,
7981 &p->u.prefix, buf,
7982 BUFSIZ));
7983 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 7984 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 7985 json_object_string_add(json, "network", buf2);
c6462ff4 7986 }
d62a17ae 7987 } else if (p->family == AF_ETHERNET) {
8228a9a7 7988 len = vty_out(vty, "%pFX", p);
b03b8898 7989 } else if (p->family == AF_EVPN) {
57f7feb6 7990 if (!json)
2dbe669b 7991 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 7992 else
60466a63 7993 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
7994 } else if (p->family == AF_FLOWSPEC) {
7995 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
7996 json ?
7997 NLRI_STRING_FORMAT_JSON_SIMPLE :
7998 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 7999 } else {
c6462ff4 8000 if (!json)
8228a9a7 8001 len = vty_out(vty, "%pFX", p);
50e05855
AD
8002 else {
8003 json_object_string_add(json, "prefix",
8004 inet_ntop(p->family,
8005 &p->u.prefix, buf,
8006 BUFSIZ));
8007 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
8008 prefix2str(p, buf2, PREFIX_STRLEN);
8009 json_object_string_add(json, "network", buf2);
8010 }
9c92b5f7 8011 }
d62a17ae 8012
9c92b5f7 8013 if (!json) {
ae248832 8014 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8015 if (len < 1)
8016 vty_out(vty, "\n%*s", 20, " ");
8017 else
8018 vty_out(vty, "%*s", len, " ");
8019 }
718e3744 8020}
8021
d62a17ae 8022enum bgp_display_type {
8023 normal_list,
718e3744 8024};
8025
18ee8310 8026/* Print the short form route status for a bgp_path_info */
4b7e6066 8027static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8028 struct bgp_path_info *path,
d62a17ae 8029 json_object *json_path)
718e3744 8030{
d62a17ae 8031 if (json_path) {
b05a1c8b 8032
d62a17ae 8033 /* Route status display. */
9b6d8fcf 8034 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8035 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8036
9b6d8fcf 8037 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8038 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8039
4056a5f6 8040 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8041 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8042
9b6d8fcf
DS
8043 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8044 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8045 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8046
d62a17ae 8047 /* Selected */
9b6d8fcf 8048 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8049 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8050
9b6d8fcf 8051 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8052 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8053
9b6d8fcf 8054 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8055 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b 8056
9b6d8fcf 8057 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8058 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8059
d62a17ae 8060 /* Internal route. */
9b6d8fcf
DS
8061 if ((path->peer->as)
8062 && (path->peer->as == path->peer->local_as))
d62a17ae 8063 json_object_string_add(json_path, "pathFrom",
8064 "internal");
8065 else
8066 json_object_string_add(json_path, "pathFrom",
8067 "external");
b05a1c8b 8068
d62a17ae 8069 return;
8070 }
b05a1c8b 8071
d62a17ae 8072 /* Route status display. */
9b6d8fcf 8073 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8074 vty_out(vty, "R");
9b6d8fcf 8075 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8076 vty_out(vty, "S");
4056a5f6 8077 else if (bgp_path_suppressed(path))
d62a17ae 8078 vty_out(vty, "s");
9b6d8fcf
DS
8079 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8080 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8081 vty_out(vty, "*");
8082 else
8083 vty_out(vty, " ");
8084
8085 /* Selected */
9b6d8fcf 8086 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8087 vty_out(vty, "h");
9b6d8fcf 8088 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8089 vty_out(vty, "d");
9b6d8fcf 8090 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8091 vty_out(vty, ">");
9b6d8fcf 8092 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8093 vty_out(vty, "=");
8094 else
8095 vty_out(vty, " ");
718e3744 8096
d62a17ae 8097 /* Internal route. */
9b6d8fcf
DS
8098 if (path->peer && (path->peer->as)
8099 && (path->peer->as == path->peer->local_as))
d62a17ae 8100 vty_out(vty, "i");
8101 else
8102 vty_out(vty, " ");
b40d939b 8103}
8104
2ba93fd6
DA
8105static char *bgp_nexthop_hostname(struct peer *peer,
8106 struct bgp_nexthop_cache *bnc)
25b5da8d 8107{
892fedb6 8108 if (peer->hostname
aef999a2 8109 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8110 return peer->hostname;
8111 return NULL;
8112}
8113
b40d939b 8114/* called from terminal list command */
bd494ec5 8115void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8116 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8117 json_object *json_paths, bool wide)
d62a17ae 8118{
aef999a2 8119 int len;
515c2602 8120 struct attr *attr = path->attr;
d62a17ae 8121 json_object *json_path = NULL;
8122 json_object *json_nexthops = NULL;
8123 json_object *json_nexthop_global = NULL;
8124 json_object *json_nexthop_ll = NULL;
6f214dd3 8125 json_object *json_ext_community = NULL;
9df8b37c 8126 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8127 bool nexthop_self =
9b6d8fcf 8128 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8129 bool nexthop_othervrf = false;
43089216 8130 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8131 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8132 char *nexthop_hostname =
8133 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8134 char esi_buf[ESI_STR_LEN];
d62a17ae 8135
8136 if (json_paths)
8137 json_path = json_object_new_object();
8138
8139 /* short status lead text */
9b6d8fcf 8140 route_vty_short_status_out(vty, path, json_path);
d62a17ae 8141
8142 if (!json_paths) {
8143 /* print prefix and mask */
8144 if (!display)
ae248832 8145 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 8146 else
ae248832 8147 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8148 } else {
ae248832 8149 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 8150 }
47fc97cc 8151
9df8b37c
PZ
8152 /*
8153 * If vrf id of nexthop is different from that of prefix,
8154 * set up printable string to append
8155 */
9b6d8fcf 8156 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8157 const char *self = "";
8158
8159 if (nexthop_self)
8160 self = "<";
8161
8162 nexthop_othervrf = true;
9b6d8fcf 8163 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8164
9b6d8fcf 8165 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8166 snprintf(vrf_id_str, sizeof(vrf_id_str),
8167 "@%s%s", VRFID_NONE_STR, self);
8168 else
8169 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8170 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8171
9b6d8fcf
DS
8172 if (path->extra->bgp_orig->inst_type
8173 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8174
9b6d8fcf 8175 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8176 } else {
8177 const char *self = "";
8178
8179 if (nexthop_self)
8180 self = "<";
8181
8182 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8183 }
8184
445c2480
DS
8185 /*
8186 * For ENCAP and EVPN routes, nexthop address family is not
8187 * neccessarily the same as the prefix address family.
8188 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8189 * EVPN routes are also exchanged with a MP nexthop. Currently,
8190 * this
8191 * is only IPv4, the value will be present in either
8192 * attr->nexthop or
8193 * attr->mp_nexthop_global_in
8194 */
8195 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8196 char buf[BUFSIZ];
8197 char nexthop[128];
8198 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8199
8200 switch (af) {
8201 case AF_INET:
772270f3
QY
8202 snprintf(nexthop, sizeof(nexthop), "%s",
8203 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8204 BUFSIZ));
445c2480
DS
8205 break;
8206 case AF_INET6:
772270f3
QY
8207 snprintf(nexthop, sizeof(nexthop), "%s",
8208 inet_ntop(af, &attr->mp_nexthop_global, buf,
8209 BUFSIZ));
445c2480
DS
8210 break;
8211 default:
772270f3 8212 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8213 break;
d62a17ae 8214 }
d62a17ae 8215
445c2480
DS
8216 if (json_paths) {
8217 json_nexthop_global = json_object_new_object();
8218
515c2602
DA
8219 json_object_string_add(json_nexthop_global, "ip",
8220 nexthop);
8221
939a97f4 8222 if (path->peer->hostname)
515c2602
DA
8223 json_object_string_add(json_nexthop_global,
8224 "hostname",
939a97f4 8225 path->peer->hostname);
515c2602
DA
8226
8227 json_object_string_add(json_nexthop_global, "afi",
8228 (af == AF_INET) ? "ipv4"
8229 : "ipv6");
445c2480
DS
8230 json_object_boolean_true_add(json_nexthop_global,
8231 "used");
aef999a2
DA
8232 } else {
8233 if (nexthop_hostname)
8234 len = vty_out(vty, "%s(%s)%s", nexthop,
8235 nexthop_hostname, vrf_id_str);
8236 else
8237 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8238
ae248832 8239 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8240 if (len < 1)
8241 vty_out(vty, "\n%*s", 36, " ");
8242 else
8243 vty_out(vty, "%*s", len, " ");
8244 }
445c2480
DS
8245 } else if (safi == SAFI_EVPN) {
8246 if (json_paths) {
23d0a753
DA
8247 char buf[BUFSIZ] = {0};
8248
445c2480
DS
8249 json_nexthop_global = json_object_new_object();
8250
515c2602 8251 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8252 inet_ntop(AF_INET,
8253 &attr->nexthop, buf,
8254 sizeof(buf)));
515c2602 8255
939a97f4 8256 if (path->peer->hostname)
515c2602
DA
8257 json_object_string_add(json_nexthop_global,
8258 "hostname",
939a97f4 8259 path->peer->hostname);
515c2602 8260
a4d82a8a
PZ
8261 json_object_string_add(json_nexthop_global, "afi",
8262 "ipv4");
445c2480
DS
8263 json_object_boolean_true_add(json_nexthop_global,
8264 "used");
aef999a2
DA
8265 } else {
8266 if (nexthop_hostname)
8267 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8268 nexthop_hostname, vrf_id_str);
8269 else
8270 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8271 vrf_id_str);
8272
ae248832 8273 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8274 if (len < 1)
8275 vty_out(vty, "\n%*s", 36, " ");
8276 else
8277 vty_out(vty, "%*s", len, " ");
8278 }
d33fc23b 8279 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8280 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a 8281 if (json_paths) {
23d0a753
DA
8282 char buf[BUFSIZ] = {0};
8283
026b914a 8284 json_nexthop_global = json_object_new_object();
515c2602 8285
026b914a
PG
8286 json_object_string_add(json_nexthop_global,
8287 "afi", "ipv4");
515c2602
DA
8288 json_object_string_add(
8289 json_nexthop_global, "ip",
23d0a753
DA
8290 inet_ntop(AF_INET, &attr->nexthop, buf,
8291 sizeof(buf)));
515c2602 8292
939a97f4 8293 if (path->peer->hostname)
515c2602
DA
8294 json_object_string_add(
8295 json_nexthop_global, "hostname",
939a97f4 8296 path->peer->hostname);
515c2602 8297
50e05855
AD
8298 json_object_boolean_true_add(
8299 json_nexthop_global,
026b914a
PG
8300 "used");
8301 } else {
aef999a2
DA
8302 if (nexthop_hostname)
8303 len = vty_out(vty, "%pI4(%s)%s",
8304 &attr->nexthop,
8305 nexthop_hostname,
8306 vrf_id_str);
8307 else
8308 len = vty_out(vty, "%pI4%s",
8309 &attr->nexthop,
8310 vrf_id_str);
8311
ae248832 8312 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8313 if (len < 1)
8314 vty_out(vty, "\n%*s", 36, " ");
8315 else
8316 vty_out(vty, "%*s", len, " ");
026b914a
PG
8317 }
8318 }
d33fc23b 8319 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8320 if (json_paths) {
23d0a753
DA
8321 char buf[BUFSIZ] = {0};
8322
445c2480 8323 json_nexthop_global = json_object_new_object();
d62a17ae 8324
515c2602 8325 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8326 inet_ntop(AF_INET,
8327 &attr->nexthop, buf,
8328 sizeof(buf)));
515c2602 8329
939a97f4 8330 if (path->peer->hostname)
515c2602
DA
8331 json_object_string_add(json_nexthop_global,
8332 "hostname",
939a97f4 8333 path->peer->hostname);
445c2480 8334
a4d82a8a
PZ
8335 json_object_string_add(json_nexthop_global, "afi",
8336 "ipv4");
445c2480
DS
8337 json_object_boolean_true_add(json_nexthop_global,
8338 "used");
8339 } else {
aef999a2
DA
8340 if (nexthop_hostname)
8341 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8342 nexthop_hostname, vrf_id_str);
8343 else
8344 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8345 vrf_id_str);
9df8b37c 8346
ae248832 8347 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8348 if (len < 1)
8349 vty_out(vty, "\n%*s", 36, " ");
8350 else
8351 vty_out(vty, "%*s", len, " ");
d62a17ae 8352 }
445c2480 8353 }
b05a1c8b 8354
445c2480 8355 /* IPv6 Next Hop */
a4d82a8a 8356 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8357 char buf[BUFSIZ];
d62a17ae 8358
445c2480
DS
8359 if (json_paths) {
8360 json_nexthop_global = json_object_new_object();
a4d82a8a 8361 json_object_string_add(
515c2602
DA
8362 json_nexthop_global, "ip",
8363 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8364 buf, BUFSIZ));
8365
939a97f4 8366 if (path->peer->hostname)
515c2602
DA
8367 json_object_string_add(json_nexthop_global,
8368 "hostname",
939a97f4 8369 path->peer->hostname);
515c2602 8370
a4d82a8a
PZ
8371 json_object_string_add(json_nexthop_global, "afi",
8372 "ipv6");
8373 json_object_string_add(json_nexthop_global, "scope",
8374 "global");
445c2480
DS
8375
8376 /* We display both LL & GL if both have been
8377 * received */
0606039c
DA
8378 if ((attr->mp_nexthop_len
8379 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 8380 || (path->peer->conf_if)) {
a4d82a8a 8381 json_nexthop_ll = json_object_new_object();
d62a17ae 8382 json_object_string_add(
515c2602
DA
8383 json_nexthop_ll, "ip",
8384 inet_ntop(AF_INET6,
8385 &attr->mp_nexthop_local, buf,
8386 BUFSIZ));
8387
939a97f4 8388 if (path->peer->hostname)
515c2602
DA
8389 json_object_string_add(
8390 json_nexthop_ll, "hostname",
939a97f4 8391 path->peer->hostname);
515c2602 8392
a4d82a8a
PZ
8393 json_object_string_add(json_nexthop_ll, "afi",
8394 "ipv6");
8395 json_object_string_add(json_nexthop_ll, "scope",
445c2480 8396 "link-local");
d62a17ae 8397
a4d82a8a
PZ
8398 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8399 &attr->mp_nexthop_local)
445c2480
DS
8400 != 0)
8401 && !attr->mp_nexthop_prefer_global)
d62a17ae 8402 json_object_boolean_true_add(
a4d82a8a 8403 json_nexthop_ll, "used");
445c2480
DS
8404 else
8405 json_object_boolean_true_add(
a4d82a8a 8406 json_nexthop_global, "used");
445c2480
DS
8407 } else
8408 json_object_boolean_true_add(
8409 json_nexthop_global, "used");
8410 } else {
8411 /* Display LL if LL/Global both in table unless
8412 * prefer-global is set */
0606039c
DA
8413 if (((attr->mp_nexthop_len
8414 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 8415 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
8416 || (path->peer->conf_if)) {
8417 if (path->peer->conf_if) {
a4d82a8a 8418 len = vty_out(vty, "%s",
9b6d8fcf 8419 path->peer->conf_if);
ae248832
MK
8420 /* len of IPv6 addr + max len of def
8421 * ifname */
8422 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8423
8424 if (len < 1)
a4d82a8a 8425 vty_out(vty, "\n%*s", 36, " ");
445c2480 8426 else
a4d82a8a 8427 vty_out(vty, "%*s", len, " ");
d62a17ae 8428 } else {
aef999a2
DA
8429 if (nexthop_hostname)
8430 len = vty_out(
8431 vty, "%pI6(%s)%s",
8432 &attr->mp_nexthop_local,
8433 nexthop_hostname,
8434 vrf_id_str);
8435 else
8436 len = vty_out(
8437 vty, "%pI6%s",
8438 &attr->mp_nexthop_local,
8439 vrf_id_str);
8440
ae248832 8441 len = wide ? (41 - len) : (16 - len);
d62a17ae 8442
8443 if (len < 1)
a4d82a8a 8444 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 8445 else
a4d82a8a 8446 vty_out(vty, "%*s", len, " ");
d62a17ae 8447 }
445c2480 8448 } else {
aef999a2
DA
8449 if (nexthop_hostname)
8450 len = vty_out(vty, "%pI6(%s)%s",
8451 &attr->mp_nexthop_global,
8452 nexthop_hostname,
8453 vrf_id_str);
8454 else
8455 len = vty_out(vty, "%pI6%s",
8456 &attr->mp_nexthop_global,
8457 vrf_id_str);
8458
ae248832 8459 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8460
8461 if (len < 1)
8462 vty_out(vty, "\n%*s", 36, " ");
8463 else
8464 vty_out(vty, "%*s", len, " ");
d62a17ae 8465 }
8466 }
445c2480 8467 }
718e3744 8468
445c2480
DS
8469 /* MED/Metric */
8470 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 8471 if (json_paths)
50e05855 8472 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
8473 else if (wide)
8474 vty_out(vty, "%7u", attr->med);
0fbac0b4 8475 else
445c2480 8476 vty_out(vty, "%10u", attr->med);
ae248832
MK
8477 else if (!json_paths) {
8478 if (wide)
8479 vty_out(vty, "%*s", 7, " ");
8480 else
8481 vty_out(vty, "%*s", 10, " ");
8482 }
d62a17ae 8483
445c2480
DS
8484 /* Local Pref */
8485 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 8486 if (json_paths)
50e05855 8487 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
8488 attr->local_pref);
8489 else
445c2480
DS
8490 vty_out(vty, "%7u", attr->local_pref);
8491 else if (!json_paths)
8492 vty_out(vty, " ");
d62a17ae 8493
445c2480
DS
8494 if (json_paths)
8495 json_object_int_add(json_path, "weight", attr->weight);
8496 else
8497 vty_out(vty, "%7u ", attr->weight);
47fc97cc 8498
445c2480
DS
8499 if (json_paths) {
8500 char buf[BUFSIZ];
a4d82a8a
PZ
8501 json_object_string_add(
8502 json_path, "peerId",
9b6d8fcf 8503 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 8504 }
b05a1c8b 8505
445c2480
DS
8506 /* Print aspath */
8507 if (attr->aspath) {
0fbac0b4 8508 if (json_paths)
50e05855 8509 json_object_string_add(json_path, "path",
0fbac0b4
DA
8510 attr->aspath->str);
8511 else
445c2480 8512 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8513 }
f1aa5d8a 8514
445c2480
DS
8515 /* Print origin */
8516 if (json_paths)
a4d82a8a
PZ
8517 json_object_string_add(json_path, "origin",
8518 bgp_origin_long_str[attr->origin]);
445c2480
DS
8519 else
8520 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8521
9df8b37c 8522 if (json_paths) {
d071f237 8523 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
8524 json_object_string_add(json_path, "esi",
8525 esi_to_str(&attr->esi,
8526 esi_buf, sizeof(esi_buf)));
8527 }
6f214dd3
CS
8528 if (safi == SAFI_EVPN &&
8529 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8530 json_ext_community = json_object_new_object();
8531 json_object_string_add(json_ext_community,
8532 "string",
8533 attr->ecommunity->str);
8534 json_object_object_add(json_path,
8535 "extendedCommunity",
8536 json_ext_community);
8537 }
8538
9df8b37c
PZ
8539 if (nexthop_self)
8540 json_object_boolean_true_add(json_path,
8541 "announceNexthopSelf");
8542 if (nexthop_othervrf) {
8543 json_object_string_add(json_path, "nhVrfName",
8544 nexthop_vrfname);
8545
8546 json_object_int_add(json_path, "nhVrfId",
8547 ((nexthop_vrfid == VRF_UNKNOWN)
8548 ? -1
8549 : (int)nexthop_vrfid));
8550 }
8551 }
8552
d62a17ae 8553 if (json_paths) {
8554 if (json_nexthop_global || json_nexthop_ll) {
8555 json_nexthops = json_object_new_array();
f1aa5d8a 8556
d62a17ae 8557 if (json_nexthop_global)
8558 json_object_array_add(json_nexthops,
8559 json_nexthop_global);
f1aa5d8a 8560
d62a17ae 8561 if (json_nexthop_ll)
8562 json_object_array_add(json_nexthops,
8563 json_nexthop_ll);
f1aa5d8a 8564
d62a17ae 8565 json_object_object_add(json_path, "nexthops",
8566 json_nexthops);
8567 }
8568
8569 json_object_array_add(json_paths, json_path);
8570 } else {
8571 vty_out(vty, "\n");
6f214dd3 8572
b5e140c8 8573 if (safi == SAFI_EVPN) {
d071f237 8574 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
8575 vty_out(vty, "%*s", 20, " ");
8576 vty_out(vty, "ESI:%s\n",
8577 esi_to_str(&attr->esi,
8578 esi_buf, sizeof(esi_buf)));
8579 }
8580 if (attr->flag &
8581 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8582 vty_out(vty, "%*s", 20, " ");
8583 vty_out(vty, "%s\n", attr->ecommunity->str);
8584 }
6f214dd3
CS
8585 }
8586
49e5a4a0 8587#ifdef ENABLE_BGP_VNC
d62a17ae 8588 /* prints an additional line, indented, with VNC info, if
8589 * present */
8590 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 8591 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 8592#endif
d62a17ae 8593 }
8594}
718e3744 8595
8596/* called from terminal list command */
5f040085
DS
8597void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
8598 struct attr *attr, safi_t safi, bool use_json,
ae248832 8599 json_object *json_ar, bool wide)
d62a17ae 8600{
8601 json_object *json_status = NULL;
8602 json_object *json_net = NULL;
aef999a2 8603 int len;
d62a17ae 8604 char buff[BUFSIZ];
dc387b0f 8605
d62a17ae 8606 /* Route status display. */
8607 if (use_json) {
8608 json_status = json_object_new_object();
8609 json_net = json_object_new_object();
8610 } else {
8611 vty_out(vty, "*");
8612 vty_out(vty, ">");
8613 vty_out(vty, " ");
8614 }
718e3744 8615
d62a17ae 8616 /* print prefix and mask */
50e05855 8617 if (use_json) {
dc387b0f
LK
8618 if (safi == SAFI_EVPN)
8619 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
8620 else if (p->family == AF_INET || p->family == AF_INET6) {
8621 json_object_string_add(
8622 json_net, "addrPrefix",
8623 inet_ntop(p->family, &p->u.prefix, buff,
8624 BUFSIZ));
8625 json_object_int_add(json_net, "prefixLen",
8626 p->prefixlen);
8627 prefix2str(p, buff, PREFIX_STRLEN);
8628 json_object_string_add(json_net, "network", buff);
8629 }
50e05855 8630 } else
ae248832 8631 route_vty_out_route(p, vty, NULL, wide);
d62a17ae 8632
8633 /* Print attribute */
8634 if (attr) {
8635 if (use_json) {
23d0a753
DA
8636 char buf[BUFSIZ] = {0};
8637
d62a17ae 8638 if (p->family == AF_INET
8639 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 8640 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 8641 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 8642 json_object_string_add(
8643 json_net, "nextHop",
23d0a753
DA
8644 inet_ntop(
8645 AF_INET,
8646 &attr->mp_nexthop_global_in,
8647 buf, sizeof(buf)));
d62a17ae 8648 else
8649 json_object_string_add(
8650 json_net, "nextHop",
23d0a753
DA
8651 inet_ntop(AF_INET,
8652 &attr->nexthop, buf,
8653 sizeof(buf)));
d62a17ae 8654 } else if (p->family == AF_INET6
8655 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8656 char buf[BUFSIZ];
8657
8658 json_object_string_add(
aa0a10fc 8659 json_net, "nextHopGlobal",
d62a17ae 8660 inet_ntop(AF_INET6,
8661 &attr->mp_nexthop_global, buf,
8662 BUFSIZ));
23d0a753
DA
8663 } else if (p->family == AF_EVPN
8664 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8665 char buf[BUFSIZ] = {0};
8666
8667 json_object_string_add(
8668 json_net, "nextHop",
8669 inet_ntop(AF_INET,
8670 &attr->mp_nexthop_global_in,
8671 buf, sizeof(buf)));
8672 }
d62a17ae 8673
8674 if (attr->flag
8675 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8676 json_object_int_add(json_net, "metric",
8677 attr->med);
8678
0fbac0b4 8679 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 8680 json_object_int_add(json_net, "locPrf",
0fbac0b4 8681 attr->local_pref);
d62a17ae 8682
8683 json_object_int_add(json_net, "weight", attr->weight);
8684
8685 /* Print aspath */
0fbac0b4 8686 if (attr->aspath)
50e05855 8687 json_object_string_add(json_net, "path",
0fbac0b4 8688 attr->aspath->str);
d62a17ae 8689
8690 /* Print origin */
8691 json_object_string_add(json_net, "bgpOriginCode",
8692 bgp_origin_str[attr->origin]);
8693 } else {
8694 if (p->family == AF_INET
8695 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8696 || safi == SAFI_EVPN
8697 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8698 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8699 || safi == SAFI_EVPN)
23d0a753
DA
8700 vty_out(vty, "%-16pI4",
8701 &attr->mp_nexthop_global_in);
ae248832 8702 else if (wide)
23d0a753 8703 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 8704 else
23d0a753 8705 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 8706 } else if (p->family == AF_INET6
8707 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 8708 char buf[BUFSIZ];
8709
8710 len = vty_out(
8711 vty, "%s",
8712 inet_ntop(AF_INET6,
8713 &attr->mp_nexthop_global, buf,
8714 BUFSIZ));
ae248832 8715 len = wide ? (41 - len) : (16 - len);
d62a17ae 8716 if (len < 1)
8717 vty_out(vty, "\n%*s", 36, " ");
8718 else
8719 vty_out(vty, "%*s", len, " ");
8720 }
8721 if (attr->flag
8722 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
8723 if (wide)
8724 vty_out(vty, "%7u", attr->med);
8725 else
8726 vty_out(vty, "%10u", attr->med);
8727 else if (wide)
8728 vty_out(vty, " ");
d62a17ae 8729 else
8730 vty_out(vty, " ");
718e3744 8731
d62a17ae 8732 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
8733 vty_out(vty, "%7u", attr->local_pref);
8734 else
8735 vty_out(vty, " ");
8736
8737 vty_out(vty, "%7u ", attr->weight);
8738
8739 /* Print aspath */
8740 if (attr->aspath)
8741 aspath_print_vty(vty, "%s", attr->aspath, " ");
8742
8743 /* Print origin */
8744 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8745 }
8746 }
8747 if (use_json) {
8748 json_object_boolean_true_add(json_status, "*");
8749 json_object_boolean_true_add(json_status, ">");
8750 json_object_object_add(json_net, "appliedStatusSymbols",
8751 json_status);
1608ff77 8752
dc387b0f
LK
8753 prefix2str(p, buff, PREFIX_STRLEN);
8754 json_object_object_add(json_ar, buff, json_net);
d62a17ae 8755 } else
8756 vty_out(vty, "\n");
8757}
8758
bd494ec5 8759void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 8760 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 8761 json_object *json)
8762{
8763 json_object *json_out = NULL;
8764 struct attr *attr;
8765 mpls_label_t label = MPLS_INVALID_LABEL;
8766
9b6d8fcf 8767 if (!path->extra)
d62a17ae 8768 return;
8769
8770 if (json)
8771 json_out = json_object_new_object();
8772
8773 /* short status lead text */
9b6d8fcf 8774 route_vty_short_status_out(vty, path, json_out);
d62a17ae 8775
8776 /* print prefix and mask */
8777 if (json == NULL) {
8778 if (!display)
ae248832 8779 route_vty_out_route(p, vty, NULL, false);
d62a17ae 8780 else
8781 vty_out(vty, "%*s", 17, " ");
8782 }
8783
8784 /* Print attribute */
9b6d8fcf 8785 attr = path->attr;
05864da7
DS
8786 if (((p->family == AF_INET)
8787 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8788 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8789 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
8790 char buf[BUFSIZ] = {0};
8791
05864da7
DS
8792 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8793 || safi == SAFI_EVPN) {
8794 if (json)
8795 json_object_string_add(
8796 json_out, "mpNexthopGlobalIn",
23d0a753
DA
8797 inet_ntop(AF_INET,
8798 &attr->mp_nexthop_global_in,
8799 buf, sizeof(buf)));
05864da7 8800 else
23d0a753
DA
8801 vty_out(vty, "%-16pI4",
8802 &attr->mp_nexthop_global_in);
05864da7
DS
8803 } else {
8804 if (json)
8805 json_object_string_add(
8806 json_out, "nexthop",
23d0a753
DA
8807 inet_ntop(AF_INET, &attr->nexthop, buf,
8808 sizeof(buf)));
05864da7 8809 else
23d0a753 8810 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
8811 }
8812 } else if (((p->family == AF_INET6)
8813 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8814 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8815 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8816 char buf_a[512];
8817
8818 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
8819 if (json)
8820 json_object_string_add(
8821 json_out, "mpNexthopGlobalIn",
8822 inet_ntop(AF_INET6,
8823 &attr->mp_nexthop_global,
8824 buf_a, sizeof(buf_a)));
8825 else
8826 vty_out(vty, "%s",
8827 inet_ntop(AF_INET6,
8828 &attr->mp_nexthop_global,
8829 buf_a, sizeof(buf_a)));
8830 } else if (attr->mp_nexthop_len
8831 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
8832 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
8833 &attr->mp_nexthop_global,
8834 &attr->mp_nexthop_local);
8835 if (json)
8836 json_object_string_add(json_out,
8837 "mpNexthopGlobalLocal",
8838 buf_a);
8839 else
8840 vty_out(vty, "%s", buf_a);
d62a17ae 8841 }
8842 }
8843
9b6d8fcf 8844 label = decode_label(&path->extra->label[0]);
d62a17ae 8845
8846 if (bgp_is_valid_label(&label)) {
8847 if (json) {
8848 json_object_int_add(json_out, "notag", label);
8849 json_object_array_add(json, json_out);
8850 } else {
8851 vty_out(vty, "notag/%d", label);
8852 vty_out(vty, "\n");
8853 }
8854 }
8855}
718e3744 8856
bd494ec5 8857void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 8858 struct bgp_path_info *path, int display,
d62a17ae 8859 json_object *json_paths)
718e3744 8860{
d62a17ae 8861 struct attr *attr;
14f51eba 8862 char buf[BUFSIZ] = {0};
d62a17ae 8863 json_object *json_path = NULL;
14f51eba
LK
8864 json_object *json_nexthop = NULL;
8865 json_object *json_overlay = NULL;
856ca177 8866
9b6d8fcf 8867 if (!path->extra)
d62a17ae 8868 return;
718e3744 8869
14f51eba
LK
8870 if (json_paths) {
8871 json_path = json_object_new_object();
8872 json_overlay = json_object_new_object();
8873 json_nexthop = json_object_new_object();
8874 }
8875
d62a17ae 8876 /* short status lead text */
9b6d8fcf 8877 route_vty_short_status_out(vty, path, json_path);
856ca177 8878
d62a17ae 8879 /* print prefix and mask */
8880 if (!display)
ae248832 8881 route_vty_out_route(p, vty, json_path, false);
d62a17ae 8882 else
8883 vty_out(vty, "%*s", 17, " ");
8884
8885 /* Print attribute */
9b6d8fcf 8886 attr = path->attr;
05864da7
DS
8887 char buf1[BUFSIZ];
8888 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 8889
05864da7
DS
8890 switch (af) {
8891 case AF_INET:
8892 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
8893 if (!json_path) {
8894 vty_out(vty, "%-16s", buf);
8895 } else {
8896 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 8897
05864da7 8898 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 8899
05864da7
DS
8900 json_object_object_add(json_path, "nexthop",
8901 json_nexthop);
8902 }
8903 break;
8904 case AF_INET6:
8905 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
8906 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
8907 if (!json_path) {
8908 vty_out(vty, "%s(%s)", buf, buf1);
8909 } else {
8910 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 8911
05864da7
DS
8912 json_object_string_add(json_nexthop, "ipv6LinkLocal",
8913 buf1);
14f51eba 8914
05864da7 8915 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 8916
05864da7
DS
8917 json_object_object_add(json_path, "nexthop",
8918 json_nexthop);
8919 }
8920 break;
8921 default:
8922 if (!json_path) {
8923 vty_out(vty, "?");
8924 } else {
8925 json_object_string_add(json_nexthop, "Error",
8926 "Unsupported address-family");
d62a17ae 8927 }
05864da7 8928 }
988258b4 8929
05864da7
DS
8930 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
8931 inet_ntop(AF_INET, &(attr->evpn_overlay.gw_ip.ipv4), buf,
8932 BUFSIZ);
8933 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
8934 inet_ntop(AF_INET6, &(attr->evpn_overlay.gw_ip.ipv6), buf,
8935 BUFSIZ);
8936 }
14f51eba 8937
05864da7
DS
8938 if (!json_path)
8939 vty_out(vty, "/%s", buf);
8940 else
8941 json_object_string_add(json_overlay, "gw", buf);
8942
8943 if (attr->ecommunity) {
8944 char *mac = NULL;
8945 struct ecommunity_val *routermac = ecommunity_lookup(
8946 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
8947 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
8948
8949 if (routermac)
8950 mac = ecom_mac2str((char *)routermac->val);
8951 if (mac) {
8952 if (!json_path) {
c4efd0f4 8953 vty_out(vty, "/%s", mac);
05864da7
DS
8954 } else {
8955 json_object_string_add(json_overlay, "rmac",
8956 mac);
988258b4 8957 }
05864da7 8958 XFREE(MTYPE_TMP, mac);
988258b4 8959 }
05864da7 8960 }
718e3744 8961
05864da7
DS
8962 if (!json_path) {
8963 vty_out(vty, "\n");
8964 } else {
8965 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 8966
05864da7 8967 json_object_array_add(json_paths, json_path);
14f51eba 8968 }
d62a17ae 8969}
718e3744 8970
d62a17ae 8971/* dampening route */
5f040085
DS
8972static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
8973 struct bgp_path_info *path, int display,
8974 afi_t afi, safi_t safi, bool use_json,
8975 json_object *json)
d62a17ae 8976{
8977 struct attr *attr;
8978 int len;
8979 char timebuf[BGP_UPTIME_LEN];
8980
8981 /* short status lead text */
9b6d8fcf 8982 route_vty_short_status_out(vty, path, json);
d62a17ae 8983
8984 /* print prefix and mask */
8985 if (!use_json) {
8986 if (!display)
ae248832 8987 route_vty_out_route(p, vty, NULL, false);
d62a17ae 8988 else
8989 vty_out(vty, "%*s", 17, " ");
8990 }
8991
9b6d8fcf 8992 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 8993 len = 17 - len;
8994 if (len < 1) {
8995 if (!use_json)
8996 vty_out(vty, "\n%*s", 34, " ");
8997 } else {
8998 if (use_json)
8999 json_object_int_add(json, "peerHost", len);
9000 else
9001 vty_out(vty, "%*s", len, " ");
9002 }
9003
9004 if (use_json)
a935f597
DA
9005 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9006 safi, use_json, json);
d62a17ae 9007 else
9b6d8fcf
DS
9008 vty_out(vty, "%s ",
9009 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9010 BGP_UPTIME_LEN, afi, safi,
9011 use_json, json));
d62a17ae 9012
9013 /* Print attribute */
9b6d8fcf 9014 attr = path->attr;
d62a17ae 9015
05864da7
DS
9016 /* Print aspath */
9017 if (attr->aspath) {
d62a17ae 9018 if (use_json)
05864da7
DS
9019 json_object_string_add(json, "asPath",
9020 attr->aspath->str);
d62a17ae 9021 else
05864da7 9022 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9023 }
05864da7
DS
9024
9025 /* Print origin */
9026 if (use_json)
9027 json_object_string_add(json, "origin",
9028 bgp_origin_str[attr->origin]);
9029 else
9030 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9031
d62a17ae 9032 if (!use_json)
9033 vty_out(vty, "\n");
9034}
718e3744 9035
d62a17ae 9036/* flap route */
5f040085
DS
9037static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9038 struct bgp_path_info *path, int display,
9039 afi_t afi, safi_t safi, bool use_json,
9040 json_object *json)
784d3a42 9041{
d62a17ae 9042 struct attr *attr;
9043 struct bgp_damp_info *bdi;
9044 char timebuf[BGP_UPTIME_LEN];
9045 int len;
784d3a42 9046
9b6d8fcf 9047 if (!path->extra)
d62a17ae 9048 return;
784d3a42 9049
9b6d8fcf 9050 bdi = path->extra->damp_info;
784d3a42 9051
d62a17ae 9052 /* short status lead text */
9b6d8fcf 9053 route_vty_short_status_out(vty, path, json);
784d3a42 9054
d62a17ae 9055 /* print prefix and mask */
9056 if (!use_json) {
9057 if (!display)
ae248832 9058 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9059 else
9060 vty_out(vty, "%*s", 17, " ");
9061 }
784d3a42 9062
9b6d8fcf 9063 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9064 len = 16 - len;
9065 if (len < 1) {
9066 if (!use_json)
9067 vty_out(vty, "\n%*s", 33, " ");
9068 } else {
9069 if (use_json)
9070 json_object_int_add(json, "peerHost", len);
9071 else
9072 vty_out(vty, "%*s", len, " ");
9073 }
784d3a42 9074
d62a17ae 9075 len = vty_out(vty, "%d", bdi->flap);
9076 len = 5 - len;
9077 if (len < 1) {
9078 if (!use_json)
9079 vty_out(vty, " ");
9080 } else {
9081 if (use_json)
9082 json_object_int_add(json, "bdiFlap", len);
9083 else
9084 vty_out(vty, "%*s", len, " ");
9085 }
9086
9087 if (use_json)
9088 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9089 json);
9090 else
996c9314
LB
9091 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9092 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9093
9b6d8fcf
DS
9094 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9095 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 9096 if (use_json)
9b6d8fcf 9097 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9098 BGP_UPTIME_LEN, afi, safi,
9099 use_json, json);
d62a17ae 9100 else
9101 vty_out(vty, "%s ",
9b6d8fcf 9102 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9103 BGP_UPTIME_LEN, afi,
9104 safi, use_json, json));
d62a17ae 9105 } else {
9106 if (!use_json)
9107 vty_out(vty, "%*s ", 8, " ");
9108 }
9109
9110 /* Print attribute */
9b6d8fcf 9111 attr = path->attr;
d62a17ae 9112
05864da7
DS
9113 /* Print aspath */
9114 if (attr->aspath) {
d62a17ae 9115 if (use_json)
05864da7
DS
9116 json_object_string_add(json, "asPath",
9117 attr->aspath->str);
d62a17ae 9118 else
05864da7 9119 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9120 }
05864da7
DS
9121
9122 /* Print origin */
9123 if (use_json)
9124 json_object_string_add(json, "origin",
9125 bgp_origin_str[attr->origin]);
9126 else
9127 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9128
d62a17ae 9129 if (!use_json)
9130 vty_out(vty, "\n");
9131}
9132
9133static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9134 int *first, const char *header,
9135 json_object *json_adv_to)
9136{
9137 char buf1[INET6_ADDRSTRLEN];
9138 json_object *json_peer = NULL;
9139
9140 if (json_adv_to) {
9141 /* 'advertised-to' is a dictionary of peers we have advertised
9142 * this
9143 * prefix too. The key is the peer's IP or swpX, the value is
9144 * the
9145 * hostname if we know it and "" if not.
9146 */
9147 json_peer = json_object_new_object();
9148
9149 if (peer->hostname)
9150 json_object_string_add(json_peer, "hostname",
9151 peer->hostname);
9152
9153 if (peer->conf_if)
9154 json_object_object_add(json_adv_to, peer->conf_if,
9155 json_peer);
9156 else
9157 json_object_object_add(
9158 json_adv_to,
9159 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9160 json_peer);
9161 } else {
9162 if (*first) {
9163 vty_out(vty, "%s", header);
9164 *first = 0;
9165 }
9166
9167 if (peer->hostname
892fedb6 9168 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9169 if (peer->conf_if)
9170 vty_out(vty, " %s(%s)", peer->hostname,
9171 peer->conf_if);
9172 else
9173 vty_out(vty, " %s(%s)", peer->hostname,
9174 sockunion2str(&peer->su, buf1,
9175 SU_ADDRSTRLEN));
9176 } else {
9177 if (peer->conf_if)
9178 vty_out(vty, " %s", peer->conf_if);
9179 else
9180 vty_out(vty, " %s",
9181 sockunion2str(&peer->su, buf1,
9182 SU_ADDRSTRLEN));
9183 }
9184 }
784d3a42
PG
9185}
9186
dcc68b5e
MS
9187static void route_vty_out_tx_ids(struct vty *vty,
9188 struct bgp_addpath_info_data *d)
9189{
9190 int i;
9191
9192 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9193 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9194 d->addpath_tx_id[i],
9195 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9196 }
9197}
9198
0dc8ee70
DS
9199static const char *bgp_path_selection_reason2str(
9200 enum bgp_path_selection_reason reason)
9201{
9202 switch (reason) {
9203 case bgp_path_selection_none:
9204 return "Nothing to Select";
0dc8ee70
DS
9205 case bgp_path_selection_first:
9206 return "First path received";
0dc8ee70
DS
9207 case bgp_path_selection_evpn_sticky_mac:
9208 return "EVPN Sticky Mac";
0dc8ee70
DS
9209 case bgp_path_selection_evpn_seq:
9210 return "EVPN sequence number";
0dc8ee70
DS
9211 case bgp_path_selection_evpn_lower_ip:
9212 return "EVPN lower IP";
d071f237
AK
9213 case bgp_path_selection_evpn_local_path:
9214 return "EVPN local ES path";
9215 case bgp_path_selection_evpn_non_proxy:
9216 return "EVPN non proxy";
0dc8ee70
DS
9217 case bgp_path_selection_weight:
9218 return "Weight";
0dc8ee70
DS
9219 case bgp_path_selection_local_pref:
9220 return "Local Pref";
0dc8ee70
DS
9221 case bgp_path_selection_local_route:
9222 return "Local Route";
0dc8ee70
DS
9223 case bgp_path_selection_confed_as_path:
9224 return "Confederation based AS Path";
0dc8ee70
DS
9225 case bgp_path_selection_as_path:
9226 return "AS Path";
0dc8ee70
DS
9227 case bgp_path_selection_origin:
9228 return "Origin";
0dc8ee70
DS
9229 case bgp_path_selection_med:
9230 return "MED";
0dc8ee70
DS
9231 case bgp_path_selection_peer:
9232 return "Peer Type";
0dc8ee70
DS
9233 case bgp_path_selection_confed:
9234 return "Confed Peer Type";
0dc8ee70
DS
9235 case bgp_path_selection_igp_metric:
9236 return "IGP Metric";
0dc8ee70
DS
9237 case bgp_path_selection_older:
9238 return "Older Path";
0dc8ee70
DS
9239 case bgp_path_selection_router_id:
9240 return "Router ID";
0dc8ee70
DS
9241 case bgp_path_selection_cluster_length:
9242 return "Cluser length";
0dc8ee70
DS
9243 case bgp_path_selection_stale:
9244 return "Path Staleness";
0dc8ee70
DS
9245 case bgp_path_selection_local_configured:
9246 return "Locally configured route";
0dc8ee70
DS
9247 case bgp_path_selection_neighbor_ip:
9248 return "Neighbor IP";
0dc8ee70
DS
9249 case bgp_path_selection_default:
9250 return "Nothing left to compare";
0dc8ee70 9251 }
a74879b2 9252 return "Invalid (internal error)";
0dc8ee70
DS
9253}
9254
5e4d4c8a
AK
9255static void route_vty_out_detail_es_info(struct vty *vty,
9256 struct attr *attr, json_object *json_path)
9257{
9258 char esi_buf[ESI_STR_LEN];
9259 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9260 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9261 ATTR_ES_PEER_ROUTER);
9262 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9263 ATTR_ES_PEER_ACTIVE);
9264 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9265 ATTR_ES_PEER_PROXY);
9266
9267 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9268 if (json_path) {
9269 json_object *json_es_info = NULL;
9270
9271 json_object_string_add(
9272 json_path, "esi",
9273 esi_buf);
9274 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9275 json_es_info = json_object_new_object();
9276 if (es_local)
9277 json_object_boolean_true_add(
9278 json_es_info, "localEs");
9279 if (peer_active)
9280 json_object_boolean_true_add(
9281 json_es_info, "peerActive");
9282 if (peer_proxy)
9283 json_object_boolean_true_add(
9284 json_es_info, "peerProxy");
9285 if (peer_router)
9286 json_object_boolean_true_add(
9287 json_es_info, "peerRouter");
9288 if (attr->mm_sync_seqnum)
9289 json_object_int_add(
9290 json_es_info, "peerSeq",
9291 attr->mm_sync_seqnum);
9292 json_object_object_add(
9293 json_path, "es_info",
9294 json_es_info);
9295 }
9296 } else {
9297 if (bgp_evpn_attr_is_sync(attr))
9298 vty_out(vty,
9299 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9300 esi_buf,
9301 es_local ? "local-es":"",
9302 peer_proxy ? "proxy " : "",
9303 peer_active ? "active ":"",
9304 peer_router ? "router ":"",
9305 attr->mm_sync_seqnum);
9306 else
9307 vty_out(vty, " ESI %s %s\n",
9308 esi_buf,
9309 es_local ? "local-es":"");
9310 }
9311}
9312
9313void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
9314 struct bgp_dest *bn, struct bgp_path_info *path,
9315 afi_t afi, safi_t safi, json_object *json_paths)
d62a17ae 9316{
9317 char buf[INET6_ADDRSTRLEN];
9318 char buf1[BUFSIZ];
515c2602 9319 struct attr *attr = path->attr;
d62a17ae 9320 int sockunion_vty_out(struct vty *, union sockunion *);
9321 time_t tbuf;
9322 json_object *json_bestpath = NULL;
9323 json_object *json_cluster_list = NULL;
9324 json_object *json_cluster_list_list = NULL;
9325 json_object *json_ext_community = NULL;
9326 json_object *json_last_update = NULL;
7fd077aa 9327 json_object *json_pmsi = NULL;
d62a17ae 9328 json_object *json_nexthop_global = NULL;
9329 json_object *json_nexthop_ll = NULL;
9330 json_object *json_nexthops = NULL;
9331 json_object *json_path = NULL;
9332 json_object *json_peer = NULL;
9333 json_object *json_string = NULL;
9334 json_object *json_adv_to = NULL;
9335 int first = 0;
9336 struct listnode *node, *nnode;
9337 struct peer *peer;
9338 int addpath_capable;
9339 int has_adj;
9340 unsigned int first_as;
1defdda8 9341 bool nexthop_self =
9b6d8fcf 9342 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9343 int i;
2ba93fd6
DA
9344 char *nexthop_hostname =
9345 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 9346
9347 if (json_paths) {
9348 json_path = json_object_new_object();
9349 json_peer = json_object_new_object();
9350 json_nexthop_global = json_object_new_object();
9351 }
9352
44c69747 9353 if (path->extra) {
b57ba6d2 9354 char tag_buf[30];
d62a17ae 9355
d62a17ae 9356 tag_buf[0] = '\0';
9b6d8fcf
DS
9357 if (path->extra && path->extra->num_labels) {
9358 bgp_evpn_label2str(path->extra->label,
9359 path->extra->num_labels, tag_buf,
a4d82a8a 9360 sizeof(tag_buf));
d62a17ae 9361 }
d7325ee7 9362 if (safi == SAFI_EVPN) {
44c69747 9363 if (!json_paths) {
2dbe669b
DA
9364 vty_out(vty, " Route %pFX",
9365 (struct prefix_evpn *)
9366 bgp_dest_get_prefix(bn));
44c69747
LK
9367 if (tag_buf[0] != '\0')
9368 vty_out(vty, " VNI %s", tag_buf);
9369 vty_out(vty, "\n");
9370 } else {
9371 if (tag_buf[0])
9372 json_object_string_add(json_path, "VNI",
9373 tag_buf);
9374 }
d7325ee7
DD
9375 }
9376
44c69747 9377 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9378 struct bgp_path_info *parent_ri;
9bcb3eef 9379 struct bgp_dest *dest, *pdest;
d62a17ae 9380
9b6d8fcf 9381 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9382 dest = parent_ri->net;
9383 if (dest && dest->pdest) {
9384 pdest = dest->pdest;
9385 prefix_rd2str(
9386 (struct prefix_rd *)bgp_dest_get_prefix(
9387 pdest),
9388 buf1, sizeof(buf1));
d7325ee7 9389 if (is_pi_family_evpn(parent_ri)) {
2dbe669b
DA
9390 vty_out(vty,
9391 " Imported from %s:%pFX, VNI %s\n",
9392 buf1,
9393 (struct prefix_evpn *)
9394 bgp_dest_get_prefix(
9395 dest),
9396 tag_buf);
d7325ee7 9397 } else
2dbe669b
DA
9398 vty_out(vty,
9399 " Imported from %s:%pFX\n",
9400 buf1,
9401 (struct prefix_evpn *)
9402 bgp_dest_get_prefix(
9403 dest));
d62a17ae 9404 }
9405 }
9406 }
d62a17ae 9407
05864da7
DS
9408 /* Line1 display AS-path, Aggregator */
9409 if (attr->aspath) {
9410 if (json_paths) {
9411 if (!attr->aspath->json)
9412 aspath_str_update(attr->aspath, true);
9413 json_object_lock(attr->aspath->json);
9414 json_object_object_add(json_path, "aspath",
9415 attr->aspath->json);
9416 } else {
9417 if (attr->aspath->segments)
9418 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9419 else
05864da7 9420 vty_out(vty, " Local");
d62a17ae 9421 }
05864da7 9422 }
d62a17ae 9423
05864da7
DS
9424 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9425 if (json_paths)
9426 json_object_boolean_true_add(json_path, "removed");
9427 else
9428 vty_out(vty, ", (removed)");
9429 }
d62a17ae 9430
05864da7
DS
9431 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9432 if (json_paths)
9433 json_object_boolean_true_add(json_path, "stale");
9434 else
9435 vty_out(vty, ", (stale)");
9436 }
d62a17ae 9437
05864da7
DS
9438 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9439 if (json_paths) {
23d0a753
DA
9440 char buf[BUFSIZ] = {0};
9441
05864da7
DS
9442 json_object_int_add(json_path, "aggregatorAs",
9443 attr->aggregator_as);
23d0a753
DA
9444 json_object_string_add(json_path, "aggregatorId",
9445 inet_ntop(AF_INET,
9446 &attr->aggregator_addr,
9447 buf, sizeof(buf)));
87c82131
DA
9448 if (attr->aggregator_as == BGP_AS_ZERO)
9449 json_object_boolean_true_add(
9450 json_path, "aggregatorAsMalformed");
9451 else
9452 json_object_boolean_false_add(
9453 json_path, "aggregatorAsMalformed");
05864da7 9454 } else {
87c82131
DA
9455 if (attr->aggregator_as == BGP_AS_ZERO)
9456 vty_out(vty,
23d0a753 9457 ", (aggregated by %u(malformed) %pI4)",
87c82131 9458 attr->aggregator_as,
23d0a753 9459 &attr->aggregator_addr);
87c82131 9460 else
23d0a753 9461 vty_out(vty, ", (aggregated by %u %pI4)",
87c82131 9462 attr->aggregator_as,
23d0a753 9463 &attr->aggregator_addr);
d62a17ae 9464 }
05864da7 9465 }
d62a17ae 9466
05864da7
DS
9467 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9468 PEER_FLAG_REFLECTOR_CLIENT)) {
9469 if (json_paths)
9470 json_object_boolean_true_add(json_path,
9471 "rxedFromRrClient");
9472 else
9473 vty_out(vty, ", (Received from a RR-client)");
9474 }
d62a17ae 9475
05864da7
DS
9476 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9477 PEER_FLAG_RSERVER_CLIENT)) {
9478 if (json_paths)
9479 json_object_boolean_true_add(json_path,
9480 "rxedFromRsClient");
9481 else
9482 vty_out(vty, ", (Received from a RS-client)");
9483 }
d62a17ae 9484
05864da7
DS
9485 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9486 if (json_paths)
9487 json_object_boolean_true_add(json_path,
9488 "dampeningHistoryEntry");
9489 else
9490 vty_out(vty, ", (history entry)");
9491 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
9492 if (json_paths)
9493 json_object_boolean_true_add(json_path,
9494 "dampeningSuppressed");
9495 else
9496 vty_out(vty, ", (suppressed due to dampening)");
9497 }
d62a17ae 9498
05864da7
DS
9499 if (!json_paths)
9500 vty_out(vty, "\n");
d62a17ae 9501
05864da7
DS
9502 /* Line2 display Next-hop, Neighbor, Router-id */
9503 /* Display the nexthop */
9bcb3eef 9504 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
9505
9506 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
9507 || bn_p->family == AF_EVPN)
05864da7
DS
9508 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
9509 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9510 char buf[BUFSIZ] = {0};
9511
05864da7
DS
9512 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9513 || safi == SAFI_EVPN) {
515c2602 9514 if (json_paths) {
d62a17ae 9515 json_object_string_add(
515c2602 9516 json_nexthop_global, "ip",
23d0a753
DA
9517 inet_ntop(AF_INET,
9518 &attr->mp_nexthop_global_in,
9519 buf, sizeof(buf)));
515c2602 9520
939a97f4 9521 if (path->peer->hostname)
515c2602
DA
9522 json_object_string_add(
9523 json_nexthop_global, "hostname",
939a97f4 9524 path->peer->hostname);
aef999a2
DA
9525 } else {
9526 if (nexthop_hostname)
9527 vty_out(vty, " %pI4(%s)",
9528 &attr->mp_nexthop_global_in,
9529 nexthop_hostname);
9530 else
9531 vty_out(vty, " %pI4",
9532 &attr->mp_nexthop_global_in);
9533 }
d62a17ae 9534 } else {
515c2602 9535 if (json_paths) {
05864da7 9536 json_object_string_add(
515c2602 9537 json_nexthop_global, "ip",
23d0a753
DA
9538 inet_ntop(AF_INET, &attr->nexthop, buf,
9539 sizeof(buf)));
515c2602 9540
939a97f4 9541 if (path->peer->hostname)
515c2602
DA
9542 json_object_string_add(
9543 json_nexthop_global, "hostname",
939a97f4 9544 path->peer->hostname);
aef999a2
DA
9545 } else {
9546 if (nexthop_hostname)
9547 vty_out(vty, " %pI4(%s)",
9548 &attr->nexthop,
9549 nexthop_hostname);
9550 else
9551 vty_out(vty, " %pI4",
9552 &attr->nexthop);
9553 }
d62a17ae 9554 }
9555
05864da7
DS
9556 if (json_paths)
9557 json_object_string_add(json_nexthop_global, "afi",
9558 "ipv4");
9559 } else {
9560 if (json_paths) {
9561 json_object_string_add(
515c2602
DA
9562 json_nexthop_global, "ip",
9563 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
9564 buf, INET6_ADDRSTRLEN));
9565
939a97f4 9566 if (path->peer->hostname)
515c2602
DA
9567 json_object_string_add(json_nexthop_global,
9568 "hostname",
939a97f4 9569 path->peer->hostname);
515c2602 9570
05864da7
DS
9571 json_object_string_add(json_nexthop_global, "afi",
9572 "ipv6");
9573 json_object_string_add(json_nexthop_global, "scope",
9574 "global");
9575 } else {
aef999a2
DA
9576 if (nexthop_hostname)
9577 vty_out(vty, " %pI6(%s)",
9578 &attr->mp_nexthop_global,
9579 nexthop_hostname);
9580 else
9581 vty_out(vty, " %pI6",
9582 &attr->mp_nexthop_global);
d62a17ae 9583 }
05864da7 9584 }
d62a17ae 9585
05864da7
DS
9586 /* Display the IGP cost or 'inaccessible' */
9587 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9588 if (json_paths)
9589 json_object_boolean_false_add(json_nexthop_global,
9590 "accessible");
9591 else
9592 vty_out(vty, " (inaccessible)");
9593 } else {
9594 if (path->extra && path->extra->igpmetric) {
d62a17ae 9595 if (json_paths)
05864da7
DS
9596 json_object_int_add(json_nexthop_global,
9597 "metric",
9598 path->extra->igpmetric);
d62a17ae 9599 else
05864da7
DS
9600 vty_out(vty, " (metric %u)",
9601 path->extra->igpmetric);
d62a17ae 9602 }
9603
05864da7 9604 /* IGP cost is 0, display this only for json */
d62a17ae 9605 else {
d62a17ae 9606 if (json_paths)
05864da7
DS
9607 json_object_int_add(json_nexthop_global,
9608 "metric", 0);
d62a17ae 9609 }
d62a17ae 9610
05864da7
DS
9611 if (json_paths)
9612 json_object_boolean_true_add(json_nexthop_global,
9613 "accessible");
9614 }
d62a17ae 9615
05864da7
DS
9616 /* Display peer "from" output */
9617 /* This path was originated locally */
9618 if (path->peer == bgp->peer_self) {
d62a17ae 9619
05864da7 9620 if (safi == SAFI_EVPN
b54892e0 9621 || (bn_p->family == AF_INET
05864da7 9622 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 9623 if (json_paths)
05864da7
DS
9624 json_object_string_add(json_peer, "peerId",
9625 "0.0.0.0");
d62a17ae 9626 else
05864da7
DS
9627 vty_out(vty, " from 0.0.0.0 ");
9628 } else {
d62a17ae 9629 if (json_paths)
05864da7
DS
9630 json_object_string_add(json_peer, "peerId",
9631 "::");
d62a17ae 9632 else
05864da7 9633 vty_out(vty, " from :: ");
d62a17ae 9634 }
d62a17ae 9635
23d0a753
DA
9636 if (json_paths) {
9637 char buf[BUFSIZ] = {0};
9638
05864da7 9639 json_object_string_add(json_peer, "routerId",
23d0a753
DA
9640 inet_ntop(AF_INET,
9641 &bgp->router_id, buf,
9642 sizeof(buf)));
9643 } else {
9644 vty_out(vty, "(%pI4)", &bgp->router_id);
9645 }
05864da7 9646 }
d62a17ae 9647
05864da7
DS
9648 /* We RXed this path from one of our peers */
9649 else {
9650
9651 if (json_paths) {
9652 json_object_string_add(json_peer, "peerId",
9653 sockunion2str(&path->peer->su,
9654 buf,
9655 SU_ADDRSTRLEN));
9656 json_object_string_add(json_peer, "routerId",
9657 inet_ntop(AF_INET,
9658 &path->peer->remote_id,
9659 buf1, sizeof(buf1)));
9660
9661 if (path->peer->hostname)
9662 json_object_string_add(json_peer, "hostname",
9663 path->peer->hostname);
9664
9665 if (path->peer->domainname)
9666 json_object_string_add(json_peer, "domainname",
9667 path->peer->domainname);
9668
9669 if (path->peer->conf_if)
9670 json_object_string_add(json_peer, "interface",
9671 path->peer->conf_if);
9672 } else {
9673 if (path->peer->conf_if) {
9674 if (path->peer->hostname
892fedb6
DA
9675 && CHECK_FLAG(path->peer->bgp->flags,
9676 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9677 vty_out(vty, " from %s(%s)",
9678 path->peer->hostname,
9679 path->peer->conf_if);
d62a17ae 9680 else
05864da7 9681 vty_out(vty, " from %s",
9b6d8fcf 9682 path->peer->conf_if);
d62a17ae 9683 } else {
05864da7 9684 if (path->peer->hostname
892fedb6
DA
9685 && CHECK_FLAG(path->peer->bgp->flags,
9686 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9687 vty_out(vty, " from %s(%s)",
9688 path->peer->hostname,
9689 path->peer->host);
d62a17ae 9690 else
05864da7
DS
9691 vty_out(vty, " from %s",
9692 sockunion2str(&path->peer->su,
9693 buf,
9694 SU_ADDRSTRLEN));
d62a17ae 9695 }
d62a17ae 9696
05864da7 9697 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 9698 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
9699 else
9700 vty_out(vty, " (%s)",
9701 inet_ntop(AF_INET,
9702 &path->peer->remote_id, buf1,
9703 sizeof(buf1)));
d62a17ae 9704 }
05864da7 9705 }
9df8b37c 9706
05864da7
DS
9707 /*
9708 * Note when vrfid of nexthop is different from that of prefix
9709 */
9710 if (path->extra && path->extra->bgp_orig) {
9711 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9712
05864da7
DS
9713 if (json_paths) {
9714 const char *vn;
9df8b37c 9715
05864da7
DS
9716 if (path->extra->bgp_orig->inst_type
9717 == BGP_INSTANCE_TYPE_DEFAULT)
9718 vn = VRF_DEFAULT_NAME;
9719 else
9720 vn = path->extra->bgp_orig->name;
9df8b37c 9721
05864da7 9722 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 9723
05864da7
DS
9724 if (nexthop_vrfid == VRF_UNKNOWN) {
9725 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 9726 } else {
05864da7
DS
9727 json_object_int_add(json_path, "nhVrfId",
9728 (int)nexthop_vrfid);
9df8b37c 9729 }
05864da7
DS
9730 } else {
9731 if (nexthop_vrfid == VRF_UNKNOWN)
9732 vty_out(vty, " vrf ?");
137147c6
DS
9733 else {
9734 struct vrf *vrf;
9735
9736 vrf = vrf_lookup_by_id(nexthop_vrfid);
9737 vty_out(vty, " vrf %s(%u)",
9738 VRF_LOGNAME(vrf), nexthop_vrfid);
9739 }
9df8b37c 9740 }
05864da7 9741 }
9df8b37c 9742
05864da7
DS
9743 if (nexthop_self) {
9744 if (json_paths) {
9745 json_object_boolean_true_add(json_path,
9746 "announceNexthopSelf");
9747 } else {
9748 vty_out(vty, " announce-nh-self");
9df8b37c 9749 }
05864da7 9750 }
9df8b37c 9751
05864da7
DS
9752 if (!json_paths)
9753 vty_out(vty, "\n");
d62a17ae 9754
05864da7
DS
9755 /* display the link-local nexthop */
9756 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9757 if (json_paths) {
9758 json_nexthop_ll = json_object_new_object();
9759 json_object_string_add(
515c2602
DA
9760 json_nexthop_ll, "ip",
9761 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9762 buf, INET6_ADDRSTRLEN));
9763
939a97f4 9764 if (path->peer->hostname)
515c2602
DA
9765 json_object_string_add(json_nexthop_ll,
9766 "hostname",
939a97f4 9767 path->peer->hostname);
515c2602 9768
05864da7
DS
9769 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
9770 json_object_string_add(json_nexthop_ll, "scope",
9771 "link-local");
d62a17ae 9772
05864da7
DS
9773 json_object_boolean_true_add(json_nexthop_ll,
9774 "accessible");
d62a17ae 9775
05864da7 9776 if (!attr->mp_nexthop_prefer_global)
d62a17ae 9777 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
9778 "used");
9779 else
9780 json_object_boolean_true_add(
9781 json_nexthop_global, "used");
9782 } else {
9783 vty_out(vty, " (%s) %s\n",
9784 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9785 buf, INET6_ADDRSTRLEN),
9786 attr->mp_nexthop_prefer_global
9787 ? "(prefer-global)"
9788 : "(used)");
d62a17ae 9789 }
05864da7
DS
9790 }
9791 /* If we do not have a link-local nexthop then we must flag the
9792 global as "used" */
9793 else {
9794 if (json_paths)
9795 json_object_boolean_true_add(json_nexthop_global,
9796 "used");
9797 }
d62a17ae 9798
b5e140c8 9799 if (safi == SAFI_EVPN &&
5e4d4c8a
AK
9800 bgp_evpn_is_esi_valid(&attr->esi)) {
9801 route_vty_out_detail_es_info(vty, attr, json_path);
b5e140c8
AK
9802 }
9803
05864da7
DS
9804 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
9805 * Int/Ext/Local, Atomic, best */
9806 if (json_paths)
9807 json_object_string_add(json_path, "origin",
9808 bgp_origin_long_str[attr->origin]);
9809 else
9810 vty_out(vty, " Origin %s",
9811 bgp_origin_long_str[attr->origin]);
9df8b37c 9812
05864da7 9813 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 9814 if (json_paths)
05864da7 9815 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 9816 else
05864da7
DS
9817 vty_out(vty, ", metric %u", attr->med);
9818 }
9df8b37c 9819
05864da7
DS
9820 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
9821 if (json_paths)
0fbac0b4 9822 json_object_int_add(json_path, "locPrf",
05864da7
DS
9823 attr->local_pref);
9824 else
9825 vty_out(vty, ", localpref %u", attr->local_pref);
9826 }
9df8b37c 9827
05864da7
DS
9828 if (attr->weight != 0) {
9829 if (json_paths)
9830 json_object_int_add(json_path, "weight", attr->weight);
9831 else
9832 vty_out(vty, ", weight %u", attr->weight);
9833 }
9df8b37c 9834
05864da7
DS
9835 if (attr->tag != 0) {
9836 if (json_paths)
9837 json_object_int_add(json_path, "tag", attr->tag);
9838 else
9839 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
9840 }
9df8b37c 9841
05864da7
DS
9842 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9843 if (json_paths)
9844 json_object_boolean_false_add(json_path, "valid");
9845 else
9846 vty_out(vty, ", invalid");
9847 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9848 if (json_paths)
9849 json_object_boolean_true_add(json_path, "valid");
9850 else
9851 vty_out(vty, ", valid");
9852 }
9df8b37c 9853
05864da7
DS
9854 if (path->peer != bgp->peer_self) {
9855 if (path->peer->as == path->peer->local_as) {
9856 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
9857 if (json_paths)
9858 json_object_string_add(
9859 json_peer, "type",
9860 "confed-internal");
d62a17ae 9861 else
05864da7 9862 vty_out(vty, ", confed-internal");
d62a17ae 9863 } else {
05864da7
DS
9864 if (json_paths)
9865 json_object_string_add(
9866 json_peer, "type", "internal");
9867 else
9868 vty_out(vty, ", internal");
9df8b37c 9869 }
05864da7
DS
9870 } else {
9871 if (bgp_confederation_peers_check(bgp,
9872 path->peer->as)) {
9873 if (json_paths)
9874 json_object_string_add(
9875 json_peer, "type",
9876 "confed-external");
d62a17ae 9877 else
05864da7 9878 vty_out(vty, ", confed-external");
d62a17ae 9879 } else {
05864da7
DS
9880 if (json_paths)
9881 json_object_string_add(
9882 json_peer, "type", "external");
9883 else
9884 vty_out(vty, ", external");
d62a17ae 9885 }
9886 }
05864da7
DS
9887 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
9888 if (json_paths) {
9889 json_object_boolean_true_add(json_path, "aggregated");
9890 json_object_boolean_true_add(json_path, "local");
9891 } else {
9892 vty_out(vty, ", aggregated, local");
9893 }
9894 } else if (path->type != ZEBRA_ROUTE_BGP) {
9895 if (json_paths)
9896 json_object_boolean_true_add(json_path, "sourced");
9897 else
9898 vty_out(vty, ", sourced");
9899 } else {
9900 if (json_paths) {
9901 json_object_boolean_true_add(json_path, "sourced");
9902 json_object_boolean_true_add(json_path, "local");
9903 } else {
9904 vty_out(vty, ", sourced, local");
d62a17ae 9905 }
05864da7 9906 }
718e3744 9907
05864da7 9908 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 9909 if (json_paths)
05864da7
DS
9910 json_object_boolean_true_add(json_path,
9911 "atomicAggregate");
d62a17ae 9912 else
05864da7
DS
9913 vty_out(vty, ", atomic-aggregate");
9914 }
d62a17ae 9915
05864da7
DS
9916 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
9917 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
9918 && bgp_path_info_mpath_count(path))) {
9919 if (json_paths)
9920 json_object_boolean_true_add(json_path, "multipath");
9921 else
9922 vty_out(vty, ", multipath");
9923 }
50e05855 9924
05864da7
DS
9925 // Mark the bestpath(s)
9926 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
9927 first_as = aspath_get_first_as(attr->aspath);
718e3744 9928
05864da7
DS
9929 if (json_paths) {
9930 if (!json_bestpath)
9931 json_bestpath = json_object_new_object();
9932 json_object_int_add(json_bestpath, "bestpathFromAs",
9933 first_as);
9934 } else {
9935 if (first_as)
9936 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 9937 else
05864da7 9938 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 9939 }
05864da7 9940 }
718e3744 9941
05864da7
DS
9942 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
9943 if (json_paths) {
9944 if (!json_bestpath)
9945 json_bestpath = json_object_new_object();
9946 json_object_boolean_true_add(json_bestpath, "overall");
9947 json_object_string_add(
9948 json_bestpath, "selectionReason",
9949 bgp_path_selection_reason2str(bn->reason));
9950 } else {
9951 vty_out(vty, ", best");
9952 vty_out(vty, " (%s)",
9953 bgp_path_selection_reason2str(bn->reason));
d62a17ae 9954 }
05864da7 9955 }
718e3744 9956
05864da7
DS
9957 if (json_bestpath)
9958 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 9959
05864da7
DS
9960 if (!json_paths)
9961 vty_out(vty, "\n");
9962
9963 /* Line 4 display Community */
9964 if (attr->community) {
9965 if (json_paths) {
9966 if (!attr->community->json)
9967 community_str(attr->community, true);
9968 json_object_lock(attr->community->json);
9969 json_object_object_add(json_path, "community",
9970 attr->community->json);
9971 } else {
9972 vty_out(vty, " Community: %s\n",
9973 attr->community->str);
d62a17ae 9974 }
05864da7 9975 }
718e3744 9976
05864da7
DS
9977 /* Line 5 display Extended-community */
9978 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9979 if (json_paths) {
9980 json_ext_community = json_object_new_object();
9981 json_object_string_add(json_ext_community, "string",
9982 attr->ecommunity->str);
9983 json_object_object_add(json_path, "extendedCommunity",
9984 json_ext_community);
d62a17ae 9985 } else {
05864da7
DS
9986 vty_out(vty, " Extended Community: %s\n",
9987 attr->ecommunity->str);
d62a17ae 9988 }
05864da7 9989 }
718e3744 9990
05864da7
DS
9991 /* Line 6 display Large community */
9992 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
9993 if (json_paths) {
9994 if (!attr->lcommunity->json)
9995 lcommunity_str(attr->lcommunity, true);
9996 json_object_lock(attr->lcommunity->json);
9997 json_object_object_add(json_path, "largeCommunity",
9998 attr->lcommunity->json);
9999 } else {
10000 vty_out(vty, " Large Community: %s\n",
10001 attr->lcommunity->str);
d62a17ae 10002 }
05864da7 10003 }
718e3744 10004
05864da7
DS
10005 /* Line 7 display Originator, Cluster-id */
10006 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10007 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10008 char buf[BUFSIZ] = {0};
10009
05864da7 10010 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10011 if (json_paths)
05864da7
DS
10012 json_object_string_add(
10013 json_path, "originatorId",
23d0a753
DA
10014 inet_ntop(AF_INET, &attr->originator_id,
10015 buf, sizeof(buf)));
d62a17ae 10016 else
23d0a753
DA
10017 vty_out(vty, " Originator: %pI4",
10018 &attr->originator_id);
d62a17ae 10019 }
856ca177 10020
05864da7
DS
10021 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
10022 int i;
d62a17ae 10023
10024 if (json_paths) {
05864da7
DS
10025 json_cluster_list = json_object_new_object();
10026 json_cluster_list_list =
10027 json_object_new_array();
10028
10029 for (i = 0; i < attr->cluster->length / 4;
10030 i++) {
10031 json_string = json_object_new_string(
23d0a753
DA
10032 inet_ntop(
10033 AF_INET,
10034 &attr->cluster->list[i],
10035 buf, sizeof(buf)));
05864da7
DS
10036 json_object_array_add(
10037 json_cluster_list_list,
10038 json_string);
10039 }
718e3744 10040
05864da7
DS
10041 /*
10042 * struct cluster_list does not have
10043 * "str" variable like aspath and community
10044 * do. Add this someday if someone asks
10045 * for it.
10046 * json_object_string_add(json_cluster_list,
10047 * "string", attr->cluster->str);
10048 */
10049 json_object_object_add(json_cluster_list,
10050 "list",
10051 json_cluster_list_list);
10052 json_object_object_add(json_path, "clusterList",
10053 json_cluster_list);
0dc8ee70 10054 } else {
05864da7
DS
10055 vty_out(vty, ", Cluster list: ");
10056
10057 for (i = 0; i < attr->cluster->length / 4;
10058 i++) {
23d0a753
DA
10059 vty_out(vty, "%pI4 ",
10060 &attr->cluster->list[i]);
05864da7 10061 }
0dc8ee70 10062 }
d62a17ae 10063 }
718e3744 10064
d62a17ae 10065 if (!json_paths)
10066 vty_out(vty, "\n");
05864da7 10067 }
d62a17ae 10068
05864da7 10069 if (path->extra && path->extra->damp_info)
a935f597 10070 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10071
05864da7
DS
10072 /* Remote Label */
10073 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10074 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10075 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 10076
05864da7
DS
10077 if (json_paths)
10078 json_object_int_add(json_path, "remoteLabel", label);
10079 else
10080 vty_out(vty, " Remote label: %d\n", label);
10081 }
d62a17ae 10082
e496b420
HS
10083 /* Remote SID */
10084 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
10085 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
10086 if (json_paths)
10087 json_object_string_add(json_path, "remoteSid", buf);
10088 else
10089 vty_out(vty, " Remote SID: %s\n", buf);
10090 }
10091
05864da7
DS
10092 /* Label Index */
10093 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10094 if (json_paths)
10095 json_object_int_add(json_path, "labelIndex",
10096 attr->label_index);
10097 else
10098 vty_out(vty, " Label Index: %d\n",
10099 attr->label_index);
10100 }
d62a17ae 10101
05864da7
DS
10102 /* Line 8 display Addpath IDs */
10103 if (path->addpath_rx_id
10104 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10105 if (json_paths) {
10106 json_object_int_add(json_path, "addpathRxId",
10107 path->addpath_rx_id);
d62a17ae 10108
05864da7
DS
10109 /* Keep backwards compatibility with the old API
10110 * by putting TX All's ID in the old field
10111 */
10112 json_object_int_add(
10113 json_path, "addpathTxId",
10114 path->tx_addpath
10115 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10116
05864da7
DS
10117 /* ... but create a specific field for each
10118 * strategy
10119 */
10120 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10121 json_object_int_add(
10122 json_path,
10123 bgp_addpath_names(i)->id_json_name,
10124 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10125 }
05864da7
DS
10126 } else {
10127 vty_out(vty, " AddPath ID: RX %u, ",
10128 path->addpath_rx_id);
d62a17ae 10129
05864da7 10130 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10131 }
05864da7 10132 }
520d5d76 10133
05864da7
DS
10134 /* If we used addpath to TX a non-bestpath we need to display
10135 * "Advertised to" on a path-by-path basis
10136 */
10137 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10138 first = 1;
dcc68b5e 10139
05864da7
DS
10140 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10141 addpath_capable =
10142 bgp_addpath_encode_tx(peer, afi, safi);
10143 has_adj = bgp_adj_out_lookup(
10144 peer, path->net,
10145 bgp_addpath_id_for_peer(peer, afi, safi,
10146 &path->tx_addpath));
10147
10148 if ((addpath_capable && has_adj)
10149 || (!addpath_capable && has_adj
10150 && CHECK_FLAG(path->flags,
10151 BGP_PATH_SELECTED))) {
10152 if (json_path && !json_adv_to)
10153 json_adv_to = json_object_new_object();
dcc68b5e 10154
05864da7
DS
10155 route_vty_out_advertised_to(
10156 vty, peer, &first,
10157 " Advertised to:", json_adv_to);
d62a17ae 10158 }
10159 }
718e3744 10160
05864da7
DS
10161 if (json_path) {
10162 if (json_adv_to) {
10163 json_object_object_add(
10164 json_path, "advertisedTo", json_adv_to);
d62a17ae 10165 }
05864da7
DS
10166 } else {
10167 if (!first) {
10168 vty_out(vty, "\n");
d62a17ae 10169 }
10170 }
05864da7 10171 }
b05a1c8b 10172
05864da7
DS
10173 /* Line 9 display Uptime */
10174 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10175 if (json_paths) {
10176 json_last_update = json_object_new_object();
10177 json_object_int_add(json_last_update, "epoch", tbuf);
10178 json_object_string_add(json_last_update, "string",
10179 ctime(&tbuf));
10180 json_object_object_add(json_path, "lastUpdate",
10181 json_last_update);
10182 } else
10183 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10184
05864da7
DS
10185 /* Line 10 display PMSI tunnel attribute, if present */
10186 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
10187 const char *str =
10188 lookup_msg(bgp_pmsi_tnltype_str, attr->pmsi_tnl_type,
10189 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10190
05864da7
DS
10191 if (json_paths) {
10192 json_pmsi = json_object_new_object();
10193 json_object_string_add(json_pmsi, "tunnelType", str);
10194 json_object_int_add(json_pmsi, "label",
10195 label2vni(&attr->label));
10196 json_object_object_add(json_path, "pmsi", json_pmsi);
10197 } else
10198 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10199 str, label2vni(&attr->label));
d62a17ae 10200 }
f1aa5d8a 10201
d62a17ae 10202 /* We've constructed the json object for this path, add it to the json
10203 * array of paths
10204 */
10205 if (json_paths) {
10206 if (json_nexthop_global || json_nexthop_ll) {
10207 json_nexthops = json_object_new_array();
f1aa5d8a 10208
d62a17ae 10209 if (json_nexthop_global)
10210 json_object_array_add(json_nexthops,
10211 json_nexthop_global);
f1aa5d8a 10212
d62a17ae 10213 if (json_nexthop_ll)
10214 json_object_array_add(json_nexthops,
10215 json_nexthop_ll);
f1aa5d8a 10216
d62a17ae 10217 json_object_object_add(json_path, "nexthops",
10218 json_nexthops);
10219 }
10220
10221 json_object_object_add(json_path, "peer", json_peer);
10222 json_object_array_add(json_paths, json_path);
05864da7 10223 }
b366b518
BB
10224}
10225
96ade3ed 10226#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10227#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10228#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10229
d62a17ae 10230static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10231 const char *prefix_list_str, afi_t afi,
10232 safi_t safi, enum bgp_show_type type);
10233static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10234 const char *filter, afi_t afi, safi_t safi,
10235 enum bgp_show_type type);
10236static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10237 const char *rmap_str, afi_t afi, safi_t safi,
10238 enum bgp_show_type type);
10239static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10240 const char *com, int exact, afi_t afi,
10241 safi_t safi);
10242static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10243 const char *prefix, afi_t afi, safi_t safi,
10244 enum bgp_show_type type);
a4d82a8a 10245static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10246 afi_t afi, safi_t safi, enum bgp_show_type type,
10247 bool use_json);
7f323236
DW
10248static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10249 const char *comstr, int exact, afi_t afi,
96f3485c 10250 safi_t safi, uint8_t show_flags);
d62a17ae 10251
1ae44dfc
LB
10252
10253static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10254 struct bgp_table *table, enum bgp_show_type type,
96f3485c
MK
10255 void *output_arg, char *rd, int is_last,
10256 unsigned long *output_cum, unsigned long *total_cum,
10257 unsigned long *json_header_depth, uint8_t show_flags)
d62a17ae 10258{
40381db7 10259 struct bgp_path_info *pi;
9bcb3eef 10260 struct bgp_dest *dest;
d62a17ae 10261 int header = 1;
10262 int display;
1ae44dfc
LB
10263 unsigned long output_count = 0;
10264 unsigned long total_count = 0;
d62a17ae 10265 struct prefix *p;
d62a17ae 10266 json_object *json_paths = NULL;
10267 int first = 1;
96f3485c
MK
10268 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10269 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10270 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10271
1ae44dfc
LB
10272 if (output_cum && *output_cum != 0)
10273 header = 0;
10274
9386b588 10275 if (use_json && !*json_header_depth) {
96f3485c
MK
10276 if (all)
10277 *json_header_depth = 1;
10278 else {
10279 vty_out(vty, "{\n");
10280 *json_header_depth = 2;
10281 }
10282
d62a17ae 10283 vty_out(vty,
23d0a753
DA
10284 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10285 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10286 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10287 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10288 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10289 ? VRF_DEFAULT_NAME
10290 : bgp->name,
10291 table->version, &bgp->router_id,
01eced22 10292 bgp->default_local_pref, bgp->as);
9386b588 10293 if (rd) {
445c2480 10294 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10295 ++*json_header_depth;
10296 }
d62a17ae 10297 }
718e3744 10298
445c2480
DS
10299 if (use_json && rd) {
10300 vty_out(vty, " \"%s\" : { ", rd);
10301 }
10302
d62a17ae 10303 /* Start processing of routes. */
9bcb3eef
DS
10304 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10305 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10306
9bcb3eef 10307 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10308 if (pi == NULL)
98ce9a06 10309 continue;
d62a17ae 10310
98ce9a06 10311 display = 0;
98ce9a06
DS
10312 if (use_json)
10313 json_paths = json_object_new_array();
10314 else
10315 json_paths = NULL;
d62a17ae 10316
6f94b685 10317 for (; pi; pi = pi->next) {
98ce9a06
DS
10318 total_count++;
10319 if (type == bgp_show_type_flap_statistics
10320 || type == bgp_show_type_flap_neighbor
10321 || type == bgp_show_type_dampend_paths
10322 || type == bgp_show_type_damp_neighbor) {
40381db7 10323 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10324 continue;
10325 }
10326 if (type == bgp_show_type_regexp) {
10327 regex_t *regex = output_arg;
d62a17ae 10328
40381db7 10329 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10330 == REG_NOMATCH)
10331 continue;
10332 }
10333 if (type == bgp_show_type_prefix_list) {
10334 struct prefix_list *plist = output_arg;
d62a17ae 10335
9bcb3eef 10336 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10337 != PREFIX_PERMIT)
10338 continue;
10339 }
10340 if (type == bgp_show_type_filter_list) {
10341 struct as_list *as_list = output_arg;
d62a17ae 10342
40381db7 10343 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
10344 != AS_FILTER_PERMIT)
10345 continue;
10346 }
10347 if (type == bgp_show_type_route_map) {
10348 struct route_map *rmap = output_arg;
9b6d8fcf 10349 struct bgp_path_info path;
98ce9a06 10350 struct attr dummy_attr;
b68885f9 10351 route_map_result_t ret;
d62a17ae 10352
6f4f49b2 10353 dummy_attr = *pi->attr;
d62a17ae 10354
40381db7 10355 path.peer = pi->peer;
9b6d8fcf 10356 path.attr = &dummy_attr;
d62a17ae 10357
9bcb3eef 10358 ret = route_map_apply(rmap, dest_p, RMAP_BGP,
9b6d8fcf 10359 &path);
98ce9a06
DS
10360 if (ret == RMAP_DENYMATCH)
10361 continue;
10362 }
10363 if (type == bgp_show_type_neighbor
10364 || type == bgp_show_type_flap_neighbor
10365 || type == bgp_show_type_damp_neighbor) {
10366 union sockunion *su = output_arg;
10367
40381db7
DS
10368 if (pi->peer == NULL
10369 || pi->peer->su_remote == NULL
10370 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
10371 continue;
10372 }
10373 if (type == bgp_show_type_cidr_only) {
d7c0a89a 10374 uint32_t destination;
d62a17ae 10375
9bcb3eef 10376 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 10377 if (IN_CLASSC(destination)
9bcb3eef 10378 && dest_p->prefixlen == 24)
98ce9a06
DS
10379 continue;
10380 if (IN_CLASSB(destination)
9bcb3eef 10381 && dest_p->prefixlen == 16)
98ce9a06
DS
10382 continue;
10383 if (IN_CLASSA(destination)
9bcb3eef 10384 && dest_p->prefixlen == 8)
98ce9a06
DS
10385 continue;
10386 }
10387 if (type == bgp_show_type_prefix_longer) {
f7813c7c 10388 p = output_arg;
9bcb3eef 10389 if (!prefix_match(p, dest_p))
98ce9a06
DS
10390 continue;
10391 }
10392 if (type == bgp_show_type_community_all) {
40381db7 10393 if (!pi->attr->community)
98ce9a06
DS
10394 continue;
10395 }
10396 if (type == bgp_show_type_community) {
10397 struct community *com = output_arg;
d62a17ae 10398
40381db7
DS
10399 if (!pi->attr->community
10400 || !community_match(pi->attr->community,
98ce9a06
DS
10401 com))
10402 continue;
10403 }
10404 if (type == bgp_show_type_community_exact) {
10405 struct community *com = output_arg;
d62a17ae 10406
40381db7
DS
10407 if (!pi->attr->community
10408 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
10409 continue;
10410 }
10411 if (type == bgp_show_type_community_list) {
10412 struct community_list *list = output_arg;
d62a17ae 10413
40381db7 10414 if (!community_list_match(pi->attr->community,
a4d82a8a 10415 list))
98ce9a06
DS
10416 continue;
10417 }
a4d82a8a 10418 if (type == bgp_show_type_community_list_exact) {
98ce9a06 10419 struct community_list *list = output_arg;
d62a17ae 10420
98ce9a06 10421 if (!community_list_exact_match(
40381db7 10422 pi->attr->community, list))
98ce9a06
DS
10423 continue;
10424 }
10425 if (type == bgp_show_type_lcommunity) {
10426 struct lcommunity *lcom = output_arg;
d62a17ae 10427
40381db7
DS
10428 if (!pi->attr->lcommunity
10429 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
10430 lcom))
10431 continue;
10432 }
36a206db 10433
10434 if (type == bgp_show_type_lcommunity_exact) {
10435 struct lcommunity *lcom = output_arg;
10436
10437 if (!pi->attr->lcommunity
10438 || !lcommunity_cmp(pi->attr->lcommunity,
10439 lcom))
10440 continue;
10441 }
98ce9a06
DS
10442 if (type == bgp_show_type_lcommunity_list) {
10443 struct community_list *list = output_arg;
d62a17ae 10444
40381db7 10445 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 10446 list))
98ce9a06
DS
10447 continue;
10448 }
36a206db 10449 if (type
10450 == bgp_show_type_lcommunity_list_exact) {
10451 struct community_list *list = output_arg;
10452
10453 if (!lcommunity_list_exact_match(
10454 pi->attr->lcommunity, list))
10455 continue;
10456 }
98ce9a06 10457 if (type == bgp_show_type_lcommunity_all) {
40381db7 10458 if (!pi->attr->lcommunity)
98ce9a06
DS
10459 continue;
10460 }
10461 if (type == bgp_show_type_dampend_paths
10462 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
10463 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
10464 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
10465 continue;
10466 }
10467
10468 if (!use_json && header) {
23d0a753
DA
10469 vty_out(vty,
10470 "BGP table version is %" PRIu64
10471 ", local router ID is %pI4, vrf id ",
10472 table->version, &bgp->router_id);
9df8b37c
PZ
10473 if (bgp->vrf_id == VRF_UNKNOWN)
10474 vty_out(vty, "%s", VRFID_NONE_STR);
10475 else
10476 vty_out(vty, "%u", bgp->vrf_id);
10477 vty_out(vty, "\n");
01eced22
AD
10478 vty_out(vty, "Default local pref %u, ",
10479 bgp->default_local_pref);
10480 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 10481 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10482 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 10483 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 10484 if (type == bgp_show_type_dampend_paths
10485 || type == bgp_show_type_damp_neighbor)
98ce9a06 10486 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
10487 else if (type == bgp_show_type_flap_statistics
10488 || type == bgp_show_type_flap_neighbor)
98ce9a06 10489 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 10490 else
ae248832
MK
10491 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
10492 : BGP_SHOW_HEADER));
98ce9a06 10493 header = 0;
d62a17ae 10494 }
98ce9a06
DS
10495 if (rd != NULL && !display && !output_count) {
10496 if (!use_json)
10497 vty_out(vty,
10498 "Route Distinguisher: %s\n",
10499 rd);
d62a17ae 10500 }
98ce9a06
DS
10501 if (type == bgp_show_type_dampend_paths
10502 || type == bgp_show_type_damp_neighbor)
9bcb3eef 10503 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10504 AFI_IP, safi, use_json,
10505 json_paths);
98ce9a06
DS
10506 else if (type == bgp_show_type_flap_statistics
10507 || type == bgp_show_type_flap_neighbor)
9bcb3eef 10508 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10509 AFI_IP, safi, use_json,
10510 json_paths);
98ce9a06 10511 else
9bcb3eef 10512 route_vty_out(vty, dest_p, pi, display, safi,
ae248832 10513 json_paths, wide);
98ce9a06 10514 display++;
d62a17ae 10515 }
10516
98ce9a06
DS
10517 if (display) {
10518 output_count++;
10519 if (!use_json)
10520 continue;
10521
625d2931 10522 /* encode prefix */
9bcb3eef 10523 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
10524 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
10525
1840384b 10526
b54892e0
DS
10527 bgp_fs_nlri_get_string(
10528 (unsigned char *)
9bcb3eef
DS
10529 dest_p->u.prefix_flowspec.ptr,
10530 dest_p->u.prefix_flowspec.prefixlen,
1840384b 10531 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
10532 family2afi(dest_p->u
10533 .prefix_flowspec.family));
625d2931 10534 if (first)
b54892e0 10535 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 10536 dest_p->u.prefix_flowspec
b54892e0 10537 .prefixlen);
625d2931 10538 else
b54892e0 10539 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 10540 dest_p->u.prefix_flowspec
b54892e0 10541 .prefixlen);
625d2931 10542 } else {
625d2931 10543 if (first)
1b78780b 10544 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 10545 else
1b78780b 10546 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 10547 }
98ce9a06 10548 vty_out(vty, "%s",
f4ec52f7
DA
10549 json_object_to_json_string_ext(
10550 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 10551 json_object_free(json_paths);
449feb8e 10552 json_paths = NULL;
98ce9a06 10553 first = 0;
1f83ed02
DS
10554 } else
10555 json_object_free(json_paths);
98ce9a06
DS
10556 }
10557
1ae44dfc
LB
10558 if (output_cum) {
10559 output_count += *output_cum;
10560 *output_cum = output_count;
10561 }
10562 if (total_cum) {
10563 total_count += *total_cum;
10564 *total_cum = total_count;
10565 }
d62a17ae 10566 if (use_json) {
9386b588 10567 if (rd) {
a4d82a8a 10568 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
10569 }
10570 if (is_last) {
a4d82a8a
PZ
10571 unsigned long i;
10572 for (i = 0; i < *json_header_depth; ++i)
10573 vty_out(vty, " } ");
96f3485c
MK
10574 if (!all)
10575 vty_out(vty, "\n");
9386b588 10576 }
d62a17ae 10577 } else {
1ae44dfc
LB
10578 if (is_last) {
10579 /* No route is displayed */
10580 if (output_count == 0) {
10581 if (type == bgp_show_type_normal)
10582 vty_out(vty,
10583 "No BGP prefixes displayed, %ld exist\n",
10584 total_count);
10585 } else
d62a17ae 10586 vty_out(vty,
1ae44dfc
LB
10587 "\nDisplayed %ld routes and %ld total paths\n",
10588 output_count, total_count);
10589 }
d62a17ae 10590 }
718e3744 10591
d62a17ae 10592 return CMD_SUCCESS;
718e3744 10593}
10594
1ae44dfc
LB
10595int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
10596 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 10597 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 10598{
9bcb3eef 10599 struct bgp_dest *dest, *next;
1ae44dfc
LB
10600 unsigned long output_cum = 0;
10601 unsigned long total_cum = 0;
9386b588 10602 unsigned long json_header_depth = 0;
67009e22 10603 struct bgp_table *itable;
0136788c 10604 bool show_msg;
96f3485c 10605 uint8_t show_flags = 0;
0136788c
LB
10606
10607 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 10608
96f3485c
MK
10609 if (use_json)
10610 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10611
9bcb3eef
DS
10612 for (dest = bgp_table_top(table); dest; dest = next) {
10613 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10614
9bcb3eef
DS
10615 next = bgp_route_next(dest);
10616 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 10617 continue;
67009e22 10618
9bcb3eef 10619 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 10620 if (itable != NULL) {
1ae44dfc 10621 struct prefix_rd prd;
06b9f471 10622 char rd[RD_ADDRSTRLEN];
1ae44dfc 10623
9bcb3eef 10624 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 10625 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 10626 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
10627 rd, next == NULL, &output_cum,
10628 &total_cum, &json_header_depth,
10629 show_flags);
0136788c
LB
10630 if (next == NULL)
10631 show_msg = false;
1ae44dfc
LB
10632 }
10633 }
0136788c
LB
10634 if (show_msg) {
10635 if (output_cum == 0)
10636 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
10637 total_cum);
10638 else
10639 vty_out(vty,
10640 "\nDisplayed %ld routes and %ld total paths\n",
10641 output_cum, total_cum);
10642 }
1ae44dfc
LB
10643 return CMD_SUCCESS;
10644}
d62a17ae 10645static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c
MK
10646 enum bgp_show_type type, void *output_arg,
10647 uint8_t show_flags)
fee0f4c6 10648{
d62a17ae 10649 struct bgp_table *table;
9386b588 10650 unsigned long json_header_depth = 0;
96f3485c 10651 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 10652
d62a17ae 10653 if (bgp == NULL) {
10654 bgp = bgp_get_default();
10655 }
fee0f4c6 10656
d62a17ae 10657 if (bgp == NULL) {
10658 if (!use_json)
10659 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10660 else
10661 vty_out(vty, "{}\n");
d62a17ae 10662 return CMD_WARNING;
10663 }
4dd6177e 10664
1ae44dfc 10665 table = bgp->rib[afi][safi];
d62a17ae 10666 /* use MPLS and ENCAP specific shows until they are merged */
10667 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
10668 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
10669 output_arg, use_json);
d62a17ae 10670 }
dba3c1d3
PG
10671
10672 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
10673 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
10674 output_arg, use_json,
10675 1, NULL, NULL);
10676 }
d62a17ae 10677 /* labeled-unicast routes live in the unicast table */
10678 else if (safi == SAFI_LABELED_UNICAST)
10679 safi = SAFI_UNICAST;
fee0f4c6 10680
96f3485c
MK
10681 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
10682 NULL, NULL, &json_header_depth, show_flags);
fee0f4c6 10683}
10684
d62a17ae 10685static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96f3485c 10686 safi_t safi, uint8_t show_flags)
f186de26 10687{
d62a17ae 10688 struct listnode *node, *nnode;
10689 struct bgp *bgp;
10690 int is_first = 1;
9f049418 10691 bool route_output = false;
96f3485c 10692 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 10693
d62a17ae 10694 if (use_json)
10695 vty_out(vty, "{\n");
9f689658 10696
d62a17ae 10697 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 10698 route_output = true;
d62a17ae 10699 if (use_json) {
10700 if (!is_first)
10701 vty_out(vty, ",\n");
10702 else
10703 is_first = 0;
10704
10705 vty_out(vty, "\"%s\":",
10706 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10707 ? VRF_DEFAULT_NAME
d62a17ae 10708 : bgp->name);
10709 } else {
10710 vty_out(vty, "\nInstance %s:\n",
10711 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10712 ? VRF_DEFAULT_NAME
d62a17ae 10713 : bgp->name);
10714 }
10715 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
96f3485c 10716 show_flags);
d62a17ae 10717 }
9f689658 10718
d62a17ae 10719 if (use_json)
10720 vty_out(vty, "}\n");
9f049418
DS
10721 else if (!route_output)
10722 vty_out(vty, "%% BGP instance not found\n");
f186de26 10723}
10724
718e3744 10725/* Header of detailed BGP route information */
d62a17ae 10726void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9bcb3eef 10727 struct bgp_dest *dest, struct prefix_rd *prd,
d62a17ae 10728 afi_t afi, safi_t safi, json_object *json)
10729{
40381db7 10730 struct bgp_path_info *pi;
b54892e0 10731 const struct prefix *p;
d62a17ae 10732 struct peer *peer;
10733 struct listnode *node, *nnode;
06b9f471 10734 char buf1[RD_ADDRSTRLEN];
0291c246 10735 char prefix_str[BUFSIZ];
d62a17ae 10736 int count = 0;
10737 int best = 0;
10738 int suppress = 0;
c5f1e1b2
C
10739 int accept_own = 0;
10740 int route_filter_translated_v4 = 0;
10741 int route_filter_v4 = 0;
10742 int route_filter_translated_v6 = 0;
10743 int route_filter_v6 = 0;
10744 int llgr_stale = 0;
10745 int no_llgr = 0;
10746 int accept_own_nexthop = 0;
10747 int blackhole = 0;
d62a17ae 10748 int no_export = 0;
10749 int no_advertise = 0;
10750 int local_as = 0;
c5f1e1b2 10751 int no_peer = 0;
d62a17ae 10752 int first = 1;
10753 int has_valid_label = 0;
10754 mpls_label_t label = 0;
10755 json_object *json_adv_to = NULL;
9bedbb1e 10756
9bcb3eef
DS
10757 p = bgp_dest_get_prefix(dest);
10758 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 10759
10760 if (has_valid_label)
9bcb3eef 10761 label = label_pton(&dest->local_label);
d62a17ae 10762
44c69747 10763 if (safi == SAFI_EVPN) {
d62a17ae 10764
44c69747 10765 if (!json) {
2dbe669b 10766 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 10767 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 10768 : "",
2dbe669b 10769 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
10770 } else {
10771 json_object_string_add(json, "rd",
10772 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
10773 "");
10774 bgp_evpn_route2json((struct prefix_evpn *)p, json);
10775 }
10776 } else {
10777 if (!json) {
8228a9a7 10778 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
d62a17ae 10779 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
10780 ? prefix_rd2str(prd, buf1,
10781 sizeof(buf1))
10782 : ""),
10783 safi == SAFI_MPLS_VPN ? ":" : "", p);
cd1964ff 10784
44c69747
LK
10785 } else
10786 json_object_string_add(json, "prefix",
10787 prefix2str(p, prefix_str, sizeof(prefix_str)));
10788 }
10789
10790 if (has_valid_label) {
10791 if (json)
10792 json_object_int_add(json, "localLabel", label);
10793 else
d62a17ae 10794 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
10795 }
10796
10797 if (!json)
d62a17ae 10798 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 10799 vty_out(vty, "not allocated\n");
718e3744 10800
9bcb3eef 10801 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 10802 count++;
40381db7 10803 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 10804 best = count;
4056a5f6 10805 if (bgp_path_suppressed(pi))
d62a17ae 10806 suppress = 1;
cee9c031 10807
40381db7 10808 if (pi->attr->community == NULL)
cee9c031
QY
10809 continue;
10810
10811 no_advertise += community_include(
40381db7
DS
10812 pi->attr->community, COMMUNITY_NO_ADVERTISE);
10813 no_export += community_include(pi->attr->community,
cee9c031 10814 COMMUNITY_NO_EXPORT);
40381db7 10815 local_as += community_include(pi->attr->community,
cee9c031 10816 COMMUNITY_LOCAL_AS);
40381db7 10817 accept_own += community_include(pi->attr->community,
cee9c031
QY
10818 COMMUNITY_ACCEPT_OWN);
10819 route_filter_translated_v4 += community_include(
40381db7 10820 pi->attr->community,
cee9c031
QY
10821 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
10822 route_filter_translated_v6 += community_include(
40381db7 10823 pi->attr->community,
cee9c031
QY
10824 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
10825 route_filter_v4 += community_include(
40381db7 10826 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 10827 route_filter_v6 += community_include(
40381db7
DS
10828 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
10829 llgr_stale += community_include(pi->attr->community,
cee9c031 10830 COMMUNITY_LLGR_STALE);
40381db7 10831 no_llgr += community_include(pi->attr->community,
cee9c031
QY
10832 COMMUNITY_NO_LLGR);
10833 accept_own_nexthop +=
40381db7 10834 community_include(pi->attr->community,
cee9c031 10835 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 10836 blackhole += community_include(pi->attr->community,
cee9c031 10837 COMMUNITY_BLACKHOLE);
40381db7 10838 no_peer += community_include(pi->attr->community,
cee9c031 10839 COMMUNITY_NO_PEER);
d62a17ae 10840 }
718e3744 10841 }
718e3744 10842
d62a17ae 10843 if (!json) {
10844 vty_out(vty, "Paths: (%d available", count);
10845 if (best) {
10846 vty_out(vty, ", best #%d", best);
b84060bb
PG
10847 if (safi == SAFI_UNICAST) {
10848 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
10849 vty_out(vty, ", table %s",
10850 VRF_DEFAULT_NAME);
10851 else
10852 vty_out(vty, ", vrf %s",
10853 bgp->name);
10854 }
d62a17ae 10855 } else
10856 vty_out(vty, ", no best path");
10857
c5f1e1b2
C
10858 if (accept_own)
10859 vty_out(vty,
10860 ", accept own local route exported and imported in different VRF");
10861 else if (route_filter_translated_v4)
10862 vty_out(vty,
10863 ", mark translated RTs for VPNv4 route filtering");
10864 else if (route_filter_v4)
10865 vty_out(vty,
10866 ", attach RT as-is for VPNv4 route filtering");
10867 else if (route_filter_translated_v6)
10868 vty_out(vty,
10869 ", mark translated RTs for VPNv6 route filtering");
10870 else if (route_filter_v6)
10871 vty_out(vty,
10872 ", attach RT as-is for VPNv6 route filtering");
10873 else if (llgr_stale)
10874 vty_out(vty,
10875 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
10876 else if (no_llgr)
10877 vty_out(vty,
10878 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
10879 else if (accept_own_nexthop)
10880 vty_out(vty,
10881 ", accept local nexthop");
10882 else if (blackhole)
10883 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 10884 else if (no_export)
10885 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
10886 else if (no_advertise)
10887 vty_out(vty, ", not advertised to any peer");
d62a17ae 10888 else if (local_as)
10889 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
10890 else if (no_peer)
10891 vty_out(vty,
10892 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 10893
10894 if (suppress)
10895 vty_out(vty,
10896 ", Advertisements suppressed by an aggregate.");
10897 vty_out(vty, ")\n");
10898 }
718e3744 10899
d62a17ae 10900 /* If we are not using addpath then we can display Advertised to and
10901 * that will
10902 * show what peers we advertised the bestpath to. If we are using
10903 * addpath
10904 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 10905 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 10906 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 10907 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 10908 if (json && !json_adv_to)
10909 json_adv_to = json_object_new_object();
10910
10911 route_vty_out_advertised_to(
10912 vty, peer, &first,
10913 " Advertised to non peer-group peers:\n ",
10914 json_adv_to);
10915 }
10916 }
10917
10918 if (json) {
10919 if (json_adv_to) {
10920 json_object_object_add(json, "advertisedTo",
10921 json_adv_to);
10922 }
10923 } else {
10924 if (first)
10925 vty_out(vty, " Not advertised to any peer");
10926 vty_out(vty, "\n");
10927 }
10928 }
718e3744 10929}
10930
44c69747 10931static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9bcb3eef
DS
10932 struct bgp_dest *bgp_node, struct vty *vty,
10933 struct bgp *bgp, afi_t afi, safi_t safi,
10934 json_object *json, enum bgp_path_type pathtype,
10935 int *display)
44c69747
LK
10936{
10937 struct bgp_path_info *pi;
10938 int header = 1;
10939 char rdbuf[RD_ADDRSTRLEN];
10940 json_object *json_header = NULL;
10941 json_object *json_paths = NULL;
10942
9bcb3eef 10943 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
44c69747
LK
10944
10945 if (json && !json_paths) {
10946 /* Instantiate json_paths only if path is valid */
10947 json_paths = json_object_new_array();
10948 if (pfx_rd) {
10949 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
10950 json_header = json_object_new_object();
10951 } else
10952 json_header = json;
10953 }
10954
10955 if (header) {
10956 route_vty_out_detail_header(
10957 vty, bgp, bgp_node, pfx_rd,
10958 AFI_IP, safi, json_header);
10959 header = 0;
10960 }
10961 (*display)++;
10962
10963 if (pathtype == BGP_PATH_SHOW_ALL
10964 || (pathtype == BGP_PATH_SHOW_BESTPATH
10965 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
10966 || (pathtype == BGP_PATH_SHOW_MULTIPATH
10967 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
10968 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
10969 route_vty_out_detail(vty, bgp, bgp_node,
10970 pi, AFI_IP, safi,
10971 json_paths);
10972 }
10973
10974 if (json && json_paths) {
10975 json_object_object_add(json_header, "paths", json_paths);
10976
10977 if (pfx_rd)
10978 json_object_object_add(json, rdbuf, json_header);
10979 }
10980}
10981
718e3744 10982/* Display specified route of BGP table. */
d62a17ae 10983static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
10984 struct bgp_table *rib, const char *ip_str,
10985 afi_t afi, safi_t safi,
10986 struct prefix_rd *prd, int prefix_check,
9f049418 10987 enum bgp_path_type pathtype, bool use_json)
d62a17ae 10988{
10989 int ret;
d62a17ae 10990 int display = 0;
10991 struct prefix match;
9bcb3eef
DS
10992 struct bgp_dest *dest;
10993 struct bgp_dest *rm;
d62a17ae 10994 struct bgp_table *table;
10995 json_object *json = NULL;
10996 json_object *json_paths = NULL;
10997
10998 /* Check IP address argument. */
10999 ret = str2prefix(ip_str, &match);
11000 if (!ret) {
11001 vty_out(vty, "address is malformed\n");
11002 return CMD_WARNING;
11003 }
718e3744 11004
d62a17ae 11005 match.family = afi2family(afi);
b05a1c8b 11006
44c69747 11007 if (use_json)
d62a17ae 11008 json = json_object_new_object();
718e3744 11009
44c69747 11010 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11011 for (dest = bgp_table_top(rib); dest;
11012 dest = bgp_route_next(dest)) {
11013 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11014
9bcb3eef 11015 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11016 continue;
9bcb3eef 11017 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11018 if (!table)
ea47320b 11019 continue;
d62a17ae 11020
ea47320b
DL
11021 if ((rm = bgp_node_match(table, &match)) == NULL)
11022 continue;
d62a17ae 11023
9bcb3eef 11024 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11025 if (prefix_check
b54892e0 11026 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11027 bgp_dest_unlock_node(rm);
ea47320b
DL
11028 continue;
11029 }
d62a17ae 11030
9bcb3eef 11031 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
11032 bgp, afi, safi, json, pathtype,
11033 &display);
44c69747 11034
9bcb3eef 11035 bgp_dest_unlock_node(rm);
44c69747
LK
11036 }
11037 } else if (safi == SAFI_EVPN) {
9bcb3eef 11038 struct bgp_dest *longest_pfx;
cded3b72 11039 bool is_exact_pfxlen_match = false;
44c69747 11040
9bcb3eef
DS
11041 for (dest = bgp_table_top(rib); dest;
11042 dest = bgp_route_next(dest)) {
11043 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11044
9bcb3eef 11045 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11046 continue;
9bcb3eef 11047 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11048 if (!table)
11049 continue;
11050
11051 longest_pfx = NULL;
cded3b72 11052 is_exact_pfxlen_match = false;
44c69747
LK
11053 /*
11054 * Search through all the prefixes for a match. The
11055 * pfx's are enumerated in ascending order of pfxlens.
11056 * So, the last pfx match is the longest match. Set
11057 * is_exact_pfxlen_match when we get exact pfxlen match
11058 */
11059 for (rm = bgp_table_top(table); rm;
11060 rm = bgp_route_next(rm)) {
b54892e0 11061 const struct prefix *rm_p =
9bcb3eef 11062 bgp_dest_get_prefix(rm);
44c69747
LK
11063 /*
11064 * Get prefixlen of the ip-prefix within type5
11065 * evpn route
11066 */
b54892e0
DS
11067 if (evpn_type5_prefix_match(rm_p, &match)
11068 && rm->info) {
44c69747
LK
11069 longest_pfx = rm;
11070 int type5_pfxlen =
b54892e0
DS
11071 bgp_evpn_get_type5_prefixlen(
11072 rm_p);
44c69747 11073 if (type5_pfxlen == match.prefixlen) {
cded3b72 11074 is_exact_pfxlen_match = true;
9bcb3eef 11075 bgp_dest_unlock_node(rm);
44c69747
LK
11076 break;
11077 }
d62a17ae 11078 }
11079 }
ea47320b 11080
44c69747
LK
11081 if (!longest_pfx)
11082 continue;
11083
11084 if (prefix_check && !is_exact_pfxlen_match)
11085 continue;
11086
11087 rm = longest_pfx;
9bcb3eef 11088 bgp_dest_lock_node(rm);
44c69747 11089
9bcb3eef 11090 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
11091 bgp, afi, safi, json, pathtype,
11092 &display);
44c69747 11093
9bcb3eef 11094 bgp_dest_unlock_node(rm);
d62a17ae 11095 }
98a9dbc7 11096 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11097 if (use_json)
11098 json_paths = json_object_new_array();
11099
63a0b7a9
PG
11100 display = bgp_flowspec_display_match_per_ip(afi, rib,
11101 &match, prefix_check,
11102 vty,
11103 use_json,
11104 json_paths);
44c69747
LK
11105 if (use_json && display)
11106 json_object_object_add(json, "paths", json_paths);
d62a17ae 11107 } else {
9bcb3eef
DS
11108 if ((dest = bgp_node_match(rib, &match)) != NULL) {
11109 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11110 if (!prefix_check
9bcb3eef
DS
11111 || dest_p->prefixlen == match.prefixlen) {
11112 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11113 safi, json, pathtype,
11114 &display);
d62a17ae 11115 }
11116
9bcb3eef 11117 bgp_dest_unlock_node(dest);
d62a17ae 11118 }
11119 }
e5eee9af 11120
d62a17ae 11121 if (use_json) {
996c9314 11122 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
11123 json, JSON_C_TO_STRING_PRETTY |
11124 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 11125 json_object_free(json);
11126 } else {
11127 if (!display) {
11128 vty_out(vty, "%% Network not in table\n");
11129 return CMD_WARNING;
11130 }
11131 }
b05a1c8b 11132
d62a17ae 11133 return CMD_SUCCESS;
718e3744 11134}
11135
fee0f4c6 11136/* Display specified route of Main RIB */
d62a17ae 11137static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11138 afi_t afi, safi_t safi, struct prefix_rd *prd,
11139 int prefix_check, enum bgp_path_type pathtype,
9f049418 11140 bool use_json)
d62a17ae 11141{
9b86009a 11142 if (!bgp) {
d62a17ae 11143 bgp = bgp_get_default();
9b86009a
RW
11144 if (!bgp) {
11145 if (!use_json)
11146 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11147 else
11148 vty_out(vty, "{}\n");
9b86009a
RW
11149 return CMD_WARNING;
11150 }
11151 }
d62a17ae 11152
11153 /* labeled-unicast routes live in the unicast table */
11154 if (safi == SAFI_LABELED_UNICAST)
11155 safi = SAFI_UNICAST;
11156
11157 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
11158 afi, safi, prd, prefix_check, pathtype,
11159 use_json);
11160}
11161
11162static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11163 struct cmd_token **argv, bool exact, afi_t afi,
11164 safi_t safi, bool uj)
d62a17ae 11165{
11166 struct lcommunity *lcom;
11167 struct buffer *b;
11168 int i;
11169 char *str;
11170 int first = 0;
96f3485c
MK
11171 uint8_t show_flags = 0;
11172
11173 if (uj)
11174 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11175
11176 b = buffer_new(1024);
11177 for (i = 0; i < argc; i++) {
11178 if (first)
11179 buffer_putc(b, ' ');
11180 else {
11181 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11182 first = 1;
11183 buffer_putstr(b, argv[i]->arg);
11184 }
11185 }
11186 }
11187 buffer_putc(b, '\0');
57d187bc 11188
d62a17ae 11189 str = buffer_getstr(b);
11190 buffer_free(b);
57d187bc 11191
d62a17ae 11192 lcom = lcommunity_str2com(str);
11193 XFREE(MTYPE_TMP, str);
11194 if (!lcom) {
11195 vty_out(vty, "%% Large-community malformed\n");
11196 return CMD_WARNING;
11197 }
57d187bc 11198
36a206db 11199 return bgp_show(vty, bgp, afi, safi,
11200 (exact ? bgp_show_type_lcommunity_exact
ae248832 11201 : bgp_show_type_lcommunity),
96f3485c 11202 lcom, show_flags);
57d187bc
JS
11203}
11204
d62a17ae 11205static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11206 const char *lcom, bool exact, afi_t afi,
11207 safi_t safi, bool uj)
57d187bc 11208{
d62a17ae 11209 struct community_list *list;
96f3485c
MK
11210 uint8_t show_flags = 0;
11211
11212 if (uj)
11213 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11214
57d187bc 11215
e237b0d2 11216 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11217 LARGE_COMMUNITY_LIST_MASTER);
11218 if (list == NULL) {
11219 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11220 lcom);
11221 return CMD_WARNING;
11222 }
57d187bc 11223
36a206db 11224 return bgp_show(vty, bgp, afi, safi,
11225 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11226 : bgp_show_type_lcommunity_list),
96f3485c 11227 list, show_flags);
fee0f4c6 11228}
11229
52951b63
DS
11230DEFUN (show_ip_bgp_large_community_list,
11231 show_ip_bgp_large_community_list_cmd,
36a206db 11232 "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
11233 SHOW_STR
11234 IP_STR
11235 BGP_STR
11236 BGP_INSTANCE_HELP_STR
9bedbb1e 11237 BGP_AFI_HELP_STR
4dd6177e 11238 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11239 "Display routes matching the large-community-list\n"
11240 "large-community-list number\n"
11241 "large-community-list name\n"
36a206db 11242 "Exact match of the large-communities\n"
52951b63
DS
11243 JSON_STR)
11244{
d62a17ae 11245 afi_t afi = AFI_IP6;
11246 safi_t safi = SAFI_UNICAST;
11247 int idx = 0;
36a206db 11248 bool exact_match = 0;
4d678463 11249 struct bgp *bgp = NULL;
9f049418 11250 bool uj = use_json(argc, argv);
d62a17ae 11251
4d678463
KA
11252 if (uj)
11253 argc--;
11254
11255 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11256 &bgp, uj);
11257 if (!idx)
11258 return CMD_WARNING;
d62a17ae 11259
11260 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11261
11262 const char *clist_number_or_name = argv[++idx]->arg;
11263
11264 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11265 exact_match = 1;
11266
11267 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11268 exact_match, afi, safi, uj);
52951b63
DS
11269}
11270DEFUN (show_ip_bgp_large_community,
11271 show_ip_bgp_large_community_cmd,
36a206db 11272 "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
11273 SHOW_STR
11274 IP_STR
11275 BGP_STR
11276 BGP_INSTANCE_HELP_STR
9bedbb1e 11277 BGP_AFI_HELP_STR
4dd6177e 11278 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11279 "Display routes matching the large-communities\n"
11280 "List of large-community numbers\n"
36a206db 11281 "Exact match of the large-communities\n"
52951b63
DS
11282 JSON_STR)
11283{
d62a17ae 11284 afi_t afi = AFI_IP6;
11285 safi_t safi = SAFI_UNICAST;
11286 int idx = 0;
36a206db 11287 bool exact_match = 0;
4d678463 11288 struct bgp *bgp = NULL;
9f049418 11289 bool uj = use_json(argc, argv);
96f3485c 11290 uint8_t show_flags = 0;
d62a17ae 11291
96f3485c
MK
11292 if (uj) {
11293 argc--;
11294 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11295 }
4d678463 11296
96f3485c
MK
11297 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11298 &bgp, uj);
11299 if (!idx)
11300 return CMD_WARNING;
d62a17ae 11301
36a206db 11302 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11303 if (argv_find(argv, argc, "exact-match", &idx))
11304 exact_match = 1;
11305 return bgp_show_lcommunity(vty, bgp, argc, argv,
11306 exact_match, afi, safi, uj);
11307 } else
d62a17ae 11308 return bgp_show(vty, bgp, afi, safi,
96f3485c 11309 bgp_show_type_lcommunity_all, NULL, show_flags);
52951b63
DS
11310}
11311
71f1613a
DA
11312static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11313 safi_t safi, struct json_object *json_array);
d62a17ae 11314static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 11315 safi_t safi, struct json_object *json);
e01ca200 11316
7b2ff250 11317
9ab0cf58
PG
11318DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11319 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11320 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11321 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
11322{
11323 bool uj = use_json(argc, argv);
11324 struct bgp *bgp = NULL;
ec76a1d1
DA
11325 safi_t safi = SAFI_UNICAST;
11326 afi_t afi = AFI_IP6;
4265b261 11327 int idx = 0;
6c9d22e2
PG
11328 struct json_object *json_all = NULL;
11329 struct json_object *json_afi_safi = NULL;
4265b261
PG
11330
11331 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11332 &bgp, false);
71f1613a 11333 if (!idx)
4265b261 11334 return CMD_WARNING;
6c9d22e2 11335
4265b261 11336 if (uj)
6c9d22e2 11337 json_all = json_object_new_object();
4265b261 11338
9ab0cf58
PG
11339 FOREACH_AFI_SAFI (afi, safi) {
11340 /*
11341 * So limit output to those afi/safi pairs that
11342 * actually have something interesting in them
11343 */
11344 if (strmatch(get_afi_safi_str(afi, safi, true),
11345 "Unknown")) {
11346 continue;
11347 }
11348 if (uj) {
11349 json_afi_safi = json_object_new_array();
11350 json_object_object_add(
11351 json_all,
11352 get_afi_safi_str(afi, safi, true),
11353 json_afi_safi);
11354 } else {
11355 json_afi_safi = NULL;
6c9d22e2 11356 }
9ab0cf58
PG
11357
11358 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 11359 }
6c9d22e2
PG
11360
11361 if (uj) {
9ab0cf58
PG
11362 vty_out(vty, "%s",
11363 json_object_to_json_string_ext(
11364 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 11365 json_object_free(json_all);
4265b261 11366 }
6c9d22e2 11367
4265b261
PG
11368 return CMD_SUCCESS;
11369}
11370
7b2ff250 11371/* BGP route print out function without JSON */
14718643
PG
11372DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
11373 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 11374 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
11375 SHOW_STR
11376 IP_STR
11377 BGP_STR
11378 BGP_INSTANCE_HELP_STR
11379 L2VPN_HELP_STR
11380 EVPN_HELP_STR
11381 "BGP RIB advertisement statistics\n"
11382 JSON_STR)
11383{
ec76a1d1
DA
11384 afi_t afi = AFI_IP6;
11385 safi_t safi = SAFI_UNICAST;
14718643
PG
11386 struct bgp *bgp = NULL;
11387 int idx = 0, ret;
11388 bool uj = use_json(argc, argv);
11389 struct json_object *json_afi_safi = NULL, *json = NULL;
11390
11391 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11392 &bgp, false);
11393 if (!idx)
11394 return CMD_WARNING;
11395
11396 if (uj)
11397 json_afi_safi = json_object_new_array();
11398 else
11399 json_afi_safi = NULL;
11400
11401 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11402
11403 if (uj) {
11404 json = json_object_new_object();
11405 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11406 json_afi_safi);
11407 vty_out(vty, "%s", json_object_to_json_string_ext(
11408 json, JSON_C_TO_STRING_PRETTY));
11409 json_object_free(json);
11410 }
11411 return ret;
11412}
11413
893cccd0 11414/* BGP route print out function without JSON */
9ab0cf58
PG
11415DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
11416 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11417 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11418 "]]\
893cccd0 11419 statistics [json]",
9ab0cf58
PG
11420 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11421 BGP_SAFI_WITH_LABEL_HELP_STR
11422 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 11423{
ec76a1d1
DA
11424 afi_t afi = AFI_IP6;
11425 safi_t safi = SAFI_UNICAST;
893cccd0
PG
11426 struct bgp *bgp = NULL;
11427 int idx = 0, ret;
11428 bool uj = use_json(argc, argv);
6c9d22e2 11429 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
11430
11431 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11432 &bgp, false);
11433 if (!idx)
11434 return CMD_WARNING;
6c9d22e2 11435
893cccd0 11436 if (uj)
6c9d22e2
PG
11437 json_afi_safi = json_object_new_array();
11438 else
11439 json_afi_safi = NULL;
11440
11441 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11442
11443 if (uj) {
11444 json = json_object_new_object();
11445 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11446 json_afi_safi);
9ab0cf58
PG
11447 vty_out(vty, "%s",
11448 json_object_to_json_string_ext(
11449 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
11450 json_object_free(json);
11451 }
11452 return ret;
893cccd0 11453}
7b2ff250
DW
11454
11455/* BGP route print out function without JSON */
96f3485c 11456DEFPY(show_ip_bgp, show_ip_bgp_cmd,
9ab0cf58
PG
11457 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11458 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11459 "]]\
96f3485c 11460 <[all$all] dampening <parameters>\
7b2ff250
DW
11461 |route-map WORD\
11462 |prefix-list WORD\
11463 |filter-list WORD\
7b2ff250
DW
11464 |community-list <(1-500)|WORD> [exact-match]\
11465 |A.B.C.D/M longer-prefixes\
11466 |X:X::X:X/M longer-prefixes\
893cccd0 11467 >",
9ab0cf58
PG
11468 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11469 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11470 "Display the entries for all address families\n"
9ab0cf58
PG
11471 "Display detailed information about dampening\n"
11472 "Display detail of configured dampening parameters\n"
11473 "Display routes matching the route-map\n"
11474 "A route-map to match on\n"
11475 "Display routes conforming to the prefix-list\n"
11476 "Prefix-list name\n"
11477 "Display routes conforming to the filter-list\n"
11478 "Regular expression access list name\n"
11479 "Display routes matching the community-list\n"
11480 "community-list number\n"
11481 "community-list name\n"
11482 "Exact match of the communities\n"
11483 "IPv4 prefix\n"
11484 "Display route and more specific routes\n"
11485 "IPv6 prefix\n"
11486 "Display route and more specific routes\n")
718e3744 11487{
d62a17ae 11488 afi_t afi = AFI_IP6;
11489 safi_t safi = SAFI_UNICAST;
11490 int exact_match = 0;
d62a17ae 11491 struct bgp *bgp = NULL;
11492 int idx = 0;
96f3485c
MK
11493 uint8_t show_flags = 0;
11494
11495 /* [<ipv4|ipv6> [all]] */
11496 if (all) {
11497 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11498 if (argv_find(argv, argc, "ipv4", &idx))
11499 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11500
11501 if (argv_find(argv, argc, "ipv6", &idx))
11502 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11503 }
d62a17ae 11504
11505 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11506 &bgp, false);
d62a17ae 11507 if (!idx)
11508 return CMD_WARNING;
11509
d62a17ae 11510 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 11511 if (argv_find(argv, argc, "parameters", &idx))
96f3485c
MK
11512 return bgp_show_dampening_parameters(vty, afi, safi,
11513 show_flags);
d62a17ae 11514 }
c016b6c7 11515
d62a17ae 11516 if (argv_find(argv, argc, "prefix-list", &idx))
11517 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
11518 safi, bgp_show_type_prefix_list);
11519
11520 if (argv_find(argv, argc, "filter-list", &idx))
11521 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
11522 safi, bgp_show_type_filter_list);
11523
d62a17ae 11524 if (argv_find(argv, argc, "route-map", &idx))
11525 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
11526 safi, bgp_show_type_route_map);
11527
d62a17ae 11528 if (argv_find(argv, argc, "community-list", &idx)) {
11529 const char *clist_number_or_name = argv[++idx]->arg;
11530 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11531 exact_match = 1;
11532 return bgp_show_community_list(vty, bgp, clist_number_or_name,
11533 exact_match, afi, safi);
11534 }
11535 /* prefix-longer */
11536 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11537 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11538 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
11539 safi,
11540 bgp_show_type_prefix_longer);
11541
7b2ff250
DW
11542 return CMD_WARNING;
11543}
11544
11545/* BGP route print out function with JSON */
ae248832 11546DEFPY (show_ip_bgp_json,
7b2ff250
DW
11547 show_ip_bgp_json_cmd,
11548 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
96f3485c 11549 [all$all]\
cf4898bc
QY
11550 [cidr-only\
11551 |dampening <flap-statistics|dampened-paths>\
11552 |community [AA:NN|local-AS|no-advertise|no-export\
11553 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11554 |accept-own|accept-own-nexthop|route-filter-v6\
11555 |route-filter-v4|route-filter-translated-v6\
11556 |route-filter-translated-v4] [exact-match]\
ae248832 11557 ] [json$uj | wide$wide]",
7b2ff250
DW
11558 SHOW_STR
11559 IP_STR
11560 BGP_STR
11561 BGP_INSTANCE_HELP_STR
11562 BGP_AFI_HELP_STR
11563 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11564 "Display the entries for all address families\n"
7b2ff250
DW
11565 "Display only routes with non-natural netmasks\n"
11566 "Display detailed information about dampening\n"
11567 "Display flap statistics of routes\n"
11568 "Display paths suppressed due to dampening\n"
11569 "Display routes matching the communities\n"
d0086e8e
AD
11570 COMMUNITY_AANN_STR
11571 "Do not send outside local AS (well-known community)\n"
11572 "Do not advertise to any peer (well-known community)\n"
11573 "Do not export to next AS (well-known community)\n"
11574 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
11575 "Do not export to any peer (well-known community)\n"
11576 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11577 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11578 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11579 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11580 "Should accept VPN route with local nexthop (well-known community)\n"
11581 "RT VPNv6 route filtering (well-known community)\n"
11582 "RT VPNv4 route filtering (well-known community)\n"
11583 "RT translated VPNv6 route filtering (well-known community)\n"
11584 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 11585 "Exact match of the communities\n"
ae248832
MK
11586 JSON_STR
11587 "Increase table width for longer prefixes\n")
7b2ff250
DW
11588{
11589 afi_t afi = AFI_IP6;
11590 safi_t safi = SAFI_UNICAST;
11591 enum bgp_show_type sh_type = bgp_show_type_normal;
11592 struct bgp *bgp = NULL;
11593 int idx = 0;
d0086e8e 11594 int exact_match = 0;
96f3485c
MK
11595 char *community = NULL;
11596 bool first = true;
11597 uint8_t show_flags = 0;
9f049418 11598
96f3485c
MK
11599
11600 if (uj) {
9f049418 11601 argc--;
96f3485c
MK
11602 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11603 }
11604
11605 /* [<ipv4|ipv6> [all]] */
11606 if (all) {
11607 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11608
11609 if (argv_find(argv, argc, "ipv4", &idx))
11610 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11611
11612 if (argv_find(argv, argc, "ipv6", &idx))
11613 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11614 }
11615
11616 if (wide)
11617 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
11618
11619 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11620 &bgp, uj);
7b2ff250
DW
11621 if (!idx)
11622 return CMD_WARNING;
11623
7b2ff250 11624 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 11625 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
11626
11627 if (argv_find(argv, argc, "dampening", &idx)) {
11628 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 11629 sh_type = bgp_show_type_dampend_paths;
7b2ff250 11630 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 11631 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
11632 }
11633
11634 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 11635 char *maybecomm = NULL;
d0086e8e 11636
79bc257a
RW
11637 if (idx + 1 < argc) {
11638 if (argv[idx + 1]->type == VARIABLE_TKN)
11639 maybecomm = argv[idx + 1]->arg;
11640 else
11641 maybecomm = argv[idx + 1]->text;
11642 }
11643
cf4898bc
QY
11644 if (maybecomm && !strmatch(maybecomm, "json")
11645 && !strmatch(maybecomm, "exact-match"))
11646 community = maybecomm;
d0086e8e 11647
cf4898bc
QY
11648 if (argv_find(argv, argc, "exact-match", &idx))
11649 exact_match = 1;
d0086e8e 11650
96f3485c
MK
11651 if (!community)
11652 sh_type = bgp_show_type_community_all;
11653 }
11654
11655 if (!all) {
11656 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
11657 if (community)
11658 return bgp_show_community(vty, bgp, community,
96f3485c
MK
11659 exact_match, afi, safi,
11660 show_flags);
cf4898bc 11661 else
96f3485c
MK
11662 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
11663 show_flags);
11664 } else {
11665 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
11666 * AFI_IP6 */
11667
11668 if (uj)
11669 vty_out(vty, "{\n");
11670
11671 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11672 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
11673 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11674 ? AFI_IP
11675 : AFI_IP6;
11676 FOREACH_SAFI (safi) {
11677 if (strmatch(get_afi_safi_str(afi, safi, true),
11678 "Unknown"))
11679 continue;
11680
11681 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11682 continue;
11683
11684 if (uj) {
11685 if (first)
11686 first = false;
11687 else
11688 vty_out(vty, ",\n");
11689 vty_out(vty, "\"%s\":{\n",
11690 get_afi_safi_str(afi, safi,
11691 true));
11692 } else
11693 vty_out(vty,
11694 "\nFor address family: %s\n",
11695 get_afi_safi_str(afi, safi,
11696 false));
11697
11698 if (community)
11699 bgp_show_community(vty, bgp, community,
11700 exact_match, afi,
11701 safi, show_flags);
11702 else
11703 bgp_show(vty, bgp, afi, safi, sh_type,
11704 NULL, show_flags);
11705 if (uj)
11706 vty_out(vty, "}\n");
11707 }
11708 } else {
11709 /* show <ip> bgp all: for each AFI and SAFI*/
11710 FOREACH_AFI_SAFI (afi, safi) {
11711 if (strmatch(get_afi_safi_str(afi, safi, true),
11712 "Unknown"))
11713 continue;
11714
11715 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11716 continue;
11717
11718 if (uj) {
11719 if (first)
11720 first = false;
11721 else
11722 vty_out(vty, ",\n");
d0086e8e 11723
96f3485c
MK
11724 vty_out(vty, "\"%s\":{\n",
11725 get_afi_safi_str(afi, safi,
11726 true));
11727 } else
11728 vty_out(vty,
11729 "\nFor address family: %s\n",
11730 get_afi_safi_str(afi, safi,
11731 false));
11732
11733 if (community)
11734 bgp_show_community(vty, bgp, community,
11735 exact_match, afi,
11736 safi, show_flags);
11737 else
11738 bgp_show(vty, bgp, afi, safi, sh_type,
11739 NULL, show_flags);
11740 if (uj)
11741 vty_out(vty, "}\n");
11742 }
11743 }
11744 if (uj)
11745 vty_out(vty, "}\n");
11746 }
11747 return CMD_SUCCESS;
a636c635 11748}
47fc97cc 11749
718e3744 11750DEFUN (show_ip_bgp_route,
11751 show_ip_bgp_route_cmd,
3efd0893 11752 "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 11753 SHOW_STR
11754 IP_STR
11755 BGP_STR
a636c635 11756 BGP_INSTANCE_HELP_STR
4f280b15 11757 BGP_AFI_HELP_STR
4dd6177e 11758 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 11759 "Network in the BGP routing table to display\n"
0c7b1b01 11760 "IPv4 prefix\n"
8c3deaae 11761 "Network in the BGP routing table to display\n"
0c7b1b01 11762 "IPv6 prefix\n"
4092b06c 11763 "Display only the bestpath\n"
b05a1c8b 11764 "Display only multipaths\n"
9973d184 11765 JSON_STR)
4092b06c 11766{
d62a17ae 11767 int prefix_check = 0;
ae19d7dd 11768
d62a17ae 11769 afi_t afi = AFI_IP6;
11770 safi_t safi = SAFI_UNICAST;
11771 char *prefix = NULL;
11772 struct bgp *bgp = NULL;
11773 enum bgp_path_type path_type;
9f049418 11774 bool uj = use_json(argc, argv);
b05a1c8b 11775
d62a17ae 11776 int idx = 0;
ae19d7dd 11777
d62a17ae 11778 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11779 &bgp, uj);
d62a17ae 11780 if (!idx)
11781 return CMD_WARNING;
c41247f5 11782
d62a17ae 11783 if (!bgp) {
11784 vty_out(vty,
11785 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
11786 return CMD_WARNING;
11787 }
a636c635 11788
d62a17ae 11789 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
11790 if (argv_find(argv, argc, "A.B.C.D", &idx)
11791 || argv_find(argv, argc, "X:X::X:X", &idx))
11792 prefix_check = 0;
11793 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11794 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11795 prefix_check = 1;
11796
11797 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
11798 && afi != AFI_IP6) {
11799 vty_out(vty,
11800 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
11801 return CMD_WARNING;
11802 }
11803 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
11804 && afi != AFI_IP) {
11805 vty_out(vty,
11806 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
11807 return CMD_WARNING;
11808 }
11809
11810 prefix = argv[idx]->arg;
11811
11812 /* [<bestpath|multipath>] */
11813 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 11814 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 11815 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 11816 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 11817 else
360660c6 11818 path_type = BGP_PATH_SHOW_ALL;
a636c635 11819
d62a17ae 11820 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
11821 path_type, uj);
4092b06c
DS
11822}
11823
8c3deaae
QY
11824DEFUN (show_ip_bgp_regexp,
11825 show_ip_bgp_regexp_cmd,
3e5b31b3 11826 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
11827 SHOW_STR
11828 IP_STR
11829 BGP_STR
b00b230a 11830 BGP_INSTANCE_HELP_STR
4f280b15 11831 BGP_AFI_HELP_STR
4dd6177e 11832 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 11833 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
11834 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
11835 JSON_STR)
8c3deaae 11836{
d62a17ae 11837 afi_t afi = AFI_IP6;
11838 safi_t safi = SAFI_UNICAST;
11839 struct bgp *bgp = NULL;
3e5b31b3
DA
11840 bool uj = use_json(argc, argv);
11841 char *regstr = NULL;
8c3deaae 11842
d62a17ae 11843 int idx = 0;
11844 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11845 &bgp, false);
d62a17ae 11846 if (!idx)
11847 return CMD_WARNING;
8c3deaae 11848
d62a17ae 11849 // get index of regex
3e5b31b3
DA
11850 if (argv_find(argv, argc, "REGEX", &idx))
11851 regstr = argv[idx]->arg;
8c3deaae 11852
5f71d11c 11853 assert(regstr);
3e5b31b3
DA
11854 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
11855 bgp_show_type_regexp, uj);
8c3deaae
QY
11856}
11857
ae248832 11858DEFPY (show_ip_bgp_instance_all,
a636c635 11859 show_ip_bgp_instance_all_cmd,
ae248832 11860 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 11861 SHOW_STR
a636c635 11862 IP_STR
4092b06c 11863 BGP_STR
a636c635 11864 BGP_INSTANCE_ALL_HELP_STR
4f280b15 11865 BGP_AFI_HELP_STR
4dd6177e 11866 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
11867 JSON_STR
11868 "Increase table width for longer prefixes\n")
4092b06c 11869{
d62a17ae 11870 afi_t afi = AFI_IP;
11871 safi_t safi = SAFI_UNICAST;
11872 struct bgp *bgp = NULL;
d62a17ae 11873 int idx = 0;
96f3485c 11874 uint8_t show_flags = 0;
ae19d7dd 11875
96f3485c 11876 if (uj) {
d62a17ae 11877 argc--;
96f3485c
MK
11878 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11879 }
11880
11881 if (wide)
11882 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 11883
9f049418
DS
11884 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11885 &bgp, uj);
11886 if (!idx)
11887 return CMD_WARNING;
11888
96f3485c 11889 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 11890 return CMD_SUCCESS;
e3e29b32
LB
11891}
11892
a4d82a8a 11893static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11894 afi_t afi, safi_t safi, enum bgp_show_type type,
11895 bool use_json)
718e3744 11896{
d62a17ae 11897 regex_t *regex;
11898 int rc;
96f3485c
MK
11899 uint8_t show_flags = 0;
11900
11901 if (use_json)
11902 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 11903
c3900853 11904 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 11905 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
11906 regstr);
11907 return CMD_WARNING_CONFIG_FAILED;
11908 }
11909
d62a17ae 11910 regex = bgp_regcomp(regstr);
11911 if (!regex) {
11912 vty_out(vty, "Can't compile regexp %s\n", regstr);
11913 return CMD_WARNING;
11914 }
a636c635 11915
96f3485c 11916 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags);
d62a17ae 11917 bgp_regex_free(regex);
11918 return rc;
e3e29b32
LB
11919}
11920
d62a17ae 11921static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
11922 const char *prefix_list_str, afi_t afi,
11923 safi_t safi, enum bgp_show_type type)
e3e29b32 11924{
d62a17ae 11925 struct prefix_list *plist;
96f3485c 11926 uint8_t show_flags = 0;
718e3744 11927
d62a17ae 11928 plist = prefix_list_lookup(afi, prefix_list_str);
11929 if (plist == NULL) {
11930 vty_out(vty, "%% %s is not a valid prefix-list name\n",
11931 prefix_list_str);
11932 return CMD_WARNING;
11933 }
718e3744 11934
96f3485c 11935 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags);
4092b06c
DS
11936}
11937
d62a17ae 11938static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
11939 const char *filter, afi_t afi, safi_t safi,
11940 enum bgp_show_type type)
4092b06c 11941{
d62a17ae 11942 struct as_list *as_list;
96f3485c 11943 uint8_t show_flags = 0;
718e3744 11944
d62a17ae 11945 as_list = as_list_lookup(filter);
11946 if (as_list == NULL) {
11947 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
11948 filter);
11949 return CMD_WARNING;
11950 }
a636c635 11951
96f3485c 11952 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags);
718e3744 11953}
11954
d62a17ae 11955static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
11956 const char *rmap_str, afi_t afi, safi_t safi,
11957 enum bgp_show_type type)
718e3744 11958{
d62a17ae 11959 struct route_map *rmap;
96f3485c 11960 uint8_t show_flags = 0;
bb46e94f 11961
d62a17ae 11962 rmap = route_map_lookup_by_name(rmap_str);
11963 if (!rmap) {
11964 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
11965 return CMD_WARNING;
11966 }
11967
96f3485c 11968 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags);
d62a17ae 11969}
11970
7f323236
DW
11971static int bgp_show_community(struct vty *vty, struct bgp *bgp,
11972 const char *comstr, int exact, afi_t afi,
96f3485c 11973 safi_t safi, uint8_t show_flags)
d62a17ae 11974{
11975 struct community *com;
d62a17ae 11976 int ret = 0;
11977
7f323236 11978 com = community_str2com(comstr);
d62a17ae 11979 if (!com) {
7f323236 11980 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 11981 return CMD_WARNING;
11982 }
11983
11984 ret = bgp_show(vty, bgp, afi, safi,
11985 (exact ? bgp_show_type_community_exact
11986 : bgp_show_type_community),
96f3485c 11987 com, show_flags);
3c1f53de 11988 community_free(&com);
46c3ce83 11989
d62a17ae 11990 return ret;
718e3744 11991}
11992
d62a17ae 11993static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
11994 const char *com, int exact, afi_t afi,
11995 safi_t safi)
50ef26d4 11996{
d62a17ae 11997 struct community_list *list;
96f3485c 11998 uint8_t show_flags = 0;
50ef26d4 11999
e237b0d2 12000 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 12001 if (list == NULL) {
12002 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12003 return CMD_WARNING;
12004 }
718e3744 12005
d62a17ae 12006 return bgp_show(vty, bgp, afi, safi,
12007 (exact ? bgp_show_type_community_list_exact
12008 : bgp_show_type_community_list),
96f3485c 12009 list, show_flags);
50ef26d4 12010}
12011
d62a17ae 12012static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12013 const char *prefix, afi_t afi, safi_t safi,
12014 enum bgp_show_type type)
718e3744 12015{
d62a17ae 12016 int ret;
12017 struct prefix *p;
96f3485c 12018 uint8_t show_flags = 0;
47fc97cc 12019
d62a17ae 12020 p = prefix_new();
95cbbd2a 12021
d62a17ae 12022 ret = str2prefix(prefix, p);
12023 if (!ret) {
12024 vty_out(vty, "%% Malformed Prefix\n");
12025 return CMD_WARNING;
12026 }
47e9b292 12027
96f3485c 12028 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags);
63265b5c 12029 prefix_free(&p);
d62a17ae 12030 return ret;
12031}
12032
d62a17ae 12033enum bgp_stats {
12034 BGP_STATS_MAXBITLEN = 0,
12035 BGP_STATS_RIB,
12036 BGP_STATS_PREFIXES,
12037 BGP_STATS_TOTPLEN,
12038 BGP_STATS_UNAGGREGATEABLE,
12039 BGP_STATS_MAX_AGGREGATEABLE,
12040 BGP_STATS_AGGREGATES,
12041 BGP_STATS_SPACE,
12042 BGP_STATS_ASPATH_COUNT,
12043 BGP_STATS_ASPATH_MAXHOPS,
12044 BGP_STATS_ASPATH_TOTHOPS,
12045 BGP_STATS_ASPATH_MAXSIZE,
12046 BGP_STATS_ASPATH_TOTSIZE,
12047 BGP_STATS_ASN_HIGHEST,
12048 BGP_STATS_MAX,
a636c635 12049};
2815e61f 12050
9ab0cf58 12051#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12052#define TABLE_STATS_IDX_JSON 1
12053
12054static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12055 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12056 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12057 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12058 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12059 "unaggregateablePrefixes"},
12060 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12061 "maximumAggregateablePrefixes"},
12062 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12063 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12064 [BGP_STATS_SPACE] = {"Address space advertised",
12065 "addressSpaceAdvertised"},
9ab0cf58
PG
12066 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12067 "advertisementsWithPaths"},
12068 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12069 "longestAsPath"},
12070 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12071 "largestAsPath"},
12072 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12073 "averageAsPathLengthHops"},
12074 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12075 "averageAsPathSizeBytes"},
12076 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12077 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12078};
2815e61f 12079
d62a17ae 12080struct bgp_table_stats {
12081 struct bgp_table *table;
12082 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12083 double total_space;
ff7924f6
PJ
12084};
12085
a636c635
DW
12086#if 0
12087#define TALLY_SIGFIG 100000
12088static unsigned long
12089ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 12090{
a636c635
DW
12091 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
12092 unsigned long res = (newtot * TALLY_SIGFIG) / count;
12093 unsigned long ret = newtot / count;
07d0c4ed 12094
a636c635
DW
12095 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
12096 return ret + 1;
12097 else
12098 return ret;
12099}
12100#endif
ff7924f6 12101
9bcb3eef 12102static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12103 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12104{
9bcb3eef 12105 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12106 struct bgp_path_info *pi;
b54892e0 12107 const struct prefix *rn_p;
d62a17ae 12108
9bcb3eef 12109 if (dest == top)
9c14ec72 12110 return;
d62a17ae 12111
9bcb3eef 12112 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12113 return;
d62a17ae 12114
9bcb3eef 12115 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12116 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12117 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12118
a636c635
DW
12119#if 0
12120 ts->counts[BGP_STATS_AVGPLEN]
12121 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
12122 ts->counts[BGP_STATS_AVGPLEN],
b54892e0 12123 rn_p->prefixlen);
a636c635 12124#endif
d62a17ae 12125
9c14ec72 12126 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12127 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12128 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12129
9bcb3eef 12130 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12131 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12132 /* announced address space */
12133 if (space)
b54892e0 12134 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12135 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12136 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12137
9c14ec72 12138
9bcb3eef 12139 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12140 ts->counts[BGP_STATS_RIB]++;
12141
05864da7
DS
12142 if (CHECK_FLAG(pi->attr->flag,
12143 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12144 ts->counts[BGP_STATS_AGGREGATES]++;
12145
12146 /* as-path stats */
05864da7 12147 if (pi->attr->aspath) {
9c14ec72
RW
12148 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12149 unsigned int size = aspath_size(pi->attr->aspath);
12150 as_t highest = aspath_highest(pi->attr->aspath);
12151
12152 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12153
12154 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12155 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12156
12157 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12158 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12159
12160 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12161 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 12162#if 0
07d0c4ed 12163 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
12164 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
12165 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
12166 hops);
12167 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
12168 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
12169 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
12170 size);
12171#endif
9c14ec72
RW
12172 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12173 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12174 }
12175 }
12176}
12177
12178static int bgp_table_stats_walker(struct thread *t)
12179{
9bcb3eef
DS
12180 struct bgp_dest *dest, *ndest;
12181 struct bgp_dest *top;
9c14ec72
RW
12182 struct bgp_table_stats *ts = THREAD_ARG(t);
12183 unsigned int space = 0;
12184
12185 if (!(top = bgp_table_top(ts->table)))
12186 return 0;
12187
12188 switch (ts->table->afi) {
12189 case AFI_IP:
12190 space = IPV4_MAX_BITLEN;
12191 break;
12192 case AFI_IP6:
12193 space = IPV6_MAX_BITLEN;
12194 break;
12195 default:
12196 return 0;
12197 }
12198
12199 ts->counts[BGP_STATS_MAXBITLEN] = space;
12200
9bcb3eef 12201 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12202 if (ts->table->safi == SAFI_MPLS_VPN
12203 || ts->table->safi == SAFI_ENCAP
12204 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12205 struct bgp_table *table;
12206
9bcb3eef 12207 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12208 if (!table)
12209 continue;
12210
12211 top = bgp_table_top(table);
9bcb3eef
DS
12212 for (ndest = bgp_table_top(table); ndest;
12213 ndest = bgp_route_next(ndest))
12214 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12215 } else {
9bcb3eef 12216 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12217 }
12218 }
9c14ec72 12219
d62a17ae 12220 return 0;
2815e61f 12221}
ff7924f6 12222
71f1613a
DA
12223static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12224 struct json_object *json_array)
12225{
12226 struct listnode *node, *nnode;
12227 struct bgp *bgp;
12228
12229 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12230 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12231}
12232
12233static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12234 safi_t safi, struct json_object *json_array)
2815e61f 12235{
d62a17ae 12236 struct bgp_table_stats ts;
12237 unsigned int i;
893cccd0
PG
12238 int ret = CMD_SUCCESS;
12239 char temp_buf[20];
6c9d22e2
PG
12240 struct json_object *json = NULL;
12241
12242 if (json_array)
12243 json = json_object_new_object();
019386c2 12244
d62a17ae 12245 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12246 char warning_msg[50];
12247
12248 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12249 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12250 safi);
6c9d22e2
PG
12251
12252 if (!json)
893cccd0
PG
12253 vty_out(vty, "%s\n", warning_msg);
12254 else
9ab0cf58 12255 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12256
893cccd0
PG
12257 ret = CMD_WARNING;
12258 goto end_table_stats;
d62a17ae 12259 }
019386c2 12260
893cccd0 12261 if (!json)
5290ceab
DA
12262 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12263 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12264 else
12265 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12266
d62a17ae 12267 /* labeled-unicast routes live in the unicast table */
12268 if (safi == SAFI_LABELED_UNICAST)
12269 safi = SAFI_UNICAST;
019386c2 12270
d62a17ae 12271 memset(&ts, 0, sizeof(ts));
12272 ts.table = bgp->rib[afi][safi];
12273 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12274
d62a17ae 12275 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12276 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12277 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12278 continue;
12279
12280 switch (i) {
a636c635
DW
12281#if 0
12282 case BGP_STATS_ASPATH_AVGHOPS:
12283 case BGP_STATS_ASPATH_AVGSIZE:
12284 case BGP_STATS_AVGPLEN:
12285 vty_out (vty, "%-30s: ", table_stats_strs[i]);
12286 vty_out (vty, "%12.2f",
12287 (float)ts.counts[i] / (float)TALLY_SIGFIG);
12288 break;
12289#endif
d62a17ae 12290 case BGP_STATS_ASPATH_TOTHOPS:
12291 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12292 if (!json) {
9ab0cf58
PG
12293 snprintf(
12294 temp_buf, sizeof(temp_buf), "%12.2f",
12295 ts.counts[i]
12296 ? (float)ts.counts[i]
12297 / (float)ts.counts
12298 [BGP_STATS_ASPATH_COUNT]
12299 : 0);
893cccd0 12300 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12301 table_stats_strs[i]
12302 [TABLE_STATS_IDX_VTY],
893cccd0 12303 temp_buf);
9ab0cf58
PG
12304 } else {
12305 json_object_double_add(
12306 json,
12307 table_stats_strs[i]
12308 [TABLE_STATS_IDX_JSON],
12309 ts.counts[i]
12310 ? (double)ts.counts[i]
12311 / (double)ts.counts
d62a17ae 12312 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12313 : 0);
12314 }
d62a17ae 12315 break;
12316 case BGP_STATS_TOTPLEN:
6c9d22e2 12317 if (!json) {
9ab0cf58
PG
12318 snprintf(
12319 temp_buf, sizeof(temp_buf), "%12.2f",
12320 ts.counts[i]
12321 ? (float)ts.counts[i]
12322 / (float)ts.counts
12323 [BGP_STATS_PREFIXES]
12324 : 0);
893cccd0 12325 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12326 table_stats_strs[i]
12327 [TABLE_STATS_IDX_VTY],
893cccd0 12328 temp_buf);
9ab0cf58
PG
12329 } else {
12330 json_object_double_add(
12331 json,
12332 table_stats_strs[i]
12333 [TABLE_STATS_IDX_JSON],
12334 ts.counts[i]
12335 ? (double)ts.counts[i]
12336 / (double)ts.counts
d62a17ae 12337 [BGP_STATS_PREFIXES]
9ab0cf58
PG
12338 : 0);
12339 }
d62a17ae 12340 break;
12341 case BGP_STATS_SPACE:
6c9d22e2
PG
12342 if (!json) {
12343 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12344 ts.total_space);
893cccd0 12345 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
12346 table_stats_strs[i]
12347 [TABLE_STATS_IDX_VTY],
893cccd0 12348 temp_buf);
9ab0cf58
PG
12349 } else {
12350 json_object_double_add(
12351 json,
12352 table_stats_strs[i]
12353 [TABLE_STATS_IDX_JSON],
12354 (double)ts.total_space);
12355 }
8d0ab76d 12356 if (afi == AFI_IP6) {
6c9d22e2
PG
12357 if (!json) {
12358 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12359 "%12g",
12360 ts.total_space
12361 * pow(2.0, -128 + 32));
6c9d22e2
PG
12362 vty_out(vty, "%30s: %s\n",
12363 "/32 equivalent %s\n",
12364 temp_buf);
9ab0cf58
PG
12365 } else {
12366 json_object_double_add(
12367 json, "/32equivalent",
12368 (double)(ts.total_space
12369 * pow(2.0,
12370 -128 + 32)));
12371 }
6c9d22e2
PG
12372 if (!json) {
12373 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12374 "%12g",
12375 ts.total_space
12376 * pow(2.0, -128 + 48));
6c9d22e2
PG
12377 vty_out(vty, "%30s: %s\n",
12378 "/48 equivalent %s\n",
12379 temp_buf);
9ab0cf58
PG
12380 } else {
12381 json_object_double_add(
12382 json, "/48equivalent",
12383 (double)(ts.total_space
12384 * pow(2.0,
12385 -128 + 48)));
12386 }
8d0ab76d 12387 } else {
6c9d22e2
PG
12388 if (!json) {
12389 snprintf(temp_buf, sizeof(temp_buf),
12390 "%12.2f",
9ab0cf58
PG
12391 ts.total_space * 100.
12392 * pow(2.0, -32));
6c9d22e2 12393 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12394 "% announced ", temp_buf);
12395 } else {
12396 json_object_double_add(
12397 json, "%announced",
12398 (double)(ts.total_space * 100.
12399 * pow(2.0, -32)));
12400 }
6c9d22e2
PG
12401 if (!json) {
12402 snprintf(temp_buf, sizeof(temp_buf),
12403 "%12.2f",
9ab0cf58
PG
12404 ts.total_space
12405 * pow(2.0, -32 + 8));
6c9d22e2
PG
12406 vty_out(vty, "%30s: %s\n",
12407 "/8 equivalent ", temp_buf);
9ab0cf58
PG
12408 } else {
12409 json_object_double_add(
12410 json, "/8equivalent",
12411 (double)(ts.total_space
12412 * pow(2.0, -32 + 8)));
12413 }
6c9d22e2
PG
12414 if (!json) {
12415 snprintf(temp_buf, sizeof(temp_buf),
12416 "%12.2f",
9ab0cf58
PG
12417 ts.total_space
12418 * pow(2.0, -32 + 24));
6c9d22e2 12419 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12420 "/24 equivalent ", temp_buf);
12421 } else {
12422 json_object_double_add(
12423 json, "/24equivalent",
12424 (double)(ts.total_space
12425 * pow(2.0, -32 + 24)));
12426 }
8d0ab76d 12427 }
d62a17ae 12428 break;
12429 default:
6c9d22e2
PG
12430 if (!json) {
12431 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
12432 ts.counts[i]);
893cccd0 12433 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12434 table_stats_strs[i]
12435 [TABLE_STATS_IDX_VTY],
12436 temp_buf);
12437 } else {
12438 json_object_int_add(
12439 json,
12440 table_stats_strs[i]
12441 [TABLE_STATS_IDX_JSON],
12442 ts.counts[i]);
12443 }
d62a17ae 12444 }
893cccd0
PG
12445 if (!json)
12446 vty_out(vty, "\n");
d62a17ae 12447 }
9ab0cf58 12448end_table_stats:
6c9d22e2
PG
12449 if (json)
12450 json_object_array_add(json_array, json);
893cccd0 12451 return ret;
d62a17ae 12452}
12453
71f1613a
DA
12454static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
12455 safi_t safi, struct json_object *json_array)
12456{
12457 if (!bgp) {
12458 bgp_table_stats_all(vty, afi, safi, json_array);
12459 return CMD_SUCCESS;
12460 }
12461
12462 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12463}
12464
d62a17ae 12465enum bgp_pcounts {
12466 PCOUNT_ADJ_IN = 0,
12467 PCOUNT_DAMPED,
12468 PCOUNT_REMOVED,
12469 PCOUNT_HISTORY,
12470 PCOUNT_STALE,
12471 PCOUNT_VALID,
12472 PCOUNT_ALL,
12473 PCOUNT_COUNTED,
7e3d9632 12474 PCOUNT_BPATH_SELECTED,
d62a17ae 12475 PCOUNT_PFCNT, /* the figure we display to users */
12476 PCOUNT_MAX,
a636c635 12477};
718e3744 12478
2b64873d 12479static const char *const pcount_strs[] = {
9d303b37
DL
12480 [PCOUNT_ADJ_IN] = "Adj-in",
12481 [PCOUNT_DAMPED] = "Damped",
12482 [PCOUNT_REMOVED] = "Removed",
12483 [PCOUNT_HISTORY] = "History",
12484 [PCOUNT_STALE] = "Stale",
12485 [PCOUNT_VALID] = "Valid",
12486 [PCOUNT_ALL] = "All RIB",
12487 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 12488 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
12489 [PCOUNT_PFCNT] = "Useable",
12490 [PCOUNT_MAX] = NULL,
a636c635 12491};
718e3744 12492
d62a17ae 12493struct peer_pcounts {
12494 unsigned int count[PCOUNT_MAX];
12495 const struct peer *peer;
12496 const struct bgp_table *table;
54317cba 12497 safi_t safi;
a636c635 12498};
47fc97cc 12499
9bcb3eef 12500static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 12501{
54317cba
JW
12502 const struct bgp_adj_in *ain;
12503 const struct bgp_path_info *pi;
d62a17ae 12504 const struct peer *peer = pc->peer;
12505
54317cba
JW
12506 for (ain = rn->adj_in; ain; ain = ain->next)
12507 if (ain->peer == peer)
12508 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 12509
9bcb3eef 12510 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 12511
54317cba
JW
12512 if (pi->peer != peer)
12513 continue;
d62a17ae 12514
54317cba 12515 pc->count[PCOUNT_ALL]++;
d62a17ae 12516
54317cba
JW
12517 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
12518 pc->count[PCOUNT_DAMPED]++;
12519 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
12520 pc->count[PCOUNT_HISTORY]++;
12521 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
12522 pc->count[PCOUNT_REMOVED]++;
12523 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
12524 pc->count[PCOUNT_STALE]++;
12525 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
12526 pc->count[PCOUNT_VALID]++;
12527 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12528 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
12529 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12530 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
12531
12532 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
12533 pc->count[PCOUNT_COUNTED]++;
12534 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12535 flog_err(
12536 EC_LIB_DEVELOPMENT,
12537 "Attempting to count but flags say it is unusable");
12538 } else {
40381db7 12539 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
12540 flog_err(
12541 EC_LIB_DEVELOPMENT,
12542 "Not counted but flags say we should");
d62a17ae 12543 }
12544 }
54317cba
JW
12545}
12546
12547static int bgp_peer_count_walker(struct thread *t)
12548{
9bcb3eef 12549 struct bgp_dest *rn, *rm;
54317cba
JW
12550 const struct bgp_table *table;
12551 struct peer_pcounts *pc = THREAD_ARG(t);
12552
12553 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
12554 || pc->safi == SAFI_EVPN) {
12555 /* Special handling for 2-level routing tables. */
12556 for (rn = bgp_table_top(pc->table); rn;
12557 rn = bgp_route_next(rn)) {
9bcb3eef 12558 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
12559 if (table != NULL)
12560 for (rm = bgp_table_top(table); rm;
12561 rm = bgp_route_next(rm))
12562 bgp_peer_count_proc(rm, pc);
12563 }
12564 } else
12565 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
12566 bgp_peer_count_proc(rn, pc);
12567
d62a17ae 12568 return 0;
718e3744 12569}
12570
d62a17ae 12571static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 12572 safi_t safi, bool use_json)
856ca177 12573{
d62a17ae 12574 struct peer_pcounts pcounts = {.peer = peer};
12575 unsigned int i;
12576 json_object *json = NULL;
12577 json_object *json_loop = NULL;
856ca177 12578
d62a17ae 12579 if (use_json) {
12580 json = json_object_new_object();
12581 json_loop = json_object_new_object();
12582 }
718e3744 12583
d62a17ae 12584 if (!peer || !peer->bgp || !peer->afc[afi][safi]
12585 || !peer->bgp->rib[afi][safi]) {
12586 if (use_json) {
12587 json_object_string_add(
12588 json, "warning",
12589 "No such neighbor or address family");
12590 vty_out(vty, "%s\n", json_object_to_json_string(json));
12591 json_object_free(json);
12592 } else
12593 vty_out(vty, "%% No such neighbor or address family\n");
12594
12595 return CMD_WARNING;
12596 }
2a71e9ce 12597
d62a17ae 12598 memset(&pcounts, 0, sizeof(pcounts));
12599 pcounts.peer = peer;
12600 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 12601 pcounts.safi = safi;
d62a17ae 12602
12603 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
12604 * stats for the thread-walk (i.e. ensure this can't be blamed on
12605 * on just vty_read()).
12606 */
d62a17ae 12607 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
12608
12609 if (use_json) {
12610 json_object_string_add(json, "prefixCountsFor", peer->host);
12611 json_object_string_add(json, "multiProtocol",
5cb5f4d0 12612 get_afi_safi_str(afi, safi, true));
d62a17ae 12613 json_object_int_add(json, "pfxCounter",
12614 peer->pcount[afi][safi]);
12615
12616 for (i = 0; i < PCOUNT_MAX; i++)
12617 json_object_int_add(json_loop, pcount_strs[i],
12618 pcounts.count[i]);
12619
12620 json_object_object_add(json, "ribTableWalkCounters", json_loop);
12621
12622 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12623 json_object_string_add(json, "pfxctDriftFor",
12624 peer->host);
12625 json_object_string_add(
12626 json, "recommended",
12627 "Please report this bug, with the above command output");
12628 }
996c9314
LB
12629 vty_out(vty, "%s\n", json_object_to_json_string_ext(
12630 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 12631 json_object_free(json);
12632 } else {
12633
12634 if (peer->hostname
892fedb6 12635 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 12636 vty_out(vty, "Prefix counts for %s/%s, %s\n",
12637 peer->hostname, peer->host,
5cb5f4d0 12638 get_afi_safi_str(afi, safi, false));
d62a17ae 12639 } else {
12640 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 12641 get_afi_safi_str(afi, safi, false));
d62a17ae 12642 }
12643
6cde4b45 12644 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 12645 vty_out(vty, "\nCounts from RIB table walk:\n\n");
12646
12647 for (i = 0; i < PCOUNT_MAX; i++)
12648 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
12649 pcounts.count[i]);
12650
12651 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12652 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
12653 vty_out(vty,
12654 "Please report this bug, with the above command output\n");
12655 }
12656 }
12657
12658 return CMD_SUCCESS;
718e3744 12659}
12660
a636c635
DW
12661DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
12662 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 12663 "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 12664 SHOW_STR
12665 IP_STR
12666 BGP_STR
8386ac43 12667 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
12668 BGP_AFI_HELP_STR
12669 BGP_SAFI_HELP_STR
0b16f239
DS
12670 "Detailed information on TCP and BGP neighbor connections\n"
12671 "Neighbor to display information about\n"
12672 "Neighbor to display information about\n"
91d37724 12673 "Neighbor on BGP configured interface\n"
a636c635 12674 "Display detailed prefix count information\n"
9973d184 12675 JSON_STR)
0b16f239 12676{
d62a17ae 12677 afi_t afi = AFI_IP6;
12678 safi_t safi = SAFI_UNICAST;
12679 struct peer *peer;
12680 int idx = 0;
12681 struct bgp *bgp = NULL;
9f049418
DS
12682 bool uj = use_json(argc, argv);
12683
12684 if (uj)
12685 argc--;
856ca177 12686
d62a17ae 12687 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12688 &bgp, uj);
d62a17ae 12689 if (!idx)
12690 return CMD_WARNING;
0b16f239 12691
d62a17ae 12692 argv_find(argv, argc, "neighbors", &idx);
12693 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
12694 if (!peer)
12695 return CMD_WARNING;
bb46e94f 12696
29c8d9da 12697 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 12698}
0b16f239 12699
d6902373
PG
12700#ifdef KEEP_OLD_VPN_COMMANDS
12701DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
12702 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
12703 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
12704 SHOW_STR
12705 IP_STR
12706 BGP_STR
d6902373 12707 BGP_VPNVX_HELP_STR
91d37724 12708 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
12709 "Detailed information on TCP and BGP neighbor connections\n"
12710 "Neighbor to display information about\n"
12711 "Neighbor to display information about\n"
91d37724 12712 "Neighbor on BGP configured interface\n"
a636c635 12713 "Display detailed prefix count information\n"
9973d184 12714 JSON_STR)
a636c635 12715{
d62a17ae 12716 int idx_peer = 6;
12717 struct peer *peer;
9f049418 12718 bool uj = use_json(argc, argv);
a636c635 12719
d62a17ae 12720 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
12721 if (!peer)
12722 return CMD_WARNING;
12723
12724 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
12725}
12726
d6902373
PG
12727DEFUN (show_ip_bgp_vpn_all_route_prefix,
12728 show_ip_bgp_vpn_all_route_prefix_cmd,
12729 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
12730 SHOW_STR
12731 IP_STR
12732 BGP_STR
d6902373 12733 BGP_VPNVX_HELP_STR
91d37724
QY
12734 "Display information about all VPNv4 NLRIs\n"
12735 "Network in the BGP routing table to display\n"
3a2d747c 12736 "Network in the BGP routing table to display\n"
9973d184 12737 JSON_STR)
91d37724 12738{
d62a17ae 12739 int idx = 0;
12740 char *network = NULL;
12741 struct bgp *bgp = bgp_get_default();
12742 if (!bgp) {
12743 vty_out(vty, "Can't find default instance\n");
12744 return CMD_WARNING;
12745 }
87e34b58 12746
d62a17ae 12747 if (argv_find(argv, argc, "A.B.C.D", &idx))
12748 network = argv[idx]->arg;
12749 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
12750 network = argv[idx]->arg;
12751 else {
12752 vty_out(vty, "Unable to figure out Network\n");
12753 return CMD_WARNING;
12754 }
87e34b58 12755
d62a17ae 12756 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 12757 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 12758}
d6902373 12759#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 12760
44c69747
LK
12761DEFUN (show_bgp_l2vpn_evpn_route_prefix,
12762 show_bgp_l2vpn_evpn_route_prefix_cmd,
12763 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 12764 SHOW_STR
4c63a661
PG
12765 BGP_STR
12766 L2VPN_HELP_STR
12767 EVPN_HELP_STR
44c69747
LK
12768 "Network in the BGP routing table to display\n"
12769 "Network in the BGP routing table to display\n"
4c63a661
PG
12770 "Network in the BGP routing table to display\n"
12771 "Network in the BGP routing table to display\n"
12772 JSON_STR)
12773{
d62a17ae 12774 int idx = 0;
12775 char *network = NULL;
44c69747 12776 int prefix_check = 0;
a636c635 12777
44c69747
LK
12778 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
12779 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 12780 network = argv[idx]->arg;
44c69747 12781 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 12782 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 12783 network = argv[idx]->arg;
44c69747
LK
12784 prefix_check = 1;
12785 } else {
d62a17ae 12786 vty_out(vty, "Unable to figure out Network\n");
12787 return CMD_WARNING;
12788 }
44c69747
LK
12789 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
12790 prefix_check, BGP_PATH_SHOW_ALL,
12791 use_json(argc, argv));
d62a17ae 12792}
12793
2f9bc755
DS
12794static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
12795 struct bgp_table *table, int *header1,
12796 int *header2, json_object *json,
12797 json_object *json_scode,
12798 json_object *json_ocode, bool wide)
12799{
12800 uint64_t version = table ? table->version : 0;
23d0a753 12801 char buf[BUFSIZ] = {0};
2f9bc755
DS
12802
12803 if (*header1) {
12804 if (json) {
12805 json_object_int_add(json, "bgpTableVersion", version);
12806 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
12807 inet_ntop(AF_INET,
12808 &bgp->router_id, buf,
12809 sizeof(buf)));
2f9bc755
DS
12810 json_object_int_add(json, "defaultLocPrf",
12811 bgp->default_local_pref);
12812 json_object_int_add(json, "localAS", bgp->as);
12813 json_object_object_add(json, "bgpStatusCodes",
12814 json_scode);
12815 json_object_object_add(json, "bgpOriginCodes",
12816 json_ocode);
12817 } else {
12818 vty_out(vty,
23d0a753
DA
12819 "BGP table version is %" PRIu64
12820 ", local router ID is %pI4, vrf id ",
12821 version, &bgp->router_id);
2f9bc755
DS
12822 if (bgp->vrf_id == VRF_UNKNOWN)
12823 vty_out(vty, "%s", VRFID_NONE_STR);
12824 else
12825 vty_out(vty, "%u", bgp->vrf_id);
12826 vty_out(vty, "\n");
12827 vty_out(vty, "Default local pref %u, ",
12828 bgp->default_local_pref);
12829 vty_out(vty, "local AS %u\n", bgp->as);
12830 vty_out(vty, BGP_SHOW_SCODE_HEADER);
12831 vty_out(vty, BGP_SHOW_NCODE_HEADER);
12832 vty_out(vty, BGP_SHOW_OCODE_HEADER);
12833 }
12834 *header1 = 0;
12835 }
12836 if (*header2) {
12837 if (!json)
12838 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
12839 : BGP_SHOW_HEADER));
12840 *header2 = 0;
12841 }
12842}
12843
d62a17ae 12844static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 12845 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c
MK
12846 const char *rmap_name, json_object *json,
12847 uint8_t show_flags)
d62a17ae 12848{
12849 struct bgp_table *table;
12850 struct bgp_adj_in *ain;
12851 struct bgp_adj_out *adj;
74a630b6
NT
12852 unsigned long output_count = 0;
12853 unsigned long filtered_count = 0;
9bcb3eef 12854 struct bgp_dest *dest;
d62a17ae 12855 int header1 = 1;
12856 struct bgp *bgp;
12857 int header2 = 1;
12858 struct attr attr;
12859 int ret;
12860 struct update_subgroup *subgrp;
12861 json_object *json_scode = NULL;
12862 json_object *json_ocode = NULL;
12863 json_object *json_ar = NULL;
12864 struct peer_af *paf;
f99def61 12865 bool route_filtered;
96f3485c
MK
12866 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12867 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d62a17ae 12868
12869 if (use_json) {
12870 json_scode = json_object_new_object();
12871 json_ocode = json_object_new_object();
12872 json_ar = json_object_new_object();
12873
12874 json_object_string_add(json_scode, "suppressed", "s");
12875 json_object_string_add(json_scode, "damped", "d");
12876 json_object_string_add(json_scode, "history", "h");
12877 json_object_string_add(json_scode, "valid", "*");
12878 json_object_string_add(json_scode, "best", ">");
12879 json_object_string_add(json_scode, "multipath", "=");
12880 json_object_string_add(json_scode, "internal", "i");
12881 json_object_string_add(json_scode, "ribFailure", "r");
12882 json_object_string_add(json_scode, "stale", "S");
12883 json_object_string_add(json_scode, "removed", "R");
12884
12885 json_object_string_add(json_ocode, "igp", "i");
12886 json_object_string_add(json_ocode, "egp", "e");
12887 json_object_string_add(json_ocode, "incomplete", "?");
12888 }
a636c635 12889
d62a17ae 12890 bgp = peer->bgp;
a636c635 12891
d62a17ae 12892 if (!bgp) {
12893 if (use_json) {
12894 json_object_string_add(json, "alert", "no BGP");
12895 vty_out(vty, "%s\n", json_object_to_json_string(json));
12896 json_object_free(json);
12897 } else
12898 vty_out(vty, "%% No bgp\n");
12899 return;
12900 }
a636c635 12901
c512a642
EDP
12902 /* labeled-unicast routes live in the unicast table */
12903 if (safi == SAFI_LABELED_UNICAST)
12904 table = bgp->rib[afi][SAFI_UNICAST];
12905 else
12906 table = bgp->rib[afi][safi];
d62a17ae 12907
12908 output_count = filtered_count = 0;
12909 subgrp = peer_subgroup(peer, afi, safi);
12910
6392aaa6 12911 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 12912 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
23d0a753
DA
12913 char buf[BUFSIZ] = {0};
12914
d62a17ae 12915 if (use_json) {
12916 json_object_int_add(json, "bgpTableVersion",
12917 table->version);
12918 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
12919 inet_ntop(AF_INET,
12920 &bgp->router_id, buf,
12921 sizeof(buf)));
01eced22
AD
12922 json_object_int_add(json, "defaultLocPrf",
12923 bgp->default_local_pref);
12924 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 12925 json_object_object_add(json, "bgpStatusCodes",
12926 json_scode);
12927 json_object_object_add(json, "bgpOriginCodes",
12928 json_ocode);
07d0c4ed
DA
12929 json_object_string_add(
12930 json, "bgpOriginatingDefaultNetwork",
12931 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 12932 } else {
23d0a753
DA
12933 vty_out(vty,
12934 "BGP table version is %" PRIu64
12935 ", local router ID is %pI4, vrf id ",
12936 table->version, &bgp->router_id);
9df8b37c
PZ
12937 if (bgp->vrf_id == VRF_UNKNOWN)
12938 vty_out(vty, "%s", VRFID_NONE_STR);
12939 else
12940 vty_out(vty, "%u", bgp->vrf_id);
12941 vty_out(vty, "\n");
01eced22
AD
12942 vty_out(vty, "Default local pref %u, ",
12943 bgp->default_local_pref);
12944 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 12945 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 12946 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 12947 vty_out(vty, BGP_SHOW_OCODE_HEADER);
12948
07d0c4ed
DA
12949 vty_out(vty, "Originating default network %s\n\n",
12950 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 12951 }
12952 header1 = 0;
12953 }
a636c635 12954
9bcb3eef 12955 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
12956 if (type == bgp_show_adj_route_received
12957 || type == bgp_show_adj_route_filtered) {
9bcb3eef 12958 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 12959 if (ain->peer != peer)
ea47320b 12960 continue;
6392aaa6 12961
2f9bc755
DS
12962 show_adj_route_header(
12963 vty, bgp, table, &header1, &header2,
12964 json, json_scode, json_ocode, wide);
6392aaa6 12965
6f4f49b2 12966 attr = *ain->attr;
f99def61
AD
12967 route_filtered = false;
12968
12969 /* Filter prefix using distribute list,
12970 * filter list or prefix list
12971 */
b54892e0 12972 const struct prefix *rn_p =
9bcb3eef 12973 bgp_dest_get_prefix(dest);
b54892e0
DS
12974 if ((bgp_input_filter(peer, rn_p, &attr, afi,
12975 safi))
12976 == FILTER_DENY)
f99def61
AD
12977 route_filtered = true;
12978
12979 /* Filter prefix using route-map */
b54892e0
DS
12980 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
12981 safi, rmap_name, NULL,
12982 0, NULL);
6392aaa6 12983
13c8e163
AD
12984 if (type == bgp_show_adj_route_filtered &&
12985 !route_filtered && ret != RMAP_DENY) {
b755861b 12986 bgp_attr_undup(&attr, ain->attr);
6392aaa6 12987 continue;
d62a17ae 12988 }
6392aaa6 12989
13c8e163
AD
12990 if (type == bgp_show_adj_route_received &&
12991 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
12992 filtered_count++;
12993
b54892e0 12994 route_vty_out_tmp(vty, rn_p, &attr, safi,
ae248832 12995 use_json, json_ar, wide);
b755861b 12996 bgp_attr_undup(&attr, ain->attr);
6392aaa6 12997 output_count++;
d62a17ae 12998 }
6392aaa6 12999 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13000 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13001 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13002 if (paf->peer != peer || !adj->attr)
924c3f6a 13003 continue;
d62a17ae 13004
2f9bc755
DS
13005 show_adj_route_header(
13006 vty, bgp, table, &header1,
13007 &header2, json, json_scode,
13008 json_ocode, wide);
d62a17ae 13009
b54892e0 13010 const struct prefix *rn_p =
9bcb3eef 13011 bgp_dest_get_prefix(dest);
b54892e0 13012
6f4f49b2 13013 attr = *adj->attr;
b755861b 13014 ret = bgp_output_modifier(
b54892e0 13015 peer, rn_p, &attr, afi, safi,
b755861b 13016 rmap_name);
f46d8e1e 13017
b755861b 13018 if (ret != RMAP_DENY) {
b54892e0
DS
13019 route_vty_out_tmp(
13020 vty, rn_p, &attr, safi,
ae248832
MK
13021 use_json, json_ar,
13022 wide);
b755861b
PM
13023 output_count++;
13024 } else {
13025 filtered_count++;
a2addae8 13026 }
b755861b
PM
13027
13028 bgp_attr_undup(&attr, adj->attr);
924c3f6a 13029 }
f20ce998
DS
13030 } else if (type == bgp_show_adj_route_bestpath) {
13031 struct bgp_path_info *pi;
13032
13033 show_adj_route_header(vty, bgp, table, &header1,
13034 &header2, json, json_scode,
13035 json_ocode, wide);
13036
13037 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13038 pi = pi->next) {
13039 if (pi->peer != peer)
13040 continue;
13041
13042 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13043 continue;
13044
13045 route_vty_out_tmp(vty,
13046 bgp_dest_get_prefix(dest),
13047 pi->attr, safi, use_json,
13048 json_ar, wide);
13049 output_count++;
13050 }
d62a17ae 13051 }
13052 }
d62a17ae 13053
d62a17ae 13054 if (use_json) {
6392aaa6
PM
13055 json_object_object_add(json, "advertisedRoutes", json_ar);
13056 json_object_int_add(json, "totalPrefixCounter", output_count);
13057 json_object_int_add(json, "filteredPrefixCounter",
13058 filtered_count);
13059
996c9314
LB
13060 vty_out(vty, "%s\n", json_object_to_json_string_ext(
13061 json, JSON_C_TO_STRING_PRETTY));
74a630b6
NT
13062
13063 if (!output_count && !filtered_count) {
13064 json_object_free(json_scode);
13065 json_object_free(json_ocode);
13066 }
13067
d62a17ae 13068 json_object_free(json);
6392aaa6
PM
13069 } else if (output_count > 0) {
13070 if (filtered_count > 0)
13071 vty_out(vty,
13072 "\nTotal number of prefixes %ld (%ld filtered)\n",
13073 output_count, filtered_count);
13074 else
13075 vty_out(vty, "\nTotal number of prefixes %ld\n",
13076 output_count);
d62a17ae 13077 }
a636c635 13078}
2a71e9ce 13079
d62a17ae 13080static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13081 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c 13082 const char *rmap_name, uint8_t show_flags)
0b16f239 13083{
d62a17ae 13084 json_object *json = NULL;
96f3485c 13085 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13086
d62a17ae 13087 if (use_json)
13088 json = json_object_new_object();
0b16f239 13089
d62a17ae 13090 if (!peer || !peer->afc[afi][safi]) {
13091 if (use_json) {
13092 json_object_string_add(
13093 json, "warning",
13094 "No such neighbor or address family");
13095 vty_out(vty, "%s\n", json_object_to_json_string(json));
13096 json_object_free(json);
13097 } else
13098 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13099
d62a17ae 13100 return CMD_WARNING;
13101 }
13102
6392aaa6
PM
13103 if ((type == bgp_show_adj_route_received
13104 || type == bgp_show_adj_route_filtered)
d62a17ae 13105 && !CHECK_FLAG(peer->af_flags[afi][safi],
13106 PEER_FLAG_SOFT_RECONFIG)) {
13107 if (use_json) {
13108 json_object_string_add(
13109 json, "warning",
13110 "Inbound soft reconfiguration not enabled");
13111 vty_out(vty, "%s\n", json_object_to_json_string(json));
13112 json_object_free(json);
13113 } else
13114 vty_out(vty,
13115 "%% Inbound soft reconfiguration not enabled\n");
13116
13117 return CMD_WARNING;
13118 }
0b16f239 13119
96f3485c 13120 show_adj_route(vty, peer, afi, safi, type, rmap_name, json, show_flags);
0b16f239 13121
d62a17ae 13122 return CMD_SUCCESS;
a636c635 13123}
50ef26d4 13124
f20ce998
DS
13125DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13126 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13127 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] neighbors <A.B.C.D|X:X::X:X|WORD> bestpath-routes [json$uj | wide$wide]",
13128 SHOW_STR
13129 IP_STR
13130 BGP_STR
13131 BGP_INSTANCE_HELP_STR
13132 BGP_AFI_HELP_STR
13133 BGP_SAFI_WITH_LABEL_HELP_STR
13134 "Detailed information on TCP and BGP neighbor connections\n"
13135 "Neighbor to display information about\n"
13136 "Neighbor to display information about\n"
13137 "Neighbor on BGP configured interface\n"
13138 "Display the routes selected by best path\n"
13139 JSON_STR
13140 "Increase table width for longer prefixes\n")
13141{
13142 afi_t afi = AFI_IP6;
13143 safi_t safi = SAFI_UNICAST;
13144 char *rmap_name = NULL;
13145 char *peerstr = NULL;
13146 struct bgp *bgp = NULL;
13147 struct peer *peer;
13148 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13149 int idx = 0;
96f3485c
MK
13150 uint8_t show_flags = 0;
13151
13152 if (uj)
13153 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13154
13155 if (wide)
13156 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13157
13158 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13159 &bgp, uj);
13160
13161 if (!idx)
13162 return CMD_WARNING;
13163
13164 argv_find(argv, argc, "neighbors", &idx);
13165 peerstr = argv[++idx]->arg;
13166
13167 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13168 if (!peer)
13169 return CMD_WARNING;
13170
96f3485c
MK
13171 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13172 show_flags);
f20ce998
DS
13173}
13174
ae248832 13175DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13176 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13177 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [all$all] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json$uj | wide$wide]",
718e3744 13178 SHOW_STR
13179 IP_STR
13180 BGP_STR
a636c635 13181 BGP_INSTANCE_HELP_STR
7395a2c9 13182 BGP_AFI_HELP_STR
4dd6177e 13183 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13184 "Display the entries for all address families\n"
718e3744 13185 "Detailed information on TCP and BGP neighbor connections\n"
13186 "Neighbor to display information about\n"
13187 "Neighbor to display information about\n"
91d37724 13188 "Neighbor on BGP configured interface\n"
a636c635 13189 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13190 "Display the received routes from neighbor\n"
13191 "Display the filtered routes received from neighbor\n"
a636c635
DW
13192 "Route-map to modify the attributes\n"
13193 "Name of the route map\n"
ae248832
MK
13194 JSON_STR
13195 "Increase table width for longer prefixes\n")
718e3744 13196{
d62a17ae 13197 afi_t afi = AFI_IP6;
13198 safi_t safi = SAFI_UNICAST;
13199 char *rmap_name = NULL;
13200 char *peerstr = NULL;
d62a17ae 13201 struct bgp *bgp = NULL;
13202 struct peer *peer;
6392aaa6 13203 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13204 int idx = 0;
96f3485c
MK
13205 bool first = true;
13206 uint8_t show_flags = 0;
6392aaa6 13207
96f3485c 13208 if (uj) {
d62a17ae 13209 argc--;
96f3485c
MK
13210 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13211 }
13212
13213 if (all) {
13214 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13215 if (argv_find(argv, argc, "ipv4", &idx))
13216 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13217
13218 if (argv_find(argv, argc, "ipv6", &idx))
13219 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13220 }
13221
13222 if (wide)
13223 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13224
9f049418
DS
13225 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13226 &bgp, uj);
13227 if (!idx)
13228 return CMD_WARNING;
13229
d62a17ae 13230 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13231 argv_find(argv, argc, "neighbors", &idx);
13232 peerstr = argv[++idx]->arg;
8c3deaae 13233
d62a17ae 13234 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13235 if (!peer)
13236 return CMD_WARNING;
856ca177 13237
d62a17ae 13238 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13239 type = bgp_show_adj_route_advertised;
13240 else if (argv_find(argv, argc, "received-routes", &idx))
13241 type = bgp_show_adj_route_received;
13242 else if (argv_find(argv, argc, "filtered-routes", &idx))
13243 type = bgp_show_adj_route_filtered;
13244
d62a17ae 13245 if (argv_find(argv, argc, "route-map", &idx))
13246 rmap_name = argv[++idx]->arg;
95cbbd2a 13247
96f3485c
MK
13248 if (!all)
13249 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13250 show_flags);
13251 if (uj)
13252 vty_out(vty, "{\n");
13253
13254 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13255 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13256 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
13257 : AFI_IP6;
13258 FOREACH_SAFI (safi) {
13259 if (strmatch(get_afi_safi_str(afi, safi, true),
13260 "Unknown"))
13261 continue;
13262
13263 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13264 continue;
13265
13266 if (uj) {
13267 if (first)
13268 first = false;
13269 else
13270 vty_out(vty, ",\n");
13271 vty_out(vty, "\"%s\":",
13272 get_afi_safi_str(afi, safi, true));
13273 } else
13274 vty_out(vty, "\nFor address family: %s\n",
13275 get_afi_safi_str(afi, safi, false));
13276
13277 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13278 show_flags);
13279 }
13280 } else {
13281 FOREACH_AFI_SAFI (afi, safi) {
13282 if (strmatch(get_afi_safi_str(afi, safi, true),
13283 "Unknown"))
13284 continue;
13285
13286 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13287 continue;
13288
13289 if (uj) {
13290 if (first)
13291 first = false;
13292 else
13293 vty_out(vty, ",\n");
13294 vty_out(vty, "\"%s\":",
13295 get_afi_safi_str(afi, safi, true));
13296 } else
13297 vty_out(vty, "\nFor address family: %s\n",
13298 get_afi_safi_str(afi, safi, false));
13299
13300 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13301 show_flags);
13302 }
13303 }
13304 if (uj)
13305 vty_out(vty, "}\n");
13306
13307 return CMD_SUCCESS;
95cbbd2a
ML
13308}
13309
718e3744 13310DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
13311 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 13312 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 13313 SHOW_STR
13314 IP_STR
13315 BGP_STR
8c3deaae
QY
13316 "Address Family\n"
13317 "Address Family\n"
718e3744 13318 "Address Family modifier\n"
13319 "Detailed information on TCP and BGP neighbor connections\n"
13320 "Neighbor to display information about\n"
13321 "Neighbor to display information about\n"
91d37724 13322 "Neighbor on BGP configured interface\n"
718e3744 13323 "Display information received from a BGP neighbor\n"
856ca177 13324 "Display the prefixlist filter\n"
9973d184 13325 JSON_STR)
718e3744 13326{
d62a17ae 13327 afi_t afi = AFI_IP6;
13328 safi_t safi = SAFI_UNICAST;
13329 char *peerstr = NULL;
13330
13331 char name[BUFSIZ];
13332 union sockunion su;
13333 struct peer *peer;
13334 int count, ret;
13335
13336 int idx = 0;
13337
13338 /* show [ip] bgp */
13339 if (argv_find(argv, argc, "ip", &idx))
13340 afi = AFI_IP;
13341 /* [<ipv4|ipv6> [unicast]] */
13342 if (argv_find(argv, argc, "ipv4", &idx))
13343 afi = AFI_IP;
13344 if (argv_find(argv, argc, "ipv6", &idx))
13345 afi = AFI_IP6;
13346 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13347 argv_find(argv, argc, "neighbors", &idx);
13348 peerstr = argv[++idx]->arg;
13349
9f049418 13350 bool uj = use_json(argc, argv);
d62a17ae 13351
13352 ret = str2sockunion(peerstr, &su);
13353 if (ret < 0) {
13354 peer = peer_lookup_by_conf_if(NULL, peerstr);
13355 if (!peer) {
13356 if (uj)
13357 vty_out(vty, "{}\n");
13358 else
13359 vty_out(vty,
13360 "%% Malformed address or name: %s\n",
13361 peerstr);
13362 return CMD_WARNING;
13363 }
13364 } else {
13365 peer = peer_lookup(NULL, &su);
13366 if (!peer) {
13367 if (uj)
13368 vty_out(vty, "{}\n");
13369 else
13370 vty_out(vty, "No peer\n");
13371 return CMD_WARNING;
13372 }
13373 }
718e3744 13374
4ced1a2c 13375 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 13376 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
13377 if (count) {
13378 if (!uj)
13379 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 13380 get_afi_safi_str(afi, safi, false));
d62a17ae 13381 prefix_bgp_show_prefix_list(vty, afi, name, uj);
13382 } else {
13383 if (uj)
13384 vty_out(vty, "{}\n");
13385 else
13386 vty_out(vty, "No functional output\n");
13387 }
718e3744 13388
d62a17ae 13389 return CMD_SUCCESS;
13390}
13391
13392static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
13393 afi_t afi, safi_t safi,
9f049418 13394 enum bgp_show_type type, bool use_json)
d62a17ae 13395{
96f3485c
MK
13396 uint8_t show_flags = 0;
13397
13398 if (use_json)
13399 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13400
d62a17ae 13401 if (!peer || !peer->afc[afi][safi]) {
13402 if (use_json) {
13403 json_object *json_no = NULL;
13404 json_no = json_object_new_object();
13405 json_object_string_add(
13406 json_no, "warning",
13407 "No such neighbor or address family");
13408 vty_out(vty, "%s\n",
13409 json_object_to_json_string(json_no));
13410 json_object_free(json_no);
13411 } else
13412 vty_out(vty, "%% No such neighbor or address family\n");
13413 return CMD_WARNING;
13414 }
47fc97cc 13415
7daf25a3
TA
13416 /* labeled-unicast routes live in the unicast table */
13417 if (safi == SAFI_LABELED_UNICAST)
13418 safi = SAFI_UNICAST;
13419
96f3485c 13420 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags);
718e3744 13421}
13422
dba3c1d3
PG
13423DEFUN (show_ip_bgp_flowspec_routes_detailed,
13424 show_ip_bgp_flowspec_routes_detailed_cmd,
13425 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
13426 SHOW_STR
13427 IP_STR
13428 BGP_STR
13429 BGP_INSTANCE_HELP_STR
13430 BGP_AFI_HELP_STR
13431 "SAFI Flowspec\n"
13432 "Detailed information on flowspec entries\n"
13433 JSON_STR)
13434{
13435 afi_t afi = AFI_IP;
13436 safi_t safi = SAFI_UNICAST;
13437 struct bgp *bgp = NULL;
13438 int idx = 0;
9f049418 13439 bool uj = use_json(argc, argv);
96f3485c 13440 uint8_t show_flags = 0;
9f049418 13441
96f3485c 13442 if (uj) {
9f049418 13443 argc--;
96f3485c
MK
13444 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13445 }
dba3c1d3
PG
13446
13447 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13448 &bgp, uj);
dba3c1d3
PG
13449 if (!idx)
13450 return CMD_WARNING;
13451
96f3485c
MK
13452 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
13453 show_flags);
dba3c1d3
PG
13454}
13455
718e3744 13456DEFUN (show_ip_bgp_neighbor_routes,
13457 show_ip_bgp_neighbor_routes_cmd,
3efd0893 13458 "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 13459 SHOW_STR
13460 IP_STR
13461 BGP_STR
8386ac43 13462 BGP_INSTANCE_HELP_STR
4f280b15 13463 BGP_AFI_HELP_STR
4dd6177e 13464 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 13465 "Detailed information on TCP and BGP neighbor connections\n"
13466 "Neighbor to display information about\n"
13467 "Neighbor to display information about\n"
91d37724 13468 "Neighbor on BGP configured interface\n"
2525cf39 13469 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
13470 "Display the dampened routes received from neighbor\n"
13471 "Display routes learned from neighbor\n"
9973d184 13472 JSON_STR)
718e3744 13473{
d62a17ae 13474 char *peerstr = NULL;
13475 struct bgp *bgp = NULL;
13476 afi_t afi = AFI_IP6;
13477 safi_t safi = SAFI_UNICAST;
13478 struct peer *peer;
13479 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 13480 int idx = 0;
9f049418
DS
13481 bool uj = use_json(argc, argv);
13482
13483 if (uj)
13484 argc--;
bb46e94f 13485
d62a17ae 13486 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13487 &bgp, uj);
d62a17ae 13488 if (!idx)
13489 return CMD_WARNING;
c493f2d8 13490
d62a17ae 13491 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13492 argv_find(argv, argc, "neighbors", &idx);
13493 peerstr = argv[++idx]->arg;
8c3deaae 13494
d62a17ae 13495 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 13496 if (!peer)
d62a17ae 13497 return CMD_WARNING;
bb46e94f 13498
d62a17ae 13499 if (argv_find(argv, argc, "flap-statistics", &idx))
13500 sh_type = bgp_show_type_flap_neighbor;
13501 else if (argv_find(argv, argc, "dampened-routes", &idx))
13502 sh_type = bgp_show_type_damp_neighbor;
13503 else if (argv_find(argv, argc, "routes", &idx))
13504 sh_type = bgp_show_type_neighbor;
2525cf39 13505
d62a17ae 13506 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 13507}
6b0655a2 13508
734b349e 13509struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 13510
d62a17ae 13511struct bgp_distance {
13512 /* Distance value for the IP source prefix. */
d7c0a89a 13513 uint8_t distance;
718e3744 13514
d62a17ae 13515 /* Name of the access-list to be matched. */
13516 char *access_list;
718e3744 13517};
13518
4f280b15
LB
13519DEFUN (show_bgp_afi_vpn_rd_route,
13520 show_bgp_afi_vpn_rd_route_cmd,
d114b977 13521 "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
13522 SHOW_STR
13523 BGP_STR
13524 BGP_AFI_HELP_STR
13525 "Address Family modifier\n"
13526 "Display information for a route distinguisher\n"
13527 "Route Distinguisher\n"
7395a2c9
DS
13528 "Network in the BGP routing table to display\n"
13529 "Network in the BGP routing table to display\n"
13530 JSON_STR)
4f280b15 13531{
d62a17ae 13532 int ret;
13533 struct prefix_rd prd;
13534 afi_t afi = AFI_MAX;
13535 int idx = 0;
4f280b15 13536
ff6566f3
DS
13537 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
13538 vty_out(vty, "%% Malformed Address Family\n");
13539 return CMD_WARNING;
13540 }
13541
d62a17ae 13542 ret = str2prefix_rd(argv[5]->arg, &prd);
13543 if (!ret) {
13544 vty_out(vty, "%% Malformed Route Distinguisher\n");
13545 return CMD_WARNING;
13546 }
ff6566f3 13547
d62a17ae 13548 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 13549 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
13550}
13551
d62a17ae 13552static struct bgp_distance *bgp_distance_new(void)
718e3744 13553{
d62a17ae 13554 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 13555}
13556
d62a17ae 13557static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 13558{
d62a17ae 13559 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 13560}
13561
37a87b8f
CS
13562int bgp_distance_set(uint8_t distance, const char *ip_str,
13563 const char *access_list_str, afi_t afi, safi_t safi,
13564 char *errmsg, size_t errmsg_len)
718e3744 13565{
d62a17ae 13566 int ret;
d62a17ae 13567 struct prefix p;
9bcb3eef 13568 struct bgp_dest *dest;
d62a17ae 13569 struct bgp_distance *bdistance;
718e3744 13570
d62a17ae 13571 ret = str2prefix(ip_str, &p);
13572 if (ret == 0) {
37a87b8f 13573 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 13574 return CMD_WARNING_CONFIG_FAILED;
13575 }
718e3744 13576
d62a17ae 13577 /* Get BGP distance node. */
9bcb3eef
DS
13578 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
13579 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 13580 if (bdistance)
9bcb3eef 13581 bgp_dest_unlock_node(dest);
ca2e160d 13582 else {
d62a17ae 13583 bdistance = bgp_distance_new();
9bcb3eef 13584 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 13585 }
718e3744 13586
d62a17ae 13587 /* Set distance value. */
13588 bdistance->distance = distance;
718e3744 13589
d62a17ae 13590 /* Reset access-list configuration. */
e1b36e13 13591 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13592 if (access_list_str)
13593 bdistance->access_list =
13594 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 13595
d62a17ae 13596 return CMD_SUCCESS;
718e3744 13597}
13598
37a87b8f
CS
13599int bgp_distance_unset(uint8_t distance, const char *ip_str,
13600 const char *access_list_str, afi_t afi, safi_t safi,
13601 char *errmsg, size_t errmsg_len)
718e3744 13602{
d62a17ae 13603 int ret;
d62a17ae 13604 struct prefix p;
9bcb3eef 13605 struct bgp_dest *dest;
d62a17ae 13606 struct bgp_distance *bdistance;
718e3744 13607
d62a17ae 13608 ret = str2prefix(ip_str, &p);
13609 if (ret == 0) {
37a87b8f 13610 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 13611 return CMD_WARNING_CONFIG_FAILED;
13612 }
718e3744 13613
9bcb3eef
DS
13614 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
13615 if (!dest) {
37a87b8f 13616 snprintf(errmsg, errmsg_len, "Can't find specified prefix\n");
d62a17ae 13617 return CMD_WARNING_CONFIG_FAILED;
13618 }
718e3744 13619
9bcb3eef 13620 bdistance = bgp_dest_get_bgp_distance_info(dest);
1f9a9fff 13621
d62a17ae 13622 if (bdistance->distance != distance) {
37a87b8f
CS
13623 snprintf(errmsg, errmsg_len,
13624 "Distance does not match configured\n");
d62a17ae 13625 return CMD_WARNING_CONFIG_FAILED;
13626 }
718e3744 13627
0a22ddfb 13628 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13629 bgp_distance_free(bdistance);
718e3744 13630
9bcb3eef
DS
13631 bgp_dest_set_bgp_path_info(dest, NULL);
13632 bgp_dest_unlock_node(dest);
13633 bgp_dest_unlock_node(dest);
718e3744 13634
d62a17ae 13635 return CMD_SUCCESS;
718e3744 13636}
13637
718e3744 13638/* Apply BGP information to distance method. */
b8685f9b 13639uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 13640 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 13641{
9bcb3eef 13642 struct bgp_dest *dest;
d62a17ae 13643 struct prefix q;
13644 struct peer *peer;
13645 struct bgp_distance *bdistance;
13646 struct access_list *alist;
13647 struct bgp_static *bgp_static;
13648
13649 if (!bgp)
13650 return 0;
13651
40381db7 13652 peer = pinfo->peer;
d62a17ae 13653
7b7d48e5
DS
13654 if (pinfo->attr->distance)
13655 return pinfo->attr->distance;
13656
d62a17ae 13657 /* Check source address. */
13658 sockunion2hostprefix(&peer->su, &q);
9bcb3eef
DS
13659 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
13660 if (dest) {
13661 bdistance = bgp_dest_get_bgp_distance_info(dest);
13662 bgp_dest_unlock_node(dest);
d62a17ae 13663
13664 if (bdistance->access_list) {
13665 alist = access_list_lookup(afi, bdistance->access_list);
13666 if (alist
13667 && access_list_apply(alist, p) == FILTER_PERMIT)
13668 return bdistance->distance;
13669 } else
13670 return bdistance->distance;
718e3744 13671 }
718e3744 13672
d62a17ae 13673 /* Backdoor check. */
9bcb3eef
DS
13674 dest = bgp_node_lookup(bgp->route[afi][safi], p);
13675 if (dest) {
13676 bgp_static = bgp_dest_get_bgp_static_info(dest);
13677 bgp_dest_unlock_node(dest);
718e3744 13678
d62a17ae 13679 if (bgp_static->backdoor) {
13680 if (bgp->distance_local[afi][safi])
13681 return bgp->distance_local[afi][safi];
13682 else
13683 return ZEBRA_IBGP_DISTANCE_DEFAULT;
13684 }
718e3744 13685 }
718e3744 13686
d62a17ae 13687 if (peer->sort == BGP_PEER_EBGP) {
13688 if (bgp->distance_ebgp[afi][safi])
13689 return bgp->distance_ebgp[afi][safi];
13690 return ZEBRA_EBGP_DISTANCE_DEFAULT;
13691 } else {
13692 if (bgp->distance_ibgp[afi][safi])
13693 return bgp->distance_ibgp[afi][safi];
13694 return ZEBRA_IBGP_DISTANCE_DEFAULT;
13695 }
718e3744 13696}
13697
a612fb77
DA
13698/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
13699 * we should tell ZEBRA update the routes for a specific
13700 * AFI/SAFI to reflect changes in RIB.
13701 */
37a87b8f
CS
13702void bgp_announce_routes_distance_update(struct bgp *bgp, afi_t update_afi,
13703 safi_t update_safi)
a612fb77
DA
13704{
13705 afi_t afi;
13706 safi_t safi;
13707
13708 FOREACH_AFI_SAFI (afi, safi) {
13709 if (!bgp_fibupd_safi(safi))
13710 continue;
13711
8b54bc30
DA
13712 if (afi != update_afi && safi != update_safi)
13713 continue;
13714
13715 if (BGP_DEBUG(zebra, ZEBRA))
13716 zlog_debug(
13717 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
13718 __func__, afi, safi);
13719 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
13720 }
13721}
13722
37a87b8f
CS
13723DEFUN_YANG(bgp_distance, bgp_distance_cmd,
13724 "distance bgp (1-255) (1-255) (1-255)",
13725 "Define an administrative distance\n"
13726 "BGP distance\n"
13727 "Distance for routes external to the AS\n"
13728 "Distance for routes internal to the AS\n"
13729 "Distance for local routes\n")
718e3744 13730{
d62a17ae 13731 int idx_number = 2;
13732 int idx_number_2 = 3;
13733 int idx_number_3 = 4;
13734 afi_t afi;
13735 safi_t safi;
37a87b8f 13736 char xpath[XPATH_MAXLEN];
718e3744 13737
d62a17ae 13738 afi = bgp_node_afi(vty);
13739 safi = bgp_node_safi(vty);
718e3744 13740
37a87b8f
CS
13741 snprintf(
13742 xpath, sizeof(xpath),
13743 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
13744 yang_afi_safi_value2identity(afi, safi),
13745 bgp_afi_safi_get_container_str(afi, safi));
13746 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[idx_number]->arg);
13747 snprintf(
13748 xpath, sizeof(xpath),
13749 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
13750 yang_afi_safi_value2identity(afi, safi),
13751 bgp_afi_safi_get_container_str(afi, safi));
13752 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
13753 argv[idx_number_2]->arg);
13754 snprintf(
13755 xpath, sizeof(xpath),
13756 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
13757 yang_afi_safi_value2identity(afi, safi),
13758 bgp_afi_safi_get_container_str(afi, safi));
13759
13760 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
13761 argv[idx_number_3]->arg);
13762
13763 return nb_cli_apply_changes(vty, NULL);
13764}
13765
13766DEFUN_YANG(no_bgp_distance, no_bgp_distance_cmd,
13767 "no distance bgp [(1-255) (1-255) (1-255)]",
13768 NO_STR
13769 "Define an administrative distance\n"
13770 "BGP distance\n"
13771 "Distance for routes external to the AS\n"
13772 "Distance for routes internal to the AS\n"
13773 "Distance for local routes\n")
13774{
13775 afi_t afi;
13776 safi_t safi;
13777 char xpath[XPATH_MAXLEN];
13778
13779 afi = bgp_node_afi(vty);
13780 safi = bgp_node_safi(vty);
13781
13782 snprintf(
13783 xpath, sizeof(xpath),
13784 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
13785 yang_afi_safi_value2identity(afi, safi),
13786 bgp_afi_safi_get_container_str(afi, safi));
13787 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13788 snprintf(
13789 xpath, sizeof(xpath),
13790 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
13791 yang_afi_safi_value2identity(afi, safi),
13792 bgp_afi_safi_get_container_str(afi, safi));
13793 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13794 snprintf(
13795 xpath, sizeof(xpath),
13796 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
13797 yang_afi_safi_value2identity(afi, safi),
13798 bgp_afi_safi_get_container_str(afi, safi));
13799
13800 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13801
13802 return nb_cli_apply_changes(vty, NULL);
718e3744 13803}
13804
37a87b8f
CS
13805void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty *vty,
13806 struct lyd_node *dnode,
13807 bool show_defaults)
718e3744 13808{
37a87b8f
CS
13809 uint8_t distance_ebgp, distance_ibgp, distance_local;
13810
13811 distance_ebgp = yang_dnode_get_uint8(dnode, "./external");
13812 distance_ibgp = yang_dnode_get_uint8(dnode, "./internal");
13813 distance_local = yang_dnode_get_uint8(dnode, "./local");
13814
13815 vty_out(vty, " distance bgp %d %d %d\n", distance_ebgp, distance_ibgp,
13816 distance_local);
13817}
13818
8cc7152a
CS
13819DEFPY_YANG(bgp_distance_source,
13820 bgp_distance_source_cmd,
13821 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
37a87b8f
CS
13822 NO_STR
13823 "Define an administrative distance\n"
8cc7152a 13824 "Distance value\n"
37a87b8f
CS
13825 "IP source prefix\n"
13826 "Access list name\n")
718e3744 13827{
37a87b8f
CS
13828 afi_t afi;
13829 safi_t safi;
13830 char xpath[XPATH_MAXLEN];
13831
13832 afi = bgp_node_afi(vty);
13833 safi = bgp_node_safi(vty);
13834
8cc7152a
CS
13835 if (!no) {
13836 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
13837 nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY,
13838 distance_str);
13839 if (acl)
13840 nb_cli_enqueue_change(vty,
13841 "./access-list-policy-export",
13842 NB_OP_CREATE, acl);
13843 else
13844 nb_cli_enqueue_change(vty,
13845 "./access-list-policy-export",
13846 NB_OP_DESTROY, NULL);
13847 } else {
13848 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
13849 }
37a87b8f
CS
13850
13851 snprintf(
13852 xpath, sizeof(xpath),
13853 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
13854 yang_afi_safi_value2identity(afi, safi),
8cc7152a 13855 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
37a87b8f
CS
13856
13857 return nb_cli_apply_changes(vty, xpath);
734b349e
MZ
13858}
13859
37a87b8f
CS
13860void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
13861 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
13862{
13863 vty_out(vty, " distance %d %s %s\n",
13864 yang_dnode_get_uint8(dnode, "./distance"),
13865 yang_dnode_get_string(dnode, "./prefix"),
13866 (yang_dnode_exists(dnode, "./access-list-policy-export"))
13867 ? yang_dnode_get_string(dnode,
13868 "./access-list-policy-export")
13869 : "");
13870}
13871
d9ce5113
CS
13872DEFPY_YANG(bgp_dampening,
13873 bgp_dampening_cmd,
13874 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_supress]]",
37a87b8f
CS
13875 NO_STR
13876 "BGP Specific commands\n"
13877 "Enable route-flap dampening\n"
13878 "Half-life time for the penalty\n"
13879 "Value to start reusing a route\n"
13880 "Value to start suppressing a route\n"
13881 "Maximum duration to suppress a stable route\n")
13882{
13883 afi_t afi;
13884 safi_t safi;
13885 char xpath[XPATH_MAXLEN];
718e3744 13886
37a87b8f
CS
13887 afi = bgp_node_afi(vty);
13888 safi = bgp_node_safi(vty);
13889
d9ce5113
CS
13890 if (!no) {
13891 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
13892 if (argc == 6) {
13893 nb_cli_enqueue_change(vty, "./reach-decay",
13894 NB_OP_MODIFY, halflife_str);
13895 nb_cli_enqueue_change(vty, "./reuse-above",
13896 NB_OP_MODIFY, reuse_str);
13897 nb_cli_enqueue_change(vty, "./suppress-above",
13898 NB_OP_MODIFY, suppress_str);
13899 nb_cli_enqueue_change(vty, "./unreach-decay",
13900 NB_OP_MODIFY, max_supress_str);
13901 } if (argc == 3) {
13902 nb_cli_enqueue_change(vty, "./reach-decay",
13903 NB_OP_MODIFY, halflife_str);
13904 }
13905 } else {
13906 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "false");
13907 }
7ebe9748 13908
37a87b8f
CS
13909 snprintf(
13910 xpath, sizeof(xpath),
13911 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
13912 yang_afi_safi_value2identity(afi, safi),
13913 bgp_afi_safi_get_container_str(afi, safi));
13914
13915 return nb_cli_apply_changes(vty, xpath);
718e3744 13916}
13917
37a87b8f
CS
13918void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty *vty,
13919 struct lyd_node *dnode,
13920 bool show_defaults)
718e3744 13921{
37a87b8f
CS
13922 if (!yang_dnode_get_bool(dnode, "./enable"))
13923 return;
13924
13925 int half = DEFAULT_HALF_LIFE * 60;
13926 int reuse = DEFAULT_REUSE;
13927 int suppress = DEFAULT_SUPPRESS;
13928 int max;
13929
13930 half = yang_dnode_get_uint8(dnode, "../reach-decay");
13931 reuse = yang_dnode_get_uint16(dnode, "../reuse-above");
13932 suppress = yang_dnode_get_uint16(dnode, "../suppress-above");
13933 max = yang_dnode_get_uint8(dnode, "../unreach-decay");
13934
13935 if (half == DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
13936 && suppress == DEFAULT_SUPPRESS && max == half * 4)
13937 vty_out(vty, " bgp dampening\n");
13938 else if (half != DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
13939 && suppress == DEFAULT_SUPPRESS && max == half * 4)
13940 vty_out(vty, " bgp dampening %u\n", half);
13941 else
13942 vty_out(vty, " bgp dampening %u %d %d %d\n", half, reuse,
13943 suppress, max);
718e3744 13944}
13945
718e3744 13946/* Display specified route of BGP table. */
d62a17ae 13947static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
13948 const char *ip_str, afi_t afi, safi_t safi,
13949 struct prefix_rd *prd, int prefix_check)
13950{
13951 int ret;
13952 struct prefix match;
9bcb3eef
DS
13953 struct bgp_dest *dest;
13954 struct bgp_dest *rm;
40381db7
DS
13955 struct bgp_path_info *pi;
13956 struct bgp_path_info *pi_temp;
d62a17ae 13957 struct bgp *bgp;
13958 struct bgp_table *table;
13959
13960 /* BGP structure lookup. */
13961 if (view_name) {
13962 bgp = bgp_lookup_by_name(view_name);
13963 if (bgp == NULL) {
13964 vty_out(vty, "%% Can't find BGP instance %s\n",
13965 view_name);
13966 return CMD_WARNING;
13967 }
13968 } else {
13969 bgp = bgp_get_default();
13970 if (bgp == NULL) {
13971 vty_out(vty, "%% No BGP process is configured\n");
13972 return CMD_WARNING;
13973 }
718e3744 13974 }
718e3744 13975
d62a17ae 13976 /* Check IP address argument. */
13977 ret = str2prefix(ip_str, &match);
13978 if (!ret) {
13979 vty_out(vty, "%% address is malformed\n");
13980 return CMD_WARNING;
13981 }
718e3744 13982
d62a17ae 13983 match.family = afi2family(afi);
13984
13985 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13986 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
13987 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
13988 dest = bgp_route_next(dest)) {
13989 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 13990
9bcb3eef 13991 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 13992 continue;
9bcb3eef 13993 table = bgp_dest_get_bgp_table_info(dest);
67009e22 13994 if (!table)
ea47320b
DL
13995 continue;
13996 if ((rm = bgp_node_match(table, &match)) == NULL)
13997 continue;
d62a17ae 13998
9bcb3eef 13999 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14000
ea47320b 14001 if (!prefix_check
b54892e0 14002 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14003 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14004 while (pi) {
14005 if (pi->extra && pi->extra->damp_info) {
14006 pi_temp = pi->next;
ea47320b 14007 bgp_damp_info_free(
40381db7 14008 pi->extra->damp_info,
a935f597 14009 1, afi, safi);
40381db7 14010 pi = pi_temp;
ea47320b 14011 } else
40381db7 14012 pi = pi->next;
d62a17ae 14013 }
ea47320b
DL
14014 }
14015
9bcb3eef 14016 bgp_dest_unlock_node(rm);
d62a17ae 14017 }
14018 } else {
9bcb3eef 14019 if ((dest = bgp_node_match(bgp->rib[afi][safi], &match))
d62a17ae 14020 != NULL) {
9bcb3eef 14021 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14022
d62a17ae 14023 if (!prefix_check
9bcb3eef
DS
14024 || dest_p->prefixlen == match.prefixlen) {
14025 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14026 while (pi) {
14027 if (pi->extra && pi->extra->damp_info) {
14028 pi_temp = pi->next;
d62a17ae 14029 bgp_damp_info_free(
40381db7 14030 pi->extra->damp_info,
a935f597 14031 1, afi, safi);
40381db7 14032 pi = pi_temp;
d62a17ae 14033 } else
40381db7 14034 pi = pi->next;
d62a17ae 14035 }
14036 }
14037
9bcb3eef 14038 bgp_dest_unlock_node(dest);
d62a17ae 14039 }
14040 }
718e3744 14041
d62a17ae 14042 return CMD_SUCCESS;
718e3744 14043}
14044
14045DEFUN (clear_ip_bgp_dampening,
14046 clear_ip_bgp_dampening_cmd,
14047 "clear ip bgp dampening",
14048 CLEAR_STR
14049 IP_STR
14050 BGP_STR
14051 "Clear route flap dampening information\n")
14052{
a935f597 14053 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 14054 return CMD_SUCCESS;
718e3744 14055}
14056
14057DEFUN (clear_ip_bgp_dampening_prefix,
14058 clear_ip_bgp_dampening_prefix_cmd,
14059 "clear ip bgp dampening A.B.C.D/M",
14060 CLEAR_STR
14061 IP_STR
14062 BGP_STR
14063 "Clear route flap dampening information\n"
0c7b1b01 14064 "IPv4 prefix\n")
718e3744 14065{
d62a17ae 14066 int idx_ipv4_prefixlen = 4;
14067 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14068 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14069}
14070
14071DEFUN (clear_ip_bgp_dampening_address,
14072 clear_ip_bgp_dampening_address_cmd,
14073 "clear ip bgp dampening A.B.C.D",
14074 CLEAR_STR
14075 IP_STR
14076 BGP_STR
14077 "Clear route flap dampening information\n"
14078 "Network to clear damping information\n")
14079{
d62a17ae 14080 int idx_ipv4 = 4;
14081 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14082 SAFI_UNICAST, NULL, 0);
718e3744 14083}
14084
14085DEFUN (clear_ip_bgp_dampening_address_mask,
14086 clear_ip_bgp_dampening_address_mask_cmd,
14087 "clear ip bgp dampening A.B.C.D A.B.C.D",
14088 CLEAR_STR
14089 IP_STR
14090 BGP_STR
14091 "Clear route flap dampening information\n"
14092 "Network to clear damping information\n"
14093 "Network mask\n")
14094{
d62a17ae 14095 int idx_ipv4 = 4;
14096 int idx_ipv4_2 = 5;
14097 int ret;
14098 char prefix_str[BUFSIZ];
718e3744 14099
d62a17ae 14100 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
14101 prefix_str);
14102 if (!ret) {
14103 vty_out(vty, "%% Inconsistent address and mask\n");
14104 return CMD_WARNING;
14105 }
718e3744 14106
d62a17ae 14107 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14108 NULL, 0);
718e3744 14109}
6b0655a2 14110
e3b78da8 14111static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14112{
14113 struct vty *vty = arg;
e3b78da8 14114 struct peer *peer = bucket->data;
825d9834
DS
14115 char buf[SU_ADDRSTRLEN];
14116
14117 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14118 sockunion2str(&peer->su, buf, sizeof(buf)));
14119}
14120
2a0e69ae
DS
14121DEFUN (show_bgp_listeners,
14122 show_bgp_listeners_cmd,
14123 "show bgp listeners",
14124 SHOW_STR
14125 BGP_STR
14126 "Display Listen Sockets and who created them\n")
14127{
14128 bgp_dump_listener_info(vty);
14129
14130 return CMD_SUCCESS;
14131}
14132
825d9834
DS
14133DEFUN (show_bgp_peerhash,
14134 show_bgp_peerhash_cmd,
14135 "show bgp peerhash",
14136 SHOW_STR
14137 BGP_STR
14138 "Display information about the BGP peerhash\n")
14139{
14140 struct list *instances = bm->bgp;
14141 struct listnode *node;
14142 struct bgp *bgp;
14143
14144 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14145 vty_out(vty, "BGP: %s\n", bgp->name);
14146 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14147 vty);
14148 }
14149
14150 return CMD_SUCCESS;
14151}
14152
587ff0fd 14153/* also used for encap safi */
2b791107
DL
14154static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14155 afi_t afi, safi_t safi)
d62a17ae 14156{
9bcb3eef
DS
14157 struct bgp_dest *pdest;
14158 struct bgp_dest *dest;
d62a17ae 14159 struct bgp_table *table;
b54892e0
DS
14160 const struct prefix *p;
14161 const struct prefix_rd *prd;
d62a17ae 14162 struct bgp_static *bgp_static;
14163 mpls_label_t label;
d62a17ae 14164 char rdbuf[RD_ADDRSTRLEN];
14165
14166 /* Network configuration. */
9bcb3eef
DS
14167 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14168 pdest = bgp_route_next(pdest)) {
14169 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14170 if (!table)
ea47320b 14171 continue;
d62a17ae 14172
9bcb3eef
DS
14173 for (dest = bgp_table_top(table); dest;
14174 dest = bgp_route_next(dest)) {
14175 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14176 if (bgp_static == NULL)
ea47320b 14177 continue;
d62a17ae 14178
9bcb3eef
DS
14179 p = bgp_dest_get_prefix(dest);
14180 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14181 pdest);
d62a17ae 14182
ea47320b 14183 /* "network" configuration display. */
06b9f471 14184 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14185 label = decode_label(&bgp_static->label);
14186
8228a9a7 14187 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14188 if (safi == SAFI_MPLS_VPN)
14189 vty_out(vty, " label %u", label);
14190
14191 if (bgp_static->rmap.name)
14192 vty_out(vty, " route-map %s",
14193 bgp_static->rmap.name);
e2a86ad9
DS
14194
14195 if (bgp_static->backdoor)
14196 vty_out(vty, " backdoor");
14197
ea47320b
DL
14198 vty_out(vty, "\n");
14199 }
14200 }
d62a17ae 14201}
14202
2b791107
DL
14203static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14204 afi_t afi, safi_t safi)
d62a17ae 14205{
9bcb3eef
DS
14206 struct bgp_dest *pdest;
14207 struct bgp_dest *dest;
d62a17ae 14208 struct bgp_table *table;
b54892e0
DS
14209 const struct prefix *p;
14210 const struct prefix_rd *prd;
d62a17ae 14211 struct bgp_static *bgp_static;
ff44f570 14212 char buf[PREFIX_STRLEN * 2];
d62a17ae 14213 char buf2[SU_ADDRSTRLEN];
14214 char rdbuf[RD_ADDRSTRLEN];
0a50c248 14215 char esi_buf[ESI_BYTES];
d62a17ae 14216
14217 /* Network configuration. */
9bcb3eef
DS
14218 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14219 pdest = bgp_route_next(pdest)) {
14220 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14221 if (!table)
ea47320b 14222 continue;
d62a17ae 14223
9bcb3eef
DS
14224 for (dest = bgp_table_top(table); dest;
14225 dest = bgp_route_next(dest)) {
14226 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14227 if (bgp_static == NULL)
ea47320b 14228 continue;
d62a17ae 14229
ea47320b 14230 char *macrouter = NULL;
d62a17ae 14231
ea47320b
DL
14232 if (bgp_static->router_mac)
14233 macrouter = prefix_mac2str(
14234 bgp_static->router_mac, NULL, 0);
14235 if (bgp_static->eth_s_id)
0a50c248
AK
14236 esi_to_str(bgp_static->eth_s_id,
14237 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
14238 p = bgp_dest_get_prefix(dest);
14239 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 14240
ea47320b 14241 /* "network" configuration display. */
06b9f471 14242 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
14243 if (p->u.prefix_evpn.route_type == 5) {
14244 char local_buf[PREFIX_STRLEN];
3714a385 14245 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
14246 struct prefix_evpn *)p)
14247 ? AF_INET
14248 : AF_INET6;
3714a385 14249 inet_ntop(family,
14250 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 14251 local_buf, PREFIX_STRLEN);
772270f3
QY
14252 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
14253 p->u.prefix_evpn.prefix_addr
14254 .ip_prefix_length);
197cb530
PG
14255 } else {
14256 prefix2str(p, buf, sizeof(buf));
14257 }
ea47320b 14258
a4d82a8a
PZ
14259 if (bgp_static->gatewayIp.family == AF_INET
14260 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
14261 inet_ntop(bgp_static->gatewayIp.family,
14262 &bgp_static->gatewayIp.u.prefix, buf2,
14263 sizeof(buf2));
ea47320b 14264 vty_out(vty,
7bcc8dac 14265 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 14266 buf, rdbuf,
14267 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 14268 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
14269 macrouter);
14270
0a22ddfb 14271 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
14272 }
14273 }
3da6fcd5
PG
14274}
14275
718e3744 14276/* Configuration of static route announcement and aggregate
14277 information. */
2b791107
DL
14278void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
14279 safi_t safi)
d62a17ae 14280{
9bcb3eef 14281 struct bgp_dest *dest;
b54892e0 14282 const struct prefix *p;
d62a17ae 14283 struct bgp_static *bgp_static;
14284 struct bgp_aggregate *bgp_aggregate;
d62a17ae 14285
2b791107
DL
14286 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
14287 bgp_config_write_network_vpn(vty, bgp, afi, safi);
14288 return;
14289 }
d62a17ae 14290
2b791107
DL
14291 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
14292 bgp_config_write_network_evpn(vty, bgp, afi, safi);
14293 return;
14294 }
d62a17ae 14295
14296 /* Network configuration. */
9bcb3eef
DS
14297 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
14298 dest = bgp_route_next(dest)) {
14299 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14300 if (bgp_static == NULL)
ea47320b 14301 continue;
d62a17ae 14302
9bcb3eef 14303 p = bgp_dest_get_prefix(dest);
d62a17ae 14304
8228a9a7 14305 vty_out(vty, " network %pFX", p);
d62a17ae 14306
ea47320b
DL
14307 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
14308 vty_out(vty, " label-index %u",
14309 bgp_static->label_index);
d62a17ae 14310
ea47320b
DL
14311 if (bgp_static->rmap.name)
14312 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
14313
14314 if (bgp_static->backdoor)
14315 vty_out(vty, " backdoor");
718e3744 14316
ea47320b
DL
14317 vty_out(vty, "\n");
14318 }
14319
d62a17ae 14320 /* Aggregate-address configuration. */
9bcb3eef
DS
14321 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
14322 dest = bgp_route_next(dest)) {
14323 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 14324 if (bgp_aggregate == NULL)
ea47320b 14325 continue;
d62a17ae 14326
9bcb3eef 14327 p = bgp_dest_get_prefix(dest);
d62a17ae 14328
8228a9a7 14329 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 14330
ea47320b
DL
14331 if (bgp_aggregate->as_set)
14332 vty_out(vty, " as-set");
d62a17ae 14333
ea47320b
DL
14334 if (bgp_aggregate->summary_only)
14335 vty_out(vty, " summary-only");
718e3744 14336
20894f50
DA
14337 if (bgp_aggregate->rmap.name)
14338 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
14339
229757f1
DA
14340 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
14341 vty_out(vty, " origin %s",
14342 bgp_origin2str(bgp_aggregate->origin));
14343
6aabb15d
RZ
14344 if (bgp_aggregate->match_med)
14345 vty_out(vty, " matching-MED-only");
14346
365ab2e7
RZ
14347 if (bgp_aggregate->suppress_map_name)
14348 vty_out(vty, " suppress-map %s",
14349 bgp_aggregate->suppress_map_name);
14350
ea47320b
DL
14351 vty_out(vty, "\n");
14352 }
d62a17ae 14353}
734b349e 14354
2b791107 14355void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 14356 safi_t safi)
d62a17ae 14357{
9bcb3eef 14358 struct bgp_dest *dest;
d62a17ae 14359 struct bgp_distance *bdistance;
14360
14361 /* Distance configuration. */
14362 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
14363 && bgp->distance_local[afi][safi]
14364 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
14365 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
14366 || bgp->distance_local[afi][safi]
14367 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 14368 vty_out(vty, " distance bgp %d %d %d\n",
14369 bgp->distance_ebgp[afi][safi],
14370 bgp->distance_ibgp[afi][safi],
14371 bgp->distance_local[afi][safi]);
14372 }
734b349e 14373
9bcb3eef
DS
14374 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
14375 dest = bgp_route_next(dest)) {
14376 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 14377 if (bdistance != NULL)
56ca3b5b 14378 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 14379 bdistance->distance, dest,
d62a17ae 14380 bdistance->access_list ? bdistance->access_list
14381 : "");
ca2e160d 14382 }
718e3744 14383}
14384
14385/* Allocate routing table structure and install commands. */
d62a17ae 14386void bgp_route_init(void)
14387{
14388 afi_t afi;
14389 safi_t safi;
14390
14391 /* Init BGP distance table. */
05c7a1cc 14392 FOREACH_AFI_SAFI (afi, safi)
960035b2 14393 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 14394
14395 /* IPv4 BGP commands. */
14396 install_element(BGP_NODE, &bgp_table_map_cmd);
14397 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 14398 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 14399
554b3b10 14400 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 14401
14402 /* IPv4 unicast configuration. */
14403 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
14404 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 14405 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 14406
554b3b10 14407 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 14408
14409 /* IPv4 multicast configuration. */
14410 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
14411 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 14412 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 14413 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 14414
14415 /* IPv4 labeled-unicast configuration. */
fb985e0c 14416 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 14417 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 14418
d62a17ae 14419 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
14420 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 14421 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 14422 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 14423 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 14424 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
14425 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 14426 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 14427
14428 install_element(VIEW_NODE,
14429 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
14430 install_element(VIEW_NODE,
14431 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 14432 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
14433 install_element(VIEW_NODE,
14434 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 14435#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14436 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 14437#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 14438 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
14439 install_element(VIEW_NODE,
44c69747 14440 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 14441
d62a17ae 14442 /* BGP dampening clear commands */
14443 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
14444 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 14445
d62a17ae 14446 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
14447 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
14448
14449 /* prefix count */
14450 install_element(ENABLE_NODE,
14451 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 14452#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14453 install_element(ENABLE_NODE,
14454 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 14455#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 14456
d62a17ae 14457 /* New config IPv6 BGP commands. */
14458 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
14459 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14460 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 14461
554b3b10 14462 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 14463
14464 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14465
fb985e0c
DA
14466 /* IPv6 labeled unicast address family. */
14467 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 14468 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 14469
d62a17ae 14470 install_element(BGP_NODE, &bgp_distance_cmd);
14471 install_element(BGP_NODE, &no_bgp_distance_cmd);
14472 install_element(BGP_NODE, &bgp_distance_source_cmd);
d62a17ae 14473 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
14474 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
14475 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
d62a17ae 14476 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
14477 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
14478 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
d62a17ae 14479 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
14480 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
8cc7152a 14481 install_element(BGP_IPV6_NODE, &bgp_distance_source_cmd);
d62a17ae 14482 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
14483 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
8cc7152a 14484 install_element(BGP_IPV6M_NODE, &bgp_distance_source_cmd);
d62a17ae 14485
ef5f4b23 14486 /* BGP dampening */
d9ce5113
CS
14487 install_element(BGP_NODE, &bgp_dampening_cmd);
14488 install_element(BGP_IPV4_NODE, &bgp_dampening_cmd);
14489 install_element(BGP_IPV4M_NODE, &bgp_dampening_cmd);
14490 install_element(BGP_IPV4L_NODE, &bgp_dampening_cmd);
14491 install_element(BGP_IPV6_NODE, &bgp_dampening_cmd);
14492 install_element(BGP_IPV6M_NODE, &bgp_dampening_cmd);
14493 install_element(BGP_IPV6L_NODE, &bgp_dampening_cmd);
d62a17ae 14494
14495 /* Large Communities */
14496 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
14497 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
14498
14499 /* show bgp ipv4 flowspec detailed */
14500 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
14501
2a0e69ae 14502 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 14503 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 14504}
14505
14506void bgp_route_finish(void)
14507{
14508 afi_t afi;
14509 safi_t safi;
14510
05c7a1cc
QY
14511 FOREACH_AFI_SAFI (afi, safi) {
14512 bgp_table_unlock(bgp_distance_table[afi][safi]);
14513 bgp_distance_table[afi][safi] = NULL;
14514 }
228da428 14515}