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