]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #6011 from patrasar/pim-no-msdp-group-cmd
[mirror_frr.git] / bgpd / bgp_route.c
CommitLineData
718e3744 1/* BGP routing information
896014f4
DL
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
718e3744 21
22#include <zebra.h>
8d0ab76d 23#include <math.h>
718e3744 24
2618a52e 25#include "printfrr.h"
718e3744 26#include "prefix.h"
27#include "linklist.h"
28#include "memory.h"
29#include "command.h"
30#include "stream.h"
31#include "filter.h"
718e3744 32#include "log.h"
33#include "routemap.h"
34#include "buffer.h"
35#include "sockunion.h"
36#include "plist.h"
37#include "thread.h"
200df115 38#include "workqueue.h"
3f9c7369 39#include "queue.h"
6e919709 40#include "memory.h"
e496b420 41#include "srv6.h"
4dcadbef 42#include "lib/json.h"
d8d084d9 43#include "lib_errors.h"
8c48b3b6 44#include "zclient.h"
718e3744 45#include "bgpd/bgpd.h"
46#include "bgpd/bgp_table.h"
47#include "bgpd/bgp_route.h"
48#include "bgpd/bgp_attr.h"
49#include "bgpd/bgp_debug.h"
14454c9f 50#include "bgpd/bgp_errors.h"
718e3744 51#include "bgpd/bgp_aspath.h"
52#include "bgpd/bgp_regex.h"
53#include "bgpd/bgp_community.h"
54#include "bgpd/bgp_ecommunity.h"
57d187bc 55#include "bgpd/bgp_lcommunity.h"
718e3744 56#include "bgpd/bgp_clist.h"
57#include "bgpd/bgp_packet.h"
58#include "bgpd/bgp_filter.h"
59#include "bgpd/bgp_fsm.h"
60#include "bgpd/bgp_mplsvpn.h"
61#include "bgpd/bgp_nexthop.h"
62#include "bgpd/bgp_damp.h"
63#include "bgpd/bgp_advertise.h"
64#include "bgpd/bgp_zebra.h"
0a486e5f 65#include "bgpd/bgp_vty.h"
96450faf 66#include "bgpd/bgp_mpath.h"
fc9a856f 67#include "bgpd/bgp_nht.h"
3f9c7369 68#include "bgpd/bgp_updgrp.h"
cd1964ff 69#include "bgpd/bgp_label.h"
dcc68b5e 70#include "bgpd/bgp_addpath.h"
4e802e66 71#include "bgpd/bgp_mac.h"
2a0e69ae 72#include "bgpd/bgp_network.h"
718e3744 73
49e5a4a0 74#ifdef ENABLE_BGP_VNC
f8b6f499
LB
75#include "bgpd/rfapi/rfapi_backend.h"
76#include "bgpd/rfapi/vnc_import_bgp.h"
77#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 78#endif
aee875b5
PG
79#include "bgpd/bgp_encap_types.h"
80#include "bgpd/bgp_encap_tlv.h"
684a7227 81#include "bgpd/bgp_evpn.h"
3da6fcd5 82#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 83#include "bgpd/bgp_flowspec.h"
98a9dbc7 84#include "bgpd/bgp_flowspec_util.h"
45918cfb 85#include "bgpd/bgp_pbr.h"
65efcfce 86
e2a86ad9
DS
87#ifndef VTYSH_EXTRACT_PL
88#include "bgpd/bgp_route_clippy.c"
89#endif
aee875b5 90
718e3744 91/* Extern from bgp_dump.c */
dde72586
SH
92extern const char *bgp_origin_str[];
93extern const char *bgp_origin_long_str[];
36235319 94const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json);
b7d08f5a 95/* PMSI strings. */
96#define PMSI_TNLTYPE_STR_NO_INFO "No info"
97#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
98static const struct message bgp_pmsi_tnltype_str[] = {
99 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
100 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
101 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
102 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
103 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
104 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
105 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
106 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 107 {0}
108};
b7d08f5a 109
9df8b37c
PZ
110#define VRFID_NONE_STR "-"
111
4a11bf2c
DL
112DEFINE_HOOK(bgp_process,
113 (struct bgp *bgp, afi_t afi, safi_t safi,
114 struct bgp_node *bn, struct peer *peer, bool withdraw),
115 (bgp, afi, safi, bn, peer, withdraw))
116
117
d62a17ae 118struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 119 safi_t safi, const struct prefix *p,
d62a17ae 120 struct prefix_rd *prd)
121{
122 struct bgp_node *rn;
123 struct bgp_node *prn = NULL;
124
125 assert(table);
d62a17ae 126
127 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
128 || (safi == SAFI_EVPN)) {
129 prn = bgp_node_get(table, (struct prefix *)prd);
130
67009e22
DS
131 if (!bgp_node_has_bgp_path_info_data(prn))
132 bgp_node_set_bgp_table_info(
133 prn, bgp_table_init(table->bgp, afi, safi));
d62a17ae 134 else
135 bgp_unlock_node(prn);
67009e22 136 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 137 }
718e3744 138
d62a17ae 139 rn = bgp_node_get(table, p);
718e3744 140
d62a17ae 141 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
142 || (safi == SAFI_EVPN))
143 rn->prn = prn;
718e3744 144
d62a17ae 145 return rn;
718e3744 146}
6b0655a2 147
d62a17ae 148struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 149 safi_t safi, const struct prefix *p,
d62a17ae 150 struct prefix_rd *prd)
128ea8ab 151{
d62a17ae 152 struct bgp_node *rn;
153 struct bgp_node *prn = NULL;
128ea8ab 154
d62a17ae 155 if (!table)
156 return NULL;
128ea8ab 157
d62a17ae 158 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
159 || (safi == SAFI_EVPN)) {
160 prn = bgp_node_lookup(table, (struct prefix *)prd);
161 if (!prn)
162 return NULL;
128ea8ab 163
6f94b685 164 if (!bgp_node_has_bgp_path_info_data(prn)) {
d62a17ae 165 bgp_unlock_node(prn);
166 return NULL;
167 }
128ea8ab 168
67009e22 169 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 170 }
128ea8ab 171
d62a17ae 172 rn = bgp_node_lookup(table, p);
128ea8ab 173
d62a17ae 174 return rn;
128ea8ab 175}
176
18ee8310
DS
177/* Allocate bgp_path_info_extra */
178static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 179{
4b7e6066
DS
180 struct bgp_path_info_extra *new;
181 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
182 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
183 new->label[0] = MPLS_INVALID_LABEL;
184 new->num_labels = 0;
3e3708cb
PG
185 new->bgp_fs_pbr = NULL;
186 new->bgp_fs_iprule = NULL;
d62a17ae 187 return new;
fb982c25
PJ
188}
189
a2e219fe 190void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 191{
4b7e6066 192 struct bgp_path_info_extra *e;
d62a17ae 193
c93a3b77
DS
194 if (!extra || !*extra)
195 return;
d62a17ae 196
c93a3b77
DS
197 e = *extra;
198 if (e->damp_info)
a935f597
DA
199 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
200 e->damp_info->safi);
d62a17ae 201
c93a3b77
DS
202 e->damp_info = NULL;
203 if (e->parent) {
40381db7 204 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 205
40381db7 206 if (bpi->net) {
0e70e6c8
DL
207 /* FIXME: since multiple e may have the same e->parent
208 * and e->parent->net is holding a refcount for each
209 * of them, we need to do some fudging here.
210 *
40381db7
DS
211 * WARNING: if bpi->net->lock drops to 0, bpi may be
212 * freed as well (because bpi->net was holding the
213 * last reference to bpi) => write after free!
0e70e6c8
DL
214 */
215 unsigned refcount;
216
40381db7
DS
217 bpi = bgp_path_info_lock(bpi);
218 refcount = bpi->net->lock - 1;
219 bgp_unlock_node((struct bgp_node *)bpi->net);
0e70e6c8 220 if (!refcount)
40381db7
DS
221 bpi->net = NULL;
222 bgp_path_info_unlock(bpi);
0e70e6c8 223 }
18ee8310 224 bgp_path_info_unlock(e->parent);
c93a3b77 225 e->parent = NULL;
d62a17ae 226 }
c93a3b77
DS
227
228 if (e->bgp_orig)
229 bgp_unlock(e->bgp_orig);
c26edcda 230
ce3c0614
PG
231 if ((*extra)->bgp_fs_iprule)
232 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 233 if ((*extra)->bgp_fs_pbr)
6a154c88 234 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 235 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
236}
237
18ee8310
DS
238/* Get bgp_path_info extra information for the given bgp_path_info, lazy
239 * allocated if required.
fb982c25 240 */
40381db7 241struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 242{
40381db7
DS
243 if (!pi->extra)
244 pi->extra = bgp_path_info_extra_new();
245 return pi->extra;
fb982c25
PJ
246}
247
718e3744 248/* Free bgp route information. */
9b6d8fcf 249static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 250{
05864da7 251 bgp_attr_unintern(&path->attr);
fb018d25 252
9b6d8fcf
DS
253 bgp_unlink_nexthop(path);
254 bgp_path_info_extra_free(&path->extra);
255 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
256 if (path->net)
257 bgp_addpath_free_info_data(&path->tx_addpath,
258 &path->net->tx_addpath);
718e3744 259
9b6d8fcf 260 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 261
9b6d8fcf 262 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 263}
264
9b6d8fcf 265struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 266{
9b6d8fcf
DS
267 path->lock++;
268 return path;
200df115 269}
270
9b6d8fcf 271struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 272{
9b6d8fcf
DS
273 assert(path && path->lock > 0);
274 path->lock--;
d62a17ae 275
9b6d8fcf 276 if (path->lock == 0) {
200df115 277#if 0
278 zlog_debug ("%s: unlocked and freeing", __func__);
279 zlog_backtrace (LOG_DEBUG);
280#endif
9b6d8fcf 281 bgp_path_info_free(path);
d62a17ae 282 return NULL;
283 }
200df115 284
285#if 0
9b6d8fcf 286 if (path->lock == 1)
200df115 287 {
288 zlog_debug ("%s: unlocked to 1", __func__);
289 zlog_backtrace (LOG_DEBUG);
290 }
291#endif
d62a17ae 292
9b6d8fcf 293 return path;
200df115 294}
295
f009ff26 296/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
297static int bgp_node_set_defer_flag(struct bgp_node *rn, bool delete)
298{
299 struct peer *peer;
300 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 301 bool set_flag = false;
f009ff26 302 struct bgp *bgp = NULL;
303 struct bgp_table *table = NULL;
304 afi_t afi = 0;
305 safi_t safi = 0;
f009ff26 306
307 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
308 * then the route selection is deferred
309 */
2ba1fe69 310 if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 311 return 0;
312
5f9c1aa2 313 if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 314 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 315 zlog_debug(
b54892e0
DS
316 "Route %pRN is in workqueue and being processed, not deferred.",
317 rn);
318
5f9c1aa2 319 return 0;
320 }
321
f009ff26 322 table = bgp_node_table(rn);
323 if (table) {
324 bgp = table->bgp;
325 afi = table->afi;
326 safi = table->safi;
327 }
328
329 for (old_pi = bgp_node_get_bgp_path_info(rn);
330 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
331 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
332 continue;
333
334 /* Route selection is deferred if there is a stale path which
335 * which indicates peer is in restart mode
336 */
36235319
QY
337 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
338 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 339 set_flag = true;
f009ff26 340 } else {
341 /* If the peer is graceful restart capable and peer is
342 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
343 */
344 peer = old_pi->peer;
36235319
QY
345 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
346 && BGP_PEER_RESTARTING_MODE(peer)
347 && (old_pi
348 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 349 set_flag = true;
f009ff26 350 }
351 }
352 if (set_flag)
353 break;
354 }
355
356 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
357 * is active
358 */
2ba1fe69 359 if (set_flag && table) {
f009ff26 360 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
361 SET_FLAG(rn->flags, BGP_NODE_SELECT_DEFER);
f009ff26 362 if (rn->rt_node == NULL)
363 rn->rt_node = listnode_add(
364 bgp->gr_info[afi][safi].route_list, rn);
365 if (BGP_DEBUG(update, UPDATE_OUT))
b54892e0
DS
366 zlog_debug("DEFER route %pRN, rn %p, node %p",
367 rn, rn, rn->rt_node);
f009ff26 368 return 0;
369 }
370 }
371 return -1;
372}
373
40381db7 374void bgp_path_info_add(struct bgp_node *rn, struct bgp_path_info *pi)
718e3744 375{
4b7e6066 376 struct bgp_path_info *top;
718e3744 377
6f94b685 378 top = bgp_node_get_bgp_path_info(rn);
d62a17ae 379
6f94b685 380 pi->next = top;
40381db7 381 pi->prev = NULL;
d62a17ae 382 if (top)
40381db7 383 top->prev = pi;
6f94b685 384 bgp_node_set_bgp_path_info(rn, pi);
d62a17ae 385
40381db7 386 bgp_path_info_lock(pi);
d62a17ae 387 bgp_lock_node(rn);
40381db7 388 peer_lock(pi->peer); /* bgp_path_info peer reference */
f009ff26 389 bgp_node_set_defer_flag(rn, false);
718e3744 390}
391
d62a17ae 392/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 393 completion callback *only* */
40381db7 394void bgp_path_info_reap(struct bgp_node *rn, struct bgp_path_info *pi)
718e3744 395{
40381db7
DS
396 if (pi->next)
397 pi->next->prev = pi->prev;
398 if (pi->prev)
399 pi->prev->next = pi->next;
d62a17ae 400 else
6f94b685 401 bgp_node_set_bgp_path_info(rn, pi->next);
d62a17ae 402
40381db7
DS
403 bgp_path_info_mpath_dequeue(pi);
404 bgp_path_info_unlock(pi);
d62a17ae 405 bgp_unlock_node(rn);
718e3744 406}
407
40381db7 408void bgp_path_info_delete(struct bgp_node *rn, struct bgp_path_info *pi)
b40d939b 409{
40381db7 410 bgp_path_info_set_flag(rn, pi, BGP_PATH_REMOVED);
d62a17ae 411 /* set of previous already took care of pcount */
40381db7 412 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 413}
414
18ee8310 415/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
416 called when a route is deleted and then quickly re-added before the
417 deletion has been processed */
40381db7 418void bgp_path_info_restore(struct bgp_node *rn, struct bgp_path_info *pi)
8d45210e 419{
40381db7 420 bgp_path_info_unset_flag(rn, pi, BGP_PATH_REMOVED);
d62a17ae 421 /* unset of previous already took care of pcount */
40381db7 422 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
423}
424
d62a17ae 425/* Adjust pcount as required */
40381db7 426static void bgp_pcount_adjust(struct bgp_node *rn, struct bgp_path_info *pi)
1a392d46 427{
d62a17ae 428 struct bgp_table *table;
67174041 429
d62a17ae 430 assert(rn && bgp_node_table(rn));
40381db7 431 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 432
d62a17ae 433 table = bgp_node_table(rn);
67174041 434
40381db7 435 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 436 return;
437
40381db7
DS
438 if (!BGP_PATH_COUNTABLE(pi)
439 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 440
40381db7 441 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 442
443 /* slight hack, but more robust against errors. */
40381db7
DS
444 if (pi->peer->pcount[table->afi][table->safi])
445 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 446 else
450971aa 447 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 448 "Asked to decrement 0 prefix count for peer");
40381db7
DS
449 } else if (BGP_PATH_COUNTABLE(pi)
450 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
451 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
452 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 453 }
1a392d46
PJ
454}
455
40381db7
DS
456static int bgp_label_index_differs(struct bgp_path_info *pi1,
457 struct bgp_path_info *pi2)
28d58fd7 458{
40381db7 459 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 460}
1a392d46 461
18ee8310 462/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
463 * This is here primarily to keep prefix-count in check.
464 */
40381db7 465void bgp_path_info_set_flag(struct bgp_node *rn, struct bgp_path_info *pi,
18ee8310 466 uint32_t flag)
1a392d46 467{
40381db7 468 SET_FLAG(pi->flags, flag);
d62a17ae 469
470 /* early bath if we know it's not a flag that changes countability state
471 */
472 if (!CHECK_FLAG(flag,
1defdda8 473 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 474 return;
475
40381db7 476 bgp_pcount_adjust(rn, pi);
1a392d46
PJ
477}
478
40381db7 479void bgp_path_info_unset_flag(struct bgp_node *rn, struct bgp_path_info *pi,
18ee8310 480 uint32_t flag)
1a392d46 481{
40381db7 482 UNSET_FLAG(pi->flags, flag);
d62a17ae 483
484 /* early bath if we know it's not a flag that changes countability state
485 */
486 if (!CHECK_FLAG(flag,
1defdda8 487 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 488 return;
489
40381db7 490 bgp_pcount_adjust(rn, pi);
1a392d46
PJ
491}
492
718e3744 493/* Get MED value. If MED value is missing and "bgp bestpath
494 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 495static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 496{
497 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
498 return attr->med;
499 else {
892fedb6 500 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 501 return BGP_MED_MAX;
502 else
503 return 0;
504 }
718e3744 505}
506
40381db7 507void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf)
2ec1e66f 508{
40381db7
DS
509 if (pi->addpath_rx_id)
510 sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
511 pi->addpath_rx_id);
d62a17ae 512 else
40381db7 513 sprintf(buf, "path %s", pi->peer->host);
d62a17ae 514}
9fbdd100 515
d62a17ae 516/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
517 */
18ee8310
DS
518static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
519 struct bgp_path_info *exist, int *paths_eq,
520 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
521 char *pfx_buf, afi_t afi, safi_t safi,
522 enum bgp_path_selection_reason *reason)
d62a17ae 523{
524 struct attr *newattr, *existattr;
525 bgp_peer_sort_t new_sort;
526 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
527 uint32_t new_pref;
528 uint32_t exist_pref;
529 uint32_t new_med;
530 uint32_t exist_med;
531 uint32_t new_weight;
532 uint32_t exist_weight;
d62a17ae 533 uint32_t newm, existm;
534 struct in_addr new_id;
535 struct in_addr exist_id;
536 int new_cluster;
537 int exist_cluster;
538 int internal_as_route;
539 int confed_as_route;
04d14c8b 540 int ret = 0;
d62a17ae 541 char new_buf[PATH_ADDPATH_STR_BUFFER];
542 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
543 uint32_t new_mm_seq;
544 uint32_t exist_mm_seq;
6d8c603a 545 int nh_cmp;
d62a17ae 546
547 *paths_eq = 0;
548
549 /* 0. Null check. */
550 if (new == NULL) {
fdf81fa0 551 *reason = bgp_path_selection_none;
d62a17ae 552 if (debug)
553 zlog_debug("%s: new is NULL", pfx_buf);
554 return 0;
555 }
2ec1e66f 556
d62a17ae 557 if (debug)
18ee8310 558 bgp_path_info_path_with_addpath_rx_str(new, new_buf);
718e3744 559
d62a17ae 560 if (exist == NULL) {
fdf81fa0 561 *reason = bgp_path_selection_first;
d62a17ae 562 if (debug)
563 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
564 new_buf);
565 return 1;
566 }
2ec1e66f 567
d62a17ae 568 if (debug) {
18ee8310 569 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
d62a17ae 570 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
571 pfx_buf, new_buf, new->flags, exist_buf,
572 exist->flags);
573 }
8ff56318 574
d62a17ae 575 newattr = new->attr;
576 existattr = exist->attr;
577
578 /* For EVPN routes, we cannot just go by local vs remote, we have to
579 * look at the MAC mobility sequence number, if present.
580 */
581 if (safi == SAFI_EVPN) {
582 /* This is an error condition described in RFC 7432 Section
583 * 15.2. The RFC
584 * states that in this scenario "the PE MUST alert the operator"
585 * but it
586 * does not state what other action to take. In order to provide
587 * some
588 * consistency in this scenario we are going to prefer the path
589 * with the
590 * sticky flag.
591 */
592 if (newattr->sticky != existattr->sticky) {
593 if (!debug) {
b54892e0
DS
594 prefix2str(bgp_node_get_prefix(new->net),
595 pfx_buf,
d62a17ae 596 sizeof(*pfx_buf)
597 * PREFIX2STR_BUFFER);
18ee8310
DS
598 bgp_path_info_path_with_addpath_rx_str(new,
599 new_buf);
600 bgp_path_info_path_with_addpath_rx_str(
601 exist, exist_buf);
d62a17ae 602 }
603
604 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 605 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
606 if (debug)
607 zlog_debug(
608 "%s: %s wins over %s due to sticky MAC flag",
609 pfx_buf, new_buf, exist_buf);
d62a17ae 610 return 1;
611 }
612
613 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 614 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
615 if (debug)
616 zlog_debug(
617 "%s: %s loses to %s due to sticky MAC flag",
618 pfx_buf, new_buf, exist_buf);
d62a17ae 619 return 0;
620 }
621 }
128ea8ab 622
d62a17ae 623 new_mm_seq = mac_mobility_seqnum(newattr);
624 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 625
d62a17ae 626 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 627 *reason = bgp_path_selection_evpn_seq;
d62a17ae 628 if (debug)
629 zlog_debug(
630 "%s: %s wins over %s due to MM seq %u > %u",
631 pfx_buf, new_buf, exist_buf, new_mm_seq,
632 exist_mm_seq);
633 return 1;
634 }
8ff56318 635
d62a17ae 636 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 637 *reason = bgp_path_selection_evpn_seq;
d62a17ae 638 if (debug)
639 zlog_debug(
640 "%s: %s loses to %s due to MM seq %u < %u",
641 pfx_buf, new_buf, exist_buf, new_mm_seq,
642 exist_mm_seq);
643 return 0;
644 }
6d8c603a
AK
645
646 /*
647 * if sequence numbers are the same path with the lowest IP
648 * wins
649 */
650 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
651 if (nh_cmp < 0) {
fdf81fa0 652 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
653 if (debug)
654 zlog_debug(
655 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
656 pfx_buf, new_buf, exist_buf, new_mm_seq,
657 inet_ntoa(new->attr->nexthop));
658 return 1;
659 }
660 if (nh_cmp > 0) {
fdf81fa0 661 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
662 if (debug)
663 zlog_debug(
664 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
665 pfx_buf, new_buf, exist_buf, new_mm_seq,
666 inet_ntoa(new->attr->nexthop));
667 return 0;
668 }
d62a17ae 669 }
9fbdd100 670
d62a17ae 671 /* 1. Weight check. */
d62a17ae 672 new_weight = newattr->weight;
673 exist_weight = existattr->weight;
8ff56318 674
d62a17ae 675 if (new_weight > exist_weight) {
fdf81fa0 676 *reason = bgp_path_selection_weight;
d62a17ae 677 if (debug)
678 zlog_debug("%s: %s wins over %s due to weight %d > %d",
679 pfx_buf, new_buf, exist_buf, new_weight,
680 exist_weight);
681 return 1;
682 }
718e3744 683
d62a17ae 684 if (new_weight < exist_weight) {
fdf81fa0 685 *reason = bgp_path_selection_weight;
d62a17ae 686 if (debug)
687 zlog_debug("%s: %s loses to %s due to weight %d < %d",
688 pfx_buf, new_buf, exist_buf, new_weight,
689 exist_weight);
690 return 0;
691 }
9fbdd100 692
d62a17ae 693 /* 2. Local preference check. */
694 new_pref = exist_pref = bgp->default_local_pref;
695
696 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
697 new_pref = newattr->local_pref;
698 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
699 exist_pref = existattr->local_pref;
700
701 if (new_pref > exist_pref) {
fdf81fa0 702 *reason = bgp_path_selection_local_pref;
d62a17ae 703 if (debug)
704 zlog_debug(
705 "%s: %s wins over %s due to localpref %d > %d",
706 pfx_buf, new_buf, exist_buf, new_pref,
707 exist_pref);
708 return 1;
709 }
718e3744 710
d62a17ae 711 if (new_pref < exist_pref) {
fdf81fa0 712 *reason = bgp_path_selection_local_pref;
d62a17ae 713 if (debug)
714 zlog_debug(
715 "%s: %s loses to %s due to localpref %d < %d",
716 pfx_buf, new_buf, exist_buf, new_pref,
717 exist_pref);
718 return 0;
719 }
9fbdd100 720
d62a17ae 721 /* 3. Local route check. We prefer:
722 * - BGP_ROUTE_STATIC
723 * - BGP_ROUTE_AGGREGATE
724 * - BGP_ROUTE_REDISTRIBUTE
725 */
90f4f482 726 if (!(new->sub_type == BGP_ROUTE_NORMAL ||
727 new->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 728 *reason = bgp_path_selection_local_route;
d62a17ae 729 if (debug)
730 zlog_debug(
731 "%s: %s wins over %s due to preferred BGP_ROUTE type",
732 pfx_buf, new_buf, exist_buf);
733 return 1;
734 }
718e3744 735
90f4f482 736 if (!(exist->sub_type == BGP_ROUTE_NORMAL ||
88493076 737 exist->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 738 *reason = bgp_path_selection_local_route;
d62a17ae 739 if (debug)
740 zlog_debug(
741 "%s: %s loses to %s due to preferred BGP_ROUTE type",
742 pfx_buf, new_buf, exist_buf);
743 return 0;
6811845b 744 }
718e3744 745
d62a17ae 746 /* 4. AS path length check. */
892fedb6 747 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 748 int exist_hops = aspath_count_hops(existattr->aspath);
749 int exist_confeds = aspath_count_confeds(existattr->aspath);
750
892fedb6 751 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 752 int aspath_hops;
753
754 aspath_hops = aspath_count_hops(newattr->aspath);
755 aspath_hops += aspath_count_confeds(newattr->aspath);
756
757 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 758 *reason = bgp_path_selection_confed_as_path;
d62a17ae 759 if (debug)
760 zlog_debug(
761 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
762 pfx_buf, new_buf, exist_buf,
763 aspath_hops,
764 (exist_hops + exist_confeds));
765 return 1;
766 }
767
768 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 769 *reason = bgp_path_selection_confed_as_path;
d62a17ae 770 if (debug)
771 zlog_debug(
772 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
773 pfx_buf, new_buf, exist_buf,
774 aspath_hops,
775 (exist_hops + exist_confeds));
776 return 0;
777 }
778 } else {
779 int newhops = aspath_count_hops(newattr->aspath);
780
781 if (newhops < exist_hops) {
fdf81fa0 782 *reason = bgp_path_selection_as_path;
d62a17ae 783 if (debug)
784 zlog_debug(
785 "%s: %s wins over %s due to aspath hopcount %d < %d",
786 pfx_buf, new_buf, exist_buf,
787 newhops, exist_hops);
788 return 1;
789 }
790
791 if (newhops > exist_hops) {
fdf81fa0 792 *reason = bgp_path_selection_as_path;
d62a17ae 793 if (debug)
794 zlog_debug(
795 "%s: %s loses to %s due to aspath hopcount %d > %d",
796 pfx_buf, new_buf, exist_buf,
797 newhops, exist_hops);
798 return 0;
799 }
800 }
801 }
9fbdd100 802
d62a17ae 803 /* 5. Origin check. */
804 if (newattr->origin < existattr->origin) {
fdf81fa0 805 *reason = bgp_path_selection_origin;
d62a17ae 806 if (debug)
807 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
808 pfx_buf, new_buf, exist_buf,
809 bgp_origin_long_str[newattr->origin],
810 bgp_origin_long_str[existattr->origin]);
811 return 1;
812 }
718e3744 813
d62a17ae 814 if (newattr->origin > existattr->origin) {
fdf81fa0 815 *reason = bgp_path_selection_origin;
d62a17ae 816 if (debug)
817 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
818 pfx_buf, new_buf, exist_buf,
819 bgp_origin_long_str[newattr->origin],
820 bgp_origin_long_str[existattr->origin]);
821 return 0;
822 }
718e3744 823
d62a17ae 824 /* 6. MED check. */
825 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
826 && aspath_count_hops(existattr->aspath) == 0);
827 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
828 && aspath_count_confeds(existattr->aspath) > 0
829 && aspath_count_hops(newattr->aspath) == 0
830 && aspath_count_hops(existattr->aspath) == 0);
831
892fedb6
DA
832 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
833 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 834 || aspath_cmp_left(newattr->aspath, existattr->aspath)
835 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
836 || internal_as_route) {
837 new_med = bgp_med_value(new->attr, bgp);
838 exist_med = bgp_med_value(exist->attr, bgp);
839
840 if (new_med < exist_med) {
fdf81fa0 841 *reason = bgp_path_selection_med;
d62a17ae 842 if (debug)
843 zlog_debug(
844 "%s: %s wins over %s due to MED %d < %d",
845 pfx_buf, new_buf, exist_buf, new_med,
846 exist_med);
847 return 1;
848 }
8ff56318 849
d62a17ae 850 if (new_med > exist_med) {
fdf81fa0 851 *reason = bgp_path_selection_med;
d62a17ae 852 if (debug)
853 zlog_debug(
854 "%s: %s loses to %s due to MED %d > %d",
855 pfx_buf, new_buf, exist_buf, new_med,
856 exist_med);
857 return 0;
858 }
859 }
9fbdd100 860
d62a17ae 861 /* 7. Peer type check. */
862 new_sort = new->peer->sort;
863 exist_sort = exist->peer->sort;
864
865 if (new_sort == BGP_PEER_EBGP
866 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 867 *reason = bgp_path_selection_peer;
d62a17ae 868 if (debug)
869 zlog_debug(
870 "%s: %s wins over %s due to eBGP peer > iBGP peer",
871 pfx_buf, new_buf, exist_buf);
872 return 1;
873 }
718e3744 874
d62a17ae 875 if (exist_sort == BGP_PEER_EBGP
876 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 877 *reason = bgp_path_selection_peer;
d62a17ae 878 if (debug)
879 zlog_debug(
880 "%s: %s loses to %s due to iBGP peer < eBGP peer",
881 pfx_buf, new_buf, exist_buf);
882 return 0;
883 }
8ff56318 884
d62a17ae 885 /* 8. IGP metric check. */
886 newm = existm = 0;
8ff56318 887
d62a17ae 888 if (new->extra)
889 newm = new->extra->igpmetric;
890 if (exist->extra)
891 existm = exist->extra->igpmetric;
9fbdd100 892
d62a17ae 893 if (newm < existm) {
894 if (debug)
895 zlog_debug(
896 "%s: %s wins over %s due to IGP metric %d < %d",
897 pfx_buf, new_buf, exist_buf, newm, existm);
898 ret = 1;
899 }
718e3744 900
d62a17ae 901 if (newm > existm) {
902 if (debug)
903 zlog_debug(
904 "%s: %s loses to %s due to IGP metric %d > %d",
905 pfx_buf, new_buf, exist_buf, newm, existm);
906 ret = 0;
5e242b0d 907 }
5e242b0d 908
d62a17ae 909 /* 9. Same IGP metric. Compare the cluster list length as
910 representative of IGP hops metric. Rewrite the metric value
911 pair (newm, existm) with the cluster list length. Prefer the
912 path with smaller cluster list length. */
913 if (newm == existm) {
bf0d28dc
DS
914 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
915 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
d62a17ae 916 && (mpath_cfg == NULL
917 || CHECK_FLAG(
918 mpath_cfg->ibgp_flags,
919 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
920 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
921 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
922
923 if (newm < existm) {
924 if (debug)
925 zlog_debug(
926 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
927 pfx_buf, new_buf, exist_buf,
928 newm, existm);
929 ret = 1;
930 }
931
932 if (newm > existm) {
933 if (debug)
934 zlog_debug(
935 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
936 pfx_buf, new_buf, exist_buf,
937 newm, existm);
938 ret = 0;
939 }
940 }
941 }
31a4638f 942
d62a17ae 943 /* 10. confed-external vs. confed-internal */
944 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
945 if (new_sort == BGP_PEER_CONFED
946 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 947 *reason = bgp_path_selection_confed;
d62a17ae 948 if (debug)
949 zlog_debug(
950 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
951 pfx_buf, new_buf, exist_buf);
952 return 1;
953 }
718e3744 954
d62a17ae 955 if (exist_sort == BGP_PEER_CONFED
956 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 957 *reason = bgp_path_selection_confed;
d62a17ae 958 if (debug)
959 zlog_debug(
960 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
961 pfx_buf, new_buf, exist_buf);
962 return 0;
963 }
964 }
718e3744 965
d62a17ae 966 /* 11. Maximum path check. */
967 if (newm == existm) {
968 /* If one path has a label but the other does not, do not treat
969 * them as equals for multipath
970 */
a4d82a8a 971 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 972 != (exist->extra
b57ba6d2 973 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 974 if (debug)
975 zlog_debug(
976 "%s: %s and %s cannot be multipath, one has a label while the other does not",
977 pfx_buf, new_buf, exist_buf);
892fedb6
DA
978 } else if (CHECK_FLAG(bgp->flags,
979 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 980
981 /*
982 * For the two paths, all comparison steps till IGP
983 * metric
984 * have succeeded - including AS_PATH hop count. Since
985 * 'bgp
986 * bestpath as-path multipath-relax' knob is on, we
987 * don't need
988 * an exact match of AS_PATH. Thus, mark the paths are
989 * equal.
990 * That will trigger both these paths to get into the
991 * multipath
992 * array.
993 */
994 *paths_eq = 1;
995
996 if (debug)
997 zlog_debug(
998 "%s: %s and %s are equal via multipath-relax",
999 pfx_buf, new_buf, exist_buf);
1000 } else if (new->peer->sort == BGP_PEER_IBGP) {
1001 if (aspath_cmp(new->attr->aspath,
1002 exist->attr->aspath)) {
1003 *paths_eq = 1;
1004
1005 if (debug)
1006 zlog_debug(
1007 "%s: %s and %s are equal via matching aspaths",
1008 pfx_buf, new_buf, exist_buf);
1009 }
1010 } else if (new->peer->as == exist->peer->as) {
1011 *paths_eq = 1;
1012
1013 if (debug)
1014 zlog_debug(
1015 "%s: %s and %s are equal via same remote-as",
1016 pfx_buf, new_buf, exist_buf);
1017 }
1018 } else {
1019 /*
1020 * TODO: If unequal cost ibgp multipath is enabled we can
1021 * mark the paths as equal here instead of returning
1022 */
1023 if (debug) {
1024 if (ret == 1)
1025 zlog_debug(
1026 "%s: %s wins over %s after IGP metric comparison",
1027 pfx_buf, new_buf, exist_buf);
1028 else
1029 zlog_debug(
1030 "%s: %s loses to %s after IGP metric comparison",
1031 pfx_buf, new_buf, exist_buf);
1032 }
fdf81fa0 1033 *reason = bgp_path_selection_igp_metric;
d62a17ae 1034 return ret;
1035 }
718e3744 1036
d62a17ae 1037 /* 12. If both paths are external, prefer the path that was received
1038 first (the oldest one). This step minimizes route-flap, since a
1039 newer path won't displace an older one, even if it was the
1040 preferred route based on the additional decision criteria below. */
892fedb6 1041 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1042 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1043 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1044 *reason = bgp_path_selection_older;
d62a17ae 1045 if (debug)
1046 zlog_debug(
1047 "%s: %s wins over %s due to oldest external",
1048 pfx_buf, new_buf, exist_buf);
1049 return 1;
1050 }
9fbdd100 1051
1defdda8 1052 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1053 *reason = bgp_path_selection_older;
d62a17ae 1054 if (debug)
1055 zlog_debug(
1056 "%s: %s loses to %s due to oldest external",
1057 pfx_buf, new_buf, exist_buf);
1058 return 0;
1059 }
1060 }
718e3744 1061
d62a17ae 1062 /* 13. Router-ID comparision. */
1063 /* If one of the paths is "stale", the corresponding peer router-id will
1064 * be 0 and would always win over the other path. If originator id is
1065 * used for the comparision, it will decide which path is better.
1066 */
1067 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1068 new_id.s_addr = newattr->originator_id.s_addr;
1069 else
1070 new_id.s_addr = new->peer->remote_id.s_addr;
1071 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1072 exist_id.s_addr = existattr->originator_id.s_addr;
1073 else
1074 exist_id.s_addr = exist->peer->remote_id.s_addr;
1075
1076 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1077 *reason = bgp_path_selection_router_id;
d62a17ae 1078 if (debug)
1079 zlog_debug(
1080 "%s: %s wins over %s due to Router-ID comparison",
1081 pfx_buf, new_buf, exist_buf);
1082 return 1;
1083 }
718e3744 1084
d62a17ae 1085 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1086 *reason = bgp_path_selection_router_id;
d62a17ae 1087 if (debug)
1088 zlog_debug(
1089 "%s: %s loses to %s due to Router-ID comparison",
1090 pfx_buf, new_buf, exist_buf);
1091 return 0;
1092 }
9fbdd100 1093
d62a17ae 1094 /* 14. Cluster length comparision. */
1095 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1096 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1097
1098 if (new_cluster < exist_cluster) {
fdf81fa0 1099 *reason = bgp_path_selection_cluster_length;
d62a17ae 1100 if (debug)
1101 zlog_debug(
1102 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1103 pfx_buf, new_buf, exist_buf, new_cluster,
1104 exist_cluster);
1105 return 1;
1106 }
718e3744 1107
d62a17ae 1108 if (new_cluster > exist_cluster) {
fdf81fa0 1109 *reason = bgp_path_selection_cluster_length;
d62a17ae 1110 if (debug)
1111 zlog_debug(
1112 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1113 pfx_buf, new_buf, exist_buf, new_cluster,
1114 exist_cluster);
1115 return 0;
1116 }
9fbdd100 1117
d62a17ae 1118 /* 15. Neighbor address comparision. */
1119 /* Do this only if neither path is "stale" as stale paths do not have
1120 * valid peer information (as the connection may or may not be up).
1121 */
1defdda8 1122 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1123 *reason = bgp_path_selection_stale;
d62a17ae 1124 if (debug)
1125 zlog_debug(
1126 "%s: %s wins over %s due to latter path being STALE",
1127 pfx_buf, new_buf, exist_buf);
1128 return 1;
1129 }
0de5153c 1130
1defdda8 1131 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1132 *reason = bgp_path_selection_stale;
d62a17ae 1133 if (debug)
1134 zlog_debug(
1135 "%s: %s loses to %s due to former path being STALE",
1136 pfx_buf, new_buf, exist_buf);
1137 return 0;
1138 }
718e3744 1139
d62a17ae 1140 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1141 if (new->peer->su_remote == NULL) {
1142 *reason = bgp_path_selection_local_configured;
d62a17ae 1143 return 0;
fdf81fa0
DS
1144 }
1145 if (exist->peer->su_remote == NULL) {
1146 *reason = bgp_path_selection_local_configured;
d62a17ae 1147 return 1;
fdf81fa0 1148 }
9fbdd100 1149
d62a17ae 1150 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1151
1152 if (ret == 1) {
fdf81fa0 1153 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1154 if (debug)
1155 zlog_debug(
1156 "%s: %s loses to %s due to Neighor IP comparison",
1157 pfx_buf, new_buf, exist_buf);
1158 return 0;
1159 }
1160
1161 if (ret == -1) {
fdf81fa0 1162 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1163 if (debug)
1164 zlog_debug(
1165 "%s: %s wins over %s due to Neighor IP comparison",
1166 pfx_buf, new_buf, exist_buf);
1167 return 1;
1168 }
9fbdd100 1169
fdf81fa0 1170 *reason = bgp_path_selection_default;
d62a17ae 1171 if (debug)
1172 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1173 pfx_buf, new_buf, exist_buf);
718e3744 1174
d62a17ae 1175 return 1;
718e3744 1176}
1177
65efcfce
LB
1178/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1179 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1180 * multipath is enabled
65efcfce 1181 * This version is compatible with */
18ee8310
DS
1182int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1183 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1184 afi_t afi, safi_t safi,
1185 enum bgp_path_selection_reason *reason)
d62a17ae 1186{
1187 int paths_eq;
1188 int ret;
18ee8310 1189 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1190 afi, safi, reason);
d62a17ae 1191
1192 if (paths_eq)
1193 ret = 0;
1194 else {
1195 if (ret == 1)
1196 ret = -1;
1197 else
1198 ret = 1;
1199 }
1200 return ret;
65efcfce
LB
1201}
1202
5a1ae2c2
DS
1203static enum filter_type bgp_input_filter(struct peer *peer,
1204 const struct prefix *p,
d62a17ae 1205 struct attr *attr, afi_t afi,
1206 safi_t safi)
718e3744 1207{
d62a17ae 1208 struct bgp_filter *filter;
718e3744 1209
d62a17ae 1210 filter = &peer->filter[afi][safi];
718e3744 1211
d62a17ae 1212#define FILTER_EXIST_WARN(F, f, filter) \
1213 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1214 zlog_debug("%s: Could not find configured input %s-list %s!", \
1215 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1216
1217 if (DISTRIBUTE_IN_NAME(filter)) {
1218 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1219
1220 if (access_list_apply(DISTRIBUTE_IN(filter), p) == FILTER_DENY)
1221 return FILTER_DENY;
1222 }
1223
1224 if (PREFIX_LIST_IN_NAME(filter)) {
1225 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1226
1227 if (prefix_list_apply(PREFIX_LIST_IN(filter), p) == PREFIX_DENY)
1228 return FILTER_DENY;
1229 }
1230
1231 if (FILTER_LIST_IN_NAME(filter)) {
1232 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1233
1234 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
1235 == AS_FILTER_DENY)
1236 return FILTER_DENY;
1237 }
1238
1239 return FILTER_PERMIT;
650f76c2 1240#undef FILTER_EXIST_WARN
718e3744 1241}
1242
b8685f9b
DS
1243static enum filter_type bgp_output_filter(struct peer *peer,
1244 const struct prefix *p,
d62a17ae 1245 struct attr *attr, afi_t afi,
1246 safi_t safi)
718e3744 1247{
d62a17ae 1248 struct bgp_filter *filter;
1249
1250 filter = &peer->filter[afi][safi];
1251
1252#define FILTER_EXIST_WARN(F, f, filter) \
1253 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1254 zlog_debug("%s: Could not find configured output %s-list %s!", \
1255 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1256
d62a17ae 1257 if (DISTRIBUTE_OUT_NAME(filter)) {
1258 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1259
d62a17ae 1260 if (access_list_apply(DISTRIBUTE_OUT(filter), p) == FILTER_DENY)
1261 return FILTER_DENY;
1262 }
1263
1264 if (PREFIX_LIST_OUT_NAME(filter)) {
1265 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1266
d62a17ae 1267 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
1268 == PREFIX_DENY)
1269 return FILTER_DENY;
1270 }
718e3744 1271
d62a17ae 1272 if (FILTER_LIST_OUT_NAME(filter)) {
1273 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1274
d62a17ae 1275 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
1276 == AS_FILTER_DENY)
1277 return FILTER_DENY;
1278 }
718e3744 1279
d62a17ae 1280 return FILTER_PERMIT;
650f76c2 1281#undef FILTER_EXIST_WARN
718e3744 1282}
1283
1284/* If community attribute includes no_export then return 1. */
3dc339cd 1285static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1286{
1287 if (attr->community) {
1288 /* NO_ADVERTISE check. */
1289 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
3dc339cd 1290 return true;
d62a17ae 1291
1292 /* NO_EXPORT check. */
1293 if (peer->sort == BGP_PEER_EBGP
1294 && community_include(attr->community, COMMUNITY_NO_EXPORT))
3dc339cd 1295 return true;
d62a17ae 1296
1297 /* NO_EXPORT_SUBCONFED check. */
1298 if (peer->sort == BGP_PEER_EBGP
1299 || peer->sort == BGP_PEER_CONFED)
1300 if (community_include(attr->community,
1301 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1302 return true;
d62a17ae 1303 }
3dc339cd 1304 return false;
718e3744 1305}
1306
1307/* Route reflection loop check. */
3dc339cd 1308static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1309{
d62a17ae 1310 struct in_addr cluster_id;
718e3744 1311
d62a17ae 1312 if (attr->cluster) {
1313 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1314 cluster_id = peer->bgp->cluster_id;
1315 else
1316 cluster_id = peer->bgp->router_id;
1317
1318 if (cluster_loop_check(attr->cluster, cluster_id))
3dc339cd 1319 return true;
d62a17ae 1320 }
3dc339cd 1321 return false;
718e3744 1322}
6b0655a2 1323
5a1ae2c2 1324static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1325 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1326 const char *rmap_name, mpls_label_t *label,
196c6b09 1327 uint32_t num_labels, struct bgp_node *rn)
718e3744 1328{
d62a17ae 1329 struct bgp_filter *filter;
82b692c0
LK
1330 struct bgp_path_info rmap_path = { 0 };
1331 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1332 route_map_result_t ret;
1333 struct route_map *rmap = NULL;
718e3744 1334
d62a17ae 1335 filter = &peer->filter[afi][safi];
718e3744 1336
d62a17ae 1337 /* Apply default weight value. */
1338 if (peer->weight[afi][safi])
1339 attr->weight = peer->weight[afi][safi];
718e3744 1340
d62a17ae 1341 if (rmap_name) {
1342 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1343
d62a17ae 1344 if (rmap == NULL)
1345 return RMAP_DENY;
1346 } else {
1347 if (ROUTE_MAP_IN_NAME(filter)) {
1348 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1349
d62a17ae 1350 if (rmap == NULL)
1351 return RMAP_DENY;
1352 }
1353 }
0b16f239 1354
d62a17ae 1355 /* Route map apply. */
1356 if (rmap) {
40381db7 1357 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1358 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1359 rmap_path.peer = peer;
1360 rmap_path.attr = attr;
82b692c0 1361 rmap_path.extra = &extra;
196c6b09
LK
1362 rmap_path.net = rn;
1363
82b692c0
LK
1364 extra.num_labels = num_labels;
1365 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1366 memcpy(extra.label, label,
1367 num_labels * sizeof(mpls_label_t));
718e3744 1368
d62a17ae 1369 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1370
d62a17ae 1371 /* Apply BGP route map to the attribute. */
40381db7 1372 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
0b16f239 1373
d62a17ae 1374 peer->rmap_type = 0;
0b16f239 1375
1f2263be 1376 if (ret == RMAP_DENYMATCH)
d62a17ae 1377 return RMAP_DENY;
0b16f239 1378 }
d62a17ae 1379 return RMAP_PERMIT;
0b16f239
DS
1380}
1381
5f040085 1382static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1383 struct attr *attr, afi_t afi, safi_t safi,
1384 const char *rmap_name)
0b16f239 1385{
40381db7 1386 struct bgp_path_info rmap_path;
d62a17ae 1387 route_map_result_t ret;
1388 struct route_map *rmap = NULL;
d7c0a89a 1389 uint8_t rmap_type;
0b16f239 1390
b787157a
DS
1391 /*
1392 * So if we get to this point and have no rmap_name
1393 * we want to just show the output as it currently
1394 * exists.
1395 */
1396 if (!rmap_name)
1397 return RMAP_PERMIT;
0b16f239 1398
d62a17ae 1399 /* Apply default weight value. */
1400 if (peer->weight[afi][safi])
1401 attr->weight = peer->weight[afi][safi];
0b16f239 1402
b787157a 1403 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1404
b787157a
DS
1405 /*
1406 * If we have a route map name and we do not find
1407 * the routemap that means we have an implicit
1408 * deny.
1409 */
1410 if (rmap == NULL)
1411 return RMAP_DENY;
0b16f239 1412
40381db7 1413 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1414 /* Route map apply. */
b787157a 1415 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1416 rmap_path.peer = peer;
1417 rmap_path.attr = attr;
0b16f239 1418
0f672529 1419 rmap_type = peer->rmap_type;
b787157a 1420 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1421
b787157a 1422 /* Apply BGP route map to the attribute. */
40381db7 1423 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
ac41b2a2 1424
0f672529 1425 peer->rmap_type = rmap_type;
b787157a
DS
1426
1427 if (ret == RMAP_DENYMATCH)
1428 /*
1429 * caller has multiple error paths with bgp_attr_flush()
1430 */
1431 return RMAP_DENY;
ac41b2a2 1432
d62a17ae 1433 return RMAP_PERMIT;
718e3744 1434}
6b0655a2 1435
5000f21c 1436/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1437static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1438 struct peer *peer, struct attr *attr)
1439{
1440 if (peer->sort == BGP_PEER_EBGP
1441 && (peer_af_flag_check(peer, afi, safi,
1442 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1443 || peer_af_flag_check(peer, afi, safi,
1444 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1445 || peer_af_flag_check(peer, afi, safi,
1446 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1447 || peer_af_flag_check(peer, afi, safi,
1448 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1449 // Take action on the entire aspath
1450 if (peer_af_flag_check(peer, afi, safi,
1451 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1452 || peer_af_flag_check(peer, afi, safi,
1453 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1454 if (peer_af_flag_check(
1455 peer, afi, safi,
1456 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1457 attr->aspath = aspath_replace_private_asns(
bf26b80e 1458 attr->aspath, bgp->as, peer->as);
d62a17ae 1459
1460 // The entire aspath consists of private ASNs so create
1461 // an empty aspath
1462 else if (aspath_private_as_check(attr->aspath))
1463 attr->aspath = aspath_empty_get();
1464
1465 // There are some public and some private ASNs, remove
1466 // the private ASNs
1467 else
1468 attr->aspath = aspath_remove_private_asns(
bf26b80e 1469 attr->aspath, peer->as);
d62a17ae 1470 }
1471
1472 // 'all' was not specified so the entire aspath must be private
1473 // ASNs
1474 // for us to do anything
1475 else if (aspath_private_as_check(attr->aspath)) {
1476 if (peer_af_flag_check(
1477 peer, afi, safi,
1478 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1479 attr->aspath = aspath_replace_private_asns(
bf26b80e 1480 attr->aspath, bgp->as, peer->as);
d62a17ae 1481 else
1482 attr->aspath = aspath_empty_get();
1483 }
1484 }
5000f21c
DS
1485}
1486
c7122e14 1487/* If this is an EBGP peer with as-override */
d62a17ae 1488static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1489 struct peer *peer, struct attr *attr)
1490{
1491 if (peer->sort == BGP_PEER_EBGP
1492 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1493 if (aspath_single_asn_check(attr->aspath, peer->as))
1494 attr->aspath = aspath_replace_specific_asn(
1495 attr->aspath, peer->as, bgp->as);
1496 }
1497}
1498
7f323236
DW
1499void bgp_attr_add_gshut_community(struct attr *attr)
1500{
1501 struct community *old;
1502 struct community *new;
1503 struct community *merge;
1504 struct community *gshut;
1505
1506 old = attr->community;
1507 gshut = community_str2com("graceful-shutdown");
1508
990f4f91 1509 assert(gshut);
1510
7f323236
DW
1511 if (old) {
1512 merge = community_merge(community_dup(old), gshut);
1513
a4d82a8a 1514 if (old->refcnt == 0)
3c1f53de 1515 community_free(&old);
7f323236
DW
1516
1517 new = community_uniq_sort(merge);
3c1f53de 1518 community_free(&merge);
7f323236
DW
1519 } else {
1520 new = community_dup(gshut);
1521 }
1522
3c1f53de 1523 community_free(&gshut);
7f323236
DW
1524 attr->community = new;
1525 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1526
1527 /* When we add the graceful-shutdown community we must also
1528 * lower the local-preference */
1529 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1530 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1531}
1532
1533
d7c0a89a 1534static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1535{
960035b2 1536 if (family == AF_INET) {
975a328e
DA
1537 attr->nexthop.s_addr = INADDR_ANY;
1538 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1539 }
d62a17ae 1540 if (family == AF_INET6)
1541 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1542 if (family == AF_EVPN)
1543 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1544}
1545
3dc339cd 1546bool subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
b8685f9b
DS
1547 struct update_subgroup *subgrp,
1548 const struct prefix *p, struct attr *attr)
d62a17ae 1549{
1550 struct bgp_filter *filter;
1551 struct peer *from;
1552 struct peer *peer;
1553 struct peer *onlypeer;
1554 struct bgp *bgp;
40381db7 1555 struct attr *piattr;
d62a17ae 1556 char buf[PREFIX_STRLEN];
b68885f9 1557 route_map_result_t ret;
d62a17ae 1558 int transparent;
1559 int reflect;
1560 afi_t afi;
1561 safi_t safi;
1562 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1563 bool nh_reset = false;
1564 uint64_t cum_bw;
d62a17ae 1565
1566 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1567 return false;
d62a17ae 1568
1569 afi = SUBGRP_AFI(subgrp);
1570 safi = SUBGRP_SAFI(subgrp);
1571 peer = SUBGRP_PEER(subgrp);
1572 onlypeer = NULL;
1573 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1574 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1575
40381db7 1576 from = pi->peer;
d62a17ae 1577 filter = &peer->filter[afi][safi];
1578 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1579 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1580 : pi->attr;
3f9c7369 1581
49e5a4a0 1582#ifdef ENABLE_BGP_VNC
d62a17ae 1583 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1584 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1585 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1586
1587 /*
1588 * direct and direct_ext type routes originate internally even
1589 * though they can have peer pointers that reference other
1590 * systems
1591 */
1592 prefix2str(p, buf, PREFIX_STRLEN);
1593 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1594 __func__, buf);
1595 samepeer_safe = 1;
1596 }
65efcfce
LB
1597#endif
1598
ddb5b488
PZ
1599 if (((afi == AFI_IP) || (afi == AFI_IP6))
1600 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1601 && (pi->type == ZEBRA_ROUTE_BGP)
1602 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1603
1604 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1605
1606 samepeer_safe = 1;
1607 }
1608
d62a17ae 1609 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1610 * pi is valid */
1611 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1612 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1613 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1614 return false;
d62a17ae 1615 }
adbac85e 1616
d62a17ae 1617 /* If this is not the bestpath then check to see if there is an enabled
1618 * addpath
1619 * feature that requires us to advertise it */
40381db7 1620 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1621 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1622 return false;
d62a17ae 1623 }
1624 }
06370dac 1625
d62a17ae 1626 /* Aggregate-address suppress check. */
40381db7 1627 if (pi->extra && pi->extra->suppress)
d62a17ae 1628 if (!UNSUPPRESS_MAP_NAME(filter)) {
3dc339cd 1629 return false;
d62a17ae 1630 }
3f9c7369 1631
13b7e7f0
DS
1632 /*
1633 * If we are doing VRF 2 VRF leaking via the import
1634 * statement, we want to prevent the route going
1635 * off box as that the RT and RD created are localy
1636 * significant and globaly useless.
1637 */
40381db7
DS
1638 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1639 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1640 return false;
13b7e7f0 1641
d62a17ae 1642 /* If it's labeled safi, make sure the route has a valid label. */
1643 if (safi == SAFI_LABELED_UNICAST) {
40381db7 1644 mpls_label_t label = bgp_adv_label(rn, pi, peer, afi, safi);
d62a17ae 1645 if (!bgp_is_valid_label(&label)) {
1646 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1647 zlog_debug("u%" PRIu64 ":s%" PRIu64
1648 " %s/%d is filtered - no label (%p)",
1649 subgrp->update_group->id, subgrp->id,
1650 inet_ntop(p->family, &p->u.prefix,
1651 buf, SU_ADDRSTRLEN),
1652 p->prefixlen, &label);
3dc339cd 1653 return false;
d62a17ae 1654 }
1655 }
cd1964ff 1656
d62a17ae 1657 /* Do not send back route to sender. */
1658 if (onlypeer && from == onlypeer) {
3dc339cd 1659 return false;
d62a17ae 1660 }
3f9c7369 1661
d62a17ae 1662 /* Do not send the default route in the BGP table if the neighbor is
1663 * configured for default-originate */
1664 if (CHECK_FLAG(peer->af_flags[afi][safi],
1665 PEER_FLAG_DEFAULT_ORIGINATE)) {
1666 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1667 return false;
d62a17ae 1668 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1669 return false;
d62a17ae 1670 }
4125bb67 1671
d62a17ae 1672 /* Transparency check. */
1673 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1674 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1675 transparent = 1;
1676 else
1677 transparent = 0;
1678
1679 /* If community is not disabled check the no-export and local. */
40381db7 1680 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1681 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1682 zlog_debug(
1683 "subgrpannouncecheck: community filter check fail");
3dc339cd 1684 return false;
d62a17ae 1685 }
3f9c7369 1686
d62a17ae 1687 /* If the attribute has originator-id and it is same as remote
1688 peer's id. */
40381db7
DS
1689 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1690 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1691 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1692 zlog_debug(
1693 "%s [Update:SEND] %s originator-id is same as "
1694 "remote router-id",
1695 onlypeer->host,
1696 prefix2str(p, buf, sizeof(buf)));
3dc339cd 1697 return false;
d62a17ae 1698 }
3f9c7369 1699
d62a17ae 1700 /* ORF prefix-list filter check */
1701 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1702 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1703 || CHECK_FLAG(peer->af_cap[afi][safi],
1704 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1705 if (peer->orf_plist[afi][safi]) {
1706 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1707 == PREFIX_DENY) {
1708 if (bgp_debug_update(NULL, p,
1709 subgrp->update_group, 0))
1710 zlog_debug(
1711 "%s [Update:SEND] %s is filtered via ORF",
1712 peer->host,
1713 prefix2str(p, buf,
1714 sizeof(buf)));
3dc339cd 1715 return false;
d62a17ae 1716 }
1717 }
1718
1719 /* Output filter check. */
40381db7 1720 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1721 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1722 zlog_debug("%s [Update:SEND] %s is filtered",
1723 peer->host, prefix2str(p, buf, sizeof(buf)));
3dc339cd 1724 return false;
d62a17ae 1725 }
3f9c7369 1726
d62a17ae 1727 /* AS path loop check. */
2b31007c
RZ
1728 if (onlypeer && onlypeer->as_path_loop_detection
1729 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1730 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1731 zlog_debug(
1732 "%s [Update:SEND] suppress announcement to peer AS %u "
1733 "that is part of AS path.",
1734 onlypeer->host, onlypeer->as);
3dc339cd 1735 return false;
d62a17ae 1736 }
3f9c7369 1737
d62a17ae 1738 /* If we're a CONFED we need to loop check the CONFED ID too */
1739 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1740 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1741 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1742 zlog_debug(
1743 "%s [Update:SEND] suppress announcement to peer AS %u"
1744 " is AS path.",
1745 peer->host, bgp->confed_id);
3dc339cd 1746 return false;
d62a17ae 1747 }
3f9c7369 1748 }
3f9c7369 1749
d62a17ae 1750 /* Route-Reflect check. */
1751 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1752 reflect = 1;
1753 else
1754 reflect = 0;
1755
1756 /* IBGP reflection check. */
1757 if (reflect && !samepeer_safe) {
1758 /* A route from a Client peer. */
1759 if (CHECK_FLAG(from->af_flags[afi][safi],
1760 PEER_FLAG_REFLECTOR_CLIENT)) {
1761 /* Reflect to all the Non-Client peers and also to the
1762 Client peers other than the originator. Originator
1763 check
1764 is already done. So there is noting to do. */
1765 /* no bgp client-to-client reflection check. */
892fedb6
DA
1766 if (CHECK_FLAG(bgp->flags,
1767 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 1768 if (CHECK_FLAG(peer->af_flags[afi][safi],
1769 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1770 return false;
d62a17ae 1771 } else {
1772 /* A route from a Non-client peer. Reflect to all other
1773 clients. */
1774 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1775 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1776 return false;
d62a17ae 1777 }
1778 }
3f9c7369 1779
d62a17ae 1780 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1781 *attr = *piattr;
d62a17ae 1782
1783 /* If local-preference is not set. */
1784 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1785 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1786 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1787 attr->local_pref = bgp->default_local_pref;
3f9c7369 1788 }
3f9c7369 1789
d62a17ae 1790 /* If originator-id is not set and the route is to be reflected,
1791 set the originator id */
1792 if (reflect
1793 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1794 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1795 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1796 }
3f9c7369 1797
d62a17ae 1798 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1799 */
1800 if (peer->sort == BGP_PEER_EBGP
1801 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1802 if (from != bgp->peer_self && !transparent
1803 && !CHECK_FLAG(peer->af_flags[afi][safi],
1804 PEER_FLAG_MED_UNCHANGED))
1805 attr->flag &=
1806 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1807 }
3f9c7369 1808
d62a17ae 1809 /* Since the nexthop attribute can vary per peer, it is not explicitly
1810 * set
1811 * in announce check, only certain flags and length (or number of
1812 * nexthops
1813 * -- for IPv6/MP_REACH) are set here in order to guide the update
1814 * formation
1815 * code in setting the nexthop(s) on a per peer basis in
1816 * reformat_peer().
1817 * Typically, the source nexthop in the attribute is preserved but in
1818 * the
1819 * scenarios where we know it will always be overwritten, we reset the
1820 * nexthop to "0" in an attempt to achieve better Update packing. An
1821 * example of this is when a prefix from each of 2 IBGP peers needs to
1822 * be
1823 * announced to an EBGP peer (and they have the same attributes barring
1824 * their nexthop).
1825 */
1826 if (reflect)
1827 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1828
1829#define NEXTHOP_IS_V6 \
1830 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1831 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1832 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1833 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1834
1835 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1836 * if
1837 * the peer (group) is configured to receive link-local nexthop
1838 * unchanged
c728d027
DA
1839 * and it is available in the prefix OR we're not reflecting the route,
1840 * link-local nexthop address is valid and
d62a17ae 1841 * the peer (group) to whom we're going to announce is on a shared
1842 * network
1843 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
1844 * By checking if nexthop LL address is valid we are sure that
1845 * we do not announce LL address as `::`.
d62a17ae 1846 */
1847 if (NEXTHOP_IS_V6) {
1848 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
1849 if ((CHECK_FLAG(peer->af_flags[afi][safi],
1850 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
1851 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
1852 || (!reflect
1853 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
1854 && peer->shared_network
d62a17ae 1855 && (from == bgp->peer_self
1856 || peer->sort == BGP_PEER_EBGP))) {
1857 attr->mp_nexthop_len =
1858 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
1859 }
3f9c7369 1860
d62a17ae 1861 /* Clear off link-local nexthop in source, whenever it is not
1862 * needed to
1863 * ensure more prefixes share the same attribute for
1864 * announcement.
1865 */
1866 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
1867 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
1868 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
1869 }
3f9c7369 1870
d62a17ae 1871 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
1872 bgp_peer_as_override(bgp, afi, safi, peer, attr);
1873
1874 /* Route map & unsuppress-map apply. */
40381db7 1875 if (ROUTE_MAP_OUT_NAME(filter) || (pi->extra && pi->extra->suppress)) {
b8694ef4
DS
1876 struct bgp_path_info rmap_path = {0};
1877 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
1878 struct attr dummy_attr = {0};
d62a17ae 1879
e34291b8 1880 /* Fill temp path_info */
1881 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra,
1882 rn, pi, peer, attr);
16f7ce2b 1883
d62a17ae 1884 /* don't confuse inbound and outbound setting */
1885 RESET_FLAG(attr->rmap_change_flags);
1886
1887 /*
1888 * The route reflector is not allowed to modify the attributes
1889 * of the reflected IBGP routes unless explicitly allowed.
1890 */
1891 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
1892 && !CHECK_FLAG(bgp->flags,
1893 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 1894 dummy_attr = *attr;
40381db7 1895 rmap_path.attr = &dummy_attr;
d62a17ae 1896 }
3f9c7369 1897
d62a17ae 1898 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 1899
40381db7 1900 if (pi->extra && pi->extra->suppress)
d62a17ae 1901 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
40381db7 1902 RMAP_BGP, &rmap_path);
d62a17ae 1903 else
1904 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
40381db7 1905 RMAP_BGP, &rmap_path);
d62a17ae 1906
1907 peer->rmap_type = 0;
1908
1909 if (ret == RMAP_DENYMATCH) {
778048bf
AD
1910 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1911 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1912 peer->host, prefix2str(p, buf, sizeof(buf)));
1913
d62a17ae 1914 bgp_attr_flush(attr);
3dc339cd 1915 return false;
d62a17ae 1916 }
3f9c7369 1917 }
3f9c7369 1918
9dac9fc8
DA
1919 /* RFC 8212 to prevent route leaks.
1920 * This specification intends to improve this situation by requiring the
1921 * explicit configuration of both BGP Import and Export Policies for any
1922 * External BGP (EBGP) session such as customers, peers, or
1923 * confederation boundaries for all enabled address families. Through
1924 * codification of the aforementioned requirement, operators will
1925 * benefit from consistent behavior across different BGP
1926 * implementations.
1927 */
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 &&
f7e1c681 2069 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 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
3b0c17e1 2447static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
2448 safi_t safi, struct bgp_node *rn,
2449 struct bgp_path_info *new_select,
2450 struct bgp_path_info *old_select)
2451{
2452 const struct prefix *p = bgp_node_get_prefix(rn);
2453
2454 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2455 return;
2456
2457 if (advertise_type5_routes(bgp, afi) && new_select
2458 && is_route_injectable_into_evpn(new_select)) {
2459
2460 /* apply the route-map */
2461 if (bgp->adv_cmd_rmap[afi][safi].map) {
2462 route_map_result_t ret;
2463 struct bgp_path_info rmap_path;
2464 struct bgp_path_info_extra rmap_path_extra;
2465 struct attr dummy_attr;
2466
2467 dummy_attr = *new_select->attr;
2468
2469 /* Fill temp path_info */
2470 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, rn,
2471 new_select, new_select->peer,
2472 &dummy_attr);
2473
2474 RESET_FLAG(dummy_attr.rmap_change_flags);
2475
2476 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
2477 p, RMAP_BGP, &rmap_path);
2478
2479 if (ret == RMAP_DENYMATCH) {
2480 bgp_attr_flush(&dummy_attr);
2481 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2482 safi);
2483 } else
2484 bgp_evpn_advertise_type5_route(
2485 bgp, p, &dummy_attr, afi, safi);
2486 } else {
2487 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2488 afi, safi);
2489 }
2490 } else if (advertise_type5_routes(bgp, afi) && old_select
2491 && is_route_injectable_into_evpn(old_select))
2492 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2493}
2494
3103e8d2
DS
2495/*
2496 * old_select = The old best path
2497 * new_select = the new best path
2498 *
2499 * if (!old_select && new_select)
2500 * We are sending new information on.
2501 *
2502 * if (old_select && new_select) {
2503 * if (new_select != old_select)
2504 * We have a new best path send a change
2505 * else
2506 * We've received a update with new attributes that needs
2507 * to be passed on.
2508 * }
2509 *
2510 * if (old_select && !new_select)
2511 * We have no eligible route that we can announce or the rn
2512 * is being removed.
2513 */
aac24838
JB
2514static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
2515 afi_t afi, safi_t safi)
d62a17ae 2516{
4b7e6066
DS
2517 struct bgp_path_info *new_select;
2518 struct bgp_path_info *old_select;
2519 struct bgp_path_info_pair old_and_new;
ddb5b488 2520 int debug = 0;
d62a17ae 2521
892fedb6 2522 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
f4c713ae 2523 if (rn)
cb9f254c 2524 debug = bgp_debug_bestpath(rn);
b54892e0 2525 if (debug)
f4c713ae 2526 zlog_debug(
b54892e0
DS
2527 "%s: bgp delete in progress, ignoring event, p=%pRN",
2528 __func__, rn);
f4c713ae
LB
2529 return;
2530 }
d62a17ae 2531 /* Is it end of initial update? (after startup) */
2532 if (!rn) {
2533 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2534 sizeof(bgp->update_delay_zebra_resume_time));
2535
2536 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2537 FOREACH_AFI_SAFI (afi, safi) {
2538 if (bgp_fibupd_safi(safi))
2539 bgp_zebra_announce_table(bgp, afi, safi);
2540 }
d62a17ae 2541 bgp->main_peers_update_hold = 0;
2542
2543 bgp_start_routeadv(bgp);
aac24838 2544 return;
d62a17ae 2545 }
cb1faec9 2546
b54892e0 2547 const struct prefix *p = bgp_node_get_prefix(rn);
b575a12c 2548
cb9f254c 2549 debug = bgp_debug_bestpath(rn);
b54892e0
DS
2550 if (debug)
2551 zlog_debug("%s: p=%pRN afi=%s, safi=%s start", __func__, rn,
ddb5b488 2552 afi2str(afi), safi2str(safi));
ddb5b488 2553
f009ff26 2554 /* The best path calculation for the route is deferred if
2555 * BGP_NODE_SELECT_DEFER is set
2556 */
2557 if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
2558 if (BGP_DEBUG(update, UPDATE_OUT))
2089dd80 2559 zlog_debug("SELECT_DEFER flag set for route %p", rn);
f009ff26 2560 return;
2561 }
2562
d62a17ae 2563 /* Best path selection. */
2564 bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new,
2565 afi, safi);
2566 old_select = old_and_new.old;
2567 new_select = old_and_new.new;
2568
2569 /* Do we need to allocate or free labels?
2570 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2571 * necessary to do this upon changes to best path. Exceptions:
2572 * - label index has changed -> recalculate resulting label
2573 * - path_info sub_type changed -> switch to/from implicit-null
2574 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2575 */
318cac96 2576 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2577 if (new_select) {
2578 if (!old_select
2579 || bgp_label_index_differs(new_select, old_select)
57592a53
AD
2580 || new_select->sub_type != old_select->sub_type
2581 || !bgp_is_valid_label(&rn->local_label)) {
2582 /* Enforced penultimate hop popping:
2583 * implicit-null for local routes, aggregate
2584 * and redistributed routes
2585 */
d62a17ae 2586 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2587 || new_select->sub_type
2588 == BGP_ROUTE_AGGREGATE
2589 || new_select->sub_type
2590 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2591 if (CHECK_FLAG(
2592 rn->flags,
2593 BGP_NODE_REGISTERED_FOR_LABEL))
2594 bgp_unregister_for_label(rn);
70e98a7f 2595 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
d62a17ae 2596 &rn->local_label);
2597 bgp_set_valid_label(&rn->local_label);
2598 } else
2599 bgp_register_for_label(rn, new_select);
2600 }
a4d82a8a
PZ
2601 } else if (CHECK_FLAG(rn->flags,
2602 BGP_NODE_REGISTERED_FOR_LABEL)) {
d62a17ae 2603 bgp_unregister_for_label(rn);
318cac96
DW
2604 }
2605 } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
2606 bgp_unregister_for_label(rn);
d62a17ae 2607 }
cd1964ff 2608
b54892e0 2609 if (debug)
ddb5b488 2610 zlog_debug(
b54892e0
DS
2611 "%s: p=%pRN afi=%s, safi=%s, old_select=%p, new_select=%p",
2612 __func__, rn, afi2str(afi), safi2str(safi),
ddb5b488 2613 old_select, new_select);
ddb5b488 2614
d62a17ae 2615 /* If best route remains the same and this is not due to user-initiated
2616 * clear, see exactly what needs to be done.
2617 */
d62a17ae 2618 if (old_select && old_select == new_select
2619 && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
1defdda8 2620 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2621 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 2622 if (bgp_zebra_has_route_changed(rn, old_select)) {
49e5a4a0 2623#ifdef ENABLE_BGP_VNC
d62a17ae 2624 vnc_import_bgp_add_route(bgp, p, old_select);
2625 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2626#endif
bb744275 2627 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2628 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2629
2630 if (new_select->type == ZEBRA_ROUTE_BGP
2631 && (new_select->sub_type == BGP_ROUTE_NORMAL
2632 || new_select->sub_type
2633 == BGP_ROUTE_IMPORTED))
2634
2635 bgp_zebra_announce(rn, p, old_select,
2636 bgp, afi, safi);
2637 }
d62a17ae 2638 }
d62a17ae 2639
2640 /* If there is a change of interest to peers, reannounce the
2641 * route. */
1defdda8 2642 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 2643 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
d62a17ae 2644 || CHECK_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED)) {
2645 group_announce_route(bgp, afi, safi, rn, new_select);
2646
2647 /* unicast routes must also be annouced to
2648 * labeled-unicast update-groups */
2649 if (safi == SAFI_UNICAST)
2650 group_announce_route(bgp, afi,
2651 SAFI_LABELED_UNICAST, rn,
2652 new_select);
2653
1defdda8 2654 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2655 UNSET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED);
2656 }
fee0f4c6 2657
3b0c17e1 2658 /* advertise/withdraw type-5 routes */
2659 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2660 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2661 bgp_process_evpn_route_injection(
2662 bgp, afi, safi, rn, old_select, old_select);
2663
b1875e65 2664 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2665 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
2666 bgp_zebra_clear_route_change_flags(rn);
d62a17ae 2667 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2668 return;
d62a17ae 2669 }
8ad7271d 2670
d62a17ae 2671 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2672 */
2673 UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR);
2674
2675 /* bestpath has changed; bump version */
2676 if (old_select || new_select) {
2677 bgp_bump_version(rn);
2678
2679 if (!bgp->t_rmap_def_originate_eval) {
2680 bgp_lock(bgp);
2681 thread_add_timer(
2682 bm->master,
2683 update_group_refresh_default_originate_route_map,
2684 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2685 &bgp->t_rmap_def_originate_eval);
2686 }
2687 }
3f9c7369 2688
d62a17ae 2689 if (old_select)
18ee8310 2690 bgp_path_info_unset_flag(rn, old_select, BGP_PATH_SELECTED);
d62a17ae 2691 if (new_select) {
ddb5b488
PZ
2692 if (debug)
2693 zlog_debug("%s: setting SELECTED flag", __func__);
18ee8310
DS
2694 bgp_path_info_set_flag(rn, new_select, BGP_PATH_SELECTED);
2695 bgp_path_info_unset_flag(rn, new_select, BGP_PATH_ATTR_CHANGED);
1defdda8 2696 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 2697 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 2698 }
338b3424 2699
49e5a4a0 2700#ifdef ENABLE_BGP_VNC
d62a17ae 2701 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2702 if (old_select != new_select) {
2703 if (old_select) {
2704 vnc_import_bgp_exterior_del_route(bgp, p,
2705 old_select);
2706 vnc_import_bgp_del_route(bgp, p, old_select);
2707 }
2708 if (new_select) {
2709 vnc_import_bgp_exterior_add_route(bgp, p,
2710 new_select);
2711 vnc_import_bgp_add_route(bgp, p, new_select);
2712 }
2713 }
2714 }
65efcfce
LB
2715#endif
2716
d62a17ae 2717 group_announce_route(bgp, afi, safi, rn, new_select);
2718
2719 /* unicast routes must also be annouced to labeled-unicast update-groups
2720 */
2721 if (safi == SAFI_UNICAST)
2722 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, rn,
2723 new_select);
2724
2725 /* FIB update. */
2726 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2727 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2728 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2729 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2730 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2731 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2732
2733 /* if this is an evpn imported type-5 prefix,
2734 * we need to withdraw the route first to clear
2735 * the nh neigh and the RMAC entry.
2736 */
2737 if (old_select &&
2738 is_route_parent_evpn(old_select))
2739 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2740
d62a17ae 2741 bgp_zebra_announce(rn, p, new_select, bgp, afi, safi);
2b659f33 2742 } else {
d62a17ae 2743 /* Withdraw the route from the kernel. */
2744 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2745 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2746 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2747 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2748
568e10ca 2749 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2750 }
718e3744 2751 }
3064bf43 2752
3b0c17e1 2753 bgp_process_evpn_route_injection(bgp, afi, safi, rn, new_select,
2754 old_select);
5424b7ba 2755
d62a17ae 2756 /* Clear any route change flags. */
2757 bgp_zebra_clear_route_change_flags(rn);
3064bf43 2758
18ee8310 2759 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2760 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
18ee8310 2761 bgp_path_info_reap(rn, old_select);
d62a17ae 2762
2763 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2764 return;
718e3744 2765}
2766
f009ff26 2767/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2768int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2769{
2770 struct bgp_node *rn;
2771 int cnt = 0;
2772 struct afi_safi_info *thread_info;
2773 struct listnode *node = NULL, *nnode = NULL;
2774
2775 if (bgp->gr_info[afi][safi].t_route_select)
2776 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
2777
2778 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
2779 zlog_debug("%s: processing route for %s : cnt %d", __func__,
2780 get_afi_safi_str(afi, safi, false),
2781 listcount(bgp->gr_info[afi][safi].route_list));
f009ff26 2782 }
2783
2784 /* Process the route list */
2785 node = listhead(bgp->gr_info[afi][safi].route_list);
f009ff26 2786 while (node) {
2787 rn = listgetdata(node);
2788 nnode = node->next;
2789 list_delete_node(bgp->gr_info[afi][safi].route_list, node);
2790 rn->rt_node = NULL;
2791
2792 if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
2793 UNSET_FLAG(rn->flags, BGP_NODE_SELECT_DEFER);
2794 bgp_process_main_one(bgp, rn, afi, safi);
2795 cnt++;
2796 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT)
2797 break;
2798 }
2799 node = nnode;
2800 }
2801
9e3b51a7 2802 /* Send EOR message when all routes are processed */
2803 if (list_isempty(bgp->gr_info[afi][safi].route_list)) {
2804 bgp_send_delayed_eor(bgp);
8c48b3b6 2805 /* Send route processing complete message to RIB */
2806 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 2807 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 2808 return 0;
9e3b51a7 2809 }
f009ff26 2810
2811 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 2812
2813 thread_info->afi = afi;
2814 thread_info->safi = safi;
2815 thread_info->bgp = bgp;
2816
2817 /* If there are more routes to be processed, start the
2818 * selection timer
2819 */
2820 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
2821 BGP_ROUTE_SELECT_DELAY,
2822 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 2823 return 0;
2824}
2825
aac24838 2826static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 2827{
aac24838
JB
2828 struct bgp_process_queue *pqnode = data;
2829 struct bgp *bgp = pqnode->bgp;
d62a17ae 2830 struct bgp_table *table;
ac021f40 2831 struct bgp_node *rn;
aac24838
JB
2832
2833 /* eoiu marker */
2834 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
2835 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
2836 /* should always have dedicated wq call */
2837 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
2838 return WQ_SUCCESS;
2839 }
2840
ac021f40
LB
2841 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
2842 rn = STAILQ_FIRST(&pqnode->pqueue);
2843 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
b3e1dd3c 2844 STAILQ_NEXT(rn, pq) = NULL; /* complete unlink */
aac24838 2845 table = bgp_node_table(rn);
ac021f40 2846 /* note, new RNs may be added as part of processing */
aac24838 2847 bgp_process_main_one(bgp, rn, table->afi, table->safi);
cb1faec9 2848
aac24838 2849 bgp_unlock_node(rn);
d62a17ae 2850 bgp_table_unlock(table);
2851 }
aac24838
JB
2852
2853 return WQ_SUCCESS;
2854}
2855
2856static void bgp_processq_del(struct work_queue *wq, void *data)
2857{
2858 struct bgp_process_queue *pqnode = data;
2859
2860 bgp_unlock(pqnode->bgp);
2861
2862 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 2863}
2864
d62a17ae 2865void bgp_process_queue_init(void)
200df115 2866{
0ce1ca80 2867 if (!bm->process_main_queue)
d62a17ae 2868 bm->process_main_queue =
2869 work_queue_new(bm->master, "process_main_queue");
2870
aac24838 2871 bm->process_main_queue->spec.workfunc = &bgp_process_wq;
d62a17ae 2872 bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
2873 bm->process_main_queue->spec.max_retries = 0;
2874 bm->process_main_queue->spec.hold = 50;
2875 /* Use a higher yield value of 50ms for main queue processing */
2876 bm->process_main_queue->spec.yield = 50 * 1000L;
200df115 2877}
2878
cfe8d15a 2879static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
2880{
2881 struct bgp_process_queue *pqnode;
2882
a4d82a8a
PZ
2883 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
2884 sizeof(struct bgp_process_queue));
aac24838
JB
2885
2886 /* unlocked in bgp_processq_del */
2887 pqnode->bgp = bgp_lock(bgp);
2888 STAILQ_INIT(&pqnode->pqueue);
2889
aac24838
JB
2890 return pqnode;
2891}
2892
d62a17ae 2893void bgp_process(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)
fee0f4c6 2894{
aac24838
JB
2895#define ARBITRARY_PROCESS_QLEN 10000
2896 struct work_queue *wq = bm->process_main_queue;
d62a17ae 2897 struct bgp_process_queue *pqnode;
cfe8d15a 2898 int pqnode_reuse = 0;
495f0b13 2899
d62a17ae 2900 /* already scheduled for processing? */
2901 if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED))
2902 return;
2e02b9b2 2903
f009ff26 2904 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
2905 * the workqueue
2906 */
2907 if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
2908 if (BGP_DEBUG(update, UPDATE_OUT))
2909 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
36235319 2910 rn);
f009ff26 2911 return;
2912 }
2913
aac24838 2914 if (wq == NULL)
d62a17ae 2915 return;
2916
aac24838 2917 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
2918 limit only if is from the same BGP view and it's not an EOIU marker
2919 */
aac24838
JB
2920 if (work_queue_item_count(wq)) {
2921 struct work_queue_item *item = work_queue_last_item(wq);
2922 pqnode = item->data;
228da428 2923
a4d82a8a
PZ
2924 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
2925 || pqnode->bgp != bgp
2926 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
2927 pqnode = bgp_processq_alloc(bgp);
2928 else
2929 pqnode_reuse = 1;
aac24838 2930 } else
cfe8d15a 2931 pqnode = bgp_processq_alloc(bgp);
aac24838 2932 /* all unlocked in bgp_process_wq */
d62a17ae 2933 bgp_table_lock(bgp_node_table(rn));
aac24838 2934
d62a17ae 2935 SET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838
JB
2936 bgp_lock_node(rn);
2937
60466a63
QY
2938 /* can't be enqueued twice */
2939 assert(STAILQ_NEXT(rn, pq) == NULL);
aac24838
JB
2940 STAILQ_INSERT_TAIL(&pqnode->pqueue, rn, pq);
2941 pqnode->queued++;
2942
cfe8d15a
LB
2943 if (!pqnode_reuse)
2944 work_queue_add(wq, pqnode);
2945
d62a17ae 2946 return;
fee0f4c6 2947}
0a486e5f 2948
d62a17ae 2949void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 2950{
d62a17ae 2951 struct bgp_process_queue *pqnode;
cb1faec9 2952
d62a17ae 2953 if (bm->process_main_queue == NULL)
2954 return;
2e02b9b2 2955
cfe8d15a 2956 pqnode = bgp_processq_alloc(bgp);
cb1faec9 2957
aac24838 2958 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
cfe8d15a 2959 work_queue_add(bm->process_main_queue, pqnode);
cb1faec9
DS
2960}
2961
d62a17ae 2962static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 2963{
d62a17ae 2964 struct peer *peer;
0a486e5f 2965
d62a17ae 2966 peer = THREAD_ARG(thread);
2967 peer->t_pmax_restart = NULL;
0a486e5f 2968
d62a17ae 2969 if (bgp_debug_neighbor_events(peer))
2970 zlog_debug(
2971 "%s Maximum-prefix restart timer expired, restore peering",
2972 peer->host);
0a486e5f 2973
a9bafa95 2974 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 2975 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 2976
d62a17ae 2977 return 0;
0a486e5f 2978}
2979
3dc339cd
DA
2980bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
2981 int always)
718e3744 2982{
d62a17ae 2983 iana_afi_t pkt_afi;
5c525538 2984 iana_safi_t pkt_safi;
9cabb64b 2985
d62a17ae 2986 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 2987 return false;
e0701b79 2988
d62a17ae 2989 if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) {
2990 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2991 PEER_STATUS_PREFIX_LIMIT)
2992 && !always)
3dc339cd 2993 return false;
e0701b79 2994
d62a17ae 2995 zlog_info(
a0a87037
DA
2996 "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32
2997 " exceed, limit %" PRIu32,
5cb5f4d0 2998 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 2999 peer->pcount[afi][safi], peer->pmax[afi][safi]);
3000 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3001
3002 if (CHECK_FLAG(peer->af_flags[afi][safi],
3003 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3004 return false;
d62a17ae 3005
3006 /* Convert AFI, SAFI to values for packet. */
3007 pkt_afi = afi_int2iana(afi);
3008 pkt_safi = safi_int2iana(safi);
3009 {
d7c0a89a 3010 uint8_t ndata[7];
d62a17ae 3011
3012 ndata[0] = (pkt_afi >> 8);
3013 ndata[1] = pkt_afi;
3014 ndata[2] = pkt_safi;
3015 ndata[3] = (peer->pmax[afi][safi] >> 24);
3016 ndata[4] = (peer->pmax[afi][safi] >> 16);
3017 ndata[5] = (peer->pmax[afi][safi] >> 8);
3018 ndata[6] = (peer->pmax[afi][safi]);
3019
3020 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3021 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3022 BGP_NOTIFY_CEASE_MAX_PREFIX,
3023 ndata, 7);
3024 }
3025
3026 /* Dynamic peers will just close their connection. */
3027 if (peer_dynamic_neighbor(peer))
3dc339cd 3028 return true;
d62a17ae 3029
3030 /* restart timer start */
3031 if (peer->pmax_restart[afi][safi]) {
3032 peer->v_pmax_restart =
3033 peer->pmax_restart[afi][safi] * 60;
3034
3035 if (bgp_debug_neighbor_events(peer))
3036 zlog_debug(
3037 "%s Maximum-prefix restart timer started for %d secs",
3038 peer->host, peer->v_pmax_restart);
3039
3040 BGP_TIMER_ON(peer->t_pmax_restart,
3041 bgp_maximum_prefix_restart_timer,
3042 peer->v_pmax_restart);
3043 }
3044
3dc339cd 3045 return true;
d62a17ae 3046 } else
3047 UNSET_FLAG(peer->af_sflags[afi][safi],
3048 PEER_STATUS_PREFIX_LIMIT);
3049
3050 if (peer->pcount[afi][safi]
3051 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
3052 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3053 PEER_STATUS_PREFIX_THRESHOLD)
3054 && !always)
3dc339cd 3055 return false;
d62a17ae 3056
3057 zlog_info(
a0a87037
DA
3058 "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32
3059 ", max %" PRIu32,
5cb5f4d0 3060 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 3061 peer->pcount[afi][safi], peer->pmax[afi][safi]);
3062 SET_FLAG(peer->af_sflags[afi][safi],
3063 PEER_STATUS_PREFIX_THRESHOLD);
3064 } else
3065 UNSET_FLAG(peer->af_sflags[afi][safi],
3066 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3067 return false;
718e3744 3068}
3069
b40d939b 3070/* Unconditionally remove the route from the RIB, without taking
3071 * damping into consideration (eg, because the session went down)
3072 */
40381db7 3073void bgp_rib_remove(struct bgp_node *rn, struct bgp_path_info *pi,
4b7e6066 3074 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3075{
f009ff26 3076
3077 struct bgp *bgp = NULL;
3078 bool delete_route = false;
3079
b54892e0
DS
3080 bgp_aggregate_decrement(peer->bgp, bgp_node_get_prefix(rn),
3081 pi, afi, safi);
d62a17ae 3082
f009ff26 3083 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
40381db7 3084 bgp_path_info_delete(rn, pi); /* keep historical info */
d62a17ae 3085
f009ff26 3086 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3087 * flag
3088 */
3089 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3090 delete_route = true;
36235319
QY
3091 else if (bgp_node_set_defer_flag(rn, true) < 0)
3092 delete_route = true;
f009ff26 3093 if (delete_route) {
3094 if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
3095 UNSET_FLAG(rn->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3096 bgp = pi->peer->bgp;
36235319
QY
3097 if ((rn->rt_node)
3098 && (bgp->gr_info[afi][safi].route_list)) {
3099 list_delete_node(bgp->gr_info[afi][safi]
3100 .route_list,
3101 rn->rt_node);
f009ff26 3102 rn->rt_node = NULL;
3103 }
3104 }
3105 }
3106 }
4a11bf2c 3107
f009ff26 3108 hook_call(bgp_process, peer->bgp, afi, safi, rn, peer, true);
d62a17ae 3109 bgp_process(peer->bgp, rn, afi, safi);
3110}
3111
40381db7 3112static void bgp_rib_withdraw(struct bgp_node *rn, struct bgp_path_info *pi,
d62a17ae 3113 struct peer *peer, afi_t afi, safi_t safi,
3114 struct prefix_rd *prd)
3115{
b54892e0
DS
3116 const struct prefix *p = bgp_node_get_prefix(rn);
3117
d62a17ae 3118 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3119 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3120 */
3121 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3122 && peer->sort == BGP_PEER_EBGP)
40381db7 3123 if ((bgp_damp_withdraw(pi, rn, afi, safi, 0))
d62a17ae 3124 == BGP_DAMP_SUPPRESSED) {
b54892e0 3125 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
d62a17ae 3126 safi);
3127 return;
3128 }
3129
49e5a4a0 3130#ifdef ENABLE_BGP_VNC
d62a17ae 3131 if (safi == SAFI_MPLS_VPN) {
3132 struct bgp_node *prn = NULL;
3133 struct bgp_table *table = NULL;
3134
3135 prn = bgp_node_get(peer->bgp->rib[afi][safi],
3136 (struct prefix *)prd);
67009e22
DS
3137 if (bgp_node_has_bgp_path_info_data(prn)) {
3138 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3139
3140 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3141 peer->bgp, prd, table, p, pi);
d62a17ae 3142 }
3143 bgp_unlock_node(prn);
3144 }
3145 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3146 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3147
b54892e0
DS
3148 vnc_import_bgp_del_route(peer->bgp, p, pi);
3149 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3150 }
65efcfce 3151 }
d62a17ae 3152#endif
128ea8ab 3153
d62a17ae 3154 /* If this is an EVPN route, process for un-import. */
3155 if (safi == SAFI_EVPN)
b54892e0 3156 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3157
40381db7 3158 bgp_rib_remove(rn, pi, peer, afi, safi);
718e3744 3159}
3160
4b7e6066
DS
3161struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3162 struct peer *peer, struct attr *attr,
3163 struct bgp_node *rn)
fb018d25 3164{
4b7e6066 3165 struct bgp_path_info *new;
fb018d25 3166
d62a17ae 3167 /* Make new BGP info. */
4b7e6066 3168 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3169 new->type = type;
3170 new->instance = instance;
3171 new->sub_type = sub_type;
3172 new->peer = peer;
3173 new->attr = attr;
3174 new->uptime = bgp_clock();
3175 new->net = rn;
d62a17ae 3176 return new;
fb018d25
DS
3177}
3178
d62a17ae 3179static void overlay_index_update(struct attr *attr,
3180 struct eth_segment_id *eth_s_id,
3181 union gw_addr *gw_ip)
684a7227 3182{
d62a17ae 3183 if (!attr)
3184 return;
684a7227 3185
d62a17ae 3186 if (eth_s_id == NULL) {
3187 memset(&(attr->evpn_overlay.eth_s_id), 0,
3188 sizeof(struct eth_segment_id));
3189 } else {
3190 memcpy(&(attr->evpn_overlay.eth_s_id), eth_s_id,
3191 sizeof(struct eth_segment_id));
3192 }
3193 if (gw_ip == NULL) {
3194 memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr));
3195 } else {
3196 memcpy(&(attr->evpn_overlay.gw_ip), gw_ip,
3197 sizeof(union gw_addr));
3198 }
684a7227
PG
3199}
3200
40381db7 3201static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3202 struct eth_segment_id *eth_s_id,
3203 union gw_addr *gw_ip)
3204{
40381db7
DS
3205 struct eth_segment_id *path_eth_s_id, *path_eth_s_id_remote;
3206 union gw_addr *path_gw_ip, *path_gw_ip_remote;
11ebf4ed
DS
3207 union {
3208 struct eth_segment_id esi;
3209 union gw_addr ip;
3210 } temp;
d62a17ae 3211
3212 if (afi != AFI_L2VPN)
3213 return true;
11ebf4ed 3214
05864da7
DS
3215 path_eth_s_id = &(path->attr->evpn_overlay.eth_s_id);
3216 path_gw_ip = &(path->attr->evpn_overlay.gw_ip);
11ebf4ed
DS
3217
3218 if (gw_ip == NULL) {
3219 memset(&temp, 0, sizeof(temp));
40381db7 3220 path_gw_ip_remote = &temp.ip;
11ebf4ed 3221 } else
40381db7 3222 path_gw_ip_remote = gw_ip;
11ebf4ed
DS
3223
3224 if (eth_s_id == NULL) {
3225 memset(&temp, 0, sizeof(temp));
40381db7 3226 path_eth_s_id_remote = &temp.esi;
11ebf4ed 3227 } else
40381db7 3228 path_eth_s_id_remote = eth_s_id;
11ebf4ed 3229
40381db7 3230 if (!memcmp(path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr)))
d62a17ae 3231 return false;
11ebf4ed 3232
40381db7 3233 return !memcmp(path_eth_s_id, path_eth_s_id_remote,
d62a17ae 3234 sizeof(struct eth_segment_id));
684a7227
PG
3235}
3236
c265ee22 3237/* Check if received nexthop is valid or not. */
3dc339cd
DA
3238static bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3239 uint8_t type, uint8_t stype,
3240 struct attr *attr, struct bgp_node *rn)
d62a17ae 3241{
2dbe3fa9 3242 bool ret = false;
d62a17ae 3243
3244 /* Only validated for unicast and multicast currently. */
3245 /* Also valid for EVPN where the nexthop is an IP address. */
3246 if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN)
3dc339cd 3247 return false;
d62a17ae 3248
3249 /* If NEXT_HOP is present, validate it. */
3250 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
975a328e 3251 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3252 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
975a328e 3253 || bgp_nexthop_self(bgp, afi, type, stype, attr, rn))
3dc339cd 3254 return true;
d62a17ae 3255 }
c265ee22 3256
d62a17ae 3257 /* If MP_NEXTHOP is present, validate it. */
3258 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3259 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3260 * it is not an IPv6 link-local address.
3261 */
3262 if (attr->mp_nexthop_len) {
3263 switch (attr->mp_nexthop_len) {
3264 case BGP_ATTR_NHLEN_IPV4:
3265 case BGP_ATTR_NHLEN_VPNV4:
975a328e
DA
3266 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
3267 || IPV4_CLASS_DE(
3268 ntohl(attr->mp_nexthop_global_in.s_addr))
3269 || bgp_nexthop_self(bgp, afi, type, stype, attr,
3270 rn));
d62a17ae 3271 break;
3272
3273 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
3274 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3275 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
3276 ret = (IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global)
3277 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3278 || IN6_IS_ADDR_MULTICAST(
949b0f24 3279 &attr->mp_nexthop_global)
3280 || bgp_nexthop_self(bgp, afi, type, stype,
3281 attr, rn));
d62a17ae 3282 break;
3283
3284 default:
3dc339cd 3285 ret = true;
d62a17ae 3286 break;
3287 }
3288 }
c265ee22 3289
d62a17ae 3290 return ret;
3291}
3292
5a1ae2c2 3293int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3294 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3295 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3296 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3297 struct bgp_route_evpn *evpn)
d62a17ae 3298{
3299 int ret;
3300 int aspath_loop_count = 0;
3301 struct bgp_node *rn;
3302 struct bgp *bgp;
3303 struct attr new_attr;
3304 struct attr *attr_new;
40381db7 3305 struct bgp_path_info *pi;
4b7e6066
DS
3306 struct bgp_path_info *new;
3307 struct bgp_path_info_extra *extra;
d62a17ae 3308 const char *reason;
3309 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3310 int connected = 0;
3311 int do_loop_check = 1;
3312 int has_valid_label = 0;
7c312383 3313 afi_t nh_afi;
949b0f24 3314 uint8_t pi_type = 0;
3315 uint8_t pi_sub_type = 0;
3316
49e5a4a0 3317#ifdef ENABLE_BGP_VNC
d62a17ae 3318 int vnc_implicit_withdraw = 0;
65efcfce 3319#endif
d62a17ae 3320 int same_attr = 0;
718e3744 3321
d62a17ae 3322 memset(&new_attr, 0, sizeof(struct attr));
3323 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3324 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3325
d62a17ae 3326 bgp = peer->bgp;
3327 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3328 /* TODO: Check to see if we can get rid of "is_valid_label" */
3329 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3330 has_valid_label = (num_labels > 0) ? 1 : 0;
3331 else
3332 has_valid_label = bgp_is_valid_label(label);
718e3744 3333
d62a17ae 3334 /* When peer's soft reconfiguration enabled. Record input packet in
3335 Adj-RIBs-In. */
3336 if (!soft_reconfig
3337 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3338 && peer != bgp->peer_self)
3339 bgp_adj_in_set(rn, peer, attr, addpath_id);
3340
3341 /* Check previously received route. */
6f94b685 3342 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
3343 if (pi->peer == peer && pi->type == type
3344 && pi->sub_type == sub_type
3345 && pi->addpath_rx_id == addpath_id)
d62a17ae 3346 break;
3347
3348 /* AS path local-as loop check. */
3349 if (peer->change_local_as) {
c4368918
DW
3350 if (peer->allowas_in[afi][safi])
3351 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3352 else if (!CHECK_FLAG(peer->flags,
3353 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3354 aspath_loop_count = 1;
3355
3356 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3357 > aspath_loop_count) {
b4d46cc9 3358 peer->stat_pfx_aspath_loop++;
d62a17ae 3359 reason = "as-path contains our own AS;";
3360 goto filtered;
3361 }
718e3744 3362 }
718e3744 3363
d62a17ae 3364 /* If the peer is configured for "allowas-in origin" and the last ASN in
3365 * the
3366 * as-path is our ASN then we do not need to call aspath_loop_check
3367 */
3368 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3369 if (aspath_get_last_as(attr->aspath) == bgp->as)
3370 do_loop_check = 0;
3371
3372 /* AS path loop check. */
3373 if (do_loop_check) {
3374 if (aspath_loop_check(attr->aspath, bgp->as)
3375 > peer->allowas_in[afi][safi]
3376 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3377 && aspath_loop_check(attr->aspath, bgp->confed_id)
3378 > peer->allowas_in[afi][safi])) {
b4d46cc9 3379 peer->stat_pfx_aspath_loop++;
d62a17ae 3380 reason = "as-path contains our own AS;";
3381 goto filtered;
3382 }
3383 }
aac9ef6c 3384
d62a17ae 3385 /* Route reflector originator ID check. */
3386 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3387 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3388 peer->stat_pfx_originator_loop++;
d62a17ae 3389 reason = "originator is us;";
3390 goto filtered;
3391 }
718e3744 3392
d62a17ae 3393 /* Route reflector cluster ID check. */
3394 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3395 peer->stat_pfx_cluster_loop++;
d62a17ae 3396 reason = "reflected from the same cluster;";
3397 goto filtered;
3398 }
718e3744 3399
d62a17ae 3400 /* Apply incoming filter. */
3401 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3402 peer->stat_pfx_filter++;
d62a17ae 3403 reason = "filter;";
3404 goto filtered;
3405 }
718e3744 3406
a8b72dc6
DA
3407 /* RFC 8212 to prevent route leaks.
3408 * This specification intends to improve this situation by requiring the
3409 * explicit configuration of both BGP Import and Export Policies for any
3410 * External BGP (EBGP) session such as customers, peers, or
3411 * confederation boundaries for all enabled address families. Through
3412 * codification of the aforementioned requirement, operators will
3413 * benefit from consistent behavior across different BGP
3414 * implementations.
3415 */
3416 if (peer->bgp->ebgp_requires_policy == DEFAULT_EBGP_POLICY_ENABLED)
3417 if (!bgp_inbound_policy_exists(peer,
3418 &peer->filter[afi][safi])) {
3419 reason = "inbound policy missing";
3420 goto filtered;
3421 }
3422
fb29348a
DA
3423 /* draft-ietf-idr-deprecate-as-set-confed-set
3424 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3425 * Eventually, This document (if approved) updates RFC 4271
3426 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3427 * and obsoletes RFC 6472.
3428 */
3429 if (peer->bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED)
3430 if (aspath_check_as_sets(attr->aspath)) {
3431 reason =
3432 "as-path contains AS_SET or AS_CONFED_SET type;";
3433 goto filtered;
3434 }
3435
6f4f49b2 3436 new_attr = *attr;
d62a17ae 3437
3438 /* Apply incoming route-map.
3439 * NB: new_attr may now contain newly allocated values from route-map
3440 * "set"
3441 * commands, so we need bgp_attr_flush in the error paths, until we
3442 * intern
3443 * the attr (which takes over the memory references) */
82b692c0 3444 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL,
196c6b09 3445 label, num_labels, rn) == RMAP_DENY) {
b4d46cc9 3446 peer->stat_pfx_filter++;
d62a17ae 3447 reason = "route-map;";
3448 bgp_attr_flush(&new_attr);
3449 goto filtered;
3450 }
718e3744 3451
05864da7 3452 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3453 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3454 /* remove from RIB previous entry */
3455 bgp_zebra_withdraw(p, pi, bgp, safi);
3456 }
3457
7f323236
DW
3458 if (peer->sort == BGP_PEER_EBGP) {
3459
a4d82a8a
PZ
3460 /* If we receive the graceful-shutdown community from an eBGP
3461 * peer we must lower local-preference */
3462 if (new_attr.community
3463 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3464 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3465 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3466
a4d82a8a
PZ
3467 /* If graceful-shutdown is configured then add the GSHUT
3468 * community to all paths received from eBGP peers */
892fedb6
DA
3469 } else if (CHECK_FLAG(peer->bgp->flags,
3470 BGP_FLAG_GRACEFUL_SHUTDOWN))
7f323236 3471 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3472 }
3473
949b0f24 3474 if (pi) {
3475 pi_type = pi->type;
3476 pi_sub_type = pi->sub_type;
3477 }
3478
d62a17ae 3479 /* next hop check. */
a4d82a8a 3480 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
949b0f24 3481 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type,
3482 pi_sub_type, &new_attr, rn)) {
b4d46cc9 3483 peer->stat_pfx_nh_invalid++;
d62a17ae 3484 reason = "martian or self next-hop;";
3485 bgp_attr_flush(&new_attr);
3486 goto filtered;
3487 }
718e3744 3488
5c14a191 3489 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3490 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3491 reason = "self mac;";
3492 goto filtered;
3493 }
3494
d62a17ae 3495 attr_new = bgp_attr_intern(&new_attr);
3496
3497 /* If the update is implicit withdraw. */
40381db7
DS
3498 if (pi) {
3499 pi->uptime = bgp_clock();
3500 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3501
4a11bf2c
DL
3502 hook_call(bgp_process, bgp, afi, safi, rn, peer, true);
3503
d62a17ae 3504 /* Same attribute comes in. */
40381db7
DS
3505 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3506 && attrhash_cmp(pi->attr, attr_new)
d62a17ae 3507 && (!has_valid_label
40381db7 3508 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3509 num_labels * sizeof(mpls_label_t))
d62a17ae 3510 == 0)
3511 && (overlay_index_equal(
40381db7 3512 afi, pi, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3513 evpn == NULL ? NULL : &evpn->gw_ip))) {
3514 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3515 BGP_CONFIG_DAMPENING)
3516 && peer->sort == BGP_PEER_EBGP
40381db7 3517 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3518 if (bgp_debug_update(peer, p, NULL, 1)) {
3519 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3520 afi, safi, prd, p, label,
3521 num_labels, addpath_id ? 1 : 0,
3522 addpath_id, pfx_buf,
3523 sizeof(pfx_buf));
d62a17ae 3524 zlog_debug("%s rcvd %s", peer->host,
3525 pfx_buf);
3526 }
3527
40381db7 3528 if (bgp_damp_update(pi, rn, afi, safi)
d62a17ae 3529 != BGP_DAMP_SUPPRESSED) {
40381db7 3530 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3531 safi);
3532 bgp_process(bgp, rn, afi, safi);
3533 }
3534 } else /* Duplicate - odd */
3535 {
3536 if (bgp_debug_update(peer, p, NULL, 1)) {
3537 if (!peer->rcvd_attr_printed) {
3538 zlog_debug(
3539 "%s rcvd UPDATE w/ attr: %s",
3540 peer->host,
3541 peer->rcvd_attr_str);
3542 peer->rcvd_attr_printed = 1;
3543 }
3544
3545 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3546 afi, safi, prd, p, label,
3547 num_labels, addpath_id ? 1 : 0,
3548 addpath_id, pfx_buf,
3549 sizeof(pfx_buf));
d62a17ae 3550 zlog_debug(
3551 "%s rcvd %s...duplicate ignored",
3552 peer->host, pfx_buf);
3553 }
3554
3555 /* graceful restart STALE flag unset. */
40381db7 3556 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3557 bgp_path_info_unset_flag(
40381db7 3558 rn, pi, BGP_PATH_STALE);
f009ff26 3559 bgp_node_set_defer_flag(rn, false);
d62a17ae 3560 bgp_process(bgp, rn, afi, safi);
3561 }
3562 }
3563
3564 bgp_unlock_node(rn);
3565 bgp_attr_unintern(&attr_new);
3566
3567 return 0;
3568 }
718e3744 3569
d62a17ae 3570 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3571 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3572 if (bgp_debug_update(peer, p, NULL, 1)) {
3573 bgp_debug_rdpfxpath2str(
a4d82a8a 3574 afi, safi, prd, p, label, num_labels,
d62a17ae 3575 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3576 sizeof(pfx_buf));
3577 zlog_debug(
3578 "%s rcvd %s, flapped quicker than processing",
3579 peer->host, pfx_buf);
3580 }
3581
40381db7 3582 bgp_path_info_restore(rn, pi);
d62a17ae 3583 }
718e3744 3584
d62a17ae 3585 /* Received Logging. */
3586 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3587 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3588 num_labels, addpath_id ? 1 : 0,
3589 addpath_id, pfx_buf,
3590 sizeof(pfx_buf));
d62a17ae 3591 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3592 }
718e3744 3593
d62a17ae 3594 /* graceful restart STALE flag unset. */
f009ff26 3595 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
40381db7 3596 bgp_path_info_unset_flag(rn, pi, BGP_PATH_STALE);
f009ff26 3597 bgp_node_set_defer_flag(rn, false);
3598 }
d62a17ae 3599
3600 /* The attribute is changed. */
40381db7 3601 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3602
3603 /* implicit withdraw, decrement aggregate and pcount here.
3604 * only if update is accepted, they'll increment below.
3605 */
40381db7 3606 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3607
3608 /* Update bgp route dampening information. */
3609 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3610 && peer->sort == BGP_PEER_EBGP) {
3611 /* This is implicit withdraw so we should update
3612 dampening
3613 information. */
40381db7
DS
3614 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
3615 bgp_damp_withdraw(pi, rn, afi, safi, 1);
d62a17ae 3616 }
49e5a4a0 3617#ifdef ENABLE_BGP_VNC
d62a17ae 3618 if (safi == SAFI_MPLS_VPN) {
3619 struct bgp_node *prn = NULL;
3620 struct bgp_table *table = NULL;
3621
3622 prn = bgp_node_get(bgp->rib[afi][safi],
3623 (struct prefix *)prd);
67009e22
DS
3624 if (bgp_node_has_bgp_path_info_data(prn)) {
3625 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3626
3627 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3628 bgp, prd, table, p, pi);
d62a17ae 3629 }
3630 bgp_unlock_node(prn);
3631 }
3632 if ((afi == AFI_IP || afi == AFI_IP6)
3633 && (safi == SAFI_UNICAST)) {
40381db7 3634 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3635 /*
3636 * Implicit withdraw case.
3637 */
3638 ++vnc_implicit_withdraw;
40381db7
DS
3639 vnc_import_bgp_del_route(bgp, p, pi);
3640 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3641 }
3642 }
65efcfce 3643#endif
128ea8ab 3644
d62a17ae 3645 /* Special handling for EVPN update of an existing route. If the
3646 * extended community attribute has changed, we need to
3647 * un-import
3648 * the route using its existing extended community. It will be
3649 * subsequently processed for import with the new extended
3650 * community.
3651 */
3652 if (safi == SAFI_EVPN && !same_attr) {
40381db7 3653 if ((pi->attr->flag
d62a17ae 3654 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3655 && (attr_new->flag
3656 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3657 int cmp;
3658
40381db7 3659 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3660 attr_new->ecommunity);
3661 if (!cmp) {
3662 if (bgp_debug_update(peer, p, NULL, 1))
3663 zlog_debug(
3664 "Change in EXT-COMM, existing %s new %s",
3665 ecommunity_str(
40381db7 3666 pi->attr->ecommunity),
d62a17ae 3667 ecommunity_str(
3668 attr_new->ecommunity));
3669 bgp_evpn_unimport_route(bgp, afi, safi,
40381db7 3670 p, pi);
d62a17ae 3671 }
3672 }
3673 }
718e3744 3674
d62a17ae 3675 /* Update to new attribute. */
40381db7
DS
3676 bgp_attr_unintern(&pi->attr);
3677 pi->attr = attr_new;
d62a17ae 3678
3679 /* Update MPLS label */
3680 if (has_valid_label) {
40381db7 3681 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3682 if (extra->label != label) {
3683 memcpy(&extra->label, label,
dbd587da 3684 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3685 extra->num_labels = num_labels;
3686 }
b57ba6d2
MK
3687 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3688 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3689 }
718e3744 3690
e496b420
HS
3691 /* Update SRv6 SID */
3692 if (attr->srv6_l3vpn) {
3693 extra = bgp_path_info_extra_get(pi);
3694 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
3695 sid_copy(&extra->sid[0],
3696 &attr->srv6_l3vpn->sid);
3697 extra->num_sids = 1;
3698 }
3699 } else if (attr->srv6_vpn) {
3700 extra = bgp_path_info_extra_get(pi);
3701 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
3702 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3703 extra->num_sids = 1;
3704 }
3705 }
3706
49e5a4a0 3707#ifdef ENABLE_BGP_VNC
d62a17ae 3708 if ((afi == AFI_IP || afi == AFI_IP6)
3709 && (safi == SAFI_UNICAST)) {
3710 if (vnc_implicit_withdraw) {
3711 /*
3712 * Add back the route with its new attributes
3713 * (e.g., nexthop).
3714 * The route is still selected, until the route
3715 * selection
3716 * queued by bgp_process actually runs. We have
3717 * to make this
3718 * update to the VNC side immediately to avoid
3719 * racing against
3720 * configuration changes (e.g., route-map
3721 * changes) which
3722 * trigger re-importation of the entire RIB.
3723 */
40381db7
DS
3724 vnc_import_bgp_add_route(bgp, p, pi);
3725 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 3726 }
3727 }
65efcfce 3728#endif
d62a17ae 3729 /* Update Overlay Index */
3730 if (afi == AFI_L2VPN) {
3731 overlay_index_update(
40381db7 3732 pi->attr, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3733 evpn == NULL ? NULL : &evpn->gw_ip);
3734 }
65efcfce 3735
d62a17ae 3736 /* Update bgp route dampening information. */
3737 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3738 && peer->sort == BGP_PEER_EBGP) {
3739 /* Now we do normal update dampening. */
40381db7 3740 ret = bgp_damp_update(pi, rn, afi, safi);
d62a17ae 3741 if (ret == BGP_DAMP_SUPPRESSED) {
3742 bgp_unlock_node(rn);
3743 return 0;
3744 }
3745 }
128ea8ab 3746
d62a17ae 3747 /* Nexthop reachability check - for unicast and
3748 * labeled-unicast.. */
7c312383
AD
3749 if (((afi == AFI_IP || afi == AFI_IP6)
3750 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3751 || (safi == SAFI_EVPN &&
3752 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
3753 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
3754 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 3755 && !CHECK_FLAG(peer->flags,
3756 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
3757 && !CHECK_FLAG(bgp->flags,
3758 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 3759 connected = 1;
3760 else
3761 connected = 0;
3762
960035b2
PZ
3763 struct bgp *bgp_nexthop = bgp;
3764
40381db7
DS
3765 if (pi->extra && pi->extra->bgp_orig)
3766 bgp_nexthop = pi->extra->bgp_orig;
960035b2 3767
7c312383
AD
3768 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
3769
3770 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
3771 pi, NULL, connected)
a4d82a8a 3772 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
40381db7 3773 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 3774 else {
3775 if (BGP_DEBUG(nht, NHT)) {
3776 char buf1[INET6_ADDRSTRLEN];
3777 inet_ntop(AF_INET,
3778 (const void *)&attr_new
3779 ->nexthop,
3780 buf1, INET6_ADDRSTRLEN);
3781 zlog_debug("%s(%s): NH unresolved",
15569c58 3782 __func__, buf1);
d62a17ae 3783 }
40381db7 3784 bgp_path_info_unset_flag(rn, pi,
18ee8310 3785 BGP_PATH_VALID);
d62a17ae 3786 }
3787 } else
40381db7 3788 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 3789
49e5a4a0 3790#ifdef ENABLE_BGP_VNC
d62a17ae 3791 if (safi == SAFI_MPLS_VPN) {
3792 struct bgp_node *prn = NULL;
3793 struct bgp_table *table = NULL;
3794
3795 prn = bgp_node_get(bgp->rib[afi][safi],
3796 (struct prefix *)prd);
67009e22
DS
3797 if (bgp_node_has_bgp_path_info_data(prn)) {
3798 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3799
3800 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 3801 bgp, prd, table, p, pi);
d62a17ae 3802 }
3803 bgp_unlock_node(prn);
3804 }
3805#endif
718e3744 3806
d62a17ae 3807 /* If this is an EVPN route and some attribute has changed,
3808 * process
3809 * route for import. If the extended community has changed, we
3810 * would
3811 * have done the un-import earlier and the import would result
3812 * in the
3813 * route getting injected into appropriate L2 VNIs. If it is
3814 * just
3815 * some other attribute change, the import will result in
3816 * updating
3817 * the attributes for the route in the VNI(s).
3818 */
7c312383
AD
3819 if (safi == SAFI_EVPN && !same_attr &&
3820 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 3821 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 3822
3823 /* Process change. */
40381db7 3824 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 3825
3826 bgp_process(bgp, rn, afi, safi);
3827 bgp_unlock_node(rn);
558d1fec 3828
ddb5b488
PZ
3829 if (SAFI_UNICAST == safi
3830 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3831 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3832
40381db7 3833 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3834 }
3835 if ((SAFI_MPLS_VPN == safi)
3836 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3837
40381db7 3838 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
3839 }
3840
49e5a4a0 3841#ifdef ENABLE_BGP_VNC
d62a17ae 3842 if (SAFI_MPLS_VPN == safi) {
3843 mpls_label_t label_decoded = decode_label(label);
28070ee3 3844
d62a17ae 3845 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3846 type, sub_type, &label_decoded);
3847 }
3848 if (SAFI_ENCAP == safi) {
3849 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3850 type, sub_type, NULL);
3851 }
28070ee3
PZ
3852#endif
3853
d62a17ae 3854 return 0;
3855 } // End of implicit withdraw
718e3744 3856
d62a17ae 3857 /* Received Logging. */
3858 if (bgp_debug_update(peer, p, NULL, 1)) {
3859 if (!peer->rcvd_attr_printed) {
3860 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3861 peer->rcvd_attr_str);
3862 peer->rcvd_attr_printed = 1;
3863 }
718e3744 3864
a4d82a8a 3865 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3866 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3867 sizeof(pfx_buf));
3868 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3869 }
718e3744 3870
d62a17ae 3871 /* Make new BGP info. */
3872 new = info_make(type, sub_type, 0, peer, attr_new, rn);
718e3744 3873
d62a17ae 3874 /* Update MPLS label */
3875 if (has_valid_label) {
18ee8310 3876 extra = bgp_path_info_extra_get(new);
8ba71050 3877 if (extra->label != label) {
dbd587da
QY
3878 memcpy(&extra->label, label,
3879 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3880 extra->num_labels = num_labels;
3881 }
b57ba6d2
MK
3882 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3883 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3884 }
718e3744 3885
e496b420
HS
3886 /* Update SRv6 SID */
3887 if (safi == SAFI_MPLS_VPN) {
3888 extra = bgp_path_info_extra_get(new);
3889 if (attr->srv6_l3vpn) {
3890 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
3891 extra->num_sids = 1;
3892 } else if (attr->srv6_vpn) {
3893 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3894 extra->num_sids = 1;
3895 }
3896 }
3897
d62a17ae 3898 /* Update Overlay Index */
3899 if (afi == AFI_L2VPN) {
3900 overlay_index_update(new->attr,
3901 evpn == NULL ? NULL : &evpn->eth_s_id,
3902 evpn == NULL ? NULL : &evpn->gw_ip);
3903 }
3904 /* Nexthop reachability check. */
7c312383
AD
3905 if (((afi == AFI_IP || afi == AFI_IP6)
3906 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3907 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
3908 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
3909 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 3910 && !CHECK_FLAG(peer->flags,
3911 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
3912 && !CHECK_FLAG(bgp->flags,
3913 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 3914 connected = 1;
3915 else
3916 connected = 0;
3917
7c312383
AD
3918 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
3919
3920 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, new, NULL,
3921 connected)
a4d82a8a 3922 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
18ee8310 3923 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
d62a17ae 3924 else {
3925 if (BGP_DEBUG(nht, NHT)) {
3926 char buf1[INET6_ADDRSTRLEN];
3927 inet_ntop(AF_INET,
3928 (const void *)&attr_new->nexthop,
3929 buf1, INET6_ADDRSTRLEN);
15569c58
DA
3930 zlog_debug("%s(%s): NH unresolved", __func__,
3931 buf1);
d62a17ae 3932 }
18ee8310 3933 bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID);
d62a17ae 3934 }
3935 } else
18ee8310 3936 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
a82478b9 3937
d62a17ae 3938 /* Addpath ID */
3939 new->addpath_rx_id = addpath_id;
3940
3941 /* Increment prefix */
3942 bgp_aggregate_increment(bgp, p, new, afi, safi);
3943
3944 /* Register new BGP information. */
18ee8310 3945 bgp_path_info_add(rn, new);
d62a17ae 3946
3947 /* route_node_get lock */
3948 bgp_unlock_node(rn);
558d1fec 3949
49e5a4a0 3950#ifdef ENABLE_BGP_VNC
d62a17ae 3951 if (safi == SAFI_MPLS_VPN) {
3952 struct bgp_node *prn = NULL;
3953 struct bgp_table *table = NULL;
3954
3955 prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
67009e22
DS
3956 if (bgp_node_has_bgp_path_info_data(prn)) {
3957 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3958
3959 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3960 bgp, prd, table, p, new);
3961 }
3962 bgp_unlock_node(prn);
3963 }
65efcfce
LB
3964#endif
3965
d62a17ae 3966 /* If maximum prefix count is configured and current prefix
3967 count exeed it. */
3968 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3969 return -1;
718e3744 3970
d62a17ae 3971 /* If this is an EVPN route, process for import. */
7c312383 3972 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 3973 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 3974
4a11bf2c
DL
3975 hook_call(bgp_process, bgp, afi, safi, rn, peer, false);
3976
d62a17ae 3977 /* Process change. */
3978 bgp_process(bgp, rn, afi, safi);
718e3744 3979
ddb5b488
PZ
3980 if (SAFI_UNICAST == safi
3981 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3982 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3983 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
3984 }
3985 if ((SAFI_MPLS_VPN == safi)
3986 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3987
3988 vpn_leak_to_vrf_update(bgp, new);
3989 }
49e5a4a0 3990#ifdef ENABLE_BGP_VNC
d62a17ae 3991 if (SAFI_MPLS_VPN == safi) {
3992 mpls_label_t label_decoded = decode_label(label);
28070ee3 3993
d62a17ae 3994 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3995 sub_type, &label_decoded);
3996 }
3997 if (SAFI_ENCAP == safi) {
3998 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3999 sub_type, NULL);
4000 }
28070ee3
PZ
4001#endif
4002
d62a17ae 4003 return 0;
718e3744 4004
d62a17ae 4005/* This BGP update is filtered. Log the reason then update BGP
4006 entry. */
4007filtered:
4a11bf2c
DL
4008 hook_call(bgp_process, bgp, afi, safi, rn, peer, true);
4009
d62a17ae 4010 if (bgp_debug_update(peer, p, NULL, 1)) {
4011 if (!peer->rcvd_attr_printed) {
4012 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4013 peer->rcvd_attr_str);
4014 peer->rcvd_attr_printed = 1;
4015 }
718e3744 4016
a4d82a8a 4017 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4018 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4019 sizeof(pfx_buf));
4020 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4021 peer->host, pfx_buf, reason);
4022 }
128ea8ab 4023
40381db7 4024 if (pi) {
d62a17ae 4025 /* If this is an EVPN route, un-import it as it is now filtered.
4026 */
4027 if (safi == SAFI_EVPN)
40381db7 4028 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4029
ddb5b488
PZ
4030 if (SAFI_UNICAST == safi
4031 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4032 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4033
40381db7 4034 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4035 }
4036 if ((SAFI_MPLS_VPN == safi)
4037 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4038
40381db7 4039 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4040 }
4041
40381db7 4042 bgp_rib_remove(rn, pi, peer, afi, safi);
d62a17ae 4043 }
4044
4045 bgp_unlock_node(rn);
558d1fec 4046
49e5a4a0 4047#ifdef ENABLE_BGP_VNC
d62a17ae 4048 /*
4049 * Filtered update is treated as an implicit withdrawal (see
4050 * bgp_rib_remove()
4051 * a few lines above)
4052 */
4053 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4054 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4055 0);
4056 }
97736e32
PZ
4057#endif
4058
d62a17ae 4059 return 0;
718e3744 4060}
4061
26a3ffd6 4062int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4063 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4064 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4065 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4066{
d62a17ae 4067 struct bgp *bgp;
4068 char pfx_buf[BGP_PRD_PATH_STRLEN];
4069 struct bgp_node *rn;
40381db7 4070 struct bgp_path_info *pi;
718e3744 4071
49e5a4a0 4072#ifdef ENABLE_BGP_VNC
d62a17ae 4073 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4074 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4075 0);
4076 }
28070ee3
PZ
4077#endif
4078
d62a17ae 4079 bgp = peer->bgp;
4080
4081 /* Lookup node. */
4082 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
4083
4084 /* If peer is soft reconfiguration enabled. Record input packet for
4085 * further calculation.
4086 *
4087 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4088 * routes that are filtered. This tanks out Quagga RS pretty badly due
4089 * to
4090 * the iteration over all RS clients.
4091 * Since we need to remove the entry from adj_in anyway, do that first
4092 * and
4093 * if there was no entry, we don't need to do anything more.
4094 */
4095 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4096 && peer != bgp->peer_self)
4097 if (!bgp_adj_in_unset(rn, peer, addpath_id)) {
b4d46cc9
DL
4098 peer->stat_pfx_dup_withdraw++;
4099
d62a17ae 4100 if (bgp_debug_update(peer, p, NULL, 1)) {
4101 bgp_debug_rdpfxpath2str(
a4d82a8a 4102 afi, safi, prd, p, label, num_labels,
d62a17ae 4103 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4104 sizeof(pfx_buf));
4105 zlog_debug(
4106 "%s withdrawing route %s not in adj-in",
4107 peer->host, pfx_buf);
4108 }
4109 bgp_unlock_node(rn);
4110 return 0;
4111 }
cd808e74 4112
d62a17ae 4113 /* Lookup withdrawn route. */
6f94b685 4114 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4115 if (pi->peer == peer && pi->type == type
4116 && pi->sub_type == sub_type
4117 && pi->addpath_rx_id == addpath_id)
d62a17ae 4118 break;
4119
4120 /* Logging. */
4121 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4122 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4123 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4124 sizeof(pfx_buf));
4125 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4126 pfx_buf);
4127 }
718e3744 4128
d62a17ae 4129 /* Withdraw specified route from routing table. */
40381db7
DS
4130 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
4131 bgp_rib_withdraw(rn, pi, peer, afi, safi, prd);
ddb5b488
PZ
4132 if (SAFI_UNICAST == safi
4133 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4134 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4135 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4136 }
4137 if ((SAFI_MPLS_VPN == safi)
4138 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4139
40381db7 4140 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4141 }
4142 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4143 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4144 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4145 sizeof(pfx_buf));
4146 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4147 }
718e3744 4148
d62a17ae 4149 /* Unlock bgp_node_get() lock. */
4150 bgp_unlock_node(rn);
4151
4152 return 0;
718e3744 4153}
6b0655a2 4154
d62a17ae 4155void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4156 int withdraw)
718e3744 4157{
d62a17ae 4158 struct update_subgroup *subgrp;
4159 subgrp = peer_subgroup(peer, afi, safi);
4160 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4161}
6182d65b 4162
718e3744 4163
3f9c7369
DS
4164/*
4165 * bgp_stop_announce_route_timer
4166 */
d62a17ae 4167void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4168{
d62a17ae 4169 if (!paf->t_announce_route)
4170 return;
4171
4172 THREAD_TIMER_OFF(paf->t_announce_route);
718e3744 4173}
6b0655a2 4174
3f9c7369
DS
4175/*
4176 * bgp_announce_route_timer_expired
4177 *
4178 * Callback that is invoked when the route announcement timer for a
4179 * peer_af expires.
4180 */
d62a17ae 4181static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4182{
d62a17ae 4183 struct peer_af *paf;
4184 struct peer *peer;
558d1fec 4185
d62a17ae 4186 paf = THREAD_ARG(t);
4187 peer = paf->peer;
718e3744 4188
d62a17ae 4189 if (peer->status != Established)
4190 return 0;
3f9c7369 4191
d62a17ae 4192 if (!peer->afc_nego[paf->afi][paf->safi])
4193 return 0;
3f9c7369 4194
d62a17ae 4195 peer_af_announce_route(paf, 1);
4196 return 0;
718e3744 4197}
4198
3f9c7369
DS
4199/*
4200 * bgp_announce_route
4201 *
4202 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4203 */
d62a17ae 4204void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4205{
4206 struct peer_af *paf;
4207 struct update_subgroup *subgrp;
4208
4209 paf = peer_af_find(peer, afi, safi);
4210 if (!paf)
4211 return;
4212 subgrp = PAF_SUBGRP(paf);
4213
4214 /*
4215 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4216 * or a refresh has already been triggered.
4217 */
4218 if (!subgrp || paf->t_announce_route)
4219 return;
4220
4221 /*
4222 * Start a timer to stagger/delay the announce. This serves
4223 * two purposes - announcement can potentially be combined for
4224 * multiple peers and the announcement doesn't happen in the
4225 * vty context.
4226 */
4227 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4228 (subgrp->peer_count == 1)
4229 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4230 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4231 &paf->t_announce_route);
3f9c7369
DS
4232}
4233
4234/*
4235 * Announce routes from all AF tables to a peer.
4236 *
4237 * This should ONLY be called when there is a need to refresh the
4238 * routes to the peer based on a policy change for this peer alone
4239 * or a route refresh request received from the peer.
4240 * The operation will result in splitting the peer from its existing
4241 * subgroups and putting it in new subgroups.
4242 */
d62a17ae 4243void bgp_announce_route_all(struct peer *peer)
718e3744 4244{
d62a17ae 4245 afi_t afi;
4246 safi_t safi;
4247
05c7a1cc
QY
4248 FOREACH_AFI_SAFI (afi, safi)
4249 bgp_announce_route(peer, afi, safi);
718e3744 4250}
6b0655a2 4251
d62a17ae 4252static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4253 struct bgp_table *table,
4254 struct prefix_rd *prd)
718e3744 4255{
d62a17ae 4256 int ret;
4257 struct bgp_node *rn;
4258 struct bgp_adj_in *ain;
718e3744 4259
d62a17ae 4260 if (!table)
4261 table = peer->bgp->rib[afi][safi];
718e3744 4262
d62a17ae 4263 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
4264 for (ain = rn->adj_in; ain; ain = ain->next) {
ea47320b
DL
4265 if (ain->peer != peer)
4266 continue;
8692c506 4267
d7d15889 4268 struct bgp_path_info *pi;
d7c0a89a 4269 uint32_t num_labels = 0;
b57ba6d2 4270 mpls_label_t *label_pnt = NULL;
8cb687c2 4271 struct bgp_route_evpn evpn;
b57ba6d2 4272
d7d15889
DS
4273 for (pi = bgp_node_get_bgp_path_info(rn); pi;
4274 pi = pi->next)
4275 if (pi->peer == peer)
4276 break;
4277
40381db7
DS
4278 if (pi && pi->extra)
4279 num_labels = pi->extra->num_labels;
b57ba6d2 4280 if (num_labels)
40381db7 4281 label_pnt = &pi->extra->label[0];
8cb687c2
DS
4282 if (pi)
4283 memcpy(&evpn, &pi->attr->evpn_overlay,
4284 sizeof(evpn));
4285 else
4286 memset(&evpn, 0, sizeof(evpn));
8692c506 4287
b54892e0
DS
4288 ret = bgp_update(peer, bgp_node_get_prefix(rn),
4289 ain->addpath_rx_id, ain->attr,
4290 afi, safi, ZEBRA_ROUTE_BGP,
a4d82a8a 4291 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 4292 num_labels, 1, &evpn);
ea47320b
DL
4293
4294 if (ret < 0) {
4295 bgp_unlock_node(rn);
4296 return;
d62a17ae 4297 }
4298 }
718e3744 4299}
4300
d62a17ae 4301void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4302{
d62a17ae 4303 struct bgp_node *rn;
4304 struct bgp_table *table;
718e3744 4305
d62a17ae 4306 if (peer->status != Established)
4307 return;
718e3744 4308
d62a17ae 4309 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4310 && (safi != SAFI_EVPN))
4311 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4312 else
4313 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
67009e22
DS
4314 rn = bgp_route_next(rn)) {
4315 table = bgp_node_get_bgp_table_info(rn);
67009e22 4316
b54892e0
DS
4317 if (table == NULL)
4318 continue;
8692c506 4319
b54892e0
DS
4320 const struct prefix *p = bgp_node_get_prefix(rn);
4321 struct prefix_rd prd;
4322
4323 prd.family = AF_UNSPEC;
4324 prd.prefixlen = 64;
4325 memcpy(&prd.val, p->u.val, 8);
4326
4327 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 4328 }
718e3744 4329}
6b0655a2 4330
228da428 4331
d62a17ae 4332struct bgp_clear_node_queue {
4333 struct bgp_node *rn;
228da428
CC
4334};
4335
d62a17ae 4336static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4337{
d62a17ae 4338 struct bgp_clear_node_queue *cnq = data;
4339 struct bgp_node *rn = cnq->rn;
4340 struct peer *peer = wq->spec.data;
40381db7 4341 struct bgp_path_info *pi;
3103e8d2 4342 struct bgp *bgp;
d62a17ae 4343 afi_t afi = bgp_node_table(rn)->afi;
4344 safi_t safi = bgp_node_table(rn)->safi;
4345
4346 assert(rn && peer);
3103e8d2 4347 bgp = peer->bgp;
d62a17ae 4348
4349 /* It is possible that we have multiple paths for a prefix from a peer
4350 * if that peer is using AddPath.
4351 */
6f94b685 4352 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 4353 if (pi->peer != peer)
ea47320b
DL
4354 continue;
4355
4356 /* graceful restart STALE flag set. */
4357 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4358 && peer->nsf[afi][safi]
40381db7
DS
4359 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4360 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
4361 bgp_path_info_set_flag(rn, pi, BGP_PATH_STALE);
ea47320b
DL
4362 else {
4363 /* If this is an EVPN route, process for
4364 * un-import. */
4365 if (safi == SAFI_EVPN)
b54892e0
DS
4366 bgp_evpn_unimport_route(bgp, afi, safi,
4367 bgp_node_get_prefix(rn),
40381db7 4368 pi);
3103e8d2
DS
4369 /* Handle withdraw for VRF route-leaking and L3VPN */
4370 if (SAFI_UNICAST == safi
4371 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4372 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4373 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4374 bgp, pi);
960035b2 4375 }
3103e8d2 4376 if (SAFI_MPLS_VPN == safi &&
960035b2 4377 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4378 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4379 }
3103e8d2 4380
40381db7 4381 bgp_rib_remove(rn, pi, peer, afi, safi);
d62a17ae 4382 }
ea47320b 4383 }
d62a17ae 4384 return WQ_SUCCESS;
200df115 4385}
4386
d62a17ae 4387static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4388{
d62a17ae 4389 struct bgp_clear_node_queue *cnq = data;
4390 struct bgp_node *rn = cnq->rn;
4391 struct bgp_table *table = bgp_node_table(rn);
228da428 4392
d62a17ae 4393 bgp_unlock_node(rn);
4394 bgp_table_unlock(table);
4395 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4396}
4397
d62a17ae 4398static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4399{
d62a17ae 4400 struct peer *peer = wq->spec.data;
64e580a7 4401
d62a17ae 4402 /* Tickle FSM to start moving again */
4403 BGP_EVENT_ADD(peer, Clearing_Completed);
4404
4405 peer_unlock(peer); /* bgp_clear_route */
200df115 4406}
718e3744 4407
d62a17ae 4408static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4409{
d62a17ae 4410 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4411
4412 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4413#undef CLEAR_QUEUE_NAME_LEN
4414
0ce1ca80 4415 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4416 peer->clear_node_queue->spec.hold = 10;
4417 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4418 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4419 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4420 peer->clear_node_queue->spec.max_retries = 0;
4421
4422 /* we only 'lock' this peer reference when the queue is actually active
4423 */
4424 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4425}
4426
d62a17ae 4427static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4428 struct bgp_table *table)
65ca75e0 4429{
d62a17ae 4430 struct bgp_node *rn;
4431 int force = bm->process_main_queue ? 0 : 1;
6cf159b9 4432
d62a17ae 4433 if (!table)
4434 table = peer->bgp->rib[afi][safi];
dc83d712 4435
d62a17ae 4436 /* If still no table => afi/safi isn't configured at all or smth. */
4437 if (!table)
4438 return;
dc83d712 4439
d62a17ae 4440 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
40381db7 4441 struct bgp_path_info *pi, *next;
d62a17ae 4442 struct bgp_adj_in *ain;
4443 struct bgp_adj_in *ain_next;
4444
4445 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4446 * queued for every clearing peer, regardless of whether it is
4447 * relevant to the peer at hand.
4448 *
4449 * Overview: There are 3 different indices which need to be
4450 * scrubbed, potentially, when a peer is removed:
4451 *
4452 * 1 peer's routes visible via the RIB (ie accepted routes)
4453 * 2 peer's routes visible by the (optional) peer's adj-in index
4454 * 3 other routes visible by the peer's adj-out index
4455 *
4456 * 3 there is no hurry in scrubbing, once the struct peer is
4457 * removed from bgp->peer, we could just GC such deleted peer's
4458 * adj-outs at our leisure.
4459 *
4460 * 1 and 2 must be 'scrubbed' in some way, at least made
4461 * invisible via RIB index before peer session is allowed to be
4462 * brought back up. So one needs to know when such a 'search' is
4463 * complete.
4464 *
4465 * Ideally:
4466 *
4467 * - there'd be a single global queue or a single RIB walker
4468 * - rather than tracking which route_nodes still need to be
4469 * examined on a peer basis, we'd track which peers still
4470 * aren't cleared
4471 *
4472 * Given that our per-peer prefix-counts now should be reliable,
4473 * this may actually be achievable. It doesn't seem to be a huge
4474 * problem at this time,
4475 *
4476 * It is possible that we have multiple paths for a prefix from
4477 * a peer
4478 * if that peer is using AddPath.
4479 */
4480 ain = rn->adj_in;
4481 while (ain) {
4482 ain_next = ain->next;
4483
4484 if (ain->peer == peer) {
4485 bgp_adj_in_remove(rn, ain);
4486 bgp_unlock_node(rn);
4487 }
4488
4489 ain = ain_next;
4490 }
4491
6f94b685 4492 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
40381db7
DS
4493 next = pi->next;
4494 if (pi->peer != peer)
d62a17ae 4495 continue;
4496
4497 if (force)
40381db7 4498 bgp_path_info_reap(rn, pi);
d62a17ae 4499 else {
4500 struct bgp_clear_node_queue *cnq;
4501
4502 /* both unlocked in bgp_clear_node_queue_del */
4503 bgp_table_lock(bgp_node_table(rn));
4504 bgp_lock_node(rn);
4505 cnq = XCALLOC(
4506 MTYPE_BGP_CLEAR_NODE_QUEUE,
4507 sizeof(struct bgp_clear_node_queue));
4508 cnq->rn = rn;
4509 work_queue_add(peer->clear_node_queue, cnq);
4510 break;
4511 }
4512 }
4513 }
4514 return;
4515}
4516
4517void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4518{
4519 struct bgp_node *rn;
4520 struct bgp_table *table;
4521
4522 if (peer->clear_node_queue == NULL)
4523 bgp_clear_node_queue_init(peer);
4524
4525 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4526 * Idle until it receives a Clearing_Completed event. This protects
4527 * against peers which flap faster than we can we clear, which could
4528 * lead to:
4529 *
4530 * a) race with routes from the new session being installed before
4531 * clear_route_node visits the node (to delete the route of that
4532 * peer)
4533 * b) resource exhaustion, clear_route_node likely leads to an entry
4534 * on the process_main queue. Fast-flapping could cause that queue
4535 * to grow and grow.
4536 */
4537
4538 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4539 * the unlock will happen upon work-queue completion; other wise, the
4540 * unlock happens at the end of this function.
4541 */
4542 if (!peer->clear_node_queue->thread)
4543 peer_lock(peer);
4544
4545 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4546 bgp_clear_route_table(peer, afi, safi, NULL);
4547 else
4548 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
67009e22
DS
4549 rn = bgp_route_next(rn)) {
4550 table = bgp_node_get_bgp_table_info(rn);
4551 if (!table)
4552 continue;
4553
4554 bgp_clear_route_table(peer, afi, safi, table);
4555 }
d62a17ae 4556
4557 /* unlock if no nodes got added to the clear-node-queue. */
4558 if (!peer->clear_node_queue->thread)
4559 peer_unlock(peer);
718e3744 4560}
d62a17ae 4561
4562void bgp_clear_route_all(struct peer *peer)
718e3744 4563{
d62a17ae 4564 afi_t afi;
4565 safi_t safi;
718e3744 4566
05c7a1cc
QY
4567 FOREACH_AFI_SAFI (afi, safi)
4568 bgp_clear_route(peer, afi, safi);
65efcfce 4569
49e5a4a0 4570#ifdef ENABLE_BGP_VNC
d62a17ae 4571 rfapiProcessPeerDown(peer);
65efcfce 4572#endif
718e3744 4573}
4574
d62a17ae 4575void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4576{
d62a17ae 4577 struct bgp_table *table;
4578 struct bgp_node *rn;
4579 struct bgp_adj_in *ain;
4580 struct bgp_adj_in *ain_next;
718e3744 4581
d62a17ae 4582 table = peer->bgp->rib[afi][safi];
718e3744 4583
d62a17ae 4584 /* It is possible that we have multiple paths for a prefix from a peer
4585 * if that peer is using AddPath.
4586 */
4587 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
4588 ain = rn->adj_in;
43143c8f 4589
d62a17ae 4590 while (ain) {
4591 ain_next = ain->next;
43143c8f 4592
d62a17ae 4593 if (ain->peer == peer) {
4594 bgp_adj_in_remove(rn, ain);
4595 bgp_unlock_node(rn);
4596 }
43143c8f 4597
d62a17ae 4598 ain = ain_next;
4599 }
4600 }
718e3744 4601}
93406d87 4602
d62a17ae 4603void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4604{
4605 struct bgp_node *rn;
40381db7 4606 struct bgp_path_info *pi;
d62a17ae 4607 struct bgp_table *table;
4608
4609 if (safi == SAFI_MPLS_VPN) {
4610 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4611 rn = bgp_route_next(rn)) {
4612 struct bgp_node *rm;
d62a17ae 4613
4614 /* look for neighbor in tables */
67009e22
DS
4615 table = bgp_node_get_bgp_table_info(rn);
4616 if (!table)
ea47320b
DL
4617 continue;
4618
4619 for (rm = bgp_table_top(table); rm;
4620 rm = bgp_route_next(rm))
6f94b685
DS
4621 for (pi = bgp_node_get_bgp_path_info(rm); pi;
4622 pi = pi->next) {
40381db7 4623 if (pi->peer != peer)
ea47320b 4624 continue;
40381db7 4625 if (!CHECK_FLAG(pi->flags,
1defdda8 4626 BGP_PATH_STALE))
ea47320b
DL
4627 break;
4628
40381db7 4629 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4630 break;
4631 }
d62a17ae 4632 }
4633 } else {
4634 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4635 rn = bgp_route_next(rn))
6f94b685
DS
4636 for (pi = bgp_node_get_bgp_path_info(rn); pi;
4637 pi = pi->next) {
40381db7 4638 if (pi->peer != peer)
ea47320b 4639 continue;
40381db7 4640 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4641 break;
40381db7 4642 bgp_rib_remove(rn, pi, peer, afi, safi);
ea47320b
DL
4643 break;
4644 }
d62a17ae 4645 }
93406d87 4646}
6b0655a2 4647
3dc339cd 4648bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 4649{
e0df4c04 4650 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 4651 return true;
e0df4c04 4652
9dac9fc8
DA
4653 if (peer->sort == BGP_PEER_EBGP
4654 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
4655 || FILTER_LIST_OUT_NAME(filter)
4656 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
4657 return true;
4658 return false;
9dac9fc8
DA
4659}
4660
3dc339cd 4661bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 4662{
e0df4c04 4663 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 4664 return true;
e0df4c04 4665
9dac9fc8
DA
4666 if (peer->sort == BGP_PEER_EBGP
4667 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
4668 || FILTER_LIST_IN_NAME(filter)
4669 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
4670 return true;
4671 return false;
9dac9fc8
DA
4672}
4673
568e10ca 4674static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
4675 safi_t safi)
bb86c601 4676{
d62a17ae 4677 struct bgp_node *rn;
40381db7 4678 struct bgp_path_info *pi;
4b7e6066 4679 struct bgp_path_info *next;
bb86c601 4680
d62a17ae 4681 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
6f94b685 4682 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
b54892e0
DS
4683 const struct prefix *p = bgp_node_get_prefix(rn);
4684
40381db7 4685 next = pi->next;
1b7bb747
CS
4686
4687 /* Unimport EVPN routes from VRFs */
4688 if (safi == SAFI_EVPN)
4689 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 4690 SAFI_EVPN, p, pi);
1b7bb747 4691
40381db7
DS
4692 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
4693 && pi->type == ZEBRA_ROUTE_BGP
4694 && (pi->sub_type == BGP_ROUTE_NORMAL
4695 || pi->sub_type == BGP_ROUTE_AGGREGATE
4696 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 4697
d62a17ae 4698 if (bgp_fibupd_safi(safi))
b54892e0 4699 bgp_zebra_withdraw(p, pi, bgp, safi);
40381db7 4700 bgp_path_info_reap(rn, pi);
d62a17ae 4701 }
4702 }
bb86c601
LB
4703}
4704
718e3744 4705/* Delete all kernel routes. */
d62a17ae 4706void bgp_cleanup_routes(struct bgp *bgp)
4707{
4708 afi_t afi;
4709 struct bgp_node *rn;
67009e22 4710 struct bgp_table *table;
d62a17ae 4711
4712 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
4713 if (afi == AFI_L2VPN)
4714 continue;
568e10ca 4715 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
4716 SAFI_UNICAST);
d62a17ae 4717 /*
4718 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4719 */
4720 if (afi != AFI_L2VPN) {
4721 safi_t safi;
4722 safi = SAFI_MPLS_VPN;
4723 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4724 rn = bgp_route_next(rn)) {
67009e22
DS
4725 table = bgp_node_get_bgp_table_info(rn);
4726 if (table != NULL) {
4727 bgp_cleanup_table(bgp, table, safi);
4728 bgp_table_finish(&table);
4729 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4730 bgp_unlock_node(rn);
4731 }
4732 }
4733 safi = SAFI_ENCAP;
4734 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4735 rn = bgp_route_next(rn)) {
67009e22
DS
4736 table = bgp_node_get_bgp_table_info(rn);
4737 if (table != NULL) {
4738 bgp_cleanup_table(bgp, table, safi);
4739 bgp_table_finish(&table);
4740 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4741 bgp_unlock_node(rn);
4742 }
4743 }
4744 }
4745 }
4746 for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn;
4747 rn = bgp_route_next(rn)) {
67009e22
DS
4748 table = bgp_node_get_bgp_table_info(rn);
4749 if (table != NULL) {
4750 bgp_cleanup_table(bgp, table, SAFI_EVPN);
4751 bgp_table_finish(&table);
4752 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4753 bgp_unlock_node(rn);
4754 }
bb86c601 4755 }
718e3744 4756}
4757
d62a17ae 4758void bgp_reset(void)
718e3744 4759{
d62a17ae 4760 vty_reset();
4761 bgp_zclient_reset();
4762 access_list_reset();
4763 prefix_list_reset();
718e3744 4764}
6b0655a2 4765
d62a17ae 4766static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 4767{
d62a17ae 4768 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
4769 && CHECK_FLAG(peer->af_cap[afi][safi],
4770 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
4771}
4772
718e3744 4773/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4774 value. */
d62a17ae 4775int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
4776 struct bgp_nlri *packet)
4777{
d7c0a89a
QY
4778 uint8_t *pnt;
4779 uint8_t *lim;
d62a17ae 4780 struct prefix p;
4781 int psize;
4782 int ret;
4783 afi_t afi;
4784 safi_t safi;
4785 int addpath_encoded;
d7c0a89a 4786 uint32_t addpath_id;
d62a17ae 4787
d62a17ae 4788 pnt = packet->nlri;
4789 lim = pnt + packet->length;
4790 afi = packet->afi;
4791 safi = packet->safi;
4792 addpath_id = 0;
4793 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
4794
4795 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4796 syntactic validity. If the field is syntactically incorrect,
4797 then the Error Subcode is set to Invalid Network Field. */
4798 for (; pnt < lim; pnt += psize) {
4799 /* Clear prefix structure. */
4800 memset(&p, 0, sizeof(struct prefix));
4801
4802 if (addpath_encoded) {
4803
4804 /* When packet overflow occurs return immediately. */
761ed665 4805 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 4806 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4807
a3a850a1 4808 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 4809 addpath_id = ntohl(addpath_id);
d62a17ae 4810 pnt += BGP_ADDPATH_ID_LEN;
4811 }
718e3744 4812
d62a17ae 4813 /* Fetch prefix length. */
4814 p.prefixlen = *pnt++;
4815 /* afi/safi validity already verified by caller,
4816 * bgp_update_receive */
4817 p.family = afi2family(afi);
4818
4819 /* Prefix length check. */
4820 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 4821 flog_err(
e50f7cfd 4822 EC_BGP_UPDATE_RCV,
14454c9f 4823 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 4824 peer->host, p.prefixlen, packet->afi);
513386b5 4825 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 4826 }
6b0655a2 4827
d62a17ae 4828 /* Packet size overflow check. */
4829 psize = PSIZE(p.prefixlen);
4830
4831 /* When packet overflow occur return immediately. */
4832 if (pnt + psize > lim) {
af4c2728 4833 flog_err(
e50f7cfd 4834 EC_BGP_UPDATE_RCV,
d62a17ae 4835 "%s [Error] Update packet error (prefix length %d overflows packet)",
4836 peer->host, p.prefixlen);
513386b5 4837 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4838 }
4839
4840 /* Defensive coding, double-check the psize fits in a struct
4841 * prefix */
4842 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 4843 flog_err(
e50f7cfd 4844 EC_BGP_UPDATE_RCV,
d62a17ae 4845 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4846 peer->host, p.prefixlen, sizeof(p.u));
513386b5 4847 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4848 }
4849
4850 /* Fetch prefix from NLRI packet. */
a85297a7 4851 memcpy(p.u.val, pnt, psize);
d62a17ae 4852
4853 /* Check address. */
4854 if (afi == AFI_IP && safi == SAFI_UNICAST) {
4855 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
4856 /* From RFC4271 Section 6.3:
4857 *
4858 * If a prefix in the NLRI field is semantically
4859 * incorrect
4860 * (e.g., an unexpected multicast IP address),
4861 * an error SHOULD
4862 * be logged locally, and the prefix SHOULD be
4863 * ignored.
a4d82a8a 4864 */
af4c2728 4865 flog_err(
e50f7cfd 4866 EC_BGP_UPDATE_RCV,
d62a17ae 4867 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4868 peer->host, inet_ntoa(p.u.prefix4));
4869 continue;
4870 }
4871 }
4872
4873 /* Check address. */
4874 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
4875 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4876 char buf[BUFSIZ];
4877
af4c2728 4878 flog_err(
e50f7cfd 4879 EC_BGP_UPDATE_RCV,
d62a17ae 4880 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4881 peer->host,
4882 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4883 BUFSIZ));
4884
4885 continue;
4886 }
4887 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
4888 char buf[BUFSIZ];
4889
af4c2728 4890 flog_err(
e50f7cfd 4891 EC_BGP_UPDATE_RCV,
d62a17ae 4892 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4893 peer->host,
4894 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4895 BUFSIZ));
4896
4897 continue;
4898 }
4899 }
4900
4901 /* Normal process. */
4902 if (attr)
4903 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
4904 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 4905 NULL, NULL, 0, 0, NULL);
d62a17ae 4906 else
4907 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
4908 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
4909 BGP_ROUTE_NORMAL, NULL, NULL, 0,
4910 NULL);
d62a17ae 4911
513386b5
DA
4912 /* Do not send BGP notification twice when maximum-prefix count
4913 * overflow. */
4914 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4915 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
4916
4917 /* Address family configuration mismatch. */
d62a17ae 4918 if (ret < 0)
513386b5 4919 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 4920 }
4921
4922 /* Packet length consistency check. */
4923 if (pnt != lim) {
af4c2728 4924 flog_err(
e50f7cfd 4925 EC_BGP_UPDATE_RCV,
d62a17ae 4926 "%s [Error] Update packet error (prefix length mismatch with total length)",
4927 peer->host);
513386b5 4928 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4929 }
6b0655a2 4930
513386b5 4931 return BGP_NLRI_PARSE_OK;
718e3744 4932}
4933
d62a17ae 4934static struct bgp_static *bgp_static_new(void)
718e3744 4935{
d62a17ae 4936 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 4937}
4938
d62a17ae 4939static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 4940{
0a22ddfb 4941 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 4942 route_map_counter_decrement(bgp_static->rmap.map);
4943
0a22ddfb 4944 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 4945 XFREE(MTYPE_BGP_STATIC, bgp_static);
4946}
4947
5f040085 4948void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 4949 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
4950{
4951 struct bgp_node *rn;
40381db7 4952 struct bgp_path_info *pi;
4b7e6066 4953 struct bgp_path_info *new;
40381db7 4954 struct bgp_path_info rmap_path;
d62a17ae 4955 struct attr attr;
4956 struct attr *attr_new;
b68885f9 4957 route_map_result_t ret;
49e5a4a0 4958#ifdef ENABLE_BGP_VNC
d62a17ae 4959 int vnc_implicit_withdraw = 0;
65efcfce 4960#endif
fee0f4c6 4961
d62a17ae 4962 assert(bgp_static);
dd8103a9 4963
d62a17ae 4964 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4965
d62a17ae 4966 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 4967
d62a17ae 4968 attr.nexthop = bgp_static->igpnexthop;
4969 attr.med = bgp_static->igpmetric;
4970 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 4971
d62a17ae 4972 if (bgp_static->atomic)
4973 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 4974
d62a17ae 4975 /* Store label index, if required. */
4976 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
4977 attr.label_index = bgp_static->label_index;
4978 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
4979 }
718e3744 4980
d62a17ae 4981 /* Apply route-map. */
4982 if (bgp_static->rmap.name) {
4983 struct attr attr_tmp = attr;
80ced710 4984
40381db7
DS
4985 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
4986 rmap_path.peer = bgp->peer_self;
4987 rmap_path.attr = &attr_tmp;
fee0f4c6 4988
d62a17ae 4989 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 4990
40381db7
DS
4991 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
4992 &rmap_path);
fee0f4c6 4993
d62a17ae 4994 bgp->peer_self->rmap_type = 0;
718e3744 4995
d62a17ae 4996 if (ret == RMAP_DENYMATCH) {
4997 /* Free uninterned attribute. */
4998 bgp_attr_flush(&attr_tmp);
718e3744 4999
d62a17ae 5000 /* Unintern original. */
5001 aspath_unintern(&attr.aspath);
5002 bgp_static_withdraw(bgp, p, afi, safi);
5003 return;
5004 }
7f323236 5005
892fedb6 5006 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
7f323236
DW
5007 bgp_attr_add_gshut_community(&attr_tmp);
5008
d62a17ae 5009 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5010 } else {
5011
892fedb6 5012 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
7f323236
DW
5013 bgp_attr_add_gshut_community(&attr);
5014
d62a17ae 5015 attr_new = bgp_attr_intern(&attr);
7f323236 5016 }
718e3744 5017
6f94b685 5018 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
5019 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5020 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5021 break;
5022
40381db7
DS
5023 if (pi) {
5024 if (attrhash_cmp(pi->attr, attr_new)
5025 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5026 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
d62a17ae 5027 bgp_unlock_node(rn);
5028 bgp_attr_unintern(&attr_new);
5029 aspath_unintern(&attr.aspath);
5030 return;
5031 } else {
5032 /* The attribute is changed. */
40381db7 5033 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5034
5035 /* Rewrite BGP route information. */
40381db7
DS
5036 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
5037 bgp_path_info_restore(rn, pi);
d62a17ae 5038 else
40381db7 5039 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5040#ifdef ENABLE_BGP_VNC
d62a17ae 5041 if ((afi == AFI_IP || afi == AFI_IP6)
5042 && (safi == SAFI_UNICAST)) {
40381db7 5043 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5044 /*
5045 * Implicit withdraw case.
40381db7 5046 * We have to do this before pi is
d62a17ae 5047 * changed
5048 */
5049 ++vnc_implicit_withdraw;
40381db7 5050 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5051 vnc_import_bgp_exterior_del_route(
40381db7 5052 bgp, p, pi);
d62a17ae 5053 }
5054 }
65efcfce 5055#endif
40381db7
DS
5056 bgp_attr_unintern(&pi->attr);
5057 pi->attr = attr_new;
5058 pi->uptime = bgp_clock();
49e5a4a0 5059#ifdef ENABLE_BGP_VNC
d62a17ae 5060 if ((afi == AFI_IP || afi == AFI_IP6)
5061 && (safi == SAFI_UNICAST)) {
5062 if (vnc_implicit_withdraw) {
40381db7 5063 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5064 vnc_import_bgp_exterior_add_route(
40381db7 5065 bgp, p, pi);
d62a17ae 5066 }
5067 }
65efcfce 5068#endif
718e3744 5069
d62a17ae 5070 /* Nexthop reachability check. */
892fedb6 5071 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5072 && (safi == SAFI_UNICAST
5073 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5074
5075 struct bgp *bgp_nexthop = bgp;
5076
40381db7
DS
5077 if (pi->extra && pi->extra->bgp_orig)
5078 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5079
5080 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
40381db7
DS
5081 afi, pi, NULL, 0))
5082 bgp_path_info_set_flag(rn, pi,
18ee8310 5083 BGP_PATH_VALID);
d62a17ae 5084 else {
5085 if (BGP_DEBUG(nht, NHT)) {
5086 char buf1[INET6_ADDRSTRLEN];
5087 inet_ntop(p->family,
5088 &p->u.prefix, buf1,
5089 INET6_ADDRSTRLEN);
5090 zlog_debug(
5091 "%s(%s): Route not in table, not advertising",
15569c58 5092 __func__, buf1);
d62a17ae 5093 }
18ee8310 5094 bgp_path_info_unset_flag(
40381db7 5095 rn, pi, BGP_PATH_VALID);
d62a17ae 5096 }
5097 } else {
5098 /* Delete the NHT structure if any, if we're
5099 * toggling between
5100 * enabling/disabling import check. We
5101 * deregister the route
5102 * from NHT to avoid overloading NHT and the
5103 * process interaction
5104 */
40381db7
DS
5105 bgp_unlink_nexthop(pi);
5106 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 5107 }
5108 /* Process change. */
40381db7 5109 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 5110 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
5111
5112 if (SAFI_UNICAST == safi
5113 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5114 || bgp->inst_type
5115 == BGP_INSTANCE_TYPE_DEFAULT)) {
5116 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5117 pi);
ddb5b488
PZ
5118 }
5119
d62a17ae 5120 bgp_unlock_node(rn);
5121 aspath_unintern(&attr.aspath);
5122 return;
5123 }
718e3744 5124 }
718e3744 5125
d62a17ae 5126 /* Make new BGP info. */
5127 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
5128 attr_new, rn);
5129 /* Nexthop reachability check. */
892fedb6 5130 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5131 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 5132 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
18ee8310 5133 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
d62a17ae 5134 else {
5135 if (BGP_DEBUG(nht, NHT)) {
5136 char buf1[INET6_ADDRSTRLEN];
5137 inet_ntop(p->family, &p->u.prefix, buf1,
5138 INET6_ADDRSTRLEN);
5139 zlog_debug(
5140 "%s(%s): Route not in table, not advertising",
15569c58 5141 __func__, buf1);
d62a17ae 5142 }
18ee8310 5143 bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID);
d62a17ae 5144 }
5145 } else {
5146 /* Delete the NHT structure if any, if we're toggling between
5147 * enabling/disabling import check. We deregister the route
5148 * from NHT to avoid overloading NHT and the process interaction
5149 */
5150 bgp_unlink_nexthop(new);
5151
18ee8310 5152 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
fc9a856f 5153 }
078430f6 5154
d62a17ae 5155 /* Aggregate address increment. */
5156 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5157
d62a17ae 5158 /* Register new BGP information. */
18ee8310 5159 bgp_path_info_add(rn, new);
718e3744 5160
d62a17ae 5161 /* route_node_get lock */
5162 bgp_unlock_node(rn);
5163
5164 /* Process change. */
5165 bgp_process(bgp, rn, afi, safi);
5166
ddb5b488
PZ
5167 if (SAFI_UNICAST == safi
5168 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5169 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5170 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5171 }
5172
d62a17ae 5173 /* Unintern original. */
5174 aspath_unintern(&attr.aspath);
718e3744 5175}
5176
5f040085 5177void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 5178 safi_t safi)
718e3744 5179{
d62a17ae 5180 struct bgp_node *rn;
40381db7 5181 struct bgp_path_info *pi;
718e3744 5182
d62a17ae 5183 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5184
d62a17ae 5185 /* Check selected route and self inserted route. */
6f94b685 5186 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
5187 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5188 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5189 break;
5190
5191 /* Withdraw static BGP route from routing table. */
40381db7 5192 if (pi) {
ddb5b488
PZ
5193 if (SAFI_UNICAST == safi
5194 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5195 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5196 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5197 }
40381db7
DS
5198 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5199 bgp_unlink_nexthop(pi);
5200 bgp_path_info_delete(rn, pi);
d62a17ae 5201 bgp_process(bgp, rn, afi, safi);
5202 }
718e3744 5203
d62a17ae 5204 /* Unlock bgp_node_lookup. */
5205 bgp_unlock_node(rn);
718e3744 5206}
5207
137446f9
LB
5208/*
5209 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5210 */
5f040085 5211static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5212 afi_t afi, safi_t safi,
5213 struct prefix_rd *prd)
718e3744 5214{
d62a17ae 5215 struct bgp_node *rn;
40381db7 5216 struct bgp_path_info *pi;
718e3744 5217
d62a17ae 5218 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5219
d62a17ae 5220 /* Check selected route and self inserted route. */
6f94b685 5221 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
5222 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5223 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5224 break;
718e3744 5225
d62a17ae 5226 /* Withdraw static BGP route from routing table. */
40381db7 5227 if (pi) {
49e5a4a0 5228#ifdef ENABLE_BGP_VNC
d62a17ae 5229 rfapiProcessWithdraw(
40381db7 5230 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5231 1); /* Kill, since it is an administrative change */
65efcfce 5232#endif
ddb5b488
PZ
5233 if (SAFI_MPLS_VPN == safi
5234 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5235 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5236 }
40381db7
DS
5237 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5238 bgp_path_info_delete(rn, pi);
d62a17ae 5239 bgp_process(bgp, rn, afi, safi);
5240 }
718e3744 5241
d62a17ae 5242 /* Unlock bgp_node_lookup. */
5243 bgp_unlock_node(rn);
718e3744 5244}
5245
5f040085 5246static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5247 struct bgp_static *bgp_static, afi_t afi,
5248 safi_t safi)
137446f9 5249{
d62a17ae 5250 struct bgp_node *rn;
4b7e6066 5251 struct bgp_path_info *new;
d62a17ae 5252 struct attr *attr_new;
5253 struct attr attr = {0};
40381db7 5254 struct bgp_path_info *pi;
49e5a4a0 5255#ifdef ENABLE_BGP_VNC
d62a17ae 5256 mpls_label_t label = 0;
65efcfce 5257#endif
d7c0a89a 5258 uint32_t num_labels = 0;
d62a17ae 5259 union gw_addr add;
137446f9 5260
d62a17ae 5261 assert(bgp_static);
137446f9 5262
b57ba6d2
MK
5263 if (bgp_static->label != MPLS_INVALID_LABEL)
5264 num_labels = 1;
d62a17ae 5265 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5266 &bgp_static->prd);
137446f9 5267
d62a17ae 5268 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5269
d62a17ae 5270 attr.nexthop = bgp_static->igpnexthop;
5271 attr.med = bgp_static->igpmetric;
5272 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5273
d62a17ae 5274 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5275 || (safi == SAFI_ENCAP)) {
5276 if (afi == AFI_IP) {
5277 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5278 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5279 }
5280 }
5281 if (afi == AFI_L2VPN) {
5282 if (bgp_static->gatewayIp.family == AF_INET)
5283 add.ipv4.s_addr =
5284 bgp_static->gatewayIp.u.prefix4.s_addr;
5285 else if (bgp_static->gatewayIp.family == AF_INET6)
5286 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5287 sizeof(struct in6_addr));
5288 overlay_index_update(&attr, bgp_static->eth_s_id, &add);
5289 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5290 struct bgp_encap_type_vxlan bet;
5291 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5292 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5293 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5294 }
5295 if (bgp_static->router_mac) {
5296 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5297 }
5298 }
5299 /* Apply route-map. */
5300 if (bgp_static->rmap.name) {
5301 struct attr attr_tmp = attr;
40381db7 5302 struct bgp_path_info rmap_path;
b68885f9 5303 route_map_result_t ret;
137446f9 5304
40381db7
DS
5305 rmap_path.peer = bgp->peer_self;
5306 rmap_path.attr = &attr_tmp;
137446f9 5307
d62a17ae 5308 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5309
40381db7
DS
5310 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
5311 &rmap_path);
137446f9 5312
d62a17ae 5313 bgp->peer_self->rmap_type = 0;
137446f9 5314
d62a17ae 5315 if (ret == RMAP_DENYMATCH) {
5316 /* Free uninterned attribute. */
5317 bgp_attr_flush(&attr_tmp);
137446f9 5318
d62a17ae 5319 /* Unintern original. */
5320 aspath_unintern(&attr.aspath);
5321 bgp_static_withdraw_safi(bgp, p, afi, safi,
5322 &bgp_static->prd);
5323 return;
5324 }
137446f9 5325
d62a17ae 5326 attr_new = bgp_attr_intern(&attr_tmp);
5327 } else {
5328 attr_new = bgp_attr_intern(&attr);
5329 }
137446f9 5330
6f94b685 5331 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
5332 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5333 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5334 break;
5335
40381db7 5336 if (pi) {
d62a17ae 5337 memset(&add, 0, sizeof(union gw_addr));
40381db7
DS
5338 if (attrhash_cmp(pi->attr, attr_new)
5339 && overlay_index_equal(afi, pi, bgp_static->eth_s_id, &add)
5340 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 5341 bgp_unlock_node(rn);
5342 bgp_attr_unintern(&attr_new);
5343 aspath_unintern(&attr.aspath);
5344 return;
5345 } else {
5346 /* The attribute is changed. */
40381db7 5347 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5348
5349 /* Rewrite BGP route information. */
40381db7
DS
5350 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
5351 bgp_path_info_restore(rn, pi);
d62a17ae 5352 else
40381db7
DS
5353 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5354 bgp_attr_unintern(&pi->attr);
5355 pi->attr = attr_new;
5356 pi->uptime = bgp_clock();
49e5a4a0 5357#ifdef ENABLE_BGP_VNC
40381db7
DS
5358 if (pi->extra)
5359 label = decode_label(&pi->extra->label[0]);
65efcfce 5360#endif
137446f9 5361
d62a17ae 5362 /* Process change. */
40381db7 5363 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 5364 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
5365
5366 if (SAFI_MPLS_VPN == safi
5367 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5368 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5369 }
49e5a4a0 5370#ifdef ENABLE_BGP_VNC
40381db7
DS
5371 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5372 pi->attr, afi, safi, pi->type,
5373 pi->sub_type, &label);
65efcfce 5374#endif
d62a17ae 5375 bgp_unlock_node(rn);
5376 aspath_unintern(&attr.aspath);
5377 return;
5378 }
5379 }
137446f9
LB
5380
5381
d62a17ae 5382 /* Make new BGP info. */
5383 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
5384 attr_new, rn);
1defdda8 5385 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5386 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5387 if (num_labels) {
5388 new->extra->label[0] = bgp_static->label;
5389 new->extra->num_labels = num_labels;
5390 }
49e5a4a0 5391#ifdef ENABLE_BGP_VNC
d62a17ae 5392 label = decode_label(&bgp_static->label);
65efcfce 5393#endif
137446f9 5394
d62a17ae 5395 /* Aggregate address increment. */
5396 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5397
d62a17ae 5398 /* Register new BGP information. */
18ee8310 5399 bgp_path_info_add(rn, new);
d62a17ae 5400 /* route_node_get lock */
5401 bgp_unlock_node(rn);
137446f9 5402
d62a17ae 5403 /* Process change. */
5404 bgp_process(bgp, rn, afi, safi);
137446f9 5405
ddb5b488
PZ
5406 if (SAFI_MPLS_VPN == safi
5407 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5408 vpn_leak_to_vrf_update(bgp, new);
5409 }
49e5a4a0 5410#ifdef ENABLE_BGP_VNC
d62a17ae 5411 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5412 safi, new->type, new->sub_type, &label);
65efcfce
LB
5413#endif
5414
d62a17ae 5415 /* Unintern original. */
5416 aspath_unintern(&attr.aspath);
137446f9
LB
5417}
5418
718e3744 5419/* Configure static BGP network. When user don't run zebra, static
5420 route should be installed as valid. */
e2a86ad9
DS
5421static int bgp_static_set(struct vty *vty, const char *negate,
5422 const char *ip_str, afi_t afi, safi_t safi,
d7c0a89a 5423 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 5424{
5425 VTY_DECLVAR_CONTEXT(bgp, bgp);
5426 int ret;
5427 struct prefix p;
5428 struct bgp_static *bgp_static;
5429 struct bgp_node *rn;
d7c0a89a 5430 uint8_t need_update = 0;
d62a17ae 5431
5432 /* Convert IP prefix string to struct prefix. */
5433 ret = str2prefix(ip_str, &p);
5434 if (!ret) {
5435 vty_out(vty, "%% Malformed prefix\n");
5436 return CMD_WARNING_CONFIG_FAILED;
5437 }
5438 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5439 vty_out(vty, "%% Malformed prefix (link-local address)\n");
5440 return CMD_WARNING_CONFIG_FAILED;
5441 }
718e3744 5442
d62a17ae 5443 apply_mask(&p);
718e3744 5444
e2a86ad9 5445 if (negate) {
718e3744 5446
e2a86ad9
DS
5447 /* Set BGP static route configuration. */
5448 rn = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5449
e2a86ad9 5450 if (!rn) {
a4d82a8a 5451 vty_out(vty, "%% Can't find static route specified\n");
d62a17ae 5452 return CMD_WARNING_CONFIG_FAILED;
5453 }
5454
5a8ba9fc 5455 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 5456
e2a86ad9
DS
5457 if ((label_index != BGP_INVALID_LABEL_INDEX)
5458 && (label_index != bgp_static->label_index)) {
5459 vty_out(vty,
5460 "%% label-index doesn't match static route\n");
5461 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5462 }
d62a17ae 5463
e2a86ad9
DS
5464 if ((rmap && bgp_static->rmap.name)
5465 && strcmp(rmap, bgp_static->rmap.name)) {
5466 vty_out(vty,
5467 "%% route-map name doesn't match static route\n");
5468 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5469 }
718e3744 5470
e2a86ad9
DS
5471 /* Update BGP RIB. */
5472 if (!bgp_static->backdoor)
5473 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5474
e2a86ad9
DS
5475 /* Clear configuration. */
5476 bgp_static_free(bgp_static);
5a8ba9fc 5477 bgp_node_set_bgp_static_info(rn, NULL);
e2a86ad9
DS
5478 bgp_unlock_node(rn);
5479 bgp_unlock_node(rn);
5480 } else {
718e3744 5481
e2a86ad9
DS
5482 /* Set BGP static route configuration. */
5483 rn = bgp_node_get(bgp->route[afi][safi], &p);
718e3744 5484
5a8ba9fc 5485 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 5486 if (bgp_static) {
e2a86ad9 5487 /* Configuration change. */
e2a86ad9
DS
5488 /* Label index cannot be changed. */
5489 if (bgp_static->label_index != label_index) {
5490 vty_out(vty, "%% cannot change label-index\n");
5491 return CMD_WARNING_CONFIG_FAILED;
5492 }
d62a17ae 5493
e2a86ad9 5494 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5495 if (bgp_static->valid
5496 && bgp_static->backdoor != backdoor)
e2a86ad9 5497 need_update = 1;
718e3744 5498
e2a86ad9 5499 bgp_static->backdoor = backdoor;
718e3744 5500
e2a86ad9 5501 if (rmap) {
0a22ddfb
QY
5502 XFREE(MTYPE_ROUTE_MAP_NAME,
5503 bgp_static->rmap.name);
b4897fa5 5504 route_map_counter_decrement(
5505 bgp_static->rmap.map);
e2a86ad9
DS
5506 bgp_static->rmap.name =
5507 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5508 bgp_static->rmap.map =
5509 route_map_lookup_by_name(rmap);
b4897fa5 5510 route_map_counter_increment(
5511 bgp_static->rmap.map);
e2a86ad9 5512 } else {
0a22ddfb
QY
5513 XFREE(MTYPE_ROUTE_MAP_NAME,
5514 bgp_static->rmap.name);
b4897fa5 5515 route_map_counter_decrement(
5516 bgp_static->rmap.map);
e2a86ad9
DS
5517 bgp_static->rmap.map = NULL;
5518 bgp_static->valid = 0;
5519 }
5520 bgp_unlock_node(rn);
5521 } else {
5522 /* New configuration. */
5523 bgp_static = bgp_static_new();
5524 bgp_static->backdoor = backdoor;
5525 bgp_static->valid = 0;
5526 bgp_static->igpmetric = 0;
975a328e 5527 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 5528 bgp_static->label_index = label_index;
718e3744 5529
e2a86ad9 5530 if (rmap) {
0a22ddfb
QY
5531 XFREE(MTYPE_ROUTE_MAP_NAME,
5532 bgp_static->rmap.name);
b4897fa5 5533 route_map_counter_decrement(
5534 bgp_static->rmap.map);
e2a86ad9
DS
5535 bgp_static->rmap.name =
5536 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5537 bgp_static->rmap.map =
5538 route_map_lookup_by_name(rmap);
b4897fa5 5539 route_map_counter_increment(
5540 bgp_static->rmap.map);
e2a86ad9 5541 }
5a8ba9fc 5542 bgp_node_set_bgp_static_info(rn, bgp_static);
e2a86ad9 5543 }
d62a17ae 5544
e2a86ad9
DS
5545 bgp_static->valid = 1;
5546 if (need_update)
5547 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5548
e2a86ad9
DS
5549 if (!bgp_static->backdoor)
5550 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5551 }
d62a17ae 5552
5553 return CMD_SUCCESS;
5554}
5555
5556void bgp_static_add(struct bgp *bgp)
5557{
5558 afi_t afi;
5559 safi_t safi;
5560 struct bgp_node *rn;
5561 struct bgp_node *rm;
5562 struct bgp_table *table;
5563 struct bgp_static *bgp_static;
5564
05c7a1cc
QY
5565 FOREACH_AFI_SAFI (afi, safi)
5566 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5567 rn = bgp_route_next(rn)) {
67009e22 5568 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5569 continue;
ea47320b 5570
05c7a1cc
QY
5571 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5572 || (safi == SAFI_EVPN)) {
67009e22 5573 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5574
5575 for (rm = bgp_table_top(table); rm;
5576 rm = bgp_route_next(rm)) {
a78beeb5 5577 bgp_static =
5a8ba9fc
DS
5578 bgp_node_get_bgp_static_info(
5579 rm);
b54892e0
DS
5580 bgp_static_update_safi(bgp,
5581 bgp_node_get_prefix(rm),
05c7a1cc
QY
5582 bgp_static, afi,
5583 safi);
d62a17ae 5584 }
05c7a1cc 5585 } else {
5a8ba9fc 5586 bgp_static_update(
b54892e0 5587 bgp, bgp_node_get_prefix(rn),
5a8ba9fc
DS
5588 bgp_node_get_bgp_static_info(rn), afi,
5589 safi);
ea47320b 5590 }
05c7a1cc 5591 }
6aeb9e78
DS
5592}
5593
718e3744 5594/* Called from bgp_delete(). Delete all static routes from the BGP
5595 instance. */
d62a17ae 5596void bgp_static_delete(struct bgp *bgp)
5597{
5598 afi_t afi;
5599 safi_t safi;
5600 struct bgp_node *rn;
5601 struct bgp_node *rm;
5602 struct bgp_table *table;
5603 struct bgp_static *bgp_static;
5604
05c7a1cc
QY
5605 FOREACH_AFI_SAFI (afi, safi)
5606 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5607 rn = bgp_route_next(rn)) {
67009e22 5608 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5609 continue;
ea47320b 5610
05c7a1cc
QY
5611 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5612 || (safi == SAFI_EVPN)) {
67009e22 5613 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5614
5615 for (rm = bgp_table_top(table); rm;
5616 rm = bgp_route_next(rm)) {
a78beeb5 5617 bgp_static =
5a8ba9fc
DS
5618 bgp_node_get_bgp_static_info(
5619 rm);
c7d14ba6
PG
5620 if (!bgp_static)
5621 continue;
5622
05c7a1cc 5623 bgp_static_withdraw_safi(
b54892e0
DS
5624 bgp, bgp_node_get_prefix(rm),
5625 AFI_IP, safi,
5626 (struct prefix_rd *)
5627 bgp_node_get_prefix(
5628 rn));
ea47320b 5629 bgp_static_free(bgp_static);
5a8ba9fc 5630 bgp_node_set_bgp_static_info(rn, NULL);
ea47320b 5631 bgp_unlock_node(rn);
d62a17ae 5632 }
05c7a1cc 5633 } else {
5a8ba9fc 5634 bgp_static = bgp_node_get_bgp_static_info(rn);
b54892e0
DS
5635 bgp_static_withdraw(bgp,
5636 bgp_node_get_prefix(rn),
5637 afi, safi);
05c7a1cc 5638 bgp_static_free(bgp_static);
5a8ba9fc 5639 bgp_node_set_bgp_static_info(rn, NULL);
05c7a1cc 5640 bgp_unlock_node(rn);
ea47320b 5641 }
05c7a1cc 5642 }
d62a17ae 5643}
5644
5645void bgp_static_redo_import_check(struct bgp *bgp)
5646{
5647 afi_t afi;
5648 safi_t safi;
5649 struct bgp_node *rn;
5650 struct bgp_node *rm;
5651 struct bgp_table *table;
5652 struct bgp_static *bgp_static;
5653
5654 /* Use this flag to force reprocessing of the route */
892fedb6 5655 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc
QY
5656 FOREACH_AFI_SAFI (afi, safi) {
5657 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5658 rn = bgp_route_next(rn)) {
67009e22 5659 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5660 continue;
ea47320b 5661
05c7a1cc
QY
5662 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5663 || (safi == SAFI_EVPN)) {
67009e22 5664 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5665
5666 for (rm = bgp_table_top(table); rm;
5667 rm = bgp_route_next(rm)) {
a78beeb5 5668 bgp_static =
5a8ba9fc
DS
5669 bgp_node_get_bgp_static_info(
5670 rm);
b54892e0
DS
5671 bgp_static_update_safi(bgp,
5672 bgp_node_get_prefix(rm),
05c7a1cc
QY
5673 bgp_static, afi,
5674 safi);
d62a17ae 5675 }
05c7a1cc 5676 } else {
5a8ba9fc 5677 bgp_static = bgp_node_get_bgp_static_info(rn);
b54892e0
DS
5678 bgp_static_update(bgp, bgp_node_get_prefix(rn),
5679 bgp_static, afi,
05c7a1cc 5680 safi);
ea47320b 5681 }
05c7a1cc
QY
5682 }
5683 }
892fedb6 5684 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 5685}
5686
5687static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
5688 safi_t safi)
5689{
5690 struct bgp_table *table;
5691 struct bgp_node *rn;
40381db7 5692 struct bgp_path_info *pi;
d62a17ae 5693
dfb6fd1d
NT
5694 /* Do not install the aggregate route if BGP is in the
5695 * process of termination.
5696 */
892fedb6
DA
5697 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
5698 || (bgp->peer_self == NULL))
dfb6fd1d
NT
5699 return;
5700
d62a17ae 5701 table = bgp->rib[afi][safi];
5702 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685 5703 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7
DS
5704 if (pi->peer == bgp->peer_self
5705 && ((pi->type == ZEBRA_ROUTE_BGP
5706 && pi->sub_type == BGP_ROUTE_STATIC)
5707 || (pi->type != ZEBRA_ROUTE_BGP
5708 && pi->sub_type
d62a17ae 5709 == BGP_ROUTE_REDISTRIBUTE))) {
b54892e0
DS
5710 bgp_aggregate_decrement(bgp,
5711 bgp_node_get_prefix(rn),
5712 pi, afi, safi);
40381db7
DS
5713 bgp_unlink_nexthop(pi);
5714 bgp_path_info_delete(rn, pi);
d62a17ae 5715 bgp_process(bgp, rn, afi, safi);
5716 }
5717 }
5718 }
ad4cbda1 5719}
5720
5721/*
5722 * Purge all networks and redistributed routes from routing table.
5723 * Invoked upon the instance going down.
5724 */
d62a17ae 5725void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 5726{
d62a17ae 5727 afi_t afi;
5728 safi_t safi;
ad4cbda1 5729
05c7a1cc
QY
5730 FOREACH_AFI_SAFI (afi, safi)
5731 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 5732}
5733
137446f9
LB
5734/*
5735 * gpz 110624
5736 * Currently this is used to set static routes for VPN and ENCAP.
5737 * I think it can probably be factored with bgp_static_set.
5738 */
d62a17ae 5739int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
5740 const char *ip_str, const char *rd_str,
5741 const char *label_str, const char *rmap_str,
5742 int evpn_type, const char *esi, const char *gwip,
5743 const char *ethtag, const char *routermac)
5744{
5745 VTY_DECLVAR_CONTEXT(bgp, bgp);
5746 int ret;
5747 struct prefix p;
5748 struct prefix_rd prd;
5749 struct bgp_node *prn;
5750 struct bgp_node *rn;
5751 struct bgp_table *table;
5752 struct bgp_static *bgp_static;
5753 mpls_label_t label = MPLS_INVALID_LABEL;
5754 struct prefix gw_ip;
5755
5756 /* validate ip prefix */
5757 ret = str2prefix(ip_str, &p);
5758 if (!ret) {
5759 vty_out(vty, "%% Malformed prefix\n");
5760 return CMD_WARNING_CONFIG_FAILED;
5761 }
5762 apply_mask(&p);
5763 if ((afi == AFI_L2VPN)
5764 && (bgp_build_evpn_prefix(evpn_type,
5765 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5766 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5767 return CMD_WARNING_CONFIG_FAILED;
5768 }
718e3744 5769
d62a17ae 5770 ret = str2prefix_rd(rd_str, &prd);
5771 if (!ret) {
5772 vty_out(vty, "%% Malformed rd\n");
5773 return CMD_WARNING_CONFIG_FAILED;
5774 }
718e3744 5775
d62a17ae 5776 if (label_str) {
5777 unsigned long label_val;
5778 label_val = strtoul(label_str, NULL, 10);
5779 encode_label(label_val, &label);
5780 }
9bedbb1e 5781
d62a17ae 5782 if (safi == SAFI_EVPN) {
5783 if (esi && str2esi(esi, NULL) == 0) {
5784 vty_out(vty, "%% Malformed ESI\n");
5785 return CMD_WARNING_CONFIG_FAILED;
5786 }
5787 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
5788 vty_out(vty, "%% Malformed Router MAC\n");
5789 return CMD_WARNING_CONFIG_FAILED;
5790 }
5791 if (gwip) {
5792 memset(&gw_ip, 0, sizeof(struct prefix));
5793 ret = str2prefix(gwip, &gw_ip);
5794 if (!ret) {
5795 vty_out(vty, "%% Malformed GatewayIp\n");
5796 return CMD_WARNING_CONFIG_FAILED;
5797 }
5798 if ((gw_ip.family == AF_INET
3714a385 5799 && is_evpn_prefix_ipaddr_v6(
d62a17ae 5800 (struct prefix_evpn *)&p))
5801 || (gw_ip.family == AF_INET6
3714a385 5802 && is_evpn_prefix_ipaddr_v4(
d62a17ae 5803 (struct prefix_evpn *)&p))) {
5804 vty_out(vty,
5805 "%% GatewayIp family differs with IP prefix\n");
5806 return CMD_WARNING_CONFIG_FAILED;
5807 }
5808 }
5809 }
5810 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
67009e22
DS
5811 if (!bgp_node_has_bgp_path_info_data(prn))
5812 bgp_node_set_bgp_table_info(prn,
5813 bgp_table_init(bgp, afi, safi));
67009e22 5814 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 5815
5816 rn = bgp_node_get(table, &p);
5817
67009e22 5818 if (bgp_node_has_bgp_path_info_data(rn)) {
d62a17ae 5819 vty_out(vty, "%% Same network configuration exists\n");
5820 bgp_unlock_node(rn);
5821 } else {
5822 /* New configuration. */
5823 bgp_static = bgp_static_new();
5824 bgp_static->backdoor = 0;
5825 bgp_static->valid = 0;
5826 bgp_static->igpmetric = 0;
975a328e 5827 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 5828 bgp_static->label = label;
5829 bgp_static->prd = prd;
5830
5831 if (rmap_str) {
0a22ddfb 5832 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5833 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 5834 bgp_static->rmap.name =
5835 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
5836 bgp_static->rmap.map =
5837 route_map_lookup_by_name(rmap_str);
b4897fa5 5838 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 5839 }
718e3744 5840
d62a17ae 5841 if (safi == SAFI_EVPN) {
5842 if (esi) {
5843 bgp_static->eth_s_id =
5844 XCALLOC(MTYPE_ATTR,
5845 sizeof(struct eth_segment_id));
5846 str2esi(esi, bgp_static->eth_s_id);
5847 }
5848 if (routermac) {
5849 bgp_static->router_mac =
28328ea9 5850 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
5851 (void)prefix_str2mac(routermac,
5852 bgp_static->router_mac);
d62a17ae 5853 }
5854 if (gwip)
5855 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
5856 }
5a8ba9fc 5857 bgp_node_set_bgp_static_info(rn, bgp_static);
718e3744 5858
d62a17ae 5859 bgp_static->valid = 1;
5860 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
5861 }
718e3744 5862
d62a17ae 5863 return CMD_SUCCESS;
718e3744 5864}
5865
5866/* Configure static BGP network. */
d62a17ae 5867int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
5868 const char *ip_str, const char *rd_str,
5869 const char *label_str, int evpn_type, const char *esi,
5870 const char *gwip, const char *ethtag)
5871{
5872 VTY_DECLVAR_CONTEXT(bgp, bgp);
5873 int ret;
5874 struct prefix p;
5875 struct prefix_rd prd;
5876 struct bgp_node *prn;
5877 struct bgp_node *rn;
5878 struct bgp_table *table;
5879 struct bgp_static *bgp_static;
5880 mpls_label_t label = MPLS_INVALID_LABEL;
5881
5882 /* Convert IP prefix string to struct prefix. */
5883 ret = str2prefix(ip_str, &p);
5884 if (!ret) {
5885 vty_out(vty, "%% Malformed prefix\n");
5886 return CMD_WARNING_CONFIG_FAILED;
5887 }
5888 apply_mask(&p);
5889 if ((afi == AFI_L2VPN)
5890 && (bgp_build_evpn_prefix(evpn_type,
5891 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5892 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5893 return CMD_WARNING_CONFIG_FAILED;
5894 }
5895 ret = str2prefix_rd(rd_str, &prd);
5896 if (!ret) {
5897 vty_out(vty, "%% Malformed rd\n");
5898 return CMD_WARNING_CONFIG_FAILED;
5899 }
718e3744 5900
d62a17ae 5901 if (label_str) {
5902 unsigned long label_val;
5903 label_val = strtoul(label_str, NULL, 10);
5904 encode_label(label_val, &label);
5905 }
718e3744 5906
d62a17ae 5907 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
67009e22
DS
5908 if (!bgp_node_has_bgp_path_info_data(prn))
5909 bgp_node_set_bgp_table_info(prn,
5910 bgp_table_init(bgp, afi, safi));
d62a17ae 5911 else
5912 bgp_unlock_node(prn);
67009e22 5913 table = bgp_node_get_bgp_table_info(prn);
718e3744 5914
d62a17ae 5915 rn = bgp_node_lookup(table, &p);
6b0655a2 5916
d62a17ae 5917 if (rn) {
5918 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 5919
5a8ba9fc 5920 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 5921 bgp_static_free(bgp_static);
5a8ba9fc 5922 bgp_node_set_bgp_static_info(rn, NULL);
d62a17ae 5923 bgp_unlock_node(rn);
5924 bgp_unlock_node(rn);
5925 } else
5926 vty_out(vty, "%% Can't find the route\n");
5927
5928 return CMD_SUCCESS;
5929}
5930
5931static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
5932 const char *rmap_name)
5933{
5934 VTY_DECLVAR_CONTEXT(bgp, bgp);
5935 struct bgp_rmap *rmap;
5936
5937 rmap = &bgp->table_map[afi][safi];
5938 if (rmap_name) {
0a22ddfb 5939 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5940 route_map_counter_decrement(rmap->map);
d62a17ae 5941 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
5942 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 5943 route_map_counter_increment(rmap->map);
d62a17ae 5944 } else {
0a22ddfb 5945 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5946 route_map_counter_decrement(rmap->map);
d62a17ae 5947 rmap->map = NULL;
5948 }
73ac8160 5949
d62a17ae 5950 if (bgp_fibupd_safi(safi))
5951 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5952
d62a17ae 5953 return CMD_SUCCESS;
73ac8160
DS
5954}
5955
d62a17ae 5956static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
5957 const char *rmap_name)
73ac8160 5958{
d62a17ae 5959 VTY_DECLVAR_CONTEXT(bgp, bgp);
5960 struct bgp_rmap *rmap;
73ac8160 5961
d62a17ae 5962 rmap = &bgp->table_map[afi][safi];
0a22ddfb 5963 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5964 route_map_counter_decrement(rmap->map);
d62a17ae 5965 rmap->map = NULL;
73ac8160 5966
d62a17ae 5967 if (bgp_fibupd_safi(safi))
5968 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5969
d62a17ae 5970 return CMD_SUCCESS;
73ac8160
DS
5971}
5972
2b791107 5973void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 5974 safi_t safi)
73ac8160 5975{
d62a17ae 5976 if (bgp->table_map[afi][safi].name) {
d62a17ae 5977 vty_out(vty, " table-map %s\n",
5978 bgp->table_map[afi][safi].name);
5979 }
73ac8160
DS
5980}
5981
73ac8160
DS
5982DEFUN (bgp_table_map,
5983 bgp_table_map_cmd,
5984 "table-map WORD",
5985 "BGP table to RIB route download filter\n"
5986 "Name of the route map\n")
5987{
d62a17ae 5988 int idx_word = 1;
5989 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5990 argv[idx_word]->arg);
73ac8160
DS
5991}
5992DEFUN (no_bgp_table_map,
5993 no_bgp_table_map_cmd,
5994 "no table-map WORD",
3a2d747c 5995 NO_STR
73ac8160
DS
5996 "BGP table to RIB route download filter\n"
5997 "Name of the route map\n")
5998{
d62a17ae 5999 int idx_word = 2;
6000 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6001 argv[idx_word]->arg);
73ac8160
DS
6002}
6003
e2a86ad9
DS
6004DEFPY(bgp_network,
6005 bgp_network_cmd,
6006 "[no] network \
6007 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6008 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6009 backdoor$backdoor}]",
6010 NO_STR
6011 "Specify a network to announce via BGP\n"
6012 "IPv4 prefix\n"
6013 "Network number\n"
6014 "Network mask\n"
6015 "Network mask\n"
6016 "Route-map to modify the attributes\n"
6017 "Name of the route map\n"
6018 "Label index to associate with the prefix\n"
6019 "Label index value\n"
6020 "Specify a BGP backdoor route\n")
6021{
6022 char addr_prefix_str[BUFSIZ];
6023
6024 if (address_str) {
6025 int ret;
718e3744 6026
e2a86ad9
DS
6027 ret = netmask_str2prefix_str(address_str, netmask_str,
6028 addr_prefix_str);
6029 if (!ret) {
6030 vty_out(vty, "%% Inconsistent address and mask\n");
6031 return CMD_WARNING_CONFIG_FAILED;
6032 }
d62a17ae 6033 }
718e3744 6034
a4d82a8a
PZ
6035 return bgp_static_set(
6036 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
6037 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
6038 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 6039}
6040
e2a86ad9
DS
6041DEFPY(ipv6_bgp_network,
6042 ipv6_bgp_network_cmd,
6043 "[no] network X:X::X:X/M$prefix \
6044 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6045 NO_STR
6046 "Specify a network to announce via BGP\n"
6047 "IPv6 prefix\n"
6048 "Route-map to modify the attributes\n"
6049 "Name of the route map\n"
6050 "Label index to associate with the prefix\n"
6051 "Label index value\n")
718e3744 6052{
a4d82a8a
PZ
6053 return bgp_static_set(
6054 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
6055 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
6056}
6057
d62a17ae 6058static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6059{
d62a17ae 6060 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6061}
6062
d62a17ae 6063static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6064{
20894f50
DA
6065 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6066 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6067 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6068}
718e3744 6069
3dc339cd
DA
6070static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6071 struct aspath *aspath,
6072 struct community *comm,
6073 struct ecommunity *ecomm,
6074 struct lcommunity *lcomm)
eaaf8adb
DS
6075{
6076 static struct aspath *ae = NULL;
6077
6078 if (!ae)
6079 ae = aspath_empty();
6080
40381db7 6081 if (!pi)
3dc339cd 6082 return false;
eaaf8adb 6083
40381db7 6084 if (origin != pi->attr->origin)
3dc339cd 6085 return false;
eaaf8adb 6086
40381db7 6087 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 6088 return false;
29f7d023 6089
40381db7 6090 if (!community_cmp(pi->attr->community, comm))
3dc339cd 6091 return false;
eaaf8adb 6092
3da2cc32 6093 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
3dc339cd 6094 return false;
eaaf8adb 6095
dd18c5a9 6096 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 6097 return false;
dd18c5a9 6098
40381db7 6099 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 6100 return false;
7ce8a8e0 6101
3dc339cd 6102 return true;
eaaf8adb
DS
6103}
6104
5f040085
DS
6105static void bgp_aggregate_install(
6106 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6107 uint8_t origin, struct aspath *aspath, struct community *community,
6108 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6109 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e
DS
6110{
6111 struct bgp_node *rn;
6112 struct bgp_table *table;
6f94b685 6113 struct bgp_path_info *pi, *orig, *new;
20894f50 6114 struct attr *attr;
c701010e
DS
6115
6116 table = bgp->rib[afi][safi];
6117
6118 rn = bgp_node_get(table, p);
eaaf8adb 6119
6f94b685 6120 for (orig = pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
6121 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6122 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6123 break;
6124
c701010e 6125 if (aggregate->count > 0) {
eaaf8adb
DS
6126 /*
6127 * If the aggregate information has not changed
6128 * no need to re-install it again.
6129 */
6f94b685 6130 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6131 ecommunity, lcommunity)) {
eaaf8adb
DS
6132 bgp_unlock_node(rn);
6133
6134 if (aspath)
6135 aspath_free(aspath);
6136 if (community)
3c1f53de 6137 community_free(&community);
3da2cc32
DS
6138 if (ecommunity)
6139 ecommunity_free(&ecommunity);
dd18c5a9
DS
6140 if (lcommunity)
6141 lcommunity_free(&lcommunity);
eaaf8adb
DS
6142
6143 return;
6144 }
6145
6146 /*
6147 * Mark the old as unusable
6148 */
40381db7
DS
6149 if (pi)
6150 bgp_path_info_delete(rn, pi);
eaaf8adb 6151
20894f50
DA
6152 attr = bgp_attr_aggregate_intern(
6153 bgp, origin, aspath, community, ecommunity, lcommunity,
6154 aggregate, atomic_aggregate, p);
6155
6156 if (!attr) {
6157 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
6158 return;
6159 }
6160
3da2cc32 6161 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
20894f50
DA
6162 bgp->peer_self, attr, rn);
6163
1defdda8 6164 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6165
18ee8310 6166 bgp_path_info_add(rn, new);
c701010e
DS
6167 bgp_process(bgp, rn, afi, safi);
6168 } else {
6f94b685 6169 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6170 if (pi->peer == bgp->peer_self
6171 && pi->type == ZEBRA_ROUTE_BGP
6172 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6173 break;
6174
6175 /* Withdraw static BGP route from routing table. */
40381db7
DS
6176 if (pi) {
6177 bgp_path_info_delete(rn, pi);
c701010e
DS
6178 bgp_process(bgp, rn, afi, safi);
6179 }
6180 }
6181
6182 bgp_unlock_node(rn);
6183}
6184
b5d58c32 6185/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
6186void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
6187 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 6188{
6189 struct bgp_table *table;
6190 struct bgp_node *top;
6191 struct bgp_node *rn;
d7c0a89a 6192 uint8_t origin;
d62a17ae 6193 struct aspath *aspath = NULL;
d62a17ae 6194 struct community *community = NULL;
3da2cc32 6195 struct ecommunity *ecommunity = NULL;
dd18c5a9 6196 struct lcommunity *lcommunity = NULL;
40381db7 6197 struct bgp_path_info *pi;
d62a17ae 6198 unsigned long match = 0;
d7c0a89a 6199 uint8_t atomic_aggregate = 0;
d62a17ae 6200
9f822fa2
S
6201 /* If the bgp instance is being deleted or self peer is deleted
6202 * then do not create aggregate route
6203 */
892fedb6
DA
6204 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6205 || (bgp->peer_self == NULL))
9f822fa2
S
6206 return;
6207
d62a17ae 6208 /* ORIGIN attribute: If at least one route among routes that are
6209 aggregated has ORIGIN with the value INCOMPLETE, then the
6210 aggregated route must have the ORIGIN attribute with the value
6211 INCOMPLETE. Otherwise, if at least one route among routes that
6212 are aggregated has ORIGIN with the value EGP, then the aggregated
6213 route must have the origin attribute with the value EGP. In all
6214 other case the value of the ORIGIN attribute of the aggregated
6215 route is INTERNAL. */
6216 origin = BGP_ORIGIN_IGP;
718e3744 6217
d62a17ae 6218 table = bgp->rib[afi][safi];
718e3744 6219
d62a17ae 6220 top = bgp_node_get(table, p);
6221 for (rn = bgp_node_get(table, p); rn;
c2ff8b3e 6222 rn = bgp_route_next_until(rn, top)) {
b54892e0
DS
6223 const struct prefix *rn_p = bgp_node_get_prefix(rn);
6224
6225 if (rn_p->prefixlen <= p->prefixlen)
c2ff8b3e 6226 continue;
d62a17ae 6227
c2ff8b3e 6228 match = 0;
d62a17ae 6229
6f94b685 6230 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 6231 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 6232 continue;
718e3744 6233
40381db7 6234 if (pi->attr->flag
c2ff8b3e
DS
6235 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
6236 atomic_aggregate = 1;
d62a17ae 6237
40381db7 6238 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 6239 continue;
d62a17ae 6240
f273fef1
DS
6241 /*
6242 * summary-only aggregate route suppress
6243 * aggregated route announcements.
6244 */
c2ff8b3e 6245 if (aggregate->summary_only) {
40381db7
DS
6246 (bgp_path_info_extra_get(pi))->suppress++;
6247 bgp_path_info_set_flag(rn, pi,
18ee8310 6248 BGP_PATH_ATTR_CHANGED);
c2ff8b3e 6249 match++;
d62a17ae 6250 }
c2ff8b3e
DS
6251
6252 aggregate->count++;
6253
f273fef1
DS
6254 /*
6255 * If at least one route among routes that are
6256 * aggregated has ORIGIN with the value INCOMPLETE,
6257 * then the aggregated route MUST have the ORIGIN
6258 * attribute with the value INCOMPLETE. Otherwise, if
6259 * at least one route among routes that are aggregated
6260 * has ORIGIN with the value EGP, then the aggregated
6261 * route MUST have the ORIGIN attribute with the value
6262 * EGP.
6263 */
fc968841
NT
6264 switch (pi->attr->origin) {
6265 case BGP_ORIGIN_INCOMPLETE:
6266 aggregate->incomplete_origin_count++;
6267 break;
6268 case BGP_ORIGIN_EGP:
6269 aggregate->egp_origin_count++;
6270 break;
6271 default:
6272 /*Do nothing.
6273 */
6274 break;
6275 }
c2ff8b3e
DS
6276
6277 if (!aggregate->as_set)
6278 continue;
6279
f273fef1
DS
6280 /*
6281 * as-set aggregate route generate origin, as path,
6282 * and community aggregation.
6283 */
fc968841
NT
6284 /* Compute aggregate route's as-path.
6285 */
ef51a7d8 6286 bgp_compute_aggregate_aspath_hash(aggregate,
6287 pi->attr->aspath);
c2ff8b3e 6288
fc968841
NT
6289 /* Compute aggregate route's community.
6290 */
6291 if (pi->attr->community)
21fec674 6292 bgp_compute_aggregate_community_hash(
fc968841
NT
6293 aggregate,
6294 pi->attr->community);
dd18c5a9 6295
fc968841
NT
6296 /* Compute aggregate route's extended community.
6297 */
6298 if (pi->attr->ecommunity)
4edd83f9 6299 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
6300 aggregate,
6301 pi->attr->ecommunity);
6302
6303 /* Compute aggregate route's large community.
6304 */
6305 if (pi->attr->lcommunity)
f1eb1f05 6306 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
6307 aggregate,
6308 pi->attr->lcommunity);
d62a17ae 6309 }
c2ff8b3e
DS
6310 if (match)
6311 bgp_process(bgp, rn, afi, safi);
6312 }
21fec674 6313 if (aggregate->as_set) {
ef51a7d8 6314 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 6315 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 6316 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 6317 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 6318 }
6319
f1eb1f05 6320
d62a17ae 6321 bgp_unlock_node(top);
718e3744 6322
718e3744 6323
fc968841
NT
6324 if (aggregate->incomplete_origin_count > 0)
6325 origin = BGP_ORIGIN_INCOMPLETE;
6326 else if (aggregate->egp_origin_count > 0)
6327 origin = BGP_ORIGIN_EGP;
d62a17ae 6328
229757f1
DA
6329 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6330 origin = aggregate->origin;
6331
fc968841
NT
6332 if (aggregate->as_set) {
6333 if (aggregate->aspath)
6334 /* Retrieve aggregate route's as-path.
6335 */
6336 aspath = aspath_dup(aggregate->aspath);
d62a17ae 6337
fc968841
NT
6338 if (aggregate->community)
6339 /* Retrieve aggregate route's community.
6340 */
6341 community = community_dup(aggregate->community);
3da2cc32 6342
fc968841
NT
6343 if (aggregate->ecommunity)
6344 /* Retrieve aggregate route's ecommunity.
6345 */
6346 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 6347
fc968841
NT
6348 if (aggregate->lcommunity)
6349 /* Retrieve aggregate route's lcommunity.
6350 */
6351 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 6352 }
718e3744 6353
c701010e 6354 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
6355 ecommunity, lcommunity, atomic_aggregate,
6356 aggregate);
718e3744 6357}
6358
5f040085
DS
6359void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
6360 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
6361{
6362 struct bgp_table *table;
6363 struct bgp_node *top;
6364 struct bgp_node *rn;
40381db7 6365 struct bgp_path_info *pi;
3b7db173
DS
6366 unsigned long match;
6367
6368 table = bgp->rib[afi][safi];
6369
6370 /* If routes exists below this node, generate aggregate routes. */
6371 top = bgp_node_get(table, p);
6372 for (rn = bgp_node_get(table, p); rn;
6373 rn = bgp_route_next_until(rn, top)) {
b54892e0
DS
6374 const struct prefix *rn_p = bgp_node_get_prefix(rn);
6375
6376 if (rn_p->prefixlen <= p->prefixlen)
3b7db173
DS
6377 continue;
6378 match = 0;
6379
6f94b685 6380 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 6381 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
6382 continue;
6383
40381db7 6384 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
6385 continue;
6386
40381db7
DS
6387 if (aggregate->summary_only && pi->extra) {
6388 pi->extra->suppress--;
3b7db173 6389
40381db7 6390 if (pi->extra->suppress == 0) {
18ee8310 6391 bgp_path_info_set_flag(
40381db7 6392 rn, pi, BGP_PATH_ATTR_CHANGED);
3b7db173
DS
6393 match++;
6394 }
6395 }
6396 aggregate->count--;
fc968841
NT
6397
6398 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6399 aggregate->incomplete_origin_count--;
6400 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6401 aggregate->egp_origin_count--;
6402
6403 if (aggregate->as_set) {
6404 /* Remove as-path from aggregate.
6405 */
ef51a7d8 6406 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
6407 aggregate,
6408 pi->attr->aspath);
6409
6410 if (pi->attr->community)
6411 /* Remove community from aggregate.
6412 */
21fec674 6413 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
6414 aggregate,
6415 pi->attr->community);
6416
6417 if (pi->attr->ecommunity)
6418 /* Remove ecommunity from aggregate.
6419 */
4edd83f9 6420 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
6421 aggregate,
6422 pi->attr->ecommunity);
6423
6424 if (pi->attr->lcommunity)
6425 /* Remove lcommunity from aggregate.
6426 */
f1eb1f05 6427 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
6428 aggregate,
6429 pi->attr->lcommunity);
6430 }
6431
3b7db173
DS
6432 }
6433
6434 /* If this node was suppressed, process the change. */
6435 if (match)
6436 bgp_process(bgp, rn, afi, safi);
6437 }
f1eb1f05 6438 if (aggregate->as_set) {
ef51a7d8 6439 aspath_free(aggregate->aspath);
6440 aggregate->aspath = NULL;
21fec674 6441 if (aggregate->community)
6442 community_free(&aggregate->community);
4edd83f9 6443 if (aggregate->ecommunity)
6444 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 6445 if (aggregate->lcommunity)
6446 lcommunity_free(&aggregate->lcommunity);
6447 }
6448
3b7db173
DS
6449 bgp_unlock_node(top);
6450}
718e3744 6451
5f040085
DS
6452static void bgp_add_route_to_aggregate(struct bgp *bgp,
6453 const struct prefix *aggr_p,
fc968841
NT
6454 struct bgp_path_info *pinew, afi_t afi,
6455 safi_t safi,
6456 struct bgp_aggregate *aggregate)
6457{
6458 uint8_t origin;
6459 struct aspath *aspath = NULL;
6460 uint8_t atomic_aggregate = 0;
6461 struct community *community = NULL;
6462 struct ecommunity *ecommunity = NULL;
6463 struct lcommunity *lcommunity = NULL;
6464
6465 /* ORIGIN attribute: If at least one route among routes that are
6466 * aggregated has ORIGIN with the value INCOMPLETE, then the
6467 * aggregated route must have the ORIGIN attribute with the value
6468 * INCOMPLETE. Otherwise, if at least one route among routes that
6469 * are aggregated has ORIGIN with the value EGP, then the aggregated
6470 * route must have the origin attribute with the value EGP. In all
6471 * other case the value of the ORIGIN attribute of the aggregated
6472 * route is INTERNAL.
6473 */
6474 origin = BGP_ORIGIN_IGP;
6475
6476 aggregate->count++;
6477
6478 if (aggregate->summary_only)
6479 (bgp_path_info_extra_get(pinew))->suppress++;
6480
6481 switch (pinew->attr->origin) {
6482 case BGP_ORIGIN_INCOMPLETE:
6483 aggregate->incomplete_origin_count++;
6484 break;
6485 case BGP_ORIGIN_EGP:
6486 aggregate->egp_origin_count++;
6487 break;
6488 default:
6489 /* Do nothing.
6490 */
6491 break;
6492 }
6493
6494 if (aggregate->incomplete_origin_count > 0)
6495 origin = BGP_ORIGIN_INCOMPLETE;
6496 else if (aggregate->egp_origin_count > 0)
6497 origin = BGP_ORIGIN_EGP;
6498
229757f1
DA
6499 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6500 origin = aggregate->origin;
6501
fc968841
NT
6502 if (aggregate->as_set) {
6503 /* Compute aggregate route's as-path.
6504 */
6505 bgp_compute_aggregate_aspath(aggregate,
6506 pinew->attr->aspath);
6507
6508 /* Compute aggregate route's community.
6509 */
6510 if (pinew->attr->community)
6511 bgp_compute_aggregate_community(
6512 aggregate,
6513 pinew->attr->community);
6514
6515 /* Compute aggregate route's extended community.
6516 */
6517 if (pinew->attr->ecommunity)
6518 bgp_compute_aggregate_ecommunity(
6519 aggregate,
6520 pinew->attr->ecommunity);
6521
6522 /* Compute aggregate route's large community.
6523 */
6524 if (pinew->attr->lcommunity)
6525 bgp_compute_aggregate_lcommunity(
6526 aggregate,
6527 pinew->attr->lcommunity);
6528
6529 /* Retrieve aggregate route's as-path.
6530 */
6531 if (aggregate->aspath)
6532 aspath = aspath_dup(aggregate->aspath);
6533
6534 /* Retrieve aggregate route's community.
6535 */
6536 if (aggregate->community)
6537 community = community_dup(aggregate->community);
6538
6539 /* Retrieve aggregate route's ecommunity.
6540 */
6541 if (aggregate->ecommunity)
6542 ecommunity = ecommunity_dup(aggregate->ecommunity);
6543
6544 /* Retrieve aggregate route's lcommunity.
6545 */
6546 if (aggregate->lcommunity)
6547 lcommunity = lcommunity_dup(aggregate->lcommunity);
6548 }
6549
6550 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6551 aspath, community, ecommunity,
6552 lcommunity, atomic_aggregate, aggregate);
6553}
6554
6555static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
6556 safi_t safi,
6557 struct bgp_path_info *pi,
6558 struct bgp_aggregate *aggregate,
5f040085 6559 const struct prefix *aggr_p)
fc968841
NT
6560{
6561 uint8_t origin;
6562 struct aspath *aspath = NULL;
6563 uint8_t atomic_aggregate = 0;
6564 struct community *community = NULL;
6565 struct ecommunity *ecommunity = NULL;
6566 struct lcommunity *lcommunity = NULL;
6567 unsigned long match = 0;
6568
6569 if (BGP_PATH_HOLDDOWN(pi))
6570 return;
6571
6572 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6573 return;
6574
6575 if (aggregate->summary_only
6576 && pi->extra
6577 && pi->extra->suppress > 0) {
6578 pi->extra->suppress--;
6579
6580 if (pi->extra->suppress == 0) {
6581 bgp_path_info_set_flag(pi->net, pi,
6582 BGP_PATH_ATTR_CHANGED);
6583 match++;
6584 }
6585 }
6586
6587 if (aggregate->count > 0)
6588 aggregate->count--;
6589
6590 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6591 aggregate->incomplete_origin_count--;
6592 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6593 aggregate->egp_origin_count--;
6594
6595 if (aggregate->as_set) {
6596 /* Remove as-path from aggregate.
6597 */
6598 bgp_remove_aspath_from_aggregate(aggregate,
6599 pi->attr->aspath);
6600
6601 if (pi->attr->community)
6602 /* Remove community from aggregate.
6603 */
6604 bgp_remove_community_from_aggregate(
6605 aggregate,
6606 pi->attr->community);
6607
6608 if (pi->attr->ecommunity)
6609 /* Remove ecommunity from aggregate.
6610 */
6611 bgp_remove_ecommunity_from_aggregate(
6612 aggregate,
6613 pi->attr->ecommunity);
6614
6615 if (pi->attr->lcommunity)
6616 /* Remove lcommunity from aggregate.
6617 */
6618 bgp_remove_lcommunity_from_aggregate(
6619 aggregate,
6620 pi->attr->lcommunity);
6621 }
6622
6623 /* If this node was suppressed, process the change. */
6624 if (match)
6625 bgp_process(bgp, pi->net, afi, safi);
6626
6627 origin = BGP_ORIGIN_IGP;
6628 if (aggregate->incomplete_origin_count > 0)
6629 origin = BGP_ORIGIN_INCOMPLETE;
6630 else if (aggregate->egp_origin_count > 0)
6631 origin = BGP_ORIGIN_EGP;
6632
229757f1
DA
6633 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6634 origin = aggregate->origin;
6635
fc968841
NT
6636 if (aggregate->as_set) {
6637 /* Retrieve aggregate route's as-path.
6638 */
6639 if (aggregate->aspath)
6640 aspath = aspath_dup(aggregate->aspath);
6641
6642 /* Retrieve aggregate route's community.
6643 */
6644 if (aggregate->community)
6645 community = community_dup(aggregate->community);
6646
6647 /* Retrieve aggregate route's ecommunity.
6648 */
6649 if (aggregate->ecommunity)
6650 ecommunity = ecommunity_dup(aggregate->ecommunity);
6651
6652 /* Retrieve aggregate route's lcommunity.
6653 */
6654 if (aggregate->lcommunity)
6655 lcommunity = lcommunity_dup(aggregate->lcommunity);
6656 }
6657
6658 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6659 aspath, community, ecommunity,
6660 lcommunity, atomic_aggregate, aggregate);
6661}
6662
5a1ae2c2 6663void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 6664 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 6665{
d62a17ae 6666 struct bgp_node *child;
6667 struct bgp_node *rn;
6668 struct bgp_aggregate *aggregate;
6669 struct bgp_table *table;
718e3744 6670
d62a17ae 6671 table = bgp->aggregate[afi][safi];
f018db83 6672
d62a17ae 6673 /* No aggregates configured. */
6674 if (bgp_table_top_nolock(table) == NULL)
6675 return;
f018db83 6676
d62a17ae 6677 if (p->prefixlen == 0)
6678 return;
718e3744 6679
40381db7 6680 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 6681 return;
718e3744 6682
d62a17ae 6683 child = bgp_node_get(table, p);
718e3744 6684
d62a17ae 6685 /* Aggregate address configuration check. */
b1e62edd 6686 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
b54892e0
DS
6687 const struct prefix *rn_p = bgp_node_get_prefix(rn);
6688
b613a918 6689 aggregate = bgp_node_get_bgp_aggregate_info(rn);
b54892e0
DS
6690 if (aggregate != NULL && rn_p->prefixlen < p->prefixlen) {
6691 bgp_add_route_to_aggregate(bgp, rn_p, pi, afi, safi,
6692 aggregate);
d62a17ae 6693 }
b1e62edd 6694 }
d62a17ae 6695 bgp_unlock_node(child);
718e3744 6696}
6697
5a1ae2c2 6698void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 6699 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 6700{
d62a17ae 6701 struct bgp_node *child;
6702 struct bgp_node *rn;
6703 struct bgp_aggregate *aggregate;
6704 struct bgp_table *table;
718e3744 6705
d62a17ae 6706 table = bgp->aggregate[afi][safi];
718e3744 6707
d62a17ae 6708 /* No aggregates configured. */
6709 if (bgp_table_top_nolock(table) == NULL)
6710 return;
718e3744 6711
d62a17ae 6712 if (p->prefixlen == 0)
6713 return;
718e3744 6714
d62a17ae 6715 child = bgp_node_get(table, p);
718e3744 6716
d62a17ae 6717 /* Aggregate address configuration check. */
b1e62edd 6718 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
b54892e0
DS
6719 const struct prefix *rn_p = bgp_node_get_prefix(rn);
6720
b613a918 6721 aggregate = bgp_node_get_bgp_aggregate_info(rn);
b54892e0
DS
6722 if (aggregate != NULL && rn_p->prefixlen < p->prefixlen) {
6723 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
6724 aggregate, rn_p);
d62a17ae 6725 }
b1e62edd 6726 }
d62a17ae 6727 bgp_unlock_node(child);
6728}
718e3744 6729
718e3744 6730/* Aggregate route attribute. */
6731#define AGGREGATE_SUMMARY_ONLY 1
6732#define AGGREGATE_AS_SET 1
fb29348a 6733#define AGGREGATE_AS_UNSET 0
718e3744 6734
229757f1
DA
6735static const char *bgp_origin2str(uint8_t origin)
6736{
6737 switch (origin) {
6738 case BGP_ORIGIN_IGP:
6739 return "igp";
6740 case BGP_ORIGIN_EGP:
6741 return "egp";
6742 case BGP_ORIGIN_INCOMPLETE:
6743 return "incomplete";
6744 }
6745 return "n/a";
6746}
6747
d62a17ae 6748static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
6749 afi_t afi, safi_t safi)
718e3744 6750{
d62a17ae 6751 VTY_DECLVAR_CONTEXT(bgp, bgp);
6752 int ret;
6753 struct prefix p;
6754 struct bgp_node *rn;
6755 struct bgp_aggregate *aggregate;
718e3744 6756
d62a17ae 6757 /* Convert string to prefix structure. */
6758 ret = str2prefix(prefix_str, &p);
6759 if (!ret) {
6760 vty_out(vty, "Malformed prefix\n");
6761 return CMD_WARNING_CONFIG_FAILED;
6762 }
6763 apply_mask(&p);
6764
6765 /* Old configuration check. */
6766 rn = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
6767 if (!rn) {
6768 vty_out(vty,
6769 "%% There is no aggregate-address configuration.\n");
6770 return CMD_WARNING_CONFIG_FAILED;
6771 }
f6269b4f 6772
b613a918 6773 aggregate = bgp_node_get_bgp_aggregate_info(rn);
09990cdd 6774 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
dd18c5a9
DS
6775 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
6776 NULL, NULL, 0, aggregate);
d62a17ae 6777
6778 /* Unlock aggregate address configuration. */
b613a918 6779 bgp_node_set_bgp_aggregate_info(rn, NULL);
fc968841
NT
6780
6781 if (aggregate->community)
6782 community_free(&aggregate->community);
6783
6784 if (aggregate->community_hash) {
6785 /* Delete all communities in the hash.
6786 */
6787 hash_clean(aggregate->community_hash,
6788 bgp_aggr_community_remove);
6789 /* Free up the community_hash.
6790 */
6791 hash_free(aggregate->community_hash);
6792 }
6793
6794 if (aggregate->ecommunity)
6795 ecommunity_free(&aggregate->ecommunity);
6796
6797 if (aggregate->ecommunity_hash) {
6798 /* Delete all ecommunities in the hash.
6799 */
6800 hash_clean(aggregate->ecommunity_hash,
6801 bgp_aggr_ecommunity_remove);
6802 /* Free up the ecommunity_hash.
6803 */
6804 hash_free(aggregate->ecommunity_hash);
6805 }
6806
6807 if (aggregate->lcommunity)
6808 lcommunity_free(&aggregate->lcommunity);
6809
6810 if (aggregate->lcommunity_hash) {
6811 /* Delete all lcommunities in the hash.
6812 */
6813 hash_clean(aggregate->lcommunity_hash,
6814 bgp_aggr_lcommunity_remove);
6815 /* Free up the lcommunity_hash.
6816 */
6817 hash_free(aggregate->lcommunity_hash);
6818 }
6819
6820 if (aggregate->aspath)
6821 aspath_free(aggregate->aspath);
6822
6823 if (aggregate->aspath_hash) {
6824 /* Delete all as-paths in the hash.
6825 */
6826 hash_clean(aggregate->aspath_hash,
6827 bgp_aggr_aspath_remove);
6828 /* Free up the aspath_hash.
6829 */
6830 hash_free(aggregate->aspath_hash);
6831 }
6832
d62a17ae 6833 bgp_aggregate_free(aggregate);
6834 bgp_unlock_node(rn);
6835 bgp_unlock_node(rn);
6836
6837 return CMD_SUCCESS;
6838}
6839
6840static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
229757f1
DA
6841 safi_t safi, const char *rmap,
6842 uint8_t summary_only, uint8_t as_set,
6843 uint8_t origin)
d62a17ae 6844{
6845 VTY_DECLVAR_CONTEXT(bgp, bgp);
6846 int ret;
6847 struct prefix p;
6848 struct bgp_node *rn;
6849 struct bgp_aggregate *aggregate;
fb29348a 6850 uint8_t as_set_new = as_set;
d62a17ae 6851
6852 /* Convert string to prefix structure. */
6853 ret = str2prefix(prefix_str, &p);
6854 if (!ret) {
6855 vty_out(vty, "Malformed prefix\n");
6856 return CMD_WARNING_CONFIG_FAILED;
6857 }
6858 apply_mask(&p);
6859
3624ac81
DS
6860 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
6861 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
6862 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6863 prefix_str);
6864 return CMD_WARNING_CONFIG_FAILED;
6865 }
6866
d62a17ae 6867 /* Old configuration check. */
6868 rn = bgp_node_get(bgp->aggregate[afi][safi], &p);
20894f50 6869 aggregate = bgp_node_get_bgp_aggregate_info(rn);
d62a17ae 6870
20894f50 6871 if (aggregate) {
d62a17ae 6872 vty_out(vty, "There is already same aggregate network.\n");
6873 /* try to remove the old entry */
6874 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
6875 if (ret) {
6876 vty_out(vty, "Error deleting aggregate.\n");
6877 bgp_unlock_node(rn);
6878 return CMD_WARNING_CONFIG_FAILED;
6879 }
6880 }
718e3744 6881
d62a17ae 6882 /* Make aggregate address structure. */
6883 aggregate = bgp_aggregate_new();
6884 aggregate->summary_only = summary_only;
fb29348a
DA
6885
6886 /* Network operators MUST NOT locally generate any new
6887 * announcements containing AS_SET or AS_CONFED_SET. If they have
6888 * announced routes with AS_SET or AS_CONFED_SET in them, then they
6889 * SHOULD withdraw those routes and re-announce routes for the
6890 * aggregate or component prefixes (i.e., the more-specific routes
6891 * subsumed by the previously aggregated route) without AS_SET
6892 * or AS_CONFED_SET in the updates.
6893 */
6894 if (bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED) {
6895 if (as_set == AGGREGATE_AS_SET) {
6896 as_set_new = AGGREGATE_AS_UNSET;
6897 zlog_warn(
63efca0e 6898 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a
DA
6899 __func__);
6900 vty_out(vty,
6901 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
6902 }
6903 }
6904
6905 aggregate->as_set = as_set_new;
d62a17ae 6906 aggregate->safi = safi;
229757f1
DA
6907 /* Override ORIGIN attribute if defined.
6908 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
6909 * to IGP which is not what rfc4271 says.
6910 * This enables the same behavior, optionally.
6911 */
6912 aggregate->origin = origin;
20894f50
DA
6913
6914 if (rmap) {
6915 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6916 route_map_counter_decrement(aggregate->rmap.map);
6917 aggregate->rmap.name =
6918 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6919 aggregate->rmap.map = route_map_lookup_by_name(rmap);
6920 route_map_counter_increment(aggregate->rmap.map);
6921 }
b613a918 6922 bgp_node_set_bgp_aggregate_info(rn, aggregate);
718e3744 6923
d62a17ae 6924 /* Aggregate address insert into BGP routing table. */
fc968841 6925 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 6926
d62a17ae 6927 return CMD_SUCCESS;
718e3744 6928}
6929
6930DEFUN (aggregate_address,
6931 aggregate_address_cmd,
229757f1 6932 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 6933 "Configure BGP aggregate entries\n"
6934 "Aggregate prefix\n"
6935 "Generate AS set path information\n"
a636c635
DW
6936 "Filter more specific routes from updates\n"
6937 "Filter more specific routes from updates\n"
20894f50
DA
6938 "Generate AS set path information\n"
6939 "Apply route map to aggregate network\n"
229757f1
DA
6940 "Name of route map\n"
6941 "BGP origin code\n"
6942 "Remote EGP\n"
6943 "Local IGP\n"
6944 "Unknown heritage\n")
718e3744 6945{
d62a17ae 6946 int idx = 0;
6947 argv_find(argv, argc, "A.B.C.D/M", &idx);
6948 char *prefix = argv[idx]->arg;
20894f50 6949 char *rmap = NULL;
229757f1 6950 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
fb29348a
DA
6951 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
6952 : AGGREGATE_AS_UNSET;
d62a17ae 6953 idx = 0;
6954 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6955 ? AGGREGATE_SUMMARY_ONLY
6956 : 0;
e3e6107d 6957
20894f50
DA
6958 idx = 0;
6959 argv_find(argv, argc, "WORD", &idx);
6960 if (idx)
6961 rmap = argv[idx]->arg;
6962
229757f1
DA
6963 idx = 0;
6964 if (argv_find(argv, argc, "origin", &idx)) {
6965 if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
6966 origin = BGP_ORIGIN_IGP;
6967 if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
6968 origin = BGP_ORIGIN_EGP;
6969 if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
6970 origin = BGP_ORIGIN_INCOMPLETE;
6971 }
6972
6973 return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty), rmap,
6974 summary_only, as_set, origin);
718e3744 6975}
6976
e3e6107d
QY
6977DEFUN (aggregate_address_mask,
6978 aggregate_address_mask_cmd,
229757f1 6979 "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 6980 "Configure BGP aggregate entries\n"
6981 "Aggregate address\n"
6982 "Aggregate mask\n"
6983 "Generate AS set path information\n"
a636c635
DW
6984 "Filter more specific routes from updates\n"
6985 "Filter more specific routes from updates\n"
20894f50
DA
6986 "Generate AS set path information\n"
6987 "Apply route map to aggregate network\n"
229757f1
DA
6988 "Name of route map\n"
6989 "BGP origin code\n"
6990 "Remote EGP\n"
6991 "Local IGP\n"
6992 "Unknown heritage\n")
718e3744 6993{
d62a17ae 6994 int idx = 0;
6995 argv_find(argv, argc, "A.B.C.D", &idx);
6996 char *prefix = argv[idx]->arg;
6997 char *mask = argv[idx + 1]->arg;
cf40d052 6998 bool rmap_found;
20894f50 6999 char *rmap = NULL;
229757f1 7000 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
fb29348a
DA
7001 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
7002 : AGGREGATE_AS_UNSET;
d62a17ae 7003 idx = 0;
7004 int summary_only = argv_find(argv, argc, "summary-only", &idx)
7005 ? AGGREGATE_SUMMARY_ONLY
7006 : 0;
7007
cf40d052
DS
7008 rmap_found = argv_find(argv, argc, "WORD", &idx);
7009 if (rmap_found)
20894f50
DA
7010 rmap = argv[idx]->arg;
7011
d62a17ae 7012 char prefix_str[BUFSIZ];
7013 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
7014
7015 if (!ret) {
7016 vty_out(vty, "%% Inconsistent address and mask\n");
7017 return CMD_WARNING_CONFIG_FAILED;
7018 }
718e3744 7019
229757f1
DA
7020 idx = 0;
7021 if (argv_find(argv, argc, "origin", &idx)) {
7022 if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
7023 origin = BGP_ORIGIN_IGP;
7024 if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
7025 origin = BGP_ORIGIN_EGP;
7026 if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
7027 origin = BGP_ORIGIN_INCOMPLETE;
7028 }
7029
d62a17ae 7030 return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
229757f1 7031 rmap, summary_only, as_set, origin);
718e3744 7032}
7033
718e3744 7034DEFUN (no_aggregate_address,
7035 no_aggregate_address_cmd,
229757f1 7036 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 7037 NO_STR
7038 "Configure BGP aggregate entries\n"
a636c635
DW
7039 "Aggregate prefix\n"
7040 "Generate AS set path information\n"
e3e6107d
QY
7041 "Filter more specific routes from updates\n"
7042 "Filter more specific routes from updates\n"
b84da0db
DA
7043 "Generate AS set path information\n"
7044 "Apply route map to aggregate network\n"
229757f1
DA
7045 "Name of route map\n"
7046 "BGP origin code\n"
7047 "Remote EGP\n"
7048 "Local IGP\n"
7049 "Unknown heritage\n")
718e3744 7050{
d62a17ae 7051 int idx = 0;
7052 argv_find(argv, argc, "A.B.C.D/M", &idx);
7053 char *prefix = argv[idx]->arg;
7054 return bgp_aggregate_unset(vty, prefix, AFI_IP, bgp_node_safi(vty));
718e3744 7055}
7056
718e3744 7057DEFUN (no_aggregate_address_mask,
7058 no_aggregate_address_mask_cmd,
229757f1 7059 "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 7060 NO_STR
7061 "Configure BGP aggregate entries\n"
7062 "Aggregate address\n"
a636c635
DW
7063 "Aggregate mask\n"
7064 "Generate AS set path information\n"
e3e6107d
QY
7065 "Filter more specific routes from updates\n"
7066 "Filter more specific routes from updates\n"
b84da0db
DA
7067 "Generate AS set path information\n"
7068 "Apply route map to aggregate network\n"
229757f1
DA
7069 "Name of route map\n"
7070 "BGP origin code\n"
7071 "Remote EGP\n"
7072 "Local IGP\n"
7073 "Unknown heritage\n")
718e3744 7074{
d62a17ae 7075 int idx = 0;
7076 argv_find(argv, argc, "A.B.C.D", &idx);
7077 char *prefix = argv[idx]->arg;
7078 char *mask = argv[idx + 1]->arg;
718e3744 7079
d62a17ae 7080 char prefix_str[BUFSIZ];
7081 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
718e3744 7082
d62a17ae 7083 if (!ret) {
7084 vty_out(vty, "%% Inconsistent address and mask\n");
7085 return CMD_WARNING_CONFIG_FAILED;
7086 }
718e3744 7087
d62a17ae 7088 return bgp_aggregate_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
718e3744 7089}
7090
718e3744 7091DEFUN (ipv6_aggregate_address,
7092 ipv6_aggregate_address_cmd,
229757f1 7093 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 7094 "Configure BGP aggregate entries\n"
7095 "Aggregate prefix\n"
5101fece 7096 "Generate AS set path information\n"
7097 "Filter more specific routes from updates\n"
7098 "Filter more specific routes from updates\n"
20894f50
DA
7099 "Generate AS set path information\n"
7100 "Apply route map to aggregate network\n"
229757f1
DA
7101 "Name of route map\n"
7102 "BGP origin code\n"
7103 "Remote EGP\n"
7104 "Local IGP\n"
7105 "Unknown heritage\n")
718e3744 7106{
d62a17ae 7107 int idx = 0;
7108 argv_find(argv, argc, "X:X::X:X/M", &idx);
7109 char *prefix = argv[idx]->arg;
20894f50 7110 char *rmap = NULL;
273fae13 7111 bool rmap_found;
229757f1 7112 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
fb29348a
DA
7113 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
7114 : AGGREGATE_AS_UNSET;
5101fece 7115
7116 idx = 0;
d62a17ae 7117 int sum_only = argv_find(argv, argc, "summary-only", &idx)
7118 ? AGGREGATE_SUMMARY_ONLY
7119 : 0;
20894f50 7120
273fae13
DA
7121 rmap_found = argv_find(argv, argc, "WORD", &idx);
7122 if (rmap_found)
20894f50
DA
7123 rmap = argv[idx]->arg;
7124
229757f1
DA
7125 idx = 0;
7126 if (argv_find(argv, argc, "origin", &idx)) {
7127 if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
7128 origin = BGP_ORIGIN_IGP;
7129 if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
7130 origin = BGP_ORIGIN_EGP;
7131 if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
7132 origin = BGP_ORIGIN_INCOMPLETE;
7133 }
7134
20894f50 7135 return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, rmap,
229757f1 7136 sum_only, as_set, origin);
718e3744 7137}
7138
7139DEFUN (no_ipv6_aggregate_address,
7140 no_ipv6_aggregate_address_cmd,
229757f1 7141 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 7142 NO_STR
7143 "Configure BGP aggregate entries\n"
16cedbb0 7144 "Aggregate prefix\n"
5101fece 7145 "Generate AS set path information\n"
7146 "Filter more specific routes from updates\n"
7147 "Filter more specific routes from updates\n"
b84da0db
DA
7148 "Generate AS set path information\n"
7149 "Apply route map to aggregate network\n"
229757f1
DA
7150 "Name of route map\n"
7151 "BGP origin code\n"
7152 "Remote EGP\n"
7153 "Local IGP\n"
7154 "Unknown heritage\n")
718e3744 7155{
d62a17ae 7156 int idx = 0;
7157 argv_find(argv, argc, "X:X::X:X/M", &idx);
7158 char *prefix = argv[idx]->arg;
7159 return bgp_aggregate_unset(vty, prefix, AFI_IP6, SAFI_UNICAST);
718e3744 7160}
7161
718e3744 7162/* Redistribute route treatment. */
d62a17ae 7163void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
7164 const union g_addr *nexthop, ifindex_t ifindex,
7165 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
7166 uint8_t type, unsigned short instance,
7167 route_tag_t tag)
d62a17ae 7168{
4b7e6066 7169 struct bgp_path_info *new;
40381db7
DS
7170 struct bgp_path_info *bpi;
7171 struct bgp_path_info rmap_path;
d62a17ae 7172 struct bgp_node *bn;
7173 struct attr attr;
7174 struct attr *new_attr;
7175 afi_t afi;
b68885f9 7176 route_map_result_t ret;
d62a17ae 7177 struct bgp_redist *red;
7178
7179 /* Make default attribute. */
7180 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
7181 /*
7182 * This must not be NULL to satisfy Coverity SA
7183 */
7184 assert(attr.aspath);
9de1f7ff 7185
a4d82a8a 7186 switch (nhtype) {
9de1f7ff
DS
7187 case NEXTHOP_TYPE_IFINDEX:
7188 break;
7189 case NEXTHOP_TYPE_IPV4:
7190 case NEXTHOP_TYPE_IPV4_IFINDEX:
7191 attr.nexthop = nexthop->ipv4;
7192 break;
7193 case NEXTHOP_TYPE_IPV6:
7194 case NEXTHOP_TYPE_IPV6_IFINDEX:
7195 attr.mp_nexthop_global = nexthop->ipv6;
7196 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
7197 break;
7198 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
7199 switch (p->family) {
7200 case AF_INET:
9de1f7ff 7201 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
7202 break;
7203 case AF_INET6:
9de1f7ff
DS
7204 memset(&attr.mp_nexthop_global, 0,
7205 sizeof(attr.mp_nexthop_global));
74489921 7206 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 7207 break;
74489921 7208 }
9de1f7ff 7209 break;
d62a17ae 7210 }
74489921 7211 attr.nh_ifindex = ifindex;
f04a80a5 7212
d62a17ae 7213 attr.med = metric;
7214 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
7215 attr.tag = tag;
718e3744 7216
d62a17ae 7217 afi = family2afi(p->family);
6aeb9e78 7218
d62a17ae 7219 red = bgp_redist_lookup(bgp, afi, type, instance);
7220 if (red) {
7221 struct attr attr_new;
718e3744 7222
d62a17ae 7223 /* Copy attribute for modification. */
6f4f49b2 7224 attr_new = attr;
718e3744 7225
d62a17ae 7226 if (red->redist_metric_flag)
7227 attr_new.med = red->redist_metric;
718e3744 7228
d62a17ae 7229 /* Apply route-map. */
7230 if (red->rmap.name) {
40381db7
DS
7231 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
7232 rmap_path.peer = bgp->peer_self;
7233 rmap_path.attr = &attr_new;
718e3744 7234
d62a17ae 7235 SET_FLAG(bgp->peer_self->rmap_type,
7236 PEER_RMAP_TYPE_REDISTRIBUTE);
7237
7238 ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
40381db7 7239 &rmap_path);
d62a17ae 7240
7241 bgp->peer_self->rmap_type = 0;
7242
7243 if (ret == RMAP_DENYMATCH) {
7244 /* Free uninterned attribute. */
7245 bgp_attr_flush(&attr_new);
7246
7247 /* Unintern original. */
7248 aspath_unintern(&attr.aspath);
7249 bgp_redistribute_delete(bgp, p, type, instance);
7250 return;
7251 }
7252 }
7253
892fedb6 7254 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
7f323236
DW
7255 bgp_attr_add_gshut_community(&attr_new);
7256
d62a17ae 7257 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7258 SAFI_UNICAST, p, NULL);
7259
7260 new_attr = bgp_attr_intern(&attr_new);
7261
6f94b685
DS
7262 for (bpi = bgp_node_get_bgp_path_info(bn); bpi;
7263 bpi = bpi->next)
40381db7
DS
7264 if (bpi->peer == bgp->peer_self
7265 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 7266 break;
7267
40381db7 7268 if (bpi) {
d62a17ae 7269 /* Ensure the (source route) type is updated. */
40381db7
DS
7270 bpi->type = type;
7271 if (attrhash_cmp(bpi->attr, new_attr)
7272 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 7273 bgp_attr_unintern(&new_attr);
7274 aspath_unintern(&attr.aspath);
7275 bgp_unlock_node(bn);
7276 return;
7277 } else {
7278 /* The attribute is changed. */
40381db7 7279 bgp_path_info_set_flag(bn, bpi,
18ee8310 7280 BGP_PATH_ATTR_CHANGED);
d62a17ae 7281
7282 /* Rewrite BGP route information. */
40381db7
DS
7283 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
7284 bgp_path_info_restore(bn, bpi);
d62a17ae 7285 else
40381db7
DS
7286 bgp_aggregate_decrement(
7287 bgp, p, bpi, afi, SAFI_UNICAST);
7288 bgp_attr_unintern(&bpi->attr);
7289 bpi->attr = new_attr;
7290 bpi->uptime = bgp_clock();
d62a17ae 7291
7292 /* Process change. */
40381db7 7293 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 7294 SAFI_UNICAST);
7295 bgp_process(bgp, bn, afi, SAFI_UNICAST);
7296 bgp_unlock_node(bn);
7297 aspath_unintern(&attr.aspath);
ddb5b488
PZ
7298
7299 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7300 || (bgp->inst_type
7301 == BGP_INSTANCE_TYPE_DEFAULT)) {
7302
7303 vpn_leak_from_vrf_update(
40381db7 7304 bgp_get_default(), bgp, bpi);
ddb5b488 7305 }
d62a17ae 7306 return;
7307 }
7308 }
7309
7310 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
7311 bgp->peer_self, new_attr, bn);
1defdda8 7312 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 7313
7314 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 7315 bgp_path_info_add(bn, new);
d62a17ae 7316 bgp_unlock_node(bn);
7317 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
7318
7319 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7320 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7321
7322 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
7323 }
d62a17ae 7324 }
7325
7326 /* Unintern original. */
7327 aspath_unintern(&attr.aspath);
718e3744 7328}
7329
d7c0a89a
QY
7330void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
7331 unsigned short instance)
718e3744 7332{
d62a17ae 7333 afi_t afi;
7334 struct bgp_node *rn;
40381db7 7335 struct bgp_path_info *pi;
d62a17ae 7336 struct bgp_redist *red;
718e3744 7337
d62a17ae 7338 afi = family2afi(p->family);
718e3744 7339
d62a17ae 7340 red = bgp_redist_lookup(bgp, afi, type, instance);
7341 if (red) {
7342 rn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7343 SAFI_UNICAST, p, NULL);
7344
6f94b685 7345 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7 7346 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 7347 break;
7348
40381db7 7349 if (pi) {
ddb5b488
PZ
7350 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7351 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7352
7353 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7354 bgp, pi);
ddb5b488 7355 }
40381db7
DS
7356 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
7357 bgp_path_info_delete(rn, pi);
d62a17ae 7358 bgp_process(bgp, rn, afi, SAFI_UNICAST);
7359 }
7360 bgp_unlock_node(rn);
7361 }
7362}
7363
7364/* Withdraw specified route type's route. */
7365void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 7366 unsigned short instance)
d62a17ae 7367{
7368 struct bgp_node *rn;
40381db7 7369 struct bgp_path_info *pi;
d62a17ae 7370 struct bgp_table *table;
7371
7372 table = bgp->rib[afi][SAFI_UNICAST];
7373
7374 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685 7375 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
7376 if (pi->peer == bgp->peer_self && pi->type == type
7377 && pi->instance == instance)
d62a17ae 7378 break;
7379
40381db7 7380 if (pi) {
ddb5b488
PZ
7381 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7382 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7383
7384 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7385 bgp, pi);
ddb5b488 7386 }
b54892e0
DS
7387 bgp_aggregate_decrement(bgp, bgp_node_get_prefix(rn),
7388 pi, afi, SAFI_UNICAST);
40381db7 7389 bgp_path_info_delete(rn, pi);
d62a17ae 7390 bgp_process(bgp, rn, afi, SAFI_UNICAST);
7391 }
718e3744 7392 }
718e3744 7393}
6b0655a2 7394
718e3744 7395/* Static function to display route. */
bd494ec5 7396static void route_vty_out_route(const struct prefix *p, struct vty *vty,
9c92b5f7 7397 json_object *json)
718e3744 7398{
be054588 7399 int len = 0;
d62a17ae 7400 char buf[BUFSIZ];
50e05855 7401 char buf2[BUFSIZ];
718e3744 7402
d62a17ae 7403 if (p->family == AF_INET) {
c6462ff4 7404 if (!json) {
89e5e9f0
PM
7405 len = vty_out(
7406 vty, "%s/%d",
7407 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
7408 p->prefixlen);
c6462ff4
MK
7409 } else {
7410 json_object_string_add(json, "prefix",
7411 inet_ntop(p->family,
7412 &p->u.prefix, buf,
7413 BUFSIZ));
7414 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 7415 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 7416 json_object_string_add(json, "network", buf2);
c6462ff4 7417 }
d62a17ae 7418 } else if (p->family == AF_ETHERNET) {
b03b8898
DS
7419 prefix2str(p, buf, PREFIX_STRLEN);
7420 len = vty_out(vty, "%s", buf);
7421 } else if (p->family == AF_EVPN) {
57f7feb6 7422 if (!json)
60466a63
QY
7423 len = vty_out(
7424 vty, "%s",
7425 bgp_evpn_route2str((struct prefix_evpn *)p, buf,
7426 BUFSIZ));
57f7feb6 7427 else
60466a63 7428 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
7429 } else if (p->family == AF_FLOWSPEC) {
7430 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
7431 json ?
7432 NLRI_STRING_FORMAT_JSON_SIMPLE :
7433 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 7434 } else {
c6462ff4 7435 if (!json)
60466a63
QY
7436 len = vty_out(
7437 vty, "%s/%d",
7438 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
7439 p->prefixlen);
50e05855
AD
7440 else {
7441 json_object_string_add(json, "prefix",
7442 inet_ntop(p->family,
7443 &p->u.prefix, buf,
7444 BUFSIZ));
7445 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
7446 prefix2str(p, buf2, PREFIX_STRLEN);
7447 json_object_string_add(json, "network", buf2);
7448 }
9c92b5f7 7449 }
d62a17ae 7450
9c92b5f7
MK
7451 if (!json) {
7452 len = 17 - len;
7453 if (len < 1)
7454 vty_out(vty, "\n%*s", 20, " ");
7455 else
7456 vty_out(vty, "%*s", len, " ");
7457 }
718e3744 7458}
7459
d62a17ae 7460enum bgp_display_type {
7461 normal_list,
718e3744 7462};
7463
18ee8310 7464/* Print the short form route status for a bgp_path_info */
4b7e6066 7465static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 7466 struct bgp_path_info *path,
d62a17ae 7467 json_object *json_path)
718e3744 7468{
d62a17ae 7469 if (json_path) {
b05a1c8b 7470
d62a17ae 7471 /* Route status display. */
9b6d8fcf 7472 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7473 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 7474
9b6d8fcf 7475 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7476 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 7477
9b6d8fcf 7478 if (path->extra && path->extra->suppress)
d62a17ae 7479 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 7480
9b6d8fcf
DS
7481 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7482 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7483 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 7484
d62a17ae 7485 /* Selected */
9b6d8fcf 7486 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7487 json_object_boolean_true_add(json_path, "history");
b05a1c8b 7488
9b6d8fcf 7489 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7490 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 7491
9b6d8fcf 7492 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7493 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b 7494
9b6d8fcf 7495 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7496 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 7497
d62a17ae 7498 /* Internal route. */
9b6d8fcf
DS
7499 if ((path->peer->as)
7500 && (path->peer->as == path->peer->local_as))
d62a17ae 7501 json_object_string_add(json_path, "pathFrom",
7502 "internal");
7503 else
7504 json_object_string_add(json_path, "pathFrom",
7505 "external");
b05a1c8b 7506
d62a17ae 7507 return;
7508 }
b05a1c8b 7509
d62a17ae 7510 /* Route status display. */
9b6d8fcf 7511 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7512 vty_out(vty, "R");
9b6d8fcf 7513 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7514 vty_out(vty, "S");
9b6d8fcf 7515 else if (path->extra && path->extra->suppress)
d62a17ae 7516 vty_out(vty, "s");
9b6d8fcf
DS
7517 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7518 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7519 vty_out(vty, "*");
7520 else
7521 vty_out(vty, " ");
7522
7523 /* Selected */
9b6d8fcf 7524 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7525 vty_out(vty, "h");
9b6d8fcf 7526 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7527 vty_out(vty, "d");
9b6d8fcf 7528 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7529 vty_out(vty, ">");
9b6d8fcf 7530 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7531 vty_out(vty, "=");
7532 else
7533 vty_out(vty, " ");
718e3744 7534
d62a17ae 7535 /* Internal route. */
9b6d8fcf
DS
7536 if (path->peer && (path->peer->as)
7537 && (path->peer->as == path->peer->local_as))
d62a17ae 7538 vty_out(vty, "i");
7539 else
7540 vty_out(vty, " ");
b40d939b 7541}
7542
515c2602 7543static char *bgp_nexthop_hostname(struct peer *peer, struct attr *attr)
25b5da8d 7544{
892fedb6
DA
7545 if (peer->hostname
7546 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)
515c2602 7547 && !(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))
25b5da8d
DA
7548 return peer->hostname;
7549 return NULL;
7550}
7551
b40d939b 7552/* called from terminal list command */
bd494ec5 7553void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 7554 struct bgp_path_info *path, int display, safi_t safi,
4b7e6066 7555 json_object *json_paths)
d62a17ae 7556{
515c2602 7557 struct attr *attr = path->attr;
d62a17ae 7558 json_object *json_path = NULL;
7559 json_object *json_nexthops = NULL;
7560 json_object *json_nexthop_global = NULL;
7561 json_object *json_nexthop_ll = NULL;
6f214dd3 7562 json_object *json_ext_community = NULL;
9df8b37c 7563 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 7564 bool nexthop_self =
9b6d8fcf 7565 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 7566 bool nexthop_othervrf = false;
43089216 7567 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 7568 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
515c2602 7569 char *nexthop_hostname = bgp_nexthop_hostname(path->peer, attr);
d62a17ae 7570
7571 if (json_paths)
7572 json_path = json_object_new_object();
7573
7574 /* short status lead text */
9b6d8fcf 7575 route_vty_short_status_out(vty, path, json_path);
d62a17ae 7576
7577 if (!json_paths) {
7578 /* print prefix and mask */
7579 if (!display)
9c92b5f7 7580 route_vty_out_route(p, vty, json_path);
d62a17ae 7581 else
7582 vty_out(vty, "%*s", 17, " ");
9c92b5f7 7583 } else {
b682f6de 7584 route_vty_out_route(p, vty, json_path);
d62a17ae 7585 }
47fc97cc 7586
9df8b37c
PZ
7587 /*
7588 * If vrf id of nexthop is different from that of prefix,
7589 * set up printable string to append
7590 */
9b6d8fcf 7591 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
7592 const char *self = "";
7593
7594 if (nexthop_self)
7595 self = "<";
7596
7597 nexthop_othervrf = true;
9b6d8fcf 7598 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 7599
9b6d8fcf 7600 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
7601 snprintf(vrf_id_str, sizeof(vrf_id_str),
7602 "@%s%s", VRFID_NONE_STR, self);
7603 else
7604 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 7605 path->extra->bgp_orig->vrf_id, self);
9df8b37c 7606
9b6d8fcf
DS
7607 if (path->extra->bgp_orig->inst_type
7608 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 7609
9b6d8fcf 7610 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
7611 } else {
7612 const char *self = "";
7613
7614 if (nexthop_self)
7615 self = "<";
7616
7617 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
7618 }
7619
445c2480
DS
7620 /*
7621 * For ENCAP and EVPN routes, nexthop address family is not
7622 * neccessarily the same as the prefix address family.
7623 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7624 * EVPN routes are also exchanged with a MP nexthop. Currently,
7625 * this
7626 * is only IPv4, the value will be present in either
7627 * attr->nexthop or
7628 * attr->mp_nexthop_global_in
7629 */
7630 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
7631 char buf[BUFSIZ];
7632 char nexthop[128];
7633 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
7634
7635 switch (af) {
7636 case AF_INET:
7637 sprintf(nexthop, "%s",
a4d82a8a
PZ
7638 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
7639 BUFSIZ));
445c2480
DS
7640 break;
7641 case AF_INET6:
7642 sprintf(nexthop, "%s",
a4d82a8a
PZ
7643 inet_ntop(af, &attr->mp_nexthop_global, buf,
7644 BUFSIZ));
445c2480
DS
7645 break;
7646 default:
7647 sprintf(nexthop, "?");
7648 break;
d62a17ae 7649 }
d62a17ae 7650
445c2480
DS
7651 if (json_paths) {
7652 json_nexthop_global = json_object_new_object();
7653
515c2602
DA
7654 json_object_string_add(json_nexthop_global, "ip",
7655 nexthop);
7656
7657 if (nexthop_hostname)
7658 json_object_string_add(json_nexthop_global,
7659 "hostname",
7660 nexthop_hostname);
7661
7662 json_object_string_add(json_nexthop_global, "afi",
7663 (af == AF_INET) ? "ipv4"
7664 : "ipv6");
445c2480
DS
7665 json_object_boolean_true_add(json_nexthop_global,
7666 "used");
7667 } else
25b5da8d 7668 vty_out(vty, "%s%s",
515c2602 7669 nexthop_hostname ? nexthop_hostname : nexthop,
25b5da8d 7670 vrf_id_str);
445c2480
DS
7671 } else if (safi == SAFI_EVPN) {
7672 if (json_paths) {
7673 json_nexthop_global = json_object_new_object();
7674
515c2602
DA
7675 json_object_string_add(json_nexthop_global, "ip",
7676 inet_ntoa(attr->nexthop));
7677
7678 if (nexthop_hostname)
7679 json_object_string_add(json_nexthop_global,
7680 "hostname",
7681 nexthop_hostname);
7682
a4d82a8a
PZ
7683 json_object_string_add(json_nexthop_global, "afi",
7684 "ipv4");
445c2480
DS
7685 json_object_boolean_true_add(json_nexthop_global,
7686 "used");
7687 } else
25b5da8d 7688 vty_out(vty, "%-16s%s",
515c2602
DA
7689 nexthop_hostname ? nexthop_hostname
7690 : inet_ntoa(attr->nexthop),
9df8b37c 7691 vrf_id_str);
d33fc23b 7692 } else if (safi == SAFI_FLOWSPEC) {
975a328e 7693 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
7694 if (json_paths) {
7695 json_nexthop_global = json_object_new_object();
515c2602 7696
026b914a
PG
7697 json_object_string_add(json_nexthop_global,
7698 "afi", "ipv4");
515c2602
DA
7699 json_object_string_add(
7700 json_nexthop_global, "ip",
7701 inet_ntoa(attr->nexthop));
7702
7703 if (nexthop_hostname)
7704 json_object_string_add(
7705 json_nexthop_global, "hostname",
7706 nexthop_hostname);
7707
50e05855
AD
7708 json_object_boolean_true_add(
7709 json_nexthop_global,
026b914a
PG
7710 "used");
7711 } else {
25b5da8d 7712 vty_out(vty, "%-16s",
515c2602
DA
7713 nexthop_hostname
7714 ? nexthop_hostname
25b5da8d 7715 : inet_ntoa(attr->nexthop));
026b914a
PG
7716 }
7717 }
d33fc23b 7718 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
7719 if (json_paths) {
7720 json_nexthop_global = json_object_new_object();
d62a17ae 7721
515c2602
DA
7722 json_object_string_add(json_nexthop_global, "ip",
7723 inet_ntoa(attr->nexthop));
7724
7725 if (nexthop_hostname)
7726 json_object_string_add(json_nexthop_global,
7727 "hostname",
7728 nexthop_hostname);
445c2480 7729
a4d82a8a
PZ
7730 json_object_string_add(json_nexthop_global, "afi",
7731 "ipv4");
445c2480
DS
7732 json_object_boolean_true_add(json_nexthop_global,
7733 "used");
7734 } else {
9df8b37c
PZ
7735 char buf[BUFSIZ];
7736
d87ff2dd 7737 snprintf(buf, sizeof(buf), "%s%s",
515c2602
DA
7738 nexthop_hostname ? nexthop_hostname
7739 : inet_ntoa(attr->nexthop),
25b5da8d 7740 vrf_id_str);
9df8b37c 7741 vty_out(vty, "%-16s", buf);
d62a17ae 7742 }
445c2480 7743 }
b05a1c8b 7744
445c2480 7745 /* IPv6 Next Hop */
a4d82a8a 7746 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
7747 int len;
7748 char buf[BUFSIZ];
d62a17ae 7749
445c2480
DS
7750 if (json_paths) {
7751 json_nexthop_global = json_object_new_object();
a4d82a8a 7752 json_object_string_add(
515c2602
DA
7753 json_nexthop_global, "ip",
7754 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
7755 buf, BUFSIZ));
7756
7757 if (nexthop_hostname)
7758 json_object_string_add(json_nexthop_global,
7759 "hostname",
7760 nexthop_hostname);
7761
a4d82a8a
PZ
7762 json_object_string_add(json_nexthop_global, "afi",
7763 "ipv6");
7764 json_object_string_add(json_nexthop_global, "scope",
7765 "global");
445c2480
DS
7766
7767 /* We display both LL & GL if both have been
7768 * received */
0606039c
DA
7769 if ((attr->mp_nexthop_len
7770 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 7771 || (path->peer->conf_if)) {
a4d82a8a 7772 json_nexthop_ll = json_object_new_object();
d62a17ae 7773 json_object_string_add(
515c2602
DA
7774 json_nexthop_ll, "ip",
7775 inet_ntop(AF_INET6,
7776 &attr->mp_nexthop_local, buf,
7777 BUFSIZ));
7778
7779 if (nexthop_hostname)
7780 json_object_string_add(
7781 json_nexthop_ll, "hostname",
7782 nexthop_hostname);
7783
a4d82a8a
PZ
7784 json_object_string_add(json_nexthop_ll, "afi",
7785 "ipv6");
7786 json_object_string_add(json_nexthop_ll, "scope",
445c2480 7787 "link-local");
d62a17ae 7788
a4d82a8a
PZ
7789 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
7790 &attr->mp_nexthop_local)
445c2480
DS
7791 != 0)
7792 && !attr->mp_nexthop_prefer_global)
d62a17ae 7793 json_object_boolean_true_add(
a4d82a8a 7794 json_nexthop_ll, "used");
445c2480
DS
7795 else
7796 json_object_boolean_true_add(
a4d82a8a 7797 json_nexthop_global, "used");
445c2480
DS
7798 } else
7799 json_object_boolean_true_add(
7800 json_nexthop_global, "used");
7801 } else {
7802 /* Display LL if LL/Global both in table unless
7803 * prefer-global is set */
0606039c
DA
7804 if (((attr->mp_nexthop_len
7805 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 7806 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
7807 || (path->peer->conf_if)) {
7808 if (path->peer->conf_if) {
a4d82a8a 7809 len = vty_out(vty, "%s",
9b6d8fcf 7810 path->peer->conf_if);
445c2480
DS
7811 len = 16 - len; /* len of IPv6
7812 addr + max
7813 len of def
7814 ifname */
7815
7816 if (len < 1)
a4d82a8a 7817 vty_out(vty, "\n%*s", 36, " ");
445c2480 7818 else
a4d82a8a 7819 vty_out(vty, "%*s", len, " ");
d62a17ae 7820 } else {
7821 len = vty_out(
9df8b37c 7822 vty, "%s%s",
515c2602
DA
7823 nexthop_hostname
7824 ? nexthop_hostname
25b5da8d
DA
7825 : inet_ntop(
7826 AF_INET6,
7827 &attr->mp_nexthop_local,
7828 buf, BUFSIZ),
9df8b37c 7829 vrf_id_str);
d62a17ae 7830 len = 16 - len;
7831
7832 if (len < 1)
a4d82a8a 7833 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 7834 else
a4d82a8a 7835 vty_out(vty, "%*s", len, " ");
d62a17ae 7836 }
445c2480 7837 } else {
a4d82a8a 7838 len = vty_out(
9df8b37c 7839 vty, "%s%s",
515c2602
DA
7840 nexthop_hostname
7841 ? nexthop_hostname
25b5da8d
DA
7842 : inet_ntop(
7843 AF_INET6,
7844 &attr->mp_nexthop_global,
7845 buf, BUFSIZ),
7846 vrf_id_str);
445c2480
DS
7847 len = 16 - len;
7848
7849 if (len < 1)
7850 vty_out(vty, "\n%*s", 36, " ");
7851 else
7852 vty_out(vty, "%*s", len, " ");
d62a17ae 7853 }
7854 }
445c2480 7855 }
718e3744 7856
445c2480
DS
7857 /* MED/Metric */
7858 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 7859 if (json_paths)
50e05855 7860 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 7861 else
445c2480
DS
7862 vty_out(vty, "%10u", attr->med);
7863 else if (!json_paths)
7864 vty_out(vty, " ");
d62a17ae 7865
445c2480
DS
7866 /* Local Pref */
7867 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 7868 if (json_paths)
50e05855 7869 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
7870 attr->local_pref);
7871 else
445c2480
DS
7872 vty_out(vty, "%7u", attr->local_pref);
7873 else if (!json_paths)
7874 vty_out(vty, " ");
d62a17ae 7875
445c2480
DS
7876 if (json_paths)
7877 json_object_int_add(json_path, "weight", attr->weight);
7878 else
7879 vty_out(vty, "%7u ", attr->weight);
47fc97cc 7880
445c2480
DS
7881 if (json_paths) {
7882 char buf[BUFSIZ];
a4d82a8a
PZ
7883 json_object_string_add(
7884 json_path, "peerId",
9b6d8fcf 7885 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 7886 }
b05a1c8b 7887
445c2480
DS
7888 /* Print aspath */
7889 if (attr->aspath) {
0fbac0b4 7890 if (json_paths)
50e05855 7891 json_object_string_add(json_path, "path",
0fbac0b4
DA
7892 attr->aspath->str);
7893 else
445c2480 7894 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 7895 }
f1aa5d8a 7896
445c2480
DS
7897 /* Print origin */
7898 if (json_paths)
a4d82a8a
PZ
7899 json_object_string_add(json_path, "origin",
7900 bgp_origin_long_str[attr->origin]);
445c2480
DS
7901 else
7902 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7903
9df8b37c 7904 if (json_paths) {
6f214dd3
CS
7905 if (safi == SAFI_EVPN &&
7906 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7907 json_ext_community = json_object_new_object();
7908 json_object_string_add(json_ext_community,
7909 "string",
7910 attr->ecommunity->str);
7911 json_object_object_add(json_path,
7912 "extendedCommunity",
7913 json_ext_community);
7914 }
7915
9df8b37c
PZ
7916 if (nexthop_self)
7917 json_object_boolean_true_add(json_path,
7918 "announceNexthopSelf");
7919 if (nexthop_othervrf) {
7920 json_object_string_add(json_path, "nhVrfName",
7921 nexthop_vrfname);
7922
7923 json_object_int_add(json_path, "nhVrfId",
7924 ((nexthop_vrfid == VRF_UNKNOWN)
7925 ? -1
7926 : (int)nexthop_vrfid));
7927 }
7928 }
7929
d62a17ae 7930 if (json_paths) {
7931 if (json_nexthop_global || json_nexthop_ll) {
7932 json_nexthops = json_object_new_array();
f1aa5d8a 7933
d62a17ae 7934 if (json_nexthop_global)
7935 json_object_array_add(json_nexthops,
7936 json_nexthop_global);
f1aa5d8a 7937
d62a17ae 7938 if (json_nexthop_ll)
7939 json_object_array_add(json_nexthops,
7940 json_nexthop_ll);
f1aa5d8a 7941
d62a17ae 7942 json_object_object_add(json_path, "nexthops",
7943 json_nexthops);
7944 }
7945
7946 json_object_array_add(json_paths, json_path);
7947 } else {
7948 vty_out(vty, "\n");
6f214dd3
CS
7949
7950 if (safi == SAFI_EVPN &&
7951 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7952 vty_out(vty, "%*s", 20, " ");
7953 vty_out(vty, "%s\n", attr->ecommunity->str);
7954 }
7955
49e5a4a0 7956#ifdef ENABLE_BGP_VNC
d62a17ae 7957 /* prints an additional line, indented, with VNC info, if
7958 * present */
7959 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 7960 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 7961#endif
d62a17ae 7962 }
7963}
718e3744 7964
7965/* called from terminal list command */
5f040085
DS
7966void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
7967 struct attr *attr, safi_t safi, bool use_json,
7968 json_object *json_ar)
d62a17ae 7969{
7970 json_object *json_status = NULL;
7971 json_object *json_net = NULL;
7972 char buff[BUFSIZ];
dc387b0f 7973
d62a17ae 7974 /* Route status display. */
7975 if (use_json) {
7976 json_status = json_object_new_object();
7977 json_net = json_object_new_object();
7978 } else {
7979 vty_out(vty, "*");
7980 vty_out(vty, ">");
7981 vty_out(vty, " ");
7982 }
718e3744 7983
d62a17ae 7984 /* print prefix and mask */
50e05855 7985 if (use_json) {
dc387b0f
LK
7986 if (safi == SAFI_EVPN)
7987 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
7988 else if (p->family == AF_INET || p->family == AF_INET6) {
7989 json_object_string_add(
7990 json_net, "addrPrefix",
7991 inet_ntop(p->family, &p->u.prefix, buff,
7992 BUFSIZ));
7993 json_object_int_add(json_net, "prefixLen",
7994 p->prefixlen);
7995 prefix2str(p, buff, PREFIX_STRLEN);
7996 json_object_string_add(json_net, "network", buff);
7997 }
50e05855 7998 } else
9c92b5f7 7999 route_vty_out_route(p, vty, NULL);
d62a17ae 8000
8001 /* Print attribute */
8002 if (attr) {
8003 if (use_json) {
8004 if (p->family == AF_INET
8005 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 8006 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 8007 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 8008 json_object_string_add(
8009 json_net, "nextHop",
8010 inet_ntoa(
8011 attr->mp_nexthop_global_in));
8012 else
8013 json_object_string_add(
8014 json_net, "nextHop",
8015 inet_ntoa(attr->nexthop));
8016 } else if (p->family == AF_INET6
8017 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8018 char buf[BUFSIZ];
8019
8020 json_object_string_add(
aa0a10fc 8021 json_net, "nextHopGlobal",
d62a17ae 8022 inet_ntop(AF_INET6,
8023 &attr->mp_nexthop_global, buf,
8024 BUFSIZ));
dc387b0f
LK
8025 } else if (p->family == AF_EVPN &&
8026 !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8027 json_object_string_add(json_net,
8028 "nextHop", inet_ntoa(
8029 attr->mp_nexthop_global_in));
d62a17ae 8030
8031 if (attr->flag
8032 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8033 json_object_int_add(json_net, "metric",
8034 attr->med);
8035
0fbac0b4 8036 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 8037 json_object_int_add(json_net, "locPrf",
0fbac0b4 8038 attr->local_pref);
d62a17ae 8039
8040 json_object_int_add(json_net, "weight", attr->weight);
8041
8042 /* Print aspath */
0fbac0b4 8043 if (attr->aspath)
50e05855 8044 json_object_string_add(json_net, "path",
0fbac0b4 8045 attr->aspath->str);
d62a17ae 8046
8047 /* Print origin */
8048 json_object_string_add(json_net, "bgpOriginCode",
8049 bgp_origin_str[attr->origin]);
8050 } else {
8051 if (p->family == AF_INET
8052 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8053 || safi == SAFI_EVPN
8054 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8055 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8056 || safi == SAFI_EVPN)
8057 vty_out(vty, "%-16s",
8058 inet_ntoa(
8059 attr->mp_nexthop_global_in));
8060 else
8061 vty_out(vty, "%-16s",
8062 inet_ntoa(attr->nexthop));
8063 } else if (p->family == AF_INET6
8064 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8065 int len;
8066 char buf[BUFSIZ];
8067
8068 len = vty_out(
8069 vty, "%s",
8070 inet_ntop(AF_INET6,
8071 &attr->mp_nexthop_global, buf,
8072 BUFSIZ));
8073 len = 16 - len;
8074 if (len < 1)
8075 vty_out(vty, "\n%*s", 36, " ");
8076 else
8077 vty_out(vty, "%*s", len, " ");
8078 }
8079 if (attr->flag
8080 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8081 vty_out(vty, "%10u", attr->med);
8082 else
8083 vty_out(vty, " ");
718e3744 8084
d62a17ae 8085 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
8086 vty_out(vty, "%7u", attr->local_pref);
8087 else
8088 vty_out(vty, " ");
8089
8090 vty_out(vty, "%7u ", attr->weight);
8091
8092 /* Print aspath */
8093 if (attr->aspath)
8094 aspath_print_vty(vty, "%s", attr->aspath, " ");
8095
8096 /* Print origin */
8097 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8098 }
8099 }
8100 if (use_json) {
8101 json_object_boolean_true_add(json_status, "*");
8102 json_object_boolean_true_add(json_status, ">");
8103 json_object_object_add(json_net, "appliedStatusSymbols",
8104 json_status);
1608ff77 8105
dc387b0f
LK
8106 prefix2str(p, buff, PREFIX_STRLEN);
8107 json_object_object_add(json_ar, buff, json_net);
d62a17ae 8108 } else
8109 vty_out(vty, "\n");
8110}
8111
bd494ec5 8112void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 8113 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 8114 json_object *json)
8115{
8116 json_object *json_out = NULL;
8117 struct attr *attr;
8118 mpls_label_t label = MPLS_INVALID_LABEL;
8119
9b6d8fcf 8120 if (!path->extra)
d62a17ae 8121 return;
8122
8123 if (json)
8124 json_out = json_object_new_object();
8125
8126 /* short status lead text */
9b6d8fcf 8127 route_vty_short_status_out(vty, path, json_out);
d62a17ae 8128
8129 /* print prefix and mask */
8130 if (json == NULL) {
8131 if (!display)
9c92b5f7 8132 route_vty_out_route(p, vty, NULL);
d62a17ae 8133 else
8134 vty_out(vty, "%*s", 17, " ");
8135 }
8136
8137 /* Print attribute */
9b6d8fcf 8138 attr = path->attr;
05864da7
DS
8139 if (((p->family == AF_INET)
8140 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8141 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8142 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8143 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8144 || safi == SAFI_EVPN) {
8145 if (json)
8146 json_object_string_add(
8147 json_out, "mpNexthopGlobalIn",
8148 inet_ntoa(attr->mp_nexthop_global_in));
8149 else
8150 vty_out(vty, "%-16s",
8151 inet_ntoa(attr->mp_nexthop_global_in));
8152 } else {
8153 if (json)
8154 json_object_string_add(
8155 json_out, "nexthop",
8156 inet_ntoa(attr->nexthop));
8157 else
8158 vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
8159 }
8160 } else if (((p->family == AF_INET6)
8161 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8162 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8163 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8164 char buf_a[512];
8165
8166 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
8167 if (json)
8168 json_object_string_add(
8169 json_out, "mpNexthopGlobalIn",
8170 inet_ntop(AF_INET6,
8171 &attr->mp_nexthop_global,
8172 buf_a, sizeof(buf_a)));
8173 else
8174 vty_out(vty, "%s",
8175 inet_ntop(AF_INET6,
8176 &attr->mp_nexthop_global,
8177 buf_a, sizeof(buf_a)));
8178 } else if (attr->mp_nexthop_len
8179 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
8180 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
8181 &attr->mp_nexthop_global,
8182 &attr->mp_nexthop_local);
8183 if (json)
8184 json_object_string_add(json_out,
8185 "mpNexthopGlobalLocal",
8186 buf_a);
8187 else
8188 vty_out(vty, "%s", buf_a);
d62a17ae 8189 }
8190 }
8191
9b6d8fcf 8192 label = decode_label(&path->extra->label[0]);
d62a17ae 8193
8194 if (bgp_is_valid_label(&label)) {
8195 if (json) {
8196 json_object_int_add(json_out, "notag", label);
8197 json_object_array_add(json, json_out);
8198 } else {
8199 vty_out(vty, "notag/%d", label);
8200 vty_out(vty, "\n");
8201 }
8202 }
8203}
718e3744 8204
bd494ec5 8205void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 8206 struct bgp_path_info *path, int display,
d62a17ae 8207 json_object *json_paths)
718e3744 8208{
d62a17ae 8209 struct attr *attr;
14f51eba 8210 char buf[BUFSIZ] = {0};
d62a17ae 8211 json_object *json_path = NULL;
14f51eba
LK
8212 json_object *json_nexthop = NULL;
8213 json_object *json_overlay = NULL;
856ca177 8214
9b6d8fcf 8215 if (!path->extra)
d62a17ae 8216 return;
718e3744 8217
14f51eba
LK
8218 if (json_paths) {
8219 json_path = json_object_new_object();
8220 json_overlay = json_object_new_object();
8221 json_nexthop = json_object_new_object();
8222 }
8223
d62a17ae 8224 /* short status lead text */
9b6d8fcf 8225 route_vty_short_status_out(vty, path, json_path);
856ca177 8226
d62a17ae 8227 /* print prefix and mask */
8228 if (!display)
14f51eba 8229 route_vty_out_route(p, vty, json_path);
d62a17ae 8230 else
8231 vty_out(vty, "%*s", 17, " ");
8232
8233 /* Print attribute */
9b6d8fcf 8234 attr = path->attr;
05864da7
DS
8235 char buf1[BUFSIZ];
8236 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 8237
05864da7
DS
8238 switch (af) {
8239 case AF_INET:
8240 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
8241 if (!json_path) {
8242 vty_out(vty, "%-16s", buf);
8243 } else {
8244 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 8245
05864da7 8246 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 8247
05864da7
DS
8248 json_object_object_add(json_path, "nexthop",
8249 json_nexthop);
8250 }
8251 break;
8252 case AF_INET6:
8253 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
8254 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
8255 if (!json_path) {
8256 vty_out(vty, "%s(%s)", buf, buf1);
8257 } else {
8258 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 8259
05864da7
DS
8260 json_object_string_add(json_nexthop, "ipv6LinkLocal",
8261 buf1);
14f51eba 8262
05864da7 8263 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 8264
05864da7
DS
8265 json_object_object_add(json_path, "nexthop",
8266 json_nexthop);
8267 }
8268 break;
8269 default:
8270 if (!json_path) {
8271 vty_out(vty, "?");
8272 } else {
8273 json_object_string_add(json_nexthop, "Error",
8274 "Unsupported address-family");
d62a17ae 8275 }
05864da7 8276 }
988258b4 8277
05864da7 8278 char *str = esi2str(&(attr->evpn_overlay.eth_s_id));
988258b4 8279
05864da7
DS
8280 if (!json_path)
8281 vty_out(vty, "%s", str);
8282 else
8283 json_object_string_add(json_overlay, "esi", str);
25b5da8d 8284
05864da7 8285 XFREE(MTYPE_TMP, str);
988258b4 8286
05864da7
DS
8287 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
8288 inet_ntop(AF_INET, &(attr->evpn_overlay.gw_ip.ipv4), buf,
8289 BUFSIZ);
8290 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
8291 inet_ntop(AF_INET6, &(attr->evpn_overlay.gw_ip.ipv6), buf,
8292 BUFSIZ);
8293 }
14f51eba 8294
05864da7
DS
8295 if (!json_path)
8296 vty_out(vty, "/%s", buf);
8297 else
8298 json_object_string_add(json_overlay, "gw", buf);
8299
8300 if (attr->ecommunity) {
8301 char *mac = NULL;
8302 struct ecommunity_val *routermac = ecommunity_lookup(
8303 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
8304 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
8305
8306 if (routermac)
8307 mac = ecom_mac2str((char *)routermac->val);
8308 if (mac) {
8309 if (!json_path) {
c4efd0f4 8310 vty_out(vty, "/%s", mac);
05864da7
DS
8311 } else {
8312 json_object_string_add(json_overlay, "rmac",
8313 mac);
988258b4 8314 }
05864da7 8315 XFREE(MTYPE_TMP, mac);
988258b4 8316 }
05864da7 8317 }
718e3744 8318
05864da7
DS
8319 if (!json_path) {
8320 vty_out(vty, "\n");
8321 } else {
8322 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 8323
05864da7 8324 json_object_array_add(json_paths, json_path);
14f51eba 8325 }
d62a17ae 8326}
718e3744 8327
d62a17ae 8328/* dampening route */
5f040085
DS
8329static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
8330 struct bgp_path_info *path, int display,
8331 afi_t afi, safi_t safi, bool use_json,
8332 json_object *json)
d62a17ae 8333{
8334 struct attr *attr;
8335 int len;
8336 char timebuf[BGP_UPTIME_LEN];
8337
8338 /* short status lead text */
9b6d8fcf 8339 route_vty_short_status_out(vty, path, json);
d62a17ae 8340
8341 /* print prefix and mask */
8342 if (!use_json) {
8343 if (!display)
9c92b5f7 8344 route_vty_out_route(p, vty, NULL);
d62a17ae 8345 else
8346 vty_out(vty, "%*s", 17, " ");
8347 }
8348
9b6d8fcf 8349 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 8350 len = 17 - len;
8351 if (len < 1) {
8352 if (!use_json)
8353 vty_out(vty, "\n%*s", 34, " ");
8354 } else {
8355 if (use_json)
8356 json_object_int_add(json, "peerHost", len);
8357 else
8358 vty_out(vty, "%*s", len, " ");
8359 }
8360
8361 if (use_json)
a935f597
DA
8362 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
8363 safi, use_json, json);
d62a17ae 8364 else
9b6d8fcf
DS
8365 vty_out(vty, "%s ",
8366 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8367 BGP_UPTIME_LEN, afi, safi,
8368 use_json, json));
d62a17ae 8369
8370 /* Print attribute */
9b6d8fcf 8371 attr = path->attr;
d62a17ae 8372
05864da7
DS
8373 /* Print aspath */
8374 if (attr->aspath) {
d62a17ae 8375 if (use_json)
05864da7
DS
8376 json_object_string_add(json, "asPath",
8377 attr->aspath->str);
d62a17ae 8378 else
05864da7 8379 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8380 }
05864da7
DS
8381
8382 /* Print origin */
8383 if (use_json)
8384 json_object_string_add(json, "origin",
8385 bgp_origin_str[attr->origin]);
8386 else
8387 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8388
d62a17ae 8389 if (!use_json)
8390 vty_out(vty, "\n");
8391}
718e3744 8392
d62a17ae 8393/* flap route */
5f040085
DS
8394static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
8395 struct bgp_path_info *path, int display,
8396 afi_t afi, safi_t safi, bool use_json,
8397 json_object *json)
784d3a42 8398{
d62a17ae 8399 struct attr *attr;
8400 struct bgp_damp_info *bdi;
8401 char timebuf[BGP_UPTIME_LEN];
8402 int len;
784d3a42 8403
9b6d8fcf 8404 if (!path->extra)
d62a17ae 8405 return;
784d3a42 8406
9b6d8fcf 8407 bdi = path->extra->damp_info;
784d3a42 8408
d62a17ae 8409 /* short status lead text */
9b6d8fcf 8410 route_vty_short_status_out(vty, path, json);
784d3a42 8411
d62a17ae 8412 /* print prefix and mask */
8413 if (!use_json) {
8414 if (!display)
9c92b5f7 8415 route_vty_out_route(p, vty, NULL);
d62a17ae 8416 else
8417 vty_out(vty, "%*s", 17, " ");
8418 }
784d3a42 8419
9b6d8fcf 8420 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 8421 len = 16 - len;
8422 if (len < 1) {
8423 if (!use_json)
8424 vty_out(vty, "\n%*s", 33, " ");
8425 } else {
8426 if (use_json)
8427 json_object_int_add(json, "peerHost", len);
8428 else
8429 vty_out(vty, "%*s", len, " ");
8430 }
784d3a42 8431
d62a17ae 8432 len = vty_out(vty, "%d", bdi->flap);
8433 len = 5 - len;
8434 if (len < 1) {
8435 if (!use_json)
8436 vty_out(vty, " ");
8437 } else {
8438 if (use_json)
8439 json_object_int_add(json, "bdiFlap", len);
8440 else
8441 vty_out(vty, "%*s", len, " ");
8442 }
8443
8444 if (use_json)
8445 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
8446 json);
8447 else
996c9314
LB
8448 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
8449 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 8450
9b6d8fcf
DS
8451 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
8452 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 8453 if (use_json)
9b6d8fcf 8454 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8455 BGP_UPTIME_LEN, afi, safi,
8456 use_json, json);
d62a17ae 8457 else
8458 vty_out(vty, "%s ",
9b6d8fcf 8459 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8460 BGP_UPTIME_LEN, afi,
8461 safi, use_json, json));
d62a17ae 8462 } else {
8463 if (!use_json)
8464 vty_out(vty, "%*s ", 8, " ");
8465 }
8466
8467 /* Print attribute */
9b6d8fcf 8468 attr = path->attr;
d62a17ae 8469
05864da7
DS
8470 /* Print aspath */
8471 if (attr->aspath) {
d62a17ae 8472 if (use_json)
05864da7
DS
8473 json_object_string_add(json, "asPath",
8474 attr->aspath->str);
d62a17ae 8475 else
05864da7 8476 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8477 }
05864da7
DS
8478
8479 /* Print origin */
8480 if (use_json)
8481 json_object_string_add(json, "origin",
8482 bgp_origin_str[attr->origin]);
8483 else
8484 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8485
d62a17ae 8486 if (!use_json)
8487 vty_out(vty, "\n");
8488}
8489
8490static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
8491 int *first, const char *header,
8492 json_object *json_adv_to)
8493{
8494 char buf1[INET6_ADDRSTRLEN];
8495 json_object *json_peer = NULL;
8496
8497 if (json_adv_to) {
8498 /* 'advertised-to' is a dictionary of peers we have advertised
8499 * this
8500 * prefix too. The key is the peer's IP or swpX, the value is
8501 * the
8502 * hostname if we know it and "" if not.
8503 */
8504 json_peer = json_object_new_object();
8505
8506 if (peer->hostname)
8507 json_object_string_add(json_peer, "hostname",
8508 peer->hostname);
8509
8510 if (peer->conf_if)
8511 json_object_object_add(json_adv_to, peer->conf_if,
8512 json_peer);
8513 else
8514 json_object_object_add(
8515 json_adv_to,
8516 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
8517 json_peer);
8518 } else {
8519 if (*first) {
8520 vty_out(vty, "%s", header);
8521 *first = 0;
8522 }
8523
8524 if (peer->hostname
892fedb6 8525 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 8526 if (peer->conf_if)
8527 vty_out(vty, " %s(%s)", peer->hostname,
8528 peer->conf_if);
8529 else
8530 vty_out(vty, " %s(%s)", peer->hostname,
8531 sockunion2str(&peer->su, buf1,
8532 SU_ADDRSTRLEN));
8533 } else {
8534 if (peer->conf_if)
8535 vty_out(vty, " %s", peer->conf_if);
8536 else
8537 vty_out(vty, " %s",
8538 sockunion2str(&peer->su, buf1,
8539 SU_ADDRSTRLEN));
8540 }
8541 }
784d3a42
PG
8542}
8543
dcc68b5e
MS
8544static void route_vty_out_tx_ids(struct vty *vty,
8545 struct bgp_addpath_info_data *d)
8546{
8547 int i;
8548
8549 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
8550 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
8551 d->addpath_tx_id[i],
8552 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
8553 }
8554}
8555
0dc8ee70
DS
8556static const char *bgp_path_selection_reason2str(
8557 enum bgp_path_selection_reason reason)
8558{
8559 switch (reason) {
8560 case bgp_path_selection_none:
8561 return "Nothing to Select";
0dc8ee70
DS
8562 case bgp_path_selection_first:
8563 return "First path received";
0dc8ee70
DS
8564 case bgp_path_selection_evpn_sticky_mac:
8565 return "EVPN Sticky Mac";
0dc8ee70
DS
8566 case bgp_path_selection_evpn_seq:
8567 return "EVPN sequence number";
0dc8ee70
DS
8568 case bgp_path_selection_evpn_lower_ip:
8569 return "EVPN lower IP";
0dc8ee70
DS
8570 case bgp_path_selection_weight:
8571 return "Weight";
0dc8ee70
DS
8572 case bgp_path_selection_local_pref:
8573 return "Local Pref";
0dc8ee70
DS
8574 case bgp_path_selection_local_route:
8575 return "Local Route";
0dc8ee70
DS
8576 case bgp_path_selection_confed_as_path:
8577 return "Confederation based AS Path";
0dc8ee70
DS
8578 case bgp_path_selection_as_path:
8579 return "AS Path";
0dc8ee70
DS
8580 case bgp_path_selection_origin:
8581 return "Origin";
0dc8ee70
DS
8582 case bgp_path_selection_med:
8583 return "MED";
0dc8ee70
DS
8584 case bgp_path_selection_peer:
8585 return "Peer Type";
0dc8ee70
DS
8586 case bgp_path_selection_confed:
8587 return "Confed Peer Type";
0dc8ee70
DS
8588 case bgp_path_selection_igp_metric:
8589 return "IGP Metric";
0dc8ee70
DS
8590 case bgp_path_selection_older:
8591 return "Older Path";
0dc8ee70
DS
8592 case bgp_path_selection_router_id:
8593 return "Router ID";
0dc8ee70
DS
8594 case bgp_path_selection_cluster_length:
8595 return "Cluser length";
0dc8ee70
DS
8596 case bgp_path_selection_stale:
8597 return "Path Staleness";
0dc8ee70
DS
8598 case bgp_path_selection_local_configured:
8599 return "Locally configured route";
0dc8ee70
DS
8600 case bgp_path_selection_neighbor_ip:
8601 return "Neighbor IP";
0dc8ee70
DS
8602 case bgp_path_selection_default:
8603 return "Nothing left to compare";
0dc8ee70 8604 }
a74879b2 8605 return "Invalid (internal error)";
0dc8ee70
DS
8606}
8607
f08b5ca0
DS
8608void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
8609 struct bgp_node *bn, struct bgp_path_info *path,
8610 afi_t afi, safi_t safi, json_object *json_paths)
d62a17ae 8611{
8612 char buf[INET6_ADDRSTRLEN];
8613 char buf1[BUFSIZ];
d62a17ae 8614 char buf2[EVPN_ROUTE_STRLEN];
515c2602 8615 struct attr *attr = path->attr;
d62a17ae 8616 int sockunion_vty_out(struct vty *, union sockunion *);
8617 time_t tbuf;
8618 json_object *json_bestpath = NULL;
8619 json_object *json_cluster_list = NULL;
8620 json_object *json_cluster_list_list = NULL;
8621 json_object *json_ext_community = NULL;
8622 json_object *json_last_update = NULL;
7fd077aa 8623 json_object *json_pmsi = NULL;
d62a17ae 8624 json_object *json_nexthop_global = NULL;
8625 json_object *json_nexthop_ll = NULL;
8626 json_object *json_nexthops = NULL;
8627 json_object *json_path = NULL;
8628 json_object *json_peer = NULL;
8629 json_object *json_string = NULL;
8630 json_object *json_adv_to = NULL;
8631 int first = 0;
8632 struct listnode *node, *nnode;
8633 struct peer *peer;
8634 int addpath_capable;
8635 int has_adj;
8636 unsigned int first_as;
1defdda8 8637 bool nexthop_self =
9b6d8fcf 8638 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 8639 int i;
515c2602 8640 char *nexthop_hostname = bgp_nexthop_hostname(path->peer, attr);
d62a17ae 8641
8642 if (json_paths) {
8643 json_path = json_object_new_object();
8644 json_peer = json_object_new_object();
8645 json_nexthop_global = json_object_new_object();
8646 }
8647
44c69747 8648 if (path->extra) {
b57ba6d2 8649 char tag_buf[30];
d62a17ae 8650
d7325ee7 8651 buf2[0] = '\0';
d62a17ae 8652 tag_buf[0] = '\0';
9b6d8fcf
DS
8653 if (path->extra && path->extra->num_labels) {
8654 bgp_evpn_label2str(path->extra->label,
8655 path->extra->num_labels, tag_buf,
a4d82a8a 8656 sizeof(tag_buf));
d62a17ae 8657 }
d7325ee7 8658 if (safi == SAFI_EVPN) {
44c69747 8659 if (!json_paths) {
b54892e0
DS
8660 bgp_evpn_route2str(
8661 (struct prefix_evpn *)
8662 bgp_node_get_prefix(bn),
8663 buf2, sizeof(buf2));
44c69747
LK
8664 vty_out(vty, " Route %s", buf2);
8665 if (tag_buf[0] != '\0')
8666 vty_out(vty, " VNI %s", tag_buf);
8667 vty_out(vty, "\n");
8668 } else {
8669 if (tag_buf[0])
8670 json_object_string_add(json_path, "VNI",
8671 tag_buf);
8672 }
d7325ee7
DD
8673 }
8674
44c69747 8675 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 8676 struct bgp_path_info *parent_ri;
d62a17ae 8677 struct bgp_node *rn, *prn;
8678
9b6d8fcf 8679 parent_ri = (struct bgp_path_info *)path->extra->parent;
d62a17ae 8680 rn = parent_ri->net;
8681 if (rn && rn->prn) {
8682 prn = rn->prn;
b54892e0
DS
8683 prefix_rd2str((struct prefix_rd *)
8684 bgp_node_get_prefix(prn),
d7325ee7
DD
8685 buf1, sizeof(buf1));
8686 if (is_pi_family_evpn(parent_ri)) {
b54892e0
DS
8687 bgp_evpn_route2str(
8688 (struct prefix_evpn *)
8689 bgp_node_get_prefix(rn),
8690 buf2, sizeof(buf2));
d7325ee7
DD
8691 vty_out(vty, " Imported from %s:%s, VNI %s\n", buf1, buf2, tag_buf);
8692 } else
8693 vty_out(vty, " Imported from %s:%s\n", buf1, buf2);
d62a17ae 8694 }
8695 }
8696 }
d62a17ae 8697
05864da7
DS
8698 /* Line1 display AS-path, Aggregator */
8699 if (attr->aspath) {
8700 if (json_paths) {
8701 if (!attr->aspath->json)
8702 aspath_str_update(attr->aspath, true);
8703 json_object_lock(attr->aspath->json);
8704 json_object_object_add(json_path, "aspath",
8705 attr->aspath->json);
8706 } else {
8707 if (attr->aspath->segments)
8708 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 8709 else
05864da7 8710 vty_out(vty, " Local");
d62a17ae 8711 }
05864da7 8712 }
d62a17ae 8713
05864da7
DS
8714 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
8715 if (json_paths)
8716 json_object_boolean_true_add(json_path, "removed");
8717 else
8718 vty_out(vty, ", (removed)");
8719 }
d62a17ae 8720
05864da7
DS
8721 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
8722 if (json_paths)
8723 json_object_boolean_true_add(json_path, "stale");
8724 else
8725 vty_out(vty, ", (stale)");
8726 }
d62a17ae 8727
05864da7
DS
8728 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
8729 if (json_paths) {
8730 json_object_int_add(json_path, "aggregatorAs",
8731 attr->aggregator_as);
8732 json_object_string_add(
8733 json_path, "aggregatorId",
8734 inet_ntoa(attr->aggregator_addr));
87c82131
DA
8735 if (attr->aggregator_as == BGP_AS_ZERO)
8736 json_object_boolean_true_add(
8737 json_path, "aggregatorAsMalformed");
8738 else
8739 json_object_boolean_false_add(
8740 json_path, "aggregatorAsMalformed");
05864da7 8741 } else {
87c82131
DA
8742 if (attr->aggregator_as == BGP_AS_ZERO)
8743 vty_out(vty,
8744 ", (aggregated by %u(malformed) %s)",
8745 attr->aggregator_as,
8746 inet_ntoa(attr->aggregator_addr));
8747 else
8748 vty_out(vty, ", (aggregated by %u %s)",
8749 attr->aggregator_as,
8750 inet_ntoa(attr->aggregator_addr));
d62a17ae 8751 }
05864da7 8752 }
d62a17ae 8753
05864da7
DS
8754 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
8755 PEER_FLAG_REFLECTOR_CLIENT)) {
8756 if (json_paths)
8757 json_object_boolean_true_add(json_path,
8758 "rxedFromRrClient");
8759 else
8760 vty_out(vty, ", (Received from a RR-client)");
8761 }
d62a17ae 8762
05864da7
DS
8763 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
8764 PEER_FLAG_RSERVER_CLIENT)) {
8765 if (json_paths)
8766 json_object_boolean_true_add(json_path,
8767 "rxedFromRsClient");
8768 else
8769 vty_out(vty, ", (Received from a RS-client)");
8770 }
d62a17ae 8771
05864da7
DS
8772 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
8773 if (json_paths)
8774 json_object_boolean_true_add(json_path,
8775 "dampeningHistoryEntry");
8776 else
8777 vty_out(vty, ", (history entry)");
8778 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
8779 if (json_paths)
8780 json_object_boolean_true_add(json_path,
8781 "dampeningSuppressed");
8782 else
8783 vty_out(vty, ", (suppressed due to dampening)");
8784 }
d62a17ae 8785
05864da7
DS
8786 if (!json_paths)
8787 vty_out(vty, "\n");
d62a17ae 8788
05864da7
DS
8789 /* Line2 display Next-hop, Neighbor, Router-id */
8790 /* Display the nexthop */
b54892e0
DS
8791 const struct prefix *bn_p = bgp_node_get_prefix(bn);
8792
8793 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
8794 || bn_p->family == AF_EVPN)
05864da7
DS
8795 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
8796 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8797 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8798 || safi == SAFI_EVPN) {
515c2602 8799 if (json_paths) {
d62a17ae 8800 json_object_string_add(
515c2602
DA
8801 json_nexthop_global, "ip",
8802 inet_ntoa(attr->mp_nexthop_global_in));
8803
8804 if (nexthop_hostname)
8805 json_object_string_add(
8806 json_nexthop_global, "hostname",
8807 nexthop_hostname);
8808 } else
d62a17ae 8809 vty_out(vty, " %s",
515c2602
DA
8810 nexthop_hostname
8811 ? nexthop_hostname
05864da7 8812 : inet_ntoa(
515c2602 8813 attr->mp_nexthop_global_in));
d62a17ae 8814 } else {
515c2602 8815 if (json_paths) {
05864da7 8816 json_object_string_add(
515c2602
DA
8817 json_nexthop_global, "ip",
8818 inet_ntoa(attr->nexthop));
8819
8820 if (nexthop_hostname)
8821 json_object_string_add(
8822 json_nexthop_global, "hostname",
8823 nexthop_hostname);
8824 } else
05864da7 8825 vty_out(vty, " %s",
515c2602
DA
8826 nexthop_hostname
8827 ? nexthop_hostname
05864da7 8828 : inet_ntoa(attr->nexthop));
d62a17ae 8829 }
8830
05864da7
DS
8831 if (json_paths)
8832 json_object_string_add(json_nexthop_global, "afi",
8833 "ipv4");
8834 } else {
8835 if (json_paths) {
8836 json_object_string_add(
515c2602
DA
8837 json_nexthop_global, "ip",
8838 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8839 buf, INET6_ADDRSTRLEN));
8840
8841 if (nexthop_hostname)
8842 json_object_string_add(json_nexthop_global,
8843 "hostname",
8844 nexthop_hostname);
8845
05864da7
DS
8846 json_object_string_add(json_nexthop_global, "afi",
8847 "ipv6");
8848 json_object_string_add(json_nexthop_global, "scope",
8849 "global");
8850 } else {
8851 vty_out(vty, " %s",
515c2602
DA
8852 nexthop_hostname
8853 ? nexthop_hostname
05864da7
DS
8854 : inet_ntop(AF_INET6,
8855 &attr->mp_nexthop_global,
8856 buf, INET6_ADDRSTRLEN));
d62a17ae 8857 }
05864da7 8858 }
d62a17ae 8859
05864da7
DS
8860 /* Display the IGP cost or 'inaccessible' */
8861 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
8862 if (json_paths)
8863 json_object_boolean_false_add(json_nexthop_global,
8864 "accessible");
8865 else
8866 vty_out(vty, " (inaccessible)");
8867 } else {
8868 if (path->extra && path->extra->igpmetric) {
d62a17ae 8869 if (json_paths)
05864da7
DS
8870 json_object_int_add(json_nexthop_global,
8871 "metric",
8872 path->extra->igpmetric);
d62a17ae 8873 else
05864da7
DS
8874 vty_out(vty, " (metric %u)",
8875 path->extra->igpmetric);
d62a17ae 8876 }
8877
05864da7 8878 /* IGP cost is 0, display this only for json */
d62a17ae 8879 else {
d62a17ae 8880 if (json_paths)
05864da7
DS
8881 json_object_int_add(json_nexthop_global,
8882 "metric", 0);
d62a17ae 8883 }
d62a17ae 8884
05864da7
DS
8885 if (json_paths)
8886 json_object_boolean_true_add(json_nexthop_global,
8887 "accessible");
8888 }
d62a17ae 8889
05864da7
DS
8890 /* Display peer "from" output */
8891 /* This path was originated locally */
8892 if (path->peer == bgp->peer_self) {
d62a17ae 8893
05864da7 8894 if (safi == SAFI_EVPN
b54892e0 8895 || (bn_p->family == AF_INET
05864da7 8896 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 8897 if (json_paths)
05864da7
DS
8898 json_object_string_add(json_peer, "peerId",
8899 "0.0.0.0");
d62a17ae 8900 else
05864da7
DS
8901 vty_out(vty, " from 0.0.0.0 ");
8902 } else {
d62a17ae 8903 if (json_paths)
05864da7
DS
8904 json_object_string_add(json_peer, "peerId",
8905 "::");
d62a17ae 8906 else
05864da7 8907 vty_out(vty, " from :: ");
d62a17ae 8908 }
d62a17ae 8909
05864da7
DS
8910 if (json_paths)
8911 json_object_string_add(json_peer, "routerId",
8912 inet_ntoa(bgp->router_id));
8913 else
8914 vty_out(vty, "(%s)", inet_ntoa(bgp->router_id));
8915 }
d62a17ae 8916
05864da7
DS
8917 /* We RXed this path from one of our peers */
8918 else {
8919
8920 if (json_paths) {
8921 json_object_string_add(json_peer, "peerId",
8922 sockunion2str(&path->peer->su,
8923 buf,
8924 SU_ADDRSTRLEN));
8925 json_object_string_add(json_peer, "routerId",
8926 inet_ntop(AF_INET,
8927 &path->peer->remote_id,
8928 buf1, sizeof(buf1)));
8929
8930 if (path->peer->hostname)
8931 json_object_string_add(json_peer, "hostname",
8932 path->peer->hostname);
8933
8934 if (path->peer->domainname)
8935 json_object_string_add(json_peer, "domainname",
8936 path->peer->domainname);
8937
8938 if (path->peer->conf_if)
8939 json_object_string_add(json_peer, "interface",
8940 path->peer->conf_if);
8941 } else {
8942 if (path->peer->conf_if) {
8943 if (path->peer->hostname
892fedb6
DA
8944 && CHECK_FLAG(path->peer->bgp->flags,
8945 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
8946 vty_out(vty, " from %s(%s)",
8947 path->peer->hostname,
8948 path->peer->conf_if);
d62a17ae 8949 else
05864da7 8950 vty_out(vty, " from %s",
9b6d8fcf 8951 path->peer->conf_if);
d62a17ae 8952 } else {
05864da7 8953 if (path->peer->hostname
892fedb6
DA
8954 && CHECK_FLAG(path->peer->bgp->flags,
8955 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
8956 vty_out(vty, " from %s(%s)",
8957 path->peer->hostname,
8958 path->peer->host);
d62a17ae 8959 else
05864da7
DS
8960 vty_out(vty, " from %s",
8961 sockunion2str(&path->peer->su,
8962 buf,
8963 SU_ADDRSTRLEN));
d62a17ae 8964 }
d62a17ae 8965
05864da7
DS
8966 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
8967 vty_out(vty, " (%s)",
8968 inet_ntoa(attr->originator_id));
8969 else
8970 vty_out(vty, " (%s)",
8971 inet_ntop(AF_INET,
8972 &path->peer->remote_id, buf1,
8973 sizeof(buf1)));
d62a17ae 8974 }
05864da7 8975 }
9df8b37c 8976
05864da7
DS
8977 /*
8978 * Note when vrfid of nexthop is different from that of prefix
8979 */
8980 if (path->extra && path->extra->bgp_orig) {
8981 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8982
05864da7
DS
8983 if (json_paths) {
8984 const char *vn;
9df8b37c 8985
05864da7
DS
8986 if (path->extra->bgp_orig->inst_type
8987 == BGP_INSTANCE_TYPE_DEFAULT)
8988 vn = VRF_DEFAULT_NAME;
8989 else
8990 vn = path->extra->bgp_orig->name;
9df8b37c 8991
05864da7 8992 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 8993
05864da7
DS
8994 if (nexthop_vrfid == VRF_UNKNOWN) {
8995 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 8996 } else {
05864da7
DS
8997 json_object_int_add(json_path, "nhVrfId",
8998 (int)nexthop_vrfid);
9df8b37c 8999 }
05864da7
DS
9000 } else {
9001 if (nexthop_vrfid == VRF_UNKNOWN)
9002 vty_out(vty, " vrf ?");
137147c6
DS
9003 else {
9004 struct vrf *vrf;
9005
9006 vrf = vrf_lookup_by_id(nexthop_vrfid);
9007 vty_out(vty, " vrf %s(%u)",
9008 VRF_LOGNAME(vrf), nexthop_vrfid);
9009 }
9df8b37c 9010 }
05864da7 9011 }
9df8b37c 9012
05864da7
DS
9013 if (nexthop_self) {
9014 if (json_paths) {
9015 json_object_boolean_true_add(json_path,
9016 "announceNexthopSelf");
9017 } else {
9018 vty_out(vty, " announce-nh-self");
9df8b37c 9019 }
05864da7 9020 }
9df8b37c 9021
05864da7
DS
9022 if (!json_paths)
9023 vty_out(vty, "\n");
d62a17ae 9024
05864da7
DS
9025 /* display the link-local nexthop */
9026 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9027 if (json_paths) {
9028 json_nexthop_ll = json_object_new_object();
9029 json_object_string_add(
515c2602
DA
9030 json_nexthop_ll, "ip",
9031 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9032 buf, INET6_ADDRSTRLEN));
9033
9034 if (nexthop_hostname)
9035 json_object_string_add(json_nexthop_ll,
9036 "hostname",
9037 nexthop_hostname);
9038
05864da7
DS
9039 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
9040 json_object_string_add(json_nexthop_ll, "scope",
9041 "link-local");
d62a17ae 9042
05864da7
DS
9043 json_object_boolean_true_add(json_nexthop_ll,
9044 "accessible");
d62a17ae 9045
05864da7 9046 if (!attr->mp_nexthop_prefer_global)
d62a17ae 9047 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
9048 "used");
9049 else
9050 json_object_boolean_true_add(
9051 json_nexthop_global, "used");
9052 } else {
9053 vty_out(vty, " (%s) %s\n",
9054 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9055 buf, INET6_ADDRSTRLEN),
9056 attr->mp_nexthop_prefer_global
9057 ? "(prefer-global)"
9058 : "(used)");
d62a17ae 9059 }
05864da7
DS
9060 }
9061 /* If we do not have a link-local nexthop then we must flag the
9062 global as "used" */
9063 else {
9064 if (json_paths)
9065 json_object_boolean_true_add(json_nexthop_global,
9066 "used");
9067 }
d62a17ae 9068
05864da7
DS
9069 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
9070 * Int/Ext/Local, Atomic, best */
9071 if (json_paths)
9072 json_object_string_add(json_path, "origin",
9073 bgp_origin_long_str[attr->origin]);
9074 else
9075 vty_out(vty, " Origin %s",
9076 bgp_origin_long_str[attr->origin]);
9df8b37c 9077
05864da7 9078 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 9079 if (json_paths)
05864da7 9080 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 9081 else
05864da7
DS
9082 vty_out(vty, ", metric %u", attr->med);
9083 }
9df8b37c 9084
05864da7
DS
9085 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
9086 if (json_paths)
0fbac0b4 9087 json_object_int_add(json_path, "locPrf",
05864da7
DS
9088 attr->local_pref);
9089 else
9090 vty_out(vty, ", localpref %u", attr->local_pref);
9091 }
9df8b37c 9092
05864da7
DS
9093 if (attr->weight != 0) {
9094 if (json_paths)
9095 json_object_int_add(json_path, "weight", attr->weight);
9096 else
9097 vty_out(vty, ", weight %u", attr->weight);
9098 }
9df8b37c 9099
05864da7
DS
9100 if (attr->tag != 0) {
9101 if (json_paths)
9102 json_object_int_add(json_path, "tag", attr->tag);
9103 else
9104 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
9105 }
9df8b37c 9106
05864da7
DS
9107 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9108 if (json_paths)
9109 json_object_boolean_false_add(json_path, "valid");
9110 else
9111 vty_out(vty, ", invalid");
9112 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9113 if (json_paths)
9114 json_object_boolean_true_add(json_path, "valid");
9115 else
9116 vty_out(vty, ", valid");
9117 }
9df8b37c 9118
05864da7
DS
9119 if (path->peer != bgp->peer_self) {
9120 if (path->peer->as == path->peer->local_as) {
9121 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
9122 if (json_paths)
9123 json_object_string_add(
9124 json_peer, "type",
9125 "confed-internal");
d62a17ae 9126 else
05864da7 9127 vty_out(vty, ", confed-internal");
d62a17ae 9128 } else {
05864da7
DS
9129 if (json_paths)
9130 json_object_string_add(
9131 json_peer, "type", "internal");
9132 else
9133 vty_out(vty, ", internal");
9df8b37c 9134 }
05864da7
DS
9135 } else {
9136 if (bgp_confederation_peers_check(bgp,
9137 path->peer->as)) {
9138 if (json_paths)
9139 json_object_string_add(
9140 json_peer, "type",
9141 "confed-external");
d62a17ae 9142 else
05864da7 9143 vty_out(vty, ", confed-external");
d62a17ae 9144 } else {
05864da7
DS
9145 if (json_paths)
9146 json_object_string_add(
9147 json_peer, "type", "external");
9148 else
9149 vty_out(vty, ", external");
d62a17ae 9150 }
9151 }
05864da7
DS
9152 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
9153 if (json_paths) {
9154 json_object_boolean_true_add(json_path, "aggregated");
9155 json_object_boolean_true_add(json_path, "local");
9156 } else {
9157 vty_out(vty, ", aggregated, local");
9158 }
9159 } else if (path->type != ZEBRA_ROUTE_BGP) {
9160 if (json_paths)
9161 json_object_boolean_true_add(json_path, "sourced");
9162 else
9163 vty_out(vty, ", sourced");
9164 } else {
9165 if (json_paths) {
9166 json_object_boolean_true_add(json_path, "sourced");
9167 json_object_boolean_true_add(json_path, "local");
9168 } else {
9169 vty_out(vty, ", sourced, local");
d62a17ae 9170 }
05864da7 9171 }
718e3744 9172
05864da7 9173 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 9174 if (json_paths)
05864da7
DS
9175 json_object_boolean_true_add(json_path,
9176 "atomicAggregate");
d62a17ae 9177 else
05864da7
DS
9178 vty_out(vty, ", atomic-aggregate");
9179 }
d62a17ae 9180
05864da7
DS
9181 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
9182 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
9183 && bgp_path_info_mpath_count(path))) {
9184 if (json_paths)
9185 json_object_boolean_true_add(json_path, "multipath");
9186 else
9187 vty_out(vty, ", multipath");
9188 }
50e05855 9189
05864da7
DS
9190 // Mark the bestpath(s)
9191 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
9192 first_as = aspath_get_first_as(attr->aspath);
718e3744 9193
05864da7
DS
9194 if (json_paths) {
9195 if (!json_bestpath)
9196 json_bestpath = json_object_new_object();
9197 json_object_int_add(json_bestpath, "bestpathFromAs",
9198 first_as);
9199 } else {
9200 if (first_as)
9201 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 9202 else
05864da7 9203 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 9204 }
05864da7 9205 }
718e3744 9206
05864da7
DS
9207 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
9208 if (json_paths) {
9209 if (!json_bestpath)
9210 json_bestpath = json_object_new_object();
9211 json_object_boolean_true_add(json_bestpath, "overall");
9212 json_object_string_add(
9213 json_bestpath, "selectionReason",
9214 bgp_path_selection_reason2str(bn->reason));
9215 } else {
9216 vty_out(vty, ", best");
9217 vty_out(vty, " (%s)",
9218 bgp_path_selection_reason2str(bn->reason));
d62a17ae 9219 }
05864da7 9220 }
718e3744 9221
05864da7
DS
9222 if (json_bestpath)
9223 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 9224
05864da7
DS
9225 if (!json_paths)
9226 vty_out(vty, "\n");
9227
9228 /* Line 4 display Community */
9229 if (attr->community) {
9230 if (json_paths) {
9231 if (!attr->community->json)
9232 community_str(attr->community, true);
9233 json_object_lock(attr->community->json);
9234 json_object_object_add(json_path, "community",
9235 attr->community->json);
9236 } else {
9237 vty_out(vty, " Community: %s\n",
9238 attr->community->str);
d62a17ae 9239 }
05864da7 9240 }
718e3744 9241
05864da7
DS
9242 /* Line 5 display Extended-community */
9243 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9244 if (json_paths) {
9245 json_ext_community = json_object_new_object();
9246 json_object_string_add(json_ext_community, "string",
9247 attr->ecommunity->str);
9248 json_object_object_add(json_path, "extendedCommunity",
9249 json_ext_community);
d62a17ae 9250 } else {
05864da7
DS
9251 vty_out(vty, " Extended Community: %s\n",
9252 attr->ecommunity->str);
d62a17ae 9253 }
05864da7 9254 }
718e3744 9255
05864da7
DS
9256 /* Line 6 display Large community */
9257 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
9258 if (json_paths) {
9259 if (!attr->lcommunity->json)
9260 lcommunity_str(attr->lcommunity, true);
9261 json_object_lock(attr->lcommunity->json);
9262 json_object_object_add(json_path, "largeCommunity",
9263 attr->lcommunity->json);
9264 } else {
9265 vty_out(vty, " Large Community: %s\n",
9266 attr->lcommunity->str);
d62a17ae 9267 }
05864da7 9268 }
718e3744 9269
05864da7
DS
9270 /* Line 7 display Originator, Cluster-id */
9271 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
9272 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
9273 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 9274 if (json_paths)
05864da7
DS
9275 json_object_string_add(
9276 json_path, "originatorId",
9277 inet_ntoa(attr->originator_id));
d62a17ae 9278 else
05864da7
DS
9279 vty_out(vty, " Originator: %s",
9280 inet_ntoa(attr->originator_id));
d62a17ae 9281 }
856ca177 9282
05864da7
DS
9283 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
9284 int i;
d62a17ae 9285
9286 if (json_paths) {
05864da7
DS
9287 json_cluster_list = json_object_new_object();
9288 json_cluster_list_list =
9289 json_object_new_array();
9290
9291 for (i = 0; i < attr->cluster->length / 4;
9292 i++) {
9293 json_string = json_object_new_string(
9294 inet_ntoa(attr->cluster
9295 ->list[i]));
9296 json_object_array_add(
9297 json_cluster_list_list,
9298 json_string);
9299 }
718e3744 9300
05864da7
DS
9301 /*
9302 * struct cluster_list does not have
9303 * "str" variable like aspath and community
9304 * do. Add this someday if someone asks
9305 * for it.
9306 * json_object_string_add(json_cluster_list,
9307 * "string", attr->cluster->str);
9308 */
9309 json_object_object_add(json_cluster_list,
9310 "list",
9311 json_cluster_list_list);
9312 json_object_object_add(json_path, "clusterList",
9313 json_cluster_list);
0dc8ee70 9314 } else {
05864da7
DS
9315 vty_out(vty, ", Cluster list: ");
9316
9317 for (i = 0; i < attr->cluster->length / 4;
9318 i++) {
9319 vty_out(vty, "%s ",
9320 inet_ntoa(attr->cluster
9321 ->list[i]));
9322 }
0dc8ee70 9323 }
d62a17ae 9324 }
718e3744 9325
d62a17ae 9326 if (!json_paths)
9327 vty_out(vty, "\n");
05864da7 9328 }
d62a17ae 9329
05864da7 9330 if (path->extra && path->extra->damp_info)
a935f597 9331 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 9332
05864da7
DS
9333 /* Remote Label */
9334 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
9335 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
9336 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 9337
05864da7
DS
9338 if (json_paths)
9339 json_object_int_add(json_path, "remoteLabel", label);
9340 else
9341 vty_out(vty, " Remote label: %d\n", label);
9342 }
d62a17ae 9343
e496b420
HS
9344 /* Remote SID */
9345 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
9346 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
9347 if (json_paths)
9348 json_object_string_add(json_path, "remoteSid", buf);
9349 else
9350 vty_out(vty, " Remote SID: %s\n", buf);
9351 }
9352
05864da7
DS
9353 /* Label Index */
9354 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
9355 if (json_paths)
9356 json_object_int_add(json_path, "labelIndex",
9357 attr->label_index);
9358 else
9359 vty_out(vty, " Label Index: %d\n",
9360 attr->label_index);
9361 }
d62a17ae 9362
05864da7
DS
9363 /* Line 8 display Addpath IDs */
9364 if (path->addpath_rx_id
9365 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
9366 if (json_paths) {
9367 json_object_int_add(json_path, "addpathRxId",
9368 path->addpath_rx_id);
d62a17ae 9369
05864da7
DS
9370 /* Keep backwards compatibility with the old API
9371 * by putting TX All's ID in the old field
9372 */
9373 json_object_int_add(
9374 json_path, "addpathTxId",
9375 path->tx_addpath
9376 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 9377
05864da7
DS
9378 /* ... but create a specific field for each
9379 * strategy
9380 */
9381 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9382 json_object_int_add(
9383 json_path,
9384 bgp_addpath_names(i)->id_json_name,
9385 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 9386 }
05864da7
DS
9387 } else {
9388 vty_out(vty, " AddPath ID: RX %u, ",
9389 path->addpath_rx_id);
d62a17ae 9390
05864da7 9391 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 9392 }
05864da7 9393 }
520d5d76 9394
05864da7
DS
9395 /* If we used addpath to TX a non-bestpath we need to display
9396 * "Advertised to" on a path-by-path basis
9397 */
9398 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9399 first = 1;
dcc68b5e 9400
05864da7
DS
9401 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9402 addpath_capable =
9403 bgp_addpath_encode_tx(peer, afi, safi);
9404 has_adj = bgp_adj_out_lookup(
9405 peer, path->net,
9406 bgp_addpath_id_for_peer(peer, afi, safi,
9407 &path->tx_addpath));
9408
9409 if ((addpath_capable && has_adj)
9410 || (!addpath_capable && has_adj
9411 && CHECK_FLAG(path->flags,
9412 BGP_PATH_SELECTED))) {
9413 if (json_path && !json_adv_to)
9414 json_adv_to = json_object_new_object();
dcc68b5e 9415
05864da7
DS
9416 route_vty_out_advertised_to(
9417 vty, peer, &first,
9418 " Advertised to:", json_adv_to);
d62a17ae 9419 }
9420 }
718e3744 9421
05864da7
DS
9422 if (json_path) {
9423 if (json_adv_to) {
9424 json_object_object_add(
9425 json_path, "advertisedTo", json_adv_to);
d62a17ae 9426 }
05864da7
DS
9427 } else {
9428 if (!first) {
9429 vty_out(vty, "\n");
d62a17ae 9430 }
9431 }
05864da7 9432 }
b05a1c8b 9433
05864da7
DS
9434 /* Line 9 display Uptime */
9435 tbuf = time(NULL) - (bgp_clock() - path->uptime);
9436 if (json_paths) {
9437 json_last_update = json_object_new_object();
9438 json_object_int_add(json_last_update, "epoch", tbuf);
9439 json_object_string_add(json_last_update, "string",
9440 ctime(&tbuf));
9441 json_object_object_add(json_path, "lastUpdate",
9442 json_last_update);
9443 } else
9444 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 9445
05864da7
DS
9446 /* Line 10 display PMSI tunnel attribute, if present */
9447 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
9448 const char *str =
9449 lookup_msg(bgp_pmsi_tnltype_str, attr->pmsi_tnl_type,
9450 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 9451
05864da7
DS
9452 if (json_paths) {
9453 json_pmsi = json_object_new_object();
9454 json_object_string_add(json_pmsi, "tunnelType", str);
9455 json_object_int_add(json_pmsi, "label",
9456 label2vni(&attr->label));
9457 json_object_object_add(json_path, "pmsi", json_pmsi);
9458 } else
9459 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
9460 str, label2vni(&attr->label));
d62a17ae 9461 }
f1aa5d8a 9462
d62a17ae 9463 /* We've constructed the json object for this path, add it to the json
9464 * array of paths
9465 */
9466 if (json_paths) {
9467 if (json_nexthop_global || json_nexthop_ll) {
9468 json_nexthops = json_object_new_array();
f1aa5d8a 9469
d62a17ae 9470 if (json_nexthop_global)
9471 json_object_array_add(json_nexthops,
9472 json_nexthop_global);
f1aa5d8a 9473
d62a17ae 9474 if (json_nexthop_ll)
9475 json_object_array_add(json_nexthops,
9476 json_nexthop_ll);
f1aa5d8a 9477
d62a17ae 9478 json_object_object_add(json_path, "nexthops",
9479 json_nexthops);
9480 }
9481
9482 json_object_object_add(json_path, "peer", json_peer);
9483 json_object_array_add(json_paths, json_path);
05864da7 9484 }
b366b518
BB
9485}
9486
96ade3ed 9487#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
9488#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9489#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 9490
d62a17ae 9491static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
9492 const char *prefix_list_str, afi_t afi,
9493 safi_t safi, enum bgp_show_type type);
9494static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
9495 const char *filter, afi_t afi, safi_t safi,
9496 enum bgp_show_type type);
9497static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
9498 const char *rmap_str, afi_t afi, safi_t safi,
9499 enum bgp_show_type type);
9500static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
9501 const char *com, int exact, afi_t afi,
9502 safi_t safi);
9503static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
9504 const char *prefix, afi_t afi, safi_t safi,
9505 enum bgp_show_type type);
a4d82a8a 9506static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
9507 afi_t afi, safi_t safi, enum bgp_show_type type,
9508 bool use_json);
7f323236
DW
9509static int bgp_show_community(struct vty *vty, struct bgp *bgp,
9510 const char *comstr, int exact, afi_t afi,
9f049418 9511 safi_t safi, bool use_json);
d62a17ae 9512
1ae44dfc
LB
9513
9514static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 9515 struct bgp_table *table, enum bgp_show_type type,
9f049418 9516 void *output_arg, bool use_json, char *rd,
a4d82a8a
PZ
9517 int is_last, unsigned long *output_cum,
9518 unsigned long *total_cum,
9386b588 9519 unsigned long *json_header_depth)
d62a17ae 9520{
40381db7 9521 struct bgp_path_info *pi;
d62a17ae 9522 struct bgp_node *rn;
9523 int header = 1;
9524 int display;
1ae44dfc
LB
9525 unsigned long output_count = 0;
9526 unsigned long total_count = 0;
d62a17ae 9527 struct prefix *p;
d62a17ae 9528 char buf2[BUFSIZ];
9529 json_object *json_paths = NULL;
9530 int first = 1;
9531
1ae44dfc
LB
9532 if (output_cum && *output_cum != 0)
9533 header = 0;
9534
9386b588 9535 if (use_json && !*json_header_depth) {
d62a17ae 9536 vty_out(vty,
66f80d74 9537 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
01eced22
AD
9538 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9539 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 9540 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b
DS
9541 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
9542 ? VRF_DEFAULT_NAME
9543 : bgp->name,
01eced22
AD
9544 table->version, inet_ntoa(bgp->router_id),
9545 bgp->default_local_pref, bgp->as);
9386b588
PZ
9546 *json_header_depth = 2;
9547 if (rd) {
445c2480 9548 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
9549 ++*json_header_depth;
9550 }
d62a17ae 9551 }
718e3744 9552
445c2480
DS
9553 if (use_json && rd) {
9554 vty_out(vty, " \"%s\" : { ", rd);
9555 }
9556
d62a17ae 9557 /* Start processing of routes. */
98ce9a06 9558 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
b54892e0
DS
9559 const struct prefix *rn_p = bgp_node_get_prefix(rn);
9560
6f94b685
DS
9561 pi = bgp_node_get_bgp_path_info(rn);
9562 if (pi == NULL)
98ce9a06 9563 continue;
d62a17ae 9564
98ce9a06 9565 display = 0;
98ce9a06
DS
9566 if (use_json)
9567 json_paths = json_object_new_array();
9568 else
9569 json_paths = NULL;
d62a17ae 9570
6f94b685 9571 for (; pi; pi = pi->next) {
98ce9a06
DS
9572 total_count++;
9573 if (type == bgp_show_type_flap_statistics
9574 || type == bgp_show_type_flap_neighbor
9575 || type == bgp_show_type_dampend_paths
9576 || type == bgp_show_type_damp_neighbor) {
40381db7 9577 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
9578 continue;
9579 }
9580 if (type == bgp_show_type_regexp) {
9581 regex_t *regex = output_arg;
d62a17ae 9582
40381db7 9583 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
9584 == REG_NOMATCH)
9585 continue;
9586 }
9587 if (type == bgp_show_type_prefix_list) {
9588 struct prefix_list *plist = output_arg;
d62a17ae 9589
b54892e0 9590 if (prefix_list_apply(plist, rn_p)
98ce9a06
DS
9591 != PREFIX_PERMIT)
9592 continue;
9593 }
9594 if (type == bgp_show_type_filter_list) {
9595 struct as_list *as_list = output_arg;
d62a17ae 9596
40381db7 9597 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
9598 != AS_FILTER_PERMIT)
9599 continue;
9600 }
9601 if (type == bgp_show_type_route_map) {
9602 struct route_map *rmap = output_arg;
9b6d8fcf 9603 struct bgp_path_info path;
98ce9a06 9604 struct attr dummy_attr;
b68885f9 9605 route_map_result_t ret;
d62a17ae 9606
6f4f49b2 9607 dummy_attr = *pi->attr;
d62a17ae 9608
40381db7 9609 path.peer = pi->peer;
9b6d8fcf 9610 path.attr = &dummy_attr;
d62a17ae 9611
b54892e0 9612 ret = route_map_apply(rmap, rn_p, RMAP_BGP,
9b6d8fcf 9613 &path);
98ce9a06
DS
9614 if (ret == RMAP_DENYMATCH)
9615 continue;
9616 }
9617 if (type == bgp_show_type_neighbor
9618 || type == bgp_show_type_flap_neighbor
9619 || type == bgp_show_type_damp_neighbor) {
9620 union sockunion *su = output_arg;
9621
40381db7
DS
9622 if (pi->peer == NULL
9623 || pi->peer->su_remote == NULL
9624 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
9625 continue;
9626 }
9627 if (type == bgp_show_type_cidr_only) {
d7c0a89a 9628 uint32_t destination;
d62a17ae 9629
b54892e0 9630 destination = ntohl(rn_p->u.prefix4.s_addr);
98ce9a06 9631 if (IN_CLASSC(destination)
b54892e0 9632 && rn_p->prefixlen == 24)
98ce9a06
DS
9633 continue;
9634 if (IN_CLASSB(destination)
b54892e0 9635 && rn_p->prefixlen == 16)
98ce9a06
DS
9636 continue;
9637 if (IN_CLASSA(destination)
b54892e0 9638 && rn_p->prefixlen == 8)
98ce9a06
DS
9639 continue;
9640 }
9641 if (type == bgp_show_type_prefix_longer) {
f7813c7c 9642 p = output_arg;
b54892e0 9643 if (!prefix_match(p, rn_p))
98ce9a06
DS
9644 continue;
9645 }
9646 if (type == bgp_show_type_community_all) {
40381db7 9647 if (!pi->attr->community)
98ce9a06
DS
9648 continue;
9649 }
9650 if (type == bgp_show_type_community) {
9651 struct community *com = output_arg;
d62a17ae 9652
40381db7
DS
9653 if (!pi->attr->community
9654 || !community_match(pi->attr->community,
98ce9a06
DS
9655 com))
9656 continue;
9657 }
9658 if (type == bgp_show_type_community_exact) {
9659 struct community *com = output_arg;
d62a17ae 9660
40381db7
DS
9661 if (!pi->attr->community
9662 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
9663 continue;
9664 }
9665 if (type == bgp_show_type_community_list) {
9666 struct community_list *list = output_arg;
d62a17ae 9667
40381db7 9668 if (!community_list_match(pi->attr->community,
a4d82a8a 9669 list))
98ce9a06
DS
9670 continue;
9671 }
a4d82a8a 9672 if (type == bgp_show_type_community_list_exact) {
98ce9a06 9673 struct community_list *list = output_arg;
d62a17ae 9674
98ce9a06 9675 if (!community_list_exact_match(
40381db7 9676 pi->attr->community, list))
98ce9a06
DS
9677 continue;
9678 }
9679 if (type == bgp_show_type_lcommunity) {
9680 struct lcommunity *lcom = output_arg;
d62a17ae 9681
40381db7
DS
9682 if (!pi->attr->lcommunity
9683 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
9684 lcom))
9685 continue;
9686 }
36a206db 9687
9688 if (type == bgp_show_type_lcommunity_exact) {
9689 struct lcommunity *lcom = output_arg;
9690
9691 if (!pi->attr->lcommunity
9692 || !lcommunity_cmp(pi->attr->lcommunity,
9693 lcom))
9694 continue;
9695 }
98ce9a06
DS
9696 if (type == bgp_show_type_lcommunity_list) {
9697 struct community_list *list = output_arg;
d62a17ae 9698
40381db7 9699 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 9700 list))
98ce9a06
DS
9701 continue;
9702 }
36a206db 9703 if (type
9704 == bgp_show_type_lcommunity_list_exact) {
9705 struct community_list *list = output_arg;
9706
9707 if (!lcommunity_list_exact_match(
9708 pi->attr->lcommunity, list))
9709 continue;
9710 }
98ce9a06 9711 if (type == bgp_show_type_lcommunity_all) {
40381db7 9712 if (!pi->attr->lcommunity)
98ce9a06
DS
9713 continue;
9714 }
9715 if (type == bgp_show_type_dampend_paths
9716 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
9717 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
9718 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
9719 continue;
9720 }
9721
9722 if (!use_json && header) {
996c9314 9723 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 9724 ", local router ID is %s, vrf id ",
98ce9a06
DS
9725 table->version,
9726 inet_ntoa(bgp->router_id));
9df8b37c
PZ
9727 if (bgp->vrf_id == VRF_UNKNOWN)
9728 vty_out(vty, "%s", VRFID_NONE_STR);
9729 else
9730 vty_out(vty, "%u", bgp->vrf_id);
9731 vty_out(vty, "\n");
01eced22
AD
9732 vty_out(vty, "Default local pref %u, ",
9733 bgp->default_local_pref);
9734 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 9735 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 9736 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 9737 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 9738 if (type == bgp_show_type_dampend_paths
9739 || type == bgp_show_type_damp_neighbor)
98ce9a06 9740 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
9741 else if (type == bgp_show_type_flap_statistics
9742 || type == bgp_show_type_flap_neighbor)
98ce9a06 9743 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 9744 else
98ce9a06
DS
9745 vty_out(vty, BGP_SHOW_HEADER);
9746 header = 0;
d62a17ae 9747 }
98ce9a06
DS
9748 if (rd != NULL && !display && !output_count) {
9749 if (!use_json)
9750 vty_out(vty,
9751 "Route Distinguisher: %s\n",
9752 rd);
d62a17ae 9753 }
98ce9a06
DS
9754 if (type == bgp_show_type_dampend_paths
9755 || type == bgp_show_type_damp_neighbor)
b54892e0
DS
9756 damp_route_vty_out(vty, rn_p, pi, display,
9757 AFI_IP, safi, use_json,
9758 json_paths);
98ce9a06
DS
9759 else if (type == bgp_show_type_flap_statistics
9760 || type == bgp_show_type_flap_neighbor)
b54892e0
DS
9761 flap_route_vty_out(vty, rn_p, pi, display,
9762 AFI_IP, safi, use_json,
9763 json_paths);
98ce9a06 9764 else
b54892e0 9765 route_vty_out(vty, rn_p, pi, display, safi,
a4d82a8a 9766 json_paths);
98ce9a06 9767 display++;
d62a17ae 9768 }
9769
98ce9a06
DS
9770 if (display) {
9771 output_count++;
9772 if (!use_json)
9773 continue;
9774
625d2931 9775 /* encode prefix */
b54892e0 9776 if (rn_p->family == AF_FLOWSPEC) {
625d2931
PG
9777 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
9778
b54892e0
DS
9779 bgp_fs_nlri_get_string(
9780 (unsigned char *)
9781 rn_p->u.prefix_flowspec.ptr,
9782 rn_p->u.prefix_flowspec.prefixlen,
9783 retstr, NLRI_STRING_FORMAT_MIN, NULL);
625d2931 9784 if (first)
b54892e0
DS
9785 vty_out(vty, "\"%s/%d\": ", retstr,
9786 rn_p->u.prefix_flowspec
9787 .prefixlen);
625d2931 9788 else
b54892e0
DS
9789 vty_out(vty, ",\"%s/%d\": ", retstr,
9790 rn_p->u.prefix_flowspec
9791 .prefixlen);
625d2931 9792 } else {
b54892e0 9793 prefix2str(rn_p, buf2, sizeof(buf2));
625d2931
PG
9794 if (first)
9795 vty_out(vty, "\"%s\": ", buf2);
9796 else
9797 vty_out(vty, ",\"%s\": ", buf2);
9798 }
98ce9a06 9799 vty_out(vty, "%s",
f4ec52f7
DA
9800 json_object_to_json_string_ext(
9801 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 9802 json_object_free(json_paths);
449feb8e 9803 json_paths = NULL;
98ce9a06 9804 first = 0;
1f83ed02
DS
9805 } else
9806 json_object_free(json_paths);
98ce9a06
DS
9807 }
9808
1ae44dfc
LB
9809 if (output_cum) {
9810 output_count += *output_cum;
9811 *output_cum = output_count;
9812 }
9813 if (total_cum) {
9814 total_count += *total_cum;
9815 *total_cum = total_count;
9816 }
d62a17ae 9817 if (use_json) {
9386b588 9818 if (rd) {
a4d82a8a 9819 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
9820 }
9821 if (is_last) {
a4d82a8a
PZ
9822 unsigned long i;
9823 for (i = 0; i < *json_header_depth; ++i)
9824 vty_out(vty, " } ");
faf6559a 9825 vty_out(vty, "\n");
9386b588 9826 }
d62a17ae 9827 } else {
1ae44dfc
LB
9828 if (is_last) {
9829 /* No route is displayed */
9830 if (output_count == 0) {
9831 if (type == bgp_show_type_normal)
9832 vty_out(vty,
9833 "No BGP prefixes displayed, %ld exist\n",
9834 total_count);
9835 } else
d62a17ae 9836 vty_out(vty,
1ae44dfc
LB
9837 "\nDisplayed %ld routes and %ld total paths\n",
9838 output_count, total_count);
9839 }
d62a17ae 9840 }
718e3744 9841
d62a17ae 9842 return CMD_SUCCESS;
718e3744 9843}
9844
1ae44dfc
LB
9845int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
9846 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 9847 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc
LB
9848{
9849 struct bgp_node *rn, *next;
9850 unsigned long output_cum = 0;
9851 unsigned long total_cum = 0;
9386b588 9852 unsigned long json_header_depth = 0;
67009e22 9853 struct bgp_table *itable;
0136788c
LB
9854 bool show_msg;
9855
9856 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc
LB
9857
9858 for (rn = bgp_table_top(table); rn; rn = next) {
b54892e0
DS
9859 const struct prefix *rn_p = bgp_node_get_prefix(rn);
9860
1ae44dfc 9861 next = bgp_route_next(rn);
b54892e0 9862 if (prd_match && memcmp(rn_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 9863 continue;
67009e22
DS
9864
9865 itable = bgp_node_get_bgp_table_info(rn);
9866 if (itable != NULL) {
1ae44dfc 9867 struct prefix_rd prd;
06b9f471 9868 char rd[RD_ADDRSTRLEN];
1ae44dfc 9869
b54892e0 9870 memcpy(&prd, rn_p, sizeof(struct prefix_rd));
06b9f471 9871 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22
DS
9872 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
9873 use_json, rd, next == NULL, &output_cum,
9874 &total_cum, &json_header_depth);
0136788c
LB
9875 if (next == NULL)
9876 show_msg = false;
1ae44dfc
LB
9877 }
9878 }
0136788c
LB
9879 if (show_msg) {
9880 if (output_cum == 0)
9881 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
9882 total_cum);
9883 else
9884 vty_out(vty,
9885 "\nDisplayed %ld routes and %ld total paths\n",
9886 output_cum, total_cum);
9887 }
1ae44dfc
LB
9888 return CMD_SUCCESS;
9889}
d62a17ae 9890static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
9f049418 9891 enum bgp_show_type type, void *output_arg, bool use_json)
fee0f4c6 9892{
d62a17ae 9893 struct bgp_table *table;
9386b588 9894 unsigned long json_header_depth = 0;
fee0f4c6 9895
d62a17ae 9896 if (bgp == NULL) {
9897 bgp = bgp_get_default();
9898 }
fee0f4c6 9899
d62a17ae 9900 if (bgp == NULL) {
9901 if (!use_json)
9902 vty_out(vty, "No BGP process is configured\n");
16307668
RW
9903 else
9904 vty_out(vty, "{}\n");
d62a17ae 9905 return CMD_WARNING;
9906 }
4dd6177e 9907
1ae44dfc 9908 table = bgp->rib[afi][safi];
d62a17ae 9909 /* use MPLS and ENCAP specific shows until they are merged */
9910 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
9911 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
9912 output_arg, use_json);
d62a17ae 9913 }
dba3c1d3
PG
9914
9915 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
9916 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
9917 output_arg, use_json,
9918 1, NULL, NULL);
9919 }
d62a17ae 9920 /* labeled-unicast routes live in the unicast table */
9921 else if (safi == SAFI_LABELED_UNICAST)
9922 safi = SAFI_UNICAST;
fee0f4c6 9923
1ae44dfc 9924 return bgp_show_table(vty, bgp, safi, table, type, output_arg, use_json,
9386b588 9925 NULL, 1, NULL, NULL, &json_header_depth);
fee0f4c6 9926}
9927
d62a17ae 9928static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
9f049418 9929 safi_t safi, bool use_json)
f186de26 9930{
d62a17ae 9931 struct listnode *node, *nnode;
9932 struct bgp *bgp;
9933 int is_first = 1;
9f049418 9934 bool route_output = false;
f186de26 9935
d62a17ae 9936 if (use_json)
9937 vty_out(vty, "{\n");
9f689658 9938
d62a17ae 9939 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 9940 route_output = true;
d62a17ae 9941 if (use_json) {
9942 if (!is_first)
9943 vty_out(vty, ",\n");
9944 else
9945 is_first = 0;
9946
9947 vty_out(vty, "\"%s\":",
9948 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 9949 ? VRF_DEFAULT_NAME
d62a17ae 9950 : bgp->name);
9951 } else {
9952 vty_out(vty, "\nInstance %s:\n",
9953 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 9954 ? VRF_DEFAULT_NAME
d62a17ae 9955 : bgp->name);
9956 }
9957 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
9958 use_json);
9959 }
9f689658 9960
d62a17ae 9961 if (use_json)
9962 vty_out(vty, "}\n");
9f049418
DS
9963 else if (!route_output)
9964 vty_out(vty, "%% BGP instance not found\n");
f186de26 9965}
9966
718e3744 9967/* Header of detailed BGP route information */
d62a17ae 9968void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9969 struct bgp_node *rn, struct prefix_rd *prd,
9970 afi_t afi, safi_t safi, json_object *json)
9971{
40381db7 9972 struct bgp_path_info *pi;
b54892e0 9973 const struct prefix *p;
d62a17ae 9974 struct peer *peer;
9975 struct listnode *node, *nnode;
06b9f471 9976 char buf1[RD_ADDRSTRLEN];
d62a17ae 9977 char buf2[INET6_ADDRSTRLEN];
d62a17ae 9978 char buf3[EVPN_ROUTE_STRLEN];
0291c246 9979 char prefix_str[BUFSIZ];
d62a17ae 9980 int count = 0;
9981 int best = 0;
9982 int suppress = 0;
c5f1e1b2
C
9983 int accept_own = 0;
9984 int route_filter_translated_v4 = 0;
9985 int route_filter_v4 = 0;
9986 int route_filter_translated_v6 = 0;
9987 int route_filter_v6 = 0;
9988 int llgr_stale = 0;
9989 int no_llgr = 0;
9990 int accept_own_nexthop = 0;
9991 int blackhole = 0;
d62a17ae 9992 int no_export = 0;
9993 int no_advertise = 0;
9994 int local_as = 0;
c5f1e1b2 9995 int no_peer = 0;
d62a17ae 9996 int first = 1;
9997 int has_valid_label = 0;
9998 mpls_label_t label = 0;
9999 json_object *json_adv_to = NULL;
9bedbb1e 10000
b54892e0 10001 p = bgp_node_get_prefix(rn);
d62a17ae 10002 has_valid_label = bgp_is_valid_label(&rn->local_label);
10003
10004 if (has_valid_label)
10005 label = label_pton(&rn->local_label);
10006
44c69747 10007 if (safi == SAFI_EVPN) {
d62a17ae 10008
44c69747 10009 if (!json) {
d62a17ae 10010 vty_out(vty, "BGP routing table entry for %s%s%s\n",
06b9f471 10011 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
44c69747 10012 : "", prd ? ":" : "",
d62a17ae 10013 bgp_evpn_route2str((struct prefix_evpn *)p,
44c69747
LK
10014 buf3, sizeof(buf3)));
10015 } else {
10016 json_object_string_add(json, "rd",
10017 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
10018 "");
10019 bgp_evpn_route2json((struct prefix_evpn *)p, json);
10020 }
10021 } else {
10022 if (!json) {
d62a17ae 10023 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
10024 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
44c69747
LK
10025 ? prefix_rd2str(prd, buf1,
10026 sizeof(buf1))
10027 : ""),
d62a17ae 10028 safi == SAFI_MPLS_VPN ? ":" : "",
10029 inet_ntop(p->family, &p->u.prefix, buf2,
44c69747 10030 INET6_ADDRSTRLEN),
d62a17ae 10031 p->prefixlen);
cd1964ff 10032
44c69747
LK
10033 } else
10034 json_object_string_add(json, "prefix",
10035 prefix2str(p, prefix_str, sizeof(prefix_str)));
10036 }
10037
10038 if (has_valid_label) {
10039 if (json)
10040 json_object_int_add(json, "localLabel", label);
10041 else
d62a17ae 10042 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
10043 }
10044
10045 if (!json)
d62a17ae 10046 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 10047 vty_out(vty, "not allocated\n");
718e3744 10048
6f94b685 10049 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
d62a17ae 10050 count++;
40381db7 10051 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 10052 best = count;
40381db7 10053 if (pi->extra && pi->extra->suppress)
d62a17ae 10054 suppress = 1;
cee9c031 10055
40381db7 10056 if (pi->attr->community == NULL)
cee9c031
QY
10057 continue;
10058
10059 no_advertise += community_include(
40381db7
DS
10060 pi->attr->community, COMMUNITY_NO_ADVERTISE);
10061 no_export += community_include(pi->attr->community,
cee9c031 10062 COMMUNITY_NO_EXPORT);
40381db7 10063 local_as += community_include(pi->attr->community,
cee9c031 10064 COMMUNITY_LOCAL_AS);
40381db7 10065 accept_own += community_include(pi->attr->community,
cee9c031
QY
10066 COMMUNITY_ACCEPT_OWN);
10067 route_filter_translated_v4 += community_include(
40381db7 10068 pi->attr->community,
cee9c031
QY
10069 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
10070 route_filter_translated_v6 += community_include(
40381db7 10071 pi->attr->community,
cee9c031
QY
10072 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
10073 route_filter_v4 += community_include(
40381db7 10074 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 10075 route_filter_v6 += community_include(
40381db7
DS
10076 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
10077 llgr_stale += community_include(pi->attr->community,
cee9c031 10078 COMMUNITY_LLGR_STALE);
40381db7 10079 no_llgr += community_include(pi->attr->community,
cee9c031
QY
10080 COMMUNITY_NO_LLGR);
10081 accept_own_nexthop +=
40381db7 10082 community_include(pi->attr->community,
cee9c031 10083 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 10084 blackhole += community_include(pi->attr->community,
cee9c031 10085 COMMUNITY_BLACKHOLE);
40381db7 10086 no_peer += community_include(pi->attr->community,
cee9c031 10087 COMMUNITY_NO_PEER);
d62a17ae 10088 }
718e3744 10089 }
718e3744 10090
d62a17ae 10091 if (!json) {
10092 vty_out(vty, "Paths: (%d available", count);
10093 if (best) {
10094 vty_out(vty, ", best #%d", best);
b84060bb
PG
10095 if (safi == SAFI_UNICAST) {
10096 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
10097 vty_out(vty, ", table %s",
10098 VRF_DEFAULT_NAME);
10099 else
10100 vty_out(vty, ", vrf %s",
10101 bgp->name);
10102 }
d62a17ae 10103 } else
10104 vty_out(vty, ", no best path");
10105
c5f1e1b2
C
10106 if (accept_own)
10107 vty_out(vty,
10108 ", accept own local route exported and imported in different VRF");
10109 else if (route_filter_translated_v4)
10110 vty_out(vty,
10111 ", mark translated RTs for VPNv4 route filtering");
10112 else if (route_filter_v4)
10113 vty_out(vty,
10114 ", attach RT as-is for VPNv4 route filtering");
10115 else if (route_filter_translated_v6)
10116 vty_out(vty,
10117 ", mark translated RTs for VPNv6 route filtering");
10118 else if (route_filter_v6)
10119 vty_out(vty,
10120 ", attach RT as-is for VPNv6 route filtering");
10121 else if (llgr_stale)
10122 vty_out(vty,
10123 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
10124 else if (no_llgr)
10125 vty_out(vty,
10126 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
10127 else if (accept_own_nexthop)
10128 vty_out(vty,
10129 ", accept local nexthop");
10130 else if (blackhole)
10131 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 10132 else if (no_export)
10133 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
10134 else if (no_advertise)
10135 vty_out(vty, ", not advertised to any peer");
d62a17ae 10136 else if (local_as)
10137 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
10138 else if (no_peer)
10139 vty_out(vty,
10140 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 10141
10142 if (suppress)
10143 vty_out(vty,
10144 ", Advertisements suppressed by an aggregate.");
10145 vty_out(vty, ")\n");
10146 }
718e3744 10147
d62a17ae 10148 /* If we are not using addpath then we can display Advertised to and
10149 * that will
10150 * show what peers we advertised the bestpath to. If we are using
10151 * addpath
10152 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 10153 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 10154 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10155 if (bgp_adj_out_lookup(peer, rn, 0)) {
10156 if (json && !json_adv_to)
10157 json_adv_to = json_object_new_object();
10158
10159 route_vty_out_advertised_to(
10160 vty, peer, &first,
10161 " Advertised to non peer-group peers:\n ",
10162 json_adv_to);
10163 }
10164 }
10165
10166 if (json) {
10167 if (json_adv_to) {
10168 json_object_object_add(json, "advertisedTo",
10169 json_adv_to);
10170 }
10171 } else {
10172 if (first)
10173 vty_out(vty, " Not advertised to any peer");
10174 vty_out(vty, "\n");
10175 }
10176 }
718e3744 10177}
10178
44c69747
LK
10179static void bgp_show_path_info(struct prefix_rd *pfx_rd,
10180 struct bgp_node *bgp_node, struct vty *vty,
10181 struct bgp *bgp, afi_t afi,
10182 safi_t safi, json_object *json,
10183 enum bgp_path_type pathtype, int *display)
10184{
10185 struct bgp_path_info *pi;
10186 int header = 1;
10187 char rdbuf[RD_ADDRSTRLEN];
10188 json_object *json_header = NULL;
10189 json_object *json_paths = NULL;
10190
10191 for (pi = bgp_node_get_bgp_path_info(bgp_node); pi;
10192 pi = pi->next) {
10193
10194 if (json && !json_paths) {
10195 /* Instantiate json_paths only if path is valid */
10196 json_paths = json_object_new_array();
10197 if (pfx_rd) {
10198 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
10199 json_header = json_object_new_object();
10200 } else
10201 json_header = json;
10202 }
10203
10204 if (header) {
10205 route_vty_out_detail_header(
10206 vty, bgp, bgp_node, pfx_rd,
10207 AFI_IP, safi, json_header);
10208 header = 0;
10209 }
10210 (*display)++;
10211
10212 if (pathtype == BGP_PATH_SHOW_ALL
10213 || (pathtype == BGP_PATH_SHOW_BESTPATH
10214 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
10215 || (pathtype == BGP_PATH_SHOW_MULTIPATH
10216 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
10217 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
10218 route_vty_out_detail(vty, bgp, bgp_node,
10219 pi, AFI_IP, safi,
10220 json_paths);
10221 }
10222
10223 if (json && json_paths) {
10224 json_object_object_add(json_header, "paths", json_paths);
10225
10226 if (pfx_rd)
10227 json_object_object_add(json, rdbuf, json_header);
10228 }
10229}
10230
718e3744 10231/* Display specified route of BGP table. */
d62a17ae 10232static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
10233 struct bgp_table *rib, const char *ip_str,
10234 afi_t afi, safi_t safi,
10235 struct prefix_rd *prd, int prefix_check,
9f049418 10236 enum bgp_path_type pathtype, bool use_json)
d62a17ae 10237{
10238 int ret;
d62a17ae 10239 int display = 0;
10240 struct prefix match;
10241 struct bgp_node *rn;
10242 struct bgp_node *rm;
d62a17ae 10243 struct bgp_table *table;
10244 json_object *json = NULL;
10245 json_object *json_paths = NULL;
10246
10247 /* Check IP address argument. */
10248 ret = str2prefix(ip_str, &match);
10249 if (!ret) {
10250 vty_out(vty, "address is malformed\n");
10251 return CMD_WARNING;
10252 }
718e3744 10253
d62a17ae 10254 match.family = afi2family(afi);
b05a1c8b 10255
44c69747 10256 if (use_json)
d62a17ae 10257 json = json_object_new_object();
718e3744 10258
44c69747 10259 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
d62a17ae 10260 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
b54892e0
DS
10261 const struct prefix *rn_p = bgp_node_get_prefix(rn);
10262
10263 if (prd && memcmp(rn_p->u.val, prd->val, 8) != 0)
d62a17ae 10264 continue;
67009e22
DS
10265 table = bgp_node_get_bgp_table_info(rn);
10266 if (!table)
ea47320b 10267 continue;
d62a17ae 10268
ea47320b
DL
10269 if ((rm = bgp_node_match(table, &match)) == NULL)
10270 continue;
d62a17ae 10271
b54892e0 10272 const struct prefix *rm_p = bgp_node_get_prefix(rm);
ea47320b 10273 if (prefix_check
b54892e0 10274 && rm_p->prefixlen != match.prefixlen) {
ea47320b
DL
10275 bgp_unlock_node(rm);
10276 continue;
10277 }
d62a17ae 10278
b54892e0
DS
10279 bgp_show_path_info((struct prefix_rd *)rn_p, rm, vty,
10280 bgp, afi, safi, json, pathtype,
10281 &display);
44c69747
LK
10282
10283 bgp_unlock_node(rm);
10284 }
10285 } else if (safi == SAFI_EVPN) {
10286 struct bgp_node *longest_pfx;
cded3b72 10287 bool is_exact_pfxlen_match = false;
44c69747
LK
10288
10289 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
b54892e0
DS
10290 const struct prefix *rn_p = bgp_node_get_prefix(rn);
10291
10292 if (prd && memcmp(&rn_p->u.val, prd->val, 8) != 0)
44c69747
LK
10293 continue;
10294 table = bgp_node_get_bgp_table_info(rn);
10295 if (!table)
10296 continue;
10297
10298 longest_pfx = NULL;
cded3b72 10299 is_exact_pfxlen_match = false;
44c69747
LK
10300 /*
10301 * Search through all the prefixes for a match. The
10302 * pfx's are enumerated in ascending order of pfxlens.
10303 * So, the last pfx match is the longest match. Set
10304 * is_exact_pfxlen_match when we get exact pfxlen match
10305 */
10306 for (rm = bgp_table_top(table); rm;
10307 rm = bgp_route_next(rm)) {
b54892e0
DS
10308 const struct prefix *rm_p =
10309 bgp_node_get_prefix(rm);
44c69747
LK
10310 /*
10311 * Get prefixlen of the ip-prefix within type5
10312 * evpn route
10313 */
b54892e0
DS
10314 if (evpn_type5_prefix_match(rm_p, &match)
10315 && rm->info) {
44c69747
LK
10316 longest_pfx = rm;
10317 int type5_pfxlen =
b54892e0
DS
10318 bgp_evpn_get_type5_prefixlen(
10319 rm_p);
44c69747 10320 if (type5_pfxlen == match.prefixlen) {
cded3b72 10321 is_exact_pfxlen_match = true;
44c69747
LK
10322 bgp_unlock_node(rm);
10323 break;
10324 }
d62a17ae 10325 }
10326 }
ea47320b 10327
44c69747
LK
10328 if (!longest_pfx)
10329 continue;
10330
10331 if (prefix_check && !is_exact_pfxlen_match)
10332 continue;
10333
10334 rm = longest_pfx;
10335 bgp_lock_node(rm);
10336
b54892e0
DS
10337 bgp_show_path_info((struct prefix_rd *)rn_p, rm, vty,
10338 bgp, afi, safi, json, pathtype,
10339 &display);
44c69747 10340
ea47320b 10341 bgp_unlock_node(rm);
d62a17ae 10342 }
98a9dbc7 10343 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
10344 if (use_json)
10345 json_paths = json_object_new_array();
10346
63a0b7a9
PG
10347 display = bgp_flowspec_display_match_per_ip(afi, rib,
10348 &match, prefix_check,
10349 vty,
10350 use_json,
10351 json_paths);
44c69747
LK
10352 if (use_json && display)
10353 json_object_object_add(json, "paths", json_paths);
d62a17ae 10354 } else {
d62a17ae 10355 if ((rn = bgp_node_match(rib, &match)) != NULL) {
b54892e0 10356 const struct prefix *rn_p = bgp_node_get_prefix(rn);
d62a17ae 10357 if (!prefix_check
b54892e0 10358 || rn_p->prefixlen == match.prefixlen) {
44c69747
LK
10359 bgp_show_path_info(NULL, rn, vty, bgp, afi,
10360 safi, json,
10361 pathtype, &display);
d62a17ae 10362 }
10363
10364 bgp_unlock_node(rn);
10365 }
10366 }
e5eee9af 10367
d62a17ae 10368 if (use_json) {
996c9314 10369 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
10370 json, JSON_C_TO_STRING_PRETTY |
10371 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 10372 json_object_free(json);
10373 } else {
10374 if (!display) {
10375 vty_out(vty, "%% Network not in table\n");
10376 return CMD_WARNING;
10377 }
10378 }
b05a1c8b 10379
d62a17ae 10380 return CMD_SUCCESS;
718e3744 10381}
10382
fee0f4c6 10383/* Display specified route of Main RIB */
d62a17ae 10384static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
10385 afi_t afi, safi_t safi, struct prefix_rd *prd,
10386 int prefix_check, enum bgp_path_type pathtype,
9f049418 10387 bool use_json)
d62a17ae 10388{
9b86009a 10389 if (!bgp) {
d62a17ae 10390 bgp = bgp_get_default();
9b86009a
RW
10391 if (!bgp) {
10392 if (!use_json)
10393 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10394 else
10395 vty_out(vty, "{}\n");
9b86009a
RW
10396 return CMD_WARNING;
10397 }
10398 }
d62a17ae 10399
10400 /* labeled-unicast routes live in the unicast table */
10401 if (safi == SAFI_LABELED_UNICAST)
10402 safi = SAFI_UNICAST;
10403
10404 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
10405 afi, safi, prd, prefix_check, pathtype,
10406 use_json);
10407}
10408
10409static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 10410 struct cmd_token **argv, bool exact, afi_t afi,
10411 safi_t safi, bool uj)
d62a17ae 10412{
10413 struct lcommunity *lcom;
10414 struct buffer *b;
10415 int i;
10416 char *str;
10417 int first = 0;
10418
10419 b = buffer_new(1024);
10420 for (i = 0; i < argc; i++) {
10421 if (first)
10422 buffer_putc(b, ' ');
10423 else {
10424 if (strmatch(argv[i]->text, "AA:BB:CC")) {
10425 first = 1;
10426 buffer_putstr(b, argv[i]->arg);
10427 }
10428 }
10429 }
10430 buffer_putc(b, '\0');
57d187bc 10431
d62a17ae 10432 str = buffer_getstr(b);
10433 buffer_free(b);
57d187bc 10434
d62a17ae 10435 lcom = lcommunity_str2com(str);
10436 XFREE(MTYPE_TMP, str);
10437 if (!lcom) {
10438 vty_out(vty, "%% Large-community malformed\n");
10439 return CMD_WARNING;
10440 }
57d187bc 10441
36a206db 10442 return bgp_show(vty, bgp, afi, safi,
10443 (exact ? bgp_show_type_lcommunity_exact
10444 : bgp_show_type_lcommunity),
10445 lcom, uj);
57d187bc
JS
10446}
10447
d62a17ae 10448static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 10449 const char *lcom, bool exact, afi_t afi,
10450 safi_t safi, bool uj)
57d187bc 10451{
d62a17ae 10452 struct community_list *list;
57d187bc 10453
e237b0d2 10454 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 10455 LARGE_COMMUNITY_LIST_MASTER);
10456 if (list == NULL) {
10457 vty_out(vty, "%% %s is not a valid large-community-list name\n",
10458 lcom);
10459 return CMD_WARNING;
10460 }
57d187bc 10461
36a206db 10462 return bgp_show(vty, bgp, afi, safi,
10463 (exact ? bgp_show_type_lcommunity_list_exact
10464 : bgp_show_type_lcommunity_list),
d62a17ae 10465 list, uj);
fee0f4c6 10466}
10467
52951b63
DS
10468DEFUN (show_ip_bgp_large_community_list,
10469 show_ip_bgp_large_community_list_cmd,
36a206db 10470 "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
10471 SHOW_STR
10472 IP_STR
10473 BGP_STR
10474 BGP_INSTANCE_HELP_STR
9bedbb1e 10475 BGP_AFI_HELP_STR
4dd6177e 10476 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10477 "Display routes matching the large-community-list\n"
10478 "large-community-list number\n"
10479 "large-community-list name\n"
36a206db 10480 "Exact match of the large-communities\n"
52951b63
DS
10481 JSON_STR)
10482{
d62a17ae 10483 afi_t afi = AFI_IP6;
10484 safi_t safi = SAFI_UNICAST;
10485 int idx = 0;
36a206db 10486 bool exact_match = 0;
4d678463 10487 struct bgp *bgp = NULL;
9f049418 10488 bool uj = use_json(argc, argv);
d62a17ae 10489
4d678463
KA
10490 if (uj)
10491 argc--;
10492
10493 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10494 &bgp, uj);
10495 if (!idx)
10496 return CMD_WARNING;
d62a17ae 10497
10498 argv_find(argv, argc, "large-community-list", &idx);
36a206db 10499
10500 const char *clist_number_or_name = argv[++idx]->arg;
10501
10502 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10503 exact_match = 1;
10504
10505 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
10506 exact_match, afi, safi, uj);
52951b63
DS
10507}
10508DEFUN (show_ip_bgp_large_community,
10509 show_ip_bgp_large_community_cmd,
36a206db 10510 "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
10511 SHOW_STR
10512 IP_STR
10513 BGP_STR
10514 BGP_INSTANCE_HELP_STR
9bedbb1e 10515 BGP_AFI_HELP_STR
4dd6177e 10516 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10517 "Display routes matching the large-communities\n"
10518 "List of large-community numbers\n"
36a206db 10519 "Exact match of the large-communities\n"
52951b63
DS
10520 JSON_STR)
10521{
d62a17ae 10522 afi_t afi = AFI_IP6;
10523 safi_t safi = SAFI_UNICAST;
10524 int idx = 0;
36a206db 10525 bool exact_match = 0;
4d678463 10526 struct bgp *bgp = NULL;
9f049418 10527 bool uj = use_json(argc, argv);
d62a17ae 10528
4d678463
KA
10529 if (uj)
10530 argc--;
10531
10532 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10533 &bgp, uj);
10534 if (!idx)
10535 return CMD_WARNING;
d62a17ae 10536
36a206db 10537 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
10538 if (argv_find(argv, argc, "exact-match", &idx))
10539 exact_match = 1;
10540 return bgp_show_lcommunity(vty, bgp, argc, argv,
10541 exact_match, afi, safi, uj);
10542 } else
d62a17ae 10543 return bgp_show(vty, bgp, afi, safi,
10544 bgp_show_type_lcommunity_all, NULL, uj);
52951b63
DS
10545}
10546
d62a17ae 10547static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
10548 safi_t safi);
e01ca200 10549
7b2ff250
DW
10550
10551/* BGP route print out function without JSON */
af462945
DS
10552DEFUN (show_ip_bgp,
10553 show_ip_bgp_cmd,
4dd6177e 10554 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
7b2ff250
DW
10555 <dampening <parameters>\
10556 |route-map WORD\
10557 |prefix-list WORD\
10558 |filter-list WORD\
10559 |statistics\
7b2ff250
DW
10560 |community-list <(1-500)|WORD> [exact-match]\
10561 |A.B.C.D/M longer-prefixes\
10562 |X:X::X:X/M longer-prefixes\
10563 >",
718e3744 10564 SHOW_STR
10565 IP_STR
10566 BGP_STR
a636c635 10567 BGP_INSTANCE_HELP_STR
4f280b15 10568 BGP_AFI_HELP_STR
4dd6177e 10569 BGP_SAFI_WITH_LABEL_HELP_STR
a636c635 10570 "Display detailed information about dampening\n"
af462945 10571 "Display detail of configured dampening parameters\n"
a636c635
DW
10572 "Display routes matching the route-map\n"
10573 "A route-map to match on\n"
10574 "Display routes conforming to the prefix-list\n"
8c3deaae 10575 "Prefix-list name\n"
a636c635
DW
10576 "Display routes conforming to the filter-list\n"
10577 "Regular expression access list name\n"
e01ca200 10578 "BGP RIB advertisement statistics\n"
a636c635
DW
10579 "Display routes matching the community-list\n"
10580 "community-list number\n"
10581 "community-list name\n"
10582 "Exact match of the communities\n"
0c7b1b01 10583 "IPv4 prefix\n"
8c3deaae 10584 "Display route and more specific routes\n"
0c7b1b01 10585 "IPv6 prefix\n"
7b2ff250 10586 "Display route and more specific routes\n")
718e3744 10587{
d62a17ae 10588 afi_t afi = AFI_IP6;
10589 safi_t safi = SAFI_UNICAST;
10590 int exact_match = 0;
d62a17ae 10591 struct bgp *bgp = NULL;
10592 int idx = 0;
10593
10594 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10595 &bgp, false);
d62a17ae 10596 if (!idx)
10597 return CMD_WARNING;
10598
d62a17ae 10599 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 10600 if (argv_find(argv, argc, "parameters", &idx))
d62a17ae 10601 return bgp_show_dampening_parameters(vty, afi, safi);
10602 }
c016b6c7 10603
d62a17ae 10604 if (argv_find(argv, argc, "prefix-list", &idx))
10605 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
10606 safi, bgp_show_type_prefix_list);
10607
10608 if (argv_find(argv, argc, "filter-list", &idx))
10609 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
10610 safi, bgp_show_type_filter_list);
10611
10612 if (argv_find(argv, argc, "statistics", &idx))
10613 return bgp_table_stats(vty, bgp, afi, safi);
10614
10615 if (argv_find(argv, argc, "route-map", &idx))
10616 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
10617 safi, bgp_show_type_route_map);
10618
d62a17ae 10619 if (argv_find(argv, argc, "community-list", &idx)) {
10620 const char *clist_number_or_name = argv[++idx]->arg;
10621 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10622 exact_match = 1;
10623 return bgp_show_community_list(vty, bgp, clist_number_or_name,
10624 exact_match, afi, safi);
10625 }
10626 /* prefix-longer */
10627 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10628 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10629 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
10630 safi,
10631 bgp_show_type_prefix_longer);
10632
7b2ff250
DW
10633 return CMD_WARNING;
10634}
10635
10636/* BGP route print out function with JSON */
10637DEFUN (show_ip_bgp_json,
10638 show_ip_bgp_json_cmd,
10639 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
cf4898bc
QY
10640 [cidr-only\
10641 |dampening <flap-statistics|dampened-paths>\
10642 |community [AA:NN|local-AS|no-advertise|no-export\
10643 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10644 |accept-own|accept-own-nexthop|route-filter-v6\
10645 |route-filter-v4|route-filter-translated-v6\
10646 |route-filter-translated-v4] [exact-match]\
10647 ] [json]",
7b2ff250
DW
10648 SHOW_STR
10649 IP_STR
10650 BGP_STR
10651 BGP_INSTANCE_HELP_STR
10652 BGP_AFI_HELP_STR
10653 BGP_SAFI_WITH_LABEL_HELP_STR
10654 "Display only routes with non-natural netmasks\n"
10655 "Display detailed information about dampening\n"
10656 "Display flap statistics of routes\n"
10657 "Display paths suppressed due to dampening\n"
10658 "Display routes matching the communities\n"
d0086e8e
AD
10659 COMMUNITY_AANN_STR
10660 "Do not send outside local AS (well-known community)\n"
10661 "Do not advertise to any peer (well-known community)\n"
10662 "Do not export to next AS (well-known community)\n"
10663 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
10664 "Do not export to any peer (well-known community)\n"
10665 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10666 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10667 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10668 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10669 "Should accept VPN route with local nexthop (well-known community)\n"
10670 "RT VPNv6 route filtering (well-known community)\n"
10671 "RT VPNv4 route filtering (well-known community)\n"
10672 "RT translated VPNv6 route filtering (well-known community)\n"
10673 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 10674 "Exact match of the communities\n"
7b2ff250
DW
10675 JSON_STR)
10676{
10677 afi_t afi = AFI_IP6;
10678 safi_t safi = SAFI_UNICAST;
10679 enum bgp_show_type sh_type = bgp_show_type_normal;
10680 struct bgp *bgp = NULL;
10681 int idx = 0;
d0086e8e 10682 int exact_match = 0;
9f049418
DS
10683 bool uj = use_json(argc, argv);
10684
10685 if (uj)
10686 argc--;
7b2ff250
DW
10687
10688 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10689 &bgp, uj);
7b2ff250
DW
10690 if (!idx)
10691 return CMD_WARNING;
10692
7b2ff250
DW
10693 if (argv_find(argv, argc, "cidr-only", &idx))
10694 return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
10695 NULL, uj);
10696
10697 if (argv_find(argv, argc, "dampening", &idx)) {
10698 if (argv_find(argv, argc, "dampened-paths", &idx))
10699 return bgp_show(vty, bgp, afi, safi,
10700 bgp_show_type_dampend_paths, NULL, uj);
10701 else if (argv_find(argv, argc, "flap-statistics", &idx))
10702 return bgp_show(vty, bgp, afi, safi,
10703 bgp_show_type_flap_statistics, NULL,
10704 uj);
10705 }
10706
10707 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 10708 char *maybecomm = NULL;
cf4898bc 10709 char *community = NULL;
d0086e8e 10710
79bc257a
RW
10711 if (idx + 1 < argc) {
10712 if (argv[idx + 1]->type == VARIABLE_TKN)
10713 maybecomm = argv[idx + 1]->arg;
10714 else
10715 maybecomm = argv[idx + 1]->text;
10716 }
10717
cf4898bc
QY
10718 if (maybecomm && !strmatch(maybecomm, "json")
10719 && !strmatch(maybecomm, "exact-match"))
10720 community = maybecomm;
d0086e8e 10721
cf4898bc
QY
10722 if (argv_find(argv, argc, "exact-match", &idx))
10723 exact_match = 1;
d0086e8e 10724
cf4898bc
QY
10725 if (community)
10726 return bgp_show_community(vty, bgp, community,
10727 exact_match, afi, safi, uj);
10728 else
d0086e8e 10729 return (bgp_show(vty, bgp, afi, safi,
cf4898bc
QY
10730 bgp_show_type_community_all, NULL,
10731 uj));
7b2ff250 10732 }
d0086e8e 10733
1ae44dfc 10734 return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj);
a636c635 10735}
47fc97cc 10736
718e3744 10737DEFUN (show_ip_bgp_route,
10738 show_ip_bgp_route_cmd,
4dd6177e 10739 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]"
ae19d7dd 10740 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
718e3744 10741 SHOW_STR
10742 IP_STR
10743 BGP_STR
a636c635 10744 BGP_INSTANCE_HELP_STR
4f280b15 10745 BGP_AFI_HELP_STR
4dd6177e 10746 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 10747 "Network in the BGP routing table to display\n"
0c7b1b01 10748 "IPv4 prefix\n"
8c3deaae 10749 "Network in the BGP routing table to display\n"
0c7b1b01 10750 "IPv6 prefix\n"
4092b06c 10751 "Display only the bestpath\n"
b05a1c8b 10752 "Display only multipaths\n"
9973d184 10753 JSON_STR)
4092b06c 10754{
d62a17ae 10755 int prefix_check = 0;
ae19d7dd 10756
d62a17ae 10757 afi_t afi = AFI_IP6;
10758 safi_t safi = SAFI_UNICAST;
10759 char *prefix = NULL;
10760 struct bgp *bgp = NULL;
10761 enum bgp_path_type path_type;
9f049418 10762 bool uj = use_json(argc, argv);
b05a1c8b 10763
d62a17ae 10764 int idx = 0;
ae19d7dd 10765
d62a17ae 10766 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10767 &bgp, uj);
d62a17ae 10768 if (!idx)
10769 return CMD_WARNING;
c41247f5 10770
d62a17ae 10771 if (!bgp) {
10772 vty_out(vty,
10773 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10774 return CMD_WARNING;
10775 }
a636c635 10776
d62a17ae 10777 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10778 if (argv_find(argv, argc, "A.B.C.D", &idx)
10779 || argv_find(argv, argc, "X:X::X:X", &idx))
10780 prefix_check = 0;
10781 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10782 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10783 prefix_check = 1;
10784
10785 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
10786 && afi != AFI_IP6) {
10787 vty_out(vty,
10788 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10789 return CMD_WARNING;
10790 }
10791 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
10792 && afi != AFI_IP) {
10793 vty_out(vty,
10794 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10795 return CMD_WARNING;
10796 }
10797
10798 prefix = argv[idx]->arg;
10799
10800 /* [<bestpath|multipath>] */
10801 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 10802 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 10803 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 10804 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 10805 else
360660c6 10806 path_type = BGP_PATH_SHOW_ALL;
a636c635 10807
d62a17ae 10808 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
10809 path_type, uj);
4092b06c
DS
10810}
10811
8c3deaae
QY
10812DEFUN (show_ip_bgp_regexp,
10813 show_ip_bgp_regexp_cmd,
3e5b31b3 10814 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
10815 SHOW_STR
10816 IP_STR
10817 BGP_STR
b00b230a 10818 BGP_INSTANCE_HELP_STR
4f280b15 10819 BGP_AFI_HELP_STR
4dd6177e 10820 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 10821 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
10822 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
10823 JSON_STR)
8c3deaae 10824{
d62a17ae 10825 afi_t afi = AFI_IP6;
10826 safi_t safi = SAFI_UNICAST;
10827 struct bgp *bgp = NULL;
3e5b31b3
DA
10828 bool uj = use_json(argc, argv);
10829 char *regstr = NULL;
8c3deaae 10830
d62a17ae 10831 int idx = 0;
10832 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10833 &bgp, false);
d62a17ae 10834 if (!idx)
10835 return CMD_WARNING;
8c3deaae 10836
d62a17ae 10837 // get index of regex
3e5b31b3
DA
10838 if (argv_find(argv, argc, "REGEX", &idx))
10839 regstr = argv[idx]->arg;
8c3deaae 10840
5f71d11c 10841 assert(regstr);
3e5b31b3
DA
10842 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
10843 bgp_show_type_regexp, uj);
8c3deaae
QY
10844}
10845
a636c635
DW
10846DEFUN (show_ip_bgp_instance_all,
10847 show_ip_bgp_instance_all_cmd,
4dd6177e 10848 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json]",
4092b06c 10849 SHOW_STR
a636c635 10850 IP_STR
4092b06c 10851 BGP_STR
a636c635 10852 BGP_INSTANCE_ALL_HELP_STR
4f280b15 10853 BGP_AFI_HELP_STR
4dd6177e 10854 BGP_SAFI_WITH_LABEL_HELP_STR
9973d184 10855 JSON_STR)
4092b06c 10856{
d62a17ae 10857 afi_t afi = AFI_IP;
10858 safi_t safi = SAFI_UNICAST;
10859 struct bgp *bgp = NULL;
d62a17ae 10860 int idx = 0;
9f049418 10861 bool uj = use_json(argc, argv);
ae19d7dd 10862
d62a17ae 10863 if (uj)
10864 argc--;
e3e29b32 10865
9f049418
DS
10866 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10867 &bgp, uj);
10868 if (!idx)
10869 return CMD_WARNING;
10870
d62a17ae 10871 bgp_show_all_instances_routes_vty(vty, afi, safi, uj);
10872 return CMD_SUCCESS;
e3e29b32
LB
10873}
10874
a4d82a8a 10875static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10876 afi_t afi, safi_t safi, enum bgp_show_type type,
10877 bool use_json)
718e3744 10878{
d62a17ae 10879 regex_t *regex;
10880 int rc;
e3e29b32 10881
c3900853 10882 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 10883 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
10884 regstr);
10885 return CMD_WARNING_CONFIG_FAILED;
10886 }
10887
d62a17ae 10888 regex = bgp_regcomp(regstr);
10889 if (!regex) {
10890 vty_out(vty, "Can't compile regexp %s\n", regstr);
10891 return CMD_WARNING;
10892 }
a636c635 10893
3e5b31b3 10894 rc = bgp_show(vty, bgp, afi, safi, type, regex, use_json);
d62a17ae 10895 bgp_regex_free(regex);
10896 return rc;
e3e29b32
LB
10897}
10898
d62a17ae 10899static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10900 const char *prefix_list_str, afi_t afi,
10901 safi_t safi, enum bgp_show_type type)
e3e29b32 10902{
d62a17ae 10903 struct prefix_list *plist;
718e3744 10904
d62a17ae 10905 plist = prefix_list_lookup(afi, prefix_list_str);
10906 if (plist == NULL) {
10907 vty_out(vty, "%% %s is not a valid prefix-list name\n",
10908 prefix_list_str);
10909 return CMD_WARNING;
10910 }
718e3744 10911
d62a17ae 10912 return bgp_show(vty, bgp, afi, safi, type, plist, 0);
4092b06c
DS
10913}
10914
d62a17ae 10915static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10916 const char *filter, afi_t afi, safi_t safi,
10917 enum bgp_show_type type)
4092b06c 10918{
d62a17ae 10919 struct as_list *as_list;
718e3744 10920
d62a17ae 10921 as_list = as_list_lookup(filter);
10922 if (as_list == NULL) {
10923 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
10924 filter);
10925 return CMD_WARNING;
10926 }
a636c635 10927
d62a17ae 10928 return bgp_show(vty, bgp, afi, safi, type, as_list, 0);
718e3744 10929}
10930
d62a17ae 10931static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10932 const char *rmap_str, afi_t afi, safi_t safi,
10933 enum bgp_show_type type)
718e3744 10934{
d62a17ae 10935 struct route_map *rmap;
bb46e94f 10936
d62a17ae 10937 rmap = route_map_lookup_by_name(rmap_str);
10938 if (!rmap) {
10939 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
10940 return CMD_WARNING;
10941 }
10942
10943 return bgp_show(vty, bgp, afi, safi, type, rmap, 0);
10944}
10945
7f323236
DW
10946static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10947 const char *comstr, int exact, afi_t afi,
9f049418 10948 safi_t safi, bool use_json)
d62a17ae 10949{
10950 struct community *com;
d62a17ae 10951 int ret = 0;
10952
7f323236 10953 com = community_str2com(comstr);
d62a17ae 10954 if (!com) {
7f323236 10955 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 10956 return CMD_WARNING;
10957 }
10958
10959 ret = bgp_show(vty, bgp, afi, safi,
10960 (exact ? bgp_show_type_community_exact
10961 : bgp_show_type_community),
d0086e8e 10962 com, use_json);
3c1f53de 10963 community_free(&com);
46c3ce83 10964
d62a17ae 10965 return ret;
718e3744 10966}
10967
d62a17ae 10968static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10969 const char *com, int exact, afi_t afi,
10970 safi_t safi)
50ef26d4 10971{
d62a17ae 10972 struct community_list *list;
50ef26d4 10973
e237b0d2 10974 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 10975 if (list == NULL) {
10976 vty_out(vty, "%% %s is not a valid community-list name\n", com);
10977 return CMD_WARNING;
10978 }
718e3744 10979
d62a17ae 10980 return bgp_show(vty, bgp, afi, safi,
10981 (exact ? bgp_show_type_community_list_exact
10982 : bgp_show_type_community_list),
10983 list, 0);
50ef26d4 10984}
10985
d62a17ae 10986static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10987 const char *prefix, afi_t afi, safi_t safi,
10988 enum bgp_show_type type)
718e3744 10989{
d62a17ae 10990 int ret;
10991 struct prefix *p;
47fc97cc 10992
d62a17ae 10993 p = prefix_new();
95cbbd2a 10994
d62a17ae 10995 ret = str2prefix(prefix, p);
10996 if (!ret) {
10997 vty_out(vty, "%% Malformed Prefix\n");
10998 return CMD_WARNING;
10999 }
47e9b292 11000
d62a17ae 11001 ret = bgp_show(vty, bgp, afi, safi, type, p, 0);
63265b5c 11002 prefix_free(&p);
d62a17ae 11003 return ret;
11004}
11005
d62a17ae 11006enum bgp_stats {
11007 BGP_STATS_MAXBITLEN = 0,
11008 BGP_STATS_RIB,
11009 BGP_STATS_PREFIXES,
11010 BGP_STATS_TOTPLEN,
11011 BGP_STATS_UNAGGREGATEABLE,
11012 BGP_STATS_MAX_AGGREGATEABLE,
11013 BGP_STATS_AGGREGATES,
11014 BGP_STATS_SPACE,
11015 BGP_STATS_ASPATH_COUNT,
11016 BGP_STATS_ASPATH_MAXHOPS,
11017 BGP_STATS_ASPATH_TOTHOPS,
11018 BGP_STATS_ASPATH_MAXSIZE,
11019 BGP_STATS_ASPATH_TOTSIZE,
11020 BGP_STATS_ASN_HIGHEST,
11021 BGP_STATS_MAX,
a636c635 11022};
2815e61f 11023
2b64873d 11024static const char *const table_stats_strs[] = {
9d303b37
DL
11025 [BGP_STATS_PREFIXES] = "Total Prefixes",
11026 [BGP_STATS_TOTPLEN] = "Average prefix length",
11027 [BGP_STATS_RIB] = "Total Advertisements",
11028 [BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes",
11029 [BGP_STATS_MAX_AGGREGATEABLE] =
11030 "Maximum aggregateable prefixes",
11031 [BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements",
11032 [BGP_STATS_SPACE] = "Address space advertised",
11033 [BGP_STATS_ASPATH_COUNT] = "Advertisements with paths",
11034 [BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)",
11035 [BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)",
11036 [BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)",
11037 [BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)",
11038 [BGP_STATS_ASN_HIGHEST] = "Highest public ASN",
11039 [BGP_STATS_MAX] = NULL,
a636c635 11040};
2815e61f 11041
d62a17ae 11042struct bgp_table_stats {
11043 struct bgp_table *table;
11044 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 11045 double total_space;
ff7924f6
PJ
11046};
11047
a636c635
DW
11048#if 0
11049#define TALLY_SIGFIG 100000
11050static unsigned long
11051ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 11052{
a636c635
DW
11053 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
11054 unsigned long res = (newtot * TALLY_SIGFIG) / count;
11055 unsigned long ret = newtot / count;
07d0c4ed 11056
a636c635
DW
11057 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
11058 return ret + 1;
11059 else
11060 return ret;
11061}
11062#endif
ff7924f6 11063
9c14ec72
RW
11064static void bgp_table_stats_rn(struct bgp_node *rn, struct bgp_node *top,
11065 struct bgp_table_stats *ts, unsigned int space)
2815e61f 11066{
9c14ec72
RW
11067 struct bgp_node *prn = bgp_node_parent_nolock(rn);
11068 struct bgp_path_info *pi;
b54892e0 11069 const struct prefix *rn_p;
d62a17ae 11070
9c14ec72
RW
11071 if (rn == top)
11072 return;
d62a17ae 11073
9c14ec72
RW
11074 if (!bgp_node_has_bgp_path_info_data(rn))
11075 return;
d62a17ae 11076
b54892e0 11077 rn_p = bgp_node_get_prefix(rn);
9c14ec72 11078 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 11079 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 11080
a636c635
DW
11081#if 0
11082 ts->counts[BGP_STATS_AVGPLEN]
11083 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
11084 ts->counts[BGP_STATS_AVGPLEN],
b54892e0 11085 rn_p->prefixlen);
a636c635 11086#endif
d62a17ae 11087
9c14ec72
RW
11088 /* check if the prefix is included by any other announcements */
11089 while (prn && !bgp_node_has_bgp_path_info_data(prn))
11090 prn = bgp_node_parent_nolock(prn);
d62a17ae 11091
9c14ec72
RW
11092 if (prn == NULL || prn == top) {
11093 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
11094 /* announced address space */
11095 if (space)
b54892e0 11096 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9c14ec72
RW
11097 } else if (bgp_node_has_bgp_path_info_data(prn))
11098 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 11099
9c14ec72
RW
11100
11101 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
11102 ts->counts[BGP_STATS_RIB]++;
11103
05864da7
DS
11104 if (CHECK_FLAG(pi->attr->flag,
11105 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
11106 ts->counts[BGP_STATS_AGGREGATES]++;
11107
11108 /* as-path stats */
05864da7 11109 if (pi->attr->aspath) {
9c14ec72
RW
11110 unsigned int hops = aspath_count_hops(pi->attr->aspath);
11111 unsigned int size = aspath_size(pi->attr->aspath);
11112 as_t highest = aspath_highest(pi->attr->aspath);
11113
11114 ts->counts[BGP_STATS_ASPATH_COUNT]++;
11115
11116 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
11117 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
11118
11119 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
11120 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
11121
11122 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
11123 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 11124#if 0
07d0c4ed 11125 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
11126 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
11127 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
11128 hops);
11129 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
11130 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
11131 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
11132 size);
11133#endif
9c14ec72
RW
11134 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
11135 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
11136 }
11137 }
11138}
11139
11140static int bgp_table_stats_walker(struct thread *t)
11141{
11142 struct bgp_node *rn, *nrn;
11143 struct bgp_node *top;
11144 struct bgp_table_stats *ts = THREAD_ARG(t);
11145 unsigned int space = 0;
11146
11147 if (!(top = bgp_table_top(ts->table)))
11148 return 0;
11149
11150 switch (ts->table->afi) {
11151 case AFI_IP:
11152 space = IPV4_MAX_BITLEN;
11153 break;
11154 case AFI_IP6:
11155 space = IPV6_MAX_BITLEN;
11156 break;
11157 default:
11158 return 0;
11159 }
11160
11161 ts->counts[BGP_STATS_MAXBITLEN] = space;
11162
11163 for (rn = top; rn; rn = bgp_route_next(rn)) {
11164 if (ts->table->safi == SAFI_MPLS_VPN) {
11165 struct bgp_table *table;
11166
11167 table = bgp_node_get_bgp_table_info(rn);
11168 if (!table)
11169 continue;
11170
11171 top = bgp_table_top(table);
11172 for (nrn = bgp_table_top(table); nrn;
11173 nrn = bgp_route_next(nrn))
11174 bgp_table_stats_rn(nrn, top, ts, space);
11175 } else {
11176 bgp_table_stats_rn(rn, top, ts, space);
d62a17ae 11177 }
11178 }
9c14ec72 11179
d62a17ae 11180 return 0;
2815e61f 11181}
ff7924f6 11182
d62a17ae 11183static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
11184 safi_t safi)
2815e61f 11185{
d62a17ae 11186 struct bgp_table_stats ts;
11187 unsigned int i;
019386c2 11188
d62a17ae 11189 if (!bgp->rib[afi][safi]) {
11190 vty_out(vty, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
11191 afi, safi);
11192 return CMD_WARNING;
11193 }
019386c2 11194
5cb5f4d0 11195 vty_out(vty, "BGP %s RIB statistics\n", get_afi_safi_str(afi, safi, false));
019386c2 11196
d62a17ae 11197 /* labeled-unicast routes live in the unicast table */
11198 if (safi == SAFI_LABELED_UNICAST)
11199 safi = SAFI_UNICAST;
019386c2 11200
d62a17ae 11201 memset(&ts, 0, sizeof(ts));
11202 ts.table = bgp->rib[afi][safi];
11203 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 11204
d62a17ae 11205 for (i = 0; i < BGP_STATS_MAX; i++) {
11206 if (!table_stats_strs[i])
11207 continue;
11208
11209 switch (i) {
a636c635
DW
11210#if 0
11211 case BGP_STATS_ASPATH_AVGHOPS:
11212 case BGP_STATS_ASPATH_AVGSIZE:
11213 case BGP_STATS_AVGPLEN:
11214 vty_out (vty, "%-30s: ", table_stats_strs[i]);
11215 vty_out (vty, "%12.2f",
11216 (float)ts.counts[i] / (float)TALLY_SIGFIG);
11217 break;
11218#endif
d62a17ae 11219 case BGP_STATS_ASPATH_TOTHOPS:
11220 case BGP_STATS_ASPATH_TOTSIZE:
11221 vty_out(vty, "%-30s: ", table_stats_strs[i]);
11222 vty_out(vty, "%12.2f",
11223 ts.counts[i]
11224 ? (float)ts.counts[i]
11225 / (float)ts.counts
11226 [BGP_STATS_ASPATH_COUNT]
11227 : 0);
11228 break;
11229 case BGP_STATS_TOTPLEN:
11230 vty_out(vty, "%-30s: ", table_stats_strs[i]);
11231 vty_out(vty, "%12.2f",
11232 ts.counts[i]
11233 ? (float)ts.counts[i]
11234 / (float)ts.counts
11235 [BGP_STATS_PREFIXES]
11236 : 0);
11237 break;
11238 case BGP_STATS_SPACE:
11239 vty_out(vty, "%-30s: ", table_stats_strs[i]);
8d0ab76d
DL
11240 vty_out(vty, "%12g\n", ts.total_space);
11241
11242 if (afi == AFI_IP6) {
11243 vty_out(vty, "%30s: ", "/32 equivalent ");
11244 vty_out(vty, "%12g\n",
a4d82a8a 11245 ts.total_space * pow(2.0, -128 + 32));
8d0ab76d
DL
11246 vty_out(vty, "%30s: ", "/48 equivalent ");
11247 vty_out(vty, "%12g\n",
a4d82a8a 11248 ts.total_space * pow(2.0, -128 + 48));
8d0ab76d
DL
11249 } else {
11250 vty_out(vty, "%30s: ", "% announced ");
11251 vty_out(vty, "%12.2f\n",
11252 ts.total_space * 100. * pow(2.0, -32));
11253 vty_out(vty, "%30s: ", "/8 equivalent ");
11254 vty_out(vty, "%12.2f\n",
a4d82a8a 11255 ts.total_space * pow(2.0, -32 + 8));
8d0ab76d
DL
11256 vty_out(vty, "%30s: ", "/24 equivalent ");
11257 vty_out(vty, "%12.2f\n",
a4d82a8a 11258 ts.total_space * pow(2.0, -32 + 24));
8d0ab76d 11259 }
d62a17ae 11260 break;
11261 default:
11262 vty_out(vty, "%-30s: ", table_stats_strs[i]);
11263 vty_out(vty, "%12llu", ts.counts[i]);
11264 }
ff7924f6 11265
d62a17ae 11266 vty_out(vty, "\n");
11267 }
11268 return CMD_SUCCESS;
11269}
11270
11271enum bgp_pcounts {
11272 PCOUNT_ADJ_IN = 0,
11273 PCOUNT_DAMPED,
11274 PCOUNT_REMOVED,
11275 PCOUNT_HISTORY,
11276 PCOUNT_STALE,
11277 PCOUNT_VALID,
11278 PCOUNT_ALL,
11279 PCOUNT_COUNTED,
11280 PCOUNT_PFCNT, /* the figure we display to users */
11281 PCOUNT_MAX,
a636c635 11282};
718e3744 11283
2b64873d 11284static const char *const pcount_strs[] = {
9d303b37
DL
11285 [PCOUNT_ADJ_IN] = "Adj-in",
11286 [PCOUNT_DAMPED] = "Damped",
11287 [PCOUNT_REMOVED] = "Removed",
11288 [PCOUNT_HISTORY] = "History",
11289 [PCOUNT_STALE] = "Stale",
11290 [PCOUNT_VALID] = "Valid",
11291 [PCOUNT_ALL] = "All RIB",
11292 [PCOUNT_COUNTED] = "PfxCt counted",
11293 [PCOUNT_PFCNT] = "Useable",
11294 [PCOUNT_MAX] = NULL,
a636c635 11295};
718e3744 11296
d62a17ae 11297struct peer_pcounts {
11298 unsigned int count[PCOUNT_MAX];
11299 const struct peer *peer;
11300 const struct bgp_table *table;
54317cba 11301 safi_t safi;
a636c635 11302};
47fc97cc 11303
54317cba
JW
11304static void bgp_peer_count_proc(struct bgp_node *rn,
11305 struct peer_pcounts *pc)
d62a17ae 11306{
54317cba
JW
11307 const struct bgp_adj_in *ain;
11308 const struct bgp_path_info *pi;
d62a17ae 11309 const struct peer *peer = pc->peer;
11310
54317cba
JW
11311 for (ain = rn->adj_in; ain; ain = ain->next)
11312 if (ain->peer == peer)
11313 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 11314
54317cba 11315 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 11316
54317cba
JW
11317 if (pi->peer != peer)
11318 continue;
d62a17ae 11319
54317cba 11320 pc->count[PCOUNT_ALL]++;
d62a17ae 11321
54317cba
JW
11322 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
11323 pc->count[PCOUNT_DAMPED]++;
11324 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
11325 pc->count[PCOUNT_HISTORY]++;
11326 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
11327 pc->count[PCOUNT_REMOVED]++;
11328 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
11329 pc->count[PCOUNT_STALE]++;
11330 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
11331 pc->count[PCOUNT_VALID]++;
11332 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
11333 pc->count[PCOUNT_PFCNT]++;
11334
11335 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
11336 pc->count[PCOUNT_COUNTED]++;
11337 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
11338 flog_err(
11339 EC_LIB_DEVELOPMENT,
11340 "Attempting to count but flags say it is unusable");
11341 } else {
40381db7 11342 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
11343 flog_err(
11344 EC_LIB_DEVELOPMENT,
11345 "Not counted but flags say we should");
d62a17ae 11346 }
11347 }
54317cba
JW
11348}
11349
11350static int bgp_peer_count_walker(struct thread *t)
11351{
11352 struct bgp_node *rn, *rm;
11353 const struct bgp_table *table;
11354 struct peer_pcounts *pc = THREAD_ARG(t);
11355
11356 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
11357 || pc->safi == SAFI_EVPN) {
11358 /* Special handling for 2-level routing tables. */
11359 for (rn = bgp_table_top(pc->table); rn;
11360 rn = bgp_route_next(rn)) {
11361 table = bgp_node_get_bgp_table_info(rn);
11362 if (table != NULL)
11363 for (rm = bgp_table_top(table); rm;
11364 rm = bgp_route_next(rm))
11365 bgp_peer_count_proc(rm, pc);
11366 }
11367 } else
11368 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
11369 bgp_peer_count_proc(rn, pc);
11370
d62a17ae 11371 return 0;
718e3744 11372}
11373
d62a17ae 11374static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 11375 safi_t safi, bool use_json)
856ca177 11376{
d62a17ae 11377 struct peer_pcounts pcounts = {.peer = peer};
11378 unsigned int i;
11379 json_object *json = NULL;
11380 json_object *json_loop = NULL;
856ca177 11381
d62a17ae 11382 if (use_json) {
11383 json = json_object_new_object();
11384 json_loop = json_object_new_object();
11385 }
718e3744 11386
d62a17ae 11387 if (!peer || !peer->bgp || !peer->afc[afi][safi]
11388 || !peer->bgp->rib[afi][safi]) {
11389 if (use_json) {
11390 json_object_string_add(
11391 json, "warning",
11392 "No such neighbor or address family");
11393 vty_out(vty, "%s\n", json_object_to_json_string(json));
11394 json_object_free(json);
11395 } else
11396 vty_out(vty, "%% No such neighbor or address family\n");
11397
11398 return CMD_WARNING;
11399 }
2a71e9ce 11400
d62a17ae 11401 memset(&pcounts, 0, sizeof(pcounts));
11402 pcounts.peer = peer;
11403 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 11404 pcounts.safi = safi;
d62a17ae 11405
11406 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
11407 * stats for the thread-walk (i.e. ensure this can't be blamed on
11408 * on just vty_read()).
11409 */
d62a17ae 11410 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
11411
11412 if (use_json) {
11413 json_object_string_add(json, "prefixCountsFor", peer->host);
11414 json_object_string_add(json, "multiProtocol",
5cb5f4d0 11415 get_afi_safi_str(afi, safi, true));
d62a17ae 11416 json_object_int_add(json, "pfxCounter",
11417 peer->pcount[afi][safi]);
11418
11419 for (i = 0; i < PCOUNT_MAX; i++)
11420 json_object_int_add(json_loop, pcount_strs[i],
11421 pcounts.count[i]);
11422
11423 json_object_object_add(json, "ribTableWalkCounters", json_loop);
11424
11425 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
11426 json_object_string_add(json, "pfxctDriftFor",
11427 peer->host);
11428 json_object_string_add(
11429 json, "recommended",
11430 "Please report this bug, with the above command output");
11431 }
996c9314
LB
11432 vty_out(vty, "%s\n", json_object_to_json_string_ext(
11433 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 11434 json_object_free(json);
11435 } else {
11436
11437 if (peer->hostname
892fedb6 11438 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 11439 vty_out(vty, "Prefix counts for %s/%s, %s\n",
11440 peer->hostname, peer->host,
5cb5f4d0 11441 get_afi_safi_str(afi, safi, false));
d62a17ae 11442 } else {
11443 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 11444 get_afi_safi_str(afi, safi, false));
d62a17ae 11445 }
11446
a0a87037 11447 vty_out(vty, "PfxCt: %" PRIu32 "\n", peer->pcount[afi][safi]);
d62a17ae 11448 vty_out(vty, "\nCounts from RIB table walk:\n\n");
11449
11450 for (i = 0; i < PCOUNT_MAX; i++)
11451 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
11452 pcounts.count[i]);
11453
11454 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
11455 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
11456 vty_out(vty,
11457 "Please report this bug, with the above command output\n");
11458 }
11459 }
11460
11461 return CMD_SUCCESS;
718e3744 11462}
11463
a636c635
DW
11464DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
11465 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
c1a44e43 11466 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] "
30a6a167 11467 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
718e3744 11468 SHOW_STR
11469 IP_STR
11470 BGP_STR
8386ac43 11471 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
11472 BGP_AFI_HELP_STR
11473 BGP_SAFI_HELP_STR
0b16f239
DS
11474 "Detailed information on TCP and BGP neighbor connections\n"
11475 "Neighbor to display information about\n"
11476 "Neighbor to display information about\n"
91d37724 11477 "Neighbor on BGP configured interface\n"
a636c635 11478 "Display detailed prefix count information\n"
9973d184 11479 JSON_STR)
0b16f239 11480{
d62a17ae 11481 afi_t afi = AFI_IP6;
11482 safi_t safi = SAFI_UNICAST;
11483 struct peer *peer;
11484 int idx = 0;
11485 struct bgp *bgp = NULL;
9f049418
DS
11486 bool uj = use_json(argc, argv);
11487
11488 if (uj)
11489 argc--;
856ca177 11490
d62a17ae 11491 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11492 &bgp, uj);
d62a17ae 11493 if (!idx)
11494 return CMD_WARNING;
0b16f239 11495
d62a17ae 11496 argv_find(argv, argc, "neighbors", &idx);
11497 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
11498 if (!peer)
11499 return CMD_WARNING;
bb46e94f 11500
29c8d9da 11501 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 11502}
0b16f239 11503
d6902373
PG
11504#ifdef KEEP_OLD_VPN_COMMANDS
11505DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
11506 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
11507 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
11508 SHOW_STR
11509 IP_STR
11510 BGP_STR
d6902373 11511 BGP_VPNVX_HELP_STR
91d37724 11512 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
11513 "Detailed information on TCP and BGP neighbor connections\n"
11514 "Neighbor to display information about\n"
11515 "Neighbor to display information about\n"
91d37724 11516 "Neighbor on BGP configured interface\n"
a636c635 11517 "Display detailed prefix count information\n"
9973d184 11518 JSON_STR)
a636c635 11519{
d62a17ae 11520 int idx_peer = 6;
11521 struct peer *peer;
9f049418 11522 bool uj = use_json(argc, argv);
a636c635 11523
d62a17ae 11524 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
11525 if (!peer)
11526 return CMD_WARNING;
11527
11528 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
11529}
11530
d6902373
PG
11531DEFUN (show_ip_bgp_vpn_all_route_prefix,
11532 show_ip_bgp_vpn_all_route_prefix_cmd,
11533 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
11534 SHOW_STR
11535 IP_STR
11536 BGP_STR
d6902373 11537 BGP_VPNVX_HELP_STR
91d37724
QY
11538 "Display information about all VPNv4 NLRIs\n"
11539 "Network in the BGP routing table to display\n"
3a2d747c 11540 "Network in the BGP routing table to display\n"
9973d184 11541 JSON_STR)
91d37724 11542{
d62a17ae 11543 int idx = 0;
11544 char *network = NULL;
11545 struct bgp *bgp = bgp_get_default();
11546 if (!bgp) {
11547 vty_out(vty, "Can't find default instance\n");
11548 return CMD_WARNING;
11549 }
87e34b58 11550
d62a17ae 11551 if (argv_find(argv, argc, "A.B.C.D", &idx))
11552 network = argv[idx]->arg;
11553 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
11554 network = argv[idx]->arg;
11555 else {
11556 vty_out(vty, "Unable to figure out Network\n");
11557 return CMD_WARNING;
11558 }
87e34b58 11559
d62a17ae 11560 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 11561 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 11562}
d6902373 11563#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 11564
44c69747
LK
11565DEFUN (show_bgp_l2vpn_evpn_route_prefix,
11566 show_bgp_l2vpn_evpn_route_prefix_cmd,
11567 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 11568 SHOW_STR
4c63a661
PG
11569 BGP_STR
11570 L2VPN_HELP_STR
11571 EVPN_HELP_STR
44c69747
LK
11572 "Network in the BGP routing table to display\n"
11573 "Network in the BGP routing table to display\n"
4c63a661
PG
11574 "Network in the BGP routing table to display\n"
11575 "Network in the BGP routing table to display\n"
11576 JSON_STR)
11577{
d62a17ae 11578 int idx = 0;
11579 char *network = NULL;
44c69747 11580 int prefix_check = 0;
a636c635 11581
44c69747
LK
11582 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
11583 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 11584 network = argv[idx]->arg;
44c69747 11585 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 11586 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 11587 network = argv[idx]->arg;
44c69747
LK
11588 prefix_check = 1;
11589 } else {
d62a17ae 11590 vty_out(vty, "Unable to figure out Network\n");
11591 return CMD_WARNING;
11592 }
44c69747
LK
11593 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
11594 prefix_check, BGP_PATH_SHOW_ALL,
11595 use_json(argc, argv));
d62a17ae 11596}
11597
11598static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 11599 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 11600 const char *rmap_name, bool use_json,
6392aaa6 11601 json_object *json)
d62a17ae 11602{
11603 struct bgp_table *table;
11604 struct bgp_adj_in *ain;
11605 struct bgp_adj_out *adj;
74a630b6
NT
11606 unsigned long output_count = 0;
11607 unsigned long filtered_count = 0;
d62a17ae 11608 struct bgp_node *rn;
11609 int header1 = 1;
11610 struct bgp *bgp;
11611 int header2 = 1;
11612 struct attr attr;
11613 int ret;
11614 struct update_subgroup *subgrp;
11615 json_object *json_scode = NULL;
11616 json_object *json_ocode = NULL;
11617 json_object *json_ar = NULL;
11618 struct peer_af *paf;
f99def61 11619 bool route_filtered;
d62a17ae 11620
11621 if (use_json) {
11622 json_scode = json_object_new_object();
11623 json_ocode = json_object_new_object();
11624 json_ar = json_object_new_object();
11625
11626 json_object_string_add(json_scode, "suppressed", "s");
11627 json_object_string_add(json_scode, "damped", "d");
11628 json_object_string_add(json_scode, "history", "h");
11629 json_object_string_add(json_scode, "valid", "*");
11630 json_object_string_add(json_scode, "best", ">");
11631 json_object_string_add(json_scode, "multipath", "=");
11632 json_object_string_add(json_scode, "internal", "i");
11633 json_object_string_add(json_scode, "ribFailure", "r");
11634 json_object_string_add(json_scode, "stale", "S");
11635 json_object_string_add(json_scode, "removed", "R");
11636
11637 json_object_string_add(json_ocode, "igp", "i");
11638 json_object_string_add(json_ocode, "egp", "e");
11639 json_object_string_add(json_ocode, "incomplete", "?");
11640 }
a636c635 11641
d62a17ae 11642 bgp = peer->bgp;
a636c635 11643
d62a17ae 11644 if (!bgp) {
11645 if (use_json) {
11646 json_object_string_add(json, "alert", "no BGP");
11647 vty_out(vty, "%s\n", json_object_to_json_string(json));
11648 json_object_free(json);
11649 } else
11650 vty_out(vty, "%% No bgp\n");
11651 return;
11652 }
a636c635 11653
c512a642
EDP
11654 /* labeled-unicast routes live in the unicast table */
11655 if (safi == SAFI_LABELED_UNICAST)
11656 table = bgp->rib[afi][SAFI_UNICAST];
11657 else
11658 table = bgp->rib[afi][safi];
d62a17ae 11659
11660 output_count = filtered_count = 0;
11661 subgrp = peer_subgroup(peer, afi, safi);
11662
6392aaa6 11663 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 11664 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
11665 if (use_json) {
11666 json_object_int_add(json, "bgpTableVersion",
11667 table->version);
11668 json_object_string_add(json, "bgpLocalRouterId",
11669 inet_ntoa(bgp->router_id));
01eced22
AD
11670 json_object_int_add(json, "defaultLocPrf",
11671 bgp->default_local_pref);
11672 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 11673 json_object_object_add(json, "bgpStatusCodes",
11674 json_scode);
11675 json_object_object_add(json, "bgpOriginCodes",
11676 json_ocode);
07d0c4ed
DA
11677 json_object_string_add(
11678 json, "bgpOriginatingDefaultNetwork",
11679 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 11680 } else {
996c9314 11681 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 11682 ", local router ID is %s, vrf id ",
d62a17ae 11683 table->version, inet_ntoa(bgp->router_id));
9df8b37c
PZ
11684 if (bgp->vrf_id == VRF_UNKNOWN)
11685 vty_out(vty, "%s", VRFID_NONE_STR);
11686 else
11687 vty_out(vty, "%u", bgp->vrf_id);
11688 vty_out(vty, "\n");
01eced22
AD
11689 vty_out(vty, "Default local pref %u, ",
11690 bgp->default_local_pref);
11691 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 11692 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11693 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 11694 vty_out(vty, BGP_SHOW_OCODE_HEADER);
11695
07d0c4ed
DA
11696 vty_out(vty, "Originating default network %s\n\n",
11697 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 11698 }
11699 header1 = 0;
11700 }
a636c635 11701
d62a17ae 11702 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6392aaa6
PM
11703 if (type == bgp_show_adj_route_received
11704 || type == bgp_show_adj_route_filtered) {
d62a17ae 11705 for (ain = rn->adj_in; ain; ain = ain->next) {
05864da7 11706 if (ain->peer != peer)
ea47320b 11707 continue;
6392aaa6 11708
ea47320b
DL
11709 if (header1) {
11710 if (use_json) {
11711 json_object_int_add(
60466a63 11712 json, "bgpTableVersion",
ea47320b
DL
11713 0);
11714 json_object_string_add(
11715 json,
11716 "bgpLocalRouterId",
11717 inet_ntoa(
11718 bgp->router_id));
01eced22
AD
11719 json_object_int_add(json,
11720 "defaultLocPrf",
11721 bgp->default_local_pref);
11722 json_object_int_add(json,
11723 "localAS", bgp->as);
ea47320b 11724 json_object_object_add(
60466a63 11725 json, "bgpStatusCodes",
ea47320b
DL
11726 json_scode);
11727 json_object_object_add(
60466a63 11728 json, "bgpOriginCodes",
ea47320b
DL
11729 json_ocode);
11730 } else {
11731 vty_out(vty,
9df8b37c 11732 "BGP table version is 0, local router ID is %s, vrf id ",
ea47320b 11733 inet_ntoa(
9df8b37c
PZ
11734 bgp->router_id));
11735 if (bgp->vrf_id == VRF_UNKNOWN)
11736 vty_out(vty, "%s",
11737 VRFID_NONE_STR);
11738 else
11739 vty_out(vty, "%u",
11740 bgp->vrf_id);
11741 vty_out(vty, "\n");
01eced22
AD
11742 vty_out(vty,
11743 "Default local pref %u, ",
11744 bgp->default_local_pref);
11745 vty_out(vty, "local AS %u\n",
11746 bgp->as);
ea47320b
DL
11747 vty_out(vty,
11748 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
11749 vty_out(vty,
11750 BGP_SHOW_NCODE_HEADER);
ea47320b
DL
11751 vty_out(vty,
11752 BGP_SHOW_OCODE_HEADER);
d62a17ae 11753 }
ea47320b
DL
11754 header1 = 0;
11755 }
11756 if (header2) {
11757 if (!use_json)
11758 vty_out(vty, BGP_SHOW_HEADER);
11759 header2 = 0;
11760 }
6392aaa6 11761
6f4f49b2 11762 attr = *ain->attr;
f99def61
AD
11763 route_filtered = false;
11764
11765 /* Filter prefix using distribute list,
11766 * filter list or prefix list
11767 */
b54892e0
DS
11768 const struct prefix *rn_p =
11769 bgp_node_get_prefix(rn);
11770 if ((bgp_input_filter(peer, rn_p, &attr, afi,
11771 safi))
11772 == FILTER_DENY)
f99def61
AD
11773 route_filtered = true;
11774
11775 /* Filter prefix using route-map */
b54892e0
DS
11776 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
11777 safi, rmap_name, NULL,
11778 0, NULL);
6392aaa6 11779
13c8e163
AD
11780 if (type == bgp_show_adj_route_filtered &&
11781 !route_filtered && ret != RMAP_DENY) {
b755861b 11782 bgp_attr_undup(&attr, ain->attr);
6392aaa6 11783 continue;
d62a17ae 11784 }
6392aaa6 11785
13c8e163
AD
11786 if (type == bgp_show_adj_route_received &&
11787 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
11788 filtered_count++;
11789
b54892e0 11790 route_vty_out_tmp(vty, rn_p, &attr, safi,
6392aaa6 11791 use_json, json_ar);
b755861b 11792 bgp_attr_undup(&attr, ain->attr);
6392aaa6 11793 output_count++;
d62a17ae 11794 }
6392aaa6 11795 } else if (type == bgp_show_adj_route_advertised) {
a79c04e7 11796 RB_FOREACH (adj, bgp_adj_out_rb, &rn->adj_out)
924c3f6a 11797 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 11798 if (paf->peer != peer || !adj->attr)
924c3f6a 11799 continue;
d62a17ae 11800
924c3f6a
DS
11801 if (header1) {
11802 if (use_json) {
11803 json_object_int_add(
11804 json,
11805 "bgpTableVersion",
11806 table->version);
11807 json_object_string_add(
11808 json,
11809 "bgpLocalRouterId",
11810 inet_ntoa(
11811 bgp->router_id));
01eced22
AD
11812 json_object_int_add(
11813 json, "defaultLocPrf",
11814 bgp->default_local_pref
11815 );
11816 json_object_int_add(
11817 json, "localAS",
11818 bgp->as);
924c3f6a
DS
11819 json_object_object_add(
11820 json,
11821 "bgpStatusCodes",
11822 json_scode);
11823 json_object_object_add(
11824 json,
11825 "bgpOriginCodes",
11826 json_ocode);
11827 } else {
11828 vty_out(vty,
11829 "BGP table version is %" PRIu64
9df8b37c 11830 ", local router ID is %s, vrf id ",
924c3f6a
DS
11831 table->version,
11832 inet_ntoa(
11833 bgp->router_id));
9df8b37c
PZ
11834 if (bgp->vrf_id ==
11835 VRF_UNKNOWN)
11836 vty_out(vty,
11837 "%s",
11838 VRFID_NONE_STR);
11839 else
11840 vty_out(vty,
11841 "%u",
11842 bgp->vrf_id);
11843 vty_out(vty, "\n");
01eced22
AD
11844 vty_out(vty,
11845 "Default local pref %u, ",
11846 bgp->default_local_pref
11847 );
11848 vty_out(vty,
11849 "local AS %u\n",
11850 bgp->as);
924c3f6a
DS
11851 vty_out(vty,
11852 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
11853 vty_out(vty,
11854 BGP_SHOW_NCODE_HEADER);
924c3f6a
DS
11855 vty_out(vty,
11856 BGP_SHOW_OCODE_HEADER);
a2addae8 11857 }
924c3f6a
DS
11858 header1 = 0;
11859 }
924c3f6a
DS
11860 if (header2) {
11861 if (!use_json)
11862 vty_out(vty,
11863 BGP_SHOW_HEADER);
11864 header2 = 0;
11865 }
d62a17ae 11866
b54892e0
DS
11867 const struct prefix *rn_p =
11868 bgp_node_get_prefix(rn);
11869
6f4f49b2 11870 attr = *adj->attr;
b755861b 11871 ret = bgp_output_modifier(
b54892e0 11872 peer, rn_p, &attr, afi, safi,
b755861b 11873 rmap_name);
f46d8e1e 11874
b755861b 11875 if (ret != RMAP_DENY) {
b54892e0
DS
11876 route_vty_out_tmp(
11877 vty, rn_p, &attr, safi,
11878 use_json, json_ar);
b755861b
PM
11879 output_count++;
11880 } else {
11881 filtered_count++;
a2addae8 11882 }
b755861b
PM
11883
11884 bgp_attr_undup(&attr, adj->attr);
924c3f6a 11885 }
d62a17ae 11886 }
11887 }
d62a17ae 11888
d62a17ae 11889 if (use_json) {
6392aaa6
PM
11890 json_object_object_add(json, "advertisedRoutes", json_ar);
11891 json_object_int_add(json, "totalPrefixCounter", output_count);
11892 json_object_int_add(json, "filteredPrefixCounter",
11893 filtered_count);
11894
996c9314
LB
11895 vty_out(vty, "%s\n", json_object_to_json_string_ext(
11896 json, JSON_C_TO_STRING_PRETTY));
74a630b6
NT
11897
11898 if (!output_count && !filtered_count) {
11899 json_object_free(json_scode);
11900 json_object_free(json_ocode);
11901 }
11902
d62a17ae 11903 json_object_free(json);
6392aaa6
PM
11904 } else if (output_count > 0) {
11905 if (filtered_count > 0)
11906 vty_out(vty,
11907 "\nTotal number of prefixes %ld (%ld filtered)\n",
11908 output_count, filtered_count);
11909 else
11910 vty_out(vty, "\nTotal number of prefixes %ld\n",
11911 output_count);
d62a17ae 11912 }
a636c635 11913}
2a71e9ce 11914
d62a17ae 11915static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 11916 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 11917 const char *rmap_name, bool use_json)
0b16f239 11918{
d62a17ae 11919 json_object *json = NULL;
0b16f239 11920
d62a17ae 11921 if (use_json)
11922 json = json_object_new_object();
0b16f239 11923
d62a17ae 11924 if (!peer || !peer->afc[afi][safi]) {
11925 if (use_json) {
11926 json_object_string_add(
11927 json, "warning",
11928 "No such neighbor or address family");
11929 vty_out(vty, "%s\n", json_object_to_json_string(json));
11930 json_object_free(json);
11931 } else
11932 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 11933
d62a17ae 11934 return CMD_WARNING;
11935 }
11936
6392aaa6
PM
11937 if ((type == bgp_show_adj_route_received
11938 || type == bgp_show_adj_route_filtered)
d62a17ae 11939 && !CHECK_FLAG(peer->af_flags[afi][safi],
11940 PEER_FLAG_SOFT_RECONFIG)) {
11941 if (use_json) {
11942 json_object_string_add(
11943 json, "warning",
11944 "Inbound soft reconfiguration not enabled");
11945 vty_out(vty, "%s\n", json_object_to_json_string(json));
11946 json_object_free(json);
11947 } else
11948 vty_out(vty,
11949 "%% Inbound soft reconfiguration not enabled\n");
11950
11951 return CMD_WARNING;
11952 }
0b16f239 11953
6392aaa6 11954 show_adj_route(vty, peer, afi, safi, type, rmap_name, use_json, json);
0b16f239 11955
d62a17ae 11956 return CMD_SUCCESS;
a636c635 11957}
50ef26d4 11958
a636c635
DW
11959DEFUN (show_ip_bgp_instance_neighbor_advertised_route,
11960 show_ip_bgp_instance_neighbor_advertised_route_cmd,
4dd6177e 11961 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
6392aaa6 11962 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
718e3744 11963 SHOW_STR
11964 IP_STR
11965 BGP_STR
a636c635 11966 BGP_INSTANCE_HELP_STR
7395a2c9 11967 BGP_AFI_HELP_STR
4dd6177e 11968 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 11969 "Detailed information on TCP and BGP neighbor connections\n"
11970 "Neighbor to display information about\n"
11971 "Neighbor to display information about\n"
91d37724 11972 "Neighbor on BGP configured interface\n"
a636c635 11973 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
11974 "Display the received routes from neighbor\n"
11975 "Display the filtered routes received from neighbor\n"
a636c635
DW
11976 "Route-map to modify the attributes\n"
11977 "Name of the route map\n"
9973d184 11978 JSON_STR)
718e3744 11979{
d62a17ae 11980 afi_t afi = AFI_IP6;
11981 safi_t safi = SAFI_UNICAST;
11982 char *rmap_name = NULL;
11983 char *peerstr = NULL;
d62a17ae 11984 struct bgp *bgp = NULL;
11985 struct peer *peer;
6392aaa6 11986 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 11987 int idx = 0;
9f049418 11988 bool uj = use_json(argc, argv);
6392aaa6 11989
d62a17ae 11990 if (uj)
11991 argc--;
30a6a167 11992
9f049418
DS
11993 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11994 &bgp, uj);
11995 if (!idx)
11996 return CMD_WARNING;
11997
d62a17ae 11998 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11999 argv_find(argv, argc, "neighbors", &idx);
12000 peerstr = argv[++idx]->arg;
8c3deaae 12001
d62a17ae 12002 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
12003 if (!peer)
12004 return CMD_WARNING;
856ca177 12005
d62a17ae 12006 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
12007 type = bgp_show_adj_route_advertised;
12008 else if (argv_find(argv, argc, "received-routes", &idx))
12009 type = bgp_show_adj_route_received;
12010 else if (argv_find(argv, argc, "filtered-routes", &idx))
12011 type = bgp_show_adj_route_filtered;
12012
d62a17ae 12013 if (argv_find(argv, argc, "route-map", &idx))
12014 rmap_name = argv[++idx]->arg;
95cbbd2a 12015
6392aaa6 12016 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj);
95cbbd2a
ML
12017}
12018
718e3744 12019DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
12020 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 12021 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 12022 SHOW_STR
12023 IP_STR
12024 BGP_STR
8c3deaae
QY
12025 "Address Family\n"
12026 "Address Family\n"
718e3744 12027 "Address Family modifier\n"
12028 "Detailed information on TCP and BGP neighbor connections\n"
12029 "Neighbor to display information about\n"
12030 "Neighbor to display information about\n"
91d37724 12031 "Neighbor on BGP configured interface\n"
718e3744 12032 "Display information received from a BGP neighbor\n"
856ca177 12033 "Display the prefixlist filter\n"
9973d184 12034 JSON_STR)
718e3744 12035{
d62a17ae 12036 afi_t afi = AFI_IP6;
12037 safi_t safi = SAFI_UNICAST;
12038 char *peerstr = NULL;
12039
12040 char name[BUFSIZ];
12041 union sockunion su;
12042 struct peer *peer;
12043 int count, ret;
12044
12045 int idx = 0;
12046
12047 /* show [ip] bgp */
12048 if (argv_find(argv, argc, "ip", &idx))
12049 afi = AFI_IP;
12050 /* [<ipv4|ipv6> [unicast]] */
12051 if (argv_find(argv, argc, "ipv4", &idx))
12052 afi = AFI_IP;
12053 if (argv_find(argv, argc, "ipv6", &idx))
12054 afi = AFI_IP6;
12055 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12056 argv_find(argv, argc, "neighbors", &idx);
12057 peerstr = argv[++idx]->arg;
12058
9f049418 12059 bool uj = use_json(argc, argv);
d62a17ae 12060
12061 ret = str2sockunion(peerstr, &su);
12062 if (ret < 0) {
12063 peer = peer_lookup_by_conf_if(NULL, peerstr);
12064 if (!peer) {
12065 if (uj)
12066 vty_out(vty, "{}\n");
12067 else
12068 vty_out(vty,
12069 "%% Malformed address or name: %s\n",
12070 peerstr);
12071 return CMD_WARNING;
12072 }
12073 } else {
12074 peer = peer_lookup(NULL, &su);
12075 if (!peer) {
12076 if (uj)
12077 vty_out(vty, "{}\n");
12078 else
12079 vty_out(vty, "No peer\n");
12080 return CMD_WARNING;
12081 }
12082 }
718e3744 12083
d62a17ae 12084 sprintf(name, "%s.%d.%d", peer->host, afi, safi);
12085 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
12086 if (count) {
12087 if (!uj)
12088 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 12089 get_afi_safi_str(afi, safi, false));
d62a17ae 12090 prefix_bgp_show_prefix_list(vty, afi, name, uj);
12091 } else {
12092 if (uj)
12093 vty_out(vty, "{}\n");
12094 else
12095 vty_out(vty, "No functional output\n");
12096 }
718e3744 12097
d62a17ae 12098 return CMD_SUCCESS;
12099}
12100
12101static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
12102 afi_t afi, safi_t safi,
9f049418 12103 enum bgp_show_type type, bool use_json)
d62a17ae 12104{
8a893163
DW
12105 /* labeled-unicast routes live in the unicast table */
12106 if (safi == SAFI_LABELED_UNICAST)
12107 safi = SAFI_UNICAST;
12108
d62a17ae 12109 if (!peer || !peer->afc[afi][safi]) {
12110 if (use_json) {
12111 json_object *json_no = NULL;
12112 json_no = json_object_new_object();
12113 json_object_string_add(
12114 json_no, "warning",
12115 "No such neighbor or address family");
12116 vty_out(vty, "%s\n",
12117 json_object_to_json_string(json_no));
12118 json_object_free(json_no);
12119 } else
12120 vty_out(vty, "%% No such neighbor or address family\n");
12121 return CMD_WARNING;
12122 }
47fc97cc 12123
d62a17ae 12124 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json);
718e3744 12125}
12126
dba3c1d3
PG
12127DEFUN (show_ip_bgp_flowspec_routes_detailed,
12128 show_ip_bgp_flowspec_routes_detailed_cmd,
12129 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
12130 SHOW_STR
12131 IP_STR
12132 BGP_STR
12133 BGP_INSTANCE_HELP_STR
12134 BGP_AFI_HELP_STR
12135 "SAFI Flowspec\n"
12136 "Detailed information on flowspec entries\n"
12137 JSON_STR)
12138{
12139 afi_t afi = AFI_IP;
12140 safi_t safi = SAFI_UNICAST;
12141 struct bgp *bgp = NULL;
12142 int idx = 0;
9f049418
DS
12143 bool uj = use_json(argc, argv);
12144
12145 if (uj)
12146 argc--;
dba3c1d3
PG
12147
12148 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12149 &bgp, uj);
dba3c1d3
PG
12150 if (!idx)
12151 return CMD_WARNING;
12152
9f049418 12153 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL, uj);
dba3c1d3
PG
12154}
12155
718e3744 12156DEFUN (show_ip_bgp_neighbor_routes,
12157 show_ip_bgp_neighbor_routes_cmd,
4dd6177e 12158 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
30a6a167 12159 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
50ef26d4 12160 SHOW_STR
12161 IP_STR
12162 BGP_STR
8386ac43 12163 BGP_INSTANCE_HELP_STR
4f280b15 12164 BGP_AFI_HELP_STR
4dd6177e 12165 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 12166 "Detailed information on TCP and BGP neighbor connections\n"
12167 "Neighbor to display information about\n"
12168 "Neighbor to display information about\n"
91d37724 12169 "Neighbor on BGP configured interface\n"
2525cf39 12170 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
12171 "Display the dampened routes received from neighbor\n"
12172 "Display routes learned from neighbor\n"
9973d184 12173 JSON_STR)
718e3744 12174{
d62a17ae 12175 char *peerstr = NULL;
12176 struct bgp *bgp = NULL;
12177 afi_t afi = AFI_IP6;
12178 safi_t safi = SAFI_UNICAST;
12179 struct peer *peer;
12180 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 12181 int idx = 0;
9f049418
DS
12182 bool uj = use_json(argc, argv);
12183
12184 if (uj)
12185 argc--;
bb46e94f 12186
d62a17ae 12187 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12188 &bgp, uj);
d62a17ae 12189 if (!idx)
12190 return CMD_WARNING;
c493f2d8 12191
d62a17ae 12192 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12193 argv_find(argv, argc, "neighbors", &idx);
12194 peerstr = argv[++idx]->arg;
8c3deaae 12195
d62a17ae 12196 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 12197 if (!peer)
d62a17ae 12198 return CMD_WARNING;
bb46e94f 12199
d62a17ae 12200 if (argv_find(argv, argc, "flap-statistics", &idx))
12201 sh_type = bgp_show_type_flap_neighbor;
12202 else if (argv_find(argv, argc, "dampened-routes", &idx))
12203 sh_type = bgp_show_type_damp_neighbor;
12204 else if (argv_find(argv, argc, "routes", &idx))
12205 sh_type = bgp_show_type_neighbor;
2525cf39 12206
d62a17ae 12207 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 12208}
6b0655a2 12209
734b349e 12210struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 12211
d62a17ae 12212struct bgp_distance {
12213 /* Distance value for the IP source prefix. */
d7c0a89a 12214 uint8_t distance;
718e3744 12215
d62a17ae 12216 /* Name of the access-list to be matched. */
12217 char *access_list;
718e3744 12218};
12219
4f280b15
LB
12220DEFUN (show_bgp_afi_vpn_rd_route,
12221 show_bgp_afi_vpn_rd_route_cmd,
d114b977 12222 "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
12223 SHOW_STR
12224 BGP_STR
12225 BGP_AFI_HELP_STR
12226 "Address Family modifier\n"
12227 "Display information for a route distinguisher\n"
12228 "Route Distinguisher\n"
7395a2c9
DS
12229 "Network in the BGP routing table to display\n"
12230 "Network in the BGP routing table to display\n"
12231 JSON_STR)
4f280b15 12232{
d62a17ae 12233 int ret;
12234 struct prefix_rd prd;
12235 afi_t afi = AFI_MAX;
12236 int idx = 0;
4f280b15 12237
ff6566f3
DS
12238 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
12239 vty_out(vty, "%% Malformed Address Family\n");
12240 return CMD_WARNING;
12241 }
12242
d62a17ae 12243 ret = str2prefix_rd(argv[5]->arg, &prd);
12244 if (!ret) {
12245 vty_out(vty, "%% Malformed Route Distinguisher\n");
12246 return CMD_WARNING;
12247 }
ff6566f3 12248
d62a17ae 12249 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 12250 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
12251}
12252
d62a17ae 12253static struct bgp_distance *bgp_distance_new(void)
718e3744 12254{
d62a17ae 12255 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 12256}
12257
d62a17ae 12258static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 12259{
d62a17ae 12260 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 12261}
12262
d62a17ae 12263static int bgp_distance_set(struct vty *vty, const char *distance_str,
12264 const char *ip_str, const char *access_list_str)
718e3744 12265{
d62a17ae 12266 int ret;
12267 afi_t afi;
12268 safi_t safi;
12269 struct prefix p;
d7c0a89a 12270 uint8_t distance;
d62a17ae 12271 struct bgp_node *rn;
12272 struct bgp_distance *bdistance;
718e3744 12273
d62a17ae 12274 afi = bgp_node_afi(vty);
12275 safi = bgp_node_safi(vty);
734b349e 12276
d62a17ae 12277 ret = str2prefix(ip_str, &p);
12278 if (ret == 0) {
12279 vty_out(vty, "Malformed prefix\n");
12280 return CMD_WARNING_CONFIG_FAILED;
12281 }
718e3744 12282
d62a17ae 12283 distance = atoi(distance_str);
718e3744 12284
d62a17ae 12285 /* Get BGP distance node. */
c4efd0f4 12286 rn = bgp_node_get(bgp_distance_table[afi][safi], &p);
5b00b40e 12287 bdistance = bgp_node_get_bgp_distance_info(rn);
ca2e160d 12288 if (bdistance)
d62a17ae 12289 bgp_unlock_node(rn);
ca2e160d 12290 else {
d62a17ae 12291 bdistance = bgp_distance_new();
5b00b40e 12292 bgp_node_set_bgp_distance_info(rn, bdistance);
d62a17ae 12293 }
718e3744 12294
d62a17ae 12295 /* Set distance value. */
12296 bdistance->distance = distance;
718e3744 12297
d62a17ae 12298 /* Reset access-list configuration. */
e1b36e13 12299 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 12300 if (access_list_str)
12301 bdistance->access_list =
12302 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 12303
d62a17ae 12304 return CMD_SUCCESS;
718e3744 12305}
12306
d62a17ae 12307static int bgp_distance_unset(struct vty *vty, const char *distance_str,
12308 const char *ip_str, const char *access_list_str)
718e3744 12309{
d62a17ae 12310 int ret;
12311 afi_t afi;
12312 safi_t safi;
12313 struct prefix p;
12314 int distance;
12315 struct bgp_node *rn;
12316 struct bgp_distance *bdistance;
718e3744 12317
d62a17ae 12318 afi = bgp_node_afi(vty);
12319 safi = bgp_node_safi(vty);
734b349e 12320
d62a17ae 12321 ret = str2prefix(ip_str, &p);
12322 if (ret == 0) {
12323 vty_out(vty, "Malformed prefix\n");
12324 return CMD_WARNING_CONFIG_FAILED;
12325 }
718e3744 12326
c4efd0f4 12327 rn = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
d62a17ae 12328 if (!rn) {
12329 vty_out(vty, "Can't find specified prefix\n");
12330 return CMD_WARNING_CONFIG_FAILED;
12331 }
718e3744 12332
5b00b40e 12333 bdistance = bgp_node_get_bgp_distance_info(rn);
d62a17ae 12334 distance = atoi(distance_str);
1f9a9fff 12335
d62a17ae 12336 if (bdistance->distance != distance) {
12337 vty_out(vty, "Distance does not match configured\n");
12338 return CMD_WARNING_CONFIG_FAILED;
12339 }
718e3744 12340
0a22ddfb 12341 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 12342 bgp_distance_free(bdistance);
718e3744 12343
6f94b685 12344 bgp_node_set_bgp_path_info(rn, NULL);
d62a17ae 12345 bgp_unlock_node(rn);
12346 bgp_unlock_node(rn);
718e3744 12347
d62a17ae 12348 return CMD_SUCCESS;
718e3744 12349}
12350
718e3744 12351/* Apply BGP information to distance method. */
b8685f9b 12352uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 12353 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 12354{
12355 struct bgp_node *rn;
12356 struct prefix q;
12357 struct peer *peer;
12358 struct bgp_distance *bdistance;
12359 struct access_list *alist;
12360 struct bgp_static *bgp_static;
12361
12362 if (!bgp)
12363 return 0;
12364
40381db7 12365 peer = pinfo->peer;
d62a17ae 12366
7b7d48e5
DS
12367 if (pinfo->attr->distance)
12368 return pinfo->attr->distance;
12369
d62a17ae 12370 /* Check source address. */
12371 sockunion2hostprefix(&peer->su, &q);
12372 rn = bgp_node_match(bgp_distance_table[afi][safi], &q);
12373 if (rn) {
5b00b40e 12374 bdistance = bgp_node_get_bgp_distance_info(rn);
d62a17ae 12375 bgp_unlock_node(rn);
12376
12377 if (bdistance->access_list) {
12378 alist = access_list_lookup(afi, bdistance->access_list);
12379 if (alist
12380 && access_list_apply(alist, p) == FILTER_PERMIT)
12381 return bdistance->distance;
12382 } else
12383 return bdistance->distance;
718e3744 12384 }
718e3744 12385
d62a17ae 12386 /* Backdoor check. */
12387 rn = bgp_node_lookup(bgp->route[afi][safi], p);
12388 if (rn) {
5a8ba9fc 12389 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 12390 bgp_unlock_node(rn);
718e3744 12391
d62a17ae 12392 if (bgp_static->backdoor) {
12393 if (bgp->distance_local[afi][safi])
12394 return bgp->distance_local[afi][safi];
12395 else
12396 return ZEBRA_IBGP_DISTANCE_DEFAULT;
12397 }
718e3744 12398 }
718e3744 12399
d62a17ae 12400 if (peer->sort == BGP_PEER_EBGP) {
12401 if (bgp->distance_ebgp[afi][safi])
12402 return bgp->distance_ebgp[afi][safi];
12403 return ZEBRA_EBGP_DISTANCE_DEFAULT;
12404 } else {
12405 if (bgp->distance_ibgp[afi][safi])
12406 return bgp->distance_ibgp[afi][safi];
12407 return ZEBRA_IBGP_DISTANCE_DEFAULT;
12408 }
718e3744 12409}
12410
a612fb77
DA
12411/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
12412 * we should tell ZEBRA update the routes for a specific
12413 * AFI/SAFI to reflect changes in RIB.
12414 */
8b54bc30
DA
12415static void bgp_announce_routes_distance_update(struct bgp *bgp,
12416 afi_t update_afi,
12417 safi_t update_safi)
a612fb77
DA
12418{
12419 afi_t afi;
12420 safi_t safi;
12421
12422 FOREACH_AFI_SAFI (afi, safi) {
12423 if (!bgp_fibupd_safi(safi))
12424 continue;
12425
8b54bc30
DA
12426 if (afi != update_afi && safi != update_safi)
12427 continue;
12428
12429 if (BGP_DEBUG(zebra, ZEBRA))
12430 zlog_debug(
12431 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
12432 __func__, afi, safi);
12433 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
12434 }
12435}
12436
718e3744 12437DEFUN (bgp_distance,
12438 bgp_distance_cmd,
6147e2c6 12439 "distance bgp (1-255) (1-255) (1-255)",
718e3744 12440 "Define an administrative distance\n"
12441 "BGP distance\n"
12442 "Distance for routes external to the AS\n"
12443 "Distance for routes internal to the AS\n"
12444 "Distance for local routes\n")
12445{
d62a17ae 12446 VTY_DECLVAR_CONTEXT(bgp, bgp);
12447 int idx_number = 2;
12448 int idx_number_2 = 3;
12449 int idx_number_3 = 4;
8b54bc30
DA
12450 int distance_ebgp = atoi(argv[idx_number]->arg);
12451 int distance_ibgp = atoi(argv[idx_number_2]->arg);
12452 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 12453 afi_t afi;
12454 safi_t safi;
718e3744 12455
d62a17ae 12456 afi = bgp_node_afi(vty);
12457 safi = bgp_node_safi(vty);
718e3744 12458
8b54bc30
DA
12459 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
12460 || bgp->distance_ibgp[afi][safi] != distance_ibgp
12461 || bgp->distance_local[afi][safi] != distance_local) {
12462 bgp->distance_ebgp[afi][safi] = distance_ebgp;
12463 bgp->distance_ibgp[afi][safi] = distance_ibgp;
12464 bgp->distance_local[afi][safi] = distance_local;
12465 bgp_announce_routes_distance_update(bgp, afi, safi);
12466 }
d62a17ae 12467 return CMD_SUCCESS;
718e3744 12468}
12469
12470DEFUN (no_bgp_distance,
12471 no_bgp_distance_cmd,
a636c635 12472 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 12473 NO_STR
12474 "Define an administrative distance\n"
12475 "BGP distance\n"
12476 "Distance for routes external to the AS\n"
12477 "Distance for routes internal to the AS\n"
12478 "Distance for local routes\n")
12479{
d62a17ae 12480 VTY_DECLVAR_CONTEXT(bgp, bgp);
12481 afi_t afi;
12482 safi_t safi;
718e3744 12483
d62a17ae 12484 afi = bgp_node_afi(vty);
12485 safi = bgp_node_safi(vty);
718e3744 12486
8b54bc30
DA
12487 if (bgp->distance_ebgp[afi][safi] != 0
12488 || bgp->distance_ibgp[afi][safi] != 0
12489 || bgp->distance_local[afi][safi] != 0) {
12490 bgp->distance_ebgp[afi][safi] = 0;
12491 bgp->distance_ibgp[afi][safi] = 0;
12492 bgp->distance_local[afi][safi] = 0;
12493 bgp_announce_routes_distance_update(bgp, afi, safi);
12494 }
d62a17ae 12495 return CMD_SUCCESS;
718e3744 12496}
12497
718e3744 12498
12499DEFUN (bgp_distance_source,
12500 bgp_distance_source_cmd,
6147e2c6 12501 "distance (1-255) A.B.C.D/M",
718e3744 12502 "Define an administrative distance\n"
12503 "Administrative distance\n"
12504 "IP source prefix\n")
12505{
d62a17ae 12506 int idx_number = 1;
12507 int idx_ipv4_prefixlen = 2;
12508 bgp_distance_set(vty, argv[idx_number]->arg,
12509 argv[idx_ipv4_prefixlen]->arg, NULL);
12510 return CMD_SUCCESS;
718e3744 12511}
12512
12513DEFUN (no_bgp_distance_source,
12514 no_bgp_distance_source_cmd,
6147e2c6 12515 "no distance (1-255) A.B.C.D/M",
718e3744 12516 NO_STR
12517 "Define an administrative distance\n"
12518 "Administrative distance\n"
12519 "IP source prefix\n")
12520{
d62a17ae 12521 int idx_number = 2;
12522 int idx_ipv4_prefixlen = 3;
12523 bgp_distance_unset(vty, argv[idx_number]->arg,
12524 argv[idx_ipv4_prefixlen]->arg, NULL);
12525 return CMD_SUCCESS;
718e3744 12526}
12527
12528DEFUN (bgp_distance_source_access_list,
12529 bgp_distance_source_access_list_cmd,
6147e2c6 12530 "distance (1-255) A.B.C.D/M WORD",
718e3744 12531 "Define an administrative distance\n"
12532 "Administrative distance\n"
12533 "IP source prefix\n"
12534 "Access list name\n")
12535{
d62a17ae 12536 int idx_number = 1;
12537 int idx_ipv4_prefixlen = 2;
12538 int idx_word = 3;
12539 bgp_distance_set(vty, argv[idx_number]->arg,
12540 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12541 return CMD_SUCCESS;
718e3744 12542}
12543
12544DEFUN (no_bgp_distance_source_access_list,
12545 no_bgp_distance_source_access_list_cmd,
6147e2c6 12546 "no distance (1-255) A.B.C.D/M WORD",
718e3744 12547 NO_STR
12548 "Define an administrative distance\n"
12549 "Administrative distance\n"
12550 "IP source prefix\n"
12551 "Access list name\n")
12552{
d62a17ae 12553 int idx_number = 2;
12554 int idx_ipv4_prefixlen = 3;
12555 int idx_word = 4;
12556 bgp_distance_unset(vty, argv[idx_number]->arg,
12557 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12558 return CMD_SUCCESS;
718e3744 12559}
6b0655a2 12560
734b349e
MZ
12561DEFUN (ipv6_bgp_distance_source,
12562 ipv6_bgp_distance_source_cmd,
39e92c06 12563 "distance (1-255) X:X::X:X/M",
734b349e
MZ
12564 "Define an administrative distance\n"
12565 "Administrative distance\n"
12566 "IP source prefix\n")
12567{
d62a17ae 12568 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
12569 return CMD_SUCCESS;
734b349e
MZ
12570}
12571
12572DEFUN (no_ipv6_bgp_distance_source,
12573 no_ipv6_bgp_distance_source_cmd,
39e92c06 12574 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
12575 NO_STR
12576 "Define an administrative distance\n"
12577 "Administrative distance\n"
12578 "IP source prefix\n")
12579{
d62a17ae 12580 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
12581 return CMD_SUCCESS;
734b349e
MZ
12582}
12583
12584DEFUN (ipv6_bgp_distance_source_access_list,
12585 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12586 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12587 "Define an administrative distance\n"
12588 "Administrative distance\n"
12589 "IP source prefix\n"
12590 "Access list name\n")
12591{
d62a17ae 12592 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
12593 return CMD_SUCCESS;
734b349e
MZ
12594}
12595
12596DEFUN (no_ipv6_bgp_distance_source_access_list,
12597 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12598 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12599 NO_STR
12600 "Define an administrative distance\n"
12601 "Administrative distance\n"
12602 "IP source prefix\n"
12603 "Access list name\n")
12604{
d62a17ae 12605 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
12606 return CMD_SUCCESS;
734b349e
MZ
12607}
12608
718e3744 12609DEFUN (bgp_damp_set,
12610 bgp_damp_set_cmd,
31500417 12611 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 12612 "BGP Specific commands\n"
12613 "Enable route-flap dampening\n"
12614 "Half-life time for the penalty\n"
12615 "Value to start reusing a route\n"
12616 "Value to start suppressing a route\n"
12617 "Maximum duration to suppress a stable route\n")
12618{
d62a17ae 12619 VTY_DECLVAR_CONTEXT(bgp, bgp);
12620 int idx_half_life = 2;
12621 int idx_reuse = 3;
12622 int idx_suppress = 4;
12623 int idx_max_suppress = 5;
12624 int half = DEFAULT_HALF_LIFE * 60;
12625 int reuse = DEFAULT_REUSE;
12626 int suppress = DEFAULT_SUPPRESS;
12627 int max = 4 * half;
12628
12629 if (argc == 6) {
12630 half = atoi(argv[idx_half_life]->arg) * 60;
12631 reuse = atoi(argv[idx_reuse]->arg);
12632 suppress = atoi(argv[idx_suppress]->arg);
12633 max = atoi(argv[idx_max_suppress]->arg) * 60;
12634 } else if (argc == 3) {
12635 half = atoi(argv[idx_half_life]->arg) * 60;
12636 max = 4 * half;
12637 }
718e3744 12638
6d24b7cc
DS
12639 /*
12640 * These can't be 0 but our SA doesn't understand the
12641 * way our cli is constructed
12642 */
12643 assert(reuse);
12644 assert(half);
d62a17ae 12645 if (suppress < reuse) {
12646 vty_out(vty,
12647 "Suppress value cannot be less than reuse value \n");
12648 return 0;
12649 }
7ebe9748 12650
d62a17ae 12651 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
12652 reuse, suppress, max);
718e3744 12653}
12654
718e3744 12655DEFUN (bgp_damp_unset,
12656 bgp_damp_unset_cmd,
d04c479d 12657 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 12658 NO_STR
12659 "BGP Specific commands\n"
16cedbb0
QY
12660 "Enable route-flap dampening\n"
12661 "Half-life time for the penalty\n"
12662 "Value to start reusing a route\n"
12663 "Value to start suppressing a route\n"
12664 "Maximum duration to suppress a stable route\n")
718e3744 12665{
d62a17ae 12666 VTY_DECLVAR_CONTEXT(bgp, bgp);
12667 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 12668}
12669
718e3744 12670/* Display specified route of BGP table. */
d62a17ae 12671static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
12672 const char *ip_str, afi_t afi, safi_t safi,
12673 struct prefix_rd *prd, int prefix_check)
12674{
12675 int ret;
12676 struct prefix match;
12677 struct bgp_node *rn;
12678 struct bgp_node *rm;
40381db7
DS
12679 struct bgp_path_info *pi;
12680 struct bgp_path_info *pi_temp;
d62a17ae 12681 struct bgp *bgp;
12682 struct bgp_table *table;
12683
12684 /* BGP structure lookup. */
12685 if (view_name) {
12686 bgp = bgp_lookup_by_name(view_name);
12687 if (bgp == NULL) {
12688 vty_out(vty, "%% Can't find BGP instance %s\n",
12689 view_name);
12690 return CMD_WARNING;
12691 }
12692 } else {
12693 bgp = bgp_get_default();
12694 if (bgp == NULL) {
12695 vty_out(vty, "%% No BGP process is configured\n");
12696 return CMD_WARNING;
12697 }
718e3744 12698 }
718e3744 12699
d62a17ae 12700 /* Check IP address argument. */
12701 ret = str2prefix(ip_str, &match);
12702 if (!ret) {
12703 vty_out(vty, "%% address is malformed\n");
12704 return CMD_WARNING;
12705 }
718e3744 12706
d62a17ae 12707 match.family = afi2family(afi);
12708
12709 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
12710 || (safi == SAFI_EVPN)) {
12711 for (rn = bgp_table_top(bgp->rib[AFI_IP][safi]); rn;
12712 rn = bgp_route_next(rn)) {
b54892e0
DS
12713 const struct prefix *rn_p = bgp_node_get_prefix(rn);
12714
12715 if (prd && memcmp(rn_p->u.val, prd->val, 8) != 0)
d62a17ae 12716 continue;
67009e22
DS
12717 table = bgp_node_get_bgp_table_info(rn);
12718 if (!table)
ea47320b
DL
12719 continue;
12720 if ((rm = bgp_node_match(table, &match)) == NULL)
12721 continue;
d62a17ae 12722
b54892e0
DS
12723 const struct prefix *rm_p = bgp_node_get_prefix(rn);
12724
ea47320b 12725 if (!prefix_check
b54892e0 12726 || rm_p->prefixlen == match.prefixlen) {
6f94b685 12727 pi = bgp_node_get_bgp_path_info(rm);
40381db7
DS
12728 while (pi) {
12729 if (pi->extra && pi->extra->damp_info) {
12730 pi_temp = pi->next;
ea47320b 12731 bgp_damp_info_free(
40381db7 12732 pi->extra->damp_info,
a935f597 12733 1, afi, safi);
40381db7 12734 pi = pi_temp;
ea47320b 12735 } else
40381db7 12736 pi = pi->next;
d62a17ae 12737 }
ea47320b
DL
12738 }
12739
12740 bgp_unlock_node(rm);
d62a17ae 12741 }
12742 } else {
12743 if ((rn = bgp_node_match(bgp->rib[afi][safi], &match))
12744 != NULL) {
b54892e0
DS
12745 const struct prefix *rn_p = bgp_node_get_prefix(rn);
12746
d62a17ae 12747 if (!prefix_check
b54892e0 12748 || rn_p->prefixlen == match.prefixlen) {
6f94b685 12749 pi = bgp_node_get_bgp_path_info(rn);
40381db7
DS
12750 while (pi) {
12751 if (pi->extra && pi->extra->damp_info) {
12752 pi_temp = pi->next;
d62a17ae 12753 bgp_damp_info_free(
40381db7 12754 pi->extra->damp_info,
a935f597 12755 1, afi, safi);
40381db7 12756 pi = pi_temp;
d62a17ae 12757 } else
40381db7 12758 pi = pi->next;
d62a17ae 12759 }
12760 }
12761
12762 bgp_unlock_node(rn);
12763 }
12764 }
718e3744 12765
d62a17ae 12766 return CMD_SUCCESS;
718e3744 12767}
12768
12769DEFUN (clear_ip_bgp_dampening,
12770 clear_ip_bgp_dampening_cmd,
12771 "clear ip bgp dampening",
12772 CLEAR_STR
12773 IP_STR
12774 BGP_STR
12775 "Clear route flap dampening information\n")
12776{
a935f597 12777 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 12778 return CMD_SUCCESS;
718e3744 12779}
12780
12781DEFUN (clear_ip_bgp_dampening_prefix,
12782 clear_ip_bgp_dampening_prefix_cmd,
12783 "clear ip bgp dampening A.B.C.D/M",
12784 CLEAR_STR
12785 IP_STR
12786 BGP_STR
12787 "Clear route flap dampening information\n"
0c7b1b01 12788 "IPv4 prefix\n")
718e3744 12789{
d62a17ae 12790 int idx_ipv4_prefixlen = 4;
12791 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
12792 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 12793}
12794
12795DEFUN (clear_ip_bgp_dampening_address,
12796 clear_ip_bgp_dampening_address_cmd,
12797 "clear ip bgp dampening A.B.C.D",
12798 CLEAR_STR
12799 IP_STR
12800 BGP_STR
12801 "Clear route flap dampening information\n"
12802 "Network to clear damping information\n")
12803{
d62a17ae 12804 int idx_ipv4 = 4;
12805 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
12806 SAFI_UNICAST, NULL, 0);
718e3744 12807}
12808
12809DEFUN (clear_ip_bgp_dampening_address_mask,
12810 clear_ip_bgp_dampening_address_mask_cmd,
12811 "clear ip bgp dampening A.B.C.D A.B.C.D",
12812 CLEAR_STR
12813 IP_STR
12814 BGP_STR
12815 "Clear route flap dampening information\n"
12816 "Network to clear damping information\n"
12817 "Network mask\n")
12818{
d62a17ae 12819 int idx_ipv4 = 4;
12820 int idx_ipv4_2 = 5;
12821 int ret;
12822 char prefix_str[BUFSIZ];
718e3744 12823
d62a17ae 12824 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
12825 prefix_str);
12826 if (!ret) {
12827 vty_out(vty, "%% Inconsistent address and mask\n");
12828 return CMD_WARNING;
12829 }
718e3744 12830
d62a17ae 12831 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
12832 NULL, 0);
718e3744 12833}
6b0655a2 12834
e3b78da8 12835static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
12836{
12837 struct vty *vty = arg;
e3b78da8 12838 struct peer *peer = bucket->data;
825d9834
DS
12839 char buf[SU_ADDRSTRLEN];
12840
12841 vty_out(vty, "\tPeer: %s %s\n", peer->host,
12842 sockunion2str(&peer->su, buf, sizeof(buf)));
12843}
12844
2a0e69ae
DS
12845DEFUN (show_bgp_listeners,
12846 show_bgp_listeners_cmd,
12847 "show bgp listeners",
12848 SHOW_STR
12849 BGP_STR
12850 "Display Listen Sockets and who created them\n")
12851{
12852 bgp_dump_listener_info(vty);
12853
12854 return CMD_SUCCESS;
12855}
12856
825d9834
DS
12857DEFUN (show_bgp_peerhash,
12858 show_bgp_peerhash_cmd,
12859 "show bgp peerhash",
12860 SHOW_STR
12861 BGP_STR
12862 "Display information about the BGP peerhash\n")
12863{
12864 struct list *instances = bm->bgp;
12865 struct listnode *node;
12866 struct bgp *bgp;
12867
12868 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
12869 vty_out(vty, "BGP: %s\n", bgp->name);
12870 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
12871 vty);
12872 }
12873
12874 return CMD_SUCCESS;
12875}
12876
587ff0fd 12877/* also used for encap safi */
2b791107
DL
12878static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
12879 afi_t afi, safi_t safi)
d62a17ae 12880{
12881 struct bgp_node *prn;
12882 struct bgp_node *rn;
12883 struct bgp_table *table;
b54892e0
DS
12884 const struct prefix *p;
12885 const struct prefix_rd *prd;
d62a17ae 12886 struct bgp_static *bgp_static;
12887 mpls_label_t label;
12888 char buf[SU_ADDRSTRLEN];
12889 char rdbuf[RD_ADDRSTRLEN];
12890
12891 /* Network configuration. */
12892 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b 12893 prn = bgp_route_next(prn)) {
67009e22
DS
12894 table = bgp_node_get_bgp_table_info(prn);
12895 if (!table)
ea47320b 12896 continue;
d62a17ae 12897
60466a63 12898 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5a8ba9fc 12899 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12900 if (bgp_static == NULL)
ea47320b 12901 continue;
d62a17ae 12902
b54892e0
DS
12903 p = bgp_node_get_prefix(rn);
12904 prd = (const struct prefix_rd *)bgp_node_get_prefix(
12905 prn);
d62a17ae 12906
ea47320b 12907 /* "network" configuration display. */
06b9f471 12908 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
12909 label = decode_label(&bgp_static->label);
12910
12911 vty_out(vty, " network %s/%d rd %s",
12912 inet_ntop(p->family, &p->u.prefix, buf,
12913 SU_ADDRSTRLEN),
12914 p->prefixlen, rdbuf);
12915 if (safi == SAFI_MPLS_VPN)
12916 vty_out(vty, " label %u", label);
12917
12918 if (bgp_static->rmap.name)
12919 vty_out(vty, " route-map %s",
12920 bgp_static->rmap.name);
e2a86ad9
DS
12921
12922 if (bgp_static->backdoor)
12923 vty_out(vty, " backdoor");
12924
ea47320b
DL
12925 vty_out(vty, "\n");
12926 }
12927 }
d62a17ae 12928}
12929
2b791107
DL
12930static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
12931 afi_t afi, safi_t safi)
d62a17ae 12932{
12933 struct bgp_node *prn;
12934 struct bgp_node *rn;
12935 struct bgp_table *table;
b54892e0
DS
12936 const struct prefix *p;
12937 const struct prefix_rd *prd;
d62a17ae 12938 struct bgp_static *bgp_static;
ff44f570 12939 char buf[PREFIX_STRLEN * 2];
d62a17ae 12940 char buf2[SU_ADDRSTRLEN];
12941 char rdbuf[RD_ADDRSTRLEN];
12942
12943 /* Network configuration. */
12944 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b 12945 prn = bgp_route_next(prn)) {
67009e22
DS
12946 table = bgp_node_get_bgp_table_info(prn);
12947 if (!table)
ea47320b 12948 continue;
d62a17ae 12949
60466a63 12950 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5a8ba9fc 12951 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12952 if (bgp_static == NULL)
ea47320b 12953 continue;
d62a17ae 12954
ea47320b
DL
12955 char *macrouter = NULL;
12956 char *esi = NULL;
d62a17ae 12957
ea47320b
DL
12958 if (bgp_static->router_mac)
12959 macrouter = prefix_mac2str(
12960 bgp_static->router_mac, NULL, 0);
12961 if (bgp_static->eth_s_id)
12962 esi = esi2str(bgp_static->eth_s_id);
b54892e0
DS
12963 p = bgp_node_get_prefix(rn);
12964 prd = (struct prefix_rd *)bgp_node_get_prefix(prn);
d62a17ae 12965
ea47320b 12966 /* "network" configuration display. */
06b9f471 12967 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
12968 if (p->u.prefix_evpn.route_type == 5) {
12969 char local_buf[PREFIX_STRLEN];
3714a385 12970 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
12971 struct prefix_evpn *)p)
12972 ? AF_INET
12973 : AF_INET6;
3714a385 12974 inet_ntop(family,
12975 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a
PZ
12976 local_buf, PREFIX_STRLEN);
12977 sprintf(buf, "%s/%u", local_buf,
3714a385 12978 p->u.prefix_evpn.prefix_addr.ip_prefix_length);
197cb530
PG
12979 } else {
12980 prefix2str(p, buf, sizeof(buf));
12981 }
ea47320b 12982
a4d82a8a
PZ
12983 if (bgp_static->gatewayIp.family == AF_INET
12984 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
12985 inet_ntop(bgp_static->gatewayIp.family,
12986 &bgp_static->gatewayIp.u.prefix, buf2,
12987 sizeof(buf2));
ea47320b 12988 vty_out(vty,
7bcc8dac 12989 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 12990 buf, rdbuf,
12991 p->u.prefix_evpn.prefix_addr.eth_tag,
60466a63 12992 decode_label(&bgp_static->label), esi, buf2,
ea47320b
DL
12993 macrouter);
12994
0a22ddfb
QY
12995 XFREE(MTYPE_TMP, macrouter);
12996 XFREE(MTYPE_TMP, esi);
ea47320b
DL
12997 }
12998 }
3da6fcd5
PG
12999}
13000
718e3744 13001/* Configuration of static route announcement and aggregate
13002 information. */
2b791107
DL
13003void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
13004 safi_t safi)
d62a17ae 13005{
13006 struct bgp_node *rn;
b54892e0 13007 const struct prefix *p;
d62a17ae 13008 struct bgp_static *bgp_static;
13009 struct bgp_aggregate *bgp_aggregate;
13010 char buf[SU_ADDRSTRLEN];
13011
2b791107
DL
13012 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
13013 bgp_config_write_network_vpn(vty, bgp, afi, safi);
13014 return;
13015 }
d62a17ae 13016
2b791107
DL
13017 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
13018 bgp_config_write_network_evpn(vty, bgp, afi, safi);
13019 return;
13020 }
d62a17ae 13021
13022 /* Network configuration. */
13023 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
ea47320b 13024 rn = bgp_route_next(rn)) {
5a8ba9fc 13025 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 13026 if (bgp_static == NULL)
ea47320b 13027 continue;
d62a17ae 13028
b54892e0 13029 p = bgp_node_get_prefix(rn);
d62a17ae 13030
d8a9922d
DS
13031 vty_out(vty, " network %s/%d",
13032 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
13033 p->prefixlen);
d62a17ae 13034
ea47320b
DL
13035 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
13036 vty_out(vty, " label-index %u",
13037 bgp_static->label_index);
d62a17ae 13038
ea47320b
DL
13039 if (bgp_static->rmap.name)
13040 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
13041
13042 if (bgp_static->backdoor)
13043 vty_out(vty, " backdoor");
718e3744 13044
ea47320b
DL
13045 vty_out(vty, "\n");
13046 }
13047
d62a17ae 13048 /* Aggregate-address configuration. */
13049 for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn;
ea47320b 13050 rn = bgp_route_next(rn)) {
b613a918 13051 bgp_aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 13052 if (bgp_aggregate == NULL)
ea47320b 13053 continue;
d62a17ae 13054
b54892e0 13055 p = bgp_node_get_prefix(rn);
d62a17ae 13056
d8a9922d
DS
13057 vty_out(vty, " aggregate-address %s/%d",
13058 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
13059 p->prefixlen);
d62a17ae 13060
ea47320b
DL
13061 if (bgp_aggregate->as_set)
13062 vty_out(vty, " as-set");
d62a17ae 13063
ea47320b
DL
13064 if (bgp_aggregate->summary_only)
13065 vty_out(vty, " summary-only");
718e3744 13066
20894f50
DA
13067 if (bgp_aggregate->rmap.name)
13068 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
13069
229757f1
DA
13070 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
13071 vty_out(vty, " origin %s",
13072 bgp_origin2str(bgp_aggregate->origin));
13073
ea47320b
DL
13074 vty_out(vty, "\n");
13075 }
d62a17ae 13076}
734b349e 13077
2b791107 13078void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 13079 safi_t safi)
d62a17ae 13080{
13081 struct bgp_node *rn;
13082 struct bgp_distance *bdistance;
13083
13084 /* Distance configuration. */
13085 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
13086 && bgp->distance_local[afi][safi]
13087 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
13088 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
13089 || bgp->distance_local[afi][safi]
13090 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 13091 vty_out(vty, " distance bgp %d %d %d\n",
13092 bgp->distance_ebgp[afi][safi],
13093 bgp->distance_ibgp[afi][safi],
13094 bgp->distance_local[afi][safi]);
13095 }
734b349e 13096
d62a17ae 13097 for (rn = bgp_table_top(bgp_distance_table[afi][safi]); rn;
ca2e160d 13098 rn = bgp_route_next(rn)) {
5b00b40e 13099 bdistance = bgp_node_get_bgp_distance_info(rn);
b54892e0
DS
13100 if (bdistance != NULL)
13101 vty_out(vty, " distance %d %pRN %s\n",
13102 bdistance->distance, rn,
d62a17ae 13103 bdistance->access_list ? bdistance->access_list
13104 : "");
ca2e160d 13105 }
718e3744 13106}
13107
13108/* Allocate routing table structure and install commands. */
d62a17ae 13109void bgp_route_init(void)
13110{
13111 afi_t afi;
13112 safi_t safi;
13113
13114 /* Init BGP distance table. */
05c7a1cc 13115 FOREACH_AFI_SAFI (afi, safi)
960035b2 13116 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 13117
13118 /* IPv4 BGP commands. */
13119 install_element(BGP_NODE, &bgp_table_map_cmd);
13120 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 13121 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 13122
13123 install_element(BGP_NODE, &aggregate_address_cmd);
13124 install_element(BGP_NODE, &aggregate_address_mask_cmd);
13125 install_element(BGP_NODE, &no_aggregate_address_cmd);
13126 install_element(BGP_NODE, &no_aggregate_address_mask_cmd);
13127
13128 /* IPv4 unicast configuration. */
13129 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
13130 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 13131 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 13132
13133 install_element(BGP_IPV4_NODE, &aggregate_address_cmd);
13134 install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd);
13135 install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd);
13136 install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
13137
13138 /* IPv4 multicast configuration. */
13139 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
13140 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 13141 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
d62a17ae 13142 install_element(BGP_IPV4M_NODE, &aggregate_address_cmd);
13143 install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
13144 install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd);
13145 install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
13146
13147 /* IPv4 labeled-unicast configuration. */
13148 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
13149 install_element(VIEW_NODE, &show_ip_bgp_cmd);
7b2ff250 13150 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 13151 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
13152 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
13153
13154 install_element(VIEW_NODE,
13155 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
13156 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
13157 install_element(VIEW_NODE,
13158 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 13159#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 13160 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 13161#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 13162 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
13163 install_element(VIEW_NODE,
44c69747 13164 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 13165
d62a17ae 13166 /* BGP dampening clear commands */
13167 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
13168 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 13169
d62a17ae 13170 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
13171 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
13172
13173 /* prefix count */
13174 install_element(ENABLE_NODE,
13175 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 13176#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 13177 install_element(ENABLE_NODE,
13178 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 13179#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 13180
d62a17ae 13181 /* New config IPv6 BGP commands. */
13182 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
13183 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 13184 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 13185
13186 install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
13187 install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
13188
13189 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 13190
d62a17ae 13191 install_element(BGP_NODE, &bgp_distance_cmd);
13192 install_element(BGP_NODE, &no_bgp_distance_cmd);
13193 install_element(BGP_NODE, &bgp_distance_source_cmd);
13194 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
13195 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
13196 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
13197 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
13198 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
13199 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
13200 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
13201 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
13202 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
13203 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
13204 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
13205 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
13206 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
13207 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
13208 install_element(BGP_IPV4M_NODE,
13209 &no_bgp_distance_source_access_list_cmd);
13210 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
13211 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
13212 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
13213 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
13214 install_element(BGP_IPV6_NODE,
13215 &ipv6_bgp_distance_source_access_list_cmd);
13216 install_element(BGP_IPV6_NODE,
13217 &no_ipv6_bgp_distance_source_access_list_cmd);
13218 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
13219 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
13220 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
13221 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
13222 install_element(BGP_IPV6M_NODE,
13223 &ipv6_bgp_distance_source_access_list_cmd);
13224 install_element(BGP_IPV6M_NODE,
13225 &no_ipv6_bgp_distance_source_access_list_cmd);
13226
13227 install_element(BGP_NODE, &bgp_damp_set_cmd);
13228 install_element(BGP_NODE, &bgp_damp_unset_cmd);
13229 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
13230 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
13231
13232 /* IPv4 Multicast Mode */
13233 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
13234 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
13235
13236 /* Large Communities */
13237 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
13238 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
13239
13240 /* show bgp ipv4 flowspec detailed */
13241 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
13242
2a0e69ae 13243 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 13244 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 13245}
13246
13247void bgp_route_finish(void)
13248{
13249 afi_t afi;
13250 safi_t safi;
13251
05c7a1cc
QY
13252 FOREACH_AFI_SAFI (afi, safi) {
13253 bgp_table_unlock(bgp_distance_table[afi][safi]);
13254 bgp_distance_table[afi][safi] = NULL;
13255 }
228da428 13256}