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