]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #6231 from dslicenc/v6-ra-hoplimit
[mirror_frr.git] / bgpd / bgp_route.c
CommitLineData
718e3744 1/* BGP routing information
896014f4
DL
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
718e3744 21
22#include <zebra.h>
8d0ab76d 23#include <math.h>
718e3744 24
2618a52e 25#include "printfrr.h"
718e3744 26#include "prefix.h"
27#include "linklist.h"
28#include "memory.h"
29#include "command.h"
30#include "stream.h"
31#include "filter.h"
718e3744 32#include "log.h"
33#include "routemap.h"
34#include "buffer.h"
35#include "sockunion.h"
36#include "plist.h"
37#include "thread.h"
200df115 38#include "workqueue.h"
3f9c7369 39#include "queue.h"
6e919709 40#include "memory.h"
e496b420 41#include "srv6.h"
4dcadbef 42#include "lib/json.h"
d8d084d9 43#include "lib_errors.h"
8c48b3b6 44#include "zclient.h"
718e3744 45#include "bgpd/bgpd.h"
46#include "bgpd/bgp_table.h"
47#include "bgpd/bgp_route.h"
48#include "bgpd/bgp_attr.h"
49#include "bgpd/bgp_debug.h"
14454c9f 50#include "bgpd/bgp_errors.h"
718e3744 51#include "bgpd/bgp_aspath.h"
52#include "bgpd/bgp_regex.h"
53#include "bgpd/bgp_community.h"
54#include "bgpd/bgp_ecommunity.h"
57d187bc 55#include "bgpd/bgp_lcommunity.h"
718e3744 56#include "bgpd/bgp_clist.h"
57#include "bgpd/bgp_packet.h"
58#include "bgpd/bgp_filter.h"
59#include "bgpd/bgp_fsm.h"
60#include "bgpd/bgp_mplsvpn.h"
61#include "bgpd/bgp_nexthop.h"
62#include "bgpd/bgp_damp.h"
63#include "bgpd/bgp_advertise.h"
64#include "bgpd/bgp_zebra.h"
0a486e5f 65#include "bgpd/bgp_vty.h"
96450faf 66#include "bgpd/bgp_mpath.h"
fc9a856f 67#include "bgpd/bgp_nht.h"
3f9c7369 68#include "bgpd/bgp_updgrp.h"
cd1964ff 69#include "bgpd/bgp_label.h"
dcc68b5e 70#include "bgpd/bgp_addpath.h"
4e802e66 71#include "bgpd/bgp_mac.h"
2a0e69ae 72#include "bgpd/bgp_network.h"
718e3744 73
49e5a4a0 74#ifdef ENABLE_BGP_VNC
f8b6f499
LB
75#include "bgpd/rfapi/rfapi_backend.h"
76#include "bgpd/rfapi/vnc_import_bgp.h"
77#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 78#endif
aee875b5
PG
79#include "bgpd/bgp_encap_types.h"
80#include "bgpd/bgp_encap_tlv.h"
684a7227 81#include "bgpd/bgp_evpn.h"
3da6fcd5 82#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 83#include "bgpd/bgp_flowspec.h"
98a9dbc7 84#include "bgpd/bgp_flowspec_util.h"
45918cfb 85#include "bgpd/bgp_pbr.h"
65efcfce 86
e2a86ad9
DS
87#ifndef VTYSH_EXTRACT_PL
88#include "bgpd/bgp_route_clippy.c"
89#endif
aee875b5 90
718e3744 91/* Extern from bgp_dump.c */
dde72586
SH
92extern const char *bgp_origin_str[];
93extern const char *bgp_origin_long_str[];
36235319 94const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json);
b7d08f5a 95/* PMSI strings. */
96#define PMSI_TNLTYPE_STR_NO_INFO "No info"
97#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
98static const struct message bgp_pmsi_tnltype_str[] = {
99 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
100 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
101 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
102 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
103 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
104 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
105 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
106 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 107 {0}
108};
b7d08f5a 109
9df8b37c
PZ
110#define VRFID_NONE_STR "-"
111
4a11bf2c
DL
112DEFINE_HOOK(bgp_process,
113 (struct bgp *bgp, afi_t afi, safi_t safi,
114 struct bgp_node *bn, struct peer *peer, bool withdraw),
115 (bgp, afi, safi, bn, peer, withdraw))
116
117
d62a17ae 118struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 119 safi_t safi, const struct prefix *p,
d62a17ae 120 struct prefix_rd *prd)
121{
122 struct bgp_node *rn;
123 struct bgp_node *prn = NULL;
124
125 assert(table);
d62a17ae 126
127 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
128 || (safi == SAFI_EVPN)) {
129 prn = bgp_node_get(table, (struct prefix *)prd);
130
67009e22
DS
131 if (!bgp_node_has_bgp_path_info_data(prn))
132 bgp_node_set_bgp_table_info(
133 prn, bgp_table_init(table->bgp, afi, safi));
d62a17ae 134 else
135 bgp_unlock_node(prn);
67009e22 136 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 137 }
718e3744 138
d62a17ae 139 rn = bgp_node_get(table, p);
718e3744 140
d62a17ae 141 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
142 || (safi == SAFI_EVPN))
143 rn->prn = prn;
718e3744 144
d62a17ae 145 return rn;
718e3744 146}
6b0655a2 147
d62a17ae 148struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 149 safi_t safi, const struct prefix *p,
d62a17ae 150 struct prefix_rd *prd)
128ea8ab 151{
d62a17ae 152 struct bgp_node *rn;
153 struct bgp_node *prn = NULL;
128ea8ab 154
d62a17ae 155 if (!table)
156 return NULL;
128ea8ab 157
d62a17ae 158 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
159 || (safi == SAFI_EVPN)) {
160 prn = bgp_node_lookup(table, (struct prefix *)prd);
161 if (!prn)
162 return NULL;
128ea8ab 163
6f94b685 164 if (!bgp_node_has_bgp_path_info_data(prn)) {
d62a17ae 165 bgp_unlock_node(prn);
166 return NULL;
167 }
128ea8ab 168
67009e22 169 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 170 }
128ea8ab 171
d62a17ae 172 rn = bgp_node_lookup(table, p);
128ea8ab 173
d62a17ae 174 return rn;
128ea8ab 175}
176
18ee8310
DS
177/* Allocate bgp_path_info_extra */
178static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 179{
4b7e6066
DS
180 struct bgp_path_info_extra *new;
181 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
182 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
183 new->label[0] = MPLS_INVALID_LABEL;
184 new->num_labels = 0;
3e3708cb
PG
185 new->bgp_fs_pbr = NULL;
186 new->bgp_fs_iprule = NULL;
d62a17ae 187 return new;
fb982c25
PJ
188}
189
a2e219fe 190void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 191{
4b7e6066 192 struct bgp_path_info_extra *e;
d62a17ae 193
c93a3b77
DS
194 if (!extra || !*extra)
195 return;
d62a17ae 196
c93a3b77
DS
197 e = *extra;
198 if (e->damp_info)
a935f597
DA
199 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
200 e->damp_info->safi);
d62a17ae 201
c93a3b77
DS
202 e->damp_info = NULL;
203 if (e->parent) {
40381db7 204 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 205
40381db7 206 if (bpi->net) {
0e70e6c8
DL
207 /* FIXME: since multiple e may have the same e->parent
208 * and e->parent->net is holding a refcount for each
209 * of them, we need to do some fudging here.
210 *
40381db7
DS
211 * WARNING: if bpi->net->lock drops to 0, bpi may be
212 * freed as well (because bpi->net was holding the
213 * last reference to bpi) => write after free!
0e70e6c8
DL
214 */
215 unsigned refcount;
216
40381db7
DS
217 bpi = bgp_path_info_lock(bpi);
218 refcount = bpi->net->lock - 1;
219 bgp_unlock_node((struct bgp_node *)bpi->net);
0e70e6c8 220 if (!refcount)
40381db7
DS
221 bpi->net = NULL;
222 bgp_path_info_unlock(bpi);
0e70e6c8 223 }
18ee8310 224 bgp_path_info_unlock(e->parent);
c93a3b77 225 e->parent = NULL;
d62a17ae 226 }
c93a3b77
DS
227
228 if (e->bgp_orig)
229 bgp_unlock(e->bgp_orig);
c26edcda 230
ce3c0614
PG
231 if ((*extra)->bgp_fs_iprule)
232 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 233 if ((*extra)->bgp_fs_pbr)
6a154c88 234 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 235 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
236}
237
18ee8310
DS
238/* Get bgp_path_info extra information for the given bgp_path_info, lazy
239 * allocated if required.
fb982c25 240 */
40381db7 241struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 242{
40381db7
DS
243 if (!pi->extra)
244 pi->extra = bgp_path_info_extra_new();
245 return pi->extra;
fb982c25
PJ
246}
247
718e3744 248/* Free bgp route information. */
9b6d8fcf 249static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 250{
05864da7 251 bgp_attr_unintern(&path->attr);
fb018d25 252
9b6d8fcf
DS
253 bgp_unlink_nexthop(path);
254 bgp_path_info_extra_free(&path->extra);
255 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
256 if (path->net)
257 bgp_addpath_free_info_data(&path->tx_addpath,
258 &path->net->tx_addpath);
718e3744 259
9b6d8fcf 260 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 261
9b6d8fcf 262 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 263}
264
9b6d8fcf 265struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 266{
9b6d8fcf
DS
267 path->lock++;
268 return path;
200df115 269}
270
9b6d8fcf 271struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 272{
9b6d8fcf
DS
273 assert(path && path->lock > 0);
274 path->lock--;
d62a17ae 275
9b6d8fcf 276 if (path->lock == 0) {
200df115 277#if 0
278 zlog_debug ("%s: unlocked and freeing", __func__);
279 zlog_backtrace (LOG_DEBUG);
280#endif
9b6d8fcf 281 bgp_path_info_free(path);
d62a17ae 282 return NULL;
283 }
200df115 284
285#if 0
9b6d8fcf 286 if (path->lock == 1)
200df115 287 {
288 zlog_debug ("%s: unlocked to 1", __func__);
289 zlog_backtrace (LOG_DEBUG);
290 }
291#endif
d62a17ae 292
9b6d8fcf 293 return path;
200df115 294}
295
f009ff26 296/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
297static int bgp_node_set_defer_flag(struct bgp_node *rn, bool delete)
298{
299 struct peer *peer;
300 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 301 bool set_flag = false;
f009ff26 302 struct bgp *bgp = NULL;
303 struct bgp_table *table = NULL;
304 afi_t afi = 0;
305 safi_t safi = 0;
f009ff26 306
307 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
308 * then the route selection is deferred
309 */
2ba1fe69 310 if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 311 return 0;
312
5f9c1aa2 313 if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 314 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 315 zlog_debug(
b54892e0
DS
316 "Route %pRN is in workqueue and being processed, not deferred.",
317 rn);
318
5f9c1aa2 319 return 0;
320 }
321
f009ff26 322 table = bgp_node_table(rn);
323 if (table) {
324 bgp = table->bgp;
325 afi = table->afi;
326 safi = table->safi;
327 }
328
329 for (old_pi = bgp_node_get_bgp_path_info(rn);
330 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
331 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
332 continue;
333
334 /* Route selection is deferred if there is a stale path which
335 * which indicates peer is in restart mode
336 */
36235319
QY
337 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
338 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 339 set_flag = true;
f009ff26 340 } else {
341 /* If the peer is graceful restart capable and peer is
342 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
343 */
344 peer = old_pi->peer;
36235319
QY
345 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
346 && BGP_PEER_RESTARTING_MODE(peer)
347 && (old_pi
348 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 349 set_flag = true;
f009ff26 350 }
351 }
352 if (set_flag)
353 break;
354 }
355
356 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
357 * is active
358 */
2ba1fe69 359 if (set_flag && table) {
f009ff26 360 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
361 SET_FLAG(rn->flags, BGP_NODE_SELECT_DEFER);
f009ff26 362 if (rn->rt_node == NULL)
363 rn->rt_node = listnode_add(
364 bgp->gr_info[afi][safi].route_list, rn);
365 if (BGP_DEBUG(update, UPDATE_OUT))
b54892e0
DS
366 zlog_debug("DEFER route %pRN, rn %p, node %p",
367 rn, rn, rn->rt_node);
f009ff26 368 return 0;
369 }
370 }
371 return -1;
372}
373
40381db7 374void bgp_path_info_add(struct bgp_node *rn, struct bgp_path_info *pi)
718e3744 375{
4b7e6066 376 struct bgp_path_info *top;
718e3744 377
6f94b685 378 top = bgp_node_get_bgp_path_info(rn);
d62a17ae 379
6f94b685 380 pi->next = top;
40381db7 381 pi->prev = NULL;
d62a17ae 382 if (top)
40381db7 383 top->prev = pi;
6f94b685 384 bgp_node_set_bgp_path_info(rn, pi);
d62a17ae 385
40381db7 386 bgp_path_info_lock(pi);
d62a17ae 387 bgp_lock_node(rn);
40381db7 388 peer_lock(pi->peer); /* bgp_path_info peer reference */
f009ff26 389 bgp_node_set_defer_flag(rn, false);
718e3744 390}
391
d62a17ae 392/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 393 completion callback *only* */
40381db7 394void bgp_path_info_reap(struct bgp_node *rn, struct bgp_path_info *pi)
718e3744 395{
40381db7
DS
396 if (pi->next)
397 pi->next->prev = pi->prev;
398 if (pi->prev)
399 pi->prev->next = pi->next;
d62a17ae 400 else
6f94b685 401 bgp_node_set_bgp_path_info(rn, pi->next);
d62a17ae 402
40381db7
DS
403 bgp_path_info_mpath_dequeue(pi);
404 bgp_path_info_unlock(pi);
d62a17ae 405 bgp_unlock_node(rn);
718e3744 406}
407
40381db7 408void bgp_path_info_delete(struct bgp_node *rn, struct bgp_path_info *pi)
b40d939b 409{
40381db7 410 bgp_path_info_set_flag(rn, pi, BGP_PATH_REMOVED);
d62a17ae 411 /* set of previous already took care of pcount */
40381db7 412 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 413}
414
18ee8310 415/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
416 called when a route is deleted and then quickly re-added before the
417 deletion has been processed */
40381db7 418void bgp_path_info_restore(struct bgp_node *rn, struct bgp_path_info *pi)
8d45210e 419{
40381db7 420 bgp_path_info_unset_flag(rn, pi, BGP_PATH_REMOVED);
d62a17ae 421 /* unset of previous already took care of pcount */
40381db7 422 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
423}
424
d62a17ae 425/* Adjust pcount as required */
40381db7 426static void bgp_pcount_adjust(struct bgp_node *rn, struct bgp_path_info *pi)
1a392d46 427{
d62a17ae 428 struct bgp_table *table;
67174041 429
d62a17ae 430 assert(rn && bgp_node_table(rn));
40381db7 431 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 432
d62a17ae 433 table = bgp_node_table(rn);
67174041 434
40381db7 435 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 436 return;
437
40381db7
DS
438 if (!BGP_PATH_COUNTABLE(pi)
439 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 440
40381db7 441 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 442
443 /* slight hack, but more robust against errors. */
40381db7
DS
444 if (pi->peer->pcount[table->afi][table->safi])
445 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 446 else
450971aa 447 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 448 "Asked to decrement 0 prefix count for peer");
40381db7
DS
449 } else if (BGP_PATH_COUNTABLE(pi)
450 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
451 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
452 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 453 }
1a392d46
PJ
454}
455
40381db7
DS
456static int bgp_label_index_differs(struct bgp_path_info *pi1,
457 struct bgp_path_info *pi2)
28d58fd7 458{
40381db7 459 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 460}
1a392d46 461
18ee8310 462/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
463 * This is here primarily to keep prefix-count in check.
464 */
40381db7 465void bgp_path_info_set_flag(struct bgp_node *rn, struct bgp_path_info *pi,
18ee8310 466 uint32_t flag)
1a392d46 467{
40381db7 468 SET_FLAG(pi->flags, flag);
d62a17ae 469
470 /* early bath if we know it's not a flag that changes countability state
471 */
472 if (!CHECK_FLAG(flag,
1defdda8 473 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 474 return;
475
40381db7 476 bgp_pcount_adjust(rn, pi);
1a392d46
PJ
477}
478
40381db7 479void bgp_path_info_unset_flag(struct bgp_node *rn, struct bgp_path_info *pi,
18ee8310 480 uint32_t flag)
1a392d46 481{
40381db7 482 UNSET_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
40381db7 490 bgp_pcount_adjust(rn, pi);
1a392d46
PJ
491}
492
718e3744 493/* Get MED value. If MED value is missing and "bgp bestpath
494 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 495static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 496{
497 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
498 return attr->med;
499 else {
892fedb6 500 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 501 return BGP_MED_MAX;
502 else
503 return 0;
504 }
718e3744 505}
506
40381db7 507void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf)
2ec1e66f 508{
40381db7
DS
509 if (pi->addpath_rx_id)
510 sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
511 pi->addpath_rx_id);
d62a17ae 512 else
40381db7 513 sprintf(buf, "path %s", pi->peer->host);
d62a17ae 514}
9fbdd100 515
d62a17ae 516/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
517 */
18ee8310
DS
518static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
519 struct bgp_path_info *exist, int *paths_eq,
520 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
521 char *pfx_buf, afi_t afi, safi_t safi,
522 enum bgp_path_selection_reason *reason)
d62a17ae 523{
524 struct attr *newattr, *existattr;
525 bgp_peer_sort_t new_sort;
526 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
527 uint32_t new_pref;
528 uint32_t exist_pref;
529 uint32_t new_med;
530 uint32_t exist_med;
531 uint32_t new_weight;
532 uint32_t exist_weight;
d62a17ae 533 uint32_t newm, existm;
534 struct in_addr new_id;
535 struct in_addr exist_id;
536 int new_cluster;
537 int exist_cluster;
538 int internal_as_route;
539 int confed_as_route;
04d14c8b 540 int ret = 0;
d62a17ae 541 char new_buf[PATH_ADDPATH_STR_BUFFER];
542 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
543 uint32_t new_mm_seq;
544 uint32_t exist_mm_seq;
6d8c603a 545 int nh_cmp;
d62a17ae 546
547 *paths_eq = 0;
548
549 /* 0. Null check. */
550 if (new == NULL) {
fdf81fa0 551 *reason = bgp_path_selection_none;
d62a17ae 552 if (debug)
553 zlog_debug("%s: new is NULL", pfx_buf);
554 return 0;
555 }
2ec1e66f 556
d62a17ae 557 if (debug)
18ee8310 558 bgp_path_info_path_with_addpath_rx_str(new, new_buf);
718e3744 559
d62a17ae 560 if (exist == NULL) {
fdf81fa0 561 *reason = bgp_path_selection_first;
d62a17ae 562 if (debug)
563 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
564 new_buf);
565 return 1;
566 }
2ec1e66f 567
d62a17ae 568 if (debug) {
18ee8310 569 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
d62a17ae 570 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
571 pfx_buf, new_buf, new->flags, exist_buf,
572 exist->flags);
573 }
8ff56318 574
d62a17ae 575 newattr = new->attr;
576 existattr = exist->attr;
577
578 /* For EVPN routes, we cannot just go by local vs remote, we have to
579 * look at the MAC mobility sequence number, if present.
580 */
581 if (safi == SAFI_EVPN) {
582 /* This is an error condition described in RFC 7432 Section
583 * 15.2. The RFC
584 * states that in this scenario "the PE MUST alert the operator"
585 * but it
586 * does not state what other action to take. In order to provide
587 * some
588 * consistency in this scenario we are going to prefer the path
589 * with the
590 * sticky flag.
591 */
592 if (newattr->sticky != existattr->sticky) {
593 if (!debug) {
b54892e0
DS
594 prefix2str(bgp_node_get_prefix(new->net),
595 pfx_buf,
d62a17ae 596 sizeof(*pfx_buf)
597 * PREFIX2STR_BUFFER);
18ee8310
DS
598 bgp_path_info_path_with_addpath_rx_str(new,
599 new_buf);
600 bgp_path_info_path_with_addpath_rx_str(
601 exist, exist_buf);
d62a17ae 602 }
603
604 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 605 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
606 if (debug)
607 zlog_debug(
608 "%s: %s wins over %s due to sticky MAC flag",
609 pfx_buf, new_buf, exist_buf);
d62a17ae 610 return 1;
611 }
612
613 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 614 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
615 if (debug)
616 zlog_debug(
617 "%s: %s loses to %s due to sticky MAC flag",
618 pfx_buf, new_buf, exist_buf);
d62a17ae 619 return 0;
620 }
621 }
128ea8ab 622
d62a17ae 623 new_mm_seq = mac_mobility_seqnum(newattr);
624 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 625
d62a17ae 626 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 627 *reason = bgp_path_selection_evpn_seq;
d62a17ae 628 if (debug)
629 zlog_debug(
630 "%s: %s wins over %s due to MM seq %u > %u",
631 pfx_buf, new_buf, exist_buf, new_mm_seq,
632 exist_mm_seq);
633 return 1;
634 }
8ff56318 635
d62a17ae 636 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 637 *reason = bgp_path_selection_evpn_seq;
d62a17ae 638 if (debug)
639 zlog_debug(
640 "%s: %s loses to %s due to MM seq %u < %u",
641 pfx_buf, new_buf, exist_buf, new_mm_seq,
642 exist_mm_seq);
643 return 0;
644 }
6d8c603a
AK
645
646 /*
647 * if sequence numbers are the same path with the lowest IP
648 * wins
649 */
650 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
651 if (nh_cmp < 0) {
fdf81fa0 652 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
653 if (debug)
654 zlog_debug(
655 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
656 pfx_buf, new_buf, exist_buf, new_mm_seq,
657 inet_ntoa(new->attr->nexthop));
658 return 1;
659 }
660 if (nh_cmp > 0) {
fdf81fa0 661 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
662 if (debug)
663 zlog_debug(
664 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
665 pfx_buf, new_buf, exist_buf, new_mm_seq,
666 inet_ntoa(new->attr->nexthop));
667 return 0;
668 }
d62a17ae 669 }
9fbdd100 670
d62a17ae 671 /* 1. Weight check. */
d62a17ae 672 new_weight = newattr->weight;
673 exist_weight = existattr->weight;
8ff56318 674
d62a17ae 675 if (new_weight > exist_weight) {
fdf81fa0 676 *reason = bgp_path_selection_weight;
d62a17ae 677 if (debug)
678 zlog_debug("%s: %s wins over %s due to weight %d > %d",
679 pfx_buf, new_buf, exist_buf, new_weight,
680 exist_weight);
681 return 1;
682 }
718e3744 683
d62a17ae 684 if (new_weight < exist_weight) {
fdf81fa0 685 *reason = bgp_path_selection_weight;
d62a17ae 686 if (debug)
687 zlog_debug("%s: %s loses to %s due to weight %d < %d",
688 pfx_buf, new_buf, exist_buf, new_weight,
689 exist_weight);
690 return 0;
691 }
9fbdd100 692
d62a17ae 693 /* 2. Local preference check. */
694 new_pref = exist_pref = bgp->default_local_pref;
695
696 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
697 new_pref = newattr->local_pref;
698 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
699 exist_pref = existattr->local_pref;
700
701 if (new_pref > exist_pref) {
fdf81fa0 702 *reason = bgp_path_selection_local_pref;
d62a17ae 703 if (debug)
704 zlog_debug(
705 "%s: %s wins over %s due to localpref %d > %d",
706 pfx_buf, new_buf, exist_buf, new_pref,
707 exist_pref);
708 return 1;
709 }
718e3744 710
d62a17ae 711 if (new_pref < exist_pref) {
fdf81fa0 712 *reason = bgp_path_selection_local_pref;
d62a17ae 713 if (debug)
714 zlog_debug(
715 "%s: %s loses to %s due to localpref %d < %d",
716 pfx_buf, new_buf, exist_buf, new_pref,
717 exist_pref);
718 return 0;
719 }
9fbdd100 720
d62a17ae 721 /* 3. Local route check. We prefer:
722 * - BGP_ROUTE_STATIC
723 * - BGP_ROUTE_AGGREGATE
724 * - BGP_ROUTE_REDISTRIBUTE
725 */
90f4f482 726 if (!(new->sub_type == BGP_ROUTE_NORMAL ||
727 new->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 728 *reason = bgp_path_selection_local_route;
d62a17ae 729 if (debug)
730 zlog_debug(
731 "%s: %s wins over %s due to preferred BGP_ROUTE type",
732 pfx_buf, new_buf, exist_buf);
733 return 1;
734 }
718e3744 735
90f4f482 736 if (!(exist->sub_type == BGP_ROUTE_NORMAL ||
88493076 737 exist->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 738 *reason = bgp_path_selection_local_route;
d62a17ae 739 if (debug)
740 zlog_debug(
741 "%s: %s loses to %s due to preferred BGP_ROUTE type",
742 pfx_buf, new_buf, exist_buf);
743 return 0;
6811845b 744 }
718e3744 745
d62a17ae 746 /* 4. AS path length check. */
892fedb6 747 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 748 int exist_hops = aspath_count_hops(existattr->aspath);
749 int exist_confeds = aspath_count_confeds(existattr->aspath);
750
892fedb6 751 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 752 int aspath_hops;
753
754 aspath_hops = aspath_count_hops(newattr->aspath);
755 aspath_hops += aspath_count_confeds(newattr->aspath);
756
757 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 758 *reason = bgp_path_selection_confed_as_path;
d62a17ae 759 if (debug)
760 zlog_debug(
761 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
762 pfx_buf, new_buf, exist_buf,
763 aspath_hops,
764 (exist_hops + exist_confeds));
765 return 1;
766 }
767
768 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 769 *reason = bgp_path_selection_confed_as_path;
d62a17ae 770 if (debug)
771 zlog_debug(
772 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
773 pfx_buf, new_buf, exist_buf,
774 aspath_hops,
775 (exist_hops + exist_confeds));
776 return 0;
777 }
778 } else {
779 int newhops = aspath_count_hops(newattr->aspath);
780
781 if (newhops < exist_hops) {
fdf81fa0 782 *reason = bgp_path_selection_as_path;
d62a17ae 783 if (debug)
784 zlog_debug(
785 "%s: %s wins over %s due to aspath hopcount %d < %d",
786 pfx_buf, new_buf, exist_buf,
787 newhops, exist_hops);
788 return 1;
789 }
790
791 if (newhops > exist_hops) {
fdf81fa0 792 *reason = bgp_path_selection_as_path;
d62a17ae 793 if (debug)
794 zlog_debug(
795 "%s: %s loses to %s due to aspath hopcount %d > %d",
796 pfx_buf, new_buf, exist_buf,
797 newhops, exist_hops);
798 return 0;
799 }
800 }
801 }
9fbdd100 802
d62a17ae 803 /* 5. Origin check. */
804 if (newattr->origin < existattr->origin) {
fdf81fa0 805 *reason = bgp_path_selection_origin;
d62a17ae 806 if (debug)
807 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
808 pfx_buf, new_buf, exist_buf,
809 bgp_origin_long_str[newattr->origin],
810 bgp_origin_long_str[existattr->origin]);
811 return 1;
812 }
718e3744 813
d62a17ae 814 if (newattr->origin > existattr->origin) {
fdf81fa0 815 *reason = bgp_path_selection_origin;
d62a17ae 816 if (debug)
817 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
818 pfx_buf, new_buf, exist_buf,
819 bgp_origin_long_str[newattr->origin],
820 bgp_origin_long_str[existattr->origin]);
821 return 0;
822 }
718e3744 823
d62a17ae 824 /* 6. MED check. */
825 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
826 && aspath_count_hops(existattr->aspath) == 0);
827 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
828 && aspath_count_confeds(existattr->aspath) > 0
829 && aspath_count_hops(newattr->aspath) == 0
830 && aspath_count_hops(existattr->aspath) == 0);
831
892fedb6
DA
832 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
833 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 834 || aspath_cmp_left(newattr->aspath, existattr->aspath)
835 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
836 || internal_as_route) {
837 new_med = bgp_med_value(new->attr, bgp);
838 exist_med = bgp_med_value(exist->attr, bgp);
839
840 if (new_med < exist_med) {
fdf81fa0 841 *reason = bgp_path_selection_med;
d62a17ae 842 if (debug)
843 zlog_debug(
844 "%s: %s wins over %s due to MED %d < %d",
845 pfx_buf, new_buf, exist_buf, new_med,
846 exist_med);
847 return 1;
848 }
8ff56318 849
d62a17ae 850 if (new_med > exist_med) {
fdf81fa0 851 *reason = bgp_path_selection_med;
d62a17ae 852 if (debug)
853 zlog_debug(
854 "%s: %s loses to %s due to MED %d > %d",
855 pfx_buf, new_buf, exist_buf, new_med,
856 exist_med);
857 return 0;
858 }
859 }
9fbdd100 860
d62a17ae 861 /* 7. Peer type check. */
862 new_sort = new->peer->sort;
863 exist_sort = exist->peer->sort;
864
865 if (new_sort == BGP_PEER_EBGP
866 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 867 *reason = bgp_path_selection_peer;
d62a17ae 868 if (debug)
869 zlog_debug(
870 "%s: %s wins over %s due to eBGP peer > iBGP peer",
871 pfx_buf, new_buf, exist_buf);
872 return 1;
873 }
718e3744 874
d62a17ae 875 if (exist_sort == BGP_PEER_EBGP
876 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 877 *reason = bgp_path_selection_peer;
d62a17ae 878 if (debug)
879 zlog_debug(
880 "%s: %s loses to %s due to iBGP peer < eBGP peer",
881 pfx_buf, new_buf, exist_buf);
882 return 0;
883 }
8ff56318 884
d62a17ae 885 /* 8. IGP metric check. */
886 newm = existm = 0;
8ff56318 887
d62a17ae 888 if (new->extra)
889 newm = new->extra->igpmetric;
890 if (exist->extra)
891 existm = exist->extra->igpmetric;
9fbdd100 892
d62a17ae 893 if (newm < existm) {
894 if (debug)
895 zlog_debug(
896 "%s: %s wins over %s due to IGP metric %d < %d",
897 pfx_buf, new_buf, exist_buf, newm, existm);
898 ret = 1;
899 }
718e3744 900
d62a17ae 901 if (newm > existm) {
902 if (debug)
903 zlog_debug(
904 "%s: %s loses to %s due to IGP metric %d > %d",
905 pfx_buf, new_buf, exist_buf, newm, existm);
906 ret = 0;
5e242b0d 907 }
5e242b0d 908
d62a17ae 909 /* 9. Same IGP metric. Compare the cluster list length as
910 representative of IGP hops metric. Rewrite the metric value
911 pair (newm, existm) with the cluster list length. Prefer the
912 path with smaller cluster list length. */
913 if (newm == existm) {
bf0d28dc
DS
914 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
915 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
d62a17ae 916 && (mpath_cfg == NULL
917 || CHECK_FLAG(
918 mpath_cfg->ibgp_flags,
919 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
920 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
921 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
922
923 if (newm < existm) {
924 if (debug)
925 zlog_debug(
926 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
927 pfx_buf, new_buf, exist_buf,
928 newm, existm);
929 ret = 1;
930 }
931
932 if (newm > existm) {
933 if (debug)
934 zlog_debug(
935 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
936 pfx_buf, new_buf, exist_buf,
937 newm, existm);
938 ret = 0;
939 }
940 }
941 }
31a4638f 942
d62a17ae 943 /* 10. confed-external vs. confed-internal */
944 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
945 if (new_sort == BGP_PEER_CONFED
946 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 947 *reason = bgp_path_selection_confed;
d62a17ae 948 if (debug)
949 zlog_debug(
950 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
951 pfx_buf, new_buf, exist_buf);
952 return 1;
953 }
718e3744 954
d62a17ae 955 if (exist_sort == BGP_PEER_CONFED
956 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 957 *reason = bgp_path_selection_confed;
d62a17ae 958 if (debug)
959 zlog_debug(
960 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
961 pfx_buf, new_buf, exist_buf);
962 return 0;
963 }
964 }
718e3744 965
d62a17ae 966 /* 11. Maximum path check. */
967 if (newm == existm) {
968 /* If one path has a label but the other does not, do not treat
969 * them as equals for multipath
970 */
a4d82a8a 971 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 972 != (exist->extra
b57ba6d2 973 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 974 if (debug)
975 zlog_debug(
976 "%s: %s and %s cannot be multipath, one has a label while the other does not",
977 pfx_buf, new_buf, exist_buf);
892fedb6
DA
978 } else if (CHECK_FLAG(bgp->flags,
979 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 980
981 /*
982 * For the two paths, all comparison steps till IGP
983 * metric
984 * have succeeded - including AS_PATH hop count. Since
985 * 'bgp
986 * bestpath as-path multipath-relax' knob is on, we
987 * don't need
988 * an exact match of AS_PATH. Thus, mark the paths are
989 * equal.
990 * That will trigger both these paths to get into the
991 * multipath
992 * array.
993 */
994 *paths_eq = 1;
995
996 if (debug)
997 zlog_debug(
998 "%s: %s and %s are equal via multipath-relax",
999 pfx_buf, new_buf, exist_buf);
1000 } else if (new->peer->sort == BGP_PEER_IBGP) {
1001 if (aspath_cmp(new->attr->aspath,
1002 exist->attr->aspath)) {
1003 *paths_eq = 1;
1004
1005 if (debug)
1006 zlog_debug(
1007 "%s: %s and %s are equal via matching aspaths",
1008 pfx_buf, new_buf, exist_buf);
1009 }
1010 } else if (new->peer->as == exist->peer->as) {
1011 *paths_eq = 1;
1012
1013 if (debug)
1014 zlog_debug(
1015 "%s: %s and %s are equal via same remote-as",
1016 pfx_buf, new_buf, exist_buf);
1017 }
1018 } else {
1019 /*
1020 * TODO: If unequal cost ibgp multipath is enabled we can
1021 * mark the paths as equal here instead of returning
1022 */
1023 if (debug) {
1024 if (ret == 1)
1025 zlog_debug(
1026 "%s: %s wins over %s after IGP metric comparison",
1027 pfx_buf, new_buf, exist_buf);
1028 else
1029 zlog_debug(
1030 "%s: %s loses to %s after IGP metric comparison",
1031 pfx_buf, new_buf, exist_buf);
1032 }
fdf81fa0 1033 *reason = bgp_path_selection_igp_metric;
d62a17ae 1034 return ret;
1035 }
718e3744 1036
d62a17ae 1037 /* 12. If both paths are external, prefer the path that was received
1038 first (the oldest one). This step minimizes route-flap, since a
1039 newer path won't displace an older one, even if it was the
1040 preferred route based on the additional decision criteria below. */
892fedb6 1041 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1042 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1043 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1044 *reason = bgp_path_selection_older;
d62a17ae 1045 if (debug)
1046 zlog_debug(
1047 "%s: %s wins over %s due to oldest external",
1048 pfx_buf, new_buf, exist_buf);
1049 return 1;
1050 }
9fbdd100 1051
1defdda8 1052 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1053 *reason = bgp_path_selection_older;
d62a17ae 1054 if (debug)
1055 zlog_debug(
1056 "%s: %s loses to %s due to oldest external",
1057 pfx_buf, new_buf, exist_buf);
1058 return 0;
1059 }
1060 }
718e3744 1061
d62a17ae 1062 /* 13. Router-ID comparision. */
1063 /* If one of the paths is "stale", the corresponding peer router-id will
1064 * be 0 and would always win over the other path. If originator id is
1065 * used for the comparision, it will decide which path is better.
1066 */
1067 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1068 new_id.s_addr = newattr->originator_id.s_addr;
1069 else
1070 new_id.s_addr = new->peer->remote_id.s_addr;
1071 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1072 exist_id.s_addr = existattr->originator_id.s_addr;
1073 else
1074 exist_id.s_addr = exist->peer->remote_id.s_addr;
1075
1076 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1077 *reason = bgp_path_selection_router_id;
d62a17ae 1078 if (debug)
1079 zlog_debug(
1080 "%s: %s wins over %s due to Router-ID comparison",
1081 pfx_buf, new_buf, exist_buf);
1082 return 1;
1083 }
718e3744 1084
d62a17ae 1085 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1086 *reason = bgp_path_selection_router_id;
d62a17ae 1087 if (debug)
1088 zlog_debug(
1089 "%s: %s loses to %s due to Router-ID comparison",
1090 pfx_buf, new_buf, exist_buf);
1091 return 0;
1092 }
9fbdd100 1093
d62a17ae 1094 /* 14. Cluster length comparision. */
1095 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1096 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1097
1098 if (new_cluster < exist_cluster) {
fdf81fa0 1099 *reason = bgp_path_selection_cluster_length;
d62a17ae 1100 if (debug)
1101 zlog_debug(
1102 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1103 pfx_buf, new_buf, exist_buf, new_cluster,
1104 exist_cluster);
1105 return 1;
1106 }
718e3744 1107
d62a17ae 1108 if (new_cluster > exist_cluster) {
fdf81fa0 1109 *reason = bgp_path_selection_cluster_length;
d62a17ae 1110 if (debug)
1111 zlog_debug(
1112 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1113 pfx_buf, new_buf, exist_buf, new_cluster,
1114 exist_cluster);
1115 return 0;
1116 }
9fbdd100 1117
d62a17ae 1118 /* 15. Neighbor address comparision. */
1119 /* Do this only if neither path is "stale" as stale paths do not have
1120 * valid peer information (as the connection may or may not be up).
1121 */
1defdda8 1122 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1123 *reason = bgp_path_selection_stale;
d62a17ae 1124 if (debug)
1125 zlog_debug(
1126 "%s: %s wins over %s due to latter path being STALE",
1127 pfx_buf, new_buf, exist_buf);
1128 return 1;
1129 }
0de5153c 1130
1defdda8 1131 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1132 *reason = bgp_path_selection_stale;
d62a17ae 1133 if (debug)
1134 zlog_debug(
1135 "%s: %s loses to %s due to former path being STALE",
1136 pfx_buf, new_buf, exist_buf);
1137 return 0;
1138 }
718e3744 1139
d62a17ae 1140 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1141 if (new->peer->su_remote == NULL) {
1142 *reason = bgp_path_selection_local_configured;
d62a17ae 1143 return 0;
fdf81fa0
DS
1144 }
1145 if (exist->peer->su_remote == NULL) {
1146 *reason = bgp_path_selection_local_configured;
d62a17ae 1147 return 1;
fdf81fa0 1148 }
9fbdd100 1149
d62a17ae 1150 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1151
1152 if (ret == 1) {
fdf81fa0 1153 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1154 if (debug)
1155 zlog_debug(
1156 "%s: %s loses to %s due to Neighor IP comparison",
1157 pfx_buf, new_buf, exist_buf);
1158 return 0;
1159 }
1160
1161 if (ret == -1) {
fdf81fa0 1162 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1163 if (debug)
1164 zlog_debug(
1165 "%s: %s wins over %s due to Neighor IP comparison",
1166 pfx_buf, new_buf, exist_buf);
1167 return 1;
1168 }
9fbdd100 1169
fdf81fa0 1170 *reason = bgp_path_selection_default;
d62a17ae 1171 if (debug)
1172 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1173 pfx_buf, new_buf, exist_buf);
718e3744 1174
d62a17ae 1175 return 1;
718e3744 1176}
1177
65efcfce
LB
1178/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1179 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1180 * multipath is enabled
65efcfce 1181 * This version is compatible with */
18ee8310
DS
1182int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1183 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1184 afi_t afi, safi_t safi,
1185 enum bgp_path_selection_reason *reason)
d62a17ae 1186{
1187 int paths_eq;
1188 int ret;
18ee8310 1189 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1190 afi, safi, reason);
d62a17ae 1191
1192 if (paths_eq)
1193 ret = 0;
1194 else {
1195 if (ret == 1)
1196 ret = -1;
1197 else
1198 ret = 1;
1199 }
1200 return ret;
65efcfce
LB
1201}
1202
5a1ae2c2
DS
1203static enum filter_type bgp_input_filter(struct peer *peer,
1204 const struct prefix *p,
d62a17ae 1205 struct attr *attr, afi_t afi,
1206 safi_t safi)
718e3744 1207{
d62a17ae 1208 struct bgp_filter *filter;
718e3744 1209
d62a17ae 1210 filter = &peer->filter[afi][safi];
718e3744 1211
d62a17ae 1212#define FILTER_EXIST_WARN(F, f, filter) \
1213 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1214 zlog_debug("%s: Could not find configured input %s-list %s!", \
1215 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1216
1217 if (DISTRIBUTE_IN_NAME(filter)) {
1218 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1219
1220 if (access_list_apply(DISTRIBUTE_IN(filter), p) == FILTER_DENY)
1221 return FILTER_DENY;
1222 }
1223
1224 if (PREFIX_LIST_IN_NAME(filter)) {
1225 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1226
1227 if (prefix_list_apply(PREFIX_LIST_IN(filter), p) == PREFIX_DENY)
1228 return FILTER_DENY;
1229 }
1230
1231 if (FILTER_LIST_IN_NAME(filter)) {
1232 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1233
1234 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
1235 == AS_FILTER_DENY)
1236 return FILTER_DENY;
1237 }
1238
1239 return FILTER_PERMIT;
650f76c2 1240#undef FILTER_EXIST_WARN
718e3744 1241}
1242
b8685f9b
DS
1243static enum filter_type bgp_output_filter(struct peer *peer,
1244 const struct prefix *p,
d62a17ae 1245 struct attr *attr, afi_t afi,
1246 safi_t safi)
718e3744 1247{
d62a17ae 1248 struct bgp_filter *filter;
1249
1250 filter = &peer->filter[afi][safi];
1251
1252#define FILTER_EXIST_WARN(F, f, filter) \
1253 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1254 zlog_debug("%s: Could not find configured output %s-list %s!", \
1255 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1256
d62a17ae 1257 if (DISTRIBUTE_OUT_NAME(filter)) {
1258 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1259
d62a17ae 1260 if (access_list_apply(DISTRIBUTE_OUT(filter), p) == FILTER_DENY)
1261 return FILTER_DENY;
1262 }
1263
1264 if (PREFIX_LIST_OUT_NAME(filter)) {
1265 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1266
d62a17ae 1267 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
1268 == PREFIX_DENY)
1269 return FILTER_DENY;
1270 }
718e3744 1271
d62a17ae 1272 if (FILTER_LIST_OUT_NAME(filter)) {
1273 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1274
d62a17ae 1275 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
1276 == AS_FILTER_DENY)
1277 return FILTER_DENY;
1278 }
718e3744 1279
d62a17ae 1280 return FILTER_PERMIT;
650f76c2 1281#undef FILTER_EXIST_WARN
718e3744 1282}
1283
1284/* If community attribute includes no_export then return 1. */
3dc339cd 1285static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1286{
1287 if (attr->community) {
1288 /* NO_ADVERTISE check. */
1289 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
3dc339cd 1290 return true;
d62a17ae 1291
1292 /* NO_EXPORT check. */
1293 if (peer->sort == BGP_PEER_EBGP
1294 && community_include(attr->community, COMMUNITY_NO_EXPORT))
3dc339cd 1295 return true;
d62a17ae 1296
1297 /* NO_EXPORT_SUBCONFED check. */
1298 if (peer->sort == BGP_PEER_EBGP
1299 || peer->sort == BGP_PEER_CONFED)
1300 if (community_include(attr->community,
1301 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1302 return true;
d62a17ae 1303 }
3dc339cd 1304 return false;
718e3744 1305}
1306
1307/* Route reflection loop check. */
3dc339cd 1308static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1309{
d62a17ae 1310 struct in_addr cluster_id;
718e3744 1311
d62a17ae 1312 if (attr->cluster) {
1313 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1314 cluster_id = peer->bgp->cluster_id;
1315 else
1316 cluster_id = peer->bgp->router_id;
1317
1318 if (cluster_loop_check(attr->cluster, cluster_id))
3dc339cd 1319 return true;
d62a17ae 1320 }
3dc339cd 1321 return false;
718e3744 1322}
6b0655a2 1323
5a1ae2c2 1324static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1325 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1326 const char *rmap_name, mpls_label_t *label,
196c6b09 1327 uint32_t num_labels, struct bgp_node *rn)
718e3744 1328{
d62a17ae 1329 struct bgp_filter *filter;
82b692c0
LK
1330 struct bgp_path_info rmap_path = { 0 };
1331 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1332 route_map_result_t ret;
1333 struct route_map *rmap = NULL;
718e3744 1334
d62a17ae 1335 filter = &peer->filter[afi][safi];
718e3744 1336
d62a17ae 1337 /* Apply default weight value. */
1338 if (peer->weight[afi][safi])
1339 attr->weight = peer->weight[afi][safi];
718e3744 1340
d62a17ae 1341 if (rmap_name) {
1342 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1343
d62a17ae 1344 if (rmap == NULL)
1345 return RMAP_DENY;
1346 } else {
1347 if (ROUTE_MAP_IN_NAME(filter)) {
1348 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1349
d62a17ae 1350 if (rmap == NULL)
1351 return RMAP_DENY;
1352 }
1353 }
0b16f239 1354
d62a17ae 1355 /* Route map apply. */
1356 if (rmap) {
40381db7 1357 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1358 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1359 rmap_path.peer = peer;
1360 rmap_path.attr = attr;
82b692c0 1361 rmap_path.extra = &extra;
196c6b09
LK
1362 rmap_path.net = rn;
1363
82b692c0
LK
1364 extra.num_labels = num_labels;
1365 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1366 memcpy(extra.label, label,
1367 num_labels * sizeof(mpls_label_t));
718e3744 1368
d62a17ae 1369 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1370
d62a17ae 1371 /* Apply BGP route map to the attribute. */
40381db7 1372 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
0b16f239 1373
d62a17ae 1374 peer->rmap_type = 0;
0b16f239 1375
1f2263be 1376 if (ret == RMAP_DENYMATCH)
d62a17ae 1377 return RMAP_DENY;
0b16f239 1378 }
d62a17ae 1379 return RMAP_PERMIT;
0b16f239
DS
1380}
1381
5f040085 1382static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1383 struct attr *attr, afi_t afi, safi_t safi,
1384 const char *rmap_name)
0b16f239 1385{
40381db7 1386 struct bgp_path_info rmap_path;
d62a17ae 1387 route_map_result_t ret;
1388 struct route_map *rmap = NULL;
d7c0a89a 1389 uint8_t rmap_type;
0b16f239 1390
b787157a
DS
1391 /*
1392 * So if we get to this point and have no rmap_name
1393 * we want to just show the output as it currently
1394 * exists.
1395 */
1396 if (!rmap_name)
1397 return RMAP_PERMIT;
0b16f239 1398
d62a17ae 1399 /* Apply default weight value. */
1400 if (peer->weight[afi][safi])
1401 attr->weight = peer->weight[afi][safi];
0b16f239 1402
b787157a 1403 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1404
b787157a
DS
1405 /*
1406 * If we have a route map name and we do not find
1407 * the routemap that means we have an implicit
1408 * deny.
1409 */
1410 if (rmap == NULL)
1411 return RMAP_DENY;
0b16f239 1412
40381db7 1413 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1414 /* Route map apply. */
b787157a 1415 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1416 rmap_path.peer = peer;
1417 rmap_path.attr = attr;
0b16f239 1418
0f672529 1419 rmap_type = peer->rmap_type;
b787157a 1420 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1421
b787157a 1422 /* Apply BGP route map to the attribute. */
40381db7 1423 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
ac41b2a2 1424
0f672529 1425 peer->rmap_type = rmap_type;
b787157a
DS
1426
1427 if (ret == RMAP_DENYMATCH)
1428 /*
1429 * caller has multiple error paths with bgp_attr_flush()
1430 */
1431 return RMAP_DENY;
ac41b2a2 1432
d62a17ae 1433 return RMAP_PERMIT;
718e3744 1434}
6b0655a2 1435
5000f21c 1436/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1437static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1438 struct peer *peer, struct attr *attr)
1439{
1440 if (peer->sort == BGP_PEER_EBGP
1441 && (peer_af_flag_check(peer, afi, safi,
1442 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1443 || peer_af_flag_check(peer, afi, safi,
1444 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1445 || peer_af_flag_check(peer, afi, safi,
1446 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1447 || peer_af_flag_check(peer, afi, safi,
1448 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1449 // Take action on the entire aspath
1450 if (peer_af_flag_check(peer, afi, safi,
1451 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1452 || peer_af_flag_check(peer, afi, safi,
1453 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1454 if (peer_af_flag_check(
1455 peer, afi, safi,
1456 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1457 attr->aspath = aspath_replace_private_asns(
bf26b80e 1458 attr->aspath, bgp->as, peer->as);
d62a17ae 1459
1460 // The entire aspath consists of private ASNs so create
1461 // an empty aspath
1462 else if (aspath_private_as_check(attr->aspath))
1463 attr->aspath = aspath_empty_get();
1464
1465 // There are some public and some private ASNs, remove
1466 // the private ASNs
1467 else
1468 attr->aspath = aspath_remove_private_asns(
bf26b80e 1469 attr->aspath, peer->as);
d62a17ae 1470 }
1471
1472 // 'all' was not specified so the entire aspath must be private
1473 // ASNs
1474 // for us to do anything
1475 else if (aspath_private_as_check(attr->aspath)) {
1476 if (peer_af_flag_check(
1477 peer, afi, safi,
1478 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1479 attr->aspath = aspath_replace_private_asns(
bf26b80e 1480 attr->aspath, bgp->as, peer->as);
d62a17ae 1481 else
1482 attr->aspath = aspath_empty_get();
1483 }
1484 }
5000f21c
DS
1485}
1486
c7122e14 1487/* If this is an EBGP peer with as-override */
d62a17ae 1488static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1489 struct peer *peer, struct attr *attr)
1490{
1491 if (peer->sort == BGP_PEER_EBGP
1492 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1493 if (aspath_single_asn_check(attr->aspath, peer->as))
1494 attr->aspath = aspath_replace_specific_asn(
1495 attr->aspath, peer->as, bgp->as);
1496 }
1497}
1498
7f323236
DW
1499void bgp_attr_add_gshut_community(struct attr *attr)
1500{
1501 struct community *old;
1502 struct community *new;
1503 struct community *merge;
1504 struct community *gshut;
1505
1506 old = attr->community;
1507 gshut = community_str2com("graceful-shutdown");
1508
990f4f91 1509 assert(gshut);
1510
7f323236
DW
1511 if (old) {
1512 merge = community_merge(community_dup(old), gshut);
1513
a4d82a8a 1514 if (old->refcnt == 0)
3c1f53de 1515 community_free(&old);
7f323236
DW
1516
1517 new = community_uniq_sort(merge);
3c1f53de 1518 community_free(&merge);
7f323236
DW
1519 } else {
1520 new = community_dup(gshut);
1521 }
1522
3c1f53de 1523 community_free(&gshut);
7f323236
DW
1524 attr->community = new;
1525 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1526
1527 /* When we add the graceful-shutdown community we must also
1528 * lower the local-preference */
1529 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1530 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1531}
1532
1533
d7c0a89a 1534static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1535{
960035b2 1536 if (family == AF_INET) {
975a328e
DA
1537 attr->nexthop.s_addr = INADDR_ANY;
1538 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1539 }
d62a17ae 1540 if (family == AF_INET6)
1541 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1542 if (family == AF_EVPN)
1543 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1544}
1545
3dc339cd 1546bool subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
b8685f9b
DS
1547 struct update_subgroup *subgrp,
1548 const struct prefix *p, struct attr *attr)
d62a17ae 1549{
1550 struct bgp_filter *filter;
1551 struct peer *from;
1552 struct peer *peer;
1553 struct peer *onlypeer;
1554 struct bgp *bgp;
40381db7 1555 struct attr *piattr;
d62a17ae 1556 char buf[PREFIX_STRLEN];
b68885f9 1557 route_map_result_t ret;
d62a17ae 1558 int transparent;
1559 int reflect;
1560 afi_t afi;
1561 safi_t safi;
1562 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1563 bool nh_reset = false;
1564 uint64_t cum_bw;
d62a17ae 1565
1566 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1567 return false;
d62a17ae 1568
1569 afi = SUBGRP_AFI(subgrp);
1570 safi = SUBGRP_SAFI(subgrp);
1571 peer = SUBGRP_PEER(subgrp);
1572 onlypeer = NULL;
1573 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1574 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1575
40381db7 1576 from = pi->peer;
d62a17ae 1577 filter = &peer->filter[afi][safi];
1578 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1579 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1580 : pi->attr;
3f9c7369 1581
49e5a4a0 1582#ifdef ENABLE_BGP_VNC
d62a17ae 1583 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1584 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1585 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1586
1587 /*
1588 * direct and direct_ext type routes originate internally even
1589 * though they can have peer pointers that reference other
1590 * systems
1591 */
1592 prefix2str(p, buf, PREFIX_STRLEN);
1593 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1594 __func__, buf);
1595 samepeer_safe = 1;
1596 }
65efcfce
LB
1597#endif
1598
ddb5b488
PZ
1599 if (((afi == AFI_IP) || (afi == AFI_IP6))
1600 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1601 && (pi->type == ZEBRA_ROUTE_BGP)
1602 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1603
1604 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1605
1606 samepeer_safe = 1;
1607 }
1608
d62a17ae 1609 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1610 * pi is valid */
1611 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1612 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1613 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1614 return false;
d62a17ae 1615 }
adbac85e 1616
d62a17ae 1617 /* If this is not the bestpath then check to see if there is an enabled
1618 * addpath
1619 * feature that requires us to advertise it */
40381db7 1620 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1621 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1622 return false;
d62a17ae 1623 }
1624 }
06370dac 1625
d62a17ae 1626 /* Aggregate-address suppress check. */
40381db7 1627 if (pi->extra && pi->extra->suppress)
d62a17ae 1628 if (!UNSUPPRESS_MAP_NAME(filter)) {
3dc339cd 1629 return false;
d62a17ae 1630 }
3f9c7369 1631
13b7e7f0
DS
1632 /*
1633 * If we are doing VRF 2 VRF leaking via the import
1634 * statement, we want to prevent the route going
1635 * off box as that the RT and RD created are localy
1636 * significant and globaly useless.
1637 */
40381db7
DS
1638 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1639 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1640 return false;
13b7e7f0 1641
d62a17ae 1642 /* If it's labeled safi, make sure the route has a valid label. */
1643 if (safi == SAFI_LABELED_UNICAST) {
40381db7 1644 mpls_label_t label = bgp_adv_label(rn, pi, peer, afi, safi);
d62a17ae 1645 if (!bgp_is_valid_label(&label)) {
1646 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1647 zlog_debug("u%" PRIu64 ":s%" PRIu64
1648 " %s/%d is filtered - no label (%p)",
1649 subgrp->update_group->id, subgrp->id,
1650 inet_ntop(p->family, &p->u.prefix,
1651 buf, SU_ADDRSTRLEN),
1652 p->prefixlen, &label);
3dc339cd 1653 return false;
d62a17ae 1654 }
1655 }
cd1964ff 1656
d62a17ae 1657 /* Do not send back route to sender. */
1658 if (onlypeer && from == onlypeer) {
3dc339cd 1659 return false;
d62a17ae 1660 }
3f9c7369 1661
d62a17ae 1662 /* Do not send the default route in the BGP table if the neighbor is
1663 * configured for default-originate */
1664 if (CHECK_FLAG(peer->af_flags[afi][safi],
1665 PEER_FLAG_DEFAULT_ORIGINATE)) {
1666 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1667 return false;
d62a17ae 1668 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1669 return false;
d62a17ae 1670 }
4125bb67 1671
d62a17ae 1672 /* Transparency check. */
1673 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1674 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1675 transparent = 1;
1676 else
1677 transparent = 0;
1678
1679 /* If community is not disabled check the no-export and local. */
40381db7 1680 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1681 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1682 zlog_debug(
1683 "subgrpannouncecheck: community filter check fail");
3dc339cd 1684 return false;
d62a17ae 1685 }
3f9c7369 1686
d62a17ae 1687 /* If the attribute has originator-id and it is same as remote
1688 peer's id. */
40381db7
DS
1689 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1690 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1691 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1692 zlog_debug(
1693 "%s [Update:SEND] %s originator-id is same as "
1694 "remote router-id",
1695 onlypeer->host,
1696 prefix2str(p, buf, sizeof(buf)));
3dc339cd 1697 return false;
d62a17ae 1698 }
3f9c7369 1699
d62a17ae 1700 /* ORF prefix-list filter check */
1701 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1702 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1703 || CHECK_FLAG(peer->af_cap[afi][safi],
1704 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1705 if (peer->orf_plist[afi][safi]) {
1706 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1707 == PREFIX_DENY) {
1708 if (bgp_debug_update(NULL, p,
1709 subgrp->update_group, 0))
1710 zlog_debug(
1711 "%s [Update:SEND] %s is filtered via ORF",
1712 peer->host,
1713 prefix2str(p, buf,
1714 sizeof(buf)));
3dc339cd 1715 return false;
d62a17ae 1716 }
1717 }
1718
1719 /* Output filter check. */
40381db7 1720 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1721 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1722 zlog_debug("%s [Update:SEND] %s is filtered",
1723 peer->host, prefix2str(p, buf, sizeof(buf)));
3dc339cd 1724 return false;
d62a17ae 1725 }
3f9c7369 1726
d62a17ae 1727 /* AS path loop check. */
2b31007c
RZ
1728 if (onlypeer && onlypeer->as_path_loop_detection
1729 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1730 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1731 zlog_debug(
1732 "%s [Update:SEND] suppress announcement to peer AS %u "
1733 "that is part of AS path.",
1734 onlypeer->host, onlypeer->as);
3dc339cd 1735 return false;
d62a17ae 1736 }
3f9c7369 1737
d62a17ae 1738 /* If we're a CONFED we need to loop check the CONFED ID too */
1739 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1740 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1741 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1742 zlog_debug(
1743 "%s [Update:SEND] suppress announcement to peer AS %u"
1744 " is AS path.",
1745 peer->host, bgp->confed_id);
3dc339cd 1746 return false;
d62a17ae 1747 }
3f9c7369 1748 }
3f9c7369 1749
d62a17ae 1750 /* Route-Reflect check. */
1751 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1752 reflect = 1;
1753 else
1754 reflect = 0;
1755
1756 /* IBGP reflection check. */
1757 if (reflect && !samepeer_safe) {
1758 /* A route from a Client peer. */
1759 if (CHECK_FLAG(from->af_flags[afi][safi],
1760 PEER_FLAG_REFLECTOR_CLIENT)) {
1761 /* Reflect to all the Non-Client peers and also to the
1762 Client peers other than the originator. Originator
1763 check
1764 is already done. So there is noting to do. */
1765 /* no bgp client-to-client reflection check. */
892fedb6
DA
1766 if (CHECK_FLAG(bgp->flags,
1767 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 1768 if (CHECK_FLAG(peer->af_flags[afi][safi],
1769 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1770 return false;
d62a17ae 1771 } else {
1772 /* A route from a Non-client peer. Reflect to all other
1773 clients. */
1774 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1775 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1776 return false;
d62a17ae 1777 }
1778 }
3f9c7369 1779
d62a17ae 1780 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1781 *attr = *piattr;
d62a17ae 1782
1783 /* If local-preference is not set. */
1784 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1785 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1786 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1787 attr->local_pref = bgp->default_local_pref;
3f9c7369 1788 }
3f9c7369 1789
d62a17ae 1790 /* If originator-id is not set and the route is to be reflected,
1791 set the originator id */
1792 if (reflect
1793 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1794 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1795 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1796 }
3f9c7369 1797
d62a17ae 1798 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1799 */
1800 if (peer->sort == BGP_PEER_EBGP
1801 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1802 if (from != bgp->peer_self && !transparent
1803 && !CHECK_FLAG(peer->af_flags[afi][safi],
1804 PEER_FLAG_MED_UNCHANGED))
1805 attr->flag &=
1806 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1807 }
3f9c7369 1808
d62a17ae 1809 /* Since the nexthop attribute can vary per peer, it is not explicitly
1810 * set
1811 * in announce check, only certain flags and length (or number of
1812 * nexthops
1813 * -- for IPv6/MP_REACH) are set here in order to guide the update
1814 * formation
1815 * code in setting the nexthop(s) on a per peer basis in
1816 * reformat_peer().
1817 * Typically, the source nexthop in the attribute is preserved but in
1818 * the
1819 * scenarios where we know it will always be overwritten, we reset the
1820 * nexthop to "0" in an attempt to achieve better Update packing. An
1821 * example of this is when a prefix from each of 2 IBGP peers needs to
1822 * be
1823 * announced to an EBGP peer (and they have the same attributes barring
1824 * their nexthop).
1825 */
1826 if (reflect)
1827 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1828
1829#define NEXTHOP_IS_V6 \
1830 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1831 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1832 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1833 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1834
1835 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1836 * if
1837 * the peer (group) is configured to receive link-local nexthop
1838 * unchanged
c728d027
DA
1839 * and it is available in the prefix OR we're not reflecting the route,
1840 * link-local nexthop address is valid and
d62a17ae 1841 * the peer (group) to whom we're going to announce is on a shared
1842 * network
1843 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
1844 * By checking if nexthop LL address is valid we are sure that
1845 * we do not announce LL address as `::`.
d62a17ae 1846 */
1847 if (NEXTHOP_IS_V6) {
1848 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
1849 if ((CHECK_FLAG(peer->af_flags[afi][safi],
1850 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
1851 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
1852 || (!reflect
1853 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
1854 && peer->shared_network
d62a17ae 1855 && (from == bgp->peer_self
1856 || peer->sort == BGP_PEER_EBGP))) {
1857 attr->mp_nexthop_len =
1858 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
1859 }
3f9c7369 1860
d62a17ae 1861 /* Clear off link-local nexthop in source, whenever it is not
1862 * needed to
1863 * ensure more prefixes share the same attribute for
1864 * announcement.
1865 */
1866 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
1867 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
1868 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
1869 }
3f9c7369 1870
d62a17ae 1871 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
1872 bgp_peer_as_override(bgp, afi, safi, peer, attr);
1873
1874 /* Route map & unsuppress-map apply. */
40381db7 1875 if (ROUTE_MAP_OUT_NAME(filter) || (pi->extra && pi->extra->suppress)) {
b8694ef4
DS
1876 struct bgp_path_info rmap_path = {0};
1877 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
1878 struct attr dummy_attr = {0};
d62a17ae 1879
e34291b8 1880 /* Fill temp path_info */
1881 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra,
1882 rn, pi, peer, attr);
16f7ce2b 1883
d62a17ae 1884 /* don't confuse inbound and outbound setting */
1885 RESET_FLAG(attr->rmap_change_flags);
1886
1887 /*
1888 * The route reflector is not allowed to modify the attributes
1889 * of the reflected IBGP routes unless explicitly allowed.
1890 */
1891 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
1892 && !CHECK_FLAG(bgp->flags,
1893 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 1894 dummy_attr = *attr;
40381db7 1895 rmap_path.attr = &dummy_attr;
d62a17ae 1896 }
3f9c7369 1897
d62a17ae 1898 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 1899
40381db7 1900 if (pi->extra && pi->extra->suppress)
d62a17ae 1901 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
40381db7 1902 RMAP_BGP, &rmap_path);
d62a17ae 1903 else
1904 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
40381db7 1905 RMAP_BGP, &rmap_path);
d62a17ae 1906
1907 peer->rmap_type = 0;
1908
1909 if (ret == RMAP_DENYMATCH) {
778048bf
AD
1910 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1911 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1912 peer->host, prefix2str(p, buf, sizeof(buf)));
1913
d62a17ae 1914 bgp_attr_flush(attr);
3dc339cd 1915 return false;
d62a17ae 1916 }
3f9c7369 1917 }
3f9c7369 1918
9dac9fc8
DA
1919 /* RFC 8212 to prevent route leaks.
1920 * This specification intends to improve this situation by requiring the
1921 * explicit configuration of both BGP Import and Export Policies for any
1922 * External BGP (EBGP) session such as customers, peers, or
1923 * confederation boundaries for all enabled address families. Through
1924 * codification of the aforementioned requirement, operators will
1925 * benefit from consistent behavior across different BGP
1926 * implementations.
1927 */
1d3fdccf 1928 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
9dac9fc8 1929 if (!bgp_outbound_policy_exists(peer, filter))
3dc339cd 1930 return false;
9dac9fc8 1931
fb29348a
DA
1932 /* draft-ietf-idr-deprecate-as-set-confed-set
1933 * Filter routes having AS_SET or AS_CONFED_SET in the path.
1934 * Eventually, This document (if approved) updates RFC 4271
1935 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
1936 * and obsoletes RFC 6472.
1937 */
1938 if (peer->bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED)
1939 if (aspath_check_as_sets(attr->aspath))
3dc339cd 1940 return false;
fb29348a 1941
33d022bc
DA
1942 /* Codification of AS 0 Processing */
1943 if (aspath_check_as_zero(attr->aspath))
1944 return 0;
1945
892fedb6 1946 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
a4d82a8a
PZ
1947 if (peer->sort == BGP_PEER_IBGP
1948 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
1949 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1950 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1951 } else {
1952 bgp_attr_add_gshut_community(attr);
1953 }
1954 }
1955
d62a17ae 1956 /* After route-map has been applied, we check to see if the nexthop to
1957 * be carried in the attribute (that is used for the announcement) can
1958 * be cleared off or not. We do this in all cases where we would be
1959 * setting the nexthop to "ourselves". For IPv6, we only need to
1960 * consider
1961 * the global nexthop here; the link-local nexthop would have been
1962 * cleared
1963 * already, and if not, it is required by the update formation code.
1964 * Also see earlier comments in this function.
1965 */
1966 /*
1967 * If route-map has performed some operation on the nexthop or the peer
1968 * configuration says to pass it unchanged, we cannot reset the nexthop
1969 * here, so only attempt to do it if these aren't true. Note that the
1970 * route-map handler itself might have cleared the nexthop, if for
1971 * example,
1972 * it is configured as 'peer-address'.
1973 */
1974 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 1975 piattr->rmap_change_flags)
d62a17ae 1976 && !transparent
1977 && !CHECK_FLAG(peer->af_flags[afi][safi],
1978 PEER_FLAG_NEXTHOP_UNCHANGED)) {
1979 /* We can reset the nexthop, if setting (or forcing) it to
1980 * 'self' */
1981 if (CHECK_FLAG(peer->af_flags[afi][safi],
1982 PEER_FLAG_NEXTHOP_SELF)
1983 || CHECK_FLAG(peer->af_flags[afi][safi],
1984 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
1985 if (!reflect
1986 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 1987 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 1988 subgroup_announce_reset_nhop(
1989 (peer_cap_enhe(peer, afi, safi)
1990 ? AF_INET6
1991 : p->family),
1992 attr);
7b651a32 1993 nh_reset = true;
1994 }
d62a17ae 1995 } else if (peer->sort == BGP_PEER_EBGP) {
1996 /* Can also reset the nexthop if announcing to EBGP, but
1997 * only if
1998 * no peer in the subgroup is on a shared subnet.
1999 * Note: 3rd party nexthop currently implemented for
2000 * IPv4 only.
2001 */
737af885
BS
2002 if ((p->family == AF_INET) &&
2003 (!bgp_subgrp_multiaccess_check_v4(
2004 piattr->nexthop,
7b651a32 2005 subgrp, from))) {
d62a17ae 2006 subgroup_announce_reset_nhop(
2007 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2008 ? AF_INET6
2009 : p->family),
737af885 2010 attr);
7b651a32 2011 nh_reset = true;
2012 }
737af885
BS
2013
2014 if ((p->family == AF_INET6) &&
2015 (!bgp_subgrp_multiaccess_check_v6(
2016 piattr->mp_nexthop_global,
7b651a32 2017 subgrp, from))) {
737af885
BS
2018 subgroup_announce_reset_nhop(
2019 (peer_cap_enhe(peer, afi, safi)
2020 ? AF_INET6
2021 : p->family),
2022 attr);
7b651a32 2023 nh_reset = true;
2024 }
737af885
BS
2025
2026
2027
40381db7 2028 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2029 /*
2030 * This flag is used for leaked vpn-vrf routes
2031 */
2032 int family = p->family;
2033
2034 if (peer_cap_enhe(peer, afi, safi))
2035 family = AF_INET6;
2036
2037 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2038 zlog_debug(
1defdda8 2039 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2040 __func__, family2str(family));
2041 subgroup_announce_reset_nhop(family, attr);
7b651a32 2042 nh_reset = true;
d62a17ae 2043 }
63696f1d 2044 }
960035b2 2045
63696f1d 2046 /* If IPv6/MP and nexthop does not have any override and happens
2047 * to
2048 * be a link-local address, reset it so that we don't pass along
2049 * the
2050 * source's link-local IPv6 address to recipients who may not be
2051 * on
2052 * the same interface.
2053 */
2054 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2055 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2056 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2057 nh_reset = true;
2058 }
d62a17ae 2059 }
3f9c7369 2060
7b651a32 2061 /*
2062 * When the next hop is set to ourselves, if all multipaths have
2063 * link-bandwidth announce the cumulative bandwidth as that makes
2064 * the most sense. However, don't modify if the link-bandwidth has
2065 * been explicitly set by user policy.
2066 */
2067 if (nh_reset &&
f7e1c681 2068 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2069 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2070 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2071 attr->ecommunity = ecommunity_replace_linkbw(
2072 bgp->as, attr->ecommunity, cum_bw);
2073
3dc339cd 2074 return true;
3f9c7369
DS
2075}
2076
f009ff26 2077static int bgp_route_select_timer_expire(struct thread *thread)
2078{
2079 struct afi_safi_info *info;
2080 afi_t afi;
2081 safi_t safi;
2082 struct bgp *bgp;
2083
2084 info = THREAD_ARG(thread);
2085 afi = info->afi;
2086 safi = info->safi;
2087 bgp = info->bgp;
2088
2089 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2090 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2091 safi);
f009ff26 2092
2093 bgp->gr_info[afi][safi].t_route_select = NULL;
2094
2095 XFREE(MTYPE_TMP, info);
2096
2097 /* Best path selection */
2098 return bgp_best_path_select_defer(bgp, afi, safi);
2099}
2100
d62a17ae 2101void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
2102 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2103 struct bgp_path_info_pair *result, afi_t afi,
2104 safi_t safi)
2105{
2106 struct bgp_path_info *new_select;
2107 struct bgp_path_info *old_select;
40381db7
DS
2108 struct bgp_path_info *pi;
2109 struct bgp_path_info *pi1;
2110 struct bgp_path_info *pi2;
2111 struct bgp_path_info *nextpi = NULL;
d62a17ae 2112 int paths_eq, do_mpath, debug;
2113 struct list mp_list;
2114 char pfx_buf[PREFIX2STR_BUFFER];
2115 char path_buf[PATH_ADDPATH_STR_BUFFER];
2116
2117 bgp_mp_list_init(&mp_list);
2118 do_mpath =
2119 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2120
cb9f254c 2121 debug = bgp_debug_bestpath(rn);
d62a17ae 2122
2123 if (debug)
b54892e0 2124 prefix2str(bgp_node_get_prefix(rn), pfx_buf, sizeof(pfx_buf));
d62a17ae 2125
19ea4cec 2126 rn->reason = bgp_path_selection_none;
d62a17ae 2127 /* bgp deterministic-med */
2128 new_select = NULL;
892fedb6 2129 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2130
1defdda8 2131 /* Clear BGP_PATH_DMED_SELECTED for all paths */
6f94b685
DS
2132 for (pi1 = bgp_node_get_bgp_path_info(rn); pi1;
2133 pi1 = pi1->next)
40381db7 2134 bgp_path_info_unset_flag(rn, pi1,
18ee8310 2135 BGP_PATH_DMED_SELECTED);
d62a17ae 2136
6f94b685
DS
2137 for (pi1 = bgp_node_get_bgp_path_info(rn); pi1;
2138 pi1 = pi1->next) {
40381db7 2139 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2140 continue;
40381db7 2141 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2142 continue;
ea8b2282 2143 if (pi1->peer != bgp->peer_self)
40381db7 2144 if (pi1->peer->status != Established)
d62a17ae 2145 continue;
2146
40381db7
DS
2147 new_select = pi1;
2148 if (pi1->next) {
2149 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2150 if (CHECK_FLAG(pi2->flags,
1defdda8 2151 BGP_PATH_DMED_CHECK))
d62a17ae 2152 continue;
40381db7 2153 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2154 continue;
ea8b2282 2155 if (pi2->peer != bgp->peer_self
d62a17ae 2156 && !CHECK_FLAG(
ea8b2282
DS
2157 pi2->peer->sflags,
2158 PEER_STATUS_NSF_WAIT))
40381db7 2159 if (pi2->peer->status
d62a17ae 2160 != Established)
2161 continue;
2162
121e245d
DS
2163 if (!aspath_cmp_left(pi1->attr->aspath,
2164 pi2->attr->aspath)
2165 && !aspath_cmp_left_confed(
40381db7 2166 pi1->attr->aspath,
121e245d
DS
2167 pi2->attr->aspath))
2168 continue;
d62a17ae 2169
121e245d
DS
2170 if (bgp_path_info_cmp(
2171 bgp, pi2, new_select,
2172 &paths_eq, mpath_cfg, debug,
fdf81fa0
DS
2173 pfx_buf, afi, safi,
2174 &rn->reason)) {
121e245d
DS
2175 bgp_path_info_unset_flag(
2176 rn, new_select,
2177 BGP_PATH_DMED_SELECTED);
2178 new_select = pi2;
d62a17ae 2179 }
121e245d
DS
2180
2181 bgp_path_info_set_flag(
2182 rn, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2183 }
2184 }
18ee8310
DS
2185 bgp_path_info_set_flag(rn, new_select,
2186 BGP_PATH_DMED_CHECK);
2187 bgp_path_info_set_flag(rn, new_select,
2188 BGP_PATH_DMED_SELECTED);
d62a17ae 2189
2190 if (debug) {
18ee8310
DS
2191 bgp_path_info_path_with_addpath_rx_str(
2192 new_select, path_buf);
c66faab1 2193 zlog_debug("%s: %s is the bestpath from AS %u",
d62a17ae 2194 pfx_buf, path_buf,
2195 aspath_get_first_as(
2196 new_select->attr->aspath));
2197 }
2198 }
2199 }
96450faf 2200
d62a17ae 2201 /* Check old selected route and new selected route. */
2202 old_select = NULL;
2203 new_select = NULL;
6f94b685
DS
2204 for (pi = bgp_node_get_bgp_path_info(rn);
2205 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2206 enum bgp_path_selection_reason reason;
2207
40381db7
DS
2208 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2209 old_select = pi;
d62a17ae 2210
40381db7 2211 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2212 /* reap REMOVED routes, if needs be
2213 * selected route must stay for a while longer though
2214 */
40381db7
DS
2215 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2216 && (pi != old_select))
2217 bgp_path_info_reap(rn, pi);
d62a17ae 2218
ddb5b488 2219 if (debug)
40381db7
DS
2220 zlog_debug("%s: pi %p in holddown", __func__,
2221 pi);
ddb5b488 2222
d62a17ae 2223 continue;
2224 }
96450faf 2225
40381db7
DS
2226 if (pi->peer && pi->peer != bgp->peer_self
2227 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2228 if (pi->peer->status != Established) {
ddb5b488
PZ
2229
2230 if (debug)
2231 zlog_debug(
40381db7
DS
2232 "%s: pi %p non self peer %s not estab state",
2233 __func__, pi, pi->peer->host);
ddb5b488 2234
d62a17ae 2235 continue;
ddb5b488 2236 }
9fbdd100 2237
892fedb6 2238 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7
DS
2239 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
2240 bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2241 if (debug)
40381db7 2242 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2243 continue;
2244 }
9fbdd100 2245
40381db7 2246 bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK);
06370dac 2247
19ea4cec 2248 reason = rn->reason;
40381db7 2249 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
fdf81fa0 2250 debug, pfx_buf, afi, safi, &rn->reason)) {
19ea4cec
DS
2251 if (new_select == NULL &&
2252 reason != bgp_path_selection_none)
2253 rn->reason = reason;
40381db7 2254 new_select = pi;
d62a17ae 2255 }
2256 }
718e3744 2257
d62a17ae 2258 /* Now that we know which path is the bestpath see if any of the other
2259 * paths
2260 * qualify as multipaths
2261 */
2262 if (debug) {
2263 if (new_select)
18ee8310
DS
2264 bgp_path_info_path_with_addpath_rx_str(new_select,
2265 path_buf);
d62a17ae 2266 else
2267 sprintf(path_buf, "NONE");
2268 zlog_debug(
2269 "%s: After path selection, newbest is %s oldbest was %s",
2270 pfx_buf, path_buf,
2271 old_select ? old_select->peer->host : "NONE");
96450faf 2272 }
9fbdd100 2273
d62a17ae 2274 if (do_mpath && new_select) {
6f94b685
DS
2275 for (pi = bgp_node_get_bgp_path_info(rn);
2276 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2277
2278 if (debug)
18ee8310 2279 bgp_path_info_path_with_addpath_rx_str(
40381db7 2280 pi, path_buf);
d62a17ae 2281
40381db7 2282 if (pi == new_select) {
d62a17ae 2283 if (debug)
2284 zlog_debug(
2285 "%s: %s is the bestpath, add to the multipath list",
2286 pfx_buf, path_buf);
40381db7 2287 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2288 continue;
2289 }
2290
40381db7 2291 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2292 continue;
2293
40381db7
DS
2294 if (pi->peer && pi->peer != bgp->peer_self
2295 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2296 PEER_STATUS_NSF_WAIT))
40381db7 2297 if (pi->peer->status != Established)
d62a17ae 2298 continue;
2299
40381db7 2300 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2301 if (debug)
2302 zlog_debug(
2303 "%s: %s has the same nexthop as the bestpath, skip it",
2304 pfx_buf, path_buf);
2305 continue;
2306 }
2307
40381db7 2308 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0
DS
2309 mpath_cfg, debug, pfx_buf, afi, safi,
2310 &rn->reason);
d62a17ae 2311
2312 if (paths_eq) {
2313 if (debug)
2314 zlog_debug(
2315 "%s: %s is equivalent to the bestpath, add to the multipath list",
2316 pfx_buf, path_buf);
40381db7 2317 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2318 }
2319 }
2320 }
fee0f4c6 2321
18ee8310
DS
2322 bgp_path_info_mpath_update(rn, new_select, old_select, &mp_list,
2323 mpath_cfg);
2324 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2325 bgp_mp_list_clear(&mp_list);
96450faf 2326
dcc68b5e
MS
2327 bgp_addpath_update_ids(bgp, rn, afi, safi);
2328
d62a17ae 2329 result->old = old_select;
2330 result->new = new_select;
96450faf 2331
d62a17ae 2332 return;
fee0f4c6 2333}
2334
3f9c7369
DS
2335/*
2336 * A new route/change in bestpath of an existing route. Evaluate the path
2337 * for advertisement to the subgroup.
2338 */
3dc339cd
DA
2339void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2340 struct bgp_path_info *selected,
2341 struct bgp_node *rn,
2342 uint32_t addpath_tx_id)
d62a17ae 2343{
b54892e0 2344 const struct prefix *p;
d62a17ae 2345 struct peer *onlypeer;
2346 struct attr attr;
2347 afi_t afi;
2348 safi_t safi;
adbac85e 2349
b54892e0 2350 p = bgp_node_get_prefix(rn);
d62a17ae 2351 afi = SUBGRP_AFI(subgrp);
2352 safi = SUBGRP_SAFI(subgrp);
2353 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2354 : NULL);
2355
e0207895
PZ
2356 if (BGP_DEBUG(update, UPDATE_OUT)) {
2357 char buf_prefix[PREFIX_STRLEN];
2358 prefix2str(p, buf_prefix, sizeof(buf_prefix));
ddb5b488
PZ
2359 zlog_debug("%s: p=%s, selected=%p", __func__, buf_prefix,
2360 selected);
e0207895
PZ
2361 }
2362
d62a17ae 2363 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2364 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2365 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2366 return;
d62a17ae 2367
2368 memset(&attr, 0, sizeof(struct attr));
2369 /* It's initialized in bgp_announce_check() */
2370
2371 /* Announcement to the subgroup. If the route is filtered withdraw it.
2372 */
2373 if (selected) {
2374 if (subgroup_announce_check(rn, selected, subgrp, p, &attr))
2375 bgp_adj_out_set_subgroup(rn, subgrp, &attr, selected);
2376 else
2377 bgp_adj_out_unset_subgroup(rn, subgrp, 1,
dcc68b5e 2378 addpath_tx_id);
d62a17ae 2379 }
2380
2381 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2382 else {
2383 bgp_adj_out_unset_subgroup(rn, subgrp, 1, addpath_tx_id);
2384 }
200df115 2385}
fee0f4c6 2386
3064bf43 2387/*
e1072051 2388 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2389 * This is called at the end of route processing.
3064bf43 2390 */
d62a17ae 2391void bgp_zebra_clear_route_change_flags(struct bgp_node *rn)
3064bf43 2392{
40381db7 2393 struct bgp_path_info *pi;
3064bf43 2394
6f94b685 2395 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 2396 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2397 continue;
40381db7
DS
2398 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2399 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2400 }
3064bf43 2401}
2402
2403/*
2404 * Has the route changed from the RIB's perspective? This is invoked only
2405 * if the route selection returns the same best route as earlier - to
2406 * determine if we need to update zebra or not.
2407 */
3dc339cd
DA
2408bool bgp_zebra_has_route_changed(struct bgp_node *rn,
2409 struct bgp_path_info *selected)
d62a17ae 2410{
4b7e6066 2411 struct bgp_path_info *mpinfo;
d62a17ae 2412
2bb9eff4
DS
2413 /* If this is multipath, check all selected paths for any nexthop
2414 * change or attribute change. Some attribute changes (e.g., community)
2415 * aren't of relevance to the RIB, but we'll update zebra to ensure
2416 * we handle the case of BGP nexthop change. This is the behavior
2417 * when the best path has an attribute change anyway.
d62a17ae 2418 */
1defdda8 2419 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2420 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2421 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2422 return true;
d62a17ae 2423
2bb9eff4
DS
2424 /*
2425 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2426 */
18ee8310
DS
2427 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2428 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2429 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2430 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2431 return true;
d62a17ae 2432 }
3064bf43 2433
d62a17ae 2434 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2435 return false;
3064bf43 2436}
2437
d62a17ae 2438struct bgp_process_queue {
2439 struct bgp *bgp;
a4d82a8a 2440 STAILQ_HEAD(, bgp_node) pqueue;
aac24838
JB
2441#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2442 unsigned int flags;
2443 unsigned int queued;
200df115 2444};
2445
3b0c17e1 2446static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
2447 safi_t safi, struct bgp_node *rn,
2448 struct bgp_path_info *new_select,
2449 struct bgp_path_info *old_select)
2450{
2451 const struct prefix *p = bgp_node_get_prefix(rn);
2452
2453 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2454 return;
2455
2456 if (advertise_type5_routes(bgp, afi) && new_select
2457 && is_route_injectable_into_evpn(new_select)) {
2458
2459 /* apply the route-map */
2460 if (bgp->adv_cmd_rmap[afi][safi].map) {
2461 route_map_result_t ret;
2462 struct bgp_path_info rmap_path;
2463 struct bgp_path_info_extra rmap_path_extra;
2464 struct attr dummy_attr;
2465
2466 dummy_attr = *new_select->attr;
2467
2468 /* Fill temp path_info */
2469 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, rn,
2470 new_select, new_select->peer,
2471 &dummy_attr);
2472
2473 RESET_FLAG(dummy_attr.rmap_change_flags);
2474
2475 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
2476 p, RMAP_BGP, &rmap_path);
2477
2478 if (ret == RMAP_DENYMATCH) {
2479 bgp_attr_flush(&dummy_attr);
2480 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2481 safi);
2482 } else
2483 bgp_evpn_advertise_type5_route(
2484 bgp, p, &dummy_attr, afi, safi);
2485 } else {
2486 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2487 afi, safi);
2488 }
2489 } else if (advertise_type5_routes(bgp, afi) && old_select
2490 && is_route_injectable_into_evpn(old_select))
2491 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2492}
2493
3103e8d2
DS
2494/*
2495 * old_select = The old best path
2496 * new_select = the new best path
2497 *
2498 * if (!old_select && new_select)
2499 * We are sending new information on.
2500 *
2501 * if (old_select && new_select) {
2502 * if (new_select != old_select)
2503 * We have a new best path send a change
2504 * else
2505 * We've received a update with new attributes that needs
2506 * to be passed on.
2507 * }
2508 *
2509 * if (old_select && !new_select)
2510 * We have no eligible route that we can announce or the rn
2511 * is being removed.
2512 */
aac24838
JB
2513static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
2514 afi_t afi, safi_t safi)
d62a17ae 2515{
4b7e6066
DS
2516 struct bgp_path_info *new_select;
2517 struct bgp_path_info *old_select;
2518 struct bgp_path_info_pair old_and_new;
ddb5b488 2519 int debug = 0;
d62a17ae 2520
892fedb6 2521 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
f4c713ae 2522 if (rn)
cb9f254c 2523 debug = bgp_debug_bestpath(rn);
b54892e0 2524 if (debug)
f4c713ae 2525 zlog_debug(
b54892e0
DS
2526 "%s: bgp delete in progress, ignoring event, p=%pRN",
2527 __func__, rn);
f4c713ae
LB
2528 return;
2529 }
d62a17ae 2530 /* Is it end of initial update? (after startup) */
2531 if (!rn) {
2532 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2533 sizeof(bgp->update_delay_zebra_resume_time));
2534
2535 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2536 FOREACH_AFI_SAFI (afi, safi) {
2537 if (bgp_fibupd_safi(safi))
2538 bgp_zebra_announce_table(bgp, afi, safi);
2539 }
d62a17ae 2540 bgp->main_peers_update_hold = 0;
2541
2542 bgp_start_routeadv(bgp);
aac24838 2543 return;
d62a17ae 2544 }
cb1faec9 2545
b54892e0 2546 const struct prefix *p = bgp_node_get_prefix(rn);
b575a12c 2547
cb9f254c 2548 debug = bgp_debug_bestpath(rn);
b54892e0
DS
2549 if (debug)
2550 zlog_debug("%s: p=%pRN afi=%s, safi=%s start", __func__, rn,
ddb5b488 2551 afi2str(afi), safi2str(safi));
ddb5b488 2552
f009ff26 2553 /* The best path calculation for the route is deferred if
2554 * BGP_NODE_SELECT_DEFER is set
2555 */
2556 if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
2557 if (BGP_DEBUG(update, UPDATE_OUT))
2089dd80 2558 zlog_debug("SELECT_DEFER flag set for route %p", rn);
f009ff26 2559 return;
2560 }
2561
d62a17ae 2562 /* Best path selection. */
2563 bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new,
2564 afi, safi);
2565 old_select = old_and_new.old;
2566 new_select = old_and_new.new;
2567
2568 /* Do we need to allocate or free labels?
2569 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2570 * necessary to do this upon changes to best path. Exceptions:
2571 * - label index has changed -> recalculate resulting label
2572 * - path_info sub_type changed -> switch to/from implicit-null
2573 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2574 */
318cac96 2575 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2576 if (new_select) {
2577 if (!old_select
2578 || bgp_label_index_differs(new_select, old_select)
57592a53
AD
2579 || new_select->sub_type != old_select->sub_type
2580 || !bgp_is_valid_label(&rn->local_label)) {
2581 /* Enforced penultimate hop popping:
2582 * implicit-null for local routes, aggregate
2583 * and redistributed routes
2584 */
d62a17ae 2585 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2586 || new_select->sub_type
2587 == BGP_ROUTE_AGGREGATE
2588 || new_select->sub_type
2589 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2590 if (CHECK_FLAG(
2591 rn->flags,
2592 BGP_NODE_REGISTERED_FOR_LABEL))
2593 bgp_unregister_for_label(rn);
70e98a7f 2594 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
d62a17ae 2595 &rn->local_label);
2596 bgp_set_valid_label(&rn->local_label);
2597 } else
2598 bgp_register_for_label(rn, new_select);
2599 }
a4d82a8a
PZ
2600 } else if (CHECK_FLAG(rn->flags,
2601 BGP_NODE_REGISTERED_FOR_LABEL)) {
d62a17ae 2602 bgp_unregister_for_label(rn);
318cac96
DW
2603 }
2604 } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
2605 bgp_unregister_for_label(rn);
d62a17ae 2606 }
cd1964ff 2607
b54892e0 2608 if (debug)
ddb5b488 2609 zlog_debug(
b54892e0
DS
2610 "%s: p=%pRN afi=%s, safi=%s, old_select=%p, new_select=%p",
2611 __func__, rn, afi2str(afi), safi2str(safi),
ddb5b488 2612 old_select, new_select);
ddb5b488 2613
d62a17ae 2614 /* If best route remains the same and this is not due to user-initiated
2615 * clear, see exactly what needs to be done.
2616 */
d62a17ae 2617 if (old_select && old_select == new_select
2618 && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
1defdda8 2619 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2620 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 2621 if (bgp_zebra_has_route_changed(rn, old_select)) {
49e5a4a0 2622#ifdef ENABLE_BGP_VNC
d62a17ae 2623 vnc_import_bgp_add_route(bgp, p, old_select);
2624 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2625#endif
bb744275 2626 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2627 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2628
2629 if (new_select->type == ZEBRA_ROUTE_BGP
2630 && (new_select->sub_type == BGP_ROUTE_NORMAL
2631 || new_select->sub_type
2632 == BGP_ROUTE_IMPORTED))
2633
2634 bgp_zebra_announce(rn, p, old_select,
2635 bgp, afi, safi);
2636 }
d62a17ae 2637 }
d62a17ae 2638
2639 /* If there is a change of interest to peers, reannounce the
2640 * route. */
1defdda8 2641 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 2642 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
d62a17ae 2643 || CHECK_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED)) {
2644 group_announce_route(bgp, afi, safi, rn, new_select);
2645
2646 /* unicast routes must also be annouced to
2647 * labeled-unicast update-groups */
2648 if (safi == SAFI_UNICAST)
2649 group_announce_route(bgp, afi,
2650 SAFI_LABELED_UNICAST, rn,
2651 new_select);
2652
1defdda8 2653 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2654 UNSET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED);
2655 }
fee0f4c6 2656
3b0c17e1 2657 /* advertise/withdraw type-5 routes */
2658 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2659 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2660 bgp_process_evpn_route_injection(
2661 bgp, afi, safi, rn, old_select, old_select);
2662
b1875e65 2663 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2664 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
2665 bgp_zebra_clear_route_change_flags(rn);
d62a17ae 2666 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2667 return;
d62a17ae 2668 }
8ad7271d 2669
d62a17ae 2670 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2671 */
2672 UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR);
2673
2674 /* bestpath has changed; bump version */
2675 if (old_select || new_select) {
2676 bgp_bump_version(rn);
2677
2678 if (!bgp->t_rmap_def_originate_eval) {
2679 bgp_lock(bgp);
2680 thread_add_timer(
2681 bm->master,
2682 update_group_refresh_default_originate_route_map,
2683 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2684 &bgp->t_rmap_def_originate_eval);
2685 }
2686 }
3f9c7369 2687
d62a17ae 2688 if (old_select)
18ee8310 2689 bgp_path_info_unset_flag(rn, old_select, BGP_PATH_SELECTED);
d62a17ae 2690 if (new_select) {
ddb5b488
PZ
2691 if (debug)
2692 zlog_debug("%s: setting SELECTED flag", __func__);
18ee8310
DS
2693 bgp_path_info_set_flag(rn, new_select, BGP_PATH_SELECTED);
2694 bgp_path_info_unset_flag(rn, new_select, BGP_PATH_ATTR_CHANGED);
1defdda8 2695 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 2696 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 2697 }
338b3424 2698
49e5a4a0 2699#ifdef ENABLE_BGP_VNC
d62a17ae 2700 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2701 if (old_select != new_select) {
2702 if (old_select) {
2703 vnc_import_bgp_exterior_del_route(bgp, p,
2704 old_select);
2705 vnc_import_bgp_del_route(bgp, p, old_select);
2706 }
2707 if (new_select) {
2708 vnc_import_bgp_exterior_add_route(bgp, p,
2709 new_select);
2710 vnc_import_bgp_add_route(bgp, p, new_select);
2711 }
2712 }
2713 }
65efcfce
LB
2714#endif
2715
d62a17ae 2716 group_announce_route(bgp, afi, safi, rn, new_select);
2717
2718 /* unicast routes must also be annouced to labeled-unicast update-groups
2719 */
2720 if (safi == SAFI_UNICAST)
2721 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, rn,
2722 new_select);
2723
2724 /* FIB update. */
2725 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2726 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2727 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2728 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2729 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2730 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2731
2732 /* if this is an evpn imported type-5 prefix,
2733 * we need to withdraw the route first to clear
2734 * the nh neigh and the RMAC entry.
2735 */
2736 if (old_select &&
2737 is_route_parent_evpn(old_select))
2738 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2739
d62a17ae 2740 bgp_zebra_announce(rn, p, new_select, bgp, afi, safi);
2b659f33 2741 } else {
d62a17ae 2742 /* Withdraw the route from the kernel. */
2743 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2744 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2745 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2746 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2747
568e10ca 2748 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2749 }
718e3744 2750 }
3064bf43 2751
3b0c17e1 2752 bgp_process_evpn_route_injection(bgp, afi, safi, rn, new_select,
2753 old_select);
5424b7ba 2754
d62a17ae 2755 /* Clear any route change flags. */
2756 bgp_zebra_clear_route_change_flags(rn);
3064bf43 2757
18ee8310 2758 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2759 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
18ee8310 2760 bgp_path_info_reap(rn, old_select);
d62a17ae 2761
2762 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2763 return;
718e3744 2764}
2765
f009ff26 2766/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2767int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2768{
2769 struct bgp_node *rn;
2770 int cnt = 0;
2771 struct afi_safi_info *thread_info;
2772 struct listnode *node = NULL, *nnode = NULL;
2773
2774 if (bgp->gr_info[afi][safi].t_route_select)
2775 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
2776
2777 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
2778 zlog_debug("%s: processing route for %s : cnt %d", __func__,
2779 get_afi_safi_str(afi, safi, false),
2780 listcount(bgp->gr_info[afi][safi].route_list));
f009ff26 2781 }
2782
2783 /* Process the route list */
2784 node = listhead(bgp->gr_info[afi][safi].route_list);
f009ff26 2785 while (node) {
2786 rn = listgetdata(node);
2787 nnode = node->next;
2788 list_delete_node(bgp->gr_info[afi][safi].route_list, node);
2789 rn->rt_node = NULL;
2790
2791 if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
2792 UNSET_FLAG(rn->flags, BGP_NODE_SELECT_DEFER);
2793 bgp_process_main_one(bgp, rn, afi, safi);
2794 cnt++;
2795 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT)
2796 break;
2797 }
2798 node = nnode;
2799 }
2800
9e3b51a7 2801 /* Send EOR message when all routes are processed */
2802 if (list_isempty(bgp->gr_info[afi][safi].route_list)) {
2803 bgp_send_delayed_eor(bgp);
8c48b3b6 2804 /* Send route processing complete message to RIB */
2805 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 2806 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 2807 return 0;
9e3b51a7 2808 }
f009ff26 2809
2810 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 2811
2812 thread_info->afi = afi;
2813 thread_info->safi = safi;
2814 thread_info->bgp = bgp;
2815
2816 /* If there are more routes to be processed, start the
2817 * selection timer
2818 */
2819 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
2820 BGP_ROUTE_SELECT_DELAY,
2821 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 2822 return 0;
2823}
2824
aac24838 2825static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 2826{
aac24838
JB
2827 struct bgp_process_queue *pqnode = data;
2828 struct bgp *bgp = pqnode->bgp;
d62a17ae 2829 struct bgp_table *table;
ac021f40 2830 struct bgp_node *rn;
aac24838
JB
2831
2832 /* eoiu marker */
2833 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
2834 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
2835 /* should always have dedicated wq call */
2836 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
2837 return WQ_SUCCESS;
2838 }
2839
ac021f40
LB
2840 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
2841 rn = STAILQ_FIRST(&pqnode->pqueue);
2842 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
b3e1dd3c 2843 STAILQ_NEXT(rn, pq) = NULL; /* complete unlink */
aac24838 2844 table = bgp_node_table(rn);
ac021f40 2845 /* note, new RNs may be added as part of processing */
aac24838 2846 bgp_process_main_one(bgp, rn, table->afi, table->safi);
cb1faec9 2847
aac24838 2848 bgp_unlock_node(rn);
d62a17ae 2849 bgp_table_unlock(table);
2850 }
aac24838
JB
2851
2852 return WQ_SUCCESS;
2853}
2854
2855static void bgp_processq_del(struct work_queue *wq, void *data)
2856{
2857 struct bgp_process_queue *pqnode = data;
2858
2859 bgp_unlock(pqnode->bgp);
2860
2861 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 2862}
2863
d62a17ae 2864void bgp_process_queue_init(void)
200df115 2865{
0ce1ca80 2866 if (!bm->process_main_queue)
d62a17ae 2867 bm->process_main_queue =
2868 work_queue_new(bm->master, "process_main_queue");
2869
aac24838 2870 bm->process_main_queue->spec.workfunc = &bgp_process_wq;
d62a17ae 2871 bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
2872 bm->process_main_queue->spec.max_retries = 0;
2873 bm->process_main_queue->spec.hold = 50;
2874 /* Use a higher yield value of 50ms for main queue processing */
2875 bm->process_main_queue->spec.yield = 50 * 1000L;
200df115 2876}
2877
cfe8d15a 2878static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
2879{
2880 struct bgp_process_queue *pqnode;
2881
a4d82a8a
PZ
2882 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
2883 sizeof(struct bgp_process_queue));
aac24838
JB
2884
2885 /* unlocked in bgp_processq_del */
2886 pqnode->bgp = bgp_lock(bgp);
2887 STAILQ_INIT(&pqnode->pqueue);
2888
aac24838
JB
2889 return pqnode;
2890}
2891
d62a17ae 2892void bgp_process(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)
fee0f4c6 2893{
aac24838
JB
2894#define ARBITRARY_PROCESS_QLEN 10000
2895 struct work_queue *wq = bm->process_main_queue;
d62a17ae 2896 struct bgp_process_queue *pqnode;
cfe8d15a 2897 int pqnode_reuse = 0;
495f0b13 2898
d62a17ae 2899 /* already scheduled for processing? */
2900 if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED))
2901 return;
2e02b9b2 2902
f009ff26 2903 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
2904 * the workqueue
2905 */
2906 if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
2907 if (BGP_DEBUG(update, UPDATE_OUT))
2908 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
36235319 2909 rn);
f009ff26 2910 return;
2911 }
2912
aac24838 2913 if (wq == NULL)
d62a17ae 2914 return;
2915
aac24838 2916 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
2917 limit only if is from the same BGP view and it's not an EOIU marker
2918 */
aac24838
JB
2919 if (work_queue_item_count(wq)) {
2920 struct work_queue_item *item = work_queue_last_item(wq);
2921 pqnode = item->data;
228da428 2922
a4d82a8a
PZ
2923 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
2924 || pqnode->bgp != bgp
2925 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
2926 pqnode = bgp_processq_alloc(bgp);
2927 else
2928 pqnode_reuse = 1;
aac24838 2929 } else
cfe8d15a 2930 pqnode = bgp_processq_alloc(bgp);
aac24838 2931 /* all unlocked in bgp_process_wq */
d62a17ae 2932 bgp_table_lock(bgp_node_table(rn));
aac24838 2933
d62a17ae 2934 SET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838
JB
2935 bgp_lock_node(rn);
2936
60466a63
QY
2937 /* can't be enqueued twice */
2938 assert(STAILQ_NEXT(rn, pq) == NULL);
aac24838
JB
2939 STAILQ_INSERT_TAIL(&pqnode->pqueue, rn, pq);
2940 pqnode->queued++;
2941
cfe8d15a
LB
2942 if (!pqnode_reuse)
2943 work_queue_add(wq, pqnode);
2944
d62a17ae 2945 return;
fee0f4c6 2946}
0a486e5f 2947
d62a17ae 2948void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 2949{
d62a17ae 2950 struct bgp_process_queue *pqnode;
cb1faec9 2951
d62a17ae 2952 if (bm->process_main_queue == NULL)
2953 return;
2e02b9b2 2954
cfe8d15a 2955 pqnode = bgp_processq_alloc(bgp);
cb1faec9 2956
aac24838 2957 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
cfe8d15a 2958 work_queue_add(bm->process_main_queue, pqnode);
cb1faec9
DS
2959}
2960
d62a17ae 2961static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 2962{
d62a17ae 2963 struct peer *peer;
0a486e5f 2964
d62a17ae 2965 peer = THREAD_ARG(thread);
2966 peer->t_pmax_restart = NULL;
0a486e5f 2967
d62a17ae 2968 if (bgp_debug_neighbor_events(peer))
2969 zlog_debug(
2970 "%s Maximum-prefix restart timer expired, restore peering",
2971 peer->host);
0a486e5f 2972
a9bafa95 2973 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 2974 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 2975
d62a17ae 2976 return 0;
0a486e5f 2977}
2978
3dc339cd
DA
2979bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
2980 int always)
718e3744 2981{
d62a17ae 2982 iana_afi_t pkt_afi;
5c525538 2983 iana_safi_t pkt_safi;
9cabb64b 2984
d62a17ae 2985 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 2986 return false;
e0701b79 2987
d62a17ae 2988 if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) {
2989 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2990 PEER_STATUS_PREFIX_LIMIT)
2991 && !always)
3dc339cd 2992 return false;
e0701b79 2993
d62a17ae 2994 zlog_info(
a0a87037
DA
2995 "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32
2996 " exceed, limit %" PRIu32,
5cb5f4d0 2997 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 2998 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2999 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3000
3001 if (CHECK_FLAG(peer->af_flags[afi][safi],
3002 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3003 return false;
d62a17ae 3004
3005 /* Convert AFI, SAFI to values for packet. */
3006 pkt_afi = afi_int2iana(afi);
3007 pkt_safi = safi_int2iana(safi);
3008 {
d7c0a89a 3009 uint8_t ndata[7];
d62a17ae 3010
3011 ndata[0] = (pkt_afi >> 8);
3012 ndata[1] = pkt_afi;
3013 ndata[2] = pkt_safi;
3014 ndata[3] = (peer->pmax[afi][safi] >> 24);
3015 ndata[4] = (peer->pmax[afi][safi] >> 16);
3016 ndata[5] = (peer->pmax[afi][safi] >> 8);
3017 ndata[6] = (peer->pmax[afi][safi]);
3018
3019 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3020 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3021 BGP_NOTIFY_CEASE_MAX_PREFIX,
3022 ndata, 7);
3023 }
3024
3025 /* Dynamic peers will just close their connection. */
3026 if (peer_dynamic_neighbor(peer))
3dc339cd 3027 return true;
d62a17ae 3028
3029 /* restart timer start */
3030 if (peer->pmax_restart[afi][safi]) {
3031 peer->v_pmax_restart =
3032 peer->pmax_restart[afi][safi] * 60;
3033
3034 if (bgp_debug_neighbor_events(peer))
3035 zlog_debug(
3036 "%s Maximum-prefix restart timer started for %d secs",
3037 peer->host, peer->v_pmax_restart);
3038
3039 BGP_TIMER_ON(peer->t_pmax_restart,
3040 bgp_maximum_prefix_restart_timer,
3041 peer->v_pmax_restart);
3042 }
3043
3dc339cd 3044 return true;
d62a17ae 3045 } else
3046 UNSET_FLAG(peer->af_sflags[afi][safi],
3047 PEER_STATUS_PREFIX_LIMIT);
3048
3049 if (peer->pcount[afi][safi]
3050 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
3051 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3052 PEER_STATUS_PREFIX_THRESHOLD)
3053 && !always)
3dc339cd 3054 return false;
d62a17ae 3055
3056 zlog_info(
a0a87037
DA
3057 "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32
3058 ", max %" PRIu32,
5cb5f4d0 3059 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 3060 peer->pcount[afi][safi], peer->pmax[afi][safi]);
3061 SET_FLAG(peer->af_sflags[afi][safi],
3062 PEER_STATUS_PREFIX_THRESHOLD);
3063 } else
3064 UNSET_FLAG(peer->af_sflags[afi][safi],
3065 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3066 return false;
718e3744 3067}
3068
b40d939b 3069/* Unconditionally remove the route from the RIB, without taking
3070 * damping into consideration (eg, because the session went down)
3071 */
40381db7 3072void bgp_rib_remove(struct bgp_node *rn, struct bgp_path_info *pi,
4b7e6066 3073 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3074{
f009ff26 3075
3076 struct bgp *bgp = NULL;
3077 bool delete_route = false;
3078
b54892e0
DS
3079 bgp_aggregate_decrement(peer->bgp, bgp_node_get_prefix(rn),
3080 pi, afi, safi);
d62a17ae 3081
f009ff26 3082 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
40381db7 3083 bgp_path_info_delete(rn, pi); /* keep historical info */
d62a17ae 3084
f009ff26 3085 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3086 * flag
3087 */
3088 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3089 delete_route = true;
36235319
QY
3090 else if (bgp_node_set_defer_flag(rn, true) < 0)
3091 delete_route = true;
f009ff26 3092 if (delete_route) {
3093 if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
3094 UNSET_FLAG(rn->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3095 bgp = pi->peer->bgp;
36235319
QY
3096 if ((rn->rt_node)
3097 && (bgp->gr_info[afi][safi].route_list)) {
3098 list_delete_node(bgp->gr_info[afi][safi]
3099 .route_list,
3100 rn->rt_node);
f009ff26 3101 rn->rt_node = NULL;
3102 }
3103 }
3104 }
3105 }
4a11bf2c 3106
f009ff26 3107 hook_call(bgp_process, peer->bgp, afi, safi, rn, peer, true);
d62a17ae 3108 bgp_process(peer->bgp, rn, afi, safi);
3109}
3110
40381db7 3111static void bgp_rib_withdraw(struct bgp_node *rn, struct bgp_path_info *pi,
d62a17ae 3112 struct peer *peer, afi_t afi, safi_t safi,
3113 struct prefix_rd *prd)
3114{
b54892e0
DS
3115 const struct prefix *p = bgp_node_get_prefix(rn);
3116
d62a17ae 3117 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3118 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3119 */
3120 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3121 && peer->sort == BGP_PEER_EBGP)
40381db7 3122 if ((bgp_damp_withdraw(pi, rn, afi, safi, 0))
d62a17ae 3123 == BGP_DAMP_SUPPRESSED) {
b54892e0 3124 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
d62a17ae 3125 safi);
3126 return;
3127 }
3128
49e5a4a0 3129#ifdef ENABLE_BGP_VNC
d62a17ae 3130 if (safi == SAFI_MPLS_VPN) {
3131 struct bgp_node *prn = NULL;
3132 struct bgp_table *table = NULL;
3133
3134 prn = bgp_node_get(peer->bgp->rib[afi][safi],
3135 (struct prefix *)prd);
67009e22
DS
3136 if (bgp_node_has_bgp_path_info_data(prn)) {
3137 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3138
3139 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3140 peer->bgp, prd, table, p, pi);
d62a17ae 3141 }
3142 bgp_unlock_node(prn);
3143 }
3144 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3145 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3146
b54892e0
DS
3147 vnc_import_bgp_del_route(peer->bgp, p, pi);
3148 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3149 }
65efcfce 3150 }
d62a17ae 3151#endif
128ea8ab 3152
d62a17ae 3153 /* If this is an EVPN route, process for un-import. */
3154 if (safi == SAFI_EVPN)
b54892e0 3155 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3156
40381db7 3157 bgp_rib_remove(rn, pi, peer, afi, safi);
718e3744 3158}
3159
4b7e6066
DS
3160struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3161 struct peer *peer, struct attr *attr,
3162 struct bgp_node *rn)
fb018d25 3163{
4b7e6066 3164 struct bgp_path_info *new;
fb018d25 3165
d62a17ae 3166 /* Make new BGP info. */
4b7e6066 3167 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3168 new->type = type;
3169 new->instance = instance;
3170 new->sub_type = sub_type;
3171 new->peer = peer;
3172 new->attr = attr;
3173 new->uptime = bgp_clock();
3174 new->net = rn;
d62a17ae 3175 return new;
fb018d25
DS
3176}
3177
d62a17ae 3178static void overlay_index_update(struct attr *attr,
3179 struct eth_segment_id *eth_s_id,
3180 union gw_addr *gw_ip)
684a7227 3181{
d62a17ae 3182 if (!attr)
3183 return;
684a7227 3184
d62a17ae 3185 if (eth_s_id == NULL) {
3186 memset(&(attr->evpn_overlay.eth_s_id), 0,
3187 sizeof(struct eth_segment_id));
3188 } else {
3189 memcpy(&(attr->evpn_overlay.eth_s_id), eth_s_id,
3190 sizeof(struct eth_segment_id));
3191 }
3192 if (gw_ip == NULL) {
3193 memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr));
3194 } else {
3195 memcpy(&(attr->evpn_overlay.gw_ip), gw_ip,
3196 sizeof(union gw_addr));
3197 }
684a7227
PG
3198}
3199
40381db7 3200static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3201 struct eth_segment_id *eth_s_id,
3202 union gw_addr *gw_ip)
3203{
40381db7
DS
3204 struct eth_segment_id *path_eth_s_id, *path_eth_s_id_remote;
3205 union gw_addr *path_gw_ip, *path_gw_ip_remote;
11ebf4ed
DS
3206 union {
3207 struct eth_segment_id esi;
3208 union gw_addr ip;
3209 } temp;
d62a17ae 3210
3211 if (afi != AFI_L2VPN)
3212 return true;
11ebf4ed 3213
05864da7
DS
3214 path_eth_s_id = &(path->attr->evpn_overlay.eth_s_id);
3215 path_gw_ip = &(path->attr->evpn_overlay.gw_ip);
11ebf4ed
DS
3216
3217 if (gw_ip == NULL) {
3218 memset(&temp, 0, sizeof(temp));
40381db7 3219 path_gw_ip_remote = &temp.ip;
11ebf4ed 3220 } else
40381db7 3221 path_gw_ip_remote = gw_ip;
11ebf4ed
DS
3222
3223 if (eth_s_id == NULL) {
3224 memset(&temp, 0, sizeof(temp));
40381db7 3225 path_eth_s_id_remote = &temp.esi;
11ebf4ed 3226 } else
40381db7 3227 path_eth_s_id_remote = eth_s_id;
11ebf4ed 3228
40381db7 3229 if (!memcmp(path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr)))
d62a17ae 3230 return false;
11ebf4ed 3231
40381db7 3232 return !memcmp(path_eth_s_id, path_eth_s_id_remote,
d62a17ae 3233 sizeof(struct eth_segment_id));
684a7227
PG
3234}
3235
c265ee22 3236/* Check if received nexthop is valid or not. */
3dc339cd
DA
3237static bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3238 uint8_t type, uint8_t stype,
3239 struct attr *attr, struct bgp_node *rn)
d62a17ae 3240{
2dbe3fa9 3241 bool ret = false;
d62a17ae 3242
3243 /* Only validated for unicast and multicast currently. */
3244 /* Also valid for EVPN where the nexthop is an IP address. */
3245 if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN)
3dc339cd 3246 return false;
d62a17ae 3247
3248 /* If NEXT_HOP is present, validate it. */
3249 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
975a328e 3250 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3251 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
975a328e 3252 || bgp_nexthop_self(bgp, afi, type, stype, attr, rn))
3dc339cd 3253 return true;
d62a17ae 3254 }
c265ee22 3255
d62a17ae 3256 /* If MP_NEXTHOP is present, validate it. */
3257 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3258 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3259 * it is not an IPv6 link-local address.
3260 */
3261 if (attr->mp_nexthop_len) {
3262 switch (attr->mp_nexthop_len) {
3263 case BGP_ATTR_NHLEN_IPV4:
3264 case BGP_ATTR_NHLEN_VPNV4:
975a328e
DA
3265 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
3266 || IPV4_CLASS_DE(
3267 ntohl(attr->mp_nexthop_global_in.s_addr))
3268 || bgp_nexthop_self(bgp, afi, type, stype, attr,
3269 rn));
d62a17ae 3270 break;
3271
3272 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
3273 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3274 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
3275 ret = (IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global)
3276 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3277 || IN6_IS_ADDR_MULTICAST(
949b0f24 3278 &attr->mp_nexthop_global)
3279 || bgp_nexthop_self(bgp, afi, type, stype,
3280 attr, rn));
d62a17ae 3281 break;
3282
3283 default:
3dc339cd 3284 ret = true;
d62a17ae 3285 break;
3286 }
3287 }
c265ee22 3288
d62a17ae 3289 return ret;
3290}
3291
5a1ae2c2 3292int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3293 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3294 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3295 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3296 struct bgp_route_evpn *evpn)
d62a17ae 3297{
3298 int ret;
3299 int aspath_loop_count = 0;
3300 struct bgp_node *rn;
3301 struct bgp *bgp;
3302 struct attr new_attr;
3303 struct attr *attr_new;
40381db7 3304 struct bgp_path_info *pi;
4b7e6066
DS
3305 struct bgp_path_info *new;
3306 struct bgp_path_info_extra *extra;
d62a17ae 3307 const char *reason;
3308 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3309 int connected = 0;
3310 int do_loop_check = 1;
3311 int has_valid_label = 0;
7c312383 3312 afi_t nh_afi;
949b0f24 3313 uint8_t pi_type = 0;
3314 uint8_t pi_sub_type = 0;
3315
49e5a4a0 3316#ifdef ENABLE_BGP_VNC
d62a17ae 3317 int vnc_implicit_withdraw = 0;
65efcfce 3318#endif
d62a17ae 3319 int same_attr = 0;
718e3744 3320
d62a17ae 3321 memset(&new_attr, 0, sizeof(struct attr));
3322 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3323 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3324
d62a17ae 3325 bgp = peer->bgp;
3326 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3327 /* TODO: Check to see if we can get rid of "is_valid_label" */
3328 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3329 has_valid_label = (num_labels > 0) ? 1 : 0;
3330 else
3331 has_valid_label = bgp_is_valid_label(label);
718e3744 3332
d62a17ae 3333 /* When peer's soft reconfiguration enabled. Record input packet in
3334 Adj-RIBs-In. */
3335 if (!soft_reconfig
3336 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3337 && peer != bgp->peer_self)
3338 bgp_adj_in_set(rn, peer, attr, addpath_id);
3339
3340 /* Check previously received route. */
6f94b685 3341 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
3342 if (pi->peer == peer && pi->type == type
3343 && pi->sub_type == sub_type
3344 && pi->addpath_rx_id == addpath_id)
d62a17ae 3345 break;
3346
3347 /* AS path local-as loop check. */
3348 if (peer->change_local_as) {
c4368918
DW
3349 if (peer->allowas_in[afi][safi])
3350 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3351 else if (!CHECK_FLAG(peer->flags,
3352 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3353 aspath_loop_count = 1;
3354
3355 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3356 > aspath_loop_count) {
b4d46cc9 3357 peer->stat_pfx_aspath_loop++;
d62a17ae 3358 reason = "as-path contains our own AS;";
3359 goto filtered;
3360 }
718e3744 3361 }
718e3744 3362
d62a17ae 3363 /* If the peer is configured for "allowas-in origin" and the last ASN in
3364 * the
3365 * as-path is our ASN then we do not need to call aspath_loop_check
3366 */
3367 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3368 if (aspath_get_last_as(attr->aspath) == bgp->as)
3369 do_loop_check = 0;
3370
3371 /* AS path loop check. */
3372 if (do_loop_check) {
3373 if (aspath_loop_check(attr->aspath, bgp->as)
3374 > peer->allowas_in[afi][safi]
3375 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3376 && aspath_loop_check(attr->aspath, bgp->confed_id)
3377 > peer->allowas_in[afi][safi])) {
b4d46cc9 3378 peer->stat_pfx_aspath_loop++;
d62a17ae 3379 reason = "as-path contains our own AS;";
3380 goto filtered;
3381 }
3382 }
aac9ef6c 3383
d62a17ae 3384 /* Route reflector originator ID check. */
3385 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3386 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3387 peer->stat_pfx_originator_loop++;
d62a17ae 3388 reason = "originator is us;";
3389 goto filtered;
3390 }
718e3744 3391
d62a17ae 3392 /* Route reflector cluster ID check. */
3393 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3394 peer->stat_pfx_cluster_loop++;
d62a17ae 3395 reason = "reflected from the same cluster;";
3396 goto filtered;
3397 }
718e3744 3398
d62a17ae 3399 /* Apply incoming filter. */
3400 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3401 peer->stat_pfx_filter++;
d62a17ae 3402 reason = "filter;";
3403 goto filtered;
3404 }
718e3744 3405
a8b72dc6
DA
3406 /* RFC 8212 to prevent route leaks.
3407 * This specification intends to improve this situation by requiring the
3408 * explicit configuration of both BGP Import and Export Policies for any
3409 * External BGP (EBGP) session such as customers, peers, or
3410 * confederation boundaries for all enabled address families. Through
3411 * codification of the aforementioned requirement, operators will
3412 * benefit from consistent behavior across different BGP
3413 * implementations.
3414 */
1d3fdccf 3415 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3416 if (!bgp_inbound_policy_exists(peer,
3417 &peer->filter[afi][safi])) {
3418 reason = "inbound policy missing";
3419 goto filtered;
3420 }
3421
fb29348a
DA
3422 /* draft-ietf-idr-deprecate-as-set-confed-set
3423 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3424 * Eventually, This document (if approved) updates RFC 4271
3425 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3426 * and obsoletes RFC 6472.
3427 */
3428 if (peer->bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED)
3429 if (aspath_check_as_sets(attr->aspath)) {
3430 reason =
3431 "as-path contains AS_SET or AS_CONFED_SET type;";
3432 goto filtered;
3433 }
3434
6f4f49b2 3435 new_attr = *attr;
d62a17ae 3436
3437 /* Apply incoming route-map.
3438 * NB: new_attr may now contain newly allocated values from route-map
3439 * "set"
3440 * commands, so we need bgp_attr_flush in the error paths, until we
3441 * intern
3442 * the attr (which takes over the memory references) */
82b692c0 3443 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL,
196c6b09 3444 label, num_labels, rn) == RMAP_DENY) {
b4d46cc9 3445 peer->stat_pfx_filter++;
d62a17ae 3446 reason = "route-map;";
3447 bgp_attr_flush(&new_attr);
3448 goto filtered;
3449 }
718e3744 3450
05864da7 3451 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3452 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3453 /* remove from RIB previous entry */
3454 bgp_zebra_withdraw(p, pi, bgp, safi);
3455 }
3456
7f323236
DW
3457 if (peer->sort == BGP_PEER_EBGP) {
3458
a4d82a8a
PZ
3459 /* If we receive the graceful-shutdown community from an eBGP
3460 * peer we must lower local-preference */
3461 if (new_attr.community
3462 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3463 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3464 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3465
a4d82a8a
PZ
3466 /* If graceful-shutdown is configured then add the GSHUT
3467 * community to all paths received from eBGP peers */
892fedb6
DA
3468 } else if (CHECK_FLAG(peer->bgp->flags,
3469 BGP_FLAG_GRACEFUL_SHUTDOWN))
7f323236 3470 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3471 }
3472
949b0f24 3473 if (pi) {
3474 pi_type = pi->type;
3475 pi_sub_type = pi->sub_type;
3476 }
3477
d62a17ae 3478 /* next hop check. */
a4d82a8a 3479 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
949b0f24 3480 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type,
3481 pi_sub_type, &new_attr, rn)) {
b4d46cc9 3482 peer->stat_pfx_nh_invalid++;
d62a17ae 3483 reason = "martian or self next-hop;";
3484 bgp_attr_flush(&new_attr);
3485 goto filtered;
3486 }
718e3744 3487
5c14a191 3488 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3489 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3490 reason = "self mac;";
3491 goto filtered;
3492 }
3493
d62a17ae 3494 attr_new = bgp_attr_intern(&new_attr);
3495
3496 /* If the update is implicit withdraw. */
40381db7
DS
3497 if (pi) {
3498 pi->uptime = bgp_clock();
3499 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3500
4a11bf2c
DL
3501 hook_call(bgp_process, bgp, afi, safi, rn, peer, true);
3502
d62a17ae 3503 /* Same attribute comes in. */
40381db7
DS
3504 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3505 && attrhash_cmp(pi->attr, attr_new)
d62a17ae 3506 && (!has_valid_label
40381db7 3507 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3508 num_labels * sizeof(mpls_label_t))
d62a17ae 3509 == 0)
3510 && (overlay_index_equal(
40381db7 3511 afi, pi, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3512 evpn == NULL ? NULL : &evpn->gw_ip))) {
3513 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3514 BGP_CONFIG_DAMPENING)
3515 && peer->sort == BGP_PEER_EBGP
40381db7 3516 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3517 if (bgp_debug_update(peer, p, NULL, 1)) {
3518 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3519 afi, safi, prd, p, label,
3520 num_labels, addpath_id ? 1 : 0,
3521 addpath_id, pfx_buf,
3522 sizeof(pfx_buf));
d62a17ae 3523 zlog_debug("%s rcvd %s", peer->host,
3524 pfx_buf);
3525 }
3526
40381db7 3527 if (bgp_damp_update(pi, rn, afi, safi)
d62a17ae 3528 != BGP_DAMP_SUPPRESSED) {
40381db7 3529 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3530 safi);
3531 bgp_process(bgp, rn, afi, safi);
3532 }
3533 } else /* Duplicate - odd */
3534 {
3535 if (bgp_debug_update(peer, p, NULL, 1)) {
3536 if (!peer->rcvd_attr_printed) {
3537 zlog_debug(
3538 "%s rcvd UPDATE w/ attr: %s",
3539 peer->host,
3540 peer->rcvd_attr_str);
3541 peer->rcvd_attr_printed = 1;
3542 }
3543
3544 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3545 afi, safi, prd, p, label,
3546 num_labels, addpath_id ? 1 : 0,
3547 addpath_id, pfx_buf,
3548 sizeof(pfx_buf));
d62a17ae 3549 zlog_debug(
3550 "%s rcvd %s...duplicate ignored",
3551 peer->host, pfx_buf);
3552 }
3553
3554 /* graceful restart STALE flag unset. */
40381db7 3555 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3556 bgp_path_info_unset_flag(
40381db7 3557 rn, pi, BGP_PATH_STALE);
f009ff26 3558 bgp_node_set_defer_flag(rn, false);
d62a17ae 3559 bgp_process(bgp, rn, afi, safi);
3560 }
3561 }
3562
3563 bgp_unlock_node(rn);
3564 bgp_attr_unintern(&attr_new);
3565
3566 return 0;
3567 }
718e3744 3568
d62a17ae 3569 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3570 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3571 if (bgp_debug_update(peer, p, NULL, 1)) {
3572 bgp_debug_rdpfxpath2str(
a4d82a8a 3573 afi, safi, prd, p, label, num_labels,
d62a17ae 3574 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3575 sizeof(pfx_buf));
3576 zlog_debug(
3577 "%s rcvd %s, flapped quicker than processing",
3578 peer->host, pfx_buf);
3579 }
3580
40381db7 3581 bgp_path_info_restore(rn, pi);
d62a17ae 3582 }
718e3744 3583
d62a17ae 3584 /* Received Logging. */
3585 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3586 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3587 num_labels, addpath_id ? 1 : 0,
3588 addpath_id, pfx_buf,
3589 sizeof(pfx_buf));
d62a17ae 3590 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3591 }
718e3744 3592
d62a17ae 3593 /* graceful restart STALE flag unset. */
f009ff26 3594 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
40381db7 3595 bgp_path_info_unset_flag(rn, pi, BGP_PATH_STALE);
f009ff26 3596 bgp_node_set_defer_flag(rn, false);
3597 }
d62a17ae 3598
3599 /* The attribute is changed. */
40381db7 3600 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3601
3602 /* implicit withdraw, decrement aggregate and pcount here.
3603 * only if update is accepted, they'll increment below.
3604 */
40381db7 3605 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3606
3607 /* Update bgp route dampening information. */
3608 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3609 && peer->sort == BGP_PEER_EBGP) {
3610 /* This is implicit withdraw so we should update
3611 dampening
3612 information. */
40381db7
DS
3613 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
3614 bgp_damp_withdraw(pi, rn, afi, safi, 1);
d62a17ae 3615 }
49e5a4a0 3616#ifdef ENABLE_BGP_VNC
d62a17ae 3617 if (safi == SAFI_MPLS_VPN) {
3618 struct bgp_node *prn = NULL;
3619 struct bgp_table *table = NULL;
3620
3621 prn = bgp_node_get(bgp->rib[afi][safi],
3622 (struct prefix *)prd);
67009e22
DS
3623 if (bgp_node_has_bgp_path_info_data(prn)) {
3624 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3625
3626 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3627 bgp, prd, table, p, pi);
d62a17ae 3628 }
3629 bgp_unlock_node(prn);
3630 }
3631 if ((afi == AFI_IP || afi == AFI_IP6)
3632 && (safi == SAFI_UNICAST)) {
40381db7 3633 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3634 /*
3635 * Implicit withdraw case.
3636 */
3637 ++vnc_implicit_withdraw;
40381db7
DS
3638 vnc_import_bgp_del_route(bgp, p, pi);
3639 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3640 }
3641 }
65efcfce 3642#endif
128ea8ab 3643
d62a17ae 3644 /* Special handling for EVPN update of an existing route. If the
3645 * extended community attribute has changed, we need to
3646 * un-import
3647 * the route using its existing extended community. It will be
3648 * subsequently processed for import with the new extended
3649 * community.
3650 */
3651 if (safi == SAFI_EVPN && !same_attr) {
40381db7 3652 if ((pi->attr->flag
d62a17ae 3653 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3654 && (attr_new->flag
3655 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3656 int cmp;
3657
40381db7 3658 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3659 attr_new->ecommunity);
3660 if (!cmp) {
3661 if (bgp_debug_update(peer, p, NULL, 1))
3662 zlog_debug(
3663 "Change in EXT-COMM, existing %s new %s",
3664 ecommunity_str(
40381db7 3665 pi->attr->ecommunity),
d62a17ae 3666 ecommunity_str(
3667 attr_new->ecommunity));
3668 bgp_evpn_unimport_route(bgp, afi, safi,
40381db7 3669 p, pi);
d62a17ae 3670 }
3671 }
3672 }
718e3744 3673
d62a17ae 3674 /* Update to new attribute. */
40381db7
DS
3675 bgp_attr_unintern(&pi->attr);
3676 pi->attr = attr_new;
d62a17ae 3677
3678 /* Update MPLS label */
3679 if (has_valid_label) {
40381db7 3680 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3681 if (extra->label != label) {
3682 memcpy(&extra->label, label,
dbd587da 3683 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3684 extra->num_labels = num_labels;
3685 }
b57ba6d2
MK
3686 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3687 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3688 }
718e3744 3689
e496b420
HS
3690 /* Update SRv6 SID */
3691 if (attr->srv6_l3vpn) {
3692 extra = bgp_path_info_extra_get(pi);
3693 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
3694 sid_copy(&extra->sid[0],
3695 &attr->srv6_l3vpn->sid);
3696 extra->num_sids = 1;
3697 }
3698 } else if (attr->srv6_vpn) {
3699 extra = bgp_path_info_extra_get(pi);
3700 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
3701 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3702 extra->num_sids = 1;
3703 }
3704 }
3705
49e5a4a0 3706#ifdef ENABLE_BGP_VNC
d62a17ae 3707 if ((afi == AFI_IP || afi == AFI_IP6)
3708 && (safi == SAFI_UNICAST)) {
3709 if (vnc_implicit_withdraw) {
3710 /*
3711 * Add back the route with its new attributes
3712 * (e.g., nexthop).
3713 * The route is still selected, until the route
3714 * selection
3715 * queued by bgp_process actually runs. We have
3716 * to make this
3717 * update to the VNC side immediately to avoid
3718 * racing against
3719 * configuration changes (e.g., route-map
3720 * changes) which
3721 * trigger re-importation of the entire RIB.
3722 */
40381db7
DS
3723 vnc_import_bgp_add_route(bgp, p, pi);
3724 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 3725 }
3726 }
65efcfce 3727#endif
d62a17ae 3728 /* Update Overlay Index */
3729 if (afi == AFI_L2VPN) {
3730 overlay_index_update(
40381db7 3731 pi->attr, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3732 evpn == NULL ? NULL : &evpn->gw_ip);
3733 }
65efcfce 3734
d62a17ae 3735 /* Update bgp route dampening information. */
3736 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3737 && peer->sort == BGP_PEER_EBGP) {
3738 /* Now we do normal update dampening. */
40381db7 3739 ret = bgp_damp_update(pi, rn, afi, safi);
d62a17ae 3740 if (ret == BGP_DAMP_SUPPRESSED) {
3741 bgp_unlock_node(rn);
3742 return 0;
3743 }
3744 }
128ea8ab 3745
d62a17ae 3746 /* Nexthop reachability check - for unicast and
3747 * labeled-unicast.. */
7c312383
AD
3748 if (((afi == AFI_IP || afi == AFI_IP6)
3749 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3750 || (safi == SAFI_EVPN &&
3751 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
3752 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
3753 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 3754 && !CHECK_FLAG(peer->flags,
3755 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
3756 && !CHECK_FLAG(bgp->flags,
3757 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 3758 connected = 1;
3759 else
3760 connected = 0;
3761
960035b2
PZ
3762 struct bgp *bgp_nexthop = bgp;
3763
40381db7
DS
3764 if (pi->extra && pi->extra->bgp_orig)
3765 bgp_nexthop = pi->extra->bgp_orig;
960035b2 3766
7c312383
AD
3767 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
3768
3769 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
3770 pi, NULL, connected)
a4d82a8a 3771 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
40381db7 3772 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 3773 else {
3774 if (BGP_DEBUG(nht, NHT)) {
3775 char buf1[INET6_ADDRSTRLEN];
3776 inet_ntop(AF_INET,
3777 (const void *)&attr_new
3778 ->nexthop,
3779 buf1, INET6_ADDRSTRLEN);
3780 zlog_debug("%s(%s): NH unresolved",
15569c58 3781 __func__, buf1);
d62a17ae 3782 }
40381db7 3783 bgp_path_info_unset_flag(rn, pi,
18ee8310 3784 BGP_PATH_VALID);
d62a17ae 3785 }
3786 } else
40381db7 3787 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 3788
49e5a4a0 3789#ifdef ENABLE_BGP_VNC
d62a17ae 3790 if (safi == SAFI_MPLS_VPN) {
3791 struct bgp_node *prn = NULL;
3792 struct bgp_table *table = NULL;
3793
3794 prn = bgp_node_get(bgp->rib[afi][safi],
3795 (struct prefix *)prd);
67009e22
DS
3796 if (bgp_node_has_bgp_path_info_data(prn)) {
3797 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3798
3799 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 3800 bgp, prd, table, p, pi);
d62a17ae 3801 }
3802 bgp_unlock_node(prn);
3803 }
3804#endif
718e3744 3805
d62a17ae 3806 /* If this is an EVPN route and some attribute has changed,
3807 * process
3808 * route for import. If the extended community has changed, we
3809 * would
3810 * have done the un-import earlier and the import would result
3811 * in the
3812 * route getting injected into appropriate L2 VNIs. If it is
3813 * just
3814 * some other attribute change, the import will result in
3815 * updating
3816 * the attributes for the route in the VNI(s).
3817 */
7c312383
AD
3818 if (safi == SAFI_EVPN && !same_attr &&
3819 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 3820 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 3821
3822 /* Process change. */
40381db7 3823 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 3824
3825 bgp_process(bgp, rn, afi, safi);
3826 bgp_unlock_node(rn);
558d1fec 3827
ddb5b488
PZ
3828 if (SAFI_UNICAST == safi
3829 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3830 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3831
40381db7 3832 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3833 }
3834 if ((SAFI_MPLS_VPN == safi)
3835 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3836
40381db7 3837 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
3838 }
3839
49e5a4a0 3840#ifdef ENABLE_BGP_VNC
d62a17ae 3841 if (SAFI_MPLS_VPN == safi) {
3842 mpls_label_t label_decoded = decode_label(label);
28070ee3 3843
d62a17ae 3844 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3845 type, sub_type, &label_decoded);
3846 }
3847 if (SAFI_ENCAP == safi) {
3848 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3849 type, sub_type, NULL);
3850 }
28070ee3
PZ
3851#endif
3852
d62a17ae 3853 return 0;
3854 } // End of implicit withdraw
718e3744 3855
d62a17ae 3856 /* Received Logging. */
3857 if (bgp_debug_update(peer, p, NULL, 1)) {
3858 if (!peer->rcvd_attr_printed) {
3859 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3860 peer->rcvd_attr_str);
3861 peer->rcvd_attr_printed = 1;
3862 }
718e3744 3863
a4d82a8a 3864 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3865 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3866 sizeof(pfx_buf));
3867 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3868 }
718e3744 3869
d62a17ae 3870 /* Make new BGP info. */
3871 new = info_make(type, sub_type, 0, peer, attr_new, rn);
718e3744 3872
d62a17ae 3873 /* Update MPLS label */
3874 if (has_valid_label) {
18ee8310 3875 extra = bgp_path_info_extra_get(new);
8ba71050 3876 if (extra->label != label) {
dbd587da
QY
3877 memcpy(&extra->label, label,
3878 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3879 extra->num_labels = num_labels;
3880 }
b57ba6d2
MK
3881 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3882 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3883 }
718e3744 3884
e496b420
HS
3885 /* Update SRv6 SID */
3886 if (safi == SAFI_MPLS_VPN) {
3887 extra = bgp_path_info_extra_get(new);
3888 if (attr->srv6_l3vpn) {
3889 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
3890 extra->num_sids = 1;
3891 } else if (attr->srv6_vpn) {
3892 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3893 extra->num_sids = 1;
3894 }
3895 }
3896
d62a17ae 3897 /* Update Overlay Index */
3898 if (afi == AFI_L2VPN) {
3899 overlay_index_update(new->attr,
3900 evpn == NULL ? NULL : &evpn->eth_s_id,
3901 evpn == NULL ? NULL : &evpn->gw_ip);
3902 }
3903 /* Nexthop reachability check. */
7c312383
AD
3904 if (((afi == AFI_IP || afi == AFI_IP6)
3905 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3906 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
3907 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
3908 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 3909 && !CHECK_FLAG(peer->flags,
3910 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
3911 && !CHECK_FLAG(bgp->flags,
3912 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 3913 connected = 1;
3914 else
3915 connected = 0;
3916
7c312383
AD
3917 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
3918
3919 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, new, NULL,
3920 connected)
a4d82a8a 3921 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
18ee8310 3922 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
d62a17ae 3923 else {
3924 if (BGP_DEBUG(nht, NHT)) {
3925 char buf1[INET6_ADDRSTRLEN];
3926 inet_ntop(AF_INET,
3927 (const void *)&attr_new->nexthop,
3928 buf1, INET6_ADDRSTRLEN);
15569c58
DA
3929 zlog_debug("%s(%s): NH unresolved", __func__,
3930 buf1);
d62a17ae 3931 }
18ee8310 3932 bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID);
d62a17ae 3933 }
3934 } else
18ee8310 3935 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
a82478b9 3936
d62a17ae 3937 /* Addpath ID */
3938 new->addpath_rx_id = addpath_id;
3939
3940 /* Increment prefix */
3941 bgp_aggregate_increment(bgp, p, new, afi, safi);
3942
3943 /* Register new BGP information. */
18ee8310 3944 bgp_path_info_add(rn, new);
d62a17ae 3945
3946 /* route_node_get lock */
3947 bgp_unlock_node(rn);
558d1fec 3948
49e5a4a0 3949#ifdef ENABLE_BGP_VNC
d62a17ae 3950 if (safi == SAFI_MPLS_VPN) {
3951 struct bgp_node *prn = NULL;
3952 struct bgp_table *table = NULL;
3953
3954 prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
67009e22
DS
3955 if (bgp_node_has_bgp_path_info_data(prn)) {
3956 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3957
3958 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3959 bgp, prd, table, p, new);
3960 }
3961 bgp_unlock_node(prn);
3962 }
65efcfce
LB
3963#endif
3964
d62a17ae 3965 /* If maximum prefix count is configured and current prefix
3966 count exeed it. */
3967 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3968 return -1;
718e3744 3969
d62a17ae 3970 /* If this is an EVPN route, process for import. */
7c312383 3971 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 3972 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 3973
4a11bf2c
DL
3974 hook_call(bgp_process, bgp, afi, safi, rn, peer, false);
3975
d62a17ae 3976 /* Process change. */
3977 bgp_process(bgp, rn, afi, safi);
718e3744 3978
ddb5b488
PZ
3979 if (SAFI_UNICAST == safi
3980 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3981 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3982 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
3983 }
3984 if ((SAFI_MPLS_VPN == safi)
3985 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3986
3987 vpn_leak_to_vrf_update(bgp, new);
3988 }
49e5a4a0 3989#ifdef ENABLE_BGP_VNC
d62a17ae 3990 if (SAFI_MPLS_VPN == safi) {
3991 mpls_label_t label_decoded = decode_label(label);
28070ee3 3992
d62a17ae 3993 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3994 sub_type, &label_decoded);
3995 }
3996 if (SAFI_ENCAP == safi) {
3997 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3998 sub_type, NULL);
3999 }
28070ee3
PZ
4000#endif
4001
d62a17ae 4002 return 0;
718e3744 4003
d62a17ae 4004/* This BGP update is filtered. Log the reason then update BGP
4005 entry. */
4006filtered:
4a11bf2c
DL
4007 hook_call(bgp_process, bgp, afi, safi, rn, peer, true);
4008
d62a17ae 4009 if (bgp_debug_update(peer, p, NULL, 1)) {
4010 if (!peer->rcvd_attr_printed) {
4011 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4012 peer->rcvd_attr_str);
4013 peer->rcvd_attr_printed = 1;
4014 }
718e3744 4015
a4d82a8a 4016 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4017 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4018 sizeof(pfx_buf));
4019 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4020 peer->host, pfx_buf, reason);
4021 }
128ea8ab 4022
40381db7 4023 if (pi) {
d62a17ae 4024 /* If this is an EVPN route, un-import it as it is now filtered.
4025 */
4026 if (safi == SAFI_EVPN)
40381db7 4027 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4028
ddb5b488
PZ
4029 if (SAFI_UNICAST == safi
4030 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4031 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4032
40381db7 4033 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4034 }
4035 if ((SAFI_MPLS_VPN == safi)
4036 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4037
40381db7 4038 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4039 }
4040
40381db7 4041 bgp_rib_remove(rn, pi, peer, afi, safi);
d62a17ae 4042 }
4043
4044 bgp_unlock_node(rn);
558d1fec 4045
49e5a4a0 4046#ifdef ENABLE_BGP_VNC
d62a17ae 4047 /*
4048 * Filtered update is treated as an implicit withdrawal (see
4049 * bgp_rib_remove()
4050 * a few lines above)
4051 */
4052 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4053 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4054 0);
4055 }
97736e32
PZ
4056#endif
4057
d62a17ae 4058 return 0;
718e3744 4059}
4060
26a3ffd6 4061int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4062 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4063 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4064 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4065{
d62a17ae 4066 struct bgp *bgp;
4067 char pfx_buf[BGP_PRD_PATH_STRLEN];
4068 struct bgp_node *rn;
40381db7 4069 struct bgp_path_info *pi;
718e3744 4070
49e5a4a0 4071#ifdef ENABLE_BGP_VNC
d62a17ae 4072 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4073 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4074 0);
4075 }
28070ee3
PZ
4076#endif
4077
d62a17ae 4078 bgp = peer->bgp;
4079
4080 /* Lookup node. */
4081 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
4082
4083 /* If peer is soft reconfiguration enabled. Record input packet for
4084 * further calculation.
4085 *
4086 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4087 * routes that are filtered. This tanks out Quagga RS pretty badly due
4088 * to
4089 * the iteration over all RS clients.
4090 * Since we need to remove the entry from adj_in anyway, do that first
4091 * and
4092 * if there was no entry, we don't need to do anything more.
4093 */
4094 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4095 && peer != bgp->peer_self)
4096 if (!bgp_adj_in_unset(rn, peer, addpath_id)) {
b4d46cc9
DL
4097 peer->stat_pfx_dup_withdraw++;
4098
d62a17ae 4099 if (bgp_debug_update(peer, p, NULL, 1)) {
4100 bgp_debug_rdpfxpath2str(
a4d82a8a 4101 afi, safi, prd, p, label, num_labels,
d62a17ae 4102 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4103 sizeof(pfx_buf));
4104 zlog_debug(
4105 "%s withdrawing route %s not in adj-in",
4106 peer->host, pfx_buf);
4107 }
4108 bgp_unlock_node(rn);
4109 return 0;
4110 }
cd808e74 4111
d62a17ae 4112 /* Lookup withdrawn route. */
6f94b685 4113 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4114 if (pi->peer == peer && pi->type == type
4115 && pi->sub_type == sub_type
4116 && pi->addpath_rx_id == addpath_id)
d62a17ae 4117 break;
4118
4119 /* Logging. */
4120 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4121 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4122 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4123 sizeof(pfx_buf));
4124 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4125 pfx_buf);
4126 }
718e3744 4127
d62a17ae 4128 /* Withdraw specified route from routing table. */
40381db7
DS
4129 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
4130 bgp_rib_withdraw(rn, pi, peer, afi, safi, prd);
ddb5b488
PZ
4131 if (SAFI_UNICAST == safi
4132 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4133 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4134 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4135 }
4136 if ((SAFI_MPLS_VPN == safi)
4137 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4138
40381db7 4139 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4140 }
4141 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4142 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4143 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4144 sizeof(pfx_buf));
4145 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4146 }
718e3744 4147
d62a17ae 4148 /* Unlock bgp_node_get() lock. */
4149 bgp_unlock_node(rn);
4150
4151 return 0;
718e3744 4152}
6b0655a2 4153
d62a17ae 4154void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4155 int withdraw)
718e3744 4156{
d62a17ae 4157 struct update_subgroup *subgrp;
4158 subgrp = peer_subgroup(peer, afi, safi);
4159 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4160}
6182d65b 4161
718e3744 4162
3f9c7369
DS
4163/*
4164 * bgp_stop_announce_route_timer
4165 */
d62a17ae 4166void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4167{
d62a17ae 4168 if (!paf->t_announce_route)
4169 return;
4170
4171 THREAD_TIMER_OFF(paf->t_announce_route);
718e3744 4172}
6b0655a2 4173
3f9c7369
DS
4174/*
4175 * bgp_announce_route_timer_expired
4176 *
4177 * Callback that is invoked when the route announcement timer for a
4178 * peer_af expires.
4179 */
d62a17ae 4180static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4181{
d62a17ae 4182 struct peer_af *paf;
4183 struct peer *peer;
558d1fec 4184
d62a17ae 4185 paf = THREAD_ARG(t);
4186 peer = paf->peer;
718e3744 4187
d62a17ae 4188 if (peer->status != Established)
4189 return 0;
3f9c7369 4190
d62a17ae 4191 if (!peer->afc_nego[paf->afi][paf->safi])
4192 return 0;
3f9c7369 4193
d62a17ae 4194 peer_af_announce_route(paf, 1);
4195 return 0;
718e3744 4196}
4197
3f9c7369
DS
4198/*
4199 * bgp_announce_route
4200 *
4201 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4202 */
d62a17ae 4203void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4204{
4205 struct peer_af *paf;
4206 struct update_subgroup *subgrp;
4207
4208 paf = peer_af_find(peer, afi, safi);
4209 if (!paf)
4210 return;
4211 subgrp = PAF_SUBGRP(paf);
4212
4213 /*
4214 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4215 * or a refresh has already been triggered.
4216 */
4217 if (!subgrp || paf->t_announce_route)
4218 return;
4219
4220 /*
4221 * Start a timer to stagger/delay the announce. This serves
4222 * two purposes - announcement can potentially be combined for
4223 * multiple peers and the announcement doesn't happen in the
4224 * vty context.
4225 */
4226 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4227 (subgrp->peer_count == 1)
4228 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4229 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4230 &paf->t_announce_route);
3f9c7369
DS
4231}
4232
4233/*
4234 * Announce routes from all AF tables to a peer.
4235 *
4236 * This should ONLY be called when there is a need to refresh the
4237 * routes to the peer based on a policy change for this peer alone
4238 * or a route refresh request received from the peer.
4239 * The operation will result in splitting the peer from its existing
4240 * subgroups and putting it in new subgroups.
4241 */
d62a17ae 4242void bgp_announce_route_all(struct peer *peer)
718e3744 4243{
d62a17ae 4244 afi_t afi;
4245 safi_t safi;
4246
05c7a1cc
QY
4247 FOREACH_AFI_SAFI (afi, safi)
4248 bgp_announce_route(peer, afi, safi);
718e3744 4249}
6b0655a2 4250
d62a17ae 4251static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4252 struct bgp_table *table,
4253 struct prefix_rd *prd)
718e3744 4254{
d62a17ae 4255 int ret;
4256 struct bgp_node *rn;
4257 struct bgp_adj_in *ain;
718e3744 4258
d62a17ae 4259 if (!table)
4260 table = peer->bgp->rib[afi][safi];
718e3744 4261
d62a17ae 4262 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
4263 for (ain = rn->adj_in; ain; ain = ain->next) {
ea47320b
DL
4264 if (ain->peer != peer)
4265 continue;
8692c506 4266
d7d15889 4267 struct bgp_path_info *pi;
d7c0a89a 4268 uint32_t num_labels = 0;
b57ba6d2 4269 mpls_label_t *label_pnt = NULL;
8cb687c2 4270 struct bgp_route_evpn evpn;
b57ba6d2 4271
d7d15889
DS
4272 for (pi = bgp_node_get_bgp_path_info(rn); pi;
4273 pi = pi->next)
4274 if (pi->peer == peer)
4275 break;
4276
40381db7
DS
4277 if (pi && pi->extra)
4278 num_labels = pi->extra->num_labels;
b57ba6d2 4279 if (num_labels)
40381db7 4280 label_pnt = &pi->extra->label[0];
8cb687c2
DS
4281 if (pi)
4282 memcpy(&evpn, &pi->attr->evpn_overlay,
4283 sizeof(evpn));
4284 else
4285 memset(&evpn, 0, sizeof(evpn));
8692c506 4286
b54892e0
DS
4287 ret = bgp_update(peer, bgp_node_get_prefix(rn),
4288 ain->addpath_rx_id, ain->attr,
4289 afi, safi, ZEBRA_ROUTE_BGP,
a4d82a8a 4290 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 4291 num_labels, 1, &evpn);
ea47320b
DL
4292
4293 if (ret < 0) {
4294 bgp_unlock_node(rn);
4295 return;
d62a17ae 4296 }
4297 }
718e3744 4298}
4299
d62a17ae 4300void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4301{
d62a17ae 4302 struct bgp_node *rn;
4303 struct bgp_table *table;
718e3744 4304
d62a17ae 4305 if (peer->status != Established)
4306 return;
718e3744 4307
d62a17ae 4308 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4309 && (safi != SAFI_EVPN))
4310 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4311 else
4312 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
67009e22
DS
4313 rn = bgp_route_next(rn)) {
4314 table = bgp_node_get_bgp_table_info(rn);
67009e22 4315
b54892e0
DS
4316 if (table == NULL)
4317 continue;
8692c506 4318
b54892e0
DS
4319 const struct prefix *p = bgp_node_get_prefix(rn);
4320 struct prefix_rd prd;
4321
4322 prd.family = AF_UNSPEC;
4323 prd.prefixlen = 64;
4324 memcpy(&prd.val, p->u.val, 8);
4325
4326 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 4327 }
718e3744 4328}
6b0655a2 4329
228da428 4330
d62a17ae 4331struct bgp_clear_node_queue {
4332 struct bgp_node *rn;
228da428
CC
4333};
4334
d62a17ae 4335static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4336{
d62a17ae 4337 struct bgp_clear_node_queue *cnq = data;
4338 struct bgp_node *rn = cnq->rn;
4339 struct peer *peer = wq->spec.data;
40381db7 4340 struct bgp_path_info *pi;
3103e8d2 4341 struct bgp *bgp;
d62a17ae 4342 afi_t afi = bgp_node_table(rn)->afi;
4343 safi_t safi = bgp_node_table(rn)->safi;
4344
4345 assert(rn && peer);
3103e8d2 4346 bgp = peer->bgp;
d62a17ae 4347
4348 /* It is possible that we have multiple paths for a prefix from a peer
4349 * if that peer is using AddPath.
4350 */
6f94b685 4351 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 4352 if (pi->peer != peer)
ea47320b
DL
4353 continue;
4354
4355 /* graceful restart STALE flag set. */
4356 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4357 && peer->nsf[afi][safi]
40381db7
DS
4358 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4359 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
4360 bgp_path_info_set_flag(rn, pi, BGP_PATH_STALE);
ea47320b
DL
4361 else {
4362 /* If this is an EVPN route, process for
4363 * un-import. */
4364 if (safi == SAFI_EVPN)
b54892e0
DS
4365 bgp_evpn_unimport_route(bgp, afi, safi,
4366 bgp_node_get_prefix(rn),
40381db7 4367 pi);
3103e8d2
DS
4368 /* Handle withdraw for VRF route-leaking and L3VPN */
4369 if (SAFI_UNICAST == safi
4370 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4371 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4372 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4373 bgp, pi);
960035b2 4374 }
3103e8d2 4375 if (SAFI_MPLS_VPN == safi &&
960035b2 4376 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4377 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4378 }
3103e8d2 4379
40381db7 4380 bgp_rib_remove(rn, pi, peer, afi, safi);
d62a17ae 4381 }
ea47320b 4382 }
d62a17ae 4383 return WQ_SUCCESS;
200df115 4384}
4385
d62a17ae 4386static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4387{
d62a17ae 4388 struct bgp_clear_node_queue *cnq = data;
4389 struct bgp_node *rn = cnq->rn;
4390 struct bgp_table *table = bgp_node_table(rn);
228da428 4391
d62a17ae 4392 bgp_unlock_node(rn);
4393 bgp_table_unlock(table);
4394 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4395}
4396
d62a17ae 4397static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4398{
d62a17ae 4399 struct peer *peer = wq->spec.data;
64e580a7 4400
d62a17ae 4401 /* Tickle FSM to start moving again */
4402 BGP_EVENT_ADD(peer, Clearing_Completed);
4403
4404 peer_unlock(peer); /* bgp_clear_route */
200df115 4405}
718e3744 4406
d62a17ae 4407static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4408{
d62a17ae 4409 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4410
4411 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4412#undef CLEAR_QUEUE_NAME_LEN
4413
0ce1ca80 4414 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4415 peer->clear_node_queue->spec.hold = 10;
4416 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4417 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4418 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4419 peer->clear_node_queue->spec.max_retries = 0;
4420
4421 /* we only 'lock' this peer reference when the queue is actually active
4422 */
4423 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4424}
4425
d62a17ae 4426static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4427 struct bgp_table *table)
65ca75e0 4428{
d62a17ae 4429 struct bgp_node *rn;
4430 int force = bm->process_main_queue ? 0 : 1;
6cf159b9 4431
d62a17ae 4432 if (!table)
4433 table = peer->bgp->rib[afi][safi];
dc83d712 4434
d62a17ae 4435 /* If still no table => afi/safi isn't configured at all or smth. */
4436 if (!table)
4437 return;
dc83d712 4438
d62a17ae 4439 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
40381db7 4440 struct bgp_path_info *pi, *next;
d62a17ae 4441 struct bgp_adj_in *ain;
4442 struct bgp_adj_in *ain_next;
4443
4444 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4445 * queued for every clearing peer, regardless of whether it is
4446 * relevant to the peer at hand.
4447 *
4448 * Overview: There are 3 different indices which need to be
4449 * scrubbed, potentially, when a peer is removed:
4450 *
4451 * 1 peer's routes visible via the RIB (ie accepted routes)
4452 * 2 peer's routes visible by the (optional) peer's adj-in index
4453 * 3 other routes visible by the peer's adj-out index
4454 *
4455 * 3 there is no hurry in scrubbing, once the struct peer is
4456 * removed from bgp->peer, we could just GC such deleted peer's
4457 * adj-outs at our leisure.
4458 *
4459 * 1 and 2 must be 'scrubbed' in some way, at least made
4460 * invisible via RIB index before peer session is allowed to be
4461 * brought back up. So one needs to know when such a 'search' is
4462 * complete.
4463 *
4464 * Ideally:
4465 *
4466 * - there'd be a single global queue or a single RIB walker
4467 * - rather than tracking which route_nodes still need to be
4468 * examined on a peer basis, we'd track which peers still
4469 * aren't cleared
4470 *
4471 * Given that our per-peer prefix-counts now should be reliable,
4472 * this may actually be achievable. It doesn't seem to be a huge
4473 * problem at this time,
4474 *
4475 * It is possible that we have multiple paths for a prefix from
4476 * a peer
4477 * if that peer is using AddPath.
4478 */
4479 ain = rn->adj_in;
4480 while (ain) {
4481 ain_next = ain->next;
4482
4483 if (ain->peer == peer) {
4484 bgp_adj_in_remove(rn, ain);
4485 bgp_unlock_node(rn);
4486 }
4487
4488 ain = ain_next;
4489 }
4490
6f94b685 4491 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
40381db7
DS
4492 next = pi->next;
4493 if (pi->peer != peer)
d62a17ae 4494 continue;
4495
4496 if (force)
40381db7 4497 bgp_path_info_reap(rn, pi);
d62a17ae 4498 else {
4499 struct bgp_clear_node_queue *cnq;
4500
4501 /* both unlocked in bgp_clear_node_queue_del */
4502 bgp_table_lock(bgp_node_table(rn));
4503 bgp_lock_node(rn);
4504 cnq = XCALLOC(
4505 MTYPE_BGP_CLEAR_NODE_QUEUE,
4506 sizeof(struct bgp_clear_node_queue));
4507 cnq->rn = rn;
4508 work_queue_add(peer->clear_node_queue, cnq);
4509 break;
4510 }
4511 }
4512 }
4513 return;
4514}
4515
4516void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4517{
4518 struct bgp_node *rn;
4519 struct bgp_table *table;
4520
4521 if (peer->clear_node_queue == NULL)
4522 bgp_clear_node_queue_init(peer);
4523
4524 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4525 * Idle until it receives a Clearing_Completed event. This protects
4526 * against peers which flap faster than we can we clear, which could
4527 * lead to:
4528 *
4529 * a) race with routes from the new session being installed before
4530 * clear_route_node visits the node (to delete the route of that
4531 * peer)
4532 * b) resource exhaustion, clear_route_node likely leads to an entry
4533 * on the process_main queue. Fast-flapping could cause that queue
4534 * to grow and grow.
4535 */
4536
4537 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4538 * the unlock will happen upon work-queue completion; other wise, the
4539 * unlock happens at the end of this function.
4540 */
4541 if (!peer->clear_node_queue->thread)
4542 peer_lock(peer);
4543
4544 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4545 bgp_clear_route_table(peer, afi, safi, NULL);
4546 else
4547 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
67009e22
DS
4548 rn = bgp_route_next(rn)) {
4549 table = bgp_node_get_bgp_table_info(rn);
4550 if (!table)
4551 continue;
4552
4553 bgp_clear_route_table(peer, afi, safi, table);
4554 }
d62a17ae 4555
4556 /* unlock if no nodes got added to the clear-node-queue. */
4557 if (!peer->clear_node_queue->thread)
4558 peer_unlock(peer);
718e3744 4559}
d62a17ae 4560
4561void bgp_clear_route_all(struct peer *peer)
718e3744 4562{
d62a17ae 4563 afi_t afi;
4564 safi_t safi;
718e3744 4565
05c7a1cc
QY
4566 FOREACH_AFI_SAFI (afi, safi)
4567 bgp_clear_route(peer, afi, safi);
65efcfce 4568
49e5a4a0 4569#ifdef ENABLE_BGP_VNC
d62a17ae 4570 rfapiProcessPeerDown(peer);
65efcfce 4571#endif
718e3744 4572}
4573
d62a17ae 4574void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4575{
d62a17ae 4576 struct bgp_table *table;
4577 struct bgp_node *rn;
4578 struct bgp_adj_in *ain;
4579 struct bgp_adj_in *ain_next;
718e3744 4580
d62a17ae 4581 table = peer->bgp->rib[afi][safi];
718e3744 4582
d62a17ae 4583 /* It is possible that we have multiple paths for a prefix from a peer
4584 * if that peer is using AddPath.
4585 */
4586 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
4587 ain = rn->adj_in;
43143c8f 4588
d62a17ae 4589 while (ain) {
4590 ain_next = ain->next;
43143c8f 4591
d62a17ae 4592 if (ain->peer == peer) {
4593 bgp_adj_in_remove(rn, ain);
4594 bgp_unlock_node(rn);
4595 }
43143c8f 4596
d62a17ae 4597 ain = ain_next;
4598 }
4599 }
718e3744 4600}
93406d87 4601
d62a17ae 4602void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4603{
4604 struct bgp_node *rn;
40381db7 4605 struct bgp_path_info *pi;
d62a17ae 4606 struct bgp_table *table;
4607
4608 if (safi == SAFI_MPLS_VPN) {
4609 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4610 rn = bgp_route_next(rn)) {
4611 struct bgp_node *rm;
d62a17ae 4612
4613 /* look for neighbor in tables */
67009e22
DS
4614 table = bgp_node_get_bgp_table_info(rn);
4615 if (!table)
ea47320b
DL
4616 continue;
4617
4618 for (rm = bgp_table_top(table); rm;
4619 rm = bgp_route_next(rm))
6f94b685
DS
4620 for (pi = bgp_node_get_bgp_path_info(rm); pi;
4621 pi = pi->next) {
40381db7 4622 if (pi->peer != peer)
ea47320b 4623 continue;
40381db7 4624 if (!CHECK_FLAG(pi->flags,
1defdda8 4625 BGP_PATH_STALE))
ea47320b
DL
4626 break;
4627
40381db7 4628 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4629 break;
4630 }
d62a17ae 4631 }
4632 } else {
4633 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4634 rn = bgp_route_next(rn))
6f94b685
DS
4635 for (pi = bgp_node_get_bgp_path_info(rn); pi;
4636 pi = pi->next) {
40381db7 4637 if (pi->peer != peer)
ea47320b 4638 continue;
40381db7 4639 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4640 break;
40381db7 4641 bgp_rib_remove(rn, pi, peer, afi, safi);
ea47320b
DL
4642 break;
4643 }
d62a17ae 4644 }
93406d87 4645}
6b0655a2 4646
3dc339cd 4647bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 4648{
e0df4c04 4649 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 4650 return true;
e0df4c04 4651
9dac9fc8
DA
4652 if (peer->sort == BGP_PEER_EBGP
4653 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
4654 || FILTER_LIST_OUT_NAME(filter)
4655 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
4656 return true;
4657 return false;
9dac9fc8
DA
4658}
4659
3dc339cd 4660bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 4661{
e0df4c04 4662 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 4663 return true;
e0df4c04 4664
9dac9fc8
DA
4665 if (peer->sort == BGP_PEER_EBGP
4666 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
4667 || FILTER_LIST_IN_NAME(filter)
4668 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
4669 return true;
4670 return false;
9dac9fc8
DA
4671}
4672
568e10ca 4673static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
4674 safi_t safi)
bb86c601 4675{
d62a17ae 4676 struct bgp_node *rn;
40381db7 4677 struct bgp_path_info *pi;
4b7e6066 4678 struct bgp_path_info *next;
bb86c601 4679
d62a17ae 4680 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
6f94b685 4681 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
b54892e0
DS
4682 const struct prefix *p = bgp_node_get_prefix(rn);
4683
40381db7 4684 next = pi->next;
1b7bb747
CS
4685
4686 /* Unimport EVPN routes from VRFs */
4687 if (safi == SAFI_EVPN)
4688 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 4689 SAFI_EVPN, p, pi);
1b7bb747 4690
40381db7
DS
4691 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
4692 && pi->type == ZEBRA_ROUTE_BGP
4693 && (pi->sub_type == BGP_ROUTE_NORMAL
4694 || pi->sub_type == BGP_ROUTE_AGGREGATE
4695 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 4696
d62a17ae 4697 if (bgp_fibupd_safi(safi))
b54892e0 4698 bgp_zebra_withdraw(p, pi, bgp, safi);
40381db7 4699 bgp_path_info_reap(rn, pi);
d62a17ae 4700 }
4701 }
bb86c601
LB
4702}
4703
718e3744 4704/* Delete all kernel routes. */
d62a17ae 4705void bgp_cleanup_routes(struct bgp *bgp)
4706{
4707 afi_t afi;
4708 struct bgp_node *rn;
67009e22 4709 struct bgp_table *table;
d62a17ae 4710
4711 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
4712 if (afi == AFI_L2VPN)
4713 continue;
568e10ca 4714 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
4715 SAFI_UNICAST);
d62a17ae 4716 /*
4717 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4718 */
4719 if (afi != AFI_L2VPN) {
4720 safi_t safi;
4721 safi = SAFI_MPLS_VPN;
4722 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4723 rn = bgp_route_next(rn)) {
67009e22
DS
4724 table = bgp_node_get_bgp_table_info(rn);
4725 if (table != NULL) {
4726 bgp_cleanup_table(bgp, table, safi);
4727 bgp_table_finish(&table);
4728 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4729 bgp_unlock_node(rn);
4730 }
4731 }
4732 safi = SAFI_ENCAP;
4733 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4734 rn = bgp_route_next(rn)) {
67009e22
DS
4735 table = bgp_node_get_bgp_table_info(rn);
4736 if (table != NULL) {
4737 bgp_cleanup_table(bgp, table, safi);
4738 bgp_table_finish(&table);
4739 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4740 bgp_unlock_node(rn);
4741 }
4742 }
4743 }
4744 }
4745 for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn;
4746 rn = bgp_route_next(rn)) {
67009e22
DS
4747 table = bgp_node_get_bgp_table_info(rn);
4748 if (table != NULL) {
4749 bgp_cleanup_table(bgp, table, SAFI_EVPN);
4750 bgp_table_finish(&table);
4751 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4752 bgp_unlock_node(rn);
4753 }
bb86c601 4754 }
718e3744 4755}
4756
d62a17ae 4757void bgp_reset(void)
718e3744 4758{
d62a17ae 4759 vty_reset();
4760 bgp_zclient_reset();
4761 access_list_reset();
4762 prefix_list_reset();
718e3744 4763}
6b0655a2 4764
d62a17ae 4765static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 4766{
d62a17ae 4767 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
4768 && CHECK_FLAG(peer->af_cap[afi][safi],
4769 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
4770}
4771
718e3744 4772/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4773 value. */
d62a17ae 4774int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
4775 struct bgp_nlri *packet)
4776{
d7c0a89a
QY
4777 uint8_t *pnt;
4778 uint8_t *lim;
d62a17ae 4779 struct prefix p;
4780 int psize;
4781 int ret;
4782 afi_t afi;
4783 safi_t safi;
4784 int addpath_encoded;
d7c0a89a 4785 uint32_t addpath_id;
d62a17ae 4786
d62a17ae 4787 pnt = packet->nlri;
4788 lim = pnt + packet->length;
4789 afi = packet->afi;
4790 safi = packet->safi;
4791 addpath_id = 0;
4792 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
4793
4794 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4795 syntactic validity. If the field is syntactically incorrect,
4796 then the Error Subcode is set to Invalid Network Field. */
4797 for (; pnt < lim; pnt += psize) {
4798 /* Clear prefix structure. */
4799 memset(&p, 0, sizeof(struct prefix));
4800
4801 if (addpath_encoded) {
4802
4803 /* When packet overflow occurs return immediately. */
761ed665 4804 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 4805 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4806
a3a850a1 4807 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 4808 addpath_id = ntohl(addpath_id);
d62a17ae 4809 pnt += BGP_ADDPATH_ID_LEN;
4810 }
718e3744 4811
d62a17ae 4812 /* Fetch prefix length. */
4813 p.prefixlen = *pnt++;
4814 /* afi/safi validity already verified by caller,
4815 * bgp_update_receive */
4816 p.family = afi2family(afi);
4817
4818 /* Prefix length check. */
4819 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 4820 flog_err(
e50f7cfd 4821 EC_BGP_UPDATE_RCV,
14454c9f 4822 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 4823 peer->host, p.prefixlen, packet->afi);
513386b5 4824 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 4825 }
6b0655a2 4826
d62a17ae 4827 /* Packet size overflow check. */
4828 psize = PSIZE(p.prefixlen);
4829
4830 /* When packet overflow occur return immediately. */
4831 if (pnt + psize > lim) {
af4c2728 4832 flog_err(
e50f7cfd 4833 EC_BGP_UPDATE_RCV,
d62a17ae 4834 "%s [Error] Update packet error (prefix length %d overflows packet)",
4835 peer->host, p.prefixlen);
513386b5 4836 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4837 }
4838
4839 /* Defensive coding, double-check the psize fits in a struct
4840 * prefix */
4841 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 4842 flog_err(
e50f7cfd 4843 EC_BGP_UPDATE_RCV,
d62a17ae 4844 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4845 peer->host, p.prefixlen, sizeof(p.u));
513386b5 4846 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4847 }
4848
4849 /* Fetch prefix from NLRI packet. */
a85297a7 4850 memcpy(p.u.val, pnt, psize);
d62a17ae 4851
4852 /* Check address. */
4853 if (afi == AFI_IP && safi == SAFI_UNICAST) {
4854 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
4855 /* From RFC4271 Section 6.3:
4856 *
4857 * If a prefix in the NLRI field is semantically
4858 * incorrect
4859 * (e.g., an unexpected multicast IP address),
4860 * an error SHOULD
4861 * be logged locally, and the prefix SHOULD be
4862 * ignored.
a4d82a8a 4863 */
af4c2728 4864 flog_err(
e50f7cfd 4865 EC_BGP_UPDATE_RCV,
d62a17ae 4866 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4867 peer->host, inet_ntoa(p.u.prefix4));
4868 continue;
4869 }
4870 }
4871
4872 /* Check address. */
4873 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
4874 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4875 char buf[BUFSIZ];
4876
af4c2728 4877 flog_err(
e50f7cfd 4878 EC_BGP_UPDATE_RCV,
d62a17ae 4879 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4880 peer->host,
4881 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4882 BUFSIZ));
4883
4884 continue;
4885 }
4886 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
4887 char buf[BUFSIZ];
4888
af4c2728 4889 flog_err(
e50f7cfd 4890 EC_BGP_UPDATE_RCV,
d62a17ae 4891 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4892 peer->host,
4893 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4894 BUFSIZ));
4895
4896 continue;
4897 }
4898 }
4899
4900 /* Normal process. */
4901 if (attr)
4902 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
4903 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 4904 NULL, NULL, 0, 0, NULL);
d62a17ae 4905 else
4906 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
4907 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
4908 BGP_ROUTE_NORMAL, NULL, NULL, 0,
4909 NULL);
d62a17ae 4910
513386b5
DA
4911 /* Do not send BGP notification twice when maximum-prefix count
4912 * overflow. */
4913 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4914 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
4915
4916 /* Address family configuration mismatch. */
d62a17ae 4917 if (ret < 0)
513386b5 4918 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 4919 }
4920
4921 /* Packet length consistency check. */
4922 if (pnt != lim) {
af4c2728 4923 flog_err(
e50f7cfd 4924 EC_BGP_UPDATE_RCV,
d62a17ae 4925 "%s [Error] Update packet error (prefix length mismatch with total length)",
4926 peer->host);
513386b5 4927 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4928 }
6b0655a2 4929
513386b5 4930 return BGP_NLRI_PARSE_OK;
718e3744 4931}
4932
d62a17ae 4933static struct bgp_static *bgp_static_new(void)
718e3744 4934{
d62a17ae 4935 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 4936}
4937
d62a17ae 4938static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 4939{
0a22ddfb 4940 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 4941 route_map_counter_decrement(bgp_static->rmap.map);
4942
0a22ddfb 4943 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 4944 XFREE(MTYPE_BGP_STATIC, bgp_static);
4945}
4946
5f040085 4947void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 4948 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
4949{
4950 struct bgp_node *rn;
40381db7 4951 struct bgp_path_info *pi;
4b7e6066 4952 struct bgp_path_info *new;
40381db7 4953 struct bgp_path_info rmap_path;
d62a17ae 4954 struct attr attr;
4955 struct attr *attr_new;
b68885f9 4956 route_map_result_t ret;
49e5a4a0 4957#ifdef ENABLE_BGP_VNC
d62a17ae 4958 int vnc_implicit_withdraw = 0;
65efcfce 4959#endif
fee0f4c6 4960
d62a17ae 4961 assert(bgp_static);
dd8103a9 4962
d62a17ae 4963 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4964
d62a17ae 4965 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 4966
d62a17ae 4967 attr.nexthop = bgp_static->igpnexthop;
4968 attr.med = bgp_static->igpmetric;
4969 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 4970
d62a17ae 4971 if (bgp_static->atomic)
4972 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 4973
d62a17ae 4974 /* Store label index, if required. */
4975 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
4976 attr.label_index = bgp_static->label_index;
4977 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
4978 }
718e3744 4979
d62a17ae 4980 /* Apply route-map. */
4981 if (bgp_static->rmap.name) {
4982 struct attr attr_tmp = attr;
80ced710 4983
40381db7
DS
4984 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
4985 rmap_path.peer = bgp->peer_self;
4986 rmap_path.attr = &attr_tmp;
fee0f4c6 4987
d62a17ae 4988 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 4989
40381db7
DS
4990 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
4991 &rmap_path);
fee0f4c6 4992
d62a17ae 4993 bgp->peer_self->rmap_type = 0;
718e3744 4994
d62a17ae 4995 if (ret == RMAP_DENYMATCH) {
4996 /* Free uninterned attribute. */
4997 bgp_attr_flush(&attr_tmp);
718e3744 4998
d62a17ae 4999 /* Unintern original. */
5000 aspath_unintern(&attr.aspath);
5001 bgp_static_withdraw(bgp, p, afi, safi);
5002 return;
5003 }
7f323236 5004
892fedb6 5005 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
7f323236
DW
5006 bgp_attr_add_gshut_community(&attr_tmp);
5007
d62a17ae 5008 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5009 } else {
5010
892fedb6 5011 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
7f323236
DW
5012 bgp_attr_add_gshut_community(&attr);
5013
d62a17ae 5014 attr_new = bgp_attr_intern(&attr);
7f323236 5015 }
718e3744 5016
6f94b685 5017 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
5018 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5019 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5020 break;
5021
40381db7
DS
5022 if (pi) {
5023 if (attrhash_cmp(pi->attr, attr_new)
5024 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5025 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
d62a17ae 5026 bgp_unlock_node(rn);
5027 bgp_attr_unintern(&attr_new);
5028 aspath_unintern(&attr.aspath);
5029 return;
5030 } else {
5031 /* The attribute is changed. */
40381db7 5032 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5033
5034 /* Rewrite BGP route information. */
40381db7
DS
5035 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
5036 bgp_path_info_restore(rn, pi);
d62a17ae 5037 else
40381db7 5038 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5039#ifdef ENABLE_BGP_VNC
d62a17ae 5040 if ((afi == AFI_IP || afi == AFI_IP6)
5041 && (safi == SAFI_UNICAST)) {
40381db7 5042 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5043 /*
5044 * Implicit withdraw case.
40381db7 5045 * We have to do this before pi is
d62a17ae 5046 * changed
5047 */
5048 ++vnc_implicit_withdraw;
40381db7 5049 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5050 vnc_import_bgp_exterior_del_route(
40381db7 5051 bgp, p, pi);
d62a17ae 5052 }
5053 }
65efcfce 5054#endif
40381db7
DS
5055 bgp_attr_unintern(&pi->attr);
5056 pi->attr = attr_new;
5057 pi->uptime = bgp_clock();
49e5a4a0 5058#ifdef ENABLE_BGP_VNC
d62a17ae 5059 if ((afi == AFI_IP || afi == AFI_IP6)
5060 && (safi == SAFI_UNICAST)) {
5061 if (vnc_implicit_withdraw) {
40381db7 5062 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5063 vnc_import_bgp_exterior_add_route(
40381db7 5064 bgp, p, pi);
d62a17ae 5065 }
5066 }
65efcfce 5067#endif
718e3744 5068
d62a17ae 5069 /* Nexthop reachability check. */
892fedb6 5070 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5071 && (safi == SAFI_UNICAST
5072 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5073
5074 struct bgp *bgp_nexthop = bgp;
5075
40381db7
DS
5076 if (pi->extra && pi->extra->bgp_orig)
5077 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5078
5079 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
40381db7
DS
5080 afi, pi, NULL, 0))
5081 bgp_path_info_set_flag(rn, pi,
18ee8310 5082 BGP_PATH_VALID);
d62a17ae 5083 else {
5084 if (BGP_DEBUG(nht, NHT)) {
5085 char buf1[INET6_ADDRSTRLEN];
5086 inet_ntop(p->family,
5087 &p->u.prefix, buf1,
5088 INET6_ADDRSTRLEN);
5089 zlog_debug(
5090 "%s(%s): Route not in table, not advertising",
15569c58 5091 __func__, buf1);
d62a17ae 5092 }
18ee8310 5093 bgp_path_info_unset_flag(
40381db7 5094 rn, pi, BGP_PATH_VALID);
d62a17ae 5095 }
5096 } else {
5097 /* Delete the NHT structure if any, if we're
5098 * toggling between
5099 * enabling/disabling import check. We
5100 * deregister the route
5101 * from NHT to avoid overloading NHT and the
5102 * process interaction
5103 */
40381db7
DS
5104 bgp_unlink_nexthop(pi);
5105 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 5106 }
5107 /* Process change. */
40381db7 5108 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 5109 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
5110
5111 if (SAFI_UNICAST == safi
5112 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5113 || bgp->inst_type
5114 == BGP_INSTANCE_TYPE_DEFAULT)) {
5115 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5116 pi);
ddb5b488
PZ
5117 }
5118
d62a17ae 5119 bgp_unlock_node(rn);
5120 aspath_unintern(&attr.aspath);
5121 return;
5122 }
718e3744 5123 }
718e3744 5124
d62a17ae 5125 /* Make new BGP info. */
5126 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
5127 attr_new, rn);
5128 /* Nexthop reachability check. */
892fedb6 5129 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5130 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 5131 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
18ee8310 5132 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
d62a17ae 5133 else {
5134 if (BGP_DEBUG(nht, NHT)) {
5135 char buf1[INET6_ADDRSTRLEN];
5136 inet_ntop(p->family, &p->u.prefix, buf1,
5137 INET6_ADDRSTRLEN);
5138 zlog_debug(
5139 "%s(%s): Route not in table, not advertising",
15569c58 5140 __func__, buf1);
d62a17ae 5141 }
18ee8310 5142 bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID);
d62a17ae 5143 }
5144 } else {
5145 /* Delete the NHT structure if any, if we're toggling between
5146 * enabling/disabling import check. We deregister the route
5147 * from NHT to avoid overloading NHT and the process interaction
5148 */
5149 bgp_unlink_nexthop(new);
5150
18ee8310 5151 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
fc9a856f 5152 }
078430f6 5153
d62a17ae 5154 /* Aggregate address increment. */
5155 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5156
d62a17ae 5157 /* Register new BGP information. */
18ee8310 5158 bgp_path_info_add(rn, new);
718e3744 5159
d62a17ae 5160 /* route_node_get lock */
5161 bgp_unlock_node(rn);
5162
5163 /* Process change. */
5164 bgp_process(bgp, rn, afi, safi);
5165
ddb5b488
PZ
5166 if (SAFI_UNICAST == safi
5167 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5168 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5169 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5170 }
5171
d62a17ae 5172 /* Unintern original. */
5173 aspath_unintern(&attr.aspath);
718e3744 5174}
5175
5f040085 5176void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 5177 safi_t safi)
718e3744 5178{
d62a17ae 5179 struct bgp_node *rn;
40381db7 5180 struct bgp_path_info *pi;
718e3744 5181
d62a17ae 5182 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5183
d62a17ae 5184 /* Check selected route and self inserted route. */
6f94b685 5185 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
5186 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5187 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5188 break;
5189
5190 /* Withdraw static BGP route from routing table. */
40381db7 5191 if (pi) {
ddb5b488
PZ
5192 if (SAFI_UNICAST == safi
5193 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5194 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5195 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5196 }
40381db7
DS
5197 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5198 bgp_unlink_nexthop(pi);
5199 bgp_path_info_delete(rn, pi);
d62a17ae 5200 bgp_process(bgp, rn, afi, safi);
5201 }
718e3744 5202
d62a17ae 5203 /* Unlock bgp_node_lookup. */
5204 bgp_unlock_node(rn);
718e3744 5205}
5206
137446f9
LB
5207/*
5208 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5209 */
5f040085 5210static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5211 afi_t afi, safi_t safi,
5212 struct prefix_rd *prd)
718e3744 5213{
d62a17ae 5214 struct bgp_node *rn;
40381db7 5215 struct bgp_path_info *pi;
718e3744 5216
d62a17ae 5217 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5218
d62a17ae 5219 /* Check selected route and self inserted route. */
6f94b685 5220 for (pi = bgp_node_get_bgp_path_info(rn); 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;
718e3744 5224
d62a17ae 5225 /* Withdraw static BGP route from routing table. */
40381db7 5226 if (pi) {
49e5a4a0 5227#ifdef ENABLE_BGP_VNC
d62a17ae 5228 rfapiProcessWithdraw(
40381db7 5229 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5230 1); /* Kill, since it is an administrative change */
65efcfce 5231#endif
ddb5b488
PZ
5232 if (SAFI_MPLS_VPN == safi
5233 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5234 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5235 }
40381db7
DS
5236 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5237 bgp_path_info_delete(rn, pi);
d62a17ae 5238 bgp_process(bgp, rn, afi, safi);
5239 }
718e3744 5240
d62a17ae 5241 /* Unlock bgp_node_lookup. */
5242 bgp_unlock_node(rn);
718e3744 5243}
5244
5f040085 5245static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5246 struct bgp_static *bgp_static, afi_t afi,
5247 safi_t safi)
137446f9 5248{
d62a17ae 5249 struct bgp_node *rn;
4b7e6066 5250 struct bgp_path_info *new;
d62a17ae 5251 struct attr *attr_new;
5252 struct attr attr = {0};
40381db7 5253 struct bgp_path_info *pi;
49e5a4a0 5254#ifdef ENABLE_BGP_VNC
d62a17ae 5255 mpls_label_t label = 0;
65efcfce 5256#endif
d7c0a89a 5257 uint32_t num_labels = 0;
d62a17ae 5258 union gw_addr add;
137446f9 5259
d62a17ae 5260 assert(bgp_static);
137446f9 5261
b57ba6d2
MK
5262 if (bgp_static->label != MPLS_INVALID_LABEL)
5263 num_labels = 1;
d62a17ae 5264 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5265 &bgp_static->prd);
137446f9 5266
d62a17ae 5267 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5268
d62a17ae 5269 attr.nexthop = bgp_static->igpnexthop;
5270 attr.med = bgp_static->igpmetric;
5271 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5272
d62a17ae 5273 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5274 || (safi == SAFI_ENCAP)) {
5275 if (afi == AFI_IP) {
5276 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5277 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5278 }
5279 }
5280 if (afi == AFI_L2VPN) {
5281 if (bgp_static->gatewayIp.family == AF_INET)
5282 add.ipv4.s_addr =
5283 bgp_static->gatewayIp.u.prefix4.s_addr;
5284 else if (bgp_static->gatewayIp.family == AF_INET6)
5285 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5286 sizeof(struct in6_addr));
5287 overlay_index_update(&attr, bgp_static->eth_s_id, &add);
5288 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5289 struct bgp_encap_type_vxlan bet;
5290 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5291 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5292 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5293 }
5294 if (bgp_static->router_mac) {
5295 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5296 }
5297 }
5298 /* Apply route-map. */
5299 if (bgp_static->rmap.name) {
5300 struct attr attr_tmp = attr;
40381db7 5301 struct bgp_path_info rmap_path;
b68885f9 5302 route_map_result_t ret;
137446f9 5303
40381db7
DS
5304 rmap_path.peer = bgp->peer_self;
5305 rmap_path.attr = &attr_tmp;
137446f9 5306
d62a17ae 5307 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5308
40381db7
DS
5309 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
5310 &rmap_path);
137446f9 5311
d62a17ae 5312 bgp->peer_self->rmap_type = 0;
137446f9 5313
d62a17ae 5314 if (ret == RMAP_DENYMATCH) {
5315 /* Free uninterned attribute. */
5316 bgp_attr_flush(&attr_tmp);
137446f9 5317
d62a17ae 5318 /* Unintern original. */
5319 aspath_unintern(&attr.aspath);
5320 bgp_static_withdraw_safi(bgp, p, afi, safi,
5321 &bgp_static->prd);
5322 return;
5323 }
137446f9 5324
d62a17ae 5325 attr_new = bgp_attr_intern(&attr_tmp);
5326 } else {
5327 attr_new = bgp_attr_intern(&attr);
5328 }
137446f9 5329
6f94b685 5330 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
5331 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5332 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5333 break;
5334
40381db7 5335 if (pi) {
d62a17ae 5336 memset(&add, 0, sizeof(union gw_addr));
40381db7
DS
5337 if (attrhash_cmp(pi->attr, attr_new)
5338 && overlay_index_equal(afi, pi, bgp_static->eth_s_id, &add)
5339 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 5340 bgp_unlock_node(rn);
5341 bgp_attr_unintern(&attr_new);
5342 aspath_unintern(&attr.aspath);
5343 return;
5344 } else {
5345 /* The attribute is changed. */
40381db7 5346 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5347
5348 /* Rewrite BGP route information. */
40381db7
DS
5349 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
5350 bgp_path_info_restore(rn, pi);
d62a17ae 5351 else
40381db7
DS
5352 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5353 bgp_attr_unintern(&pi->attr);
5354 pi->attr = attr_new;
5355 pi->uptime = bgp_clock();
49e5a4a0 5356#ifdef ENABLE_BGP_VNC
40381db7
DS
5357 if (pi->extra)
5358 label = decode_label(&pi->extra->label[0]);
65efcfce 5359#endif
137446f9 5360
d62a17ae 5361 /* Process change. */
40381db7 5362 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 5363 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
5364
5365 if (SAFI_MPLS_VPN == safi
5366 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5367 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5368 }
49e5a4a0 5369#ifdef ENABLE_BGP_VNC
40381db7
DS
5370 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5371 pi->attr, afi, safi, pi->type,
5372 pi->sub_type, &label);
65efcfce 5373#endif
d62a17ae 5374 bgp_unlock_node(rn);
5375 aspath_unintern(&attr.aspath);
5376 return;
5377 }
5378 }
137446f9
LB
5379
5380
d62a17ae 5381 /* Make new BGP info. */
5382 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
5383 attr_new, rn);
1defdda8 5384 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5385 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5386 if (num_labels) {
5387 new->extra->label[0] = bgp_static->label;
5388 new->extra->num_labels = num_labels;
5389 }
49e5a4a0 5390#ifdef ENABLE_BGP_VNC
d62a17ae 5391 label = decode_label(&bgp_static->label);
65efcfce 5392#endif
137446f9 5393
d62a17ae 5394 /* Aggregate address increment. */
5395 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5396
d62a17ae 5397 /* Register new BGP information. */
18ee8310 5398 bgp_path_info_add(rn, new);
d62a17ae 5399 /* route_node_get lock */
5400 bgp_unlock_node(rn);
137446f9 5401
d62a17ae 5402 /* Process change. */
5403 bgp_process(bgp, rn, afi, safi);
137446f9 5404
ddb5b488
PZ
5405 if (SAFI_MPLS_VPN == safi
5406 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5407 vpn_leak_to_vrf_update(bgp, new);
5408 }
49e5a4a0 5409#ifdef ENABLE_BGP_VNC
d62a17ae 5410 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5411 safi, new->type, new->sub_type, &label);
65efcfce
LB
5412#endif
5413
d62a17ae 5414 /* Unintern original. */
5415 aspath_unintern(&attr.aspath);
137446f9
LB
5416}
5417
718e3744 5418/* Configure static BGP network. When user don't run zebra, static
5419 route should be installed as valid. */
e2a86ad9
DS
5420static int bgp_static_set(struct vty *vty, const char *negate,
5421 const char *ip_str, afi_t afi, safi_t safi,
d7c0a89a 5422 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 5423{
5424 VTY_DECLVAR_CONTEXT(bgp, bgp);
5425 int ret;
5426 struct prefix p;
5427 struct bgp_static *bgp_static;
5428 struct bgp_node *rn;
d7c0a89a 5429 uint8_t need_update = 0;
d62a17ae 5430
5431 /* Convert IP prefix string to struct prefix. */
5432 ret = str2prefix(ip_str, &p);
5433 if (!ret) {
5434 vty_out(vty, "%% Malformed prefix\n");
5435 return CMD_WARNING_CONFIG_FAILED;
5436 }
5437 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5438 vty_out(vty, "%% Malformed prefix (link-local address)\n");
5439 return CMD_WARNING_CONFIG_FAILED;
5440 }
718e3744 5441
d62a17ae 5442 apply_mask(&p);
718e3744 5443
e2a86ad9 5444 if (negate) {
718e3744 5445
e2a86ad9
DS
5446 /* Set BGP static route configuration. */
5447 rn = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5448
e2a86ad9 5449 if (!rn) {
a4d82a8a 5450 vty_out(vty, "%% Can't find static route specified\n");
d62a17ae 5451 return CMD_WARNING_CONFIG_FAILED;
5452 }
5453
5a8ba9fc 5454 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 5455
e2a86ad9
DS
5456 if ((label_index != BGP_INVALID_LABEL_INDEX)
5457 && (label_index != bgp_static->label_index)) {
5458 vty_out(vty,
5459 "%% label-index doesn't match static route\n");
5460 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5461 }
d62a17ae 5462
e2a86ad9
DS
5463 if ((rmap && bgp_static->rmap.name)
5464 && strcmp(rmap, bgp_static->rmap.name)) {
5465 vty_out(vty,
5466 "%% route-map name doesn't match static route\n");
5467 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5468 }
718e3744 5469
e2a86ad9
DS
5470 /* Update BGP RIB. */
5471 if (!bgp_static->backdoor)
5472 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5473
e2a86ad9
DS
5474 /* Clear configuration. */
5475 bgp_static_free(bgp_static);
5a8ba9fc 5476 bgp_node_set_bgp_static_info(rn, NULL);
e2a86ad9
DS
5477 bgp_unlock_node(rn);
5478 bgp_unlock_node(rn);
5479 } else {
718e3744 5480
e2a86ad9
DS
5481 /* Set BGP static route configuration. */
5482 rn = bgp_node_get(bgp->route[afi][safi], &p);
718e3744 5483
5a8ba9fc 5484 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 5485 if (bgp_static) {
e2a86ad9 5486 /* Configuration change. */
e2a86ad9
DS
5487 /* Label index cannot be changed. */
5488 if (bgp_static->label_index != label_index) {
5489 vty_out(vty, "%% cannot change label-index\n");
5490 return CMD_WARNING_CONFIG_FAILED;
5491 }
d62a17ae 5492
e2a86ad9 5493 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5494 if (bgp_static->valid
5495 && bgp_static->backdoor != backdoor)
e2a86ad9 5496 need_update = 1;
718e3744 5497
e2a86ad9 5498 bgp_static->backdoor = backdoor;
718e3744 5499
e2a86ad9 5500 if (rmap) {
0a22ddfb
QY
5501 XFREE(MTYPE_ROUTE_MAP_NAME,
5502 bgp_static->rmap.name);
b4897fa5 5503 route_map_counter_decrement(
5504 bgp_static->rmap.map);
e2a86ad9
DS
5505 bgp_static->rmap.name =
5506 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5507 bgp_static->rmap.map =
5508 route_map_lookup_by_name(rmap);
b4897fa5 5509 route_map_counter_increment(
5510 bgp_static->rmap.map);
e2a86ad9 5511 } else {
0a22ddfb
QY
5512 XFREE(MTYPE_ROUTE_MAP_NAME,
5513 bgp_static->rmap.name);
b4897fa5 5514 route_map_counter_decrement(
5515 bgp_static->rmap.map);
e2a86ad9
DS
5516 bgp_static->rmap.map = NULL;
5517 bgp_static->valid = 0;
5518 }
5519 bgp_unlock_node(rn);
5520 } else {
5521 /* New configuration. */
5522 bgp_static = bgp_static_new();
5523 bgp_static->backdoor = backdoor;
5524 bgp_static->valid = 0;
5525 bgp_static->igpmetric = 0;
975a328e 5526 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 5527 bgp_static->label_index = label_index;
718e3744 5528
e2a86ad9 5529 if (rmap) {
0a22ddfb
QY
5530 XFREE(MTYPE_ROUTE_MAP_NAME,
5531 bgp_static->rmap.name);
b4897fa5 5532 route_map_counter_decrement(
5533 bgp_static->rmap.map);
e2a86ad9
DS
5534 bgp_static->rmap.name =
5535 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5536 bgp_static->rmap.map =
5537 route_map_lookup_by_name(rmap);
b4897fa5 5538 route_map_counter_increment(
5539 bgp_static->rmap.map);
e2a86ad9 5540 }
5a8ba9fc 5541 bgp_node_set_bgp_static_info(rn, bgp_static);
e2a86ad9 5542 }
d62a17ae 5543
e2a86ad9
DS
5544 bgp_static->valid = 1;
5545 if (need_update)
5546 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5547
e2a86ad9
DS
5548 if (!bgp_static->backdoor)
5549 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5550 }
d62a17ae 5551
5552 return CMD_SUCCESS;
5553}
5554
5555void bgp_static_add(struct bgp *bgp)
5556{
5557 afi_t afi;
5558 safi_t safi;
5559 struct bgp_node *rn;
5560 struct bgp_node *rm;
5561 struct bgp_table *table;
5562 struct bgp_static *bgp_static;
5563
05c7a1cc
QY
5564 FOREACH_AFI_SAFI (afi, safi)
5565 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5566 rn = bgp_route_next(rn)) {
67009e22 5567 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5568 continue;
ea47320b 5569
05c7a1cc
QY
5570 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5571 || (safi == SAFI_EVPN)) {
67009e22 5572 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5573
5574 for (rm = bgp_table_top(table); rm;
5575 rm = bgp_route_next(rm)) {
a78beeb5 5576 bgp_static =
5a8ba9fc
DS
5577 bgp_node_get_bgp_static_info(
5578 rm);
b54892e0
DS
5579 bgp_static_update_safi(bgp,
5580 bgp_node_get_prefix(rm),
05c7a1cc
QY
5581 bgp_static, afi,
5582 safi);
d62a17ae 5583 }
05c7a1cc 5584 } else {
5a8ba9fc 5585 bgp_static_update(
b54892e0 5586 bgp, bgp_node_get_prefix(rn),
5a8ba9fc
DS
5587 bgp_node_get_bgp_static_info(rn), afi,
5588 safi);
ea47320b 5589 }
05c7a1cc 5590 }
6aeb9e78
DS
5591}
5592
718e3744 5593/* Called from bgp_delete(). Delete all static routes from the BGP
5594 instance. */
d62a17ae 5595void bgp_static_delete(struct bgp *bgp)
5596{
5597 afi_t afi;
5598 safi_t safi;
5599 struct bgp_node *rn;
5600 struct bgp_node *rm;
5601 struct bgp_table *table;
5602 struct bgp_static *bgp_static;
5603
05c7a1cc
QY
5604 FOREACH_AFI_SAFI (afi, safi)
5605 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5606 rn = bgp_route_next(rn)) {
67009e22 5607 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5608 continue;
ea47320b 5609
05c7a1cc
QY
5610 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5611 || (safi == SAFI_EVPN)) {
67009e22 5612 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5613
5614 for (rm = bgp_table_top(table); rm;
5615 rm = bgp_route_next(rm)) {
a78beeb5 5616 bgp_static =
5a8ba9fc
DS
5617 bgp_node_get_bgp_static_info(
5618 rm);
c7d14ba6
PG
5619 if (!bgp_static)
5620 continue;
5621
05c7a1cc 5622 bgp_static_withdraw_safi(
b54892e0
DS
5623 bgp, bgp_node_get_prefix(rm),
5624 AFI_IP, safi,
5625 (struct prefix_rd *)
5626 bgp_node_get_prefix(
5627 rn));
ea47320b 5628 bgp_static_free(bgp_static);
5a8ba9fc 5629 bgp_node_set_bgp_static_info(rn, NULL);
ea47320b 5630 bgp_unlock_node(rn);
d62a17ae 5631 }
05c7a1cc 5632 } else {
5a8ba9fc 5633 bgp_static = bgp_node_get_bgp_static_info(rn);
b54892e0
DS
5634 bgp_static_withdraw(bgp,
5635 bgp_node_get_prefix(rn),
5636 afi, safi);
05c7a1cc 5637 bgp_static_free(bgp_static);
5a8ba9fc 5638 bgp_node_set_bgp_static_info(rn, NULL);
05c7a1cc 5639 bgp_unlock_node(rn);
ea47320b 5640 }
05c7a1cc 5641 }
d62a17ae 5642}
5643
5644void bgp_static_redo_import_check(struct bgp *bgp)
5645{
5646 afi_t afi;
5647 safi_t safi;
5648 struct bgp_node *rn;
5649 struct bgp_node *rm;
5650 struct bgp_table *table;
5651 struct bgp_static *bgp_static;
5652
5653 /* Use this flag to force reprocessing of the route */
892fedb6 5654 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc
QY
5655 FOREACH_AFI_SAFI (afi, safi) {
5656 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5657 rn = bgp_route_next(rn)) {
67009e22 5658 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5659 continue;
ea47320b 5660
05c7a1cc
QY
5661 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5662 || (safi == SAFI_EVPN)) {
67009e22 5663 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5664
5665 for (rm = bgp_table_top(table); rm;
5666 rm = bgp_route_next(rm)) {
a78beeb5 5667 bgp_static =
5a8ba9fc
DS
5668 bgp_node_get_bgp_static_info(
5669 rm);
b54892e0
DS
5670 bgp_static_update_safi(bgp,
5671 bgp_node_get_prefix(rm),
05c7a1cc
QY
5672 bgp_static, afi,
5673 safi);
d62a17ae 5674 }
05c7a1cc 5675 } else {
5a8ba9fc 5676 bgp_static = bgp_node_get_bgp_static_info(rn);
b54892e0
DS
5677 bgp_static_update(bgp, bgp_node_get_prefix(rn),
5678 bgp_static, afi,
05c7a1cc 5679 safi);
ea47320b 5680 }
05c7a1cc
QY
5681 }
5682 }
892fedb6 5683 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 5684}
5685
5686static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
5687 safi_t safi)
5688{
5689 struct bgp_table *table;
5690 struct bgp_node *rn;
40381db7 5691 struct bgp_path_info *pi;
d62a17ae 5692
dfb6fd1d
NT
5693 /* Do not install the aggregate route if BGP is in the
5694 * process of termination.
5695 */
892fedb6
DA
5696 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
5697 || (bgp->peer_self == NULL))
dfb6fd1d
NT
5698 return;
5699
d62a17ae 5700 table = bgp->rib[afi][safi];
5701 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685 5702 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7
DS
5703 if (pi->peer == bgp->peer_self
5704 && ((pi->type == ZEBRA_ROUTE_BGP
5705 && pi->sub_type == BGP_ROUTE_STATIC)
5706 || (pi->type != ZEBRA_ROUTE_BGP
5707 && pi->sub_type
d62a17ae 5708 == BGP_ROUTE_REDISTRIBUTE))) {
b54892e0
DS
5709 bgp_aggregate_decrement(bgp,
5710 bgp_node_get_prefix(rn),
5711 pi, afi, safi);
40381db7
DS
5712 bgp_unlink_nexthop(pi);
5713 bgp_path_info_delete(rn, pi);
d62a17ae 5714 bgp_process(bgp, rn, afi, safi);
5715 }
5716 }
5717 }
ad4cbda1 5718}
5719
5720/*
5721 * Purge all networks and redistributed routes from routing table.
5722 * Invoked upon the instance going down.
5723 */
d62a17ae 5724void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 5725{
d62a17ae 5726 afi_t afi;
5727 safi_t safi;
ad4cbda1 5728
05c7a1cc
QY
5729 FOREACH_AFI_SAFI (afi, safi)
5730 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 5731}
5732
137446f9
LB
5733/*
5734 * gpz 110624
5735 * Currently this is used to set static routes for VPN and ENCAP.
5736 * I think it can probably be factored with bgp_static_set.
5737 */
d62a17ae 5738int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
5739 const char *ip_str, const char *rd_str,
5740 const char *label_str, const char *rmap_str,
5741 int evpn_type, const char *esi, const char *gwip,
5742 const char *ethtag, const char *routermac)
5743{
5744 VTY_DECLVAR_CONTEXT(bgp, bgp);
5745 int ret;
5746 struct prefix p;
5747 struct prefix_rd prd;
5748 struct bgp_node *prn;
5749 struct bgp_node *rn;
5750 struct bgp_table *table;
5751 struct bgp_static *bgp_static;
5752 mpls_label_t label = MPLS_INVALID_LABEL;
5753 struct prefix gw_ip;
5754
5755 /* validate ip prefix */
5756 ret = str2prefix(ip_str, &p);
5757 if (!ret) {
5758 vty_out(vty, "%% Malformed prefix\n");
5759 return CMD_WARNING_CONFIG_FAILED;
5760 }
5761 apply_mask(&p);
5762 if ((afi == AFI_L2VPN)
5763 && (bgp_build_evpn_prefix(evpn_type,
5764 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5765 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5766 return CMD_WARNING_CONFIG_FAILED;
5767 }
718e3744 5768
d62a17ae 5769 ret = str2prefix_rd(rd_str, &prd);
5770 if (!ret) {
5771 vty_out(vty, "%% Malformed rd\n");
5772 return CMD_WARNING_CONFIG_FAILED;
5773 }
718e3744 5774
d62a17ae 5775 if (label_str) {
5776 unsigned long label_val;
5777 label_val = strtoul(label_str, NULL, 10);
5778 encode_label(label_val, &label);
5779 }
9bedbb1e 5780
d62a17ae 5781 if (safi == SAFI_EVPN) {
5782 if (esi && str2esi(esi, NULL) == 0) {
5783 vty_out(vty, "%% Malformed ESI\n");
5784 return CMD_WARNING_CONFIG_FAILED;
5785 }
5786 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
5787 vty_out(vty, "%% Malformed Router MAC\n");
5788 return CMD_WARNING_CONFIG_FAILED;
5789 }
5790 if (gwip) {
5791 memset(&gw_ip, 0, sizeof(struct prefix));
5792 ret = str2prefix(gwip, &gw_ip);
5793 if (!ret) {
5794 vty_out(vty, "%% Malformed GatewayIp\n");
5795 return CMD_WARNING_CONFIG_FAILED;
5796 }
5797 if ((gw_ip.family == AF_INET
3714a385 5798 && is_evpn_prefix_ipaddr_v6(
d62a17ae 5799 (struct prefix_evpn *)&p))
5800 || (gw_ip.family == AF_INET6
3714a385 5801 && is_evpn_prefix_ipaddr_v4(
d62a17ae 5802 (struct prefix_evpn *)&p))) {
5803 vty_out(vty,
5804 "%% GatewayIp family differs with IP prefix\n");
5805 return CMD_WARNING_CONFIG_FAILED;
5806 }
5807 }
5808 }
5809 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
67009e22
DS
5810 if (!bgp_node_has_bgp_path_info_data(prn))
5811 bgp_node_set_bgp_table_info(prn,
5812 bgp_table_init(bgp, afi, safi));
67009e22 5813 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 5814
5815 rn = bgp_node_get(table, &p);
5816
67009e22 5817 if (bgp_node_has_bgp_path_info_data(rn)) {
d62a17ae 5818 vty_out(vty, "%% Same network configuration exists\n");
5819 bgp_unlock_node(rn);
5820 } else {
5821 /* New configuration. */
5822 bgp_static = bgp_static_new();
5823 bgp_static->backdoor = 0;
5824 bgp_static->valid = 0;
5825 bgp_static->igpmetric = 0;
975a328e 5826 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 5827 bgp_static->label = label;
5828 bgp_static->prd = prd;
5829
5830 if (rmap_str) {
0a22ddfb 5831 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5832 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 5833 bgp_static->rmap.name =
5834 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
5835 bgp_static->rmap.map =
5836 route_map_lookup_by_name(rmap_str);
b4897fa5 5837 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 5838 }
718e3744 5839
d62a17ae 5840 if (safi == SAFI_EVPN) {
5841 if (esi) {
5842 bgp_static->eth_s_id =
5843 XCALLOC(MTYPE_ATTR,
5844 sizeof(struct eth_segment_id));
5845 str2esi(esi, bgp_static->eth_s_id);
5846 }
5847 if (routermac) {
5848 bgp_static->router_mac =
28328ea9 5849 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
5850 (void)prefix_str2mac(routermac,
5851 bgp_static->router_mac);
d62a17ae 5852 }
5853 if (gwip)
5854 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
5855 }
5a8ba9fc 5856 bgp_node_set_bgp_static_info(rn, bgp_static);
718e3744 5857
d62a17ae 5858 bgp_static->valid = 1;
5859 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
5860 }
718e3744 5861
d62a17ae 5862 return CMD_SUCCESS;
718e3744 5863}
5864
5865/* Configure static BGP network. */
d62a17ae 5866int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
5867 const char *ip_str, const char *rd_str,
5868 const char *label_str, int evpn_type, const char *esi,
5869 const char *gwip, const char *ethtag)
5870{
5871 VTY_DECLVAR_CONTEXT(bgp, bgp);
5872 int ret;
5873 struct prefix p;
5874 struct prefix_rd prd;
5875 struct bgp_node *prn;
5876 struct bgp_node *rn;
5877 struct bgp_table *table;
5878 struct bgp_static *bgp_static;
5879 mpls_label_t label = MPLS_INVALID_LABEL;
5880
5881 /* Convert IP prefix string to struct prefix. */
5882 ret = str2prefix(ip_str, &p);
5883 if (!ret) {
5884 vty_out(vty, "%% Malformed prefix\n");
5885 return CMD_WARNING_CONFIG_FAILED;
5886 }
5887 apply_mask(&p);
5888 if ((afi == AFI_L2VPN)
5889 && (bgp_build_evpn_prefix(evpn_type,
5890 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5891 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5892 return CMD_WARNING_CONFIG_FAILED;
5893 }
5894 ret = str2prefix_rd(rd_str, &prd);
5895 if (!ret) {
5896 vty_out(vty, "%% Malformed rd\n");
5897 return CMD_WARNING_CONFIG_FAILED;
5898 }
718e3744 5899
d62a17ae 5900 if (label_str) {
5901 unsigned long label_val;
5902 label_val = strtoul(label_str, NULL, 10);
5903 encode_label(label_val, &label);
5904 }
718e3744 5905
d62a17ae 5906 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
67009e22
DS
5907 if (!bgp_node_has_bgp_path_info_data(prn))
5908 bgp_node_set_bgp_table_info(prn,
5909 bgp_table_init(bgp, afi, safi));
d62a17ae 5910 else
5911 bgp_unlock_node(prn);
67009e22 5912 table = bgp_node_get_bgp_table_info(prn);
718e3744 5913
d62a17ae 5914 rn = bgp_node_lookup(table, &p);
6b0655a2 5915
d62a17ae 5916 if (rn) {
5917 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 5918
5a8ba9fc 5919 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 5920 bgp_static_free(bgp_static);
5a8ba9fc 5921 bgp_node_set_bgp_static_info(rn, NULL);
d62a17ae 5922 bgp_unlock_node(rn);
5923 bgp_unlock_node(rn);
5924 } else
5925 vty_out(vty, "%% Can't find the route\n");
5926
5927 return CMD_SUCCESS;
5928}
5929
5930static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
5931 const char *rmap_name)
5932{
5933 VTY_DECLVAR_CONTEXT(bgp, bgp);
5934 struct bgp_rmap *rmap;
5935
5936 rmap = &bgp->table_map[afi][safi];
5937 if (rmap_name) {
0a22ddfb 5938 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5939 route_map_counter_decrement(rmap->map);
d62a17ae 5940 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
5941 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 5942 route_map_counter_increment(rmap->map);
d62a17ae 5943 } else {
0a22ddfb 5944 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5945 route_map_counter_decrement(rmap->map);
d62a17ae 5946 rmap->map = NULL;
5947 }
73ac8160 5948
d62a17ae 5949 if (bgp_fibupd_safi(safi))
5950 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5951
d62a17ae 5952 return CMD_SUCCESS;
73ac8160
DS
5953}
5954
d62a17ae 5955static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
5956 const char *rmap_name)
73ac8160 5957{
d62a17ae 5958 VTY_DECLVAR_CONTEXT(bgp, bgp);
5959 struct bgp_rmap *rmap;
73ac8160 5960
d62a17ae 5961 rmap = &bgp->table_map[afi][safi];
0a22ddfb 5962 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5963 route_map_counter_decrement(rmap->map);
d62a17ae 5964 rmap->map = NULL;
73ac8160 5965
d62a17ae 5966 if (bgp_fibupd_safi(safi))
5967 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5968
d62a17ae 5969 return CMD_SUCCESS;
73ac8160
DS
5970}
5971
2b791107 5972void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 5973 safi_t safi)
73ac8160 5974{
d62a17ae 5975 if (bgp->table_map[afi][safi].name) {
d62a17ae 5976 vty_out(vty, " table-map %s\n",
5977 bgp->table_map[afi][safi].name);
5978 }
73ac8160
DS
5979}
5980
73ac8160
DS
5981DEFUN (bgp_table_map,
5982 bgp_table_map_cmd,
5983 "table-map WORD",
5984 "BGP table to RIB route download filter\n"
5985 "Name of the route map\n")
5986{
d62a17ae 5987 int idx_word = 1;
5988 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5989 argv[idx_word]->arg);
73ac8160
DS
5990}
5991DEFUN (no_bgp_table_map,
5992 no_bgp_table_map_cmd,
5993 "no table-map WORD",
3a2d747c 5994 NO_STR
73ac8160
DS
5995 "BGP table to RIB route download filter\n"
5996 "Name of the route map\n")
5997{
d62a17ae 5998 int idx_word = 2;
5999 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6000 argv[idx_word]->arg);
73ac8160
DS
6001}
6002
e2a86ad9
DS
6003DEFPY(bgp_network,
6004 bgp_network_cmd,
6005 "[no] network \
6006 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6007 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6008 backdoor$backdoor}]",
6009 NO_STR
6010 "Specify a network to announce via BGP\n"
6011 "IPv4 prefix\n"
6012 "Network number\n"
6013 "Network mask\n"
6014 "Network mask\n"
6015 "Route-map to modify the attributes\n"
6016 "Name of the route map\n"
6017 "Label index to associate with the prefix\n"
6018 "Label index value\n"
6019 "Specify a BGP backdoor route\n")
6020{
6021 char addr_prefix_str[BUFSIZ];
6022
6023 if (address_str) {
6024 int ret;
718e3744 6025
e2a86ad9
DS
6026 ret = netmask_str2prefix_str(address_str, netmask_str,
6027 addr_prefix_str);
6028 if (!ret) {
6029 vty_out(vty, "%% Inconsistent address and mask\n");
6030 return CMD_WARNING_CONFIG_FAILED;
6031 }
d62a17ae 6032 }
718e3744 6033
a4d82a8a
PZ
6034 return bgp_static_set(
6035 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
6036 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
6037 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 6038}
6039
e2a86ad9
DS
6040DEFPY(ipv6_bgp_network,
6041 ipv6_bgp_network_cmd,
6042 "[no] network X:X::X:X/M$prefix \
6043 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6044 NO_STR
6045 "Specify a network to announce via BGP\n"
6046 "IPv6 prefix\n"
6047 "Route-map to modify the attributes\n"
6048 "Name of the route map\n"
6049 "Label index to associate with the prefix\n"
6050 "Label index value\n")
718e3744 6051{
a4d82a8a
PZ
6052 return bgp_static_set(
6053 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
6054 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
6055}
6056
d62a17ae 6057static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6058{
d62a17ae 6059 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6060}
6061
d62a17ae 6062static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6063{
20894f50
DA
6064 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6065 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6066 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6067}
718e3744 6068
3dc339cd
DA
6069static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6070 struct aspath *aspath,
6071 struct community *comm,
6072 struct ecommunity *ecomm,
6073 struct lcommunity *lcomm)
eaaf8adb
DS
6074{
6075 static struct aspath *ae = NULL;
6076
6077 if (!ae)
6078 ae = aspath_empty();
6079
40381db7 6080 if (!pi)
3dc339cd 6081 return false;
eaaf8adb 6082
40381db7 6083 if (origin != pi->attr->origin)
3dc339cd 6084 return false;
eaaf8adb 6085
40381db7 6086 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 6087 return false;
29f7d023 6088
40381db7 6089 if (!community_cmp(pi->attr->community, comm))
3dc339cd 6090 return false;
eaaf8adb 6091
3da2cc32 6092 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
3dc339cd 6093 return false;
eaaf8adb 6094
dd18c5a9 6095 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 6096 return false;
dd18c5a9 6097
40381db7 6098 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 6099 return false;
7ce8a8e0 6100
3dc339cd 6101 return true;
eaaf8adb
DS
6102}
6103
5f040085
DS
6104static void bgp_aggregate_install(
6105 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6106 uint8_t origin, struct aspath *aspath, struct community *community,
6107 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6108 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e
DS
6109{
6110 struct bgp_node *rn;
6111 struct bgp_table *table;
6f94b685 6112 struct bgp_path_info *pi, *orig, *new;
20894f50 6113 struct attr *attr;
c701010e
DS
6114
6115 table = bgp->rib[afi][safi];
6116
6117 rn = bgp_node_get(table, p);
eaaf8adb 6118
6f94b685 6119 for (orig = pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
6120 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6121 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6122 break;
6123
c701010e 6124 if (aggregate->count > 0) {
eaaf8adb
DS
6125 /*
6126 * If the aggregate information has not changed
6127 * no need to re-install it again.
6128 */
6f94b685 6129 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6130 ecommunity, lcommunity)) {
eaaf8adb
DS
6131 bgp_unlock_node(rn);
6132
6133 if (aspath)
6134 aspath_free(aspath);
6135 if (community)
3c1f53de 6136 community_free(&community);
3da2cc32
DS
6137 if (ecommunity)
6138 ecommunity_free(&ecommunity);
dd18c5a9
DS
6139 if (lcommunity)
6140 lcommunity_free(&lcommunity);
eaaf8adb
DS
6141
6142 return;
6143 }
6144
6145 /*
6146 * Mark the old as unusable
6147 */
40381db7
DS
6148 if (pi)
6149 bgp_path_info_delete(rn, pi);
eaaf8adb 6150
20894f50
DA
6151 attr = bgp_attr_aggregate_intern(
6152 bgp, origin, aspath, community, ecommunity, lcommunity,
6153 aggregate, atomic_aggregate, p);
6154
6155 if (!attr) {
6156 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
6157 return;
6158 }
6159
3da2cc32 6160 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
20894f50
DA
6161 bgp->peer_self, attr, rn);
6162
1defdda8 6163 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6164
18ee8310 6165 bgp_path_info_add(rn, new);
c701010e
DS
6166 bgp_process(bgp, rn, afi, safi);
6167 } else {
6f94b685 6168 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6169 if (pi->peer == bgp->peer_self
6170 && pi->type == ZEBRA_ROUTE_BGP
6171 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6172 break;
6173
6174 /* Withdraw static BGP route from routing table. */
40381db7
DS
6175 if (pi) {
6176 bgp_path_info_delete(rn, pi);
c701010e
DS
6177 bgp_process(bgp, rn, afi, safi);
6178 }
6179 }
6180
6181 bgp_unlock_node(rn);
6182}
6183
b5d58c32 6184/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
6185void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
6186 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 6187{
6188 struct bgp_table *table;
6189 struct bgp_node *top;
6190 struct bgp_node *rn;
d7c0a89a 6191 uint8_t origin;
d62a17ae 6192 struct aspath *aspath = NULL;
d62a17ae 6193 struct community *community = NULL;
3da2cc32 6194 struct ecommunity *ecommunity = NULL;
dd18c5a9 6195 struct lcommunity *lcommunity = NULL;
40381db7 6196 struct bgp_path_info *pi;
d62a17ae 6197 unsigned long match = 0;
d7c0a89a 6198 uint8_t atomic_aggregate = 0;
d62a17ae 6199
9f822fa2
S
6200 /* If the bgp instance is being deleted or self peer is deleted
6201 * then do not create aggregate route
6202 */
892fedb6
DA
6203 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6204 || (bgp->peer_self == NULL))
9f822fa2
S
6205 return;
6206
d62a17ae 6207 /* ORIGIN attribute: If at least one route among routes that are
6208 aggregated has ORIGIN with the value INCOMPLETE, then the
6209 aggregated route must have the ORIGIN attribute with the value
6210 INCOMPLETE. Otherwise, if at least one route among routes that
6211 are aggregated has ORIGIN with the value EGP, then the aggregated
6212 route must have the origin attribute with the value EGP. In all
6213 other case the value of the ORIGIN attribute of the aggregated
6214 route is INTERNAL. */
6215 origin = BGP_ORIGIN_IGP;
718e3744 6216
d62a17ae 6217 table = bgp->rib[afi][safi];
718e3744 6218
d62a17ae 6219 top = bgp_node_get(table, p);
6220 for (rn = bgp_node_get(table, p); rn;
c2ff8b3e 6221 rn = bgp_route_next_until(rn, top)) {
b54892e0
DS
6222 const struct prefix *rn_p = bgp_node_get_prefix(rn);
6223
6224 if (rn_p->prefixlen <= p->prefixlen)
c2ff8b3e 6225 continue;
d62a17ae 6226
c2ff8b3e 6227 match = 0;
d62a17ae 6228
6f94b685 6229 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 6230 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 6231 continue;
718e3744 6232
40381db7 6233 if (pi->attr->flag
c2ff8b3e
DS
6234 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
6235 atomic_aggregate = 1;
d62a17ae 6236
40381db7 6237 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 6238 continue;
d62a17ae 6239
f273fef1
DS
6240 /*
6241 * summary-only aggregate route suppress
6242 * aggregated route announcements.
6243 */
c2ff8b3e 6244 if (aggregate->summary_only) {
40381db7
DS
6245 (bgp_path_info_extra_get(pi))->suppress++;
6246 bgp_path_info_set_flag(rn, pi,
18ee8310 6247 BGP_PATH_ATTR_CHANGED);
c2ff8b3e 6248 match++;
d62a17ae 6249 }
c2ff8b3e
DS
6250
6251 aggregate->count++;
6252
f273fef1
DS
6253 /*
6254 * If at least one route among routes that are
6255 * aggregated has ORIGIN with the value INCOMPLETE,
6256 * then the aggregated route MUST have the ORIGIN
6257 * attribute with the value INCOMPLETE. Otherwise, if
6258 * at least one route among routes that are aggregated
6259 * has ORIGIN with the value EGP, then the aggregated
6260 * route MUST have the ORIGIN attribute with the value
6261 * EGP.
6262 */
fc968841
NT
6263 switch (pi->attr->origin) {
6264 case BGP_ORIGIN_INCOMPLETE:
6265 aggregate->incomplete_origin_count++;
6266 break;
6267 case BGP_ORIGIN_EGP:
6268 aggregate->egp_origin_count++;
6269 break;
6270 default:
6271 /*Do nothing.
6272 */
6273 break;
6274 }
c2ff8b3e
DS
6275
6276 if (!aggregate->as_set)
6277 continue;
6278
f273fef1
DS
6279 /*
6280 * as-set aggregate route generate origin, as path,
6281 * and community aggregation.
6282 */
fc968841
NT
6283 /* Compute aggregate route's as-path.
6284 */
ef51a7d8 6285 bgp_compute_aggregate_aspath_hash(aggregate,
6286 pi->attr->aspath);
c2ff8b3e 6287
fc968841
NT
6288 /* Compute aggregate route's community.
6289 */
6290 if (pi->attr->community)
21fec674 6291 bgp_compute_aggregate_community_hash(
fc968841
NT
6292 aggregate,
6293 pi->attr->community);
dd18c5a9 6294
fc968841
NT
6295 /* Compute aggregate route's extended community.
6296 */
6297 if (pi->attr->ecommunity)
4edd83f9 6298 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
6299 aggregate,
6300 pi->attr->ecommunity);
6301
6302 /* Compute aggregate route's large community.
6303 */
6304 if (pi->attr->lcommunity)
f1eb1f05 6305 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
6306 aggregate,
6307 pi->attr->lcommunity);
d62a17ae 6308 }
c2ff8b3e
DS
6309 if (match)
6310 bgp_process(bgp, rn, afi, safi);
6311 }
21fec674 6312 if (aggregate->as_set) {
ef51a7d8 6313 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 6314 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 6315 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 6316 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 6317 }
6318
f1eb1f05 6319
d62a17ae 6320 bgp_unlock_node(top);
718e3744 6321
718e3744 6322
fc968841
NT
6323 if (aggregate->incomplete_origin_count > 0)
6324 origin = BGP_ORIGIN_INCOMPLETE;
6325 else if (aggregate->egp_origin_count > 0)
6326 origin = BGP_ORIGIN_EGP;
d62a17ae 6327
229757f1
DA
6328 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6329 origin = aggregate->origin;
6330
fc968841
NT
6331 if (aggregate->as_set) {
6332 if (aggregate->aspath)
6333 /* Retrieve aggregate route's as-path.
6334 */
6335 aspath = aspath_dup(aggregate->aspath);
d62a17ae 6336
fc968841
NT
6337 if (aggregate->community)
6338 /* Retrieve aggregate route's community.
6339 */
6340 community = community_dup(aggregate->community);
3da2cc32 6341
fc968841
NT
6342 if (aggregate->ecommunity)
6343 /* Retrieve aggregate route's ecommunity.
6344 */
6345 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 6346
fc968841
NT
6347 if (aggregate->lcommunity)
6348 /* Retrieve aggregate route's lcommunity.
6349 */
6350 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 6351 }
718e3744 6352
c701010e 6353 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
6354 ecommunity, lcommunity, atomic_aggregate,
6355 aggregate);
718e3744 6356}
6357
5f040085
DS
6358void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
6359 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
6360{
6361 struct bgp_table *table;
6362 struct bgp_node *top;
6363 struct bgp_node *rn;
40381db7 6364 struct bgp_path_info *pi;
3b7db173
DS
6365 unsigned long match;
6366
6367 table = bgp->rib[afi][safi];
6368
6369 /* If routes exists below this node, generate aggregate routes. */
6370 top = bgp_node_get(table, p);
6371 for (rn = bgp_node_get(table, p); rn;
6372 rn = bgp_route_next_until(rn, top)) {
b54892e0
DS
6373 const struct prefix *rn_p = bgp_node_get_prefix(rn);
6374
6375 if (rn_p->prefixlen <= p->prefixlen)
3b7db173
DS
6376 continue;
6377 match = 0;
6378
6f94b685 6379 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 6380 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
6381 continue;
6382
40381db7 6383 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
6384 continue;
6385
40381db7
DS
6386 if (aggregate->summary_only && pi->extra) {
6387 pi->extra->suppress--;
3b7db173 6388
40381db7 6389 if (pi->extra->suppress == 0) {
18ee8310 6390 bgp_path_info_set_flag(
40381db7 6391 rn, pi, BGP_PATH_ATTR_CHANGED);
3b7db173
DS
6392 match++;
6393 }
6394 }
6395 aggregate->count--;
fc968841
NT
6396
6397 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6398 aggregate->incomplete_origin_count--;
6399 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6400 aggregate->egp_origin_count--;
6401
6402 if (aggregate->as_set) {
6403 /* Remove as-path from aggregate.
6404 */
ef51a7d8 6405 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
6406 aggregate,
6407 pi->attr->aspath);
6408
6409 if (pi->attr->community)
6410 /* Remove community from aggregate.
6411 */
21fec674 6412 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
6413 aggregate,
6414 pi->attr->community);
6415
6416 if (pi->attr->ecommunity)
6417 /* Remove ecommunity from aggregate.
6418 */
4edd83f9 6419 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
6420 aggregate,
6421 pi->attr->ecommunity);
6422
6423 if (pi->attr->lcommunity)
6424 /* Remove lcommunity from aggregate.
6425 */
f1eb1f05 6426 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
6427 aggregate,
6428 pi->attr->lcommunity);
6429 }
6430
3b7db173
DS
6431 }
6432
6433 /* If this node was suppressed, process the change. */
6434 if (match)
6435 bgp_process(bgp, rn, afi, safi);
6436 }
f1eb1f05 6437 if (aggregate->as_set) {
ef51a7d8 6438 aspath_free(aggregate->aspath);
6439 aggregate->aspath = NULL;
21fec674 6440 if (aggregate->community)
6441 community_free(&aggregate->community);
4edd83f9 6442 if (aggregate->ecommunity)
6443 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 6444 if (aggregate->lcommunity)
6445 lcommunity_free(&aggregate->lcommunity);
6446 }
6447
3b7db173
DS
6448 bgp_unlock_node(top);
6449}
718e3744 6450
5f040085
DS
6451static void bgp_add_route_to_aggregate(struct bgp *bgp,
6452 const struct prefix *aggr_p,
fc968841
NT
6453 struct bgp_path_info *pinew, afi_t afi,
6454 safi_t safi,
6455 struct bgp_aggregate *aggregate)
6456{
6457 uint8_t origin;
6458 struct aspath *aspath = NULL;
6459 uint8_t atomic_aggregate = 0;
6460 struct community *community = NULL;
6461 struct ecommunity *ecommunity = NULL;
6462 struct lcommunity *lcommunity = NULL;
6463
6464 /* ORIGIN attribute: If at least one route among routes that are
6465 * aggregated has ORIGIN with the value INCOMPLETE, then the
6466 * aggregated route must have the ORIGIN attribute with the value
6467 * INCOMPLETE. Otherwise, if at least one route among routes that
6468 * are aggregated has ORIGIN with the value EGP, then the aggregated
6469 * route must have the origin attribute with the value EGP. In all
6470 * other case the value of the ORIGIN attribute of the aggregated
6471 * route is INTERNAL.
6472 */
6473 origin = BGP_ORIGIN_IGP;
6474
6475 aggregate->count++;
6476
6477 if (aggregate->summary_only)
6478 (bgp_path_info_extra_get(pinew))->suppress++;
6479
6480 switch (pinew->attr->origin) {
6481 case BGP_ORIGIN_INCOMPLETE:
6482 aggregate->incomplete_origin_count++;
6483 break;
6484 case BGP_ORIGIN_EGP:
6485 aggregate->egp_origin_count++;
6486 break;
6487 default:
6488 /* Do nothing.
6489 */
6490 break;
6491 }
6492
6493 if (aggregate->incomplete_origin_count > 0)
6494 origin = BGP_ORIGIN_INCOMPLETE;
6495 else if (aggregate->egp_origin_count > 0)
6496 origin = BGP_ORIGIN_EGP;
6497
229757f1
DA
6498 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6499 origin = aggregate->origin;
6500
fc968841
NT
6501 if (aggregate->as_set) {
6502 /* Compute aggregate route's as-path.
6503 */
6504 bgp_compute_aggregate_aspath(aggregate,
6505 pinew->attr->aspath);
6506
6507 /* Compute aggregate route's community.
6508 */
6509 if (pinew->attr->community)
6510 bgp_compute_aggregate_community(
6511 aggregate,
6512 pinew->attr->community);
6513
6514 /* Compute aggregate route's extended community.
6515 */
6516 if (pinew->attr->ecommunity)
6517 bgp_compute_aggregate_ecommunity(
6518 aggregate,
6519 pinew->attr->ecommunity);
6520
6521 /* Compute aggregate route's large community.
6522 */
6523 if (pinew->attr->lcommunity)
6524 bgp_compute_aggregate_lcommunity(
6525 aggregate,
6526 pinew->attr->lcommunity);
6527
6528 /* Retrieve aggregate route's as-path.
6529 */
6530 if (aggregate->aspath)
6531 aspath = aspath_dup(aggregate->aspath);
6532
6533 /* Retrieve aggregate route's community.
6534 */
6535 if (aggregate->community)
6536 community = community_dup(aggregate->community);
6537
6538 /* Retrieve aggregate route's ecommunity.
6539 */
6540 if (aggregate->ecommunity)
6541 ecommunity = ecommunity_dup(aggregate->ecommunity);
6542
6543 /* Retrieve aggregate route's lcommunity.
6544 */
6545 if (aggregate->lcommunity)
6546 lcommunity = lcommunity_dup(aggregate->lcommunity);
6547 }
6548
6549 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6550 aspath, community, ecommunity,
6551 lcommunity, atomic_aggregate, aggregate);
6552}
6553
6554static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
6555 safi_t safi,
6556 struct bgp_path_info *pi,
6557 struct bgp_aggregate *aggregate,
5f040085 6558 const struct prefix *aggr_p)
fc968841
NT
6559{
6560 uint8_t origin;
6561 struct aspath *aspath = NULL;
6562 uint8_t atomic_aggregate = 0;
6563 struct community *community = NULL;
6564 struct ecommunity *ecommunity = NULL;
6565 struct lcommunity *lcommunity = NULL;
6566 unsigned long match = 0;
6567
6568 if (BGP_PATH_HOLDDOWN(pi))
6569 return;
6570
6571 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6572 return;
6573
6574 if (aggregate->summary_only
6575 && pi->extra
6576 && pi->extra->suppress > 0) {
6577 pi->extra->suppress--;
6578
6579 if (pi->extra->suppress == 0) {
6580 bgp_path_info_set_flag(pi->net, pi,
6581 BGP_PATH_ATTR_CHANGED);
6582 match++;
6583 }
6584 }
6585
6586 if (aggregate->count > 0)
6587 aggregate->count--;
6588
6589 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6590 aggregate->incomplete_origin_count--;
6591 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6592 aggregate->egp_origin_count--;
6593
6594 if (aggregate->as_set) {
6595 /* Remove as-path from aggregate.
6596 */
6597 bgp_remove_aspath_from_aggregate(aggregate,
6598 pi->attr->aspath);
6599
6600 if (pi->attr->community)
6601 /* Remove community from aggregate.
6602 */
6603 bgp_remove_community_from_aggregate(
6604 aggregate,
6605 pi->attr->community);
6606
6607 if (pi->attr->ecommunity)
6608 /* Remove ecommunity from aggregate.
6609 */
6610 bgp_remove_ecommunity_from_aggregate(
6611 aggregate,
6612 pi->attr->ecommunity);
6613
6614 if (pi->attr->lcommunity)
6615 /* Remove lcommunity from aggregate.
6616 */
6617 bgp_remove_lcommunity_from_aggregate(
6618 aggregate,
6619 pi->attr->lcommunity);
6620 }
6621
6622 /* If this node was suppressed, process the change. */
6623 if (match)
6624 bgp_process(bgp, pi->net, afi, safi);
6625
6626 origin = BGP_ORIGIN_IGP;
6627 if (aggregate->incomplete_origin_count > 0)
6628 origin = BGP_ORIGIN_INCOMPLETE;
6629 else if (aggregate->egp_origin_count > 0)
6630 origin = BGP_ORIGIN_EGP;
6631
229757f1
DA
6632 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6633 origin = aggregate->origin;
6634
fc968841
NT
6635 if (aggregate->as_set) {
6636 /* Retrieve aggregate route's as-path.
6637 */
6638 if (aggregate->aspath)
6639 aspath = aspath_dup(aggregate->aspath);
6640
6641 /* Retrieve aggregate route's community.
6642 */
6643 if (aggregate->community)
6644 community = community_dup(aggregate->community);
6645
6646 /* Retrieve aggregate route's ecommunity.
6647 */
6648 if (aggregate->ecommunity)
6649 ecommunity = ecommunity_dup(aggregate->ecommunity);
6650
6651 /* Retrieve aggregate route's lcommunity.
6652 */
6653 if (aggregate->lcommunity)
6654 lcommunity = lcommunity_dup(aggregate->lcommunity);
6655 }
6656
6657 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6658 aspath, community, ecommunity,
6659 lcommunity, atomic_aggregate, aggregate);
6660}
6661
5a1ae2c2 6662void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 6663 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 6664{
d62a17ae 6665 struct bgp_node *child;
6666 struct bgp_node *rn;
6667 struct bgp_aggregate *aggregate;
6668 struct bgp_table *table;
718e3744 6669
d62a17ae 6670 table = bgp->aggregate[afi][safi];
f018db83 6671
d62a17ae 6672 /* No aggregates configured. */
6673 if (bgp_table_top_nolock(table) == NULL)
6674 return;
f018db83 6675
d62a17ae 6676 if (p->prefixlen == 0)
6677 return;
718e3744 6678
40381db7 6679 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 6680 return;
718e3744 6681
d62a17ae 6682 child = bgp_node_get(table, p);
718e3744 6683
d62a17ae 6684 /* Aggregate address configuration check. */
b1e62edd 6685 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
b54892e0
DS
6686 const struct prefix *rn_p = bgp_node_get_prefix(rn);
6687
b613a918 6688 aggregate = bgp_node_get_bgp_aggregate_info(rn);
b54892e0
DS
6689 if (aggregate != NULL && rn_p->prefixlen < p->prefixlen) {
6690 bgp_add_route_to_aggregate(bgp, rn_p, pi, afi, safi,
6691 aggregate);
d62a17ae 6692 }
b1e62edd 6693 }
d62a17ae 6694 bgp_unlock_node(child);
718e3744 6695}
6696
5a1ae2c2 6697void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 6698 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 6699{
d62a17ae 6700 struct bgp_node *child;
6701 struct bgp_node *rn;
6702 struct bgp_aggregate *aggregate;
6703 struct bgp_table *table;
718e3744 6704
d62a17ae 6705 table = bgp->aggregate[afi][safi];
718e3744 6706
d62a17ae 6707 /* No aggregates configured. */
6708 if (bgp_table_top_nolock(table) == NULL)
6709 return;
718e3744 6710
d62a17ae 6711 if (p->prefixlen == 0)
6712 return;
718e3744 6713
d62a17ae 6714 child = bgp_node_get(table, p);
718e3744 6715
d62a17ae 6716 /* Aggregate address configuration check. */
b1e62edd 6717 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
b54892e0
DS
6718 const struct prefix *rn_p = bgp_node_get_prefix(rn);
6719
b613a918 6720 aggregate = bgp_node_get_bgp_aggregate_info(rn);
b54892e0
DS
6721 if (aggregate != NULL && rn_p->prefixlen < p->prefixlen) {
6722 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
6723 aggregate, rn_p);
d62a17ae 6724 }
b1e62edd 6725 }
d62a17ae 6726 bgp_unlock_node(child);
6727}
718e3744 6728
718e3744 6729/* Aggregate route attribute. */
6730#define AGGREGATE_SUMMARY_ONLY 1
6731#define AGGREGATE_AS_SET 1
fb29348a 6732#define AGGREGATE_AS_UNSET 0
718e3744 6733
229757f1
DA
6734static const char *bgp_origin2str(uint8_t origin)
6735{
6736 switch (origin) {
6737 case BGP_ORIGIN_IGP:
6738 return "igp";
6739 case BGP_ORIGIN_EGP:
6740 return "egp";
6741 case BGP_ORIGIN_INCOMPLETE:
6742 return "incomplete";
6743 }
6744 return "n/a";
6745}
6746
d62a17ae 6747static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
6748 afi_t afi, safi_t safi)
718e3744 6749{
d62a17ae 6750 VTY_DECLVAR_CONTEXT(bgp, bgp);
6751 int ret;
6752 struct prefix p;
6753 struct bgp_node *rn;
6754 struct bgp_aggregate *aggregate;
718e3744 6755
d62a17ae 6756 /* Convert string to prefix structure. */
6757 ret = str2prefix(prefix_str, &p);
6758 if (!ret) {
6759 vty_out(vty, "Malformed prefix\n");
6760 return CMD_WARNING_CONFIG_FAILED;
6761 }
6762 apply_mask(&p);
6763
6764 /* Old configuration check. */
6765 rn = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
6766 if (!rn) {
6767 vty_out(vty,
6768 "%% There is no aggregate-address configuration.\n");
6769 return CMD_WARNING_CONFIG_FAILED;
6770 }
f6269b4f 6771
b613a918 6772 aggregate = bgp_node_get_bgp_aggregate_info(rn);
09990cdd 6773 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
dd18c5a9
DS
6774 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
6775 NULL, NULL, 0, aggregate);
d62a17ae 6776
6777 /* Unlock aggregate address configuration. */
b613a918 6778 bgp_node_set_bgp_aggregate_info(rn, NULL);
fc968841
NT
6779
6780 if (aggregate->community)
6781 community_free(&aggregate->community);
6782
6783 if (aggregate->community_hash) {
6784 /* Delete all communities in the hash.
6785 */
6786 hash_clean(aggregate->community_hash,
6787 bgp_aggr_community_remove);
6788 /* Free up the community_hash.
6789 */
6790 hash_free(aggregate->community_hash);
6791 }
6792
6793 if (aggregate->ecommunity)
6794 ecommunity_free(&aggregate->ecommunity);
6795
6796 if (aggregate->ecommunity_hash) {
6797 /* Delete all ecommunities in the hash.
6798 */
6799 hash_clean(aggregate->ecommunity_hash,
6800 bgp_aggr_ecommunity_remove);
6801 /* Free up the ecommunity_hash.
6802 */
6803 hash_free(aggregate->ecommunity_hash);
6804 }
6805
6806 if (aggregate->lcommunity)
6807 lcommunity_free(&aggregate->lcommunity);
6808
6809 if (aggregate->lcommunity_hash) {
6810 /* Delete all lcommunities in the hash.
6811 */
6812 hash_clean(aggregate->lcommunity_hash,
6813 bgp_aggr_lcommunity_remove);
6814 /* Free up the lcommunity_hash.
6815 */
6816 hash_free(aggregate->lcommunity_hash);
6817 }
6818
6819 if (aggregate->aspath)
6820 aspath_free(aggregate->aspath);
6821
6822 if (aggregate->aspath_hash) {
6823 /* Delete all as-paths in the hash.
6824 */
6825 hash_clean(aggregate->aspath_hash,
6826 bgp_aggr_aspath_remove);
6827 /* Free up the aspath_hash.
6828 */
6829 hash_free(aggregate->aspath_hash);
6830 }
6831
d62a17ae 6832 bgp_aggregate_free(aggregate);
6833 bgp_unlock_node(rn);
6834 bgp_unlock_node(rn);
6835
6836 return CMD_SUCCESS;
6837}
6838
6839static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
229757f1
DA
6840 safi_t safi, const char *rmap,
6841 uint8_t summary_only, uint8_t as_set,
6842 uint8_t origin)
d62a17ae 6843{
6844 VTY_DECLVAR_CONTEXT(bgp, bgp);
6845 int ret;
6846 struct prefix p;
6847 struct bgp_node *rn;
6848 struct bgp_aggregate *aggregate;
fb29348a 6849 uint8_t as_set_new = as_set;
d62a17ae 6850
6851 /* Convert string to prefix structure. */
6852 ret = str2prefix(prefix_str, &p);
6853 if (!ret) {
6854 vty_out(vty, "Malformed prefix\n");
6855 return CMD_WARNING_CONFIG_FAILED;
6856 }
6857 apply_mask(&p);
6858
3624ac81
DS
6859 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
6860 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
6861 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6862 prefix_str);
6863 return CMD_WARNING_CONFIG_FAILED;
6864 }
6865
d62a17ae 6866 /* Old configuration check. */
6867 rn = bgp_node_get(bgp->aggregate[afi][safi], &p);
20894f50 6868 aggregate = bgp_node_get_bgp_aggregate_info(rn);
d62a17ae 6869
20894f50 6870 if (aggregate) {
d62a17ae 6871 vty_out(vty, "There is already same aggregate network.\n");
6872 /* try to remove the old entry */
6873 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
6874 if (ret) {
6875 vty_out(vty, "Error deleting aggregate.\n");
6876 bgp_unlock_node(rn);
6877 return CMD_WARNING_CONFIG_FAILED;
6878 }
6879 }
718e3744 6880
d62a17ae 6881 /* Make aggregate address structure. */
6882 aggregate = bgp_aggregate_new();
6883 aggregate->summary_only = summary_only;
fb29348a
DA
6884
6885 /* Network operators MUST NOT locally generate any new
6886 * announcements containing AS_SET or AS_CONFED_SET. If they have
6887 * announced routes with AS_SET or AS_CONFED_SET in them, then they
6888 * SHOULD withdraw those routes and re-announce routes for the
6889 * aggregate or component prefixes (i.e., the more-specific routes
6890 * subsumed by the previously aggregated route) without AS_SET
6891 * or AS_CONFED_SET in the updates.
6892 */
6893 if (bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED) {
6894 if (as_set == AGGREGATE_AS_SET) {
6895 as_set_new = AGGREGATE_AS_UNSET;
6896 zlog_warn(
63efca0e 6897 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a
DA
6898 __func__);
6899 vty_out(vty,
6900 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
6901 }
6902 }
6903
6904 aggregate->as_set = as_set_new;
d62a17ae 6905 aggregate->safi = safi;
229757f1
DA
6906 /* Override ORIGIN attribute if defined.
6907 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
6908 * to IGP which is not what rfc4271 says.
6909 * This enables the same behavior, optionally.
6910 */
6911 aggregate->origin = origin;
20894f50
DA
6912
6913 if (rmap) {
6914 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6915 route_map_counter_decrement(aggregate->rmap.map);
6916 aggregate->rmap.name =
6917 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6918 aggregate->rmap.map = route_map_lookup_by_name(rmap);
6919 route_map_counter_increment(aggregate->rmap.map);
6920 }
b613a918 6921 bgp_node_set_bgp_aggregate_info(rn, aggregate);
718e3744 6922
d62a17ae 6923 /* Aggregate address insert into BGP routing table. */
fc968841 6924 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 6925
d62a17ae 6926 return CMD_SUCCESS;
718e3744 6927}
6928
6929DEFUN (aggregate_address,
6930 aggregate_address_cmd,
229757f1 6931 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 6932 "Configure BGP aggregate entries\n"
6933 "Aggregate prefix\n"
6934 "Generate AS set path information\n"
a636c635
DW
6935 "Filter more specific routes from updates\n"
6936 "Filter more specific routes from updates\n"
20894f50
DA
6937 "Generate AS set path information\n"
6938 "Apply route map to aggregate network\n"
229757f1
DA
6939 "Name of route map\n"
6940 "BGP origin code\n"
6941 "Remote EGP\n"
6942 "Local IGP\n"
6943 "Unknown heritage\n")
718e3744 6944{
d62a17ae 6945 int idx = 0;
6946 argv_find(argv, argc, "A.B.C.D/M", &idx);
6947 char *prefix = argv[idx]->arg;
20894f50 6948 char *rmap = NULL;
229757f1 6949 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
fb29348a
DA
6950 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
6951 : AGGREGATE_AS_UNSET;
d62a17ae 6952 idx = 0;
6953 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6954 ? AGGREGATE_SUMMARY_ONLY
6955 : 0;
e3e6107d 6956
20894f50
DA
6957 idx = 0;
6958 argv_find(argv, argc, "WORD", &idx);
6959 if (idx)
6960 rmap = argv[idx]->arg;
6961
229757f1
DA
6962 idx = 0;
6963 if (argv_find(argv, argc, "origin", &idx)) {
6964 if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
6965 origin = BGP_ORIGIN_IGP;
6966 if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
6967 origin = BGP_ORIGIN_EGP;
6968 if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
6969 origin = BGP_ORIGIN_INCOMPLETE;
6970 }
6971
6972 return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty), rmap,
6973 summary_only, as_set, origin);
718e3744 6974}
6975
e3e6107d
QY
6976DEFUN (aggregate_address_mask,
6977 aggregate_address_mask_cmd,
229757f1 6978 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 6979 "Configure BGP aggregate entries\n"
6980 "Aggregate address\n"
6981 "Aggregate mask\n"
6982 "Generate AS set path information\n"
a636c635
DW
6983 "Filter more specific routes from updates\n"
6984 "Filter more specific routes from updates\n"
20894f50
DA
6985 "Generate AS set path information\n"
6986 "Apply route map to aggregate network\n"
229757f1
DA
6987 "Name of route map\n"
6988 "BGP origin code\n"
6989 "Remote EGP\n"
6990 "Local IGP\n"
6991 "Unknown heritage\n")
718e3744 6992{
d62a17ae 6993 int idx = 0;
6994 argv_find(argv, argc, "A.B.C.D", &idx);
6995 char *prefix = argv[idx]->arg;
6996 char *mask = argv[idx + 1]->arg;
cf40d052 6997 bool rmap_found;
20894f50 6998 char *rmap = NULL;
229757f1 6999 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
fb29348a
DA
7000 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
7001 : AGGREGATE_AS_UNSET;
d62a17ae 7002 idx = 0;
7003 int summary_only = argv_find(argv, argc, "summary-only", &idx)
7004 ? AGGREGATE_SUMMARY_ONLY
7005 : 0;
7006
cf40d052
DS
7007 rmap_found = argv_find(argv, argc, "WORD", &idx);
7008 if (rmap_found)
20894f50
DA
7009 rmap = argv[idx]->arg;
7010
d62a17ae 7011 char prefix_str[BUFSIZ];
7012 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
7013
7014 if (!ret) {
7015 vty_out(vty, "%% Inconsistent address and mask\n");
7016 return CMD_WARNING_CONFIG_FAILED;
7017 }
718e3744 7018
229757f1
DA
7019 idx = 0;
7020 if (argv_find(argv, argc, "origin", &idx)) {
7021 if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
7022 origin = BGP_ORIGIN_IGP;
7023 if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
7024 origin = BGP_ORIGIN_EGP;
7025 if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
7026 origin = BGP_ORIGIN_INCOMPLETE;
7027 }
7028
d62a17ae 7029 return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
229757f1 7030 rmap, summary_only, as_set, origin);
718e3744 7031}
7032
718e3744 7033DEFUN (no_aggregate_address,
7034 no_aggregate_address_cmd,
229757f1 7035 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 7036 NO_STR
7037 "Configure BGP aggregate entries\n"
a636c635
DW
7038 "Aggregate prefix\n"
7039 "Generate AS set path information\n"
e3e6107d
QY
7040 "Filter more specific routes from updates\n"
7041 "Filter more specific routes from updates\n"
b84da0db
DA
7042 "Generate AS set path information\n"
7043 "Apply route map to aggregate network\n"
229757f1
DA
7044 "Name of route map\n"
7045 "BGP origin code\n"
7046 "Remote EGP\n"
7047 "Local IGP\n"
7048 "Unknown heritage\n")
718e3744 7049{
d62a17ae 7050 int idx = 0;
7051 argv_find(argv, argc, "A.B.C.D/M", &idx);
7052 char *prefix = argv[idx]->arg;
7053 return bgp_aggregate_unset(vty, prefix, AFI_IP, bgp_node_safi(vty));
718e3744 7054}
7055
718e3744 7056DEFUN (no_aggregate_address_mask,
7057 no_aggregate_address_mask_cmd,
229757f1 7058 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 7059 NO_STR
7060 "Configure BGP aggregate entries\n"
7061 "Aggregate address\n"
a636c635
DW
7062 "Aggregate mask\n"
7063 "Generate AS set path information\n"
e3e6107d
QY
7064 "Filter more specific routes from updates\n"
7065 "Filter more specific routes from updates\n"
b84da0db
DA
7066 "Generate AS set path information\n"
7067 "Apply route map to aggregate network\n"
229757f1
DA
7068 "Name of route map\n"
7069 "BGP origin code\n"
7070 "Remote EGP\n"
7071 "Local IGP\n"
7072 "Unknown heritage\n")
718e3744 7073{
d62a17ae 7074 int idx = 0;
7075 argv_find(argv, argc, "A.B.C.D", &idx);
7076 char *prefix = argv[idx]->arg;
7077 char *mask = argv[idx + 1]->arg;
718e3744 7078
d62a17ae 7079 char prefix_str[BUFSIZ];
7080 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
718e3744 7081
d62a17ae 7082 if (!ret) {
7083 vty_out(vty, "%% Inconsistent address and mask\n");
7084 return CMD_WARNING_CONFIG_FAILED;
7085 }
718e3744 7086
d62a17ae 7087 return bgp_aggregate_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
718e3744 7088}
7089
718e3744 7090DEFUN (ipv6_aggregate_address,
7091 ipv6_aggregate_address_cmd,
229757f1 7092 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 7093 "Configure BGP aggregate entries\n"
7094 "Aggregate prefix\n"
5101fece 7095 "Generate AS set path information\n"
7096 "Filter more specific routes from updates\n"
7097 "Filter more specific routes from updates\n"
20894f50
DA
7098 "Generate AS set path information\n"
7099 "Apply route map to aggregate network\n"
229757f1
DA
7100 "Name of route map\n"
7101 "BGP origin code\n"
7102 "Remote EGP\n"
7103 "Local IGP\n"
7104 "Unknown heritage\n")
718e3744 7105{
d62a17ae 7106 int idx = 0;
7107 argv_find(argv, argc, "X:X::X:X/M", &idx);
7108 char *prefix = argv[idx]->arg;
20894f50 7109 char *rmap = NULL;
273fae13 7110 bool rmap_found;
229757f1 7111 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
fb29348a
DA
7112 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
7113 : AGGREGATE_AS_UNSET;
5101fece 7114
7115 idx = 0;
d62a17ae 7116 int sum_only = argv_find(argv, argc, "summary-only", &idx)
7117 ? AGGREGATE_SUMMARY_ONLY
7118 : 0;
20894f50 7119
273fae13
DA
7120 rmap_found = argv_find(argv, argc, "WORD", &idx);
7121 if (rmap_found)
20894f50
DA
7122 rmap = argv[idx]->arg;
7123
229757f1
DA
7124 idx = 0;
7125 if (argv_find(argv, argc, "origin", &idx)) {
7126 if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
7127 origin = BGP_ORIGIN_IGP;
7128 if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
7129 origin = BGP_ORIGIN_EGP;
7130 if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
7131 origin = BGP_ORIGIN_INCOMPLETE;
7132 }
7133
20894f50 7134 return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, rmap,
229757f1 7135 sum_only, as_set, origin);
718e3744 7136}
7137
7138DEFUN (no_ipv6_aggregate_address,
7139 no_ipv6_aggregate_address_cmd,
229757f1 7140 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 7141 NO_STR
7142 "Configure BGP aggregate entries\n"
16cedbb0 7143 "Aggregate prefix\n"
5101fece 7144 "Generate AS set path information\n"
7145 "Filter more specific routes from updates\n"
7146 "Filter more specific routes from updates\n"
b84da0db
DA
7147 "Generate AS set path information\n"
7148 "Apply route map to aggregate network\n"
229757f1
DA
7149 "Name of route map\n"
7150 "BGP origin code\n"
7151 "Remote EGP\n"
7152 "Local IGP\n"
7153 "Unknown heritage\n")
718e3744 7154{
d62a17ae 7155 int idx = 0;
7156 argv_find(argv, argc, "X:X::X:X/M", &idx);
7157 char *prefix = argv[idx]->arg;
7158 return bgp_aggregate_unset(vty, prefix, AFI_IP6, SAFI_UNICAST);
718e3744 7159}
7160
718e3744 7161/* Redistribute route treatment. */
d62a17ae 7162void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
7163 const union g_addr *nexthop, ifindex_t ifindex,
7164 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
7165 uint8_t type, unsigned short instance,
7166 route_tag_t tag)
d62a17ae 7167{
4b7e6066 7168 struct bgp_path_info *new;
40381db7
DS
7169 struct bgp_path_info *bpi;
7170 struct bgp_path_info rmap_path;
d62a17ae 7171 struct bgp_node *bn;
7172 struct attr attr;
7173 struct attr *new_attr;
7174 afi_t afi;
b68885f9 7175 route_map_result_t ret;
d62a17ae 7176 struct bgp_redist *red;
7177
7178 /* Make default attribute. */
7179 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
7180 /*
7181 * This must not be NULL to satisfy Coverity SA
7182 */
7183 assert(attr.aspath);
9de1f7ff 7184
a4d82a8a 7185 switch (nhtype) {
9de1f7ff
DS
7186 case NEXTHOP_TYPE_IFINDEX:
7187 break;
7188 case NEXTHOP_TYPE_IPV4:
7189 case NEXTHOP_TYPE_IPV4_IFINDEX:
7190 attr.nexthop = nexthop->ipv4;
7191 break;
7192 case NEXTHOP_TYPE_IPV6:
7193 case NEXTHOP_TYPE_IPV6_IFINDEX:
7194 attr.mp_nexthop_global = nexthop->ipv6;
7195 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
7196 break;
7197 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
7198 switch (p->family) {
7199 case AF_INET:
9de1f7ff 7200 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
7201 break;
7202 case AF_INET6:
9de1f7ff
DS
7203 memset(&attr.mp_nexthop_global, 0,
7204 sizeof(attr.mp_nexthop_global));
74489921 7205 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 7206 break;
74489921 7207 }
9de1f7ff 7208 break;
d62a17ae 7209 }
74489921 7210 attr.nh_ifindex = ifindex;
f04a80a5 7211
d62a17ae 7212 attr.med = metric;
7213 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
7214 attr.tag = tag;
718e3744 7215
d62a17ae 7216 afi = family2afi(p->family);
6aeb9e78 7217
d62a17ae 7218 red = bgp_redist_lookup(bgp, afi, type, instance);
7219 if (red) {
7220 struct attr attr_new;
718e3744 7221
d62a17ae 7222 /* Copy attribute for modification. */
6f4f49b2 7223 attr_new = attr;
718e3744 7224
d62a17ae 7225 if (red->redist_metric_flag)
7226 attr_new.med = red->redist_metric;
718e3744 7227
d62a17ae 7228 /* Apply route-map. */
7229 if (red->rmap.name) {
40381db7
DS
7230 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
7231 rmap_path.peer = bgp->peer_self;
7232 rmap_path.attr = &attr_new;
718e3744 7233
d62a17ae 7234 SET_FLAG(bgp->peer_self->rmap_type,
7235 PEER_RMAP_TYPE_REDISTRIBUTE);
7236
7237 ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
40381db7 7238 &rmap_path);
d62a17ae 7239
7240 bgp->peer_self->rmap_type = 0;
7241
7242 if (ret == RMAP_DENYMATCH) {
7243 /* Free uninterned attribute. */
7244 bgp_attr_flush(&attr_new);
7245
7246 /* Unintern original. */
7247 aspath_unintern(&attr.aspath);
7248 bgp_redistribute_delete(bgp, p, type, instance);
7249 return;
7250 }
7251 }
7252
892fedb6 7253 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
7f323236
DW
7254 bgp_attr_add_gshut_community(&attr_new);
7255
d62a17ae 7256 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7257 SAFI_UNICAST, p, NULL);
7258
7259 new_attr = bgp_attr_intern(&attr_new);
7260
6f94b685
DS
7261 for (bpi = bgp_node_get_bgp_path_info(bn); bpi;
7262 bpi = bpi->next)
40381db7
DS
7263 if (bpi->peer == bgp->peer_self
7264 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 7265 break;
7266
40381db7 7267 if (bpi) {
d62a17ae 7268 /* Ensure the (source route) type is updated. */
40381db7
DS
7269 bpi->type = type;
7270 if (attrhash_cmp(bpi->attr, new_attr)
7271 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 7272 bgp_attr_unintern(&new_attr);
7273 aspath_unintern(&attr.aspath);
7274 bgp_unlock_node(bn);
7275 return;
7276 } else {
7277 /* The attribute is changed. */
40381db7 7278 bgp_path_info_set_flag(bn, bpi,
18ee8310 7279 BGP_PATH_ATTR_CHANGED);
d62a17ae 7280
7281 /* Rewrite BGP route information. */
40381db7
DS
7282 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
7283 bgp_path_info_restore(bn, bpi);
d62a17ae 7284 else
40381db7
DS
7285 bgp_aggregate_decrement(
7286 bgp, p, bpi, afi, SAFI_UNICAST);
7287 bgp_attr_unintern(&bpi->attr);
7288 bpi->attr = new_attr;
7289 bpi->uptime = bgp_clock();
d62a17ae 7290
7291 /* Process change. */
40381db7 7292 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 7293 SAFI_UNICAST);
7294 bgp_process(bgp, bn, afi, SAFI_UNICAST);
7295 bgp_unlock_node(bn);
7296 aspath_unintern(&attr.aspath);
ddb5b488
PZ
7297
7298 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7299 || (bgp->inst_type
7300 == BGP_INSTANCE_TYPE_DEFAULT)) {
7301
7302 vpn_leak_from_vrf_update(
40381db7 7303 bgp_get_default(), bgp, bpi);
ddb5b488 7304 }
d62a17ae 7305 return;
7306 }
7307 }
7308
7309 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
7310 bgp->peer_self, new_attr, bn);
1defdda8 7311 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 7312
7313 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 7314 bgp_path_info_add(bn, new);
d62a17ae 7315 bgp_unlock_node(bn);
7316 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
7317
7318 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7319 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7320
7321 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
7322 }
d62a17ae 7323 }
7324
7325 /* Unintern original. */
7326 aspath_unintern(&attr.aspath);
718e3744 7327}
7328
d7c0a89a
QY
7329void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
7330 unsigned short instance)
718e3744 7331{
d62a17ae 7332 afi_t afi;
7333 struct bgp_node *rn;
40381db7 7334 struct bgp_path_info *pi;
d62a17ae 7335 struct bgp_redist *red;
718e3744 7336
d62a17ae 7337 afi = family2afi(p->family);
718e3744 7338
d62a17ae 7339 red = bgp_redist_lookup(bgp, afi, type, instance);
7340 if (red) {
7341 rn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7342 SAFI_UNICAST, p, NULL);
7343
6f94b685 7344 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7 7345 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 7346 break;
7347
40381db7 7348 if (pi) {
ddb5b488
PZ
7349 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7350 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7351
7352 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7353 bgp, pi);
ddb5b488 7354 }
40381db7
DS
7355 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
7356 bgp_path_info_delete(rn, pi);
d62a17ae 7357 bgp_process(bgp, rn, afi, SAFI_UNICAST);
7358 }
7359 bgp_unlock_node(rn);
7360 }
7361}
7362
7363/* Withdraw specified route type's route. */
7364void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 7365 unsigned short instance)
d62a17ae 7366{
7367 struct bgp_node *rn;
40381db7 7368 struct bgp_path_info *pi;
d62a17ae 7369 struct bgp_table *table;
7370
7371 table = bgp->rib[afi][SAFI_UNICAST];
7372
7373 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685 7374 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
7375 if (pi->peer == bgp->peer_self && pi->type == type
7376 && pi->instance == instance)
d62a17ae 7377 break;
7378
40381db7 7379 if (pi) {
ddb5b488
PZ
7380 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7381 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7382
7383 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7384 bgp, pi);
ddb5b488 7385 }
b54892e0
DS
7386 bgp_aggregate_decrement(bgp, bgp_node_get_prefix(rn),
7387 pi, afi, SAFI_UNICAST);
40381db7 7388 bgp_path_info_delete(rn, pi);
d62a17ae 7389 bgp_process(bgp, rn, afi, SAFI_UNICAST);
7390 }
718e3744 7391 }
718e3744 7392}
6b0655a2 7393
718e3744 7394/* Static function to display route. */
bd494ec5 7395static void route_vty_out_route(const struct prefix *p, struct vty *vty,
9c92b5f7 7396 json_object *json)
718e3744 7397{
be054588 7398 int len = 0;
d62a17ae 7399 char buf[BUFSIZ];
50e05855 7400 char buf2[BUFSIZ];
718e3744 7401
d62a17ae 7402 if (p->family == AF_INET) {
c6462ff4 7403 if (!json) {
89e5e9f0
PM
7404 len = vty_out(
7405 vty, "%s/%d",
7406 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
7407 p->prefixlen);
c6462ff4
MK
7408 } else {
7409 json_object_string_add(json, "prefix",
7410 inet_ntop(p->family,
7411 &p->u.prefix, buf,
7412 BUFSIZ));
7413 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 7414 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 7415 json_object_string_add(json, "network", buf2);
c6462ff4 7416 }
d62a17ae 7417 } else if (p->family == AF_ETHERNET) {
b03b8898
DS
7418 prefix2str(p, buf, PREFIX_STRLEN);
7419 len = vty_out(vty, "%s", buf);
7420 } else if (p->family == AF_EVPN) {
57f7feb6 7421 if (!json)
60466a63
QY
7422 len = vty_out(
7423 vty, "%s",
7424 bgp_evpn_route2str((struct prefix_evpn *)p, buf,
7425 BUFSIZ));
57f7feb6 7426 else
60466a63 7427 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
7428 } else if (p->family == AF_FLOWSPEC) {
7429 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
7430 json ?
7431 NLRI_STRING_FORMAT_JSON_SIMPLE :
7432 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 7433 } else {
c6462ff4 7434 if (!json)
60466a63
QY
7435 len = vty_out(
7436 vty, "%s/%d",
7437 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
7438 p->prefixlen);
50e05855
AD
7439 else {
7440 json_object_string_add(json, "prefix",
7441 inet_ntop(p->family,
7442 &p->u.prefix, buf,
7443 BUFSIZ));
7444 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
7445 prefix2str(p, buf2, PREFIX_STRLEN);
7446 json_object_string_add(json, "network", buf2);
7447 }
9c92b5f7 7448 }
d62a17ae 7449
9c92b5f7
MK
7450 if (!json) {
7451 len = 17 - len;
7452 if (len < 1)
7453 vty_out(vty, "\n%*s", 20, " ");
7454 else
7455 vty_out(vty, "%*s", len, " ");
7456 }
718e3744 7457}
7458
d62a17ae 7459enum bgp_display_type {
7460 normal_list,
718e3744 7461};
7462
18ee8310 7463/* Print the short form route status for a bgp_path_info */
4b7e6066 7464static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 7465 struct bgp_path_info *path,
d62a17ae 7466 json_object *json_path)
718e3744 7467{
d62a17ae 7468 if (json_path) {
b05a1c8b 7469
d62a17ae 7470 /* Route status display. */
9b6d8fcf 7471 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7472 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 7473
9b6d8fcf 7474 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7475 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 7476
9b6d8fcf 7477 if (path->extra && path->extra->suppress)
d62a17ae 7478 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 7479
9b6d8fcf
DS
7480 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7481 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7482 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 7483
d62a17ae 7484 /* Selected */
9b6d8fcf 7485 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7486 json_object_boolean_true_add(json_path, "history");
b05a1c8b 7487
9b6d8fcf 7488 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7489 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 7490
9b6d8fcf 7491 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7492 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b 7493
9b6d8fcf 7494 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7495 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 7496
d62a17ae 7497 /* Internal route. */
9b6d8fcf
DS
7498 if ((path->peer->as)
7499 && (path->peer->as == path->peer->local_as))
d62a17ae 7500 json_object_string_add(json_path, "pathFrom",
7501 "internal");
7502 else
7503 json_object_string_add(json_path, "pathFrom",
7504 "external");
b05a1c8b 7505
d62a17ae 7506 return;
7507 }
b05a1c8b 7508
d62a17ae 7509 /* Route status display. */
9b6d8fcf 7510 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7511 vty_out(vty, "R");
9b6d8fcf 7512 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7513 vty_out(vty, "S");
9b6d8fcf 7514 else if (path->extra && path->extra->suppress)
d62a17ae 7515 vty_out(vty, "s");
9b6d8fcf
DS
7516 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7517 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7518 vty_out(vty, "*");
7519 else
7520 vty_out(vty, " ");
7521
7522 /* Selected */
9b6d8fcf 7523 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7524 vty_out(vty, "h");
9b6d8fcf 7525 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7526 vty_out(vty, "d");
9b6d8fcf 7527 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7528 vty_out(vty, ">");
9b6d8fcf 7529 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7530 vty_out(vty, "=");
7531 else
7532 vty_out(vty, " ");
718e3744 7533
d62a17ae 7534 /* Internal route. */
9b6d8fcf
DS
7535 if (path->peer && (path->peer->as)
7536 && (path->peer->as == path->peer->local_as))
d62a17ae 7537 vty_out(vty, "i");
7538 else
7539 vty_out(vty, " ");
b40d939b 7540}
7541
2ba93fd6
DA
7542static char *bgp_nexthop_hostname(struct peer *peer,
7543 struct bgp_nexthop_cache *bnc)
25b5da8d 7544{
892fedb6 7545 if (peer->hostname
eb91f8d6 7546 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME) && bnc
2ba93fd6 7547 && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
25b5da8d
DA
7548 return peer->hostname;
7549 return NULL;
7550}
7551
b40d939b 7552/* called from terminal list command */
bd494ec5 7553void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 7554 struct bgp_path_info *path, int display, safi_t safi,
4b7e6066 7555 json_object *json_paths)
d62a17ae 7556{
515c2602 7557 struct attr *attr = path->attr;
d62a17ae 7558 json_object *json_path = NULL;
7559 json_object *json_nexthops = NULL;
7560 json_object *json_nexthop_global = NULL;
7561 json_object *json_nexthop_ll = NULL;
6f214dd3 7562 json_object *json_ext_community = NULL;
9df8b37c 7563 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 7564 bool nexthop_self =
9b6d8fcf 7565 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 7566 bool nexthop_othervrf = false;
43089216 7567 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 7568 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
7569 char *nexthop_hostname =
7570 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 7571
7572 if (json_paths)
7573 json_path = json_object_new_object();
7574
7575 /* short status lead text */
9b6d8fcf 7576 route_vty_short_status_out(vty, path, json_path);
d62a17ae 7577
7578 if (!json_paths) {
7579 /* print prefix and mask */
7580 if (!display)
9c92b5f7 7581 route_vty_out_route(p, vty, json_path);
d62a17ae 7582 else
7583 vty_out(vty, "%*s", 17, " ");
9c92b5f7 7584 } else {
b682f6de 7585 route_vty_out_route(p, vty, json_path);
d62a17ae 7586 }
47fc97cc 7587
9df8b37c
PZ
7588 /*
7589 * If vrf id of nexthop is different from that of prefix,
7590 * set up printable string to append
7591 */
9b6d8fcf 7592 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
7593 const char *self = "";
7594
7595 if (nexthop_self)
7596 self = "<";
7597
7598 nexthop_othervrf = true;
9b6d8fcf 7599 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 7600
9b6d8fcf 7601 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
7602 snprintf(vrf_id_str, sizeof(vrf_id_str),
7603 "@%s%s", VRFID_NONE_STR, self);
7604 else
7605 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 7606 path->extra->bgp_orig->vrf_id, self);
9df8b37c 7607
9b6d8fcf
DS
7608 if (path->extra->bgp_orig->inst_type
7609 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 7610
9b6d8fcf 7611 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
7612 } else {
7613 const char *self = "";
7614
7615 if (nexthop_self)
7616 self = "<";
7617
7618 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
7619 }
7620
445c2480
DS
7621 /*
7622 * For ENCAP and EVPN routes, nexthop address family is not
7623 * neccessarily the same as the prefix address family.
7624 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7625 * EVPN routes are also exchanged with a MP nexthop. Currently,
7626 * this
7627 * is only IPv4, the value will be present in either
7628 * attr->nexthop or
7629 * attr->mp_nexthop_global_in
7630 */
7631 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
7632 char buf[BUFSIZ];
7633 char nexthop[128];
7634 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
7635
7636 switch (af) {
7637 case AF_INET:
7638 sprintf(nexthop, "%s",
a4d82a8a
PZ
7639 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
7640 BUFSIZ));
445c2480
DS
7641 break;
7642 case AF_INET6:
7643 sprintf(nexthop, "%s",
a4d82a8a
PZ
7644 inet_ntop(af, &attr->mp_nexthop_global, buf,
7645 BUFSIZ));
445c2480
DS
7646 break;
7647 default:
7648 sprintf(nexthop, "?");
7649 break;
d62a17ae 7650 }
d62a17ae 7651
445c2480
DS
7652 if (json_paths) {
7653 json_nexthop_global = json_object_new_object();
7654
515c2602
DA
7655 json_object_string_add(json_nexthop_global, "ip",
7656 nexthop);
7657
7658 if (nexthop_hostname)
7659 json_object_string_add(json_nexthop_global,
7660 "hostname",
7661 nexthop_hostname);
7662
7663 json_object_string_add(json_nexthop_global, "afi",
7664 (af == AF_INET) ? "ipv4"
7665 : "ipv6");
445c2480
DS
7666 json_object_boolean_true_add(json_nexthop_global,
7667 "used");
7668 } else
25b5da8d 7669 vty_out(vty, "%s%s",
515c2602 7670 nexthop_hostname ? nexthop_hostname : nexthop,
25b5da8d 7671 vrf_id_str);
445c2480
DS
7672 } else if (safi == SAFI_EVPN) {
7673 if (json_paths) {
7674 json_nexthop_global = json_object_new_object();
7675
515c2602
DA
7676 json_object_string_add(json_nexthop_global, "ip",
7677 inet_ntoa(attr->nexthop));
7678
7679 if (nexthop_hostname)
7680 json_object_string_add(json_nexthop_global,
7681 "hostname",
7682 nexthop_hostname);
7683
a4d82a8a
PZ
7684 json_object_string_add(json_nexthop_global, "afi",
7685 "ipv4");
445c2480
DS
7686 json_object_boolean_true_add(json_nexthop_global,
7687 "used");
7688 } else
25b5da8d 7689 vty_out(vty, "%-16s%s",
515c2602
DA
7690 nexthop_hostname ? nexthop_hostname
7691 : inet_ntoa(attr->nexthop),
9df8b37c 7692 vrf_id_str);
d33fc23b 7693 } else if (safi == SAFI_FLOWSPEC) {
975a328e 7694 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
7695 if (json_paths) {
7696 json_nexthop_global = json_object_new_object();
515c2602 7697
026b914a
PG
7698 json_object_string_add(json_nexthop_global,
7699 "afi", "ipv4");
515c2602
DA
7700 json_object_string_add(
7701 json_nexthop_global, "ip",
7702 inet_ntoa(attr->nexthop));
7703
7704 if (nexthop_hostname)
7705 json_object_string_add(
7706 json_nexthop_global, "hostname",
7707 nexthop_hostname);
7708
50e05855
AD
7709 json_object_boolean_true_add(
7710 json_nexthop_global,
026b914a
PG
7711 "used");
7712 } else {
25b5da8d 7713 vty_out(vty, "%-16s",
515c2602
DA
7714 nexthop_hostname
7715 ? nexthop_hostname
25b5da8d 7716 : inet_ntoa(attr->nexthop));
026b914a
PG
7717 }
7718 }
d33fc23b 7719 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
7720 if (json_paths) {
7721 json_nexthop_global = json_object_new_object();
d62a17ae 7722
515c2602
DA
7723 json_object_string_add(json_nexthop_global, "ip",
7724 inet_ntoa(attr->nexthop));
7725
7726 if (nexthop_hostname)
7727 json_object_string_add(json_nexthop_global,
7728 "hostname",
7729 nexthop_hostname);
445c2480 7730
a4d82a8a
PZ
7731 json_object_string_add(json_nexthop_global, "afi",
7732 "ipv4");
445c2480
DS
7733 json_object_boolean_true_add(json_nexthop_global,
7734 "used");
7735 } else {
9df8b37c
PZ
7736 char buf[BUFSIZ];
7737
d87ff2dd 7738 snprintf(buf, sizeof(buf), "%s%s",
515c2602
DA
7739 nexthop_hostname ? nexthop_hostname
7740 : inet_ntoa(attr->nexthop),
25b5da8d 7741 vrf_id_str);
9df8b37c 7742 vty_out(vty, "%-16s", buf);
d62a17ae 7743 }
445c2480 7744 }
b05a1c8b 7745
445c2480 7746 /* IPv6 Next Hop */
a4d82a8a 7747 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
7748 int len;
7749 char buf[BUFSIZ];
d62a17ae 7750
445c2480
DS
7751 if (json_paths) {
7752 json_nexthop_global = json_object_new_object();
a4d82a8a 7753 json_object_string_add(
515c2602
DA
7754 json_nexthop_global, "ip",
7755 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
7756 buf, BUFSIZ));
7757
7758 if (nexthop_hostname)
7759 json_object_string_add(json_nexthop_global,
7760 "hostname",
7761 nexthop_hostname);
7762
a4d82a8a
PZ
7763 json_object_string_add(json_nexthop_global, "afi",
7764 "ipv6");
7765 json_object_string_add(json_nexthop_global, "scope",
7766 "global");
445c2480
DS
7767
7768 /* We display both LL & GL if both have been
7769 * received */
0606039c
DA
7770 if ((attr->mp_nexthop_len
7771 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 7772 || (path->peer->conf_if)) {
a4d82a8a 7773 json_nexthop_ll = json_object_new_object();
d62a17ae 7774 json_object_string_add(
515c2602
DA
7775 json_nexthop_ll, "ip",
7776 inet_ntop(AF_INET6,
7777 &attr->mp_nexthop_local, buf,
7778 BUFSIZ));
7779
7780 if (nexthop_hostname)
7781 json_object_string_add(
7782 json_nexthop_ll, "hostname",
7783 nexthop_hostname);
7784
a4d82a8a
PZ
7785 json_object_string_add(json_nexthop_ll, "afi",
7786 "ipv6");
7787 json_object_string_add(json_nexthop_ll, "scope",
445c2480 7788 "link-local");
d62a17ae 7789
a4d82a8a
PZ
7790 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
7791 &attr->mp_nexthop_local)
445c2480
DS
7792 != 0)
7793 && !attr->mp_nexthop_prefer_global)
d62a17ae 7794 json_object_boolean_true_add(
a4d82a8a 7795 json_nexthop_ll, "used");
445c2480
DS
7796 else
7797 json_object_boolean_true_add(
a4d82a8a 7798 json_nexthop_global, "used");
445c2480
DS
7799 } else
7800 json_object_boolean_true_add(
7801 json_nexthop_global, "used");
7802 } else {
7803 /* Display LL if LL/Global both in table unless
7804 * prefer-global is set */
0606039c
DA
7805 if (((attr->mp_nexthop_len
7806 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 7807 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
7808 || (path->peer->conf_if)) {
7809 if (path->peer->conf_if) {
a4d82a8a 7810 len = vty_out(vty, "%s",
9b6d8fcf 7811 path->peer->conf_if);
445c2480
DS
7812 len = 16 - len; /* len of IPv6
7813 addr + max
7814 len of def
7815 ifname */
7816
7817 if (len < 1)
a4d82a8a 7818 vty_out(vty, "\n%*s", 36, " ");
445c2480 7819 else
a4d82a8a 7820 vty_out(vty, "%*s", len, " ");
d62a17ae 7821 } else {
7822 len = vty_out(
9df8b37c 7823 vty, "%s%s",
515c2602
DA
7824 nexthop_hostname
7825 ? nexthop_hostname
25b5da8d
DA
7826 : inet_ntop(
7827 AF_INET6,
7828 &attr->mp_nexthop_local,
7829 buf, BUFSIZ),
9df8b37c 7830 vrf_id_str);
d62a17ae 7831 len = 16 - len;
7832
7833 if (len < 1)
a4d82a8a 7834 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 7835 else
a4d82a8a 7836 vty_out(vty, "%*s", len, " ");
d62a17ae 7837 }
445c2480 7838 } else {
a4d82a8a 7839 len = vty_out(
9df8b37c 7840 vty, "%s%s",
515c2602
DA
7841 nexthop_hostname
7842 ? nexthop_hostname
25b5da8d
DA
7843 : inet_ntop(
7844 AF_INET6,
7845 &attr->mp_nexthop_global,
7846 buf, BUFSIZ),
7847 vrf_id_str);
445c2480
DS
7848 len = 16 - len;
7849
7850 if (len < 1)
7851 vty_out(vty, "\n%*s", 36, " ");
7852 else
7853 vty_out(vty, "%*s", len, " ");
d62a17ae 7854 }
7855 }
445c2480 7856 }
718e3744 7857
445c2480
DS
7858 /* MED/Metric */
7859 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 7860 if (json_paths)
50e05855 7861 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 7862 else
445c2480
DS
7863 vty_out(vty, "%10u", attr->med);
7864 else if (!json_paths)
7865 vty_out(vty, " ");
d62a17ae 7866
445c2480
DS
7867 /* Local Pref */
7868 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 7869 if (json_paths)
50e05855 7870 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
7871 attr->local_pref);
7872 else
445c2480
DS
7873 vty_out(vty, "%7u", attr->local_pref);
7874 else if (!json_paths)
7875 vty_out(vty, " ");
d62a17ae 7876
445c2480
DS
7877 if (json_paths)
7878 json_object_int_add(json_path, "weight", attr->weight);
7879 else
7880 vty_out(vty, "%7u ", attr->weight);
47fc97cc 7881
445c2480
DS
7882 if (json_paths) {
7883 char buf[BUFSIZ];
a4d82a8a
PZ
7884 json_object_string_add(
7885 json_path, "peerId",
9b6d8fcf 7886 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 7887 }
b05a1c8b 7888
445c2480
DS
7889 /* Print aspath */
7890 if (attr->aspath) {
0fbac0b4 7891 if (json_paths)
50e05855 7892 json_object_string_add(json_path, "path",
0fbac0b4
DA
7893 attr->aspath->str);
7894 else
445c2480 7895 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 7896 }
f1aa5d8a 7897
445c2480
DS
7898 /* Print origin */
7899 if (json_paths)
a4d82a8a
PZ
7900 json_object_string_add(json_path, "origin",
7901 bgp_origin_long_str[attr->origin]);
445c2480
DS
7902 else
7903 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7904
9df8b37c 7905 if (json_paths) {
6f214dd3
CS
7906 if (safi == SAFI_EVPN &&
7907 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7908 json_ext_community = json_object_new_object();
7909 json_object_string_add(json_ext_community,
7910 "string",
7911 attr->ecommunity->str);
7912 json_object_object_add(json_path,
7913 "extendedCommunity",
7914 json_ext_community);
7915 }
7916
9df8b37c
PZ
7917 if (nexthop_self)
7918 json_object_boolean_true_add(json_path,
7919 "announceNexthopSelf");
7920 if (nexthop_othervrf) {
7921 json_object_string_add(json_path, "nhVrfName",
7922 nexthop_vrfname);
7923
7924 json_object_int_add(json_path, "nhVrfId",
7925 ((nexthop_vrfid == VRF_UNKNOWN)
7926 ? -1
7927 : (int)nexthop_vrfid));
7928 }
7929 }
7930
d62a17ae 7931 if (json_paths) {
7932 if (json_nexthop_global || json_nexthop_ll) {
7933 json_nexthops = json_object_new_array();
f1aa5d8a 7934
d62a17ae 7935 if (json_nexthop_global)
7936 json_object_array_add(json_nexthops,
7937 json_nexthop_global);
f1aa5d8a 7938
d62a17ae 7939 if (json_nexthop_ll)
7940 json_object_array_add(json_nexthops,
7941 json_nexthop_ll);
f1aa5d8a 7942
d62a17ae 7943 json_object_object_add(json_path, "nexthops",
7944 json_nexthops);
7945 }
7946
7947 json_object_array_add(json_paths, json_path);
7948 } else {
7949 vty_out(vty, "\n");
6f214dd3
CS
7950
7951 if (safi == SAFI_EVPN &&
7952 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7953 vty_out(vty, "%*s", 20, " ");
7954 vty_out(vty, "%s\n", attr->ecommunity->str);
7955 }
7956
49e5a4a0 7957#ifdef ENABLE_BGP_VNC
d62a17ae 7958 /* prints an additional line, indented, with VNC info, if
7959 * present */
7960 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 7961 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 7962#endif
d62a17ae 7963 }
7964}
718e3744 7965
7966/* called from terminal list command */
5f040085
DS
7967void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
7968 struct attr *attr, safi_t safi, bool use_json,
7969 json_object *json_ar)
d62a17ae 7970{
7971 json_object *json_status = NULL;
7972 json_object *json_net = NULL;
7973 char buff[BUFSIZ];
dc387b0f 7974
d62a17ae 7975 /* Route status display. */
7976 if (use_json) {
7977 json_status = json_object_new_object();
7978 json_net = json_object_new_object();
7979 } else {
7980 vty_out(vty, "*");
7981 vty_out(vty, ">");
7982 vty_out(vty, " ");
7983 }
718e3744 7984
d62a17ae 7985 /* print prefix and mask */
50e05855 7986 if (use_json) {
dc387b0f
LK
7987 if (safi == SAFI_EVPN)
7988 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
7989 else if (p->family == AF_INET || p->family == AF_INET6) {
7990 json_object_string_add(
7991 json_net, "addrPrefix",
7992 inet_ntop(p->family, &p->u.prefix, buff,
7993 BUFSIZ));
7994 json_object_int_add(json_net, "prefixLen",
7995 p->prefixlen);
7996 prefix2str(p, buff, PREFIX_STRLEN);
7997 json_object_string_add(json_net, "network", buff);
7998 }
50e05855 7999 } else
9c92b5f7 8000 route_vty_out_route(p, vty, NULL);
d62a17ae 8001
8002 /* Print attribute */
8003 if (attr) {
8004 if (use_json) {
8005 if (p->family == AF_INET
8006 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 8007 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 8008 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 8009 json_object_string_add(
8010 json_net, "nextHop",
8011 inet_ntoa(
8012 attr->mp_nexthop_global_in));
8013 else
8014 json_object_string_add(
8015 json_net, "nextHop",
8016 inet_ntoa(attr->nexthop));
8017 } else if (p->family == AF_INET6
8018 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8019 char buf[BUFSIZ];
8020
8021 json_object_string_add(
aa0a10fc 8022 json_net, "nextHopGlobal",
d62a17ae 8023 inet_ntop(AF_INET6,
8024 &attr->mp_nexthop_global, buf,
8025 BUFSIZ));
dc387b0f
LK
8026 } else if (p->family == AF_EVPN &&
8027 !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8028 json_object_string_add(json_net,
8029 "nextHop", inet_ntoa(
8030 attr->mp_nexthop_global_in));
d62a17ae 8031
8032 if (attr->flag
8033 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8034 json_object_int_add(json_net, "metric",
8035 attr->med);
8036
0fbac0b4 8037 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 8038 json_object_int_add(json_net, "locPrf",
0fbac0b4 8039 attr->local_pref);
d62a17ae 8040
8041 json_object_int_add(json_net, "weight", attr->weight);
8042
8043 /* Print aspath */
0fbac0b4 8044 if (attr->aspath)
50e05855 8045 json_object_string_add(json_net, "path",
0fbac0b4 8046 attr->aspath->str);
d62a17ae 8047
8048 /* Print origin */
8049 json_object_string_add(json_net, "bgpOriginCode",
8050 bgp_origin_str[attr->origin]);
8051 } else {
8052 if (p->family == AF_INET
8053 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8054 || safi == SAFI_EVPN
8055 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8056 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8057 || safi == SAFI_EVPN)
8058 vty_out(vty, "%-16s",
8059 inet_ntoa(
8060 attr->mp_nexthop_global_in));
8061 else
8062 vty_out(vty, "%-16s",
8063 inet_ntoa(attr->nexthop));
8064 } else if (p->family == AF_INET6
8065 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8066 int len;
8067 char buf[BUFSIZ];
8068
8069 len = vty_out(
8070 vty, "%s",
8071 inet_ntop(AF_INET6,
8072 &attr->mp_nexthop_global, buf,
8073 BUFSIZ));
8074 len = 16 - len;
8075 if (len < 1)
8076 vty_out(vty, "\n%*s", 36, " ");
8077 else
8078 vty_out(vty, "%*s", len, " ");
8079 }
8080 if (attr->flag
8081 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8082 vty_out(vty, "%10u", attr->med);
8083 else
8084 vty_out(vty, " ");
718e3744 8085
d62a17ae 8086 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
8087 vty_out(vty, "%7u", attr->local_pref);
8088 else
8089 vty_out(vty, " ");
8090
8091 vty_out(vty, "%7u ", attr->weight);
8092
8093 /* Print aspath */
8094 if (attr->aspath)
8095 aspath_print_vty(vty, "%s", attr->aspath, " ");
8096
8097 /* Print origin */
8098 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8099 }
8100 }
8101 if (use_json) {
8102 json_object_boolean_true_add(json_status, "*");
8103 json_object_boolean_true_add(json_status, ">");
8104 json_object_object_add(json_net, "appliedStatusSymbols",
8105 json_status);
1608ff77 8106
dc387b0f
LK
8107 prefix2str(p, buff, PREFIX_STRLEN);
8108 json_object_object_add(json_ar, buff, json_net);
d62a17ae 8109 } else
8110 vty_out(vty, "\n");
8111}
8112
bd494ec5 8113void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 8114 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 8115 json_object *json)
8116{
8117 json_object *json_out = NULL;
8118 struct attr *attr;
8119 mpls_label_t label = MPLS_INVALID_LABEL;
8120
9b6d8fcf 8121 if (!path->extra)
d62a17ae 8122 return;
8123
8124 if (json)
8125 json_out = json_object_new_object();
8126
8127 /* short status lead text */
9b6d8fcf 8128 route_vty_short_status_out(vty, path, json_out);
d62a17ae 8129
8130 /* print prefix and mask */
8131 if (json == NULL) {
8132 if (!display)
9c92b5f7 8133 route_vty_out_route(p, vty, NULL);
d62a17ae 8134 else
8135 vty_out(vty, "%*s", 17, " ");
8136 }
8137
8138 /* Print attribute */
9b6d8fcf 8139 attr = path->attr;
05864da7
DS
8140 if (((p->family == AF_INET)
8141 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8142 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8143 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8144 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8145 || safi == SAFI_EVPN) {
8146 if (json)
8147 json_object_string_add(
8148 json_out, "mpNexthopGlobalIn",
8149 inet_ntoa(attr->mp_nexthop_global_in));
8150 else
8151 vty_out(vty, "%-16s",
8152 inet_ntoa(attr->mp_nexthop_global_in));
8153 } else {
8154 if (json)
8155 json_object_string_add(
8156 json_out, "nexthop",
8157 inet_ntoa(attr->nexthop));
8158 else
8159 vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
8160 }
8161 } else if (((p->family == AF_INET6)
8162 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8163 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8164 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8165 char buf_a[512];
8166
8167 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
8168 if (json)
8169 json_object_string_add(
8170 json_out, "mpNexthopGlobalIn",
8171 inet_ntop(AF_INET6,
8172 &attr->mp_nexthop_global,
8173 buf_a, sizeof(buf_a)));
8174 else
8175 vty_out(vty, "%s",
8176 inet_ntop(AF_INET6,
8177 &attr->mp_nexthop_global,
8178 buf_a, sizeof(buf_a)));
8179 } else if (attr->mp_nexthop_len
8180 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
8181 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
8182 &attr->mp_nexthop_global,
8183 &attr->mp_nexthop_local);
8184 if (json)
8185 json_object_string_add(json_out,
8186 "mpNexthopGlobalLocal",
8187 buf_a);
8188 else
8189 vty_out(vty, "%s", buf_a);
d62a17ae 8190 }
8191 }
8192
9b6d8fcf 8193 label = decode_label(&path->extra->label[0]);
d62a17ae 8194
8195 if (bgp_is_valid_label(&label)) {
8196 if (json) {
8197 json_object_int_add(json_out, "notag", label);
8198 json_object_array_add(json, json_out);
8199 } else {
8200 vty_out(vty, "notag/%d", label);
8201 vty_out(vty, "\n");
8202 }
8203 }
8204}
718e3744 8205
bd494ec5 8206void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 8207 struct bgp_path_info *path, int display,
d62a17ae 8208 json_object *json_paths)
718e3744 8209{
d62a17ae 8210 struct attr *attr;
14f51eba 8211 char buf[BUFSIZ] = {0};
d62a17ae 8212 json_object *json_path = NULL;
14f51eba
LK
8213 json_object *json_nexthop = NULL;
8214 json_object *json_overlay = NULL;
856ca177 8215
9b6d8fcf 8216 if (!path->extra)
d62a17ae 8217 return;
718e3744 8218
14f51eba
LK
8219 if (json_paths) {
8220 json_path = json_object_new_object();
8221 json_overlay = json_object_new_object();
8222 json_nexthop = json_object_new_object();
8223 }
8224
d62a17ae 8225 /* short status lead text */
9b6d8fcf 8226 route_vty_short_status_out(vty, path, json_path);
856ca177 8227
d62a17ae 8228 /* print prefix and mask */
8229 if (!display)
14f51eba 8230 route_vty_out_route(p, vty, json_path);
d62a17ae 8231 else
8232 vty_out(vty, "%*s", 17, " ");
8233
8234 /* Print attribute */
9b6d8fcf 8235 attr = path->attr;
05864da7
DS
8236 char buf1[BUFSIZ];
8237 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 8238
05864da7
DS
8239 switch (af) {
8240 case AF_INET:
8241 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
8242 if (!json_path) {
8243 vty_out(vty, "%-16s", buf);
8244 } else {
8245 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 8246
05864da7 8247 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 8248
05864da7
DS
8249 json_object_object_add(json_path, "nexthop",
8250 json_nexthop);
8251 }
8252 break;
8253 case AF_INET6:
8254 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
8255 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
8256 if (!json_path) {
8257 vty_out(vty, "%s(%s)", buf, buf1);
8258 } else {
8259 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 8260
05864da7
DS
8261 json_object_string_add(json_nexthop, "ipv6LinkLocal",
8262 buf1);
14f51eba 8263
05864da7 8264 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 8265
05864da7
DS
8266 json_object_object_add(json_path, "nexthop",
8267 json_nexthop);
8268 }
8269 break;
8270 default:
8271 if (!json_path) {
8272 vty_out(vty, "?");
8273 } else {
8274 json_object_string_add(json_nexthop, "Error",
8275 "Unsupported address-family");
d62a17ae 8276 }
05864da7 8277 }
988258b4 8278
05864da7 8279 char *str = esi2str(&(attr->evpn_overlay.eth_s_id));
988258b4 8280
05864da7
DS
8281 if (!json_path)
8282 vty_out(vty, "%s", str);
8283 else
8284 json_object_string_add(json_overlay, "esi", str);
25b5da8d 8285
05864da7 8286 XFREE(MTYPE_TMP, str);
988258b4 8287
05864da7
DS
8288 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
8289 inet_ntop(AF_INET, &(attr->evpn_overlay.gw_ip.ipv4), buf,
8290 BUFSIZ);
8291 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
8292 inet_ntop(AF_INET6, &(attr->evpn_overlay.gw_ip.ipv6), buf,
8293 BUFSIZ);
8294 }
14f51eba 8295
05864da7
DS
8296 if (!json_path)
8297 vty_out(vty, "/%s", buf);
8298 else
8299 json_object_string_add(json_overlay, "gw", buf);
8300
8301 if (attr->ecommunity) {
8302 char *mac = NULL;
8303 struct ecommunity_val *routermac = ecommunity_lookup(
8304 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
8305 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
8306
8307 if (routermac)
8308 mac = ecom_mac2str((char *)routermac->val);
8309 if (mac) {
8310 if (!json_path) {
c4efd0f4 8311 vty_out(vty, "/%s", mac);
05864da7
DS
8312 } else {
8313 json_object_string_add(json_overlay, "rmac",
8314 mac);
988258b4 8315 }
05864da7 8316 XFREE(MTYPE_TMP, mac);
988258b4 8317 }
05864da7 8318 }
718e3744 8319
05864da7
DS
8320 if (!json_path) {
8321 vty_out(vty, "\n");
8322 } else {
8323 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 8324
05864da7 8325 json_object_array_add(json_paths, json_path);
14f51eba 8326 }
d62a17ae 8327}
718e3744 8328
d62a17ae 8329/* dampening route */
5f040085
DS
8330static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
8331 struct bgp_path_info *path, int display,
8332 afi_t afi, safi_t safi, bool use_json,
8333 json_object *json)
d62a17ae 8334{
8335 struct attr *attr;
8336 int len;
8337 char timebuf[BGP_UPTIME_LEN];
8338
8339 /* short status lead text */
9b6d8fcf 8340 route_vty_short_status_out(vty, path, json);
d62a17ae 8341
8342 /* print prefix and mask */
8343 if (!use_json) {
8344 if (!display)
9c92b5f7 8345 route_vty_out_route(p, vty, NULL);
d62a17ae 8346 else
8347 vty_out(vty, "%*s", 17, " ");
8348 }
8349
9b6d8fcf 8350 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 8351 len = 17 - len;
8352 if (len < 1) {
8353 if (!use_json)
8354 vty_out(vty, "\n%*s", 34, " ");
8355 } else {
8356 if (use_json)
8357 json_object_int_add(json, "peerHost", len);
8358 else
8359 vty_out(vty, "%*s", len, " ");
8360 }
8361
8362 if (use_json)
a935f597
DA
8363 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
8364 safi, use_json, json);
d62a17ae 8365 else
9b6d8fcf
DS
8366 vty_out(vty, "%s ",
8367 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8368 BGP_UPTIME_LEN, afi, safi,
8369 use_json, json));
d62a17ae 8370
8371 /* Print attribute */
9b6d8fcf 8372 attr = path->attr;
d62a17ae 8373
05864da7
DS
8374 /* Print aspath */
8375 if (attr->aspath) {
d62a17ae 8376 if (use_json)
05864da7
DS
8377 json_object_string_add(json, "asPath",
8378 attr->aspath->str);
d62a17ae 8379 else
05864da7 8380 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8381 }
05864da7
DS
8382
8383 /* Print origin */
8384 if (use_json)
8385 json_object_string_add(json, "origin",
8386 bgp_origin_str[attr->origin]);
8387 else
8388 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8389
d62a17ae 8390 if (!use_json)
8391 vty_out(vty, "\n");
8392}
718e3744 8393
d62a17ae 8394/* flap route */
5f040085
DS
8395static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
8396 struct bgp_path_info *path, int display,
8397 afi_t afi, safi_t safi, bool use_json,
8398 json_object *json)
784d3a42 8399{
d62a17ae 8400 struct attr *attr;
8401 struct bgp_damp_info *bdi;
8402 char timebuf[BGP_UPTIME_LEN];
8403 int len;
784d3a42 8404
9b6d8fcf 8405 if (!path->extra)
d62a17ae 8406 return;
784d3a42 8407
9b6d8fcf 8408 bdi = path->extra->damp_info;
784d3a42 8409
d62a17ae 8410 /* short status lead text */
9b6d8fcf 8411 route_vty_short_status_out(vty, path, json);
784d3a42 8412
d62a17ae 8413 /* print prefix and mask */
8414 if (!use_json) {
8415 if (!display)
9c92b5f7 8416 route_vty_out_route(p, vty, NULL);
d62a17ae 8417 else
8418 vty_out(vty, "%*s", 17, " ");
8419 }
784d3a42 8420
9b6d8fcf 8421 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 8422 len = 16 - len;
8423 if (len < 1) {
8424 if (!use_json)
8425 vty_out(vty, "\n%*s", 33, " ");
8426 } else {
8427 if (use_json)
8428 json_object_int_add(json, "peerHost", len);
8429 else
8430 vty_out(vty, "%*s", len, " ");
8431 }
784d3a42 8432
d62a17ae 8433 len = vty_out(vty, "%d", bdi->flap);
8434 len = 5 - len;
8435 if (len < 1) {
8436 if (!use_json)
8437 vty_out(vty, " ");
8438 } else {
8439 if (use_json)
8440 json_object_int_add(json, "bdiFlap", len);
8441 else
8442 vty_out(vty, "%*s", len, " ");
8443 }
8444
8445 if (use_json)
8446 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
8447 json);
8448 else
996c9314
LB
8449 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
8450 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 8451
9b6d8fcf
DS
8452 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
8453 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 8454 if (use_json)
9b6d8fcf 8455 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8456 BGP_UPTIME_LEN, afi, safi,
8457 use_json, json);
d62a17ae 8458 else
8459 vty_out(vty, "%s ",
9b6d8fcf 8460 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8461 BGP_UPTIME_LEN, afi,
8462 safi, use_json, json));
d62a17ae 8463 } else {
8464 if (!use_json)
8465 vty_out(vty, "%*s ", 8, " ");
8466 }
8467
8468 /* Print attribute */
9b6d8fcf 8469 attr = path->attr;
d62a17ae 8470
05864da7
DS
8471 /* Print aspath */
8472 if (attr->aspath) {
d62a17ae 8473 if (use_json)
05864da7
DS
8474 json_object_string_add(json, "asPath",
8475 attr->aspath->str);
d62a17ae 8476 else
05864da7 8477 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8478 }
05864da7
DS
8479
8480 /* Print origin */
8481 if (use_json)
8482 json_object_string_add(json, "origin",
8483 bgp_origin_str[attr->origin]);
8484 else
8485 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8486
d62a17ae 8487 if (!use_json)
8488 vty_out(vty, "\n");
8489}
8490
8491static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
8492 int *first, const char *header,
8493 json_object *json_adv_to)
8494{
8495 char buf1[INET6_ADDRSTRLEN];
8496 json_object *json_peer = NULL;
8497
8498 if (json_adv_to) {
8499 /* 'advertised-to' is a dictionary of peers we have advertised
8500 * this
8501 * prefix too. The key is the peer's IP or swpX, the value is
8502 * the
8503 * hostname if we know it and "" if not.
8504 */
8505 json_peer = json_object_new_object();
8506
8507 if (peer->hostname)
8508 json_object_string_add(json_peer, "hostname",
8509 peer->hostname);
8510
8511 if (peer->conf_if)
8512 json_object_object_add(json_adv_to, peer->conf_if,
8513 json_peer);
8514 else
8515 json_object_object_add(
8516 json_adv_to,
8517 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
8518 json_peer);
8519 } else {
8520 if (*first) {
8521 vty_out(vty, "%s", header);
8522 *first = 0;
8523 }
8524
8525 if (peer->hostname
892fedb6 8526 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 8527 if (peer->conf_if)
8528 vty_out(vty, " %s(%s)", peer->hostname,
8529 peer->conf_if);
8530 else
8531 vty_out(vty, " %s(%s)", peer->hostname,
8532 sockunion2str(&peer->su, buf1,
8533 SU_ADDRSTRLEN));
8534 } else {
8535 if (peer->conf_if)
8536 vty_out(vty, " %s", peer->conf_if);
8537 else
8538 vty_out(vty, " %s",
8539 sockunion2str(&peer->su, buf1,
8540 SU_ADDRSTRLEN));
8541 }
8542 }
784d3a42
PG
8543}
8544
dcc68b5e
MS
8545static void route_vty_out_tx_ids(struct vty *vty,
8546 struct bgp_addpath_info_data *d)
8547{
8548 int i;
8549
8550 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
8551 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
8552 d->addpath_tx_id[i],
8553 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
8554 }
8555}
8556
0dc8ee70
DS
8557static const char *bgp_path_selection_reason2str(
8558 enum bgp_path_selection_reason reason)
8559{
8560 switch (reason) {
8561 case bgp_path_selection_none:
8562 return "Nothing to Select";
0dc8ee70
DS
8563 case bgp_path_selection_first:
8564 return "First path received";
0dc8ee70
DS
8565 case bgp_path_selection_evpn_sticky_mac:
8566 return "EVPN Sticky Mac";
0dc8ee70
DS
8567 case bgp_path_selection_evpn_seq:
8568 return "EVPN sequence number";
0dc8ee70
DS
8569 case bgp_path_selection_evpn_lower_ip:
8570 return "EVPN lower IP";
0dc8ee70
DS
8571 case bgp_path_selection_weight:
8572 return "Weight";
0dc8ee70
DS
8573 case bgp_path_selection_local_pref:
8574 return "Local Pref";
0dc8ee70
DS
8575 case bgp_path_selection_local_route:
8576 return "Local Route";
0dc8ee70
DS
8577 case bgp_path_selection_confed_as_path:
8578 return "Confederation based AS Path";
0dc8ee70
DS
8579 case bgp_path_selection_as_path:
8580 return "AS Path";
0dc8ee70
DS
8581 case bgp_path_selection_origin:
8582 return "Origin";
0dc8ee70
DS
8583 case bgp_path_selection_med:
8584 return "MED";
0dc8ee70
DS
8585 case bgp_path_selection_peer:
8586 return "Peer Type";
0dc8ee70
DS
8587 case bgp_path_selection_confed:
8588 return "Confed Peer Type";
0dc8ee70
DS
8589 case bgp_path_selection_igp_metric:
8590 return "IGP Metric";
0dc8ee70
DS
8591 case bgp_path_selection_older:
8592 return "Older Path";
0dc8ee70
DS
8593 case bgp_path_selection_router_id:
8594 return "Router ID";
0dc8ee70
DS
8595 case bgp_path_selection_cluster_length:
8596 return "Cluser length";
0dc8ee70
DS
8597 case bgp_path_selection_stale:
8598 return "Path Staleness";
0dc8ee70
DS
8599 case bgp_path_selection_local_configured:
8600 return "Locally configured route";
0dc8ee70
DS
8601 case bgp_path_selection_neighbor_ip:
8602 return "Neighbor IP";
0dc8ee70
DS
8603 case bgp_path_selection_default:
8604 return "Nothing left to compare";
0dc8ee70 8605 }
a74879b2 8606 return "Invalid (internal error)";
0dc8ee70
DS
8607}
8608
f08b5ca0
DS
8609void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
8610 struct bgp_node *bn, struct bgp_path_info *path,
8611 afi_t afi, safi_t safi, json_object *json_paths)
d62a17ae 8612{
8613 char buf[INET6_ADDRSTRLEN];
8614 char buf1[BUFSIZ];
d62a17ae 8615 char buf2[EVPN_ROUTE_STRLEN];
515c2602 8616 struct attr *attr = path->attr;
d62a17ae 8617 int sockunion_vty_out(struct vty *, union sockunion *);
8618 time_t tbuf;
8619 json_object *json_bestpath = NULL;
8620 json_object *json_cluster_list = NULL;
8621 json_object *json_cluster_list_list = NULL;
8622 json_object *json_ext_community = NULL;
8623 json_object *json_last_update = NULL;
7fd077aa 8624 json_object *json_pmsi = NULL;
d62a17ae 8625 json_object *json_nexthop_global = NULL;
8626 json_object *json_nexthop_ll = NULL;
8627 json_object *json_nexthops = NULL;
8628 json_object *json_path = NULL;
8629 json_object *json_peer = NULL;
8630 json_object *json_string = NULL;
8631 json_object *json_adv_to = NULL;
8632 int first = 0;
8633 struct listnode *node, *nnode;
8634 struct peer *peer;
8635 int addpath_capable;
8636 int has_adj;
8637 unsigned int first_as;
1defdda8 8638 bool nexthop_self =
9b6d8fcf 8639 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 8640 int i;
2ba93fd6
DA
8641 char *nexthop_hostname =
8642 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 8643
8644 if (json_paths) {
8645 json_path = json_object_new_object();
8646 json_peer = json_object_new_object();
8647 json_nexthop_global = json_object_new_object();
8648 }
8649
44c69747 8650 if (path->extra) {
b57ba6d2 8651 char tag_buf[30];
d62a17ae 8652
d7325ee7 8653 buf2[0] = '\0';
d62a17ae 8654 tag_buf[0] = '\0';
9b6d8fcf
DS
8655 if (path->extra && path->extra->num_labels) {
8656 bgp_evpn_label2str(path->extra->label,
8657 path->extra->num_labels, tag_buf,
a4d82a8a 8658 sizeof(tag_buf));
d62a17ae 8659 }
d7325ee7 8660 if (safi == SAFI_EVPN) {
44c69747 8661 if (!json_paths) {
b54892e0
DS
8662 bgp_evpn_route2str(
8663 (struct prefix_evpn *)
8664 bgp_node_get_prefix(bn),
8665 buf2, sizeof(buf2));
44c69747
LK
8666 vty_out(vty, " Route %s", buf2);
8667 if (tag_buf[0] != '\0')
8668 vty_out(vty, " VNI %s", tag_buf);
8669 vty_out(vty, "\n");
8670 } else {
8671 if (tag_buf[0])
8672 json_object_string_add(json_path, "VNI",
8673 tag_buf);
8674 }
d7325ee7
DD
8675 }
8676
44c69747 8677 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 8678 struct bgp_path_info *parent_ri;
d62a17ae 8679 struct bgp_node *rn, *prn;
8680
9b6d8fcf 8681 parent_ri = (struct bgp_path_info *)path->extra->parent;
d62a17ae 8682 rn = parent_ri->net;
8683 if (rn && rn->prn) {
8684 prn = rn->prn;
b54892e0
DS
8685 prefix_rd2str((struct prefix_rd *)
8686 bgp_node_get_prefix(prn),
d7325ee7
DD
8687 buf1, sizeof(buf1));
8688 if (is_pi_family_evpn(parent_ri)) {
b54892e0
DS
8689 bgp_evpn_route2str(
8690 (struct prefix_evpn *)
8691 bgp_node_get_prefix(rn),
8692 buf2, sizeof(buf2));
d7325ee7
DD
8693 vty_out(vty, " Imported from %s:%s, VNI %s\n", buf1, buf2, tag_buf);
8694 } else
8695 vty_out(vty, " Imported from %s:%s\n", buf1, buf2);
d62a17ae 8696 }
8697 }
8698 }
d62a17ae 8699
05864da7
DS
8700 /* Line1 display AS-path, Aggregator */
8701 if (attr->aspath) {
8702 if (json_paths) {
8703 if (!attr->aspath->json)
8704 aspath_str_update(attr->aspath, true);
8705 json_object_lock(attr->aspath->json);
8706 json_object_object_add(json_path, "aspath",
8707 attr->aspath->json);
8708 } else {
8709 if (attr->aspath->segments)
8710 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 8711 else
05864da7 8712 vty_out(vty, " Local");
d62a17ae 8713 }
05864da7 8714 }
d62a17ae 8715
05864da7
DS
8716 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
8717 if (json_paths)
8718 json_object_boolean_true_add(json_path, "removed");
8719 else
8720 vty_out(vty, ", (removed)");
8721 }
d62a17ae 8722
05864da7
DS
8723 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
8724 if (json_paths)
8725 json_object_boolean_true_add(json_path, "stale");
8726 else
8727 vty_out(vty, ", (stale)");
8728 }
d62a17ae 8729
05864da7
DS
8730 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
8731 if (json_paths) {
8732 json_object_int_add(json_path, "aggregatorAs",
8733 attr->aggregator_as);
8734 json_object_string_add(
8735 json_path, "aggregatorId",
8736 inet_ntoa(attr->aggregator_addr));
87c82131
DA
8737 if (attr->aggregator_as == BGP_AS_ZERO)
8738 json_object_boolean_true_add(
8739 json_path, "aggregatorAsMalformed");
8740 else
8741 json_object_boolean_false_add(
8742 json_path, "aggregatorAsMalformed");
05864da7 8743 } else {
87c82131
DA
8744 if (attr->aggregator_as == BGP_AS_ZERO)
8745 vty_out(vty,
8746 ", (aggregated by %u(malformed) %s)",
8747 attr->aggregator_as,
8748 inet_ntoa(attr->aggregator_addr));
8749 else
8750 vty_out(vty, ", (aggregated by %u %s)",
8751 attr->aggregator_as,
8752 inet_ntoa(attr->aggregator_addr));
d62a17ae 8753 }
05864da7 8754 }
d62a17ae 8755
05864da7
DS
8756 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
8757 PEER_FLAG_REFLECTOR_CLIENT)) {
8758 if (json_paths)
8759 json_object_boolean_true_add(json_path,
8760 "rxedFromRrClient");
8761 else
8762 vty_out(vty, ", (Received from a RR-client)");
8763 }
d62a17ae 8764
05864da7
DS
8765 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
8766 PEER_FLAG_RSERVER_CLIENT)) {
8767 if (json_paths)
8768 json_object_boolean_true_add(json_path,
8769 "rxedFromRsClient");
8770 else
8771 vty_out(vty, ", (Received from a RS-client)");
8772 }
d62a17ae 8773
05864da7
DS
8774 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
8775 if (json_paths)
8776 json_object_boolean_true_add(json_path,
8777 "dampeningHistoryEntry");
8778 else
8779 vty_out(vty, ", (history entry)");
8780 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
8781 if (json_paths)
8782 json_object_boolean_true_add(json_path,
8783 "dampeningSuppressed");
8784 else
8785 vty_out(vty, ", (suppressed due to dampening)");
8786 }
d62a17ae 8787
05864da7
DS
8788 if (!json_paths)
8789 vty_out(vty, "\n");
d62a17ae 8790
05864da7
DS
8791 /* Line2 display Next-hop, Neighbor, Router-id */
8792 /* Display the nexthop */
b54892e0
DS
8793 const struct prefix *bn_p = bgp_node_get_prefix(bn);
8794
8795 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
8796 || bn_p->family == AF_EVPN)
05864da7
DS
8797 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
8798 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8799 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8800 || safi == SAFI_EVPN) {
515c2602 8801 if (json_paths) {
d62a17ae 8802 json_object_string_add(
515c2602
DA
8803 json_nexthop_global, "ip",
8804 inet_ntoa(attr->mp_nexthop_global_in));
8805
8806 if (nexthop_hostname)
8807 json_object_string_add(
8808 json_nexthop_global, "hostname",
8809 nexthop_hostname);
8810 } else
d62a17ae 8811 vty_out(vty, " %s",
515c2602
DA
8812 nexthop_hostname
8813 ? nexthop_hostname
05864da7 8814 : inet_ntoa(
515c2602 8815 attr->mp_nexthop_global_in));
d62a17ae 8816 } else {
515c2602 8817 if (json_paths) {
05864da7 8818 json_object_string_add(
515c2602
DA
8819 json_nexthop_global, "ip",
8820 inet_ntoa(attr->nexthop));
8821
8822 if (nexthop_hostname)
8823 json_object_string_add(
8824 json_nexthop_global, "hostname",
8825 nexthop_hostname);
8826 } else
05864da7 8827 vty_out(vty, " %s",
515c2602
DA
8828 nexthop_hostname
8829 ? nexthop_hostname
05864da7 8830 : inet_ntoa(attr->nexthop));
d62a17ae 8831 }
8832
05864da7
DS
8833 if (json_paths)
8834 json_object_string_add(json_nexthop_global, "afi",
8835 "ipv4");
8836 } else {
8837 if (json_paths) {
8838 json_object_string_add(
515c2602
DA
8839 json_nexthop_global, "ip",
8840 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8841 buf, INET6_ADDRSTRLEN));
8842
8843 if (nexthop_hostname)
8844 json_object_string_add(json_nexthop_global,
8845 "hostname",
8846 nexthop_hostname);
8847
05864da7
DS
8848 json_object_string_add(json_nexthop_global, "afi",
8849 "ipv6");
8850 json_object_string_add(json_nexthop_global, "scope",
8851 "global");
8852 } else {
8853 vty_out(vty, " %s",
515c2602
DA
8854 nexthop_hostname
8855 ? nexthop_hostname
05864da7
DS
8856 : inet_ntop(AF_INET6,
8857 &attr->mp_nexthop_global,
8858 buf, INET6_ADDRSTRLEN));
d62a17ae 8859 }
05864da7 8860 }
d62a17ae 8861
05864da7
DS
8862 /* Display the IGP cost or 'inaccessible' */
8863 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
8864 if (json_paths)
8865 json_object_boolean_false_add(json_nexthop_global,
8866 "accessible");
8867 else
8868 vty_out(vty, " (inaccessible)");
8869 } else {
8870 if (path->extra && path->extra->igpmetric) {
d62a17ae 8871 if (json_paths)
05864da7
DS
8872 json_object_int_add(json_nexthop_global,
8873 "metric",
8874 path->extra->igpmetric);
d62a17ae 8875 else
05864da7
DS
8876 vty_out(vty, " (metric %u)",
8877 path->extra->igpmetric);
d62a17ae 8878 }
8879
05864da7 8880 /* IGP cost is 0, display this only for json */
d62a17ae 8881 else {
d62a17ae 8882 if (json_paths)
05864da7
DS
8883 json_object_int_add(json_nexthop_global,
8884 "metric", 0);
d62a17ae 8885 }
d62a17ae 8886
05864da7
DS
8887 if (json_paths)
8888 json_object_boolean_true_add(json_nexthop_global,
8889 "accessible");
8890 }
d62a17ae 8891
05864da7
DS
8892 /* Display peer "from" output */
8893 /* This path was originated locally */
8894 if (path->peer == bgp->peer_self) {
d62a17ae 8895
05864da7 8896 if (safi == SAFI_EVPN
b54892e0 8897 || (bn_p->family == AF_INET
05864da7 8898 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 8899 if (json_paths)
05864da7
DS
8900 json_object_string_add(json_peer, "peerId",
8901 "0.0.0.0");
d62a17ae 8902 else
05864da7
DS
8903 vty_out(vty, " from 0.0.0.0 ");
8904 } else {
d62a17ae 8905 if (json_paths)
05864da7
DS
8906 json_object_string_add(json_peer, "peerId",
8907 "::");
d62a17ae 8908 else
05864da7 8909 vty_out(vty, " from :: ");
d62a17ae 8910 }
d62a17ae 8911
05864da7
DS
8912 if (json_paths)
8913 json_object_string_add(json_peer, "routerId",
8914 inet_ntoa(bgp->router_id));
8915 else
8916 vty_out(vty, "(%s)", inet_ntoa(bgp->router_id));
8917 }
d62a17ae 8918
05864da7
DS
8919 /* We RXed this path from one of our peers */
8920 else {
8921
8922 if (json_paths) {
8923 json_object_string_add(json_peer, "peerId",
8924 sockunion2str(&path->peer->su,
8925 buf,
8926 SU_ADDRSTRLEN));
8927 json_object_string_add(json_peer, "routerId",
8928 inet_ntop(AF_INET,
8929 &path->peer->remote_id,
8930 buf1, sizeof(buf1)));
8931
8932 if (path->peer->hostname)
8933 json_object_string_add(json_peer, "hostname",
8934 path->peer->hostname);
8935
8936 if (path->peer->domainname)
8937 json_object_string_add(json_peer, "domainname",
8938 path->peer->domainname);
8939
8940 if (path->peer->conf_if)
8941 json_object_string_add(json_peer, "interface",
8942 path->peer->conf_if);
8943 } else {
8944 if (path->peer->conf_if) {
8945 if (path->peer->hostname
892fedb6
DA
8946 && CHECK_FLAG(path->peer->bgp->flags,
8947 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
8948 vty_out(vty, " from %s(%s)",
8949 path->peer->hostname,
8950 path->peer->conf_if);
d62a17ae 8951 else
05864da7 8952 vty_out(vty, " from %s",
9b6d8fcf 8953 path->peer->conf_if);
d62a17ae 8954 } else {
05864da7 8955 if (path->peer->hostname
892fedb6
DA
8956 && CHECK_FLAG(path->peer->bgp->flags,
8957 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
8958 vty_out(vty, " from %s(%s)",
8959 path->peer->hostname,
8960 path->peer->host);
d62a17ae 8961 else
05864da7
DS
8962 vty_out(vty, " from %s",
8963 sockunion2str(&path->peer->su,
8964 buf,
8965 SU_ADDRSTRLEN));
d62a17ae 8966 }
d62a17ae 8967
05864da7
DS
8968 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
8969 vty_out(vty, " (%s)",
8970 inet_ntoa(attr->originator_id));
8971 else
8972 vty_out(vty, " (%s)",
8973 inet_ntop(AF_INET,
8974 &path->peer->remote_id, buf1,
8975 sizeof(buf1)));
d62a17ae 8976 }
05864da7 8977 }
9df8b37c 8978
05864da7
DS
8979 /*
8980 * Note when vrfid of nexthop is different from that of prefix
8981 */
8982 if (path->extra && path->extra->bgp_orig) {
8983 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8984
05864da7
DS
8985 if (json_paths) {
8986 const char *vn;
9df8b37c 8987
05864da7
DS
8988 if (path->extra->bgp_orig->inst_type
8989 == BGP_INSTANCE_TYPE_DEFAULT)
8990 vn = VRF_DEFAULT_NAME;
8991 else
8992 vn = path->extra->bgp_orig->name;
9df8b37c 8993
05864da7 8994 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 8995
05864da7
DS
8996 if (nexthop_vrfid == VRF_UNKNOWN) {
8997 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 8998 } else {
05864da7
DS
8999 json_object_int_add(json_path, "nhVrfId",
9000 (int)nexthop_vrfid);
9df8b37c 9001 }
05864da7
DS
9002 } else {
9003 if (nexthop_vrfid == VRF_UNKNOWN)
9004 vty_out(vty, " vrf ?");
137147c6
DS
9005 else {
9006 struct vrf *vrf;
9007
9008 vrf = vrf_lookup_by_id(nexthop_vrfid);
9009 vty_out(vty, " vrf %s(%u)",
9010 VRF_LOGNAME(vrf), nexthop_vrfid);
9011 }
9df8b37c 9012 }
05864da7 9013 }
9df8b37c 9014
05864da7
DS
9015 if (nexthop_self) {
9016 if (json_paths) {
9017 json_object_boolean_true_add(json_path,
9018 "announceNexthopSelf");
9019 } else {
9020 vty_out(vty, " announce-nh-self");
9df8b37c 9021 }
05864da7 9022 }
9df8b37c 9023
05864da7
DS
9024 if (!json_paths)
9025 vty_out(vty, "\n");
d62a17ae 9026
05864da7
DS
9027 /* display the link-local nexthop */
9028 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9029 if (json_paths) {
9030 json_nexthop_ll = json_object_new_object();
9031 json_object_string_add(
515c2602
DA
9032 json_nexthop_ll, "ip",
9033 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9034 buf, INET6_ADDRSTRLEN));
9035
9036 if (nexthop_hostname)
9037 json_object_string_add(json_nexthop_ll,
9038 "hostname",
9039 nexthop_hostname);
9040
05864da7
DS
9041 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
9042 json_object_string_add(json_nexthop_ll, "scope",
9043 "link-local");
d62a17ae 9044
05864da7
DS
9045 json_object_boolean_true_add(json_nexthop_ll,
9046 "accessible");
d62a17ae 9047
05864da7 9048 if (!attr->mp_nexthop_prefer_global)
d62a17ae 9049 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
9050 "used");
9051 else
9052 json_object_boolean_true_add(
9053 json_nexthop_global, "used");
9054 } else {
9055 vty_out(vty, " (%s) %s\n",
9056 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9057 buf, INET6_ADDRSTRLEN),
9058 attr->mp_nexthop_prefer_global
9059 ? "(prefer-global)"
9060 : "(used)");
d62a17ae 9061 }
05864da7
DS
9062 }
9063 /* If we do not have a link-local nexthop then we must flag the
9064 global as "used" */
9065 else {
9066 if (json_paths)
9067 json_object_boolean_true_add(json_nexthop_global,
9068 "used");
9069 }
d62a17ae 9070
05864da7
DS
9071 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
9072 * Int/Ext/Local, Atomic, best */
9073 if (json_paths)
9074 json_object_string_add(json_path, "origin",
9075 bgp_origin_long_str[attr->origin]);
9076 else
9077 vty_out(vty, " Origin %s",
9078 bgp_origin_long_str[attr->origin]);
9df8b37c 9079
05864da7 9080 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 9081 if (json_paths)
05864da7 9082 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 9083 else
05864da7
DS
9084 vty_out(vty, ", metric %u", attr->med);
9085 }
9df8b37c 9086
05864da7
DS
9087 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
9088 if (json_paths)
0fbac0b4 9089 json_object_int_add(json_path, "locPrf",
05864da7
DS
9090 attr->local_pref);
9091 else
9092 vty_out(vty, ", localpref %u", attr->local_pref);
9093 }
9df8b37c 9094
05864da7
DS
9095 if (attr->weight != 0) {
9096 if (json_paths)
9097 json_object_int_add(json_path, "weight", attr->weight);
9098 else
9099 vty_out(vty, ", weight %u", attr->weight);
9100 }
9df8b37c 9101
05864da7
DS
9102 if (attr->tag != 0) {
9103 if (json_paths)
9104 json_object_int_add(json_path, "tag", attr->tag);
9105 else
9106 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
9107 }
9df8b37c 9108
05864da7
DS
9109 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9110 if (json_paths)
9111 json_object_boolean_false_add(json_path, "valid");
9112 else
9113 vty_out(vty, ", invalid");
9114 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9115 if (json_paths)
9116 json_object_boolean_true_add(json_path, "valid");
9117 else
9118 vty_out(vty, ", valid");
9119 }
9df8b37c 9120
05864da7
DS
9121 if (path->peer != bgp->peer_self) {
9122 if (path->peer->as == path->peer->local_as) {
9123 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
9124 if (json_paths)
9125 json_object_string_add(
9126 json_peer, "type",
9127 "confed-internal");
d62a17ae 9128 else
05864da7 9129 vty_out(vty, ", confed-internal");
d62a17ae 9130 } else {
05864da7
DS
9131 if (json_paths)
9132 json_object_string_add(
9133 json_peer, "type", "internal");
9134 else
9135 vty_out(vty, ", internal");
9df8b37c 9136 }
05864da7
DS
9137 } else {
9138 if (bgp_confederation_peers_check(bgp,
9139 path->peer->as)) {
9140 if (json_paths)
9141 json_object_string_add(
9142 json_peer, "type",
9143 "confed-external");
d62a17ae 9144 else
05864da7 9145 vty_out(vty, ", confed-external");
d62a17ae 9146 } else {
05864da7
DS
9147 if (json_paths)
9148 json_object_string_add(
9149 json_peer, "type", "external");
9150 else
9151 vty_out(vty, ", external");
d62a17ae 9152 }
9153 }
05864da7
DS
9154 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
9155 if (json_paths) {
9156 json_object_boolean_true_add(json_path, "aggregated");
9157 json_object_boolean_true_add(json_path, "local");
9158 } else {
9159 vty_out(vty, ", aggregated, local");
9160 }
9161 } else if (path->type != ZEBRA_ROUTE_BGP) {
9162 if (json_paths)
9163 json_object_boolean_true_add(json_path, "sourced");
9164 else
9165 vty_out(vty, ", sourced");
9166 } else {
9167 if (json_paths) {
9168 json_object_boolean_true_add(json_path, "sourced");
9169 json_object_boolean_true_add(json_path, "local");
9170 } else {
9171 vty_out(vty, ", sourced, local");
d62a17ae 9172 }
05864da7 9173 }
718e3744 9174
05864da7 9175 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 9176 if (json_paths)
05864da7
DS
9177 json_object_boolean_true_add(json_path,
9178 "atomicAggregate");
d62a17ae 9179 else
05864da7
DS
9180 vty_out(vty, ", atomic-aggregate");
9181 }
d62a17ae 9182
05864da7
DS
9183 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
9184 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
9185 && bgp_path_info_mpath_count(path))) {
9186 if (json_paths)
9187 json_object_boolean_true_add(json_path, "multipath");
9188 else
9189 vty_out(vty, ", multipath");
9190 }
50e05855 9191
05864da7
DS
9192 // Mark the bestpath(s)
9193 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
9194 first_as = aspath_get_first_as(attr->aspath);
718e3744 9195
05864da7
DS
9196 if (json_paths) {
9197 if (!json_bestpath)
9198 json_bestpath = json_object_new_object();
9199 json_object_int_add(json_bestpath, "bestpathFromAs",
9200 first_as);
9201 } else {
9202 if (first_as)
9203 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 9204 else
05864da7 9205 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 9206 }
05864da7 9207 }
718e3744 9208
05864da7
DS
9209 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
9210 if (json_paths) {
9211 if (!json_bestpath)
9212 json_bestpath = json_object_new_object();
9213 json_object_boolean_true_add(json_bestpath, "overall");
9214 json_object_string_add(
9215 json_bestpath, "selectionReason",
9216 bgp_path_selection_reason2str(bn->reason));
9217 } else {
9218 vty_out(vty, ", best");
9219 vty_out(vty, " (%s)",
9220 bgp_path_selection_reason2str(bn->reason));
d62a17ae 9221 }
05864da7 9222 }
718e3744 9223
05864da7
DS
9224 if (json_bestpath)
9225 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 9226
05864da7
DS
9227 if (!json_paths)
9228 vty_out(vty, "\n");
9229
9230 /* Line 4 display Community */
9231 if (attr->community) {
9232 if (json_paths) {
9233 if (!attr->community->json)
9234 community_str(attr->community, true);
9235 json_object_lock(attr->community->json);
9236 json_object_object_add(json_path, "community",
9237 attr->community->json);
9238 } else {
9239 vty_out(vty, " Community: %s\n",
9240 attr->community->str);
d62a17ae 9241 }
05864da7 9242 }
718e3744 9243
05864da7
DS
9244 /* Line 5 display Extended-community */
9245 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9246 if (json_paths) {
9247 json_ext_community = json_object_new_object();
9248 json_object_string_add(json_ext_community, "string",
9249 attr->ecommunity->str);
9250 json_object_object_add(json_path, "extendedCommunity",
9251 json_ext_community);
d62a17ae 9252 } else {
05864da7
DS
9253 vty_out(vty, " Extended Community: %s\n",
9254 attr->ecommunity->str);
d62a17ae 9255 }
05864da7 9256 }
718e3744 9257
05864da7
DS
9258 /* Line 6 display Large community */
9259 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
9260 if (json_paths) {
9261 if (!attr->lcommunity->json)
9262 lcommunity_str(attr->lcommunity, true);
9263 json_object_lock(attr->lcommunity->json);
9264 json_object_object_add(json_path, "largeCommunity",
9265 attr->lcommunity->json);
9266 } else {
9267 vty_out(vty, " Large Community: %s\n",
9268 attr->lcommunity->str);
d62a17ae 9269 }
05864da7 9270 }
718e3744 9271
05864da7
DS
9272 /* Line 7 display Originator, Cluster-id */
9273 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
9274 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
9275 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 9276 if (json_paths)
05864da7
DS
9277 json_object_string_add(
9278 json_path, "originatorId",
9279 inet_ntoa(attr->originator_id));
d62a17ae 9280 else
05864da7
DS
9281 vty_out(vty, " Originator: %s",
9282 inet_ntoa(attr->originator_id));
d62a17ae 9283 }
856ca177 9284
05864da7
DS
9285 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
9286 int i;
d62a17ae 9287
9288 if (json_paths) {
05864da7
DS
9289 json_cluster_list = json_object_new_object();
9290 json_cluster_list_list =
9291 json_object_new_array();
9292
9293 for (i = 0; i < attr->cluster->length / 4;
9294 i++) {
9295 json_string = json_object_new_string(
9296 inet_ntoa(attr->cluster
9297 ->list[i]));
9298 json_object_array_add(
9299 json_cluster_list_list,
9300 json_string);
9301 }
718e3744 9302
05864da7
DS
9303 /*
9304 * struct cluster_list does not have
9305 * "str" variable like aspath and community
9306 * do. Add this someday if someone asks
9307 * for it.
9308 * json_object_string_add(json_cluster_list,
9309 * "string", attr->cluster->str);
9310 */
9311 json_object_object_add(json_cluster_list,
9312 "list",
9313 json_cluster_list_list);
9314 json_object_object_add(json_path, "clusterList",
9315 json_cluster_list);
0dc8ee70 9316 } else {
05864da7
DS
9317 vty_out(vty, ", Cluster list: ");
9318
9319 for (i = 0; i < attr->cluster->length / 4;
9320 i++) {
9321 vty_out(vty, "%s ",
9322 inet_ntoa(attr->cluster
9323 ->list[i]));
9324 }
0dc8ee70 9325 }
d62a17ae 9326 }
718e3744 9327
d62a17ae 9328 if (!json_paths)
9329 vty_out(vty, "\n");
05864da7 9330 }
d62a17ae 9331
05864da7 9332 if (path->extra && path->extra->damp_info)
a935f597 9333 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 9334
05864da7
DS
9335 /* Remote Label */
9336 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
9337 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
9338 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 9339
05864da7
DS
9340 if (json_paths)
9341 json_object_int_add(json_path, "remoteLabel", label);
9342 else
9343 vty_out(vty, " Remote label: %d\n", label);
9344 }
d62a17ae 9345
e496b420
HS
9346 /* Remote SID */
9347 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
9348 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
9349 if (json_paths)
9350 json_object_string_add(json_path, "remoteSid", buf);
9351 else
9352 vty_out(vty, " Remote SID: %s\n", buf);
9353 }
9354
05864da7
DS
9355 /* Label Index */
9356 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
9357 if (json_paths)
9358 json_object_int_add(json_path, "labelIndex",
9359 attr->label_index);
9360 else
9361 vty_out(vty, " Label Index: %d\n",
9362 attr->label_index);
9363 }
d62a17ae 9364
05864da7
DS
9365 /* Line 8 display Addpath IDs */
9366 if (path->addpath_rx_id
9367 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
9368 if (json_paths) {
9369 json_object_int_add(json_path, "addpathRxId",
9370 path->addpath_rx_id);
d62a17ae 9371
05864da7
DS
9372 /* Keep backwards compatibility with the old API
9373 * by putting TX All's ID in the old field
9374 */
9375 json_object_int_add(
9376 json_path, "addpathTxId",
9377 path->tx_addpath
9378 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 9379
05864da7
DS
9380 /* ... but create a specific field for each
9381 * strategy
9382 */
9383 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9384 json_object_int_add(
9385 json_path,
9386 bgp_addpath_names(i)->id_json_name,
9387 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 9388 }
05864da7
DS
9389 } else {
9390 vty_out(vty, " AddPath ID: RX %u, ",
9391 path->addpath_rx_id);
d62a17ae 9392
05864da7 9393 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 9394 }
05864da7 9395 }
520d5d76 9396
05864da7
DS
9397 /* If we used addpath to TX a non-bestpath we need to display
9398 * "Advertised to" on a path-by-path basis
9399 */
9400 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9401 first = 1;
dcc68b5e 9402
05864da7
DS
9403 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9404 addpath_capable =
9405 bgp_addpath_encode_tx(peer, afi, safi);
9406 has_adj = bgp_adj_out_lookup(
9407 peer, path->net,
9408 bgp_addpath_id_for_peer(peer, afi, safi,
9409 &path->tx_addpath));
9410
9411 if ((addpath_capable && has_adj)
9412 || (!addpath_capable && has_adj
9413 && CHECK_FLAG(path->flags,
9414 BGP_PATH_SELECTED))) {
9415 if (json_path && !json_adv_to)
9416 json_adv_to = json_object_new_object();
dcc68b5e 9417
05864da7
DS
9418 route_vty_out_advertised_to(
9419 vty, peer, &first,
9420 " Advertised to:", json_adv_to);
d62a17ae 9421 }
9422 }
718e3744 9423
05864da7
DS
9424 if (json_path) {
9425 if (json_adv_to) {
9426 json_object_object_add(
9427 json_path, "advertisedTo", json_adv_to);
d62a17ae 9428 }
05864da7
DS
9429 } else {
9430 if (!first) {
9431 vty_out(vty, "\n");
d62a17ae 9432 }
9433 }
05864da7 9434 }
b05a1c8b 9435
05864da7
DS
9436 /* Line 9 display Uptime */
9437 tbuf = time(NULL) - (bgp_clock() - path->uptime);
9438 if (json_paths) {
9439 json_last_update = json_object_new_object();
9440 json_object_int_add(json_last_update, "epoch", tbuf);
9441 json_object_string_add(json_last_update, "string",
9442 ctime(&tbuf));
9443 json_object_object_add(json_path, "lastUpdate",
9444 json_last_update);
9445 } else
9446 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 9447
05864da7
DS
9448 /* Line 10 display PMSI tunnel attribute, if present */
9449 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
9450 const char *str =
9451 lookup_msg(bgp_pmsi_tnltype_str, attr->pmsi_tnl_type,
9452 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 9453
05864da7
DS
9454 if (json_paths) {
9455 json_pmsi = json_object_new_object();
9456 json_object_string_add(json_pmsi, "tunnelType", str);
9457 json_object_int_add(json_pmsi, "label",
9458 label2vni(&attr->label));
9459 json_object_object_add(json_path, "pmsi", json_pmsi);
9460 } else
9461 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
9462 str, label2vni(&attr->label));
d62a17ae 9463 }
f1aa5d8a 9464
d62a17ae 9465 /* We've constructed the json object for this path, add it to the json
9466 * array of paths
9467 */
9468 if (json_paths) {
9469 if (json_nexthop_global || json_nexthop_ll) {
9470 json_nexthops = json_object_new_array();
f1aa5d8a 9471
d62a17ae 9472 if (json_nexthop_global)
9473 json_object_array_add(json_nexthops,
9474 json_nexthop_global);
f1aa5d8a 9475
d62a17ae 9476 if (json_nexthop_ll)
9477 json_object_array_add(json_nexthops,
9478 json_nexthop_ll);
f1aa5d8a 9479
d62a17ae 9480 json_object_object_add(json_path, "nexthops",
9481 json_nexthops);
9482 }
9483
9484 json_object_object_add(json_path, "peer", json_peer);
9485 json_object_array_add(json_paths, json_path);
05864da7 9486 }
b366b518
BB
9487}
9488
96ade3ed 9489#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
9490#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9491#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 9492
d62a17ae 9493static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
9494 const char *prefix_list_str, afi_t afi,
9495 safi_t safi, enum bgp_show_type type);
9496static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
9497 const char *filter, afi_t afi, safi_t safi,
9498 enum bgp_show_type type);
9499static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
9500 const char *rmap_str, afi_t afi, safi_t safi,
9501 enum bgp_show_type type);
9502static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
9503 const char *com, int exact, afi_t afi,
9504 safi_t safi);
9505static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
9506 const char *prefix, afi_t afi, safi_t safi,
9507 enum bgp_show_type type);
a4d82a8a 9508static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
9509 afi_t afi, safi_t safi, enum bgp_show_type type,
9510 bool use_json);
7f323236
DW
9511static int bgp_show_community(struct vty *vty, struct bgp *bgp,
9512 const char *comstr, int exact, afi_t afi,
9f049418 9513 safi_t safi, bool use_json);
d62a17ae 9514
1ae44dfc
LB
9515
9516static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 9517 struct bgp_table *table, enum bgp_show_type type,
9f049418 9518 void *output_arg, bool use_json, char *rd,
a4d82a8a
PZ
9519 int is_last, unsigned long *output_cum,
9520 unsigned long *total_cum,
9386b588 9521 unsigned long *json_header_depth)
d62a17ae 9522{
40381db7 9523 struct bgp_path_info *pi;
d62a17ae 9524 struct bgp_node *rn;
9525 int header = 1;
9526 int display;
1ae44dfc
LB
9527 unsigned long output_count = 0;
9528 unsigned long total_count = 0;
d62a17ae 9529 struct prefix *p;
d62a17ae 9530 char buf2[BUFSIZ];
9531 json_object *json_paths = NULL;
9532 int first = 1;
9533
1ae44dfc
LB
9534 if (output_cum && *output_cum != 0)
9535 header = 0;
9536
9386b588 9537 if (use_json && !*json_header_depth) {
d62a17ae 9538 vty_out(vty,
66f80d74 9539 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
01eced22
AD
9540 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9541 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 9542 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b
DS
9543 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
9544 ? VRF_DEFAULT_NAME
9545 : bgp->name,
01eced22
AD
9546 table->version, inet_ntoa(bgp->router_id),
9547 bgp->default_local_pref, bgp->as);
9386b588
PZ
9548 *json_header_depth = 2;
9549 if (rd) {
445c2480 9550 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
9551 ++*json_header_depth;
9552 }
d62a17ae 9553 }
718e3744 9554
445c2480
DS
9555 if (use_json && rd) {
9556 vty_out(vty, " \"%s\" : { ", rd);
9557 }
9558
d62a17ae 9559 /* Start processing of routes. */
98ce9a06 9560 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
b54892e0
DS
9561 const struct prefix *rn_p = bgp_node_get_prefix(rn);
9562
6f94b685
DS
9563 pi = bgp_node_get_bgp_path_info(rn);
9564 if (pi == NULL)
98ce9a06 9565 continue;
d62a17ae 9566
98ce9a06 9567 display = 0;
98ce9a06
DS
9568 if (use_json)
9569 json_paths = json_object_new_array();
9570 else
9571 json_paths = NULL;
d62a17ae 9572
6f94b685 9573 for (; pi; pi = pi->next) {
98ce9a06
DS
9574 total_count++;
9575 if (type == bgp_show_type_flap_statistics
9576 || type == bgp_show_type_flap_neighbor
9577 || type == bgp_show_type_dampend_paths
9578 || type == bgp_show_type_damp_neighbor) {
40381db7 9579 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
9580 continue;
9581 }
9582 if (type == bgp_show_type_regexp) {
9583 regex_t *regex = output_arg;
d62a17ae 9584
40381db7 9585 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
9586 == REG_NOMATCH)
9587 continue;
9588 }
9589 if (type == bgp_show_type_prefix_list) {
9590 struct prefix_list *plist = output_arg;
d62a17ae 9591
b54892e0 9592 if (prefix_list_apply(plist, rn_p)
98ce9a06
DS
9593 != PREFIX_PERMIT)
9594 continue;
9595 }
9596 if (type == bgp_show_type_filter_list) {
9597 struct as_list *as_list = output_arg;
d62a17ae 9598
40381db7 9599 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
9600 != AS_FILTER_PERMIT)
9601 continue;
9602 }
9603 if (type == bgp_show_type_route_map) {
9604 struct route_map *rmap = output_arg;
9b6d8fcf 9605 struct bgp_path_info path;
98ce9a06 9606 struct attr dummy_attr;
b68885f9 9607 route_map_result_t ret;
d62a17ae 9608
6f4f49b2 9609 dummy_attr = *pi->attr;
d62a17ae 9610
40381db7 9611 path.peer = pi->peer;
9b6d8fcf 9612 path.attr = &dummy_attr;
d62a17ae 9613
b54892e0 9614 ret = route_map_apply(rmap, rn_p, RMAP_BGP,
9b6d8fcf 9615 &path);
98ce9a06
DS
9616 if (ret == RMAP_DENYMATCH)
9617 continue;
9618 }
9619 if (type == bgp_show_type_neighbor
9620 || type == bgp_show_type_flap_neighbor
9621 || type == bgp_show_type_damp_neighbor) {
9622 union sockunion *su = output_arg;
9623
40381db7
DS
9624 if (pi->peer == NULL
9625 || pi->peer->su_remote == NULL
9626 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
9627 continue;
9628 }
9629 if (type == bgp_show_type_cidr_only) {
d7c0a89a 9630 uint32_t destination;
d62a17ae 9631
b54892e0 9632 destination = ntohl(rn_p->u.prefix4.s_addr);
98ce9a06 9633 if (IN_CLASSC(destination)
b54892e0 9634 && rn_p->prefixlen == 24)
98ce9a06
DS
9635 continue;
9636 if (IN_CLASSB(destination)
b54892e0 9637 && rn_p->prefixlen == 16)
98ce9a06
DS
9638 continue;
9639 if (IN_CLASSA(destination)
b54892e0 9640 && rn_p->prefixlen == 8)
98ce9a06
DS
9641 continue;
9642 }
9643 if (type == bgp_show_type_prefix_longer) {
f7813c7c 9644 p = output_arg;
b54892e0 9645 if (!prefix_match(p, rn_p))
98ce9a06
DS
9646 continue;
9647 }
9648 if (type == bgp_show_type_community_all) {
40381db7 9649 if (!pi->attr->community)
98ce9a06
DS
9650 continue;
9651 }
9652 if (type == bgp_show_type_community) {
9653 struct community *com = output_arg;
d62a17ae 9654
40381db7
DS
9655 if (!pi->attr->community
9656 || !community_match(pi->attr->community,
98ce9a06
DS
9657 com))
9658 continue;
9659 }
9660 if (type == bgp_show_type_community_exact) {
9661 struct community *com = output_arg;
d62a17ae 9662
40381db7
DS
9663 if (!pi->attr->community
9664 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
9665 continue;
9666 }
9667 if (type == bgp_show_type_community_list) {
9668 struct community_list *list = output_arg;
d62a17ae 9669
40381db7 9670 if (!community_list_match(pi->attr->community,
a4d82a8a 9671 list))
98ce9a06
DS
9672 continue;
9673 }
a4d82a8a 9674 if (type == bgp_show_type_community_list_exact) {
98ce9a06 9675 struct community_list *list = output_arg;
d62a17ae 9676
98ce9a06 9677 if (!community_list_exact_match(
40381db7 9678 pi->attr->community, list))
98ce9a06
DS
9679 continue;
9680 }
9681 if (type == bgp_show_type_lcommunity) {
9682 struct lcommunity *lcom = output_arg;
d62a17ae 9683
40381db7
DS
9684 if (!pi->attr->lcommunity
9685 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
9686 lcom))
9687 continue;
9688 }
36a206db 9689
9690 if (type == bgp_show_type_lcommunity_exact) {
9691 struct lcommunity *lcom = output_arg;
9692
9693 if (!pi->attr->lcommunity
9694 || !lcommunity_cmp(pi->attr->lcommunity,
9695 lcom))
9696 continue;
9697 }
98ce9a06
DS
9698 if (type == bgp_show_type_lcommunity_list) {
9699 struct community_list *list = output_arg;
d62a17ae 9700
40381db7 9701 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 9702 list))
98ce9a06
DS
9703 continue;
9704 }
36a206db 9705 if (type
9706 == bgp_show_type_lcommunity_list_exact) {
9707 struct community_list *list = output_arg;
9708
9709 if (!lcommunity_list_exact_match(
9710 pi->attr->lcommunity, list))
9711 continue;
9712 }
98ce9a06 9713 if (type == bgp_show_type_lcommunity_all) {
40381db7 9714 if (!pi->attr->lcommunity)
98ce9a06
DS
9715 continue;
9716 }
9717 if (type == bgp_show_type_dampend_paths
9718 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
9719 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
9720 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
9721 continue;
9722 }
9723
9724 if (!use_json && header) {
996c9314 9725 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 9726 ", local router ID is %s, vrf id ",
98ce9a06
DS
9727 table->version,
9728 inet_ntoa(bgp->router_id));
9df8b37c
PZ
9729 if (bgp->vrf_id == VRF_UNKNOWN)
9730 vty_out(vty, "%s", VRFID_NONE_STR);
9731 else
9732 vty_out(vty, "%u", bgp->vrf_id);
9733 vty_out(vty, "\n");
01eced22
AD
9734 vty_out(vty, "Default local pref %u, ",
9735 bgp->default_local_pref);
9736 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 9737 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 9738 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 9739 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 9740 if (type == bgp_show_type_dampend_paths
9741 || type == bgp_show_type_damp_neighbor)
98ce9a06 9742 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
9743 else if (type == bgp_show_type_flap_statistics
9744 || type == bgp_show_type_flap_neighbor)
98ce9a06 9745 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 9746 else
98ce9a06
DS
9747 vty_out(vty, BGP_SHOW_HEADER);
9748 header = 0;
d62a17ae 9749 }
98ce9a06
DS
9750 if (rd != NULL && !display && !output_count) {
9751 if (!use_json)
9752 vty_out(vty,
9753 "Route Distinguisher: %s\n",
9754 rd);
d62a17ae 9755 }
98ce9a06
DS
9756 if (type == bgp_show_type_dampend_paths
9757 || type == bgp_show_type_damp_neighbor)
b54892e0
DS
9758 damp_route_vty_out(vty, rn_p, pi, display,
9759 AFI_IP, safi, use_json,
9760 json_paths);
98ce9a06
DS
9761 else if (type == bgp_show_type_flap_statistics
9762 || type == bgp_show_type_flap_neighbor)
b54892e0
DS
9763 flap_route_vty_out(vty, rn_p, pi, display,
9764 AFI_IP, safi, use_json,
9765 json_paths);
98ce9a06 9766 else
b54892e0 9767 route_vty_out(vty, rn_p, pi, display, safi,
a4d82a8a 9768 json_paths);
98ce9a06 9769 display++;
d62a17ae 9770 }
9771
98ce9a06
DS
9772 if (display) {
9773 output_count++;
9774 if (!use_json)
9775 continue;
9776
625d2931 9777 /* encode prefix */
b54892e0 9778 if (rn_p->family == AF_FLOWSPEC) {
625d2931
PG
9779 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
9780
b54892e0
DS
9781 bgp_fs_nlri_get_string(
9782 (unsigned char *)
9783 rn_p->u.prefix_flowspec.ptr,
9784 rn_p->u.prefix_flowspec.prefixlen,
9785 retstr, NLRI_STRING_FORMAT_MIN, NULL);
625d2931 9786 if (first)
b54892e0
DS
9787 vty_out(vty, "\"%s/%d\": ", retstr,
9788 rn_p->u.prefix_flowspec
9789 .prefixlen);
625d2931 9790 else
b54892e0
DS
9791 vty_out(vty, ",\"%s/%d\": ", retstr,
9792 rn_p->u.prefix_flowspec
9793 .prefixlen);
625d2931 9794 } else {
b54892e0 9795 prefix2str(rn_p, buf2, sizeof(buf2));
625d2931
PG
9796 if (first)
9797 vty_out(vty, "\"%s\": ", buf2);
9798 else
9799 vty_out(vty, ",\"%s\": ", buf2);
9800 }
98ce9a06 9801 vty_out(vty, "%s",
f4ec52f7
DA
9802 json_object_to_json_string_ext(
9803 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 9804 json_object_free(json_paths);
449feb8e 9805 json_paths = NULL;
98ce9a06 9806 first = 0;
1f83ed02
DS
9807 } else
9808 json_object_free(json_paths);
98ce9a06
DS
9809 }
9810
1ae44dfc
LB
9811 if (output_cum) {
9812 output_count += *output_cum;
9813 *output_cum = output_count;
9814 }
9815 if (total_cum) {
9816 total_count += *total_cum;
9817 *total_cum = total_count;
9818 }
d62a17ae 9819 if (use_json) {
9386b588 9820 if (rd) {
a4d82a8a 9821 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
9822 }
9823 if (is_last) {
a4d82a8a
PZ
9824 unsigned long i;
9825 for (i = 0; i < *json_header_depth; ++i)
9826 vty_out(vty, " } ");
faf6559a 9827 vty_out(vty, "\n");
9386b588 9828 }
d62a17ae 9829 } else {
1ae44dfc
LB
9830 if (is_last) {
9831 /* No route is displayed */
9832 if (output_count == 0) {
9833 if (type == bgp_show_type_normal)
9834 vty_out(vty,
9835 "No BGP prefixes displayed, %ld exist\n",
9836 total_count);
9837 } else
d62a17ae 9838 vty_out(vty,
1ae44dfc
LB
9839 "\nDisplayed %ld routes and %ld total paths\n",
9840 output_count, total_count);
9841 }
d62a17ae 9842 }
718e3744 9843
d62a17ae 9844 return CMD_SUCCESS;
718e3744 9845}
9846
1ae44dfc
LB
9847int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
9848 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 9849 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc
LB
9850{
9851 struct bgp_node *rn, *next;
9852 unsigned long output_cum = 0;
9853 unsigned long total_cum = 0;
9386b588 9854 unsigned long json_header_depth = 0;
67009e22 9855 struct bgp_table *itable;
0136788c
LB
9856 bool show_msg;
9857
9858 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc
LB
9859
9860 for (rn = bgp_table_top(table); rn; rn = next) {
b54892e0
DS
9861 const struct prefix *rn_p = bgp_node_get_prefix(rn);
9862
1ae44dfc 9863 next = bgp_route_next(rn);
b54892e0 9864 if (prd_match && memcmp(rn_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 9865 continue;
67009e22
DS
9866
9867 itable = bgp_node_get_bgp_table_info(rn);
9868 if (itable != NULL) {
1ae44dfc 9869 struct prefix_rd prd;
06b9f471 9870 char rd[RD_ADDRSTRLEN];
1ae44dfc 9871
b54892e0 9872 memcpy(&prd, rn_p, sizeof(struct prefix_rd));
06b9f471 9873 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22
DS
9874 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
9875 use_json, rd, next == NULL, &output_cum,
9876 &total_cum, &json_header_depth);
0136788c
LB
9877 if (next == NULL)
9878 show_msg = false;
1ae44dfc
LB
9879 }
9880 }
0136788c
LB
9881 if (show_msg) {
9882 if (output_cum == 0)
9883 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
9884 total_cum);
9885 else
9886 vty_out(vty,
9887 "\nDisplayed %ld routes and %ld total paths\n",
9888 output_cum, total_cum);
9889 }
1ae44dfc
LB
9890 return CMD_SUCCESS;
9891}
d62a17ae 9892static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
9f049418 9893 enum bgp_show_type type, void *output_arg, bool use_json)
fee0f4c6 9894{
d62a17ae 9895 struct bgp_table *table;
9386b588 9896 unsigned long json_header_depth = 0;
fee0f4c6 9897
d62a17ae 9898 if (bgp == NULL) {
9899 bgp = bgp_get_default();
9900 }
fee0f4c6 9901
d62a17ae 9902 if (bgp == NULL) {
9903 if (!use_json)
9904 vty_out(vty, "No BGP process is configured\n");
16307668
RW
9905 else
9906 vty_out(vty, "{}\n");
d62a17ae 9907 return CMD_WARNING;
9908 }
4dd6177e 9909
1ae44dfc 9910 table = bgp->rib[afi][safi];
d62a17ae 9911 /* use MPLS and ENCAP specific shows until they are merged */
9912 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
9913 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
9914 output_arg, use_json);
d62a17ae 9915 }
dba3c1d3
PG
9916
9917 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
9918 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
9919 output_arg, use_json,
9920 1, NULL, NULL);
9921 }
d62a17ae 9922 /* labeled-unicast routes live in the unicast table */
9923 else if (safi == SAFI_LABELED_UNICAST)
9924 safi = SAFI_UNICAST;
fee0f4c6 9925
1ae44dfc 9926 return bgp_show_table(vty, bgp, safi, table, type, output_arg, use_json,
9386b588 9927 NULL, 1, NULL, NULL, &json_header_depth);
fee0f4c6 9928}
9929
d62a17ae 9930static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
9f049418 9931 safi_t safi, bool use_json)
f186de26 9932{
d62a17ae 9933 struct listnode *node, *nnode;
9934 struct bgp *bgp;
9935 int is_first = 1;
9f049418 9936 bool route_output = false;
f186de26 9937
d62a17ae 9938 if (use_json)
9939 vty_out(vty, "{\n");
9f689658 9940
d62a17ae 9941 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 9942 route_output = true;
d62a17ae 9943 if (use_json) {
9944 if (!is_first)
9945 vty_out(vty, ",\n");
9946 else
9947 is_first = 0;
9948
9949 vty_out(vty, "\"%s\":",
9950 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 9951 ? VRF_DEFAULT_NAME
d62a17ae 9952 : bgp->name);
9953 } else {
9954 vty_out(vty, "\nInstance %s:\n",
9955 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 9956 ? VRF_DEFAULT_NAME
d62a17ae 9957 : bgp->name);
9958 }
9959 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
9960 use_json);
9961 }
9f689658 9962
d62a17ae 9963 if (use_json)
9964 vty_out(vty, "}\n");
9f049418
DS
9965 else if (!route_output)
9966 vty_out(vty, "%% BGP instance not found\n");
f186de26 9967}
9968
718e3744 9969/* Header of detailed BGP route information */
d62a17ae 9970void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9971 struct bgp_node *rn, struct prefix_rd *prd,
9972 afi_t afi, safi_t safi, json_object *json)
9973{
40381db7 9974 struct bgp_path_info *pi;
b54892e0 9975 const struct prefix *p;
d62a17ae 9976 struct peer *peer;
9977 struct listnode *node, *nnode;
06b9f471 9978 char buf1[RD_ADDRSTRLEN];
d62a17ae 9979 char buf2[INET6_ADDRSTRLEN];
d62a17ae 9980 char buf3[EVPN_ROUTE_STRLEN];
0291c246 9981 char prefix_str[BUFSIZ];
d62a17ae 9982 int count = 0;
9983 int best = 0;
9984 int suppress = 0;
c5f1e1b2
C
9985 int accept_own = 0;
9986 int route_filter_translated_v4 = 0;
9987 int route_filter_v4 = 0;
9988 int route_filter_translated_v6 = 0;
9989 int route_filter_v6 = 0;
9990 int llgr_stale = 0;
9991 int no_llgr = 0;
9992 int accept_own_nexthop = 0;
9993 int blackhole = 0;
d62a17ae 9994 int no_export = 0;
9995 int no_advertise = 0;
9996 int local_as = 0;
c5f1e1b2 9997 int no_peer = 0;
d62a17ae 9998 int first = 1;
9999 int has_valid_label = 0;
10000 mpls_label_t label = 0;
10001 json_object *json_adv_to = NULL;
9bedbb1e 10002
b54892e0 10003 p = bgp_node_get_prefix(rn);
d62a17ae 10004 has_valid_label = bgp_is_valid_label(&rn->local_label);
10005
10006 if (has_valid_label)
10007 label = label_pton(&rn->local_label);
10008
44c69747 10009 if (safi == SAFI_EVPN) {
d62a17ae 10010
44c69747 10011 if (!json) {
d62a17ae 10012 vty_out(vty, "BGP routing table entry for %s%s%s\n",
06b9f471 10013 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
44c69747 10014 : "", prd ? ":" : "",
d62a17ae 10015 bgp_evpn_route2str((struct prefix_evpn *)p,
44c69747
LK
10016 buf3, sizeof(buf3)));
10017 } else {
10018 json_object_string_add(json, "rd",
10019 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
10020 "");
10021 bgp_evpn_route2json((struct prefix_evpn *)p, json);
10022 }
10023 } else {
10024 if (!json) {
d62a17ae 10025 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
10026 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
44c69747
LK
10027 ? prefix_rd2str(prd, buf1,
10028 sizeof(buf1))
10029 : ""),
d62a17ae 10030 safi == SAFI_MPLS_VPN ? ":" : "",
10031 inet_ntop(p->family, &p->u.prefix, buf2,
44c69747 10032 INET6_ADDRSTRLEN),
d62a17ae 10033 p->prefixlen);
cd1964ff 10034
44c69747
LK
10035 } else
10036 json_object_string_add(json, "prefix",
10037 prefix2str(p, prefix_str, sizeof(prefix_str)));
10038 }
10039
10040 if (has_valid_label) {
10041 if (json)
10042 json_object_int_add(json, "localLabel", label);
10043 else
d62a17ae 10044 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
10045 }
10046
10047 if (!json)
d62a17ae 10048 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 10049 vty_out(vty, "not allocated\n");
718e3744 10050
6f94b685 10051 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
d62a17ae 10052 count++;
40381db7 10053 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 10054 best = count;
40381db7 10055 if (pi->extra && pi->extra->suppress)
d62a17ae 10056 suppress = 1;
cee9c031 10057
40381db7 10058 if (pi->attr->community == NULL)
cee9c031
QY
10059 continue;
10060
10061 no_advertise += community_include(
40381db7
DS
10062 pi->attr->community, COMMUNITY_NO_ADVERTISE);
10063 no_export += community_include(pi->attr->community,
cee9c031 10064 COMMUNITY_NO_EXPORT);
40381db7 10065 local_as += community_include(pi->attr->community,
cee9c031 10066 COMMUNITY_LOCAL_AS);
40381db7 10067 accept_own += community_include(pi->attr->community,
cee9c031
QY
10068 COMMUNITY_ACCEPT_OWN);
10069 route_filter_translated_v4 += community_include(
40381db7 10070 pi->attr->community,
cee9c031
QY
10071 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
10072 route_filter_translated_v6 += community_include(
40381db7 10073 pi->attr->community,
cee9c031
QY
10074 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
10075 route_filter_v4 += community_include(
40381db7 10076 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 10077 route_filter_v6 += community_include(
40381db7
DS
10078 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
10079 llgr_stale += community_include(pi->attr->community,
cee9c031 10080 COMMUNITY_LLGR_STALE);
40381db7 10081 no_llgr += community_include(pi->attr->community,
cee9c031
QY
10082 COMMUNITY_NO_LLGR);
10083 accept_own_nexthop +=
40381db7 10084 community_include(pi->attr->community,
cee9c031 10085 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 10086 blackhole += community_include(pi->attr->community,
cee9c031 10087 COMMUNITY_BLACKHOLE);
40381db7 10088 no_peer += community_include(pi->attr->community,
cee9c031 10089 COMMUNITY_NO_PEER);
d62a17ae 10090 }
718e3744 10091 }
718e3744 10092
d62a17ae 10093 if (!json) {
10094 vty_out(vty, "Paths: (%d available", count);
10095 if (best) {
10096 vty_out(vty, ", best #%d", best);
b84060bb
PG
10097 if (safi == SAFI_UNICAST) {
10098 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
10099 vty_out(vty, ", table %s",
10100 VRF_DEFAULT_NAME);
10101 else
10102 vty_out(vty, ", vrf %s",
10103 bgp->name);
10104 }
d62a17ae 10105 } else
10106 vty_out(vty, ", no best path");
10107
c5f1e1b2
C
10108 if (accept_own)
10109 vty_out(vty,
10110 ", accept own local route exported and imported in different VRF");
10111 else if (route_filter_translated_v4)
10112 vty_out(vty,
10113 ", mark translated RTs for VPNv4 route filtering");
10114 else if (route_filter_v4)
10115 vty_out(vty,
10116 ", attach RT as-is for VPNv4 route filtering");
10117 else if (route_filter_translated_v6)
10118 vty_out(vty,
10119 ", mark translated RTs for VPNv6 route filtering");
10120 else if (route_filter_v6)
10121 vty_out(vty,
10122 ", attach RT as-is for VPNv6 route filtering");
10123 else if (llgr_stale)
10124 vty_out(vty,
10125 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
10126 else if (no_llgr)
10127 vty_out(vty,
10128 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
10129 else if (accept_own_nexthop)
10130 vty_out(vty,
10131 ", accept local nexthop");
10132 else if (blackhole)
10133 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 10134 else if (no_export)
10135 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
10136 else if (no_advertise)
10137 vty_out(vty, ", not advertised to any peer");
d62a17ae 10138 else if (local_as)
10139 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
10140 else if (no_peer)
10141 vty_out(vty,
10142 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 10143
10144 if (suppress)
10145 vty_out(vty,
10146 ", Advertisements suppressed by an aggregate.");
10147 vty_out(vty, ")\n");
10148 }
718e3744 10149
d62a17ae 10150 /* If we are not using addpath then we can display Advertised to and
10151 * that will
10152 * show what peers we advertised the bestpath to. If we are using
10153 * addpath
10154 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 10155 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 10156 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10157 if (bgp_adj_out_lookup(peer, rn, 0)) {
10158 if (json && !json_adv_to)
10159 json_adv_to = json_object_new_object();
10160
10161 route_vty_out_advertised_to(
10162 vty, peer, &first,
10163 " Advertised to non peer-group peers:\n ",
10164 json_adv_to);
10165 }
10166 }
10167
10168 if (json) {
10169 if (json_adv_to) {
10170 json_object_object_add(json, "advertisedTo",
10171 json_adv_to);
10172 }
10173 } else {
10174 if (first)
10175 vty_out(vty, " Not advertised to any peer");
10176 vty_out(vty, "\n");
10177 }
10178 }
718e3744 10179}
10180
44c69747
LK
10181static void bgp_show_path_info(struct prefix_rd *pfx_rd,
10182 struct bgp_node *bgp_node, struct vty *vty,
10183 struct bgp *bgp, afi_t afi,
10184 safi_t safi, json_object *json,
10185 enum bgp_path_type pathtype, int *display)
10186{
10187 struct bgp_path_info *pi;
10188 int header = 1;
10189 char rdbuf[RD_ADDRSTRLEN];
10190 json_object *json_header = NULL;
10191 json_object *json_paths = NULL;
10192
10193 for (pi = bgp_node_get_bgp_path_info(bgp_node); pi;
10194 pi = pi->next) {
10195
10196 if (json && !json_paths) {
10197 /* Instantiate json_paths only if path is valid */
10198 json_paths = json_object_new_array();
10199 if (pfx_rd) {
10200 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
10201 json_header = json_object_new_object();
10202 } else
10203 json_header = json;
10204 }
10205
10206 if (header) {
10207 route_vty_out_detail_header(
10208 vty, bgp, bgp_node, pfx_rd,
10209 AFI_IP, safi, json_header);
10210 header = 0;
10211 }
10212 (*display)++;
10213
10214 if (pathtype == BGP_PATH_SHOW_ALL
10215 || (pathtype == BGP_PATH_SHOW_BESTPATH
10216 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
10217 || (pathtype == BGP_PATH_SHOW_MULTIPATH
10218 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
10219 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
10220 route_vty_out_detail(vty, bgp, bgp_node,
10221 pi, AFI_IP, safi,
10222 json_paths);
10223 }
10224
10225 if (json && json_paths) {
10226 json_object_object_add(json_header, "paths", json_paths);
10227
10228 if (pfx_rd)
10229 json_object_object_add(json, rdbuf, json_header);
10230 }
10231}
10232
718e3744 10233/* Display specified route of BGP table. */
d62a17ae 10234static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
10235 struct bgp_table *rib, const char *ip_str,
10236 afi_t afi, safi_t safi,
10237 struct prefix_rd *prd, int prefix_check,
9f049418 10238 enum bgp_path_type pathtype, bool use_json)
d62a17ae 10239{
10240 int ret;
d62a17ae 10241 int display = 0;
10242 struct prefix match;
10243 struct bgp_node *rn;
10244 struct bgp_node *rm;
d62a17ae 10245 struct bgp_table *table;
10246 json_object *json = NULL;
10247 json_object *json_paths = NULL;
10248
10249 /* Check IP address argument. */
10250 ret = str2prefix(ip_str, &match);
10251 if (!ret) {
10252 vty_out(vty, "address is malformed\n");
10253 return CMD_WARNING;
10254 }
718e3744 10255
d62a17ae 10256 match.family = afi2family(afi);
b05a1c8b 10257
44c69747 10258 if (use_json)
d62a17ae 10259 json = json_object_new_object();
718e3744 10260
44c69747 10261 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
d62a17ae 10262 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
b54892e0
DS
10263 const struct prefix *rn_p = bgp_node_get_prefix(rn);
10264
10265 if (prd && memcmp(rn_p->u.val, prd->val, 8) != 0)
d62a17ae 10266 continue;
67009e22
DS
10267 table = bgp_node_get_bgp_table_info(rn);
10268 if (!table)
ea47320b 10269 continue;
d62a17ae 10270
ea47320b
DL
10271 if ((rm = bgp_node_match(table, &match)) == NULL)
10272 continue;
d62a17ae 10273
b54892e0 10274 const struct prefix *rm_p = bgp_node_get_prefix(rm);
ea47320b 10275 if (prefix_check
b54892e0 10276 && rm_p->prefixlen != match.prefixlen) {
ea47320b
DL
10277 bgp_unlock_node(rm);
10278 continue;
10279 }
d62a17ae 10280
b54892e0
DS
10281 bgp_show_path_info((struct prefix_rd *)rn_p, rm, vty,
10282 bgp, afi, safi, json, pathtype,
10283 &display);
44c69747
LK
10284
10285 bgp_unlock_node(rm);
10286 }
10287 } else if (safi == SAFI_EVPN) {
10288 struct bgp_node *longest_pfx;
cded3b72 10289 bool is_exact_pfxlen_match = false;
44c69747
LK
10290
10291 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
b54892e0
DS
10292 const struct prefix *rn_p = bgp_node_get_prefix(rn);
10293
10294 if (prd && memcmp(&rn_p->u.val, prd->val, 8) != 0)
44c69747
LK
10295 continue;
10296 table = bgp_node_get_bgp_table_info(rn);
10297 if (!table)
10298 continue;
10299
10300 longest_pfx = NULL;
cded3b72 10301 is_exact_pfxlen_match = false;
44c69747
LK
10302 /*
10303 * Search through all the prefixes for a match. The
10304 * pfx's are enumerated in ascending order of pfxlens.
10305 * So, the last pfx match is the longest match. Set
10306 * is_exact_pfxlen_match when we get exact pfxlen match
10307 */
10308 for (rm = bgp_table_top(table); rm;
10309 rm = bgp_route_next(rm)) {
b54892e0
DS
10310 const struct prefix *rm_p =
10311 bgp_node_get_prefix(rm);
44c69747
LK
10312 /*
10313 * Get prefixlen of the ip-prefix within type5
10314 * evpn route
10315 */
b54892e0
DS
10316 if (evpn_type5_prefix_match(rm_p, &match)
10317 && rm->info) {
44c69747
LK
10318 longest_pfx = rm;
10319 int type5_pfxlen =
b54892e0
DS
10320 bgp_evpn_get_type5_prefixlen(
10321 rm_p);
44c69747 10322 if (type5_pfxlen == match.prefixlen) {
cded3b72 10323 is_exact_pfxlen_match = true;
44c69747
LK
10324 bgp_unlock_node(rm);
10325 break;
10326 }
d62a17ae 10327 }
10328 }
ea47320b 10329
44c69747
LK
10330 if (!longest_pfx)
10331 continue;
10332
10333 if (prefix_check && !is_exact_pfxlen_match)
10334 continue;
10335
10336 rm = longest_pfx;
10337 bgp_lock_node(rm);
10338
b54892e0
DS
10339 bgp_show_path_info((struct prefix_rd *)rn_p, rm, vty,
10340 bgp, afi, safi, json, pathtype,
10341 &display);
44c69747 10342
ea47320b 10343 bgp_unlock_node(rm);
d62a17ae 10344 }
98a9dbc7 10345 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
10346 if (use_json)
10347 json_paths = json_object_new_array();
10348
63a0b7a9
PG
10349 display = bgp_flowspec_display_match_per_ip(afi, rib,
10350 &match, prefix_check,
10351 vty,
10352 use_json,
10353 json_paths);
44c69747
LK
10354 if (use_json && display)
10355 json_object_object_add(json, "paths", json_paths);
d62a17ae 10356 } else {
d62a17ae 10357 if ((rn = bgp_node_match(rib, &match)) != NULL) {
b54892e0 10358 const struct prefix *rn_p = bgp_node_get_prefix(rn);
d62a17ae 10359 if (!prefix_check
b54892e0 10360 || rn_p->prefixlen == match.prefixlen) {
44c69747
LK
10361 bgp_show_path_info(NULL, rn, vty, bgp, afi,
10362 safi, json,
10363 pathtype, &display);
d62a17ae 10364 }
10365
10366 bgp_unlock_node(rn);
10367 }
10368 }
e5eee9af 10369
d62a17ae 10370 if (use_json) {
996c9314 10371 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
10372 json, JSON_C_TO_STRING_PRETTY |
10373 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 10374 json_object_free(json);
10375 } else {
10376 if (!display) {
10377 vty_out(vty, "%% Network not in table\n");
10378 return CMD_WARNING;
10379 }
10380 }
b05a1c8b 10381
d62a17ae 10382 return CMD_SUCCESS;
718e3744 10383}
10384
fee0f4c6 10385/* Display specified route of Main RIB */
d62a17ae 10386static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
10387 afi_t afi, safi_t safi, struct prefix_rd *prd,
10388 int prefix_check, enum bgp_path_type pathtype,
9f049418 10389 bool use_json)
d62a17ae 10390{
9b86009a 10391 if (!bgp) {
d62a17ae 10392 bgp = bgp_get_default();
9b86009a
RW
10393 if (!bgp) {
10394 if (!use_json)
10395 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10396 else
10397 vty_out(vty, "{}\n");
9b86009a
RW
10398 return CMD_WARNING;
10399 }
10400 }
d62a17ae 10401
10402 /* labeled-unicast routes live in the unicast table */
10403 if (safi == SAFI_LABELED_UNICAST)
10404 safi = SAFI_UNICAST;
10405
10406 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
10407 afi, safi, prd, prefix_check, pathtype,
10408 use_json);
10409}
10410
10411static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 10412 struct cmd_token **argv, bool exact, afi_t afi,
10413 safi_t safi, bool uj)
d62a17ae 10414{
10415 struct lcommunity *lcom;
10416 struct buffer *b;
10417 int i;
10418 char *str;
10419 int first = 0;
10420
10421 b = buffer_new(1024);
10422 for (i = 0; i < argc; i++) {
10423 if (first)
10424 buffer_putc(b, ' ');
10425 else {
10426 if (strmatch(argv[i]->text, "AA:BB:CC")) {
10427 first = 1;
10428 buffer_putstr(b, argv[i]->arg);
10429 }
10430 }
10431 }
10432 buffer_putc(b, '\0');
57d187bc 10433
d62a17ae 10434 str = buffer_getstr(b);
10435 buffer_free(b);
57d187bc 10436
d62a17ae 10437 lcom = lcommunity_str2com(str);
10438 XFREE(MTYPE_TMP, str);
10439 if (!lcom) {
10440 vty_out(vty, "%% Large-community malformed\n");
10441 return CMD_WARNING;
10442 }
57d187bc 10443
36a206db 10444 return bgp_show(vty, bgp, afi, safi,
10445 (exact ? bgp_show_type_lcommunity_exact
10446 : bgp_show_type_lcommunity),
10447 lcom, uj);
57d187bc
JS
10448}
10449
d62a17ae 10450static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 10451 const char *lcom, bool exact, afi_t afi,
10452 safi_t safi, bool uj)
57d187bc 10453{
d62a17ae 10454 struct community_list *list;
57d187bc 10455
e237b0d2 10456 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 10457 LARGE_COMMUNITY_LIST_MASTER);
10458 if (list == NULL) {
10459 vty_out(vty, "%% %s is not a valid large-community-list name\n",
10460 lcom);
10461 return CMD_WARNING;
10462 }
57d187bc 10463
36a206db 10464 return bgp_show(vty, bgp, afi, safi,
10465 (exact ? bgp_show_type_lcommunity_list_exact
10466 : bgp_show_type_lcommunity_list),
d62a17ae 10467 list, uj);
fee0f4c6 10468}
10469
52951b63
DS
10470DEFUN (show_ip_bgp_large_community_list,
10471 show_ip_bgp_large_community_list_cmd,
36a206db 10472 "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
10473 SHOW_STR
10474 IP_STR
10475 BGP_STR
10476 BGP_INSTANCE_HELP_STR
9bedbb1e 10477 BGP_AFI_HELP_STR
4dd6177e 10478 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10479 "Display routes matching the large-community-list\n"
10480 "large-community-list number\n"
10481 "large-community-list name\n"
36a206db 10482 "Exact match of the large-communities\n"
52951b63
DS
10483 JSON_STR)
10484{
d62a17ae 10485 afi_t afi = AFI_IP6;
10486 safi_t safi = SAFI_UNICAST;
10487 int idx = 0;
36a206db 10488 bool exact_match = 0;
4d678463 10489 struct bgp *bgp = NULL;
9f049418 10490 bool uj = use_json(argc, argv);
d62a17ae 10491
4d678463
KA
10492 if (uj)
10493 argc--;
10494
10495 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10496 &bgp, uj);
10497 if (!idx)
10498 return CMD_WARNING;
d62a17ae 10499
10500 argv_find(argv, argc, "large-community-list", &idx);
36a206db 10501
10502 const char *clist_number_or_name = argv[++idx]->arg;
10503
10504 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10505 exact_match = 1;
10506
10507 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
10508 exact_match, afi, safi, uj);
52951b63
DS
10509}
10510DEFUN (show_ip_bgp_large_community,
10511 show_ip_bgp_large_community_cmd,
36a206db 10512 "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
10513 SHOW_STR
10514 IP_STR
10515 BGP_STR
10516 BGP_INSTANCE_HELP_STR
9bedbb1e 10517 BGP_AFI_HELP_STR
4dd6177e 10518 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10519 "Display routes matching the large-communities\n"
10520 "List of large-community numbers\n"
36a206db 10521 "Exact match of the large-communities\n"
52951b63
DS
10522 JSON_STR)
10523{
d62a17ae 10524 afi_t afi = AFI_IP6;
10525 safi_t safi = SAFI_UNICAST;
10526 int idx = 0;
36a206db 10527 bool exact_match = 0;
4d678463 10528 struct bgp *bgp = NULL;
9f049418 10529 bool uj = use_json(argc, argv);
d62a17ae 10530
4d678463
KA
10531 if (uj)
10532 argc--;
10533
10534 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10535 &bgp, uj);
10536 if (!idx)
10537 return CMD_WARNING;
d62a17ae 10538
36a206db 10539 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
10540 if (argv_find(argv, argc, "exact-match", &idx))
10541 exact_match = 1;
10542 return bgp_show_lcommunity(vty, bgp, argc, argv,
10543 exact_match, afi, safi, uj);
10544 } else
d62a17ae 10545 return bgp_show(vty, bgp, afi, safi,
10546 bgp_show_type_lcommunity_all, NULL, uj);
52951b63
DS
10547}
10548
d62a17ae 10549static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 10550 safi_t safi, struct json_object *json);
e01ca200 10551
7b2ff250 10552
9ab0cf58
PG
10553DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
10554 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
10555 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
10556 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
10557{
10558 bool uj = use_json(argc, argv);
10559 struct bgp *bgp = NULL;
10560 safi_t safi;
10561 afi_t afi;
10562 int idx = 0;
6c9d22e2
PG
10563 struct json_object *json_all = NULL;
10564 struct json_object *json_afi_safi = NULL;
4265b261
PG
10565
10566 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10567 &bgp, false);
9ab0cf58 10568 if (!bgp)
4265b261 10569 return CMD_WARNING;
6c9d22e2 10570
4265b261 10571 if (uj)
6c9d22e2 10572 json_all = json_object_new_object();
4265b261 10573
9ab0cf58
PG
10574 FOREACH_AFI_SAFI (afi, safi) {
10575 /*
10576 * So limit output to those afi/safi pairs that
10577 * actually have something interesting in them
10578 */
10579 if (strmatch(get_afi_safi_str(afi, safi, true),
10580 "Unknown")) {
10581 continue;
10582 }
10583 if (uj) {
10584 json_afi_safi = json_object_new_array();
10585 json_object_object_add(
10586 json_all,
10587 get_afi_safi_str(afi, safi, true),
10588 json_afi_safi);
10589 } else {
10590 json_afi_safi = NULL;
6c9d22e2 10591 }
9ab0cf58
PG
10592
10593 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 10594 }
6c9d22e2
PG
10595
10596 if (uj) {
9ab0cf58
PG
10597 vty_out(vty, "%s",
10598 json_object_to_json_string_ext(
10599 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 10600 json_object_free(json_all);
4265b261 10601 }
6c9d22e2 10602
4265b261
PG
10603 return CMD_SUCCESS;
10604}
10605
7b2ff250 10606/* BGP route print out function without JSON */
14718643
PG
10607DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
10608 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 10609 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
10610 SHOW_STR
10611 IP_STR
10612 BGP_STR
10613 BGP_INSTANCE_HELP_STR
10614 L2VPN_HELP_STR
10615 EVPN_HELP_STR
10616 "BGP RIB advertisement statistics\n"
10617 JSON_STR)
10618{
9ab0cf58
PG
10619 afi_t afi;
10620 safi_t safi;
14718643
PG
10621 struct bgp *bgp = NULL;
10622 int idx = 0, ret;
10623 bool uj = use_json(argc, argv);
10624 struct json_object *json_afi_safi = NULL, *json = NULL;
10625
10626 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10627 &bgp, false);
10628 if (!idx)
10629 return CMD_WARNING;
10630
10631 if (uj)
10632 json_afi_safi = json_object_new_array();
10633 else
10634 json_afi_safi = NULL;
10635
10636 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
10637
10638 if (uj) {
10639 json = json_object_new_object();
10640 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
10641 json_afi_safi);
10642 vty_out(vty, "%s", json_object_to_json_string_ext(
10643 json, JSON_C_TO_STRING_PRETTY));
10644 json_object_free(json);
10645 }
10646 return ret;
10647}
10648
893cccd0 10649/* BGP route print out function without JSON */
9ab0cf58
PG
10650DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
10651 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
10652 " [" BGP_SAFI_WITH_LABEL_CMD_STR
10653 "]]\
893cccd0 10654 statistics [json]",
9ab0cf58
PG
10655 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
10656 BGP_SAFI_WITH_LABEL_HELP_STR
10657 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 10658{
9ab0cf58
PG
10659 afi_t afi;
10660 safi_t safi;
893cccd0
PG
10661 struct bgp *bgp = NULL;
10662 int idx = 0, ret;
10663 bool uj = use_json(argc, argv);
6c9d22e2 10664 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
10665
10666 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10667 &bgp, false);
10668 if (!idx)
10669 return CMD_WARNING;
6c9d22e2 10670
893cccd0 10671 if (uj)
6c9d22e2
PG
10672 json_afi_safi = json_object_new_array();
10673 else
10674 json_afi_safi = NULL;
10675
10676 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
10677
10678 if (uj) {
10679 json = json_object_new_object();
10680 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
10681 json_afi_safi);
9ab0cf58
PG
10682 vty_out(vty, "%s",
10683 json_object_to_json_string_ext(
10684 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
10685 json_object_free(json);
10686 }
10687 return ret;
893cccd0 10688}
7b2ff250
DW
10689
10690/* BGP route print out function without JSON */
9ab0cf58
PG
10691DEFUN(show_ip_bgp, show_ip_bgp_cmd,
10692 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
10693 " [" BGP_SAFI_WITH_LABEL_CMD_STR
10694 "]]\
7b2ff250
DW
10695 <dampening <parameters>\
10696 |route-map WORD\
10697 |prefix-list WORD\
10698 |filter-list WORD\
7b2ff250
DW
10699 |community-list <(1-500)|WORD> [exact-match]\
10700 |A.B.C.D/M longer-prefixes\
10701 |X:X::X:X/M longer-prefixes\
893cccd0 10702 >",
9ab0cf58
PG
10703 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
10704 BGP_SAFI_WITH_LABEL_HELP_STR
10705 "Display detailed information about dampening\n"
10706 "Display detail of configured dampening parameters\n"
10707 "Display routes matching the route-map\n"
10708 "A route-map to match on\n"
10709 "Display routes conforming to the prefix-list\n"
10710 "Prefix-list name\n"
10711 "Display routes conforming to the filter-list\n"
10712 "Regular expression access list name\n"
10713 "Display routes matching the community-list\n"
10714 "community-list number\n"
10715 "community-list name\n"
10716 "Exact match of the communities\n"
10717 "IPv4 prefix\n"
10718 "Display route and more specific routes\n"
10719 "IPv6 prefix\n"
10720 "Display route and more specific routes\n")
718e3744 10721{
d62a17ae 10722 afi_t afi = AFI_IP6;
10723 safi_t safi = SAFI_UNICAST;
10724 int exact_match = 0;
d62a17ae 10725 struct bgp *bgp = NULL;
10726 int idx = 0;
10727
10728 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10729 &bgp, false);
d62a17ae 10730 if (!idx)
10731 return CMD_WARNING;
10732
d62a17ae 10733 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 10734 if (argv_find(argv, argc, "parameters", &idx))
d62a17ae 10735 return bgp_show_dampening_parameters(vty, afi, safi);
10736 }
c016b6c7 10737
d62a17ae 10738 if (argv_find(argv, argc, "prefix-list", &idx))
10739 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
10740 safi, bgp_show_type_prefix_list);
10741
10742 if (argv_find(argv, argc, "filter-list", &idx))
10743 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
10744 safi, bgp_show_type_filter_list);
10745
d62a17ae 10746 if (argv_find(argv, argc, "route-map", &idx))
10747 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
10748 safi, bgp_show_type_route_map);
10749
d62a17ae 10750 if (argv_find(argv, argc, "community-list", &idx)) {
10751 const char *clist_number_or_name = argv[++idx]->arg;
10752 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10753 exact_match = 1;
10754 return bgp_show_community_list(vty, bgp, clist_number_or_name,
10755 exact_match, afi, safi);
10756 }
10757 /* prefix-longer */
10758 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10759 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10760 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
10761 safi,
10762 bgp_show_type_prefix_longer);
10763
7b2ff250
DW
10764 return CMD_WARNING;
10765}
10766
10767/* BGP route print out function with JSON */
10768DEFUN (show_ip_bgp_json,
10769 show_ip_bgp_json_cmd,
10770 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
cf4898bc
QY
10771 [cidr-only\
10772 |dampening <flap-statistics|dampened-paths>\
10773 |community [AA:NN|local-AS|no-advertise|no-export\
10774 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10775 |accept-own|accept-own-nexthop|route-filter-v6\
10776 |route-filter-v4|route-filter-translated-v6\
10777 |route-filter-translated-v4] [exact-match]\
10778 ] [json]",
7b2ff250
DW
10779 SHOW_STR
10780 IP_STR
10781 BGP_STR
10782 BGP_INSTANCE_HELP_STR
10783 BGP_AFI_HELP_STR
10784 BGP_SAFI_WITH_LABEL_HELP_STR
10785 "Display only routes with non-natural netmasks\n"
10786 "Display detailed information about dampening\n"
10787 "Display flap statistics of routes\n"
10788 "Display paths suppressed due to dampening\n"
10789 "Display routes matching the communities\n"
d0086e8e
AD
10790 COMMUNITY_AANN_STR
10791 "Do not send outside local AS (well-known community)\n"
10792 "Do not advertise to any peer (well-known community)\n"
10793 "Do not export to next AS (well-known community)\n"
10794 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
10795 "Do not export to any peer (well-known community)\n"
10796 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10797 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10798 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10799 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10800 "Should accept VPN route with local nexthop (well-known community)\n"
10801 "RT VPNv6 route filtering (well-known community)\n"
10802 "RT VPNv4 route filtering (well-known community)\n"
10803 "RT translated VPNv6 route filtering (well-known community)\n"
10804 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 10805 "Exact match of the communities\n"
7b2ff250
DW
10806 JSON_STR)
10807{
10808 afi_t afi = AFI_IP6;
10809 safi_t safi = SAFI_UNICAST;
10810 enum bgp_show_type sh_type = bgp_show_type_normal;
10811 struct bgp *bgp = NULL;
10812 int idx = 0;
d0086e8e 10813 int exact_match = 0;
9f049418
DS
10814 bool uj = use_json(argc, argv);
10815
10816 if (uj)
10817 argc--;
7b2ff250
DW
10818
10819 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10820 &bgp, uj);
7b2ff250
DW
10821 if (!idx)
10822 return CMD_WARNING;
10823
7b2ff250
DW
10824 if (argv_find(argv, argc, "cidr-only", &idx))
10825 return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
10826 NULL, uj);
10827
10828 if (argv_find(argv, argc, "dampening", &idx)) {
10829 if (argv_find(argv, argc, "dampened-paths", &idx))
10830 return bgp_show(vty, bgp, afi, safi,
10831 bgp_show_type_dampend_paths, NULL, uj);
10832 else if (argv_find(argv, argc, "flap-statistics", &idx))
10833 return bgp_show(vty, bgp, afi, safi,
10834 bgp_show_type_flap_statistics, NULL,
10835 uj);
10836 }
10837
10838 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 10839 char *maybecomm = NULL;
cf4898bc 10840 char *community = NULL;
d0086e8e 10841
79bc257a
RW
10842 if (idx + 1 < argc) {
10843 if (argv[idx + 1]->type == VARIABLE_TKN)
10844 maybecomm = argv[idx + 1]->arg;
10845 else
10846 maybecomm = argv[idx + 1]->text;
10847 }
10848
cf4898bc
QY
10849 if (maybecomm && !strmatch(maybecomm, "json")
10850 && !strmatch(maybecomm, "exact-match"))
10851 community = maybecomm;
d0086e8e 10852
cf4898bc
QY
10853 if (argv_find(argv, argc, "exact-match", &idx))
10854 exact_match = 1;
d0086e8e 10855
cf4898bc
QY
10856 if (community)
10857 return bgp_show_community(vty, bgp, community,
10858 exact_match, afi, safi, uj);
10859 else
d0086e8e 10860 return (bgp_show(vty, bgp, afi, safi,
cf4898bc
QY
10861 bgp_show_type_community_all, NULL,
10862 uj));
7b2ff250 10863 }
d0086e8e 10864
1ae44dfc 10865 return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj);
a636c635 10866}
47fc97cc 10867
718e3744 10868DEFUN (show_ip_bgp_route,
10869 show_ip_bgp_route_cmd,
4dd6177e 10870 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]"
ae19d7dd 10871 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
718e3744 10872 SHOW_STR
10873 IP_STR
10874 BGP_STR
a636c635 10875 BGP_INSTANCE_HELP_STR
4f280b15 10876 BGP_AFI_HELP_STR
4dd6177e 10877 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 10878 "Network in the BGP routing table to display\n"
0c7b1b01 10879 "IPv4 prefix\n"
8c3deaae 10880 "Network in the BGP routing table to display\n"
0c7b1b01 10881 "IPv6 prefix\n"
4092b06c 10882 "Display only the bestpath\n"
b05a1c8b 10883 "Display only multipaths\n"
9973d184 10884 JSON_STR)
4092b06c 10885{
d62a17ae 10886 int prefix_check = 0;
ae19d7dd 10887
d62a17ae 10888 afi_t afi = AFI_IP6;
10889 safi_t safi = SAFI_UNICAST;
10890 char *prefix = NULL;
10891 struct bgp *bgp = NULL;
10892 enum bgp_path_type path_type;
9f049418 10893 bool uj = use_json(argc, argv);
b05a1c8b 10894
d62a17ae 10895 int idx = 0;
ae19d7dd 10896
d62a17ae 10897 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10898 &bgp, uj);
d62a17ae 10899 if (!idx)
10900 return CMD_WARNING;
c41247f5 10901
d62a17ae 10902 if (!bgp) {
10903 vty_out(vty,
10904 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10905 return CMD_WARNING;
10906 }
a636c635 10907
d62a17ae 10908 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10909 if (argv_find(argv, argc, "A.B.C.D", &idx)
10910 || argv_find(argv, argc, "X:X::X:X", &idx))
10911 prefix_check = 0;
10912 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10913 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10914 prefix_check = 1;
10915
10916 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
10917 && afi != AFI_IP6) {
10918 vty_out(vty,
10919 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10920 return CMD_WARNING;
10921 }
10922 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
10923 && afi != AFI_IP) {
10924 vty_out(vty,
10925 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10926 return CMD_WARNING;
10927 }
10928
10929 prefix = argv[idx]->arg;
10930
10931 /* [<bestpath|multipath>] */
10932 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 10933 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 10934 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 10935 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 10936 else
360660c6 10937 path_type = BGP_PATH_SHOW_ALL;
a636c635 10938
d62a17ae 10939 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
10940 path_type, uj);
4092b06c
DS
10941}
10942
8c3deaae
QY
10943DEFUN (show_ip_bgp_regexp,
10944 show_ip_bgp_regexp_cmd,
3e5b31b3 10945 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
10946 SHOW_STR
10947 IP_STR
10948 BGP_STR
b00b230a 10949 BGP_INSTANCE_HELP_STR
4f280b15 10950 BGP_AFI_HELP_STR
4dd6177e 10951 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 10952 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
10953 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
10954 JSON_STR)
8c3deaae 10955{
d62a17ae 10956 afi_t afi = AFI_IP6;
10957 safi_t safi = SAFI_UNICAST;
10958 struct bgp *bgp = NULL;
3e5b31b3
DA
10959 bool uj = use_json(argc, argv);
10960 char *regstr = NULL;
8c3deaae 10961
d62a17ae 10962 int idx = 0;
10963 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10964 &bgp, false);
d62a17ae 10965 if (!idx)
10966 return CMD_WARNING;
8c3deaae 10967
d62a17ae 10968 // get index of regex
3e5b31b3
DA
10969 if (argv_find(argv, argc, "REGEX", &idx))
10970 regstr = argv[idx]->arg;
8c3deaae 10971
5f71d11c 10972 assert(regstr);
3e5b31b3
DA
10973 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
10974 bgp_show_type_regexp, uj);
8c3deaae
QY
10975}
10976
a636c635
DW
10977DEFUN (show_ip_bgp_instance_all,
10978 show_ip_bgp_instance_all_cmd,
4dd6177e 10979 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json]",
4092b06c 10980 SHOW_STR
a636c635 10981 IP_STR
4092b06c 10982 BGP_STR
a636c635 10983 BGP_INSTANCE_ALL_HELP_STR
4f280b15 10984 BGP_AFI_HELP_STR
4dd6177e 10985 BGP_SAFI_WITH_LABEL_HELP_STR
9973d184 10986 JSON_STR)
4092b06c 10987{
d62a17ae 10988 afi_t afi = AFI_IP;
10989 safi_t safi = SAFI_UNICAST;
10990 struct bgp *bgp = NULL;
d62a17ae 10991 int idx = 0;
9f049418 10992 bool uj = use_json(argc, argv);
ae19d7dd 10993
d62a17ae 10994 if (uj)
10995 argc--;
e3e29b32 10996
9f049418
DS
10997 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10998 &bgp, uj);
10999 if (!idx)
11000 return CMD_WARNING;
11001
d62a17ae 11002 bgp_show_all_instances_routes_vty(vty, afi, safi, uj);
11003 return CMD_SUCCESS;
e3e29b32
LB
11004}
11005
a4d82a8a 11006static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11007 afi_t afi, safi_t safi, enum bgp_show_type type,
11008 bool use_json)
718e3744 11009{
d62a17ae 11010 regex_t *regex;
11011 int rc;
e3e29b32 11012
c3900853 11013 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 11014 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
11015 regstr);
11016 return CMD_WARNING_CONFIG_FAILED;
11017 }
11018
d62a17ae 11019 regex = bgp_regcomp(regstr);
11020 if (!regex) {
11021 vty_out(vty, "Can't compile regexp %s\n", regstr);
11022 return CMD_WARNING;
11023 }
a636c635 11024
3e5b31b3 11025 rc = bgp_show(vty, bgp, afi, safi, type, regex, use_json);
d62a17ae 11026 bgp_regex_free(regex);
11027 return rc;
e3e29b32
LB
11028}
11029
d62a17ae 11030static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
11031 const char *prefix_list_str, afi_t afi,
11032 safi_t safi, enum bgp_show_type type)
e3e29b32 11033{
d62a17ae 11034 struct prefix_list *plist;
718e3744 11035
d62a17ae 11036 plist = prefix_list_lookup(afi, prefix_list_str);
11037 if (plist == NULL) {
11038 vty_out(vty, "%% %s is not a valid prefix-list name\n",
11039 prefix_list_str);
11040 return CMD_WARNING;
11041 }
718e3744 11042
d62a17ae 11043 return bgp_show(vty, bgp, afi, safi, type, plist, 0);
4092b06c
DS
11044}
11045
d62a17ae 11046static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
11047 const char *filter, afi_t afi, safi_t safi,
11048 enum bgp_show_type type)
4092b06c 11049{
d62a17ae 11050 struct as_list *as_list;
718e3744 11051
d62a17ae 11052 as_list = as_list_lookup(filter);
11053 if (as_list == NULL) {
11054 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
11055 filter);
11056 return CMD_WARNING;
11057 }
a636c635 11058
d62a17ae 11059 return bgp_show(vty, bgp, afi, safi, type, as_list, 0);
718e3744 11060}
11061
d62a17ae 11062static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
11063 const char *rmap_str, afi_t afi, safi_t safi,
11064 enum bgp_show_type type)
718e3744 11065{
d62a17ae 11066 struct route_map *rmap;
bb46e94f 11067
d62a17ae 11068 rmap = route_map_lookup_by_name(rmap_str);
11069 if (!rmap) {
11070 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
11071 return CMD_WARNING;
11072 }
11073
11074 return bgp_show(vty, bgp, afi, safi, type, rmap, 0);
11075}
11076
7f323236
DW
11077static int bgp_show_community(struct vty *vty, struct bgp *bgp,
11078 const char *comstr, int exact, afi_t afi,
9f049418 11079 safi_t safi, bool use_json)
d62a17ae 11080{
11081 struct community *com;
d62a17ae 11082 int ret = 0;
11083
7f323236 11084 com = community_str2com(comstr);
d62a17ae 11085 if (!com) {
7f323236 11086 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 11087 return CMD_WARNING;
11088 }
11089
11090 ret = bgp_show(vty, bgp, afi, safi,
11091 (exact ? bgp_show_type_community_exact
11092 : bgp_show_type_community),
d0086e8e 11093 com, use_json);
3c1f53de 11094 community_free(&com);
46c3ce83 11095
d62a17ae 11096 return ret;
718e3744 11097}
11098
d62a17ae 11099static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
11100 const char *com, int exact, afi_t afi,
11101 safi_t safi)
50ef26d4 11102{
d62a17ae 11103 struct community_list *list;
50ef26d4 11104
e237b0d2 11105 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 11106 if (list == NULL) {
11107 vty_out(vty, "%% %s is not a valid community-list name\n", com);
11108 return CMD_WARNING;
11109 }
718e3744 11110
d62a17ae 11111 return bgp_show(vty, bgp, afi, safi,
11112 (exact ? bgp_show_type_community_list_exact
11113 : bgp_show_type_community_list),
11114 list, 0);
50ef26d4 11115}
11116
d62a17ae 11117static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
11118 const char *prefix, afi_t afi, safi_t safi,
11119 enum bgp_show_type type)
718e3744 11120{
d62a17ae 11121 int ret;
11122 struct prefix *p;
47fc97cc 11123
d62a17ae 11124 p = prefix_new();
95cbbd2a 11125
d62a17ae 11126 ret = str2prefix(prefix, p);
11127 if (!ret) {
11128 vty_out(vty, "%% Malformed Prefix\n");
11129 return CMD_WARNING;
11130 }
47e9b292 11131
d62a17ae 11132 ret = bgp_show(vty, bgp, afi, safi, type, p, 0);
63265b5c 11133 prefix_free(&p);
d62a17ae 11134 return ret;
11135}
11136
d62a17ae 11137enum bgp_stats {
11138 BGP_STATS_MAXBITLEN = 0,
11139 BGP_STATS_RIB,
11140 BGP_STATS_PREFIXES,
11141 BGP_STATS_TOTPLEN,
11142 BGP_STATS_UNAGGREGATEABLE,
11143 BGP_STATS_MAX_AGGREGATEABLE,
11144 BGP_STATS_AGGREGATES,
11145 BGP_STATS_SPACE,
11146 BGP_STATS_ASPATH_COUNT,
11147 BGP_STATS_ASPATH_MAXHOPS,
11148 BGP_STATS_ASPATH_TOTHOPS,
11149 BGP_STATS_ASPATH_MAXSIZE,
11150 BGP_STATS_ASPATH_TOTSIZE,
11151 BGP_STATS_ASN_HIGHEST,
11152 BGP_STATS_MAX,
a636c635 11153};
2815e61f 11154
9ab0cf58 11155#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
11156#define TABLE_STATS_IDX_JSON 1
11157
11158static const char *table_stats_strs[][2] = {
6c9d22e2
PG
11159 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
11160 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
11161 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
11162 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
11163 "unaggregateablePrefixes"},
11164 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
11165 "maximumAggregateablePrefixes"},
11166 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
11167 "bgpAggregateAdvertisements"},
6c9d22e2
PG
11168 [BGP_STATS_SPACE] = {"Address space advertised",
11169 "addressSpaceAdvertised"},
9ab0cf58
PG
11170 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
11171 "advertisementsWithPaths"},
11172 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
11173 "longestAsPath"},
11174 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
11175 "largestAsPath"},
11176 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
11177 "averageAsPathLengthHops"},
11178 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
11179 "averageAsPathSizeBytes"},
11180 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 11181 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 11182};
2815e61f 11183
d62a17ae 11184struct bgp_table_stats {
11185 struct bgp_table *table;
11186 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 11187 double total_space;
ff7924f6
PJ
11188};
11189
a636c635
DW
11190#if 0
11191#define TALLY_SIGFIG 100000
11192static unsigned long
11193ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 11194{
a636c635
DW
11195 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
11196 unsigned long res = (newtot * TALLY_SIGFIG) / count;
11197 unsigned long ret = newtot / count;
07d0c4ed 11198
a636c635
DW
11199 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
11200 return ret + 1;
11201 else
11202 return ret;
11203}
11204#endif
ff7924f6 11205
9c14ec72
RW
11206static void bgp_table_stats_rn(struct bgp_node *rn, struct bgp_node *top,
11207 struct bgp_table_stats *ts, unsigned int space)
2815e61f 11208{
9c14ec72
RW
11209 struct bgp_node *prn = bgp_node_parent_nolock(rn);
11210 struct bgp_path_info *pi;
b54892e0 11211 const struct prefix *rn_p;
d62a17ae 11212
9c14ec72
RW
11213 if (rn == top)
11214 return;
d62a17ae 11215
9c14ec72
RW
11216 if (!bgp_node_has_bgp_path_info_data(rn))
11217 return;
d62a17ae 11218
b54892e0 11219 rn_p = bgp_node_get_prefix(rn);
9c14ec72 11220 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 11221 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 11222
a636c635
DW
11223#if 0
11224 ts->counts[BGP_STATS_AVGPLEN]
11225 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
11226 ts->counts[BGP_STATS_AVGPLEN],
b54892e0 11227 rn_p->prefixlen);
a636c635 11228#endif
d62a17ae 11229
9c14ec72
RW
11230 /* check if the prefix is included by any other announcements */
11231 while (prn && !bgp_node_has_bgp_path_info_data(prn))
11232 prn = bgp_node_parent_nolock(prn);
d62a17ae 11233
9c14ec72
RW
11234 if (prn == NULL || prn == top) {
11235 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
11236 /* announced address space */
11237 if (space)
b54892e0 11238 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9c14ec72
RW
11239 } else if (bgp_node_has_bgp_path_info_data(prn))
11240 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 11241
9c14ec72
RW
11242
11243 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
11244 ts->counts[BGP_STATS_RIB]++;
11245
05864da7
DS
11246 if (CHECK_FLAG(pi->attr->flag,
11247 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
11248 ts->counts[BGP_STATS_AGGREGATES]++;
11249
11250 /* as-path stats */
05864da7 11251 if (pi->attr->aspath) {
9c14ec72
RW
11252 unsigned int hops = aspath_count_hops(pi->attr->aspath);
11253 unsigned int size = aspath_size(pi->attr->aspath);
11254 as_t highest = aspath_highest(pi->attr->aspath);
11255
11256 ts->counts[BGP_STATS_ASPATH_COUNT]++;
11257
11258 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
11259 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
11260
11261 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
11262 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
11263
11264 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
11265 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 11266#if 0
07d0c4ed 11267 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
11268 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
11269 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
11270 hops);
11271 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
11272 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
11273 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
11274 size);
11275#endif
9c14ec72
RW
11276 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
11277 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
11278 }
11279 }
11280}
11281
11282static int bgp_table_stats_walker(struct thread *t)
11283{
11284 struct bgp_node *rn, *nrn;
11285 struct bgp_node *top;
11286 struct bgp_table_stats *ts = THREAD_ARG(t);
11287 unsigned int space = 0;
11288
11289 if (!(top = bgp_table_top(ts->table)))
11290 return 0;
11291
11292 switch (ts->table->afi) {
11293 case AFI_IP:
11294 space = IPV4_MAX_BITLEN;
11295 break;
11296 case AFI_IP6:
11297 space = IPV6_MAX_BITLEN;
11298 break;
11299 default:
11300 return 0;
11301 }
11302
11303 ts->counts[BGP_STATS_MAXBITLEN] = space;
11304
11305 for (rn = top; rn; rn = bgp_route_next(rn)) {
9ab0cf58
PG
11306 if (ts->table->safi == SAFI_MPLS_VPN
11307 || ts->table->safi == SAFI_ENCAP
11308 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
11309 struct bgp_table *table;
11310
11311 table = bgp_node_get_bgp_table_info(rn);
11312 if (!table)
11313 continue;
11314
11315 top = bgp_table_top(table);
11316 for (nrn = bgp_table_top(table); nrn;
11317 nrn = bgp_route_next(nrn))
11318 bgp_table_stats_rn(nrn, top, ts, space);
11319 } else {
11320 bgp_table_stats_rn(rn, top, ts, space);
d62a17ae 11321 }
11322 }
9c14ec72 11323
d62a17ae 11324 return 0;
2815e61f 11325}
ff7924f6 11326
d62a17ae 11327static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
6c9d22e2 11328 safi_t safi, struct json_object *json_array)
2815e61f 11329{
d62a17ae 11330 struct bgp_table_stats ts;
11331 unsigned int i;
893cccd0
PG
11332 int ret = CMD_SUCCESS;
11333 char temp_buf[20];
6c9d22e2
PG
11334 struct json_object *json = NULL;
11335
11336 if (json_array)
11337 json = json_object_new_object();
019386c2 11338
d62a17ae 11339 if (!bgp->rib[afi][safi]) {
893cccd0
PG
11340 char warning_msg[50];
11341
11342 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
11343 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
11344 safi);
6c9d22e2
PG
11345
11346 if (!json)
893cccd0
PG
11347 vty_out(vty, "%s\n", warning_msg);
11348 else
9ab0cf58 11349 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 11350
893cccd0
PG
11351 ret = CMD_WARNING;
11352 goto end_table_stats;
d62a17ae 11353 }
019386c2 11354
893cccd0
PG
11355 if (!json)
11356 vty_out(vty, "BGP %s RIB statistics\n",
11357 get_afi_safi_str(afi, safi, false));
019386c2 11358
d62a17ae 11359 /* labeled-unicast routes live in the unicast table */
11360 if (safi == SAFI_LABELED_UNICAST)
11361 safi = SAFI_UNICAST;
019386c2 11362
d62a17ae 11363 memset(&ts, 0, sizeof(ts));
11364 ts.table = bgp->rib[afi][safi];
11365 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 11366
d62a17ae 11367 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
11368 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
11369 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 11370 continue;
11371
11372 switch (i) {
a636c635
DW
11373#if 0
11374 case BGP_STATS_ASPATH_AVGHOPS:
11375 case BGP_STATS_ASPATH_AVGSIZE:
11376 case BGP_STATS_AVGPLEN:
11377 vty_out (vty, "%-30s: ", table_stats_strs[i]);
11378 vty_out (vty, "%12.2f",
11379 (float)ts.counts[i] / (float)TALLY_SIGFIG);
11380 break;
11381#endif
d62a17ae 11382 case BGP_STATS_ASPATH_TOTHOPS:
11383 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 11384 if (!json) {
9ab0cf58
PG
11385 snprintf(
11386 temp_buf, sizeof(temp_buf), "%12.2f",
11387 ts.counts[i]
11388 ? (float)ts.counts[i]
11389 / (float)ts.counts
11390 [BGP_STATS_ASPATH_COUNT]
11391 : 0);
893cccd0 11392 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
11393 table_stats_strs[i]
11394 [TABLE_STATS_IDX_VTY],
893cccd0 11395 temp_buf);
9ab0cf58
PG
11396 } else {
11397 json_object_double_add(
11398 json,
11399 table_stats_strs[i]
11400 [TABLE_STATS_IDX_JSON],
11401 ts.counts[i]
11402 ? (double)ts.counts[i]
11403 / (double)ts.counts
d62a17ae 11404 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
11405 : 0);
11406 }
d62a17ae 11407 break;
11408 case BGP_STATS_TOTPLEN:
6c9d22e2 11409 if (!json) {
9ab0cf58
PG
11410 snprintf(
11411 temp_buf, sizeof(temp_buf), "%12.2f",
11412 ts.counts[i]
11413 ? (float)ts.counts[i]
11414 / (float)ts.counts
11415 [BGP_STATS_PREFIXES]
11416 : 0);
893cccd0 11417 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
11418 table_stats_strs[i]
11419 [TABLE_STATS_IDX_VTY],
893cccd0 11420 temp_buf);
9ab0cf58
PG
11421 } else {
11422 json_object_double_add(
11423 json,
11424 table_stats_strs[i]
11425 [TABLE_STATS_IDX_JSON],
11426 ts.counts[i]
11427 ? (double)ts.counts[i]
11428 / (double)ts.counts
d62a17ae 11429 [BGP_STATS_PREFIXES]
9ab0cf58
PG
11430 : 0);
11431 }
d62a17ae 11432 break;
11433 case BGP_STATS_SPACE:
6c9d22e2
PG
11434 if (!json) {
11435 snprintf(temp_buf, sizeof(temp_buf), "%12g",
11436 ts.total_space);
893cccd0 11437 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
11438 table_stats_strs[i]
11439 [TABLE_STATS_IDX_VTY],
893cccd0 11440 temp_buf);
9ab0cf58
PG
11441 } else {
11442 json_object_double_add(
11443 json,
11444 table_stats_strs[i]
11445 [TABLE_STATS_IDX_JSON],
11446 (double)ts.total_space);
11447 }
8d0ab76d 11448 if (afi == AFI_IP6) {
6c9d22e2
PG
11449 if (!json) {
11450 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
11451 "%12g",
11452 ts.total_space
11453 * pow(2.0, -128 + 32));
6c9d22e2
PG
11454 vty_out(vty, "%30s: %s\n",
11455 "/32 equivalent %s\n",
11456 temp_buf);
9ab0cf58
PG
11457 } else {
11458 json_object_double_add(
11459 json, "/32equivalent",
11460 (double)(ts.total_space
11461 * pow(2.0,
11462 -128 + 32)));
11463 }
6c9d22e2
PG
11464 if (!json) {
11465 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
11466 "%12g",
11467 ts.total_space
11468 * pow(2.0, -128 + 48));
6c9d22e2
PG
11469 vty_out(vty, "%30s: %s\n",
11470 "/48 equivalent %s\n",
11471 temp_buf);
9ab0cf58
PG
11472 } else {
11473 json_object_double_add(
11474 json, "/48equivalent",
11475 (double)(ts.total_space
11476 * pow(2.0,
11477 -128 + 48)));
11478 }
8d0ab76d 11479 } else {
6c9d22e2
PG
11480 if (!json) {
11481 snprintf(temp_buf, sizeof(temp_buf),
11482 "%12.2f",
9ab0cf58
PG
11483 ts.total_space * 100.
11484 * pow(2.0, -32));
6c9d22e2 11485 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
11486 "% announced ", temp_buf);
11487 } else {
11488 json_object_double_add(
11489 json, "%announced",
11490 (double)(ts.total_space * 100.
11491 * pow(2.0, -32)));
11492 }
6c9d22e2
PG
11493 if (!json) {
11494 snprintf(temp_buf, sizeof(temp_buf),
11495 "%12.2f",
9ab0cf58
PG
11496 ts.total_space
11497 * pow(2.0, -32 + 8));
6c9d22e2
PG
11498 vty_out(vty, "%30s: %s\n",
11499 "/8 equivalent ", temp_buf);
9ab0cf58
PG
11500 } else {
11501 json_object_double_add(
11502 json, "/8equivalent",
11503 (double)(ts.total_space
11504 * pow(2.0, -32 + 8)));
11505 }
6c9d22e2
PG
11506 if (!json) {
11507 snprintf(temp_buf, sizeof(temp_buf),
11508 "%12.2f",
9ab0cf58
PG
11509 ts.total_space
11510 * pow(2.0, -32 + 24));
6c9d22e2 11511 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
11512 "/24 equivalent ", temp_buf);
11513 } else {
11514 json_object_double_add(
11515 json, "/24equivalent",
11516 (double)(ts.total_space
11517 * pow(2.0, -32 + 24)));
11518 }
8d0ab76d 11519 }
d62a17ae 11520 break;
11521 default:
6c9d22e2
PG
11522 if (!json) {
11523 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
11524 ts.counts[i]);
893cccd0 11525 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
11526 table_stats_strs[i]
11527 [TABLE_STATS_IDX_VTY],
11528 temp_buf);
11529 } else {
11530 json_object_int_add(
11531 json,
11532 table_stats_strs[i]
11533 [TABLE_STATS_IDX_JSON],
11534 ts.counts[i]);
11535 }
d62a17ae 11536 }
893cccd0
PG
11537 if (!json)
11538 vty_out(vty, "\n");
d62a17ae 11539 }
9ab0cf58 11540end_table_stats:
6c9d22e2
PG
11541 if (json)
11542 json_object_array_add(json_array, json);
893cccd0 11543 return ret;
d62a17ae 11544}
11545
11546enum bgp_pcounts {
11547 PCOUNT_ADJ_IN = 0,
11548 PCOUNT_DAMPED,
11549 PCOUNT_REMOVED,
11550 PCOUNT_HISTORY,
11551 PCOUNT_STALE,
11552 PCOUNT_VALID,
11553 PCOUNT_ALL,
11554 PCOUNT_COUNTED,
11555 PCOUNT_PFCNT, /* the figure we display to users */
11556 PCOUNT_MAX,
a636c635 11557};
718e3744 11558
2b64873d 11559static const char *const pcount_strs[] = {
9d303b37
DL
11560 [PCOUNT_ADJ_IN] = "Adj-in",
11561 [PCOUNT_DAMPED] = "Damped",
11562 [PCOUNT_REMOVED] = "Removed",
11563 [PCOUNT_HISTORY] = "History",
11564 [PCOUNT_STALE] = "Stale",
11565 [PCOUNT_VALID] = "Valid",
11566 [PCOUNT_ALL] = "All RIB",
11567 [PCOUNT_COUNTED] = "PfxCt counted",
11568 [PCOUNT_PFCNT] = "Useable",
11569 [PCOUNT_MAX] = NULL,
a636c635 11570};
718e3744 11571
d62a17ae 11572struct peer_pcounts {
11573 unsigned int count[PCOUNT_MAX];
11574 const struct peer *peer;
11575 const struct bgp_table *table;
54317cba 11576 safi_t safi;
a636c635 11577};
47fc97cc 11578
54317cba
JW
11579static void bgp_peer_count_proc(struct bgp_node *rn,
11580 struct peer_pcounts *pc)
d62a17ae 11581{
54317cba
JW
11582 const struct bgp_adj_in *ain;
11583 const struct bgp_path_info *pi;
d62a17ae 11584 const struct peer *peer = pc->peer;
11585
54317cba
JW
11586 for (ain = rn->adj_in; ain; ain = ain->next)
11587 if (ain->peer == peer)
11588 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 11589
54317cba 11590 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 11591
54317cba
JW
11592 if (pi->peer != peer)
11593 continue;
d62a17ae 11594
54317cba 11595 pc->count[PCOUNT_ALL]++;
d62a17ae 11596
54317cba
JW
11597 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
11598 pc->count[PCOUNT_DAMPED]++;
11599 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
11600 pc->count[PCOUNT_HISTORY]++;
11601 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
11602 pc->count[PCOUNT_REMOVED]++;
11603 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
11604 pc->count[PCOUNT_STALE]++;
11605 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
11606 pc->count[PCOUNT_VALID]++;
11607 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
11608 pc->count[PCOUNT_PFCNT]++;
11609
11610 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
11611 pc->count[PCOUNT_COUNTED]++;
11612 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
11613 flog_err(
11614 EC_LIB_DEVELOPMENT,
11615 "Attempting to count but flags say it is unusable");
11616 } else {
40381db7 11617 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
11618 flog_err(
11619 EC_LIB_DEVELOPMENT,
11620 "Not counted but flags say we should");
d62a17ae 11621 }
11622 }
54317cba
JW
11623}
11624
11625static int bgp_peer_count_walker(struct thread *t)
11626{
11627 struct bgp_node *rn, *rm;
11628 const struct bgp_table *table;
11629 struct peer_pcounts *pc = THREAD_ARG(t);
11630
11631 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
11632 || pc->safi == SAFI_EVPN) {
11633 /* Special handling for 2-level routing tables. */
11634 for (rn = bgp_table_top(pc->table); rn;
11635 rn = bgp_route_next(rn)) {
11636 table = bgp_node_get_bgp_table_info(rn);
11637 if (table != NULL)
11638 for (rm = bgp_table_top(table); rm;
11639 rm = bgp_route_next(rm))
11640 bgp_peer_count_proc(rm, pc);
11641 }
11642 } else
11643 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
11644 bgp_peer_count_proc(rn, pc);
11645
d62a17ae 11646 return 0;
718e3744 11647}
11648
d62a17ae 11649static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 11650 safi_t safi, bool use_json)
856ca177 11651{
d62a17ae 11652 struct peer_pcounts pcounts = {.peer = peer};
11653 unsigned int i;
11654 json_object *json = NULL;
11655 json_object *json_loop = NULL;
856ca177 11656
d62a17ae 11657 if (use_json) {
11658 json = json_object_new_object();
11659 json_loop = json_object_new_object();
11660 }
718e3744 11661
d62a17ae 11662 if (!peer || !peer->bgp || !peer->afc[afi][safi]
11663 || !peer->bgp->rib[afi][safi]) {
11664 if (use_json) {
11665 json_object_string_add(
11666 json, "warning",
11667 "No such neighbor or address family");
11668 vty_out(vty, "%s\n", json_object_to_json_string(json));
11669 json_object_free(json);
11670 } else
11671 vty_out(vty, "%% No such neighbor or address family\n");
11672
11673 return CMD_WARNING;
11674 }
2a71e9ce 11675
d62a17ae 11676 memset(&pcounts, 0, sizeof(pcounts));
11677 pcounts.peer = peer;
11678 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 11679 pcounts.safi = safi;
d62a17ae 11680
11681 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
11682 * stats for the thread-walk (i.e. ensure this can't be blamed on
11683 * on just vty_read()).
11684 */
d62a17ae 11685 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
11686
11687 if (use_json) {
11688 json_object_string_add(json, "prefixCountsFor", peer->host);
11689 json_object_string_add(json, "multiProtocol",
5cb5f4d0 11690 get_afi_safi_str(afi, safi, true));
d62a17ae 11691 json_object_int_add(json, "pfxCounter",
11692 peer->pcount[afi][safi]);
11693
11694 for (i = 0; i < PCOUNT_MAX; i++)
11695 json_object_int_add(json_loop, pcount_strs[i],
11696 pcounts.count[i]);
11697
11698 json_object_object_add(json, "ribTableWalkCounters", json_loop);
11699
11700 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
11701 json_object_string_add(json, "pfxctDriftFor",
11702 peer->host);
11703 json_object_string_add(
11704 json, "recommended",
11705 "Please report this bug, with the above command output");
11706 }
996c9314
LB
11707 vty_out(vty, "%s\n", json_object_to_json_string_ext(
11708 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 11709 json_object_free(json);
11710 } else {
11711
11712 if (peer->hostname
892fedb6 11713 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 11714 vty_out(vty, "Prefix counts for %s/%s, %s\n",
11715 peer->hostname, peer->host,
5cb5f4d0 11716 get_afi_safi_str(afi, safi, false));
d62a17ae 11717 } else {
11718 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 11719 get_afi_safi_str(afi, safi, false));
d62a17ae 11720 }
11721
a0a87037 11722 vty_out(vty, "PfxCt: %" PRIu32 "\n", peer->pcount[afi][safi]);
d62a17ae 11723 vty_out(vty, "\nCounts from RIB table walk:\n\n");
11724
11725 for (i = 0; i < PCOUNT_MAX; i++)
11726 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
11727 pcounts.count[i]);
11728
11729 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
11730 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
11731 vty_out(vty,
11732 "Please report this bug, with the above command output\n");
11733 }
11734 }
11735
11736 return CMD_SUCCESS;
718e3744 11737}
11738
a636c635
DW
11739DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
11740 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
c1a44e43 11741 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] "
30a6a167 11742 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
718e3744 11743 SHOW_STR
11744 IP_STR
11745 BGP_STR
8386ac43 11746 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
11747 BGP_AFI_HELP_STR
11748 BGP_SAFI_HELP_STR
0b16f239
DS
11749 "Detailed information on TCP and BGP neighbor connections\n"
11750 "Neighbor to display information about\n"
11751 "Neighbor to display information about\n"
91d37724 11752 "Neighbor on BGP configured interface\n"
a636c635 11753 "Display detailed prefix count information\n"
9973d184 11754 JSON_STR)
0b16f239 11755{
d62a17ae 11756 afi_t afi = AFI_IP6;
11757 safi_t safi = SAFI_UNICAST;
11758 struct peer *peer;
11759 int idx = 0;
11760 struct bgp *bgp = NULL;
9f049418
DS
11761 bool uj = use_json(argc, argv);
11762
11763 if (uj)
11764 argc--;
856ca177 11765
d62a17ae 11766 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11767 &bgp, uj);
d62a17ae 11768 if (!idx)
11769 return CMD_WARNING;
0b16f239 11770
d62a17ae 11771 argv_find(argv, argc, "neighbors", &idx);
11772 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
11773 if (!peer)
11774 return CMD_WARNING;
bb46e94f 11775
29c8d9da 11776 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 11777}
0b16f239 11778
d6902373
PG
11779#ifdef KEEP_OLD_VPN_COMMANDS
11780DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
11781 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
11782 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
11783 SHOW_STR
11784 IP_STR
11785 BGP_STR
d6902373 11786 BGP_VPNVX_HELP_STR
91d37724 11787 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
11788 "Detailed information on TCP and BGP neighbor connections\n"
11789 "Neighbor to display information about\n"
11790 "Neighbor to display information about\n"
91d37724 11791 "Neighbor on BGP configured interface\n"
a636c635 11792 "Display detailed prefix count information\n"
9973d184 11793 JSON_STR)
a636c635 11794{
d62a17ae 11795 int idx_peer = 6;
11796 struct peer *peer;
9f049418 11797 bool uj = use_json(argc, argv);
a636c635 11798
d62a17ae 11799 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
11800 if (!peer)
11801 return CMD_WARNING;
11802
11803 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
11804}
11805
d6902373
PG
11806DEFUN (show_ip_bgp_vpn_all_route_prefix,
11807 show_ip_bgp_vpn_all_route_prefix_cmd,
11808 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
11809 SHOW_STR
11810 IP_STR
11811 BGP_STR
d6902373 11812 BGP_VPNVX_HELP_STR
91d37724
QY
11813 "Display information about all VPNv4 NLRIs\n"
11814 "Network in the BGP routing table to display\n"
3a2d747c 11815 "Network in the BGP routing table to display\n"
9973d184 11816 JSON_STR)
91d37724 11817{
d62a17ae 11818 int idx = 0;
11819 char *network = NULL;
11820 struct bgp *bgp = bgp_get_default();
11821 if (!bgp) {
11822 vty_out(vty, "Can't find default instance\n");
11823 return CMD_WARNING;
11824 }
87e34b58 11825
d62a17ae 11826 if (argv_find(argv, argc, "A.B.C.D", &idx))
11827 network = argv[idx]->arg;
11828 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
11829 network = argv[idx]->arg;
11830 else {
11831 vty_out(vty, "Unable to figure out Network\n");
11832 return CMD_WARNING;
11833 }
87e34b58 11834
d62a17ae 11835 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 11836 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 11837}
d6902373 11838#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 11839
44c69747
LK
11840DEFUN (show_bgp_l2vpn_evpn_route_prefix,
11841 show_bgp_l2vpn_evpn_route_prefix_cmd,
11842 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 11843 SHOW_STR
4c63a661
PG
11844 BGP_STR
11845 L2VPN_HELP_STR
11846 EVPN_HELP_STR
44c69747
LK
11847 "Network in the BGP routing table to display\n"
11848 "Network in the BGP routing table to display\n"
4c63a661
PG
11849 "Network in the BGP routing table to display\n"
11850 "Network in the BGP routing table to display\n"
11851 JSON_STR)
11852{
d62a17ae 11853 int idx = 0;
11854 char *network = NULL;
44c69747 11855 int prefix_check = 0;
a636c635 11856
44c69747
LK
11857 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
11858 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 11859 network = argv[idx]->arg;
44c69747 11860 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 11861 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 11862 network = argv[idx]->arg;
44c69747
LK
11863 prefix_check = 1;
11864 } else {
d62a17ae 11865 vty_out(vty, "Unable to figure out Network\n");
11866 return CMD_WARNING;
11867 }
44c69747
LK
11868 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
11869 prefix_check, BGP_PATH_SHOW_ALL,
11870 use_json(argc, argv));
d62a17ae 11871}
11872
11873static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 11874 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 11875 const char *rmap_name, bool use_json,
6392aaa6 11876 json_object *json)
d62a17ae 11877{
11878 struct bgp_table *table;
11879 struct bgp_adj_in *ain;
11880 struct bgp_adj_out *adj;
74a630b6
NT
11881 unsigned long output_count = 0;
11882 unsigned long filtered_count = 0;
d62a17ae 11883 struct bgp_node *rn;
11884 int header1 = 1;
11885 struct bgp *bgp;
11886 int header2 = 1;
11887 struct attr attr;
11888 int ret;
11889 struct update_subgroup *subgrp;
11890 json_object *json_scode = NULL;
11891 json_object *json_ocode = NULL;
11892 json_object *json_ar = NULL;
11893 struct peer_af *paf;
f99def61 11894 bool route_filtered;
d62a17ae 11895
11896 if (use_json) {
11897 json_scode = json_object_new_object();
11898 json_ocode = json_object_new_object();
11899 json_ar = json_object_new_object();
11900
11901 json_object_string_add(json_scode, "suppressed", "s");
11902 json_object_string_add(json_scode, "damped", "d");
11903 json_object_string_add(json_scode, "history", "h");
11904 json_object_string_add(json_scode, "valid", "*");
11905 json_object_string_add(json_scode, "best", ">");
11906 json_object_string_add(json_scode, "multipath", "=");
11907 json_object_string_add(json_scode, "internal", "i");
11908 json_object_string_add(json_scode, "ribFailure", "r");
11909 json_object_string_add(json_scode, "stale", "S");
11910 json_object_string_add(json_scode, "removed", "R");
11911
11912 json_object_string_add(json_ocode, "igp", "i");
11913 json_object_string_add(json_ocode, "egp", "e");
11914 json_object_string_add(json_ocode, "incomplete", "?");
11915 }
a636c635 11916
d62a17ae 11917 bgp = peer->bgp;
a636c635 11918
d62a17ae 11919 if (!bgp) {
11920 if (use_json) {
11921 json_object_string_add(json, "alert", "no BGP");
11922 vty_out(vty, "%s\n", json_object_to_json_string(json));
11923 json_object_free(json);
11924 } else
11925 vty_out(vty, "%% No bgp\n");
11926 return;
11927 }
a636c635 11928
c512a642
EDP
11929 /* labeled-unicast routes live in the unicast table */
11930 if (safi == SAFI_LABELED_UNICAST)
11931 table = bgp->rib[afi][SAFI_UNICAST];
11932 else
11933 table = bgp->rib[afi][safi];
d62a17ae 11934
11935 output_count = filtered_count = 0;
11936 subgrp = peer_subgroup(peer, afi, safi);
11937
6392aaa6 11938 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 11939 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
11940 if (use_json) {
11941 json_object_int_add(json, "bgpTableVersion",
11942 table->version);
11943 json_object_string_add(json, "bgpLocalRouterId",
11944 inet_ntoa(bgp->router_id));
01eced22
AD
11945 json_object_int_add(json, "defaultLocPrf",
11946 bgp->default_local_pref);
11947 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 11948 json_object_object_add(json, "bgpStatusCodes",
11949 json_scode);
11950 json_object_object_add(json, "bgpOriginCodes",
11951 json_ocode);
07d0c4ed
DA
11952 json_object_string_add(
11953 json, "bgpOriginatingDefaultNetwork",
11954 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 11955 } else {
996c9314 11956 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 11957 ", local router ID is %s, vrf id ",
d62a17ae 11958 table->version, inet_ntoa(bgp->router_id));
9df8b37c
PZ
11959 if (bgp->vrf_id == VRF_UNKNOWN)
11960 vty_out(vty, "%s", VRFID_NONE_STR);
11961 else
11962 vty_out(vty, "%u", bgp->vrf_id);
11963 vty_out(vty, "\n");
01eced22
AD
11964 vty_out(vty, "Default local pref %u, ",
11965 bgp->default_local_pref);
11966 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 11967 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11968 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 11969 vty_out(vty, BGP_SHOW_OCODE_HEADER);
11970
07d0c4ed
DA
11971 vty_out(vty, "Originating default network %s\n\n",
11972 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 11973 }
11974 header1 = 0;
11975 }
a636c635 11976
d62a17ae 11977 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6392aaa6
PM
11978 if (type == bgp_show_adj_route_received
11979 || type == bgp_show_adj_route_filtered) {
d62a17ae 11980 for (ain = rn->adj_in; ain; ain = ain->next) {
05864da7 11981 if (ain->peer != peer)
ea47320b 11982 continue;
6392aaa6 11983
ea47320b
DL
11984 if (header1) {
11985 if (use_json) {
11986 json_object_int_add(
60466a63 11987 json, "bgpTableVersion",
ea47320b
DL
11988 0);
11989 json_object_string_add(
11990 json,
11991 "bgpLocalRouterId",
11992 inet_ntoa(
11993 bgp->router_id));
01eced22
AD
11994 json_object_int_add(json,
11995 "defaultLocPrf",
11996 bgp->default_local_pref);
11997 json_object_int_add(json,
11998 "localAS", bgp->as);
ea47320b 11999 json_object_object_add(
60466a63 12000 json, "bgpStatusCodes",
ea47320b
DL
12001 json_scode);
12002 json_object_object_add(
60466a63 12003 json, "bgpOriginCodes",
ea47320b
DL
12004 json_ocode);
12005 } else {
12006 vty_out(vty,
9df8b37c 12007 "BGP table version is 0, local router ID is %s, vrf id ",
ea47320b 12008 inet_ntoa(
9df8b37c
PZ
12009 bgp->router_id));
12010 if (bgp->vrf_id == VRF_UNKNOWN)
12011 vty_out(vty, "%s",
12012 VRFID_NONE_STR);
12013 else
12014 vty_out(vty, "%u",
12015 bgp->vrf_id);
12016 vty_out(vty, "\n");
01eced22
AD
12017 vty_out(vty,
12018 "Default local pref %u, ",
12019 bgp->default_local_pref);
12020 vty_out(vty, "local AS %u\n",
12021 bgp->as);
ea47320b
DL
12022 vty_out(vty,
12023 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
12024 vty_out(vty,
12025 BGP_SHOW_NCODE_HEADER);
ea47320b
DL
12026 vty_out(vty,
12027 BGP_SHOW_OCODE_HEADER);
d62a17ae 12028 }
ea47320b
DL
12029 header1 = 0;
12030 }
12031 if (header2) {
12032 if (!use_json)
12033 vty_out(vty, BGP_SHOW_HEADER);
12034 header2 = 0;
12035 }
6392aaa6 12036
6f4f49b2 12037 attr = *ain->attr;
f99def61
AD
12038 route_filtered = false;
12039
12040 /* Filter prefix using distribute list,
12041 * filter list or prefix list
12042 */
b54892e0
DS
12043 const struct prefix *rn_p =
12044 bgp_node_get_prefix(rn);
12045 if ((bgp_input_filter(peer, rn_p, &attr, afi,
12046 safi))
12047 == FILTER_DENY)
f99def61
AD
12048 route_filtered = true;
12049
12050 /* Filter prefix using route-map */
b54892e0
DS
12051 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
12052 safi, rmap_name, NULL,
12053 0, NULL);
6392aaa6 12054
13c8e163
AD
12055 if (type == bgp_show_adj_route_filtered &&
12056 !route_filtered && ret != RMAP_DENY) {
b755861b 12057 bgp_attr_undup(&attr, ain->attr);
6392aaa6 12058 continue;
d62a17ae 12059 }
6392aaa6 12060
13c8e163
AD
12061 if (type == bgp_show_adj_route_received &&
12062 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
12063 filtered_count++;
12064
b54892e0 12065 route_vty_out_tmp(vty, rn_p, &attr, safi,
6392aaa6 12066 use_json, json_ar);
b755861b 12067 bgp_attr_undup(&attr, ain->attr);
6392aaa6 12068 output_count++;
d62a17ae 12069 }
6392aaa6 12070 } else if (type == bgp_show_adj_route_advertised) {
a79c04e7 12071 RB_FOREACH (adj, bgp_adj_out_rb, &rn->adj_out)
924c3f6a 12072 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 12073 if (paf->peer != peer || !adj->attr)
924c3f6a 12074 continue;
d62a17ae 12075
924c3f6a
DS
12076 if (header1) {
12077 if (use_json) {
12078 json_object_int_add(
12079 json,
12080 "bgpTableVersion",
12081 table->version);
12082 json_object_string_add(
12083 json,
12084 "bgpLocalRouterId",
12085 inet_ntoa(
12086 bgp->router_id));
01eced22
AD
12087 json_object_int_add(
12088 json, "defaultLocPrf",
12089 bgp->default_local_pref
12090 );
12091 json_object_int_add(
12092 json, "localAS",
12093 bgp->as);
924c3f6a
DS
12094 json_object_object_add(
12095 json,
12096 "bgpStatusCodes",
12097 json_scode);
12098 json_object_object_add(
12099 json,
12100 "bgpOriginCodes",
12101 json_ocode);
12102 } else {
12103 vty_out(vty,
12104 "BGP table version is %" PRIu64
9df8b37c 12105 ", local router ID is %s, vrf id ",
924c3f6a
DS
12106 table->version,
12107 inet_ntoa(
12108 bgp->router_id));
9df8b37c
PZ
12109 if (bgp->vrf_id ==
12110 VRF_UNKNOWN)
12111 vty_out(vty,
12112 "%s",
12113 VRFID_NONE_STR);
12114 else
12115 vty_out(vty,
12116 "%u",
12117 bgp->vrf_id);
12118 vty_out(vty, "\n");
01eced22
AD
12119 vty_out(vty,
12120 "Default local pref %u, ",
12121 bgp->default_local_pref
12122 );
12123 vty_out(vty,
12124 "local AS %u\n",
12125 bgp->as);
924c3f6a
DS
12126 vty_out(vty,
12127 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
12128 vty_out(vty,
12129 BGP_SHOW_NCODE_HEADER);
924c3f6a
DS
12130 vty_out(vty,
12131 BGP_SHOW_OCODE_HEADER);
a2addae8 12132 }
924c3f6a
DS
12133 header1 = 0;
12134 }
924c3f6a
DS
12135 if (header2) {
12136 if (!use_json)
12137 vty_out(vty,
12138 BGP_SHOW_HEADER);
12139 header2 = 0;
12140 }
d62a17ae 12141
b54892e0
DS
12142 const struct prefix *rn_p =
12143 bgp_node_get_prefix(rn);
12144
6f4f49b2 12145 attr = *adj->attr;
b755861b 12146 ret = bgp_output_modifier(
b54892e0 12147 peer, rn_p, &attr, afi, safi,
b755861b 12148 rmap_name);
f46d8e1e 12149
b755861b 12150 if (ret != RMAP_DENY) {
b54892e0
DS
12151 route_vty_out_tmp(
12152 vty, rn_p, &attr, safi,
12153 use_json, json_ar);
b755861b
PM
12154 output_count++;
12155 } else {
12156 filtered_count++;
a2addae8 12157 }
b755861b
PM
12158
12159 bgp_attr_undup(&attr, adj->attr);
924c3f6a 12160 }
d62a17ae 12161 }
12162 }
d62a17ae 12163
d62a17ae 12164 if (use_json) {
6392aaa6
PM
12165 json_object_object_add(json, "advertisedRoutes", json_ar);
12166 json_object_int_add(json, "totalPrefixCounter", output_count);
12167 json_object_int_add(json, "filteredPrefixCounter",
12168 filtered_count);
12169
996c9314
LB
12170 vty_out(vty, "%s\n", json_object_to_json_string_ext(
12171 json, JSON_C_TO_STRING_PRETTY));
74a630b6
NT
12172
12173 if (!output_count && !filtered_count) {
12174 json_object_free(json_scode);
12175 json_object_free(json_ocode);
12176 }
12177
d62a17ae 12178 json_object_free(json);
6392aaa6
PM
12179 } else if (output_count > 0) {
12180 if (filtered_count > 0)
12181 vty_out(vty,
12182 "\nTotal number of prefixes %ld (%ld filtered)\n",
12183 output_count, filtered_count);
12184 else
12185 vty_out(vty, "\nTotal number of prefixes %ld\n",
12186 output_count);
d62a17ae 12187 }
a636c635 12188}
2a71e9ce 12189
d62a17ae 12190static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 12191 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 12192 const char *rmap_name, bool use_json)
0b16f239 12193{
d62a17ae 12194 json_object *json = NULL;
0b16f239 12195
d62a17ae 12196 if (use_json)
12197 json = json_object_new_object();
0b16f239 12198
d62a17ae 12199 if (!peer || !peer->afc[afi][safi]) {
12200 if (use_json) {
12201 json_object_string_add(
12202 json, "warning",
12203 "No such neighbor or address family");
12204 vty_out(vty, "%s\n", json_object_to_json_string(json));
12205 json_object_free(json);
12206 } else
12207 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 12208
d62a17ae 12209 return CMD_WARNING;
12210 }
12211
6392aaa6
PM
12212 if ((type == bgp_show_adj_route_received
12213 || type == bgp_show_adj_route_filtered)
d62a17ae 12214 && !CHECK_FLAG(peer->af_flags[afi][safi],
12215 PEER_FLAG_SOFT_RECONFIG)) {
12216 if (use_json) {
12217 json_object_string_add(
12218 json, "warning",
12219 "Inbound soft reconfiguration not enabled");
12220 vty_out(vty, "%s\n", json_object_to_json_string(json));
12221 json_object_free(json);
12222 } else
12223 vty_out(vty,
12224 "%% Inbound soft reconfiguration not enabled\n");
12225
12226 return CMD_WARNING;
12227 }
0b16f239 12228
6392aaa6 12229 show_adj_route(vty, peer, afi, safi, type, rmap_name, use_json, json);
0b16f239 12230
d62a17ae 12231 return CMD_SUCCESS;
a636c635 12232}
50ef26d4 12233
a636c635
DW
12234DEFUN (show_ip_bgp_instance_neighbor_advertised_route,
12235 show_ip_bgp_instance_neighbor_advertised_route_cmd,
4dd6177e 12236 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
6392aaa6 12237 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
718e3744 12238 SHOW_STR
12239 IP_STR
12240 BGP_STR
a636c635 12241 BGP_INSTANCE_HELP_STR
7395a2c9 12242 BGP_AFI_HELP_STR
4dd6177e 12243 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 12244 "Detailed information on TCP and BGP neighbor connections\n"
12245 "Neighbor to display information about\n"
12246 "Neighbor to display information about\n"
91d37724 12247 "Neighbor on BGP configured interface\n"
a636c635 12248 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
12249 "Display the received routes from neighbor\n"
12250 "Display the filtered routes received from neighbor\n"
a636c635
DW
12251 "Route-map to modify the attributes\n"
12252 "Name of the route map\n"
9973d184 12253 JSON_STR)
718e3744 12254{
d62a17ae 12255 afi_t afi = AFI_IP6;
12256 safi_t safi = SAFI_UNICAST;
12257 char *rmap_name = NULL;
12258 char *peerstr = NULL;
d62a17ae 12259 struct bgp *bgp = NULL;
12260 struct peer *peer;
6392aaa6 12261 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 12262 int idx = 0;
9f049418 12263 bool uj = use_json(argc, argv);
6392aaa6 12264
d62a17ae 12265 if (uj)
12266 argc--;
30a6a167 12267
9f049418
DS
12268 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12269 &bgp, uj);
12270 if (!idx)
12271 return CMD_WARNING;
12272
d62a17ae 12273 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12274 argv_find(argv, argc, "neighbors", &idx);
12275 peerstr = argv[++idx]->arg;
8c3deaae 12276
d62a17ae 12277 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
12278 if (!peer)
12279 return CMD_WARNING;
856ca177 12280
d62a17ae 12281 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
12282 type = bgp_show_adj_route_advertised;
12283 else if (argv_find(argv, argc, "received-routes", &idx))
12284 type = bgp_show_adj_route_received;
12285 else if (argv_find(argv, argc, "filtered-routes", &idx))
12286 type = bgp_show_adj_route_filtered;
12287
d62a17ae 12288 if (argv_find(argv, argc, "route-map", &idx))
12289 rmap_name = argv[++idx]->arg;
95cbbd2a 12290
6392aaa6 12291 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj);
95cbbd2a
ML
12292}
12293
718e3744 12294DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
12295 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 12296 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 12297 SHOW_STR
12298 IP_STR
12299 BGP_STR
8c3deaae
QY
12300 "Address Family\n"
12301 "Address Family\n"
718e3744 12302 "Address Family modifier\n"
12303 "Detailed information on TCP and BGP neighbor connections\n"
12304 "Neighbor to display information about\n"
12305 "Neighbor to display information about\n"
91d37724 12306 "Neighbor on BGP configured interface\n"
718e3744 12307 "Display information received from a BGP neighbor\n"
856ca177 12308 "Display the prefixlist filter\n"
9973d184 12309 JSON_STR)
718e3744 12310{
d62a17ae 12311 afi_t afi = AFI_IP6;
12312 safi_t safi = SAFI_UNICAST;
12313 char *peerstr = NULL;
12314
12315 char name[BUFSIZ];
12316 union sockunion su;
12317 struct peer *peer;
12318 int count, ret;
12319
12320 int idx = 0;
12321
12322 /* show [ip] bgp */
12323 if (argv_find(argv, argc, "ip", &idx))
12324 afi = AFI_IP;
12325 /* [<ipv4|ipv6> [unicast]] */
12326 if (argv_find(argv, argc, "ipv4", &idx))
12327 afi = AFI_IP;
12328 if (argv_find(argv, argc, "ipv6", &idx))
12329 afi = AFI_IP6;
12330 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12331 argv_find(argv, argc, "neighbors", &idx);
12332 peerstr = argv[++idx]->arg;
12333
9f049418 12334 bool uj = use_json(argc, argv);
d62a17ae 12335
12336 ret = str2sockunion(peerstr, &su);
12337 if (ret < 0) {
12338 peer = peer_lookup_by_conf_if(NULL, peerstr);
12339 if (!peer) {
12340 if (uj)
12341 vty_out(vty, "{}\n");
12342 else
12343 vty_out(vty,
12344 "%% Malformed address or name: %s\n",
12345 peerstr);
12346 return CMD_WARNING;
12347 }
12348 } else {
12349 peer = peer_lookup(NULL, &su);
12350 if (!peer) {
12351 if (uj)
12352 vty_out(vty, "{}\n");
12353 else
12354 vty_out(vty, "No peer\n");
12355 return CMD_WARNING;
12356 }
12357 }
718e3744 12358
d62a17ae 12359 sprintf(name, "%s.%d.%d", peer->host, afi, safi);
12360 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
12361 if (count) {
12362 if (!uj)
12363 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 12364 get_afi_safi_str(afi, safi, false));
d62a17ae 12365 prefix_bgp_show_prefix_list(vty, afi, name, uj);
12366 } else {
12367 if (uj)
12368 vty_out(vty, "{}\n");
12369 else
12370 vty_out(vty, "No functional output\n");
12371 }
718e3744 12372
d62a17ae 12373 return CMD_SUCCESS;
12374}
12375
12376static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
12377 afi_t afi, safi_t safi,
9f049418 12378 enum bgp_show_type type, bool use_json)
d62a17ae 12379{
8a893163
DW
12380 /* labeled-unicast routes live in the unicast table */
12381 if (safi == SAFI_LABELED_UNICAST)
12382 safi = SAFI_UNICAST;
12383
d62a17ae 12384 if (!peer || !peer->afc[afi][safi]) {
12385 if (use_json) {
12386 json_object *json_no = NULL;
12387 json_no = json_object_new_object();
12388 json_object_string_add(
12389 json_no, "warning",
12390 "No such neighbor or address family");
12391 vty_out(vty, "%s\n",
12392 json_object_to_json_string(json_no));
12393 json_object_free(json_no);
12394 } else
12395 vty_out(vty, "%% No such neighbor or address family\n");
12396 return CMD_WARNING;
12397 }
47fc97cc 12398
d62a17ae 12399 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json);
718e3744 12400}
12401
dba3c1d3
PG
12402DEFUN (show_ip_bgp_flowspec_routes_detailed,
12403 show_ip_bgp_flowspec_routes_detailed_cmd,
12404 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
12405 SHOW_STR
12406 IP_STR
12407 BGP_STR
12408 BGP_INSTANCE_HELP_STR
12409 BGP_AFI_HELP_STR
12410 "SAFI Flowspec\n"
12411 "Detailed information on flowspec entries\n"
12412 JSON_STR)
12413{
12414 afi_t afi = AFI_IP;
12415 safi_t safi = SAFI_UNICAST;
12416 struct bgp *bgp = NULL;
12417 int idx = 0;
9f049418
DS
12418 bool uj = use_json(argc, argv);
12419
12420 if (uj)
12421 argc--;
dba3c1d3
PG
12422
12423 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12424 &bgp, uj);
dba3c1d3
PG
12425 if (!idx)
12426 return CMD_WARNING;
12427
9f049418 12428 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL, uj);
dba3c1d3
PG
12429}
12430
718e3744 12431DEFUN (show_ip_bgp_neighbor_routes,
12432 show_ip_bgp_neighbor_routes_cmd,
4dd6177e 12433 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
30a6a167 12434 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
50ef26d4 12435 SHOW_STR
12436 IP_STR
12437 BGP_STR
8386ac43 12438 BGP_INSTANCE_HELP_STR
4f280b15 12439 BGP_AFI_HELP_STR
4dd6177e 12440 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 12441 "Detailed information on TCP and BGP neighbor connections\n"
12442 "Neighbor to display information about\n"
12443 "Neighbor to display information about\n"
91d37724 12444 "Neighbor on BGP configured interface\n"
2525cf39 12445 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
12446 "Display the dampened routes received from neighbor\n"
12447 "Display routes learned from neighbor\n"
9973d184 12448 JSON_STR)
718e3744 12449{
d62a17ae 12450 char *peerstr = NULL;
12451 struct bgp *bgp = NULL;
12452 afi_t afi = AFI_IP6;
12453 safi_t safi = SAFI_UNICAST;
12454 struct peer *peer;
12455 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 12456 int idx = 0;
9f049418
DS
12457 bool uj = use_json(argc, argv);
12458
12459 if (uj)
12460 argc--;
bb46e94f 12461
d62a17ae 12462 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12463 &bgp, uj);
d62a17ae 12464 if (!idx)
12465 return CMD_WARNING;
c493f2d8 12466
d62a17ae 12467 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12468 argv_find(argv, argc, "neighbors", &idx);
12469 peerstr = argv[++idx]->arg;
8c3deaae 12470
d62a17ae 12471 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 12472 if (!peer)
d62a17ae 12473 return CMD_WARNING;
bb46e94f 12474
d62a17ae 12475 if (argv_find(argv, argc, "flap-statistics", &idx))
12476 sh_type = bgp_show_type_flap_neighbor;
12477 else if (argv_find(argv, argc, "dampened-routes", &idx))
12478 sh_type = bgp_show_type_damp_neighbor;
12479 else if (argv_find(argv, argc, "routes", &idx))
12480 sh_type = bgp_show_type_neighbor;
2525cf39 12481
d62a17ae 12482 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 12483}
6b0655a2 12484
734b349e 12485struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 12486
d62a17ae 12487struct bgp_distance {
12488 /* Distance value for the IP source prefix. */
d7c0a89a 12489 uint8_t distance;
718e3744 12490
d62a17ae 12491 /* Name of the access-list to be matched. */
12492 char *access_list;
718e3744 12493};
12494
4f280b15
LB
12495DEFUN (show_bgp_afi_vpn_rd_route,
12496 show_bgp_afi_vpn_rd_route_cmd,
d114b977 12497 "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
12498 SHOW_STR
12499 BGP_STR
12500 BGP_AFI_HELP_STR
12501 "Address Family modifier\n"
12502 "Display information for a route distinguisher\n"
12503 "Route Distinguisher\n"
7395a2c9
DS
12504 "Network in the BGP routing table to display\n"
12505 "Network in the BGP routing table to display\n"
12506 JSON_STR)
4f280b15 12507{
d62a17ae 12508 int ret;
12509 struct prefix_rd prd;
12510 afi_t afi = AFI_MAX;
12511 int idx = 0;
4f280b15 12512
ff6566f3
DS
12513 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
12514 vty_out(vty, "%% Malformed Address Family\n");
12515 return CMD_WARNING;
12516 }
12517
d62a17ae 12518 ret = str2prefix_rd(argv[5]->arg, &prd);
12519 if (!ret) {
12520 vty_out(vty, "%% Malformed Route Distinguisher\n");
12521 return CMD_WARNING;
12522 }
ff6566f3 12523
d62a17ae 12524 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 12525 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
12526}
12527
d62a17ae 12528static struct bgp_distance *bgp_distance_new(void)
718e3744 12529{
d62a17ae 12530 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 12531}
12532
d62a17ae 12533static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 12534{
d62a17ae 12535 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 12536}
12537
d62a17ae 12538static int bgp_distance_set(struct vty *vty, const char *distance_str,
12539 const char *ip_str, const char *access_list_str)
718e3744 12540{
d62a17ae 12541 int ret;
12542 afi_t afi;
12543 safi_t safi;
12544 struct prefix p;
d7c0a89a 12545 uint8_t distance;
d62a17ae 12546 struct bgp_node *rn;
12547 struct bgp_distance *bdistance;
718e3744 12548
d62a17ae 12549 afi = bgp_node_afi(vty);
12550 safi = bgp_node_safi(vty);
734b349e 12551
d62a17ae 12552 ret = str2prefix(ip_str, &p);
12553 if (ret == 0) {
12554 vty_out(vty, "Malformed prefix\n");
12555 return CMD_WARNING_CONFIG_FAILED;
12556 }
718e3744 12557
d62a17ae 12558 distance = atoi(distance_str);
718e3744 12559
d62a17ae 12560 /* Get BGP distance node. */
c4efd0f4 12561 rn = bgp_node_get(bgp_distance_table[afi][safi], &p);
5b00b40e 12562 bdistance = bgp_node_get_bgp_distance_info(rn);
ca2e160d 12563 if (bdistance)
d62a17ae 12564 bgp_unlock_node(rn);
ca2e160d 12565 else {
d62a17ae 12566 bdistance = bgp_distance_new();
5b00b40e 12567 bgp_node_set_bgp_distance_info(rn, bdistance);
d62a17ae 12568 }
718e3744 12569
d62a17ae 12570 /* Set distance value. */
12571 bdistance->distance = distance;
718e3744 12572
d62a17ae 12573 /* Reset access-list configuration. */
e1b36e13 12574 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 12575 if (access_list_str)
12576 bdistance->access_list =
12577 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 12578
d62a17ae 12579 return CMD_SUCCESS;
718e3744 12580}
12581
d62a17ae 12582static int bgp_distance_unset(struct vty *vty, const char *distance_str,
12583 const char *ip_str, const char *access_list_str)
718e3744 12584{
d62a17ae 12585 int ret;
12586 afi_t afi;
12587 safi_t safi;
12588 struct prefix p;
12589 int distance;
12590 struct bgp_node *rn;
12591 struct bgp_distance *bdistance;
718e3744 12592
d62a17ae 12593 afi = bgp_node_afi(vty);
12594 safi = bgp_node_safi(vty);
734b349e 12595
d62a17ae 12596 ret = str2prefix(ip_str, &p);
12597 if (ret == 0) {
12598 vty_out(vty, "Malformed prefix\n");
12599 return CMD_WARNING_CONFIG_FAILED;
12600 }
718e3744 12601
c4efd0f4 12602 rn = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
d62a17ae 12603 if (!rn) {
12604 vty_out(vty, "Can't find specified prefix\n");
12605 return CMD_WARNING_CONFIG_FAILED;
12606 }
718e3744 12607
5b00b40e 12608 bdistance = bgp_node_get_bgp_distance_info(rn);
d62a17ae 12609 distance = atoi(distance_str);
1f9a9fff 12610
d62a17ae 12611 if (bdistance->distance != distance) {
12612 vty_out(vty, "Distance does not match configured\n");
12613 return CMD_WARNING_CONFIG_FAILED;
12614 }
718e3744 12615
0a22ddfb 12616 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 12617 bgp_distance_free(bdistance);
718e3744 12618
6f94b685 12619 bgp_node_set_bgp_path_info(rn, NULL);
d62a17ae 12620 bgp_unlock_node(rn);
12621 bgp_unlock_node(rn);
718e3744 12622
d62a17ae 12623 return CMD_SUCCESS;
718e3744 12624}
12625
718e3744 12626/* Apply BGP information to distance method. */
b8685f9b 12627uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 12628 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 12629{
12630 struct bgp_node *rn;
12631 struct prefix q;
12632 struct peer *peer;
12633 struct bgp_distance *bdistance;
12634 struct access_list *alist;
12635 struct bgp_static *bgp_static;
12636
12637 if (!bgp)
12638 return 0;
12639
40381db7 12640 peer = pinfo->peer;
d62a17ae 12641
7b7d48e5
DS
12642 if (pinfo->attr->distance)
12643 return pinfo->attr->distance;
12644
d62a17ae 12645 /* Check source address. */
12646 sockunion2hostprefix(&peer->su, &q);
12647 rn = bgp_node_match(bgp_distance_table[afi][safi], &q);
12648 if (rn) {
5b00b40e 12649 bdistance = bgp_node_get_bgp_distance_info(rn);
d62a17ae 12650 bgp_unlock_node(rn);
12651
12652 if (bdistance->access_list) {
12653 alist = access_list_lookup(afi, bdistance->access_list);
12654 if (alist
12655 && access_list_apply(alist, p) == FILTER_PERMIT)
12656 return bdistance->distance;
12657 } else
12658 return bdistance->distance;
718e3744 12659 }
718e3744 12660
d62a17ae 12661 /* Backdoor check. */
12662 rn = bgp_node_lookup(bgp->route[afi][safi], p);
12663 if (rn) {
5a8ba9fc 12664 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 12665 bgp_unlock_node(rn);
718e3744 12666
d62a17ae 12667 if (bgp_static->backdoor) {
12668 if (bgp->distance_local[afi][safi])
12669 return bgp->distance_local[afi][safi];
12670 else
12671 return ZEBRA_IBGP_DISTANCE_DEFAULT;
12672 }
718e3744 12673 }
718e3744 12674
d62a17ae 12675 if (peer->sort == BGP_PEER_EBGP) {
12676 if (bgp->distance_ebgp[afi][safi])
12677 return bgp->distance_ebgp[afi][safi];
12678 return ZEBRA_EBGP_DISTANCE_DEFAULT;
12679 } else {
12680 if (bgp->distance_ibgp[afi][safi])
12681 return bgp->distance_ibgp[afi][safi];
12682 return ZEBRA_IBGP_DISTANCE_DEFAULT;
12683 }
718e3744 12684}
12685
a612fb77
DA
12686/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
12687 * we should tell ZEBRA update the routes for a specific
12688 * AFI/SAFI to reflect changes in RIB.
12689 */
8b54bc30
DA
12690static void bgp_announce_routes_distance_update(struct bgp *bgp,
12691 afi_t update_afi,
12692 safi_t update_safi)
a612fb77
DA
12693{
12694 afi_t afi;
12695 safi_t safi;
12696
12697 FOREACH_AFI_SAFI (afi, safi) {
12698 if (!bgp_fibupd_safi(safi))
12699 continue;
12700
8b54bc30
DA
12701 if (afi != update_afi && safi != update_safi)
12702 continue;
12703
12704 if (BGP_DEBUG(zebra, ZEBRA))
12705 zlog_debug(
12706 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
12707 __func__, afi, safi);
12708 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
12709 }
12710}
12711
718e3744 12712DEFUN (bgp_distance,
12713 bgp_distance_cmd,
6147e2c6 12714 "distance bgp (1-255) (1-255) (1-255)",
718e3744 12715 "Define an administrative distance\n"
12716 "BGP distance\n"
12717 "Distance for routes external to the AS\n"
12718 "Distance for routes internal to the AS\n"
12719 "Distance for local routes\n")
12720{
d62a17ae 12721 VTY_DECLVAR_CONTEXT(bgp, bgp);
12722 int idx_number = 2;
12723 int idx_number_2 = 3;
12724 int idx_number_3 = 4;
8b54bc30
DA
12725 int distance_ebgp = atoi(argv[idx_number]->arg);
12726 int distance_ibgp = atoi(argv[idx_number_2]->arg);
12727 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 12728 afi_t afi;
12729 safi_t safi;
718e3744 12730
d62a17ae 12731 afi = bgp_node_afi(vty);
12732 safi = bgp_node_safi(vty);
718e3744 12733
8b54bc30
DA
12734 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
12735 || bgp->distance_ibgp[afi][safi] != distance_ibgp
12736 || bgp->distance_local[afi][safi] != distance_local) {
12737 bgp->distance_ebgp[afi][safi] = distance_ebgp;
12738 bgp->distance_ibgp[afi][safi] = distance_ibgp;
12739 bgp->distance_local[afi][safi] = distance_local;
12740 bgp_announce_routes_distance_update(bgp, afi, safi);
12741 }
d62a17ae 12742 return CMD_SUCCESS;
718e3744 12743}
12744
12745DEFUN (no_bgp_distance,
12746 no_bgp_distance_cmd,
a636c635 12747 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 12748 NO_STR
12749 "Define an administrative distance\n"
12750 "BGP distance\n"
12751 "Distance for routes external to the AS\n"
12752 "Distance for routes internal to the AS\n"
12753 "Distance for local routes\n")
12754{
d62a17ae 12755 VTY_DECLVAR_CONTEXT(bgp, bgp);
12756 afi_t afi;
12757 safi_t safi;
718e3744 12758
d62a17ae 12759 afi = bgp_node_afi(vty);
12760 safi = bgp_node_safi(vty);
718e3744 12761
8b54bc30
DA
12762 if (bgp->distance_ebgp[afi][safi] != 0
12763 || bgp->distance_ibgp[afi][safi] != 0
12764 || bgp->distance_local[afi][safi] != 0) {
12765 bgp->distance_ebgp[afi][safi] = 0;
12766 bgp->distance_ibgp[afi][safi] = 0;
12767 bgp->distance_local[afi][safi] = 0;
12768 bgp_announce_routes_distance_update(bgp, afi, safi);
12769 }
d62a17ae 12770 return CMD_SUCCESS;
718e3744 12771}
12772
718e3744 12773
12774DEFUN (bgp_distance_source,
12775 bgp_distance_source_cmd,
6147e2c6 12776 "distance (1-255) A.B.C.D/M",
718e3744 12777 "Define an administrative distance\n"
12778 "Administrative distance\n"
12779 "IP source prefix\n")
12780{
d62a17ae 12781 int idx_number = 1;
12782 int idx_ipv4_prefixlen = 2;
12783 bgp_distance_set(vty, argv[idx_number]->arg,
12784 argv[idx_ipv4_prefixlen]->arg, NULL);
12785 return CMD_SUCCESS;
718e3744 12786}
12787
12788DEFUN (no_bgp_distance_source,
12789 no_bgp_distance_source_cmd,
6147e2c6 12790 "no distance (1-255) A.B.C.D/M",
718e3744 12791 NO_STR
12792 "Define an administrative distance\n"
12793 "Administrative distance\n"
12794 "IP source prefix\n")
12795{
d62a17ae 12796 int idx_number = 2;
12797 int idx_ipv4_prefixlen = 3;
12798 bgp_distance_unset(vty, argv[idx_number]->arg,
12799 argv[idx_ipv4_prefixlen]->arg, NULL);
12800 return CMD_SUCCESS;
718e3744 12801}
12802
12803DEFUN (bgp_distance_source_access_list,
12804 bgp_distance_source_access_list_cmd,
6147e2c6 12805 "distance (1-255) A.B.C.D/M WORD",
718e3744 12806 "Define an administrative distance\n"
12807 "Administrative distance\n"
12808 "IP source prefix\n"
12809 "Access list name\n")
12810{
d62a17ae 12811 int idx_number = 1;
12812 int idx_ipv4_prefixlen = 2;
12813 int idx_word = 3;
12814 bgp_distance_set(vty, argv[idx_number]->arg,
12815 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12816 return CMD_SUCCESS;
718e3744 12817}
12818
12819DEFUN (no_bgp_distance_source_access_list,
12820 no_bgp_distance_source_access_list_cmd,
6147e2c6 12821 "no distance (1-255) A.B.C.D/M WORD",
718e3744 12822 NO_STR
12823 "Define an administrative distance\n"
12824 "Administrative distance\n"
12825 "IP source prefix\n"
12826 "Access list name\n")
12827{
d62a17ae 12828 int idx_number = 2;
12829 int idx_ipv4_prefixlen = 3;
12830 int idx_word = 4;
12831 bgp_distance_unset(vty, argv[idx_number]->arg,
12832 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12833 return CMD_SUCCESS;
718e3744 12834}
6b0655a2 12835
734b349e
MZ
12836DEFUN (ipv6_bgp_distance_source,
12837 ipv6_bgp_distance_source_cmd,
39e92c06 12838 "distance (1-255) X:X::X:X/M",
734b349e
MZ
12839 "Define an administrative distance\n"
12840 "Administrative distance\n"
12841 "IP source prefix\n")
12842{
d62a17ae 12843 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
12844 return CMD_SUCCESS;
734b349e
MZ
12845}
12846
12847DEFUN (no_ipv6_bgp_distance_source,
12848 no_ipv6_bgp_distance_source_cmd,
39e92c06 12849 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
12850 NO_STR
12851 "Define an administrative distance\n"
12852 "Administrative distance\n"
12853 "IP source prefix\n")
12854{
d62a17ae 12855 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
12856 return CMD_SUCCESS;
734b349e
MZ
12857}
12858
12859DEFUN (ipv6_bgp_distance_source_access_list,
12860 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12861 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12862 "Define an administrative distance\n"
12863 "Administrative distance\n"
12864 "IP source prefix\n"
12865 "Access list name\n")
12866{
d62a17ae 12867 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
12868 return CMD_SUCCESS;
734b349e
MZ
12869}
12870
12871DEFUN (no_ipv6_bgp_distance_source_access_list,
12872 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12873 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12874 NO_STR
12875 "Define an administrative distance\n"
12876 "Administrative distance\n"
12877 "IP source prefix\n"
12878 "Access list name\n")
12879{
d62a17ae 12880 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
12881 return CMD_SUCCESS;
734b349e
MZ
12882}
12883
718e3744 12884DEFUN (bgp_damp_set,
12885 bgp_damp_set_cmd,
31500417 12886 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 12887 "BGP Specific commands\n"
12888 "Enable route-flap dampening\n"
12889 "Half-life time for the penalty\n"
12890 "Value to start reusing a route\n"
12891 "Value to start suppressing a route\n"
12892 "Maximum duration to suppress a stable route\n")
12893{
d62a17ae 12894 VTY_DECLVAR_CONTEXT(bgp, bgp);
12895 int idx_half_life = 2;
12896 int idx_reuse = 3;
12897 int idx_suppress = 4;
12898 int idx_max_suppress = 5;
12899 int half = DEFAULT_HALF_LIFE * 60;
12900 int reuse = DEFAULT_REUSE;
12901 int suppress = DEFAULT_SUPPRESS;
12902 int max = 4 * half;
12903
12904 if (argc == 6) {
12905 half = atoi(argv[idx_half_life]->arg) * 60;
12906 reuse = atoi(argv[idx_reuse]->arg);
12907 suppress = atoi(argv[idx_suppress]->arg);
12908 max = atoi(argv[idx_max_suppress]->arg) * 60;
12909 } else if (argc == 3) {
12910 half = atoi(argv[idx_half_life]->arg) * 60;
12911 max = 4 * half;
12912 }
718e3744 12913
6d24b7cc
DS
12914 /*
12915 * These can't be 0 but our SA doesn't understand the
12916 * way our cli is constructed
12917 */
12918 assert(reuse);
12919 assert(half);
d62a17ae 12920 if (suppress < reuse) {
12921 vty_out(vty,
12922 "Suppress value cannot be less than reuse value \n");
12923 return 0;
12924 }
7ebe9748 12925
d62a17ae 12926 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
12927 reuse, suppress, max);
718e3744 12928}
12929
718e3744 12930DEFUN (bgp_damp_unset,
12931 bgp_damp_unset_cmd,
d04c479d 12932 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 12933 NO_STR
12934 "BGP Specific commands\n"
16cedbb0
QY
12935 "Enable route-flap dampening\n"
12936 "Half-life time for the penalty\n"
12937 "Value to start reusing a route\n"
12938 "Value to start suppressing a route\n"
12939 "Maximum duration to suppress a stable route\n")
718e3744 12940{
d62a17ae 12941 VTY_DECLVAR_CONTEXT(bgp, bgp);
12942 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 12943}
12944
718e3744 12945/* Display specified route of BGP table. */
d62a17ae 12946static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
12947 const char *ip_str, afi_t afi, safi_t safi,
12948 struct prefix_rd *prd, int prefix_check)
12949{
12950 int ret;
12951 struct prefix match;
12952 struct bgp_node *rn;
12953 struct bgp_node *rm;
40381db7
DS
12954 struct bgp_path_info *pi;
12955 struct bgp_path_info *pi_temp;
d62a17ae 12956 struct bgp *bgp;
12957 struct bgp_table *table;
12958
12959 /* BGP structure lookup. */
12960 if (view_name) {
12961 bgp = bgp_lookup_by_name(view_name);
12962 if (bgp == NULL) {
12963 vty_out(vty, "%% Can't find BGP instance %s\n",
12964 view_name);
12965 return CMD_WARNING;
12966 }
12967 } else {
12968 bgp = bgp_get_default();
12969 if (bgp == NULL) {
12970 vty_out(vty, "%% No BGP process is configured\n");
12971 return CMD_WARNING;
12972 }
718e3744 12973 }
718e3744 12974
d62a17ae 12975 /* Check IP address argument. */
12976 ret = str2prefix(ip_str, &match);
12977 if (!ret) {
12978 vty_out(vty, "%% address is malformed\n");
12979 return CMD_WARNING;
12980 }
718e3744 12981
d62a17ae 12982 match.family = afi2family(afi);
12983
12984 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
12985 || (safi == SAFI_EVPN)) {
12986 for (rn = bgp_table_top(bgp->rib[AFI_IP][safi]); rn;
12987 rn = bgp_route_next(rn)) {
b54892e0
DS
12988 const struct prefix *rn_p = bgp_node_get_prefix(rn);
12989
12990 if (prd && memcmp(rn_p->u.val, prd->val, 8) != 0)
d62a17ae 12991 continue;
67009e22
DS
12992 table = bgp_node_get_bgp_table_info(rn);
12993 if (!table)
ea47320b
DL
12994 continue;
12995 if ((rm = bgp_node_match(table, &match)) == NULL)
12996 continue;
d62a17ae 12997
b54892e0
DS
12998 const struct prefix *rm_p = bgp_node_get_prefix(rn);
12999
ea47320b 13000 if (!prefix_check
b54892e0 13001 || rm_p->prefixlen == match.prefixlen) {
6f94b685 13002 pi = bgp_node_get_bgp_path_info(rm);
40381db7
DS
13003 while (pi) {
13004 if (pi->extra && pi->extra->damp_info) {
13005 pi_temp = pi->next;
ea47320b 13006 bgp_damp_info_free(
40381db7 13007 pi->extra->damp_info,
a935f597 13008 1, afi, safi);
40381db7 13009 pi = pi_temp;
ea47320b 13010 } else
40381db7 13011 pi = pi->next;
d62a17ae 13012 }
ea47320b
DL
13013 }
13014
13015 bgp_unlock_node(rm);
d62a17ae 13016 }
13017 } else {
13018 if ((rn = bgp_node_match(bgp->rib[afi][safi], &match))
13019 != NULL) {
b54892e0
DS
13020 const struct prefix *rn_p = bgp_node_get_prefix(rn);
13021
d62a17ae 13022 if (!prefix_check
b54892e0 13023 || rn_p->prefixlen == match.prefixlen) {
6f94b685 13024 pi = bgp_node_get_bgp_path_info(rn);
40381db7
DS
13025 while (pi) {
13026 if (pi->extra && pi->extra->damp_info) {
13027 pi_temp = pi->next;
d62a17ae 13028 bgp_damp_info_free(
40381db7 13029 pi->extra->damp_info,
a935f597 13030 1, afi, safi);
40381db7 13031 pi = pi_temp;
d62a17ae 13032 } else
40381db7 13033 pi = pi->next;
d62a17ae 13034 }
13035 }
13036
13037 bgp_unlock_node(rn);
13038 }
13039 }
718e3744 13040
d62a17ae 13041 return CMD_SUCCESS;
718e3744 13042}
13043
13044DEFUN (clear_ip_bgp_dampening,
13045 clear_ip_bgp_dampening_cmd,
13046 "clear ip bgp dampening",
13047 CLEAR_STR
13048 IP_STR
13049 BGP_STR
13050 "Clear route flap dampening information\n")
13051{
a935f597 13052 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 13053 return CMD_SUCCESS;
718e3744 13054}
13055
13056DEFUN (clear_ip_bgp_dampening_prefix,
13057 clear_ip_bgp_dampening_prefix_cmd,
13058 "clear ip bgp dampening A.B.C.D/M",
13059 CLEAR_STR
13060 IP_STR
13061 BGP_STR
13062 "Clear route flap dampening information\n"
0c7b1b01 13063 "IPv4 prefix\n")
718e3744 13064{
d62a17ae 13065 int idx_ipv4_prefixlen = 4;
13066 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
13067 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 13068}
13069
13070DEFUN (clear_ip_bgp_dampening_address,
13071 clear_ip_bgp_dampening_address_cmd,
13072 "clear ip bgp dampening A.B.C.D",
13073 CLEAR_STR
13074 IP_STR
13075 BGP_STR
13076 "Clear route flap dampening information\n"
13077 "Network to clear damping information\n")
13078{
d62a17ae 13079 int idx_ipv4 = 4;
13080 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
13081 SAFI_UNICAST, NULL, 0);
718e3744 13082}
13083
13084DEFUN (clear_ip_bgp_dampening_address_mask,
13085 clear_ip_bgp_dampening_address_mask_cmd,
13086 "clear ip bgp dampening A.B.C.D A.B.C.D",
13087 CLEAR_STR
13088 IP_STR
13089 BGP_STR
13090 "Clear route flap dampening information\n"
13091 "Network to clear damping information\n"
13092 "Network mask\n")
13093{
d62a17ae 13094 int idx_ipv4 = 4;
13095 int idx_ipv4_2 = 5;
13096 int ret;
13097 char prefix_str[BUFSIZ];
718e3744 13098
d62a17ae 13099 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
13100 prefix_str);
13101 if (!ret) {
13102 vty_out(vty, "%% Inconsistent address and mask\n");
13103 return CMD_WARNING;
13104 }
718e3744 13105
d62a17ae 13106 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
13107 NULL, 0);
718e3744 13108}
6b0655a2 13109
e3b78da8 13110static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
13111{
13112 struct vty *vty = arg;
e3b78da8 13113 struct peer *peer = bucket->data;
825d9834
DS
13114 char buf[SU_ADDRSTRLEN];
13115
13116 vty_out(vty, "\tPeer: %s %s\n", peer->host,
13117 sockunion2str(&peer->su, buf, sizeof(buf)));
13118}
13119
2a0e69ae
DS
13120DEFUN (show_bgp_listeners,
13121 show_bgp_listeners_cmd,
13122 "show bgp listeners",
13123 SHOW_STR
13124 BGP_STR
13125 "Display Listen Sockets and who created them\n")
13126{
13127 bgp_dump_listener_info(vty);
13128
13129 return CMD_SUCCESS;
13130}
13131
825d9834
DS
13132DEFUN (show_bgp_peerhash,
13133 show_bgp_peerhash_cmd,
13134 "show bgp peerhash",
13135 SHOW_STR
13136 BGP_STR
13137 "Display information about the BGP peerhash\n")
13138{
13139 struct list *instances = bm->bgp;
13140 struct listnode *node;
13141 struct bgp *bgp;
13142
13143 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
13144 vty_out(vty, "BGP: %s\n", bgp->name);
13145 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
13146 vty);
13147 }
13148
13149 return CMD_SUCCESS;
13150}
13151
587ff0fd 13152/* also used for encap safi */
2b791107
DL
13153static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
13154 afi_t afi, safi_t safi)
d62a17ae 13155{
13156 struct bgp_node *prn;
13157 struct bgp_node *rn;
13158 struct bgp_table *table;
b54892e0
DS
13159 const struct prefix *p;
13160 const struct prefix_rd *prd;
d62a17ae 13161 struct bgp_static *bgp_static;
13162 mpls_label_t label;
13163 char buf[SU_ADDRSTRLEN];
13164 char rdbuf[RD_ADDRSTRLEN];
13165
13166 /* Network configuration. */
13167 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b 13168 prn = bgp_route_next(prn)) {
67009e22
DS
13169 table = bgp_node_get_bgp_table_info(prn);
13170 if (!table)
ea47320b 13171 continue;
d62a17ae 13172
60466a63 13173 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5a8ba9fc 13174 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 13175 if (bgp_static == NULL)
ea47320b 13176 continue;
d62a17ae 13177
b54892e0
DS
13178 p = bgp_node_get_prefix(rn);
13179 prd = (const struct prefix_rd *)bgp_node_get_prefix(
13180 prn);
d62a17ae 13181
ea47320b 13182 /* "network" configuration display. */
06b9f471 13183 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
13184 label = decode_label(&bgp_static->label);
13185
13186 vty_out(vty, " network %s/%d rd %s",
13187 inet_ntop(p->family, &p->u.prefix, buf,
13188 SU_ADDRSTRLEN),
13189 p->prefixlen, rdbuf);
13190 if (safi == SAFI_MPLS_VPN)
13191 vty_out(vty, " label %u", label);
13192
13193 if (bgp_static->rmap.name)
13194 vty_out(vty, " route-map %s",
13195 bgp_static->rmap.name);
e2a86ad9
DS
13196
13197 if (bgp_static->backdoor)
13198 vty_out(vty, " backdoor");
13199
ea47320b
DL
13200 vty_out(vty, "\n");
13201 }
13202 }
d62a17ae 13203}
13204
2b791107
DL
13205static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
13206 afi_t afi, safi_t safi)
d62a17ae 13207{
13208 struct bgp_node *prn;
13209 struct bgp_node *rn;
13210 struct bgp_table *table;
b54892e0
DS
13211 const struct prefix *p;
13212 const struct prefix_rd *prd;
d62a17ae 13213 struct bgp_static *bgp_static;
ff44f570 13214 char buf[PREFIX_STRLEN * 2];
d62a17ae 13215 char buf2[SU_ADDRSTRLEN];
13216 char rdbuf[RD_ADDRSTRLEN];
13217
13218 /* Network configuration. */
13219 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b 13220 prn = bgp_route_next(prn)) {
67009e22
DS
13221 table = bgp_node_get_bgp_table_info(prn);
13222 if (!table)
ea47320b 13223 continue;
d62a17ae 13224
60466a63 13225 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5a8ba9fc 13226 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 13227 if (bgp_static == NULL)
ea47320b 13228 continue;
d62a17ae 13229
ea47320b
DL
13230 char *macrouter = NULL;
13231 char *esi = NULL;
d62a17ae 13232
ea47320b
DL
13233 if (bgp_static->router_mac)
13234 macrouter = prefix_mac2str(
13235 bgp_static->router_mac, NULL, 0);
13236 if (bgp_static->eth_s_id)
13237 esi = esi2str(bgp_static->eth_s_id);
b54892e0
DS
13238 p = bgp_node_get_prefix(rn);
13239 prd = (struct prefix_rd *)bgp_node_get_prefix(prn);
d62a17ae 13240
ea47320b 13241 /* "network" configuration display. */
06b9f471 13242 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
13243 if (p->u.prefix_evpn.route_type == 5) {
13244 char local_buf[PREFIX_STRLEN];
3714a385 13245 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
13246 struct prefix_evpn *)p)
13247 ? AF_INET
13248 : AF_INET6;
3714a385 13249 inet_ntop(family,
13250 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a
PZ
13251 local_buf, PREFIX_STRLEN);
13252 sprintf(buf, "%s/%u", local_buf,
3714a385 13253 p->u.prefix_evpn.prefix_addr.ip_prefix_length);
197cb530
PG
13254 } else {
13255 prefix2str(p, buf, sizeof(buf));
13256 }
ea47320b 13257
a4d82a8a
PZ
13258 if (bgp_static->gatewayIp.family == AF_INET
13259 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
13260 inet_ntop(bgp_static->gatewayIp.family,
13261 &bgp_static->gatewayIp.u.prefix, buf2,
13262 sizeof(buf2));
ea47320b 13263 vty_out(vty,
7bcc8dac 13264 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 13265 buf, rdbuf,
13266 p->u.prefix_evpn.prefix_addr.eth_tag,
60466a63 13267 decode_label(&bgp_static->label), esi, buf2,
ea47320b
DL
13268 macrouter);
13269
0a22ddfb
QY
13270 XFREE(MTYPE_TMP, macrouter);
13271 XFREE(MTYPE_TMP, esi);
ea47320b
DL
13272 }
13273 }
3da6fcd5
PG
13274}
13275
718e3744 13276/* Configuration of static route announcement and aggregate
13277 information. */
2b791107
DL
13278void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
13279 safi_t safi)
d62a17ae 13280{
13281 struct bgp_node *rn;
b54892e0 13282 const struct prefix *p;
d62a17ae 13283 struct bgp_static *bgp_static;
13284 struct bgp_aggregate *bgp_aggregate;
13285 char buf[SU_ADDRSTRLEN];
13286
2b791107
DL
13287 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
13288 bgp_config_write_network_vpn(vty, bgp, afi, safi);
13289 return;
13290 }
d62a17ae 13291
2b791107
DL
13292 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
13293 bgp_config_write_network_evpn(vty, bgp, afi, safi);
13294 return;
13295 }
d62a17ae 13296
13297 /* Network configuration. */
13298 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
ea47320b 13299 rn = bgp_route_next(rn)) {
5a8ba9fc 13300 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 13301 if (bgp_static == NULL)
ea47320b 13302 continue;
d62a17ae 13303
b54892e0 13304 p = bgp_node_get_prefix(rn);
d62a17ae 13305
d8a9922d
DS
13306 vty_out(vty, " network %s/%d",
13307 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
13308 p->prefixlen);
d62a17ae 13309
ea47320b
DL
13310 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
13311 vty_out(vty, " label-index %u",
13312 bgp_static->label_index);
d62a17ae 13313
ea47320b
DL
13314 if (bgp_static->rmap.name)
13315 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
13316
13317 if (bgp_static->backdoor)
13318 vty_out(vty, " backdoor");
718e3744 13319
ea47320b
DL
13320 vty_out(vty, "\n");
13321 }
13322
d62a17ae 13323 /* Aggregate-address configuration. */
13324 for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn;
ea47320b 13325 rn = bgp_route_next(rn)) {
b613a918 13326 bgp_aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 13327 if (bgp_aggregate == NULL)
ea47320b 13328 continue;
d62a17ae 13329
b54892e0 13330 p = bgp_node_get_prefix(rn);
d62a17ae 13331
d8a9922d
DS
13332 vty_out(vty, " aggregate-address %s/%d",
13333 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
13334 p->prefixlen);
d62a17ae 13335
ea47320b
DL
13336 if (bgp_aggregate->as_set)
13337 vty_out(vty, " as-set");
d62a17ae 13338
ea47320b
DL
13339 if (bgp_aggregate->summary_only)
13340 vty_out(vty, " summary-only");
718e3744 13341
20894f50
DA
13342 if (bgp_aggregate->rmap.name)
13343 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
13344
229757f1
DA
13345 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
13346 vty_out(vty, " origin %s",
13347 bgp_origin2str(bgp_aggregate->origin));
13348
ea47320b
DL
13349 vty_out(vty, "\n");
13350 }
d62a17ae 13351}
734b349e 13352
2b791107 13353void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 13354 safi_t safi)
d62a17ae 13355{
13356 struct bgp_node *rn;
13357 struct bgp_distance *bdistance;
13358
13359 /* Distance configuration. */
13360 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
13361 && bgp->distance_local[afi][safi]
13362 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
13363 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
13364 || bgp->distance_local[afi][safi]
13365 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 13366 vty_out(vty, " distance bgp %d %d %d\n",
13367 bgp->distance_ebgp[afi][safi],
13368 bgp->distance_ibgp[afi][safi],
13369 bgp->distance_local[afi][safi]);
13370 }
734b349e 13371
d62a17ae 13372 for (rn = bgp_table_top(bgp_distance_table[afi][safi]); rn;
ca2e160d 13373 rn = bgp_route_next(rn)) {
5b00b40e 13374 bdistance = bgp_node_get_bgp_distance_info(rn);
b54892e0
DS
13375 if (bdistance != NULL)
13376 vty_out(vty, " distance %d %pRN %s\n",
13377 bdistance->distance, rn,
d62a17ae 13378 bdistance->access_list ? bdistance->access_list
13379 : "");
ca2e160d 13380 }
718e3744 13381}
13382
13383/* Allocate routing table structure and install commands. */
d62a17ae 13384void bgp_route_init(void)
13385{
13386 afi_t afi;
13387 safi_t safi;
13388
13389 /* Init BGP distance table. */
05c7a1cc 13390 FOREACH_AFI_SAFI (afi, safi)
960035b2 13391 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 13392
13393 /* IPv4 BGP commands. */
13394 install_element(BGP_NODE, &bgp_table_map_cmd);
13395 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 13396 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 13397
13398 install_element(BGP_NODE, &aggregate_address_cmd);
13399 install_element(BGP_NODE, &aggregate_address_mask_cmd);
13400 install_element(BGP_NODE, &no_aggregate_address_cmd);
13401 install_element(BGP_NODE, &no_aggregate_address_mask_cmd);
13402
13403 /* IPv4 unicast configuration. */
13404 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
13405 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 13406 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 13407
13408 install_element(BGP_IPV4_NODE, &aggregate_address_cmd);
13409 install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd);
13410 install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd);
13411 install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
13412
13413 /* IPv4 multicast configuration. */
13414 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
13415 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 13416 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
d62a17ae 13417 install_element(BGP_IPV4M_NODE, &aggregate_address_cmd);
13418 install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
13419 install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd);
13420 install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
13421
13422 /* IPv4 labeled-unicast configuration. */
13423 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
13424 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 13425 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 13426 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 13427 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 13428 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
13429 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 13430 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 13431
13432 install_element(VIEW_NODE,
13433 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
13434 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
13435 install_element(VIEW_NODE,
13436 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 13437#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 13438 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 13439#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 13440 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
13441 install_element(VIEW_NODE,
44c69747 13442 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 13443
d62a17ae 13444 /* BGP dampening clear commands */
13445 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
13446 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 13447
d62a17ae 13448 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
13449 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
13450
13451 /* prefix count */
13452 install_element(ENABLE_NODE,
13453 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 13454#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 13455 install_element(ENABLE_NODE,
13456 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 13457#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 13458
d62a17ae 13459 /* New config IPv6 BGP commands. */
13460 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
13461 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 13462 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 13463
13464 install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
13465 install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
13466
13467 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 13468
d62a17ae 13469 install_element(BGP_NODE, &bgp_distance_cmd);
13470 install_element(BGP_NODE, &no_bgp_distance_cmd);
13471 install_element(BGP_NODE, &bgp_distance_source_cmd);
13472 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
13473 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
13474 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
13475 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
13476 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
13477 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
13478 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
13479 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
13480 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
13481 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
13482 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
13483 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
13484 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
13485 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
13486 install_element(BGP_IPV4M_NODE,
13487 &no_bgp_distance_source_access_list_cmd);
13488 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
13489 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
13490 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
13491 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
13492 install_element(BGP_IPV6_NODE,
13493 &ipv6_bgp_distance_source_access_list_cmd);
13494 install_element(BGP_IPV6_NODE,
13495 &no_ipv6_bgp_distance_source_access_list_cmd);
13496 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
13497 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
13498 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
13499 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
13500 install_element(BGP_IPV6M_NODE,
13501 &ipv6_bgp_distance_source_access_list_cmd);
13502 install_element(BGP_IPV6M_NODE,
13503 &no_ipv6_bgp_distance_source_access_list_cmd);
13504
13505 install_element(BGP_NODE, &bgp_damp_set_cmd);
13506 install_element(BGP_NODE, &bgp_damp_unset_cmd);
13507 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
13508 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
13509
13510 /* IPv4 Multicast Mode */
13511 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
13512 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
13513
13514 /* Large Communities */
13515 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
13516 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
13517
13518 /* show bgp ipv4 flowspec detailed */
13519 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
13520
2a0e69ae 13521 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 13522 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 13523}
13524
13525void bgp_route_finish(void)
13526{
13527 afi_t afi;
13528 safi_t safi;
13529
05c7a1cc
QY
13530 FOREACH_AFI_SAFI (afi, safi) {
13531 bgp_table_unlock(bgp_distance_table[afi][safi]);
13532 bgp_distance_table[afi][safi] = NULL;
13533 }
228da428 13534}