]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
bgpd: use _RO list iter variant for gr macro
[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"
718e3744 72
65efcfce 73#if ENABLE_BGP_VNC
f8b6f499
LB
74#include "bgpd/rfapi/rfapi_backend.h"
75#include "bgpd/rfapi/vnc_import_bgp.h"
76#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 77#endif
aee875b5
PG
78#include "bgpd/bgp_encap_types.h"
79#include "bgpd/bgp_encap_tlv.h"
684a7227 80#include "bgpd/bgp_evpn.h"
3da6fcd5 81#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 82#include "bgpd/bgp_flowspec.h"
98a9dbc7 83#include "bgpd/bgp_flowspec_util.h"
45918cfb 84#include "bgpd/bgp_pbr.h"
65efcfce 85
e2a86ad9
DS
86#ifndef VTYSH_EXTRACT_PL
87#include "bgpd/bgp_route_clippy.c"
88#endif
aee875b5 89
718e3744 90/* Extern from bgp_dump.c */
dde72586
SH
91extern const char *bgp_origin_str[];
92extern const char *bgp_origin_long_str[];
f009ff26 93const char *get_afi_safi_str(afi_t afi,
94 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,
119 safi_t safi, struct prefix *p,
120 struct prefix_rd *prd)
121{
122 struct bgp_node *rn;
123 struct bgp_node *prn = NULL;
124
125 assert(table);
126 if (!table)
127 return NULL;
128
129 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
130 || (safi == SAFI_EVPN)) {
131 prn = bgp_node_get(table, (struct prefix *)prd);
132
67009e22
DS
133 if (!bgp_node_has_bgp_path_info_data(prn))
134 bgp_node_set_bgp_table_info(
135 prn, bgp_table_init(table->bgp, afi, safi));
d62a17ae 136 else
137 bgp_unlock_node(prn);
67009e22 138 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 139 }
718e3744 140
d62a17ae 141 rn = bgp_node_get(table, p);
718e3744 142
d62a17ae 143 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
144 || (safi == SAFI_EVPN))
145 rn->prn = prn;
718e3744 146
d62a17ae 147 return rn;
718e3744 148}
6b0655a2 149
d62a17ae 150struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
151 safi_t safi, struct prefix *p,
152 struct prefix_rd *prd)
128ea8ab 153{
d62a17ae 154 struct bgp_node *rn;
155 struct bgp_node *prn = NULL;
128ea8ab 156
d62a17ae 157 if (!table)
158 return NULL;
128ea8ab 159
d62a17ae 160 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
161 || (safi == SAFI_EVPN)) {
162 prn = bgp_node_lookup(table, (struct prefix *)prd);
163 if (!prn)
164 return NULL;
128ea8ab 165
6f94b685 166 if (!bgp_node_has_bgp_path_info_data(prn)) {
d62a17ae 167 bgp_unlock_node(prn);
168 return NULL;
169 }
128ea8ab 170
67009e22 171 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 172 }
128ea8ab 173
d62a17ae 174 rn = bgp_node_lookup(table, p);
128ea8ab 175
d62a17ae 176 return rn;
128ea8ab 177}
178
18ee8310
DS
179/* Allocate bgp_path_info_extra */
180static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 181{
4b7e6066
DS
182 struct bgp_path_info_extra *new;
183 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
184 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
185 new->label[0] = MPLS_INVALID_LABEL;
186 new->num_labels = 0;
3e3708cb
PG
187 new->bgp_fs_pbr = NULL;
188 new->bgp_fs_iprule = NULL;
d62a17ae 189 return new;
fb982c25
PJ
190}
191
a2e219fe 192void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 193{
4b7e6066 194 struct bgp_path_info_extra *e;
d62a17ae 195
c93a3b77
DS
196 if (!extra || !*extra)
197 return;
d62a17ae 198
c93a3b77
DS
199 e = *extra;
200 if (e->damp_info)
a935f597
DA
201 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
202 e->damp_info->safi);
d62a17ae 203
c93a3b77
DS
204 e->damp_info = NULL;
205 if (e->parent) {
40381db7 206 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 207
40381db7 208 if (bpi->net) {
0e70e6c8
DL
209 /* FIXME: since multiple e may have the same e->parent
210 * and e->parent->net is holding a refcount for each
211 * of them, we need to do some fudging here.
212 *
40381db7
DS
213 * WARNING: if bpi->net->lock drops to 0, bpi may be
214 * freed as well (because bpi->net was holding the
215 * last reference to bpi) => write after free!
0e70e6c8
DL
216 */
217 unsigned refcount;
218
40381db7
DS
219 bpi = bgp_path_info_lock(bpi);
220 refcount = bpi->net->lock - 1;
221 bgp_unlock_node((struct bgp_node *)bpi->net);
0e70e6c8 222 if (!refcount)
40381db7
DS
223 bpi->net = NULL;
224 bgp_path_info_unlock(bpi);
0e70e6c8 225 }
18ee8310 226 bgp_path_info_unlock(e->parent);
c93a3b77 227 e->parent = NULL;
d62a17ae 228 }
c93a3b77
DS
229
230 if (e->bgp_orig)
231 bgp_unlock(e->bgp_orig);
c26edcda 232
ce3c0614
PG
233 if ((*extra)->bgp_fs_iprule)
234 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 235 if ((*extra)->bgp_fs_pbr)
6a154c88 236 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77
DS
237 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
238
239 *extra = NULL;
fb982c25
PJ
240}
241
18ee8310
DS
242/* Get bgp_path_info extra information for the given bgp_path_info, lazy
243 * allocated if required.
fb982c25 244 */
40381db7 245struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 246{
40381db7
DS
247 if (!pi->extra)
248 pi->extra = bgp_path_info_extra_new();
249 return pi->extra;
fb982c25
PJ
250}
251
718e3744 252/* Free bgp route information. */
9b6d8fcf 253static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 254{
05864da7 255 bgp_attr_unintern(&path->attr);
fb018d25 256
9b6d8fcf
DS
257 bgp_unlink_nexthop(path);
258 bgp_path_info_extra_free(&path->extra);
259 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
260 if (path->net)
261 bgp_addpath_free_info_data(&path->tx_addpath,
262 &path->net->tx_addpath);
718e3744 263
9b6d8fcf 264 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 265
9b6d8fcf 266 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 267}
268
9b6d8fcf 269struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 270{
9b6d8fcf
DS
271 path->lock++;
272 return path;
200df115 273}
274
9b6d8fcf 275struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 276{
9b6d8fcf
DS
277 assert(path && path->lock > 0);
278 path->lock--;
d62a17ae 279
9b6d8fcf 280 if (path->lock == 0) {
200df115 281#if 0
282 zlog_debug ("%s: unlocked and freeing", __func__);
283 zlog_backtrace (LOG_DEBUG);
284#endif
9b6d8fcf 285 bgp_path_info_free(path);
d62a17ae 286 return NULL;
287 }
200df115 288
289#if 0
9b6d8fcf 290 if (path->lock == 1)
200df115 291 {
292 zlog_debug ("%s: unlocked to 1", __func__);
293 zlog_backtrace (LOG_DEBUG);
294 }
295#endif
d62a17ae 296
9b6d8fcf 297 return path;
200df115 298}
299
f009ff26 300/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
301static int bgp_node_set_defer_flag(struct bgp_node *rn, bool delete)
302{
303 struct peer *peer;
304 struct bgp_path_info *old_pi, *nextpi;
305 bool set_flag = 0;
306 struct bgp *bgp = NULL;
307 struct bgp_table *table = NULL;
308 afi_t afi = 0;
309 safi_t safi = 0;
310 char buf[PREFIX2STR_BUFFER];
311
312 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
313 * then the route selection is deferred
314 */
2ba1fe69 315 if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 316 return 0;
317
5f9c1aa2 318 if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED)) {
319 if (BGP_DEBUG(update, UPDATE_OUT)) {
320 prefix2str(&rn->p, buf, PREFIX2STR_BUFFER);
321 zlog_debug("Route %s is in workqueue and being processed, not deferred.",
322 buf);
323 }
324 return 0;
325 }
326
f009ff26 327 table = bgp_node_table(rn);
328 if (table) {
329 bgp = table->bgp;
330 afi = table->afi;
331 safi = table->safi;
332 }
333
334 for (old_pi = bgp_node_get_bgp_path_info(rn);
335 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
336 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
337 continue;
338
339 /* Route selection is deferred if there is a stale path which
340 * which indicates peer is in restart mode
341 */
342 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE) &&
343 (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
344 set_flag = 1;
345 } else {
346 /* If the peer is graceful restart capable and peer is
347 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
348 */
349 peer = old_pi->peer;
350 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer) &&
351 BGP_PEER_RESTARTING_MODE(peer) &&
352 (old_pi && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
353 set_flag = 1;
354 }
355 }
356 if (set_flag)
357 break;
358 }
359
360 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
361 * is active
362 */
2ba1fe69 363 if (set_flag && table) {
f009ff26 364 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
365 SET_FLAG(rn->flags, BGP_NODE_SELECT_DEFER);
366 prefix2str(&rn->p, buf, PREFIX2STR_BUFFER);
367 if (rn->rt_node == NULL)
368 rn->rt_node = listnode_add(
369 bgp->gr_info[afi][safi].route_list, rn);
370 if (BGP_DEBUG(update, UPDATE_OUT))
371 zlog_debug("DEFER route %s, rn %p, node %p",
372 buf, rn, rn->rt_node);
373 return 0;
374 }
375 }
376 return -1;
377}
378
40381db7 379void bgp_path_info_add(struct bgp_node *rn, struct bgp_path_info *pi)
718e3744 380{
4b7e6066 381 struct bgp_path_info *top;
718e3744 382
6f94b685 383 top = bgp_node_get_bgp_path_info(rn);
d62a17ae 384
6f94b685 385 pi->next = top;
40381db7 386 pi->prev = NULL;
d62a17ae 387 if (top)
40381db7 388 top->prev = pi;
6f94b685 389 bgp_node_set_bgp_path_info(rn, pi);
d62a17ae 390
40381db7 391 bgp_path_info_lock(pi);
d62a17ae 392 bgp_lock_node(rn);
40381db7 393 peer_lock(pi->peer); /* bgp_path_info peer reference */
f009ff26 394 bgp_node_set_defer_flag(rn, false);
718e3744 395}
396
d62a17ae 397/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 398 completion callback *only* */
40381db7 399void bgp_path_info_reap(struct bgp_node *rn, struct bgp_path_info *pi)
718e3744 400{
40381db7
DS
401 if (pi->next)
402 pi->next->prev = pi->prev;
403 if (pi->prev)
404 pi->prev->next = pi->next;
d62a17ae 405 else
6f94b685 406 bgp_node_set_bgp_path_info(rn, pi->next);
d62a17ae 407
40381db7
DS
408 bgp_path_info_mpath_dequeue(pi);
409 bgp_path_info_unlock(pi);
d62a17ae 410 bgp_unlock_node(rn);
718e3744 411}
412
40381db7 413void bgp_path_info_delete(struct bgp_node *rn, struct bgp_path_info *pi)
b40d939b 414{
40381db7 415 bgp_path_info_set_flag(rn, pi, BGP_PATH_REMOVED);
d62a17ae 416 /* set of previous already took care of pcount */
40381db7 417 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 418}
419
18ee8310 420/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
421 called when a route is deleted and then quickly re-added before the
422 deletion has been processed */
40381db7 423void bgp_path_info_restore(struct bgp_node *rn, struct bgp_path_info *pi)
8d45210e 424{
40381db7 425 bgp_path_info_unset_flag(rn, pi, BGP_PATH_REMOVED);
d62a17ae 426 /* unset of previous already took care of pcount */
40381db7 427 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
428}
429
d62a17ae 430/* Adjust pcount as required */
40381db7 431static void bgp_pcount_adjust(struct bgp_node *rn, struct bgp_path_info *pi)
1a392d46 432{
d62a17ae 433 struct bgp_table *table;
67174041 434
d62a17ae 435 assert(rn && bgp_node_table(rn));
40381db7 436 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 437
d62a17ae 438 table = bgp_node_table(rn);
67174041 439
40381db7 440 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 441 return;
442
40381db7
DS
443 if (!BGP_PATH_COUNTABLE(pi)
444 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 445
40381db7 446 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 447
448 /* slight hack, but more robust against errors. */
40381db7
DS
449 if (pi->peer->pcount[table->afi][table->safi])
450 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 451 else
450971aa 452 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 453 "Asked to decrement 0 prefix count for peer");
40381db7
DS
454 } else if (BGP_PATH_COUNTABLE(pi)
455 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
456 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
457 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 458 }
1a392d46
PJ
459}
460
40381db7
DS
461static int bgp_label_index_differs(struct bgp_path_info *pi1,
462 struct bgp_path_info *pi2)
28d58fd7 463{
40381db7 464 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 465}
1a392d46 466
18ee8310 467/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
468 * This is here primarily to keep prefix-count in check.
469 */
40381db7 470void bgp_path_info_set_flag(struct bgp_node *rn, struct bgp_path_info *pi,
18ee8310 471 uint32_t flag)
1a392d46 472{
40381db7 473 SET_FLAG(pi->flags, flag);
d62a17ae 474
475 /* early bath if we know it's not a flag that changes countability state
476 */
477 if (!CHECK_FLAG(flag,
1defdda8 478 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 479 return;
480
40381db7 481 bgp_pcount_adjust(rn, pi);
1a392d46
PJ
482}
483
40381db7 484void bgp_path_info_unset_flag(struct bgp_node *rn, struct bgp_path_info *pi,
18ee8310 485 uint32_t flag)
1a392d46 486{
40381db7 487 UNSET_FLAG(pi->flags, flag);
d62a17ae 488
489 /* early bath if we know it's not a flag that changes countability state
490 */
491 if (!CHECK_FLAG(flag,
1defdda8 492 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 493 return;
494
40381db7 495 bgp_pcount_adjust(rn, pi);
1a392d46
PJ
496}
497
718e3744 498/* Get MED value. If MED value is missing and "bgp bestpath
499 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 500static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 501{
502 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
503 return attr->med;
504 else {
505 if (bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST))
506 return BGP_MED_MAX;
507 else
508 return 0;
509 }
718e3744 510}
511
40381db7 512void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf)
2ec1e66f 513{
40381db7
DS
514 if (pi->addpath_rx_id)
515 sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
516 pi->addpath_rx_id);
d62a17ae 517 else
40381db7 518 sprintf(buf, "path %s", pi->peer->host);
d62a17ae 519}
9fbdd100 520
d62a17ae 521/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
522 */
18ee8310
DS
523static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
524 struct bgp_path_info *exist, int *paths_eq,
525 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
526 char *pfx_buf, afi_t afi, safi_t safi,
527 enum bgp_path_selection_reason *reason)
d62a17ae 528{
529 struct attr *newattr, *existattr;
530 bgp_peer_sort_t new_sort;
531 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
532 uint32_t new_pref;
533 uint32_t exist_pref;
534 uint32_t new_med;
535 uint32_t exist_med;
536 uint32_t new_weight;
537 uint32_t exist_weight;
d62a17ae 538 uint32_t newm, existm;
539 struct in_addr new_id;
540 struct in_addr exist_id;
541 int new_cluster;
542 int exist_cluster;
543 int internal_as_route;
544 int confed_as_route;
04d14c8b 545 int ret = 0;
d62a17ae 546 char new_buf[PATH_ADDPATH_STR_BUFFER];
547 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
548 uint32_t new_mm_seq;
549 uint32_t exist_mm_seq;
6d8c603a 550 int nh_cmp;
d62a17ae 551
552 *paths_eq = 0;
553
554 /* 0. Null check. */
555 if (new == NULL) {
fdf81fa0 556 *reason = bgp_path_selection_none;
d62a17ae 557 if (debug)
558 zlog_debug("%s: new is NULL", pfx_buf);
559 return 0;
560 }
2ec1e66f 561
d62a17ae 562 if (debug)
18ee8310 563 bgp_path_info_path_with_addpath_rx_str(new, new_buf);
718e3744 564
d62a17ae 565 if (exist == NULL) {
fdf81fa0 566 *reason = bgp_path_selection_first;
d62a17ae 567 if (debug)
568 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
569 new_buf);
570 return 1;
571 }
2ec1e66f 572
d62a17ae 573 if (debug) {
18ee8310 574 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
d62a17ae 575 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
576 pfx_buf, new_buf, new->flags, exist_buf,
577 exist->flags);
578 }
8ff56318 579
d62a17ae 580 newattr = new->attr;
581 existattr = exist->attr;
582
583 /* For EVPN routes, we cannot just go by local vs remote, we have to
584 * look at the MAC mobility sequence number, if present.
585 */
586 if (safi == SAFI_EVPN) {
587 /* This is an error condition described in RFC 7432 Section
588 * 15.2. The RFC
589 * states that in this scenario "the PE MUST alert the operator"
590 * but it
591 * does not state what other action to take. In order to provide
592 * some
593 * consistency in this scenario we are going to prefer the path
594 * with the
595 * sticky flag.
596 */
597 if (newattr->sticky != existattr->sticky) {
598 if (!debug) {
599 prefix2str(&new->net->p, pfx_buf,
600 sizeof(*pfx_buf)
601 * PREFIX2STR_BUFFER);
18ee8310
DS
602 bgp_path_info_path_with_addpath_rx_str(new,
603 new_buf);
604 bgp_path_info_path_with_addpath_rx_str(
605 exist, exist_buf);
d62a17ae 606 }
607
608 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 609 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
610 if (debug)
611 zlog_debug(
612 "%s: %s wins over %s due to sticky MAC flag",
613 pfx_buf, new_buf, exist_buf);
d62a17ae 614 return 1;
615 }
616
617 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 618 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
619 if (debug)
620 zlog_debug(
621 "%s: %s loses to %s due to sticky MAC flag",
622 pfx_buf, new_buf, exist_buf);
d62a17ae 623 return 0;
624 }
625 }
128ea8ab 626
d62a17ae 627 new_mm_seq = mac_mobility_seqnum(newattr);
628 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 629
d62a17ae 630 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 631 *reason = bgp_path_selection_evpn_seq;
d62a17ae 632 if (debug)
633 zlog_debug(
634 "%s: %s wins over %s due to MM seq %u > %u",
635 pfx_buf, new_buf, exist_buf, new_mm_seq,
636 exist_mm_seq);
637 return 1;
638 }
8ff56318 639
d62a17ae 640 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 641 *reason = bgp_path_selection_evpn_seq;
d62a17ae 642 if (debug)
643 zlog_debug(
644 "%s: %s loses to %s due to MM seq %u < %u",
645 pfx_buf, new_buf, exist_buf, new_mm_seq,
646 exist_mm_seq);
647 return 0;
648 }
6d8c603a
AK
649
650 /*
651 * if sequence numbers are the same path with the lowest IP
652 * wins
653 */
654 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
655 if (nh_cmp < 0) {
fdf81fa0 656 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
657 if (debug)
658 zlog_debug(
659 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
660 pfx_buf, new_buf, exist_buf, new_mm_seq,
661 inet_ntoa(new->attr->nexthop));
662 return 1;
663 }
664 if (nh_cmp > 0) {
fdf81fa0 665 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
666 if (debug)
667 zlog_debug(
668 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
669 pfx_buf, new_buf, exist_buf, new_mm_seq,
670 inet_ntoa(new->attr->nexthop));
671 return 0;
672 }
d62a17ae 673 }
9fbdd100 674
d62a17ae 675 /* 1. Weight check. */
d62a17ae 676 new_weight = newattr->weight;
677 exist_weight = existattr->weight;
8ff56318 678
d62a17ae 679 if (new_weight > exist_weight) {
fdf81fa0 680 *reason = bgp_path_selection_weight;
d62a17ae 681 if (debug)
682 zlog_debug("%s: %s wins over %s due to weight %d > %d",
683 pfx_buf, new_buf, exist_buf, new_weight,
684 exist_weight);
685 return 1;
686 }
718e3744 687
d62a17ae 688 if (new_weight < exist_weight) {
fdf81fa0 689 *reason = bgp_path_selection_weight;
d62a17ae 690 if (debug)
691 zlog_debug("%s: %s loses to %s due to weight %d < %d",
692 pfx_buf, new_buf, exist_buf, new_weight,
693 exist_weight);
694 return 0;
695 }
9fbdd100 696
d62a17ae 697 /* 2. Local preference check. */
698 new_pref = exist_pref = bgp->default_local_pref;
699
700 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
701 new_pref = newattr->local_pref;
702 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
703 exist_pref = existattr->local_pref;
704
705 if (new_pref > exist_pref) {
fdf81fa0 706 *reason = bgp_path_selection_local_pref;
d62a17ae 707 if (debug)
708 zlog_debug(
709 "%s: %s wins over %s due to localpref %d > %d",
710 pfx_buf, new_buf, exist_buf, new_pref,
711 exist_pref);
712 return 1;
713 }
718e3744 714
d62a17ae 715 if (new_pref < exist_pref) {
fdf81fa0 716 *reason = bgp_path_selection_local_pref;
d62a17ae 717 if (debug)
718 zlog_debug(
719 "%s: %s loses to %s due to localpref %d < %d",
720 pfx_buf, new_buf, exist_buf, new_pref,
721 exist_pref);
722 return 0;
723 }
9fbdd100 724
d62a17ae 725 /* 3. Local route check. We prefer:
726 * - BGP_ROUTE_STATIC
727 * - BGP_ROUTE_AGGREGATE
728 * - BGP_ROUTE_REDISTRIBUTE
729 */
90f4f482 730 if (!(new->sub_type == BGP_ROUTE_NORMAL ||
731 new->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 732 *reason = bgp_path_selection_local_route;
d62a17ae 733 if (debug)
734 zlog_debug(
735 "%s: %s wins over %s due to preferred BGP_ROUTE type",
736 pfx_buf, new_buf, exist_buf);
737 return 1;
738 }
718e3744 739
90f4f482 740 if (!(exist->sub_type == BGP_ROUTE_NORMAL ||
88493076 741 exist->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 742 *reason = bgp_path_selection_local_route;
d62a17ae 743 if (debug)
744 zlog_debug(
745 "%s: %s loses to %s due to preferred BGP_ROUTE type",
746 pfx_buf, new_buf, exist_buf);
747 return 0;
6811845b 748 }
718e3744 749
d62a17ae 750 /* 4. AS path length check. */
751 if (!bgp_flag_check(bgp, BGP_FLAG_ASPATH_IGNORE)) {
752 int exist_hops = aspath_count_hops(existattr->aspath);
753 int exist_confeds = aspath_count_confeds(existattr->aspath);
754
755 if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_CONFED)) {
756 int aspath_hops;
757
758 aspath_hops = aspath_count_hops(newattr->aspath);
759 aspath_hops += aspath_count_confeds(newattr->aspath);
760
761 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 762 *reason = bgp_path_selection_confed_as_path;
d62a17ae 763 if (debug)
764 zlog_debug(
765 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
766 pfx_buf, new_buf, exist_buf,
767 aspath_hops,
768 (exist_hops + exist_confeds));
769 return 1;
770 }
771
772 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 773 *reason = bgp_path_selection_confed_as_path;
d62a17ae 774 if (debug)
775 zlog_debug(
776 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
777 pfx_buf, new_buf, exist_buf,
778 aspath_hops,
779 (exist_hops + exist_confeds));
780 return 0;
781 }
782 } else {
783 int newhops = aspath_count_hops(newattr->aspath);
784
785 if (newhops < exist_hops) {
fdf81fa0 786 *reason = bgp_path_selection_as_path;
d62a17ae 787 if (debug)
788 zlog_debug(
789 "%s: %s wins over %s due to aspath hopcount %d < %d",
790 pfx_buf, new_buf, exist_buf,
791 newhops, exist_hops);
792 return 1;
793 }
794
795 if (newhops > exist_hops) {
fdf81fa0 796 *reason = bgp_path_selection_as_path;
d62a17ae 797 if (debug)
798 zlog_debug(
799 "%s: %s loses to %s due to aspath hopcount %d > %d",
800 pfx_buf, new_buf, exist_buf,
801 newhops, exist_hops);
802 return 0;
803 }
804 }
805 }
9fbdd100 806
d62a17ae 807 /* 5. Origin check. */
808 if (newattr->origin < existattr->origin) {
fdf81fa0 809 *reason = bgp_path_selection_origin;
d62a17ae 810 if (debug)
811 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
812 pfx_buf, new_buf, exist_buf,
813 bgp_origin_long_str[newattr->origin],
814 bgp_origin_long_str[existattr->origin]);
815 return 1;
816 }
718e3744 817
d62a17ae 818 if (newattr->origin > existattr->origin) {
fdf81fa0 819 *reason = bgp_path_selection_origin;
d62a17ae 820 if (debug)
821 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
822 pfx_buf, new_buf, exist_buf,
823 bgp_origin_long_str[newattr->origin],
824 bgp_origin_long_str[existattr->origin]);
825 return 0;
826 }
718e3744 827
d62a17ae 828 /* 6. MED check. */
829 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
830 && aspath_count_hops(existattr->aspath) == 0);
831 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
832 && aspath_count_confeds(existattr->aspath) > 0
833 && aspath_count_hops(newattr->aspath) == 0
834 && aspath_count_hops(existattr->aspath) == 0);
835
836 if (bgp_flag_check(bgp, BGP_FLAG_ALWAYS_COMPARE_MED)
837 || (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED) && confed_as_route)
838 || aspath_cmp_left(newattr->aspath, existattr->aspath)
839 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
840 || internal_as_route) {
841 new_med = bgp_med_value(new->attr, bgp);
842 exist_med = bgp_med_value(exist->attr, bgp);
843
844 if (new_med < exist_med) {
fdf81fa0 845 *reason = bgp_path_selection_med;
d62a17ae 846 if (debug)
847 zlog_debug(
848 "%s: %s wins over %s due to MED %d < %d",
849 pfx_buf, new_buf, exist_buf, new_med,
850 exist_med);
851 return 1;
852 }
8ff56318 853
d62a17ae 854 if (new_med > exist_med) {
fdf81fa0 855 *reason = bgp_path_selection_med;
d62a17ae 856 if (debug)
857 zlog_debug(
858 "%s: %s loses to %s due to MED %d > %d",
859 pfx_buf, new_buf, exist_buf, new_med,
860 exist_med);
861 return 0;
862 }
863 }
9fbdd100 864
d62a17ae 865 /* 7. Peer type check. */
866 new_sort = new->peer->sort;
867 exist_sort = exist->peer->sort;
868
869 if (new_sort == BGP_PEER_EBGP
870 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 871 *reason = bgp_path_selection_peer;
d62a17ae 872 if (debug)
873 zlog_debug(
874 "%s: %s wins over %s due to eBGP peer > iBGP peer",
875 pfx_buf, new_buf, exist_buf);
876 return 1;
877 }
718e3744 878
d62a17ae 879 if (exist_sort == BGP_PEER_EBGP
880 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 881 *reason = bgp_path_selection_peer;
d62a17ae 882 if (debug)
883 zlog_debug(
884 "%s: %s loses to %s due to iBGP peer < eBGP peer",
885 pfx_buf, new_buf, exist_buf);
886 return 0;
887 }
8ff56318 888
d62a17ae 889 /* 8. IGP metric check. */
890 newm = existm = 0;
8ff56318 891
d62a17ae 892 if (new->extra)
893 newm = new->extra->igpmetric;
894 if (exist->extra)
895 existm = exist->extra->igpmetric;
9fbdd100 896
d62a17ae 897 if (newm < existm) {
898 if (debug)
899 zlog_debug(
900 "%s: %s wins over %s due to IGP metric %d < %d",
901 pfx_buf, new_buf, exist_buf, newm, existm);
902 ret = 1;
903 }
718e3744 904
d62a17ae 905 if (newm > existm) {
906 if (debug)
907 zlog_debug(
908 "%s: %s loses to %s due to IGP metric %d > %d",
909 pfx_buf, new_buf, exist_buf, newm, existm);
910 ret = 0;
5e242b0d 911 }
5e242b0d 912
d62a17ae 913 /* 9. Same IGP metric. Compare the cluster list length as
914 representative of IGP hops metric. Rewrite the metric value
915 pair (newm, existm) with the cluster list length. Prefer the
916 path with smaller cluster list length. */
917 if (newm == existm) {
918 if (peer_sort(new->peer) == BGP_PEER_IBGP
919 && peer_sort(exist->peer) == BGP_PEER_IBGP
920 && (mpath_cfg == NULL
921 || CHECK_FLAG(
922 mpath_cfg->ibgp_flags,
923 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
924 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
925 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
926
927 if (newm < existm) {
928 if (debug)
929 zlog_debug(
930 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
931 pfx_buf, new_buf, exist_buf,
932 newm, existm);
933 ret = 1;
934 }
935
936 if (newm > existm) {
937 if (debug)
938 zlog_debug(
939 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
940 pfx_buf, new_buf, exist_buf,
941 newm, existm);
942 ret = 0;
943 }
944 }
945 }
31a4638f 946
d62a17ae 947 /* 10. confed-external vs. confed-internal */
948 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
949 if (new_sort == BGP_PEER_CONFED
950 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 951 *reason = bgp_path_selection_confed;
d62a17ae 952 if (debug)
953 zlog_debug(
954 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
955 pfx_buf, new_buf, exist_buf);
956 return 1;
957 }
718e3744 958
d62a17ae 959 if (exist_sort == BGP_PEER_CONFED
960 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 961 *reason = bgp_path_selection_confed;
d62a17ae 962 if (debug)
963 zlog_debug(
964 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
965 pfx_buf, new_buf, exist_buf);
966 return 0;
967 }
968 }
718e3744 969
d62a17ae 970 /* 11. Maximum path check. */
971 if (newm == existm) {
972 /* If one path has a label but the other does not, do not treat
973 * them as equals for multipath
974 */
a4d82a8a 975 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 976 != (exist->extra
b57ba6d2 977 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 978 if (debug)
979 zlog_debug(
980 "%s: %s and %s cannot be multipath, one has a label while the other does not",
981 pfx_buf, new_buf, exist_buf);
982 } else if (bgp_flag_check(bgp,
983 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
984
985 /*
986 * For the two paths, all comparison steps till IGP
987 * metric
988 * have succeeded - including AS_PATH hop count. Since
989 * 'bgp
990 * bestpath as-path multipath-relax' knob is on, we
991 * don't need
992 * an exact match of AS_PATH. Thus, mark the paths are
993 * equal.
994 * That will trigger both these paths to get into the
995 * multipath
996 * array.
997 */
998 *paths_eq = 1;
999
1000 if (debug)
1001 zlog_debug(
1002 "%s: %s and %s are equal via multipath-relax",
1003 pfx_buf, new_buf, exist_buf);
1004 } else if (new->peer->sort == BGP_PEER_IBGP) {
1005 if (aspath_cmp(new->attr->aspath,
1006 exist->attr->aspath)) {
1007 *paths_eq = 1;
1008
1009 if (debug)
1010 zlog_debug(
1011 "%s: %s and %s are equal via matching aspaths",
1012 pfx_buf, new_buf, exist_buf);
1013 }
1014 } else if (new->peer->as == exist->peer->as) {
1015 *paths_eq = 1;
1016
1017 if (debug)
1018 zlog_debug(
1019 "%s: %s and %s are equal via same remote-as",
1020 pfx_buf, new_buf, exist_buf);
1021 }
1022 } else {
1023 /*
1024 * TODO: If unequal cost ibgp multipath is enabled we can
1025 * mark the paths as equal here instead of returning
1026 */
1027 if (debug) {
1028 if (ret == 1)
1029 zlog_debug(
1030 "%s: %s wins over %s after IGP metric comparison",
1031 pfx_buf, new_buf, exist_buf);
1032 else
1033 zlog_debug(
1034 "%s: %s loses to %s after IGP metric comparison",
1035 pfx_buf, new_buf, exist_buf);
1036 }
fdf81fa0 1037 *reason = bgp_path_selection_igp_metric;
d62a17ae 1038 return ret;
1039 }
718e3744 1040
d62a17ae 1041 /* 12. If both paths are external, prefer the path that was received
1042 first (the oldest one). This step minimizes route-flap, since a
1043 newer path won't displace an older one, even if it was the
1044 preferred route based on the additional decision criteria below. */
1045 if (!bgp_flag_check(bgp, BGP_FLAG_COMPARE_ROUTER_ID)
1046 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1047 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1048 *reason = bgp_path_selection_older;
d62a17ae 1049 if (debug)
1050 zlog_debug(
1051 "%s: %s wins over %s due to oldest external",
1052 pfx_buf, new_buf, exist_buf);
1053 return 1;
1054 }
9fbdd100 1055
1defdda8 1056 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1057 *reason = bgp_path_selection_older;
d62a17ae 1058 if (debug)
1059 zlog_debug(
1060 "%s: %s loses to %s due to oldest external",
1061 pfx_buf, new_buf, exist_buf);
1062 return 0;
1063 }
1064 }
718e3744 1065
d62a17ae 1066 /* 13. Router-ID comparision. */
1067 /* If one of the paths is "stale", the corresponding peer router-id will
1068 * be 0 and would always win over the other path. If originator id is
1069 * used for the comparision, it will decide which path is better.
1070 */
1071 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1072 new_id.s_addr = newattr->originator_id.s_addr;
1073 else
1074 new_id.s_addr = new->peer->remote_id.s_addr;
1075 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1076 exist_id.s_addr = existattr->originator_id.s_addr;
1077 else
1078 exist_id.s_addr = exist->peer->remote_id.s_addr;
1079
1080 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1081 *reason = bgp_path_selection_router_id;
d62a17ae 1082 if (debug)
1083 zlog_debug(
1084 "%s: %s wins over %s due to Router-ID comparison",
1085 pfx_buf, new_buf, exist_buf);
1086 return 1;
1087 }
718e3744 1088
d62a17ae 1089 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1090 *reason = bgp_path_selection_router_id;
d62a17ae 1091 if (debug)
1092 zlog_debug(
1093 "%s: %s loses to %s due to Router-ID comparison",
1094 pfx_buf, new_buf, exist_buf);
1095 return 0;
1096 }
9fbdd100 1097
d62a17ae 1098 /* 14. Cluster length comparision. */
1099 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1100 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1101
1102 if (new_cluster < exist_cluster) {
fdf81fa0 1103 *reason = bgp_path_selection_cluster_length;
d62a17ae 1104 if (debug)
1105 zlog_debug(
1106 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1107 pfx_buf, new_buf, exist_buf, new_cluster,
1108 exist_cluster);
1109 return 1;
1110 }
718e3744 1111
d62a17ae 1112 if (new_cluster > exist_cluster) {
fdf81fa0 1113 *reason = bgp_path_selection_cluster_length;
d62a17ae 1114 if (debug)
1115 zlog_debug(
1116 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1117 pfx_buf, new_buf, exist_buf, new_cluster,
1118 exist_cluster);
1119 return 0;
1120 }
9fbdd100 1121
d62a17ae 1122 /* 15. Neighbor address comparision. */
1123 /* Do this only if neither path is "stale" as stale paths do not have
1124 * valid peer information (as the connection may or may not be up).
1125 */
1defdda8 1126 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1127 *reason = bgp_path_selection_stale;
d62a17ae 1128 if (debug)
1129 zlog_debug(
1130 "%s: %s wins over %s due to latter path being STALE",
1131 pfx_buf, new_buf, exist_buf);
1132 return 1;
1133 }
0de5153c 1134
1defdda8 1135 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1136 *reason = bgp_path_selection_stale;
d62a17ae 1137 if (debug)
1138 zlog_debug(
1139 "%s: %s loses to %s due to former path being STALE",
1140 pfx_buf, new_buf, exist_buf);
1141 return 0;
1142 }
718e3744 1143
d62a17ae 1144 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1145 if (new->peer->su_remote == NULL) {
1146 *reason = bgp_path_selection_local_configured;
d62a17ae 1147 return 0;
fdf81fa0
DS
1148 }
1149 if (exist->peer->su_remote == NULL) {
1150 *reason = bgp_path_selection_local_configured;
d62a17ae 1151 return 1;
fdf81fa0 1152 }
9fbdd100 1153
d62a17ae 1154 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1155
1156 if (ret == 1) {
fdf81fa0 1157 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1158 if (debug)
1159 zlog_debug(
1160 "%s: %s loses to %s due to Neighor IP comparison",
1161 pfx_buf, new_buf, exist_buf);
1162 return 0;
1163 }
1164
1165 if (ret == -1) {
fdf81fa0 1166 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1167 if (debug)
1168 zlog_debug(
1169 "%s: %s wins over %s due to Neighor IP comparison",
1170 pfx_buf, new_buf, exist_buf);
1171 return 1;
1172 }
9fbdd100 1173
fdf81fa0 1174 *reason = bgp_path_selection_default;
d62a17ae 1175 if (debug)
1176 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1177 pfx_buf, new_buf, exist_buf);
718e3744 1178
d62a17ae 1179 return 1;
718e3744 1180}
1181
65efcfce
LB
1182/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1183 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1184 * multipath is enabled
65efcfce 1185 * This version is compatible with */
18ee8310
DS
1186int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1187 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1188 afi_t afi, safi_t safi,
1189 enum bgp_path_selection_reason *reason)
d62a17ae 1190{
1191 int paths_eq;
1192 int ret;
18ee8310 1193 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1194 afi, safi, reason);
d62a17ae 1195
1196 if (paths_eq)
1197 ret = 0;
1198 else {
1199 if (ret == 1)
1200 ret = -1;
1201 else
1202 ret = 1;
1203 }
1204 return ret;
65efcfce
LB
1205}
1206
d62a17ae 1207static enum filter_type bgp_input_filter(struct peer *peer, struct prefix *p,
1208 struct attr *attr, afi_t afi,
1209 safi_t safi)
718e3744 1210{
d62a17ae 1211 struct bgp_filter *filter;
718e3744 1212
d62a17ae 1213 filter = &peer->filter[afi][safi];
718e3744 1214
d62a17ae 1215#define FILTER_EXIST_WARN(F, f, filter) \
1216 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1217 zlog_debug("%s: Could not find configured input %s-list %s!", \
1218 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1219
1220 if (DISTRIBUTE_IN_NAME(filter)) {
1221 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1222
1223 if (access_list_apply(DISTRIBUTE_IN(filter), p) == FILTER_DENY)
1224 return FILTER_DENY;
1225 }
1226
1227 if (PREFIX_LIST_IN_NAME(filter)) {
1228 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1229
1230 if (prefix_list_apply(PREFIX_LIST_IN(filter), p) == PREFIX_DENY)
1231 return FILTER_DENY;
1232 }
1233
1234 if (FILTER_LIST_IN_NAME(filter)) {
1235 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1236
1237 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
1238 == AS_FILTER_DENY)
1239 return FILTER_DENY;
1240 }
1241
1242 return FILTER_PERMIT;
650f76c2 1243#undef FILTER_EXIST_WARN
718e3744 1244}
1245
d62a17ae 1246static enum filter_type bgp_output_filter(struct peer *peer, struct prefix *p,
1247 struct attr *attr, afi_t afi,
1248 safi_t safi)
718e3744 1249{
d62a17ae 1250 struct bgp_filter *filter;
1251
1252 filter = &peer->filter[afi][safi];
1253
1254#define FILTER_EXIST_WARN(F, f, filter) \
1255 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1256 zlog_debug("%s: Could not find configured output %s-list %s!", \
1257 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1258
d62a17ae 1259 if (DISTRIBUTE_OUT_NAME(filter)) {
1260 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1261
d62a17ae 1262 if (access_list_apply(DISTRIBUTE_OUT(filter), p) == FILTER_DENY)
1263 return FILTER_DENY;
1264 }
1265
1266 if (PREFIX_LIST_OUT_NAME(filter)) {
1267 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1268
d62a17ae 1269 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
1270 == PREFIX_DENY)
1271 return FILTER_DENY;
1272 }
718e3744 1273
d62a17ae 1274 if (FILTER_LIST_OUT_NAME(filter)) {
1275 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1276
d62a17ae 1277 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
1278 == AS_FILTER_DENY)
1279 return FILTER_DENY;
1280 }
718e3744 1281
d62a17ae 1282 return FILTER_PERMIT;
650f76c2 1283#undef FILTER_EXIST_WARN
718e3744 1284}
1285
1286/* If community attribute includes no_export then return 1. */
d62a17ae 1287static int bgp_community_filter(struct peer *peer, struct attr *attr)
1288{
1289 if (attr->community) {
1290 /* NO_ADVERTISE check. */
1291 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
1292 return 1;
1293
1294 /* NO_EXPORT check. */
1295 if (peer->sort == BGP_PEER_EBGP
1296 && community_include(attr->community, COMMUNITY_NO_EXPORT))
1297 return 1;
1298
1299 /* NO_EXPORT_SUBCONFED check. */
1300 if (peer->sort == BGP_PEER_EBGP
1301 || peer->sort == BGP_PEER_CONFED)
1302 if (community_include(attr->community,
1303 COMMUNITY_NO_EXPORT_SUBCONFED))
1304 return 1;
1305 }
1306 return 0;
718e3744 1307}
1308
1309/* Route reflection loop check. */
d62a17ae 1310static int bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1311{
d62a17ae 1312 struct in_addr cluster_id;
718e3744 1313
d62a17ae 1314 if (attr->cluster) {
1315 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1316 cluster_id = peer->bgp->cluster_id;
1317 else
1318 cluster_id = peer->bgp->router_id;
1319
1320 if (cluster_loop_check(attr->cluster, cluster_id))
1321 return 1;
1322 }
1323 return 0;
718e3744 1324}
6b0655a2 1325
d62a17ae 1326static int bgp_input_modifier(struct peer *peer, struct prefix *p,
1327 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1328 const char *rmap_name, mpls_label_t *label,
196c6b09 1329 uint32_t num_labels, struct bgp_node *rn)
718e3744 1330{
d62a17ae 1331 struct bgp_filter *filter;
82b692c0
LK
1332 struct bgp_path_info rmap_path = { 0 };
1333 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1334 route_map_result_t ret;
1335 struct route_map *rmap = NULL;
718e3744 1336
d62a17ae 1337 filter = &peer->filter[afi][safi];
718e3744 1338
d62a17ae 1339 /* Apply default weight value. */
1340 if (peer->weight[afi][safi])
1341 attr->weight = peer->weight[afi][safi];
718e3744 1342
d62a17ae 1343 if (rmap_name) {
1344 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1345
d62a17ae 1346 if (rmap == NULL)
1347 return RMAP_DENY;
1348 } else {
1349 if (ROUTE_MAP_IN_NAME(filter)) {
1350 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1351
d62a17ae 1352 if (rmap == NULL)
1353 return RMAP_DENY;
1354 }
1355 }
0b16f239 1356
d62a17ae 1357 /* Route map apply. */
1358 if (rmap) {
40381db7 1359 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1360 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1361 rmap_path.peer = peer;
1362 rmap_path.attr = attr;
82b692c0 1363 rmap_path.extra = &extra;
196c6b09
LK
1364 rmap_path.net = rn;
1365
82b692c0
LK
1366 extra.num_labels = num_labels;
1367 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1368 memcpy(extra.label, label,
1369 num_labels * sizeof(mpls_label_t));
718e3744 1370
d62a17ae 1371 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1372
d62a17ae 1373 /* Apply BGP route map to the attribute. */
40381db7 1374 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
0b16f239 1375
d62a17ae 1376 peer->rmap_type = 0;
0b16f239 1377
1f2263be 1378 if (ret == RMAP_DENYMATCH)
d62a17ae 1379 return RMAP_DENY;
0b16f239 1380 }
d62a17ae 1381 return RMAP_PERMIT;
0b16f239
DS
1382}
1383
d62a17ae 1384static int bgp_output_modifier(struct peer *peer, struct prefix *p,
1385 struct attr *attr, afi_t afi, safi_t safi,
1386 const char *rmap_name)
0b16f239 1387{
40381db7 1388 struct bgp_path_info rmap_path;
d62a17ae 1389 route_map_result_t ret;
1390 struct route_map *rmap = NULL;
d7c0a89a 1391 uint8_t rmap_type;
0b16f239 1392
b787157a
DS
1393 /*
1394 * So if we get to this point and have no rmap_name
1395 * we want to just show the output as it currently
1396 * exists.
1397 */
1398 if (!rmap_name)
1399 return RMAP_PERMIT;
0b16f239 1400
d62a17ae 1401 /* Apply default weight value. */
1402 if (peer->weight[afi][safi])
1403 attr->weight = peer->weight[afi][safi];
0b16f239 1404
b787157a 1405 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1406
b787157a
DS
1407 /*
1408 * If we have a route map name and we do not find
1409 * the routemap that means we have an implicit
1410 * deny.
1411 */
1412 if (rmap == NULL)
1413 return RMAP_DENY;
0b16f239 1414
40381db7 1415 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1416 /* Route map apply. */
b787157a 1417 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1418 rmap_path.peer = peer;
1419 rmap_path.attr = attr;
0b16f239 1420
0f672529 1421 rmap_type = peer->rmap_type;
b787157a 1422 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1423
b787157a 1424 /* Apply BGP route map to the attribute. */
40381db7 1425 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
ac41b2a2 1426
0f672529 1427 peer->rmap_type = rmap_type;
b787157a
DS
1428
1429 if (ret == RMAP_DENYMATCH)
1430 /*
1431 * caller has multiple error paths with bgp_attr_flush()
1432 */
1433 return RMAP_DENY;
ac41b2a2 1434
d62a17ae 1435 return RMAP_PERMIT;
718e3744 1436}
6b0655a2 1437
5000f21c 1438/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1439static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1440 struct peer *peer, struct attr *attr)
1441{
1442 if (peer->sort == BGP_PEER_EBGP
1443 && (peer_af_flag_check(peer, afi, safi,
1444 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1445 || peer_af_flag_check(peer, afi, safi,
1446 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1447 || peer_af_flag_check(peer, afi, safi,
1448 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1449 || peer_af_flag_check(peer, afi, safi,
1450 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1451 // Take action on the entire aspath
1452 if (peer_af_flag_check(peer, afi, safi,
1453 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1454 || peer_af_flag_check(peer, afi, safi,
1455 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1456 if (peer_af_flag_check(
1457 peer, afi, safi,
1458 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1459 attr->aspath = aspath_replace_private_asns(
bf26b80e 1460 attr->aspath, bgp->as, peer->as);
d62a17ae 1461
1462 // The entire aspath consists of private ASNs so create
1463 // an empty aspath
1464 else if (aspath_private_as_check(attr->aspath))
1465 attr->aspath = aspath_empty_get();
1466
1467 // There are some public and some private ASNs, remove
1468 // the private ASNs
1469 else
1470 attr->aspath = aspath_remove_private_asns(
bf26b80e 1471 attr->aspath, peer->as);
d62a17ae 1472 }
1473
1474 // 'all' was not specified so the entire aspath must be private
1475 // ASNs
1476 // for us to do anything
1477 else if (aspath_private_as_check(attr->aspath)) {
1478 if (peer_af_flag_check(
1479 peer, afi, safi,
1480 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1481 attr->aspath = aspath_replace_private_asns(
bf26b80e 1482 attr->aspath, bgp->as, peer->as);
d62a17ae 1483 else
1484 attr->aspath = aspath_empty_get();
1485 }
1486 }
5000f21c
DS
1487}
1488
c7122e14 1489/* If this is an EBGP peer with as-override */
d62a17ae 1490static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1491 struct peer *peer, struct attr *attr)
1492{
1493 if (peer->sort == BGP_PEER_EBGP
1494 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1495 if (aspath_single_asn_check(attr->aspath, peer->as))
1496 attr->aspath = aspath_replace_specific_asn(
1497 attr->aspath, peer->as, bgp->as);
1498 }
1499}
1500
7f323236
DW
1501void bgp_attr_add_gshut_community(struct attr *attr)
1502{
1503 struct community *old;
1504 struct community *new;
1505 struct community *merge;
1506 struct community *gshut;
1507
1508 old = attr->community;
1509 gshut = community_str2com("graceful-shutdown");
1510
990f4f91 1511 assert(gshut);
1512
7f323236
DW
1513 if (old) {
1514 merge = community_merge(community_dup(old), gshut);
1515
a4d82a8a 1516 if (old->refcnt == 0)
3c1f53de 1517 community_free(&old);
7f323236
DW
1518
1519 new = community_uniq_sort(merge);
3c1f53de 1520 community_free(&merge);
7f323236
DW
1521 } else {
1522 new = community_dup(gshut);
1523 }
1524
3c1f53de 1525 community_free(&gshut);
7f323236
DW
1526 attr->community = new;
1527 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1528
1529 /* When we add the graceful-shutdown community we must also
1530 * lower the local-preference */
1531 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1532 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1533}
1534
1535
d7c0a89a 1536static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1537{
960035b2 1538 if (family == AF_INET) {
d62a17ae 1539 attr->nexthop.s_addr = 0;
960035b2
PZ
1540 attr->mp_nexthop_global_in.s_addr = 0;
1541 }
d62a17ae 1542 if (family == AF_INET6)
1543 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1544 if (family == AF_EVPN)
1545 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1546}
1547
40381db7 1548int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
d62a17ae 1549 struct update_subgroup *subgrp, struct prefix *p,
1550 struct attr *attr)
1551{
1552 struct bgp_filter *filter;
1553 struct peer *from;
1554 struct peer *peer;
1555 struct peer *onlypeer;
1556 struct bgp *bgp;
40381db7 1557 struct attr *piattr;
d62a17ae 1558 char buf[PREFIX_STRLEN];
b68885f9 1559 route_map_result_t ret;
d62a17ae 1560 int transparent;
1561 int reflect;
1562 afi_t afi;
1563 safi_t safi;
1564 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
1565
1566 if (DISABLE_BGP_ANNOUNCE)
1567 return 0;
1568
1569 afi = SUBGRP_AFI(subgrp);
1570 safi = SUBGRP_SAFI(subgrp);
1571 peer = SUBGRP_PEER(subgrp);
1572 onlypeer = NULL;
1573 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1574 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1575
40381db7 1576 from = pi->peer;
d62a17ae 1577 filter = &peer->filter[afi][safi];
1578 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1579 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1580 : pi->attr;
3f9c7369 1581
65efcfce 1582#if ENABLE_BGP_VNC
d62a17ae 1583 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1584 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1585 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1586
1587 /*
1588 * direct and direct_ext type routes originate internally even
1589 * though they can have peer pointers that reference other
1590 * systems
1591 */
1592 prefix2str(p, buf, PREFIX_STRLEN);
1593 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1594 __func__, buf);
1595 samepeer_safe = 1;
1596 }
65efcfce
LB
1597#endif
1598
ddb5b488
PZ
1599 if (((afi == AFI_IP) || (afi == AFI_IP6))
1600 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1601 && (pi->type == ZEBRA_ROUTE_BGP)
1602 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1603
1604 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1605
1606 samepeer_safe = 1;
1607 }
1608
d62a17ae 1609 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1610 * pi is valid */
1611 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1612 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1613 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 1614 return 0;
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)) {
d62a17ae 1622 return 0;
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)) {
1629 return 0;
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)
13b7e7f0
DS
1640 return 0;
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);
1653 return 0;
1654 }
1655 }
cd1964ff 1656
d62a17ae 1657 /* Do not send back route to sender. */
1658 if (onlypeer && from == onlypeer) {
1659 return 0;
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)
1667 return 0;
1668 else if (p->family == AF_INET6 && p->prefixlen == 0)
1669 return 0;
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");
1684 return 0;
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)));
1697 return 0;
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)));
1715 return 0;
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)));
1724 return 0;
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);
1735 return 0;
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);
1746 return 0;
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. */
1766 if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
1767 if (CHECK_FLAG(peer->af_flags[afi][safi],
1768 PEER_FLAG_REFLECTOR_CLIENT))
1769 return 0;
1770 } else {
1771 /* A route from a Non-client peer. Reflect to all other
1772 clients. */
1773 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1774 PEER_FLAG_REFLECTOR_CLIENT))
1775 return 0;
1776 }
1777 }
3f9c7369 1778
d62a17ae 1779 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1780 *attr = *piattr;
d62a17ae 1781
1782 /* If local-preference is not set. */
1783 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1784 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1785 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1786 attr->local_pref = bgp->default_local_pref;
3f9c7369 1787 }
3f9c7369 1788
d62a17ae 1789 /* If originator-id is not set and the route is to be reflected,
1790 set the originator id */
1791 if (reflect
1792 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1793 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1794 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1795 }
3f9c7369 1796
d62a17ae 1797 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1798 */
1799 if (peer->sort == BGP_PEER_EBGP
1800 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1801 if (from != bgp->peer_self && !transparent
1802 && !CHECK_FLAG(peer->af_flags[afi][safi],
1803 PEER_FLAG_MED_UNCHANGED))
1804 attr->flag &=
1805 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1806 }
3f9c7369 1807
d62a17ae 1808 /* Since the nexthop attribute can vary per peer, it is not explicitly
1809 * set
1810 * in announce check, only certain flags and length (or number of
1811 * nexthops
1812 * -- for IPv6/MP_REACH) are set here in order to guide the update
1813 * formation
1814 * code in setting the nexthop(s) on a per peer basis in
1815 * reformat_peer().
1816 * Typically, the source nexthop in the attribute is preserved but in
1817 * the
1818 * scenarios where we know it will always be overwritten, we reset the
1819 * nexthop to "0" in an attempt to achieve better Update packing. An
1820 * example of this is when a prefix from each of 2 IBGP peers needs to
1821 * be
1822 * announced to an EBGP peer (and they have the same attributes barring
1823 * their nexthop).
1824 */
1825 if (reflect)
1826 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1827
1828#define NEXTHOP_IS_V6 \
1829 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1830 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1831 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1832 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1833
1834 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1835 * if
1836 * the peer (group) is configured to receive link-local nexthop
1837 * unchanged
c728d027
DA
1838 * and it is available in the prefix OR we're not reflecting the route,
1839 * link-local nexthop address is valid and
d62a17ae 1840 * the peer (group) to whom we're going to announce is on a shared
1841 * network
1842 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
1843 * By checking if nexthop LL address is valid we are sure that
1844 * we do not announce LL address as `::`.
d62a17ae 1845 */
1846 if (NEXTHOP_IS_V6) {
1847 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
1848 if ((CHECK_FLAG(peer->af_flags[afi][safi],
1849 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
1850 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
1851 || (!reflect
1852 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
1853 && peer->shared_network
d62a17ae 1854 && (from == bgp->peer_self
1855 || peer->sort == BGP_PEER_EBGP))) {
1856 attr->mp_nexthop_len =
1857 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
1858 }
3f9c7369 1859
d62a17ae 1860 /* Clear off link-local nexthop in source, whenever it is not
1861 * needed to
1862 * ensure more prefixes share the same attribute for
1863 * announcement.
1864 */
1865 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
1866 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
1867 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
1868 }
3f9c7369 1869
d62a17ae 1870 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
1871 bgp_peer_as_override(bgp, afi, safi, peer, attr);
1872
1873 /* Route map & unsuppress-map apply. */
40381db7 1874 if (ROUTE_MAP_OUT_NAME(filter) || (pi->extra && pi->extra->suppress)) {
b8694ef4
DS
1875 struct bgp_path_info rmap_path = {0};
1876 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
1877 struct attr dummy_attr = {0};
d62a17ae 1878
40381db7
DS
1879 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
1880 rmap_path.peer = peer;
1881 rmap_path.attr = attr;
196c6b09 1882 rmap_path.net = rn;
d37ba549 1883
40381db7
DS
1884 if (pi->extra) {
1885 memcpy(&dummy_rmap_path_extra, pi->extra,
4b7e6066 1886 sizeof(struct bgp_path_info_extra));
40381db7 1887 rmap_path.extra = &dummy_rmap_path_extra;
16f7ce2b
MK
1888 }
1889
d62a17ae 1890 /* don't confuse inbound and outbound setting */
1891 RESET_FLAG(attr->rmap_change_flags);
1892
1893 /*
1894 * The route reflector is not allowed to modify the attributes
1895 * of the reflected IBGP routes unless explicitly allowed.
1896 */
1897 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1898 && !bgp_flag_check(bgp,
1899 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 1900 dummy_attr = *attr;
40381db7 1901 rmap_path.attr = &dummy_attr;
d62a17ae 1902 }
3f9c7369 1903
d62a17ae 1904 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 1905
40381db7 1906 if (pi->extra && pi->extra->suppress)
d62a17ae 1907 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
40381db7 1908 RMAP_BGP, &rmap_path);
d62a17ae 1909 else
1910 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
40381db7 1911 RMAP_BGP, &rmap_path);
d62a17ae 1912
1913 peer->rmap_type = 0;
1914
1915 if (ret == RMAP_DENYMATCH) {
778048bf
AD
1916 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1917 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1918 peer->host, prefix2str(p, buf, sizeof(buf)));
1919
d62a17ae 1920 bgp_attr_flush(attr);
1921 return 0;
1922 }
3f9c7369 1923 }
3f9c7369 1924
9dac9fc8
DA
1925 /* RFC 8212 to prevent route leaks.
1926 * This specification intends to improve this situation by requiring the
1927 * explicit configuration of both BGP Import and Export Policies for any
1928 * External BGP (EBGP) session such as customers, peers, or
1929 * confederation boundaries for all enabled address families. Through
1930 * codification of the aforementioned requirement, operators will
1931 * benefit from consistent behavior across different BGP
1932 * implementations.
1933 */
1934 if (peer->bgp->ebgp_requires_policy
1935 == DEFAULT_EBGP_POLICY_ENABLED)
1936 if (!bgp_outbound_policy_exists(peer, filter))
1937 return 0;
1938
fb29348a
DA
1939 /* draft-ietf-idr-deprecate-as-set-confed-set
1940 * Filter routes having AS_SET or AS_CONFED_SET in the path.
1941 * Eventually, This document (if approved) updates RFC 4271
1942 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
1943 * and obsoletes RFC 6472.
1944 */
1945 if (peer->bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED)
1946 if (aspath_check_as_sets(attr->aspath))
1947 return 0;
1948
7f323236 1949 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
a4d82a8a
PZ
1950 if (peer->sort == BGP_PEER_IBGP
1951 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
1952 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1953 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1954 } else {
1955 bgp_attr_add_gshut_community(attr);
1956 }
1957 }
1958
d62a17ae 1959 /* After route-map has been applied, we check to see if the nexthop to
1960 * be carried in the attribute (that is used for the announcement) can
1961 * be cleared off or not. We do this in all cases where we would be
1962 * setting the nexthop to "ourselves". For IPv6, we only need to
1963 * consider
1964 * the global nexthop here; the link-local nexthop would have been
1965 * cleared
1966 * already, and if not, it is required by the update formation code.
1967 * Also see earlier comments in this function.
1968 */
1969 /*
1970 * If route-map has performed some operation on the nexthop or the peer
1971 * configuration says to pass it unchanged, we cannot reset the nexthop
1972 * here, so only attempt to do it if these aren't true. Note that the
1973 * route-map handler itself might have cleared the nexthop, if for
1974 * example,
1975 * it is configured as 'peer-address'.
1976 */
1977 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 1978 piattr->rmap_change_flags)
d62a17ae 1979 && !transparent
1980 && !CHECK_FLAG(peer->af_flags[afi][safi],
1981 PEER_FLAG_NEXTHOP_UNCHANGED)) {
1982 /* We can reset the nexthop, if setting (or forcing) it to
1983 * 'self' */
1984 if (CHECK_FLAG(peer->af_flags[afi][safi],
1985 PEER_FLAG_NEXTHOP_SELF)
1986 || CHECK_FLAG(peer->af_flags[afi][safi],
1987 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
1988 if (!reflect
1989 || CHECK_FLAG(peer->af_flags[afi][safi],
1990 PEER_FLAG_FORCE_NEXTHOP_SELF))
1991 subgroup_announce_reset_nhop(
1992 (peer_cap_enhe(peer, afi, safi)
1993 ? AF_INET6
1994 : p->family),
1995 attr);
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,
2006 subgrp)))
d62a17ae 2007 subgroup_announce_reset_nhop(
2008 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2009 ? AF_INET6
2010 : p->family),
737af885
BS
2011 attr);
2012
2013 if ((p->family == AF_INET6) &&
2014 (!bgp_subgrp_multiaccess_check_v6(
2015 piattr->mp_nexthop_global,
2016 subgrp)))
2017 subgroup_announce_reset_nhop(
2018 (peer_cap_enhe(peer, afi, safi)
2019 ? AF_INET6
2020 : p->family),
2021 attr);
2022
2023
2024
40381db7 2025 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2026 /*
2027 * This flag is used for leaked vpn-vrf routes
2028 */
2029 int family = p->family;
2030
2031 if (peer_cap_enhe(peer, afi, safi))
2032 family = AF_INET6;
2033
2034 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2035 zlog_debug(
1defdda8 2036 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2037 __func__, family2str(family));
2038 subgroup_announce_reset_nhop(family, attr);
d62a17ae 2039 }
63696f1d 2040 }
960035b2 2041
63696f1d 2042 /* If IPv6/MP and nexthop does not have any override and happens
2043 * to
2044 * be a link-local address, reset it so that we don't pass along
2045 * the
2046 * source's link-local IPv6 address to recipients who may not be
2047 * on
2048 * the same interface.
2049 */
2050 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
2051 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global))
2052 subgroup_announce_reset_nhop(AF_INET6, attr);
d62a17ae 2053 }
3f9c7369 2054
d62a17ae 2055 return 1;
3f9c7369
DS
2056}
2057
f009ff26 2058static int bgp_route_select_timer_expire(struct thread *thread)
2059{
2060 struct afi_safi_info *info;
2061 afi_t afi;
2062 safi_t safi;
2063 struct bgp *bgp;
2064
2065 info = THREAD_ARG(thread);
2066 afi = info->afi;
2067 safi = info->safi;
2068 bgp = info->bgp;
2069
2070 if (BGP_DEBUG(update, UPDATE_OUT))
2071 zlog_debug("afi %d, safi %d : route select timer expired",
2072 afi, safi);
2073
2074 bgp->gr_info[afi][safi].t_route_select = NULL;
2075
2076 XFREE(MTYPE_TMP, info);
2077
2078 /* Best path selection */
2079 return bgp_best_path_select_defer(bgp, afi, safi);
2080}
2081
d62a17ae 2082void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
2083 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2084 struct bgp_path_info_pair *result, afi_t afi,
2085 safi_t safi)
2086{
2087 struct bgp_path_info *new_select;
2088 struct bgp_path_info *old_select;
40381db7
DS
2089 struct bgp_path_info *pi;
2090 struct bgp_path_info *pi1;
2091 struct bgp_path_info *pi2;
2092 struct bgp_path_info *nextpi = NULL;
d62a17ae 2093 int paths_eq, do_mpath, debug;
2094 struct list mp_list;
2095 char pfx_buf[PREFIX2STR_BUFFER];
2096 char path_buf[PATH_ADDPATH_STR_BUFFER];
2097
2098 bgp_mp_list_init(&mp_list);
2099 do_mpath =
2100 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2101
2102 debug = bgp_debug_bestpath(&rn->p);
2103
2104 if (debug)
2105 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2106
2107 /* bgp deterministic-med */
2108 new_select = NULL;
2109 if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)) {
2110
1defdda8 2111 /* Clear BGP_PATH_DMED_SELECTED for all paths */
6f94b685
DS
2112 for (pi1 = bgp_node_get_bgp_path_info(rn); pi1;
2113 pi1 = pi1->next)
40381db7 2114 bgp_path_info_unset_flag(rn, pi1,
18ee8310 2115 BGP_PATH_DMED_SELECTED);
d62a17ae 2116
6f94b685
DS
2117 for (pi1 = bgp_node_get_bgp_path_info(rn); pi1;
2118 pi1 = pi1->next) {
40381db7 2119 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2120 continue;
40381db7 2121 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2122 continue;
ea8b2282 2123 if (pi1->peer != bgp->peer_self)
40381db7 2124 if (pi1->peer->status != Established)
d62a17ae 2125 continue;
2126
40381db7
DS
2127 new_select = pi1;
2128 if (pi1->next) {
2129 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2130 if (CHECK_FLAG(pi2->flags,
1defdda8 2131 BGP_PATH_DMED_CHECK))
d62a17ae 2132 continue;
40381db7 2133 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2134 continue;
ea8b2282 2135 if (pi2->peer != bgp->peer_self
d62a17ae 2136 && !CHECK_FLAG(
ea8b2282
DS
2137 pi2->peer->sflags,
2138 PEER_STATUS_NSF_WAIT))
40381db7 2139 if (pi2->peer->status
d62a17ae 2140 != Established)
2141 continue;
2142
121e245d
DS
2143 if (!aspath_cmp_left(pi1->attr->aspath,
2144 pi2->attr->aspath)
2145 && !aspath_cmp_left_confed(
40381db7 2146 pi1->attr->aspath,
121e245d
DS
2147 pi2->attr->aspath))
2148 continue;
d62a17ae 2149
121e245d
DS
2150 if (bgp_path_info_cmp(
2151 bgp, pi2, new_select,
2152 &paths_eq, mpath_cfg, debug,
fdf81fa0
DS
2153 pfx_buf, afi, safi,
2154 &rn->reason)) {
121e245d
DS
2155 bgp_path_info_unset_flag(
2156 rn, new_select,
2157 BGP_PATH_DMED_SELECTED);
2158 new_select = pi2;
d62a17ae 2159 }
121e245d
DS
2160
2161 bgp_path_info_set_flag(
2162 rn, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2163 }
2164 }
18ee8310
DS
2165 bgp_path_info_set_flag(rn, new_select,
2166 BGP_PATH_DMED_CHECK);
2167 bgp_path_info_set_flag(rn, new_select,
2168 BGP_PATH_DMED_SELECTED);
d62a17ae 2169
2170 if (debug) {
18ee8310
DS
2171 bgp_path_info_path_with_addpath_rx_str(
2172 new_select, path_buf);
c66faab1 2173 zlog_debug("%s: %s is the bestpath from AS %u",
d62a17ae 2174 pfx_buf, path_buf,
2175 aspath_get_first_as(
2176 new_select->attr->aspath));
2177 }
2178 }
2179 }
96450faf 2180
d62a17ae 2181 /* Check old selected route and new selected route. */
2182 old_select = NULL;
2183 new_select = NULL;
6f94b685
DS
2184 for (pi = bgp_node_get_bgp_path_info(rn);
2185 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
40381db7
DS
2186 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2187 old_select = pi;
d62a17ae 2188
40381db7 2189 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2190 /* reap REMOVED routes, if needs be
2191 * selected route must stay for a while longer though
2192 */
40381db7
DS
2193 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2194 && (pi != old_select))
2195 bgp_path_info_reap(rn, pi);
d62a17ae 2196
ddb5b488 2197 if (debug)
40381db7
DS
2198 zlog_debug("%s: pi %p in holddown", __func__,
2199 pi);
ddb5b488 2200
d62a17ae 2201 continue;
2202 }
96450faf 2203
40381db7
DS
2204 if (pi->peer && pi->peer != bgp->peer_self
2205 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2206 if (pi->peer->status != Established) {
ddb5b488
PZ
2207
2208 if (debug)
2209 zlog_debug(
40381db7
DS
2210 "%s: pi %p non self peer %s not estab state",
2211 __func__, pi, pi->peer->host);
ddb5b488 2212
d62a17ae 2213 continue;
ddb5b488 2214 }
9fbdd100 2215
d62a17ae 2216 if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)
40381db7
DS
2217 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
2218 bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2219 if (debug)
40381db7 2220 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2221 continue;
2222 }
9fbdd100 2223
40381db7 2224 bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK);
06370dac 2225
40381db7 2226 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
fdf81fa0 2227 debug, pfx_buf, afi, safi, &rn->reason)) {
40381db7 2228 new_select = pi;
d62a17ae 2229 }
2230 }
718e3744 2231
d62a17ae 2232 /* Now that we know which path is the bestpath see if any of the other
2233 * paths
2234 * qualify as multipaths
2235 */
2236 if (debug) {
2237 if (new_select)
18ee8310
DS
2238 bgp_path_info_path_with_addpath_rx_str(new_select,
2239 path_buf);
d62a17ae 2240 else
2241 sprintf(path_buf, "NONE");
2242 zlog_debug(
2243 "%s: After path selection, newbest is %s oldbest was %s",
2244 pfx_buf, path_buf,
2245 old_select ? old_select->peer->host : "NONE");
96450faf 2246 }
9fbdd100 2247
d62a17ae 2248 if (do_mpath && new_select) {
6f94b685
DS
2249 for (pi = bgp_node_get_bgp_path_info(rn);
2250 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2251
2252 if (debug)
18ee8310 2253 bgp_path_info_path_with_addpath_rx_str(
40381db7 2254 pi, path_buf);
d62a17ae 2255
40381db7 2256 if (pi == new_select) {
d62a17ae 2257 if (debug)
2258 zlog_debug(
2259 "%s: %s is the bestpath, add to the multipath list",
2260 pfx_buf, path_buf);
40381db7 2261 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2262 continue;
2263 }
2264
40381db7 2265 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2266 continue;
2267
40381db7
DS
2268 if (pi->peer && pi->peer != bgp->peer_self
2269 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2270 PEER_STATUS_NSF_WAIT))
40381db7 2271 if (pi->peer->status != Established)
d62a17ae 2272 continue;
2273
40381db7 2274 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2275 if (debug)
2276 zlog_debug(
2277 "%s: %s has the same nexthop as the bestpath, skip it",
2278 pfx_buf, path_buf);
2279 continue;
2280 }
2281
40381db7 2282 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0
DS
2283 mpath_cfg, debug, pfx_buf, afi, safi,
2284 &rn->reason);
d62a17ae 2285
2286 if (paths_eq) {
2287 if (debug)
2288 zlog_debug(
2289 "%s: %s is equivalent to the bestpath, add to the multipath list",
2290 pfx_buf, path_buf);
40381db7 2291 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2292 }
2293 }
2294 }
fee0f4c6 2295
18ee8310
DS
2296 bgp_path_info_mpath_update(rn, new_select, old_select, &mp_list,
2297 mpath_cfg);
2298 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2299 bgp_mp_list_clear(&mp_list);
96450faf 2300
dcc68b5e
MS
2301 bgp_addpath_update_ids(bgp, rn, afi, safi);
2302
d62a17ae 2303 result->old = old_select;
2304 result->new = new_select;
96450faf 2305
d62a17ae 2306 return;
fee0f4c6 2307}
2308
3f9c7369
DS
2309/*
2310 * A new route/change in bestpath of an existing route. Evaluate the path
2311 * for advertisement to the subgroup.
2312 */
d62a17ae 2313int subgroup_process_announce_selected(struct update_subgroup *subgrp,
4b7e6066 2314 struct bgp_path_info *selected,
d62a17ae 2315 struct bgp_node *rn,
d7c0a89a 2316 uint32_t addpath_tx_id)
d62a17ae 2317{
2318 struct prefix *p;
2319 struct peer *onlypeer;
2320 struct attr attr;
2321 afi_t afi;
2322 safi_t safi;
adbac85e 2323
d62a17ae 2324 p = &rn->p;
2325 afi = SUBGRP_AFI(subgrp);
2326 safi = SUBGRP_SAFI(subgrp);
2327 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2328 : NULL);
2329
e0207895
PZ
2330 if (BGP_DEBUG(update, UPDATE_OUT)) {
2331 char buf_prefix[PREFIX_STRLEN];
2332 prefix2str(p, buf_prefix, sizeof(buf_prefix));
ddb5b488
PZ
2333 zlog_debug("%s: p=%s, selected=%p", __func__, buf_prefix,
2334 selected);
e0207895
PZ
2335 }
2336
d62a17ae 2337 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2338 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2339 PEER_STATUS_ORF_WAIT_REFRESH))
d62a17ae 2340 return 0;
2341
2342 memset(&attr, 0, sizeof(struct attr));
2343 /* It's initialized in bgp_announce_check() */
2344
2345 /* Announcement to the subgroup. If the route is filtered withdraw it.
2346 */
2347 if (selected) {
2348 if (subgroup_announce_check(rn, selected, subgrp, p, &attr))
2349 bgp_adj_out_set_subgroup(rn, subgrp, &attr, selected);
2350 else
2351 bgp_adj_out_unset_subgroup(rn, subgrp, 1,
dcc68b5e 2352 addpath_tx_id);
d62a17ae 2353 }
2354
2355 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2356 else {
2357 bgp_adj_out_unset_subgroup(rn, subgrp, 1, addpath_tx_id);
2358 }
558d1fec 2359
d62a17ae 2360 return 0;
200df115 2361}
fee0f4c6 2362
3064bf43 2363/*
e1072051 2364 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2365 * This is called at the end of route processing.
3064bf43 2366 */
d62a17ae 2367void bgp_zebra_clear_route_change_flags(struct bgp_node *rn)
3064bf43 2368{
40381db7 2369 struct bgp_path_info *pi;
3064bf43 2370
6f94b685 2371 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 2372 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2373 continue;
40381db7
DS
2374 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2375 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2376 }
3064bf43 2377}
2378
2379/*
2380 * Has the route changed from the RIB's perspective? This is invoked only
2381 * if the route selection returns the same best route as earlier - to
2382 * determine if we need to update zebra or not.
2383 */
4b7e6066
DS
2384int bgp_zebra_has_route_changed(struct bgp_node *rn,
2385 struct bgp_path_info *selected)
d62a17ae 2386{
4b7e6066 2387 struct bgp_path_info *mpinfo;
d62a17ae 2388
2bb9eff4
DS
2389 /* If this is multipath, check all selected paths for any nexthop
2390 * change or attribute change. Some attribute changes (e.g., community)
2391 * aren't of relevance to the RIB, but we'll update zebra to ensure
2392 * we handle the case of BGP nexthop change. This is the behavior
2393 * when the best path has an attribute change anyway.
d62a17ae 2394 */
1defdda8
DS
2395 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
2396 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG))
d62a17ae 2397 return 1;
2398
2bb9eff4
DS
2399 /*
2400 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2401 */
18ee8310
DS
2402 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2403 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2404 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2405 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
d62a17ae 2406 return 1;
2407 }
3064bf43 2408
d62a17ae 2409 /* Nothing has changed from the RIB's perspective. */
2410 return 0;
3064bf43 2411}
2412
d62a17ae 2413struct bgp_process_queue {
2414 struct bgp *bgp;
a4d82a8a 2415 STAILQ_HEAD(, bgp_node) pqueue;
aac24838
JB
2416#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2417 unsigned int flags;
2418 unsigned int queued;
200df115 2419};
2420
3103e8d2
DS
2421/*
2422 * old_select = The old best path
2423 * new_select = the new best path
2424 *
2425 * if (!old_select && new_select)
2426 * We are sending new information on.
2427 *
2428 * if (old_select && new_select) {
2429 * if (new_select != old_select)
2430 * We have a new best path send a change
2431 * else
2432 * We've received a update with new attributes that needs
2433 * to be passed on.
2434 * }
2435 *
2436 * if (old_select && !new_select)
2437 * We have no eligible route that we can announce or the rn
2438 * is being removed.
2439 */
aac24838
JB
2440static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
2441 afi_t afi, safi_t safi)
d62a17ae 2442{
4b7e6066
DS
2443 struct bgp_path_info *new_select;
2444 struct bgp_path_info *old_select;
2445 struct bgp_path_info_pair old_and_new;
ddb5b488
PZ
2446 char pfx_buf[PREFIX2STR_BUFFER];
2447 int debug = 0;
d62a17ae 2448
f4c713ae
LB
2449 if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS)) {
2450 if (rn)
2451 debug = bgp_debug_bestpath(&rn->p);
2452 if (debug) {
2453 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2454 zlog_debug(
2455 "%s: bgp delete in progress, ignoring event, p=%s",
2456 __func__, pfx_buf);
2457 }
2458 return;
2459 }
d62a17ae 2460 /* Is it end of initial update? (after startup) */
2461 if (!rn) {
2462 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2463 sizeof(bgp->update_delay_zebra_resume_time));
2464
2465 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2466 FOREACH_AFI_SAFI (afi, safi) {
2467 if (bgp_fibupd_safi(safi))
2468 bgp_zebra_announce_table(bgp, afi, safi);
2469 }
d62a17ae 2470 bgp->main_peers_update_hold = 0;
2471
2472 bgp_start_routeadv(bgp);
aac24838 2473 return;
d62a17ae 2474 }
cb1faec9 2475
b575a12c
A
2476 struct prefix *p = &rn->p;
2477
ddb5b488
PZ
2478 debug = bgp_debug_bestpath(&rn->p);
2479 if (debug) {
2480 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2481 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__, pfx_buf,
2482 afi2str(afi), safi2str(safi));
2483 }
2484
f009ff26 2485 /* The best path calculation for the route is deferred if
2486 * BGP_NODE_SELECT_DEFER is set
2487 */
2488 if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
2489 if (BGP_DEBUG(update, UPDATE_OUT))
2ba1fe69 2490 zlog_debug("SELECT_DEFER falg set for route %p", rn);
f009ff26 2491 return;
2492 }
2493
d62a17ae 2494 /* Best path selection. */
2495 bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new,
2496 afi, safi);
2497 old_select = old_and_new.old;
2498 new_select = old_and_new.new;
2499
2500 /* Do we need to allocate or free labels?
2501 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2502 * necessary to do this upon changes to best path. Exceptions:
2503 * - label index has changed -> recalculate resulting label
2504 * - path_info sub_type changed -> switch to/from implicit-null
2505 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2506 */
318cac96 2507 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2508 if (new_select) {
2509 if (!old_select
2510 || bgp_label_index_differs(new_select, old_select)
57592a53
AD
2511 || new_select->sub_type != old_select->sub_type
2512 || !bgp_is_valid_label(&rn->local_label)) {
2513 /* Enforced penultimate hop popping:
2514 * implicit-null for local routes, aggregate
2515 * and redistributed routes
2516 */
d62a17ae 2517 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2518 || new_select->sub_type
2519 == BGP_ROUTE_AGGREGATE
2520 || new_select->sub_type
2521 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2522 if (CHECK_FLAG(
2523 rn->flags,
2524 BGP_NODE_REGISTERED_FOR_LABEL))
2525 bgp_unregister_for_label(rn);
70e98a7f 2526 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
d62a17ae 2527 &rn->local_label);
2528 bgp_set_valid_label(&rn->local_label);
2529 } else
2530 bgp_register_for_label(rn, new_select);
2531 }
a4d82a8a
PZ
2532 } else if (CHECK_FLAG(rn->flags,
2533 BGP_NODE_REGISTERED_FOR_LABEL)) {
d62a17ae 2534 bgp_unregister_for_label(rn);
318cac96
DW
2535 }
2536 } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
2537 bgp_unregister_for_label(rn);
d62a17ae 2538 }
cd1964ff 2539
ddb5b488
PZ
2540 if (debug) {
2541 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2542 zlog_debug(
2543 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2544 __func__, pfx_buf, afi2str(afi), safi2str(safi),
2545 old_select, new_select);
2546 }
2547
d62a17ae 2548 /* If best route remains the same and this is not due to user-initiated
2549 * clear, see exactly what needs to be done.
2550 */
d62a17ae 2551 if (old_select && old_select == new_select
2552 && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
1defdda8 2553 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2554 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 2555 if (bgp_zebra_has_route_changed(rn, old_select)) {
65efcfce 2556#if ENABLE_BGP_VNC
d62a17ae 2557 vnc_import_bgp_add_route(bgp, p, old_select);
2558 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2559#endif
bb744275 2560 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2561 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2562
2563 if (new_select->type == ZEBRA_ROUTE_BGP
2564 && (new_select->sub_type == BGP_ROUTE_NORMAL
2565 || new_select->sub_type
2566 == BGP_ROUTE_IMPORTED))
2567
2568 bgp_zebra_announce(rn, p, old_select,
2569 bgp, afi, safi);
2570 }
d62a17ae 2571 }
1defdda8 2572 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
d62a17ae 2573 bgp_zebra_clear_route_change_flags(rn);
2574
2575 /* If there is a change of interest to peers, reannounce the
2576 * route. */
1defdda8 2577 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
d62a17ae 2578 || CHECK_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED)) {
2579 group_announce_route(bgp, afi, safi, rn, new_select);
2580
2581 /* unicast routes must also be annouced to
2582 * labeled-unicast update-groups */
2583 if (safi == SAFI_UNICAST)
2584 group_announce_route(bgp, afi,
2585 SAFI_LABELED_UNICAST, rn,
2586 new_select);
2587
1defdda8 2588 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2589 UNSET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED);
2590 }
fee0f4c6 2591
d62a17ae 2592 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2593 return;
d62a17ae 2594 }
8ad7271d 2595
d62a17ae 2596 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2597 */
2598 UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR);
2599
2600 /* bestpath has changed; bump version */
2601 if (old_select || new_select) {
2602 bgp_bump_version(rn);
2603
2604 if (!bgp->t_rmap_def_originate_eval) {
2605 bgp_lock(bgp);
2606 thread_add_timer(
2607 bm->master,
2608 update_group_refresh_default_originate_route_map,
2609 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2610 &bgp->t_rmap_def_originate_eval);
2611 }
2612 }
3f9c7369 2613
d62a17ae 2614 if (old_select)
18ee8310 2615 bgp_path_info_unset_flag(rn, old_select, BGP_PATH_SELECTED);
d62a17ae 2616 if (new_select) {
ddb5b488
PZ
2617 if (debug)
2618 zlog_debug("%s: setting SELECTED flag", __func__);
18ee8310
DS
2619 bgp_path_info_set_flag(rn, new_select, BGP_PATH_SELECTED);
2620 bgp_path_info_unset_flag(rn, new_select, BGP_PATH_ATTR_CHANGED);
1defdda8 2621 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
d62a17ae 2622 }
338b3424 2623
65efcfce 2624#if ENABLE_BGP_VNC
d62a17ae 2625 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2626 if (old_select != new_select) {
2627 if (old_select) {
2628 vnc_import_bgp_exterior_del_route(bgp, p,
2629 old_select);
2630 vnc_import_bgp_del_route(bgp, p, old_select);
2631 }
2632 if (new_select) {
2633 vnc_import_bgp_exterior_add_route(bgp, p,
2634 new_select);
2635 vnc_import_bgp_add_route(bgp, p, new_select);
2636 }
2637 }
2638 }
65efcfce
LB
2639#endif
2640
d62a17ae 2641 group_announce_route(bgp, afi, safi, rn, new_select);
2642
2643 /* unicast routes must also be annouced to labeled-unicast update-groups
2644 */
2645 if (safi == SAFI_UNICAST)
2646 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, rn,
2647 new_select);
2648
2649 /* FIB update. */
2650 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2651 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2652 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2653 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2654 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2655 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2656
2657 /* if this is an evpn imported type-5 prefix,
2658 * we need to withdraw the route first to clear
2659 * the nh neigh and the RMAC entry.
2660 */
2661 if (old_select &&
2662 is_route_parent_evpn(old_select))
2663 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2664
d62a17ae 2665 bgp_zebra_announce(rn, p, new_select, bgp, afi, safi);
2b659f33 2666 } else {
d62a17ae 2667 /* Withdraw the route from the kernel. */
2668 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2669 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2670 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2671 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2672
568e10ca 2673 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2674 }
718e3744 2675 }
3064bf43 2676
5424b7ba
MK
2677 /* advertise/withdraw type-5 routes */
2678 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
f106e3a7 2679 if (advertise_type5_routes(bgp, afi) &&
2680 new_select &&
2681 is_route_injectable_into_evpn(new_select)) {
7e4ed18e
MK
2682
2683 /* apply the route-map */
2684 if (bgp->adv_cmd_rmap[afi][safi].map) {
b68885f9 2685 route_map_result_t ret;
7e4ed18e 2686
3518f352
DS
2687 ret = route_map_apply(
2688 bgp->adv_cmd_rmap[afi][safi].map,
2689 &rn->p, RMAP_BGP, new_select);
b68885f9 2690 if (ret == RMAP_PERMITMATCH)
3518f352
DS
2691 bgp_evpn_advertise_type5_route(
2692 bgp, &rn->p, new_select->attr,
2693 afi, safi);
c27ee4c4 2694 else
2695 bgp_evpn_withdraw_type5_route(
2696 bgp, &rn->p, afi, safi);
7e4ed18e
MK
2697 } else {
2698 bgp_evpn_advertise_type5_route(bgp,
2699 &rn->p,
2700 new_select->attr,
2701 afi, safi);
2702
2703 }
f106e3a7 2704 } else if (advertise_type5_routes(bgp, afi) &&
2705 old_select &&
2706 is_route_injectable_into_evpn(old_select))
31310b25 2707 bgp_evpn_withdraw_type5_route(bgp, &rn->p, afi, safi);
5424b7ba
MK
2708 }
2709
d62a17ae 2710 /* Clear any route change flags. */
2711 bgp_zebra_clear_route_change_flags(rn);
3064bf43 2712
18ee8310 2713 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2714 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
18ee8310 2715 bgp_path_info_reap(rn, old_select);
d62a17ae 2716
2717 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2718 return;
718e3744 2719}
2720
f009ff26 2721/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2722int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2723{
2724 struct bgp_node *rn;
2725 int cnt = 0;
2726 struct afi_safi_info *thread_info;
2727 struct listnode *node = NULL, *nnode = NULL;
2728
2729 if (bgp->gr_info[afi][safi].t_route_select)
2730 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
2731
2732 if (BGP_DEBUG(update, UPDATE_OUT)) {
2733 zlog_debug("%s: processing route for %s : cnt %d",
2734 __func__, get_afi_safi_str(afi, safi, false),
2735 listcount(bgp->gr_info[afi][safi].route_list));
2736 }
2737
2738 /* Process the route list */
2739 node = listhead(bgp->gr_info[afi][safi].route_list);
f009ff26 2740 while (node) {
2741 rn = listgetdata(node);
2742 nnode = node->next;
2743 list_delete_node(bgp->gr_info[afi][safi].route_list, node);
2744 rn->rt_node = NULL;
2745
2746 if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
2747 UNSET_FLAG(rn->flags, BGP_NODE_SELECT_DEFER);
2748 bgp_process_main_one(bgp, rn, afi, safi);
2749 cnt++;
2750 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT)
2751 break;
2752 }
2753 node = nnode;
2754 }
2755
9e3b51a7 2756 /* Send EOR message when all routes are processed */
2757 if (list_isempty(bgp->gr_info[afi][safi].route_list)) {
2758 bgp_send_delayed_eor(bgp);
8c48b3b6 2759 /* Send route processing complete message to RIB */
2760 bgp_zebra_update(afi, safi, bgp->vrf_id,
2761 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 2762 return 0;
9e3b51a7 2763 }
f009ff26 2764
2765 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 2766
2767 thread_info->afi = afi;
2768 thread_info->safi = safi;
2769 thread_info->bgp = bgp;
2770
2771 /* If there are more routes to be processed, start the
2772 * selection timer
2773 */
2774 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
2775 BGP_ROUTE_SELECT_DELAY,
2776 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 2777 return 0;
2778}
2779
aac24838 2780static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 2781{
aac24838
JB
2782 struct bgp_process_queue *pqnode = data;
2783 struct bgp *bgp = pqnode->bgp;
d62a17ae 2784 struct bgp_table *table;
ac021f40 2785 struct bgp_node *rn;
aac24838
JB
2786
2787 /* eoiu marker */
2788 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
2789 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
2790 /* should always have dedicated wq call */
2791 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
2792 return WQ_SUCCESS;
2793 }
2794
ac021f40
LB
2795 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
2796 rn = STAILQ_FIRST(&pqnode->pqueue);
2797 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
b3e1dd3c 2798 STAILQ_NEXT(rn, pq) = NULL; /* complete unlink */
aac24838 2799 table = bgp_node_table(rn);
ac021f40 2800 /* note, new RNs may be added as part of processing */
aac24838 2801 bgp_process_main_one(bgp, rn, table->afi, table->safi);
cb1faec9 2802
aac24838 2803 bgp_unlock_node(rn);
d62a17ae 2804 bgp_table_unlock(table);
2805 }
aac24838
JB
2806
2807 return WQ_SUCCESS;
2808}
2809
2810static void bgp_processq_del(struct work_queue *wq, void *data)
2811{
2812 struct bgp_process_queue *pqnode = data;
2813
2814 bgp_unlock(pqnode->bgp);
2815
2816 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 2817}
2818
d62a17ae 2819void bgp_process_queue_init(void)
200df115 2820{
0ce1ca80 2821 if (!bm->process_main_queue)
d62a17ae 2822 bm->process_main_queue =
2823 work_queue_new(bm->master, "process_main_queue");
2824
aac24838 2825 bm->process_main_queue->spec.workfunc = &bgp_process_wq;
d62a17ae 2826 bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
2827 bm->process_main_queue->spec.max_retries = 0;
2828 bm->process_main_queue->spec.hold = 50;
2829 /* Use a higher yield value of 50ms for main queue processing */
2830 bm->process_main_queue->spec.yield = 50 * 1000L;
200df115 2831}
2832
cfe8d15a 2833static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
2834{
2835 struct bgp_process_queue *pqnode;
2836
a4d82a8a
PZ
2837 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
2838 sizeof(struct bgp_process_queue));
aac24838
JB
2839
2840 /* unlocked in bgp_processq_del */
2841 pqnode->bgp = bgp_lock(bgp);
2842 STAILQ_INIT(&pqnode->pqueue);
2843
aac24838
JB
2844 return pqnode;
2845}
2846
d62a17ae 2847void bgp_process(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)
fee0f4c6 2848{
aac24838
JB
2849#define ARBITRARY_PROCESS_QLEN 10000
2850 struct work_queue *wq = bm->process_main_queue;
d62a17ae 2851 struct bgp_process_queue *pqnode;
cfe8d15a 2852 int pqnode_reuse = 0;
495f0b13 2853
d62a17ae 2854 /* already scheduled for processing? */
2855 if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED))
2856 return;
2e02b9b2 2857
f009ff26 2858 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
2859 * the workqueue
2860 */
2861 if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
2862 if (BGP_DEBUG(update, UPDATE_OUT))
2863 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
2864 rn);
2865 return;
2866 }
2867
aac24838 2868 if (wq == NULL)
d62a17ae 2869 return;
2870
aac24838 2871 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
2872 limit only if is from the same BGP view and it's not an EOIU marker
2873 */
aac24838
JB
2874 if (work_queue_item_count(wq)) {
2875 struct work_queue_item *item = work_queue_last_item(wq);
2876 pqnode = item->data;
228da428 2877
a4d82a8a
PZ
2878 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
2879 || pqnode->bgp != bgp
2880 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
2881 pqnode = bgp_processq_alloc(bgp);
2882 else
2883 pqnode_reuse = 1;
aac24838 2884 } else
cfe8d15a 2885 pqnode = bgp_processq_alloc(bgp);
aac24838 2886 /* all unlocked in bgp_process_wq */
d62a17ae 2887 bgp_table_lock(bgp_node_table(rn));
aac24838 2888
d62a17ae 2889 SET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838
JB
2890 bgp_lock_node(rn);
2891
60466a63
QY
2892 /* can't be enqueued twice */
2893 assert(STAILQ_NEXT(rn, pq) == NULL);
aac24838
JB
2894 STAILQ_INSERT_TAIL(&pqnode->pqueue, rn, pq);
2895 pqnode->queued++;
2896
cfe8d15a
LB
2897 if (!pqnode_reuse)
2898 work_queue_add(wq, pqnode);
2899
d62a17ae 2900 return;
fee0f4c6 2901}
0a486e5f 2902
d62a17ae 2903void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 2904{
d62a17ae 2905 struct bgp_process_queue *pqnode;
cb1faec9 2906
d62a17ae 2907 if (bm->process_main_queue == NULL)
2908 return;
2e02b9b2 2909
cfe8d15a 2910 pqnode = bgp_processq_alloc(bgp);
cb1faec9 2911
aac24838 2912 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
cfe8d15a 2913 work_queue_add(bm->process_main_queue, pqnode);
cb1faec9
DS
2914}
2915
d62a17ae 2916static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 2917{
d62a17ae 2918 struct peer *peer;
0a486e5f 2919
d62a17ae 2920 peer = THREAD_ARG(thread);
2921 peer->t_pmax_restart = NULL;
0a486e5f 2922
d62a17ae 2923 if (bgp_debug_neighbor_events(peer))
2924 zlog_debug(
2925 "%s Maximum-prefix restart timer expired, restore peering",
2926 peer->host);
0a486e5f 2927
a9bafa95
DS
2928 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
2929 zlog_debug("%s: %s peer_clear failed",
2930 __PRETTY_FUNCTION__, peer->host);
0a486e5f 2931
d62a17ae 2932 return 0;
0a486e5f 2933}
2934
d62a17ae 2935int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
2936 int always)
718e3744 2937{
d62a17ae 2938 iana_afi_t pkt_afi;
5c525538 2939 iana_safi_t pkt_safi;
9cabb64b 2940
d62a17ae 2941 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
2942 return 0;
e0701b79 2943
d62a17ae 2944 if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) {
2945 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2946 PEER_STATUS_PREFIX_LIMIT)
2947 && !always)
2948 return 0;
e0701b79 2949
d62a17ae 2950 zlog_info(
a0a87037
DA
2951 "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32
2952 " exceed, limit %" PRIu32,
5cb5f4d0 2953 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 2954 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2955 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
2956
2957 if (CHECK_FLAG(peer->af_flags[afi][safi],
2958 PEER_FLAG_MAX_PREFIX_WARNING))
2959 return 0;
2960
2961 /* Convert AFI, SAFI to values for packet. */
2962 pkt_afi = afi_int2iana(afi);
2963 pkt_safi = safi_int2iana(safi);
2964 {
d7c0a89a 2965 uint8_t ndata[7];
d62a17ae 2966
2967 ndata[0] = (pkt_afi >> 8);
2968 ndata[1] = pkt_afi;
2969 ndata[2] = pkt_safi;
2970 ndata[3] = (peer->pmax[afi][safi] >> 24);
2971 ndata[4] = (peer->pmax[afi][safi] >> 16);
2972 ndata[5] = (peer->pmax[afi][safi] >> 8);
2973 ndata[6] = (peer->pmax[afi][safi]);
2974
2975 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2976 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
2977 BGP_NOTIFY_CEASE_MAX_PREFIX,
2978 ndata, 7);
2979 }
2980
2981 /* Dynamic peers will just close their connection. */
2982 if (peer_dynamic_neighbor(peer))
2983 return 1;
2984
2985 /* restart timer start */
2986 if (peer->pmax_restart[afi][safi]) {
2987 peer->v_pmax_restart =
2988 peer->pmax_restart[afi][safi] * 60;
2989
2990 if (bgp_debug_neighbor_events(peer))
2991 zlog_debug(
2992 "%s Maximum-prefix restart timer started for %d secs",
2993 peer->host, peer->v_pmax_restart);
2994
2995 BGP_TIMER_ON(peer->t_pmax_restart,
2996 bgp_maximum_prefix_restart_timer,
2997 peer->v_pmax_restart);
2998 }
2999
3000 return 1;
3001 } else
3002 UNSET_FLAG(peer->af_sflags[afi][safi],
3003 PEER_STATUS_PREFIX_LIMIT);
3004
3005 if (peer->pcount[afi][safi]
3006 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
3007 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3008 PEER_STATUS_PREFIX_THRESHOLD)
3009 && !always)
3010 return 0;
3011
3012 zlog_info(
a0a87037
DA
3013 "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32
3014 ", max %" PRIu32,
5cb5f4d0 3015 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 3016 peer->pcount[afi][safi], peer->pmax[afi][safi]);
3017 SET_FLAG(peer->af_sflags[afi][safi],
3018 PEER_STATUS_PREFIX_THRESHOLD);
3019 } else
3020 UNSET_FLAG(peer->af_sflags[afi][safi],
3021 PEER_STATUS_PREFIX_THRESHOLD);
3022 return 0;
718e3744 3023}
3024
b40d939b 3025/* Unconditionally remove the route from the RIB, without taking
3026 * damping into consideration (eg, because the session went down)
3027 */
40381db7 3028void bgp_rib_remove(struct bgp_node *rn, struct bgp_path_info *pi,
4b7e6066 3029 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3030{
f009ff26 3031
3032 struct bgp *bgp = NULL;
3033 bool delete_route = false;
3034
40381db7 3035 bgp_aggregate_decrement(peer->bgp, &rn->p, pi, afi, safi);
d62a17ae 3036
f009ff26 3037 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
40381db7 3038 bgp_path_info_delete(rn, pi); /* keep historical info */
d62a17ae 3039
f009ff26 3040 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3041 * flag
3042 */
3043 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3044 delete_route = true;
3045 else
3046 if (bgp_node_set_defer_flag(rn, true) < 0)
3047 delete_route = true;
3048 if (delete_route) {
3049 if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
3050 UNSET_FLAG(rn->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3051 bgp = pi->peer->bgp;
3052 if ((rn->rt_node) &&
3053 (bgp->gr_info[afi][safi]
3054 .route_list)) {
3055 list_delete_node(
3056 bgp->gr_info[afi][safi]
3057 .route_list,
3058 rn->rt_node);
3059 rn->rt_node = NULL;
3060 }
3061 }
3062 }
3063 }
4a11bf2c 3064
f009ff26 3065 hook_call(bgp_process, peer->bgp, afi, safi, rn, peer, true);
d62a17ae 3066 bgp_process(peer->bgp, rn, afi, safi);
3067}
3068
40381db7 3069static void bgp_rib_withdraw(struct bgp_node *rn, struct bgp_path_info *pi,
d62a17ae 3070 struct peer *peer, afi_t afi, safi_t safi,
3071 struct prefix_rd *prd)
3072{
d62a17ae 3073 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3074 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3075 */
3076 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3077 && peer->sort == BGP_PEER_EBGP)
40381db7 3078 if ((bgp_damp_withdraw(pi, rn, afi, safi, 0))
d62a17ae 3079 == BGP_DAMP_SUPPRESSED) {
40381db7 3080 bgp_aggregate_decrement(peer->bgp, &rn->p, pi, afi,
d62a17ae 3081 safi);
3082 return;
3083 }
3084
65efcfce 3085#if ENABLE_BGP_VNC
d62a17ae 3086 if (safi == SAFI_MPLS_VPN) {
3087 struct bgp_node *prn = NULL;
3088 struct bgp_table *table = NULL;
3089
3090 prn = bgp_node_get(peer->bgp->rib[afi][safi],
3091 (struct prefix *)prd);
67009e22
DS
3092 if (bgp_node_has_bgp_path_info_data(prn)) {
3093 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3094
3095 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3096 peer->bgp, prd, table, &rn->p, pi);
d62a17ae 3097 }
3098 bgp_unlock_node(prn);
3099 }
3100 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3101 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3102
40381db7 3103 vnc_import_bgp_del_route(peer->bgp, &rn->p, pi);
d62a17ae 3104 vnc_import_bgp_exterior_del_route(peer->bgp, &rn->p,
40381db7 3105 pi);
d62a17ae 3106 }
65efcfce 3107 }
d62a17ae 3108#endif
128ea8ab 3109
d62a17ae 3110 /* If this is an EVPN route, process for un-import. */
3111 if (safi == SAFI_EVPN)
40381db7 3112 bgp_evpn_unimport_route(peer->bgp, afi, safi, &rn->p, pi);
128ea8ab 3113
40381db7 3114 bgp_rib_remove(rn, pi, peer, afi, safi);
718e3744 3115}
3116
4b7e6066
DS
3117struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3118 struct peer *peer, struct attr *attr,
3119 struct bgp_node *rn)
fb018d25 3120{
4b7e6066 3121 struct bgp_path_info *new;
fb018d25 3122
d62a17ae 3123 /* Make new BGP info. */
4b7e6066 3124 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3125 new->type = type;
3126 new->instance = instance;
3127 new->sub_type = sub_type;
3128 new->peer = peer;
3129 new->attr = attr;
3130 new->uptime = bgp_clock();
3131 new->net = rn;
d62a17ae 3132 return new;
fb018d25
DS
3133}
3134
d62a17ae 3135static void overlay_index_update(struct attr *attr,
3136 struct eth_segment_id *eth_s_id,
3137 union gw_addr *gw_ip)
684a7227 3138{
d62a17ae 3139 if (!attr)
3140 return;
684a7227 3141
d62a17ae 3142 if (eth_s_id == NULL) {
3143 memset(&(attr->evpn_overlay.eth_s_id), 0,
3144 sizeof(struct eth_segment_id));
3145 } else {
3146 memcpy(&(attr->evpn_overlay.eth_s_id), eth_s_id,
3147 sizeof(struct eth_segment_id));
3148 }
3149 if (gw_ip == NULL) {
3150 memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr));
3151 } else {
3152 memcpy(&(attr->evpn_overlay.gw_ip), gw_ip,
3153 sizeof(union gw_addr));
3154 }
684a7227
PG
3155}
3156
40381db7 3157static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3158 struct eth_segment_id *eth_s_id,
3159 union gw_addr *gw_ip)
3160{
40381db7
DS
3161 struct eth_segment_id *path_eth_s_id, *path_eth_s_id_remote;
3162 union gw_addr *path_gw_ip, *path_gw_ip_remote;
11ebf4ed
DS
3163 union {
3164 struct eth_segment_id esi;
3165 union gw_addr ip;
3166 } temp;
d62a17ae 3167
3168 if (afi != AFI_L2VPN)
3169 return true;
11ebf4ed 3170
05864da7
DS
3171 path_eth_s_id = &(path->attr->evpn_overlay.eth_s_id);
3172 path_gw_ip = &(path->attr->evpn_overlay.gw_ip);
11ebf4ed
DS
3173
3174 if (gw_ip == NULL) {
3175 memset(&temp, 0, sizeof(temp));
40381db7 3176 path_gw_ip_remote = &temp.ip;
11ebf4ed 3177 } else
40381db7 3178 path_gw_ip_remote = gw_ip;
11ebf4ed
DS
3179
3180 if (eth_s_id == NULL) {
3181 memset(&temp, 0, sizeof(temp));
40381db7 3182 path_eth_s_id_remote = &temp.esi;
11ebf4ed 3183 } else
40381db7 3184 path_eth_s_id_remote = eth_s_id;
11ebf4ed 3185
40381db7 3186 if (!memcmp(path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr)))
d62a17ae 3187 return false;
11ebf4ed 3188
40381db7 3189 return !memcmp(path_eth_s_id, path_eth_s_id_remote,
d62a17ae 3190 sizeof(struct eth_segment_id));
684a7227
PG
3191}
3192
c265ee22 3193/* Check if received nexthop is valid or not. */
d62a17ae 3194static int bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
949b0f24 3195 uint8_t type, uint8_t stype,
3196 struct attr *attr, struct bgp_node *rn)
d62a17ae 3197{
3198 int ret = 0;
3199
3200 /* Only validated for unicast and multicast currently. */
3201 /* Also valid for EVPN where the nexthop is an IP address. */
3202 if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN)
3203 return 0;
3204
3205 /* If NEXT_HOP is present, validate it. */
3206 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
3207 if (attr->nexthop.s_addr == 0
3208 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
949b0f24 3209 || bgp_nexthop_self(bgp, afi, type, stype,
3210 attr, rn))
d62a17ae 3211 return 1;
3212 }
c265ee22 3213
d62a17ae 3214 /* If MP_NEXTHOP is present, validate it. */
3215 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3216 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3217 * it is not an IPv6 link-local address.
3218 */
3219 if (attr->mp_nexthop_len) {
3220 switch (attr->mp_nexthop_len) {
3221 case BGP_ATTR_NHLEN_IPV4:
3222 case BGP_ATTR_NHLEN_VPNV4:
3223 ret = (attr->mp_nexthop_global_in.s_addr == 0
3224 || IPV4_CLASS_DE(ntohl(
3225 attr->mp_nexthop_global_in.s_addr))
949b0f24 3226 || bgp_nexthop_self(bgp, afi, type, stype,
3227 attr, rn));
d62a17ae 3228 break;
3229
3230 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
3231 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3232 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
3233 ret = (IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global)
3234 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3235 || IN6_IS_ADDR_MULTICAST(
949b0f24 3236 &attr->mp_nexthop_global)
3237 || bgp_nexthop_self(bgp, afi, type, stype,
3238 attr, rn));
d62a17ae 3239 break;
3240
3241 default:
3242 ret = 1;
3243 break;
3244 }
3245 }
c265ee22 3246
d62a17ae 3247 return ret;
3248}
3249
d7c0a89a 3250int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
d62a17ae 3251 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3252 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3253 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3254 struct bgp_route_evpn *evpn)
d62a17ae 3255{
3256 int ret;
3257 int aspath_loop_count = 0;
3258 struct bgp_node *rn;
3259 struct bgp *bgp;
3260 struct attr new_attr;
3261 struct attr *attr_new;
40381db7 3262 struct bgp_path_info *pi;
4b7e6066
DS
3263 struct bgp_path_info *new;
3264 struct bgp_path_info_extra *extra;
d62a17ae 3265 const char *reason;
3266 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3267 int connected = 0;
3268 int do_loop_check = 1;
3269 int has_valid_label = 0;
7c312383 3270 afi_t nh_afi;
949b0f24 3271 uint8_t pi_type = 0;
3272 uint8_t pi_sub_type = 0;
3273
65efcfce 3274#if ENABLE_BGP_VNC
d62a17ae 3275 int vnc_implicit_withdraw = 0;
65efcfce 3276#endif
d62a17ae 3277 int same_attr = 0;
718e3744 3278
d62a17ae 3279 memset(&new_attr, 0, sizeof(struct attr));
3280 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3281 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3282
d62a17ae 3283 bgp = peer->bgp;
3284 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3285 /* TODO: Check to see if we can get rid of "is_valid_label" */
3286 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3287 has_valid_label = (num_labels > 0) ? 1 : 0;
3288 else
3289 has_valid_label = bgp_is_valid_label(label);
718e3744 3290
d62a17ae 3291 /* When peer's soft reconfiguration enabled. Record input packet in
3292 Adj-RIBs-In. */
3293 if (!soft_reconfig
3294 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3295 && peer != bgp->peer_self)
3296 bgp_adj_in_set(rn, peer, attr, addpath_id);
3297
3298 /* Check previously received route. */
6f94b685 3299 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
3300 if (pi->peer == peer && pi->type == type
3301 && pi->sub_type == sub_type
3302 && pi->addpath_rx_id == addpath_id)
d62a17ae 3303 break;
3304
3305 /* AS path local-as loop check. */
3306 if (peer->change_local_as) {
c4368918
DW
3307 if (peer->allowas_in[afi][safi])
3308 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3309 else if (!CHECK_FLAG(peer->flags,
3310 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3311 aspath_loop_count = 1;
3312
3313 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3314 > aspath_loop_count) {
b4d46cc9 3315 peer->stat_pfx_aspath_loop++;
d62a17ae 3316 reason = "as-path contains our own AS;";
3317 goto filtered;
3318 }
718e3744 3319 }
718e3744 3320
d62a17ae 3321 /* If the peer is configured for "allowas-in origin" and the last ASN in
3322 * the
3323 * as-path is our ASN then we do not need to call aspath_loop_check
3324 */
3325 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3326 if (aspath_get_last_as(attr->aspath) == bgp->as)
3327 do_loop_check = 0;
3328
3329 /* AS path loop check. */
3330 if (do_loop_check) {
3331 if (aspath_loop_check(attr->aspath, bgp->as)
3332 > peer->allowas_in[afi][safi]
3333 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3334 && aspath_loop_check(attr->aspath, bgp->confed_id)
3335 > peer->allowas_in[afi][safi])) {
b4d46cc9 3336 peer->stat_pfx_aspath_loop++;
d62a17ae 3337 reason = "as-path contains our own AS;";
3338 goto filtered;
3339 }
3340 }
aac9ef6c 3341
d62a17ae 3342 /* Route reflector originator ID check. */
3343 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3344 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3345 peer->stat_pfx_originator_loop++;
d62a17ae 3346 reason = "originator is us;";
3347 goto filtered;
3348 }
718e3744 3349
d62a17ae 3350 /* Route reflector cluster ID check. */
3351 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3352 peer->stat_pfx_cluster_loop++;
d62a17ae 3353 reason = "reflected from the same cluster;";
3354 goto filtered;
3355 }
718e3744 3356
d62a17ae 3357 /* Apply incoming filter. */
3358 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3359 peer->stat_pfx_filter++;
d62a17ae 3360 reason = "filter;";
3361 goto filtered;
3362 }
718e3744 3363
a8b72dc6
DA
3364 /* RFC 8212 to prevent route leaks.
3365 * This specification intends to improve this situation by requiring the
3366 * explicit configuration of both BGP Import and Export Policies for any
3367 * External BGP (EBGP) session such as customers, peers, or
3368 * confederation boundaries for all enabled address families. Through
3369 * codification of the aforementioned requirement, operators will
3370 * benefit from consistent behavior across different BGP
3371 * implementations.
3372 */
3373 if (peer->bgp->ebgp_requires_policy == DEFAULT_EBGP_POLICY_ENABLED)
3374 if (!bgp_inbound_policy_exists(peer,
3375 &peer->filter[afi][safi])) {
3376 reason = "inbound policy missing";
3377 goto filtered;
3378 }
3379
fb29348a
DA
3380 /* draft-ietf-idr-deprecate-as-set-confed-set
3381 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3382 * Eventually, This document (if approved) updates RFC 4271
3383 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3384 * and obsoletes RFC 6472.
3385 */
3386 if (peer->bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED)
3387 if (aspath_check_as_sets(attr->aspath)) {
3388 reason =
3389 "as-path contains AS_SET or AS_CONFED_SET type;";
3390 goto filtered;
3391 }
3392
6f4f49b2 3393 new_attr = *attr;
d62a17ae 3394
3395 /* Apply incoming route-map.
3396 * NB: new_attr may now contain newly allocated values from route-map
3397 * "set"
3398 * commands, so we need bgp_attr_flush in the error paths, until we
3399 * intern
3400 * the attr (which takes over the memory references) */
82b692c0 3401 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL,
196c6b09 3402 label, num_labels, rn) == RMAP_DENY) {
b4d46cc9 3403 peer->stat_pfx_filter++;
d62a17ae 3404 reason = "route-map;";
3405 bgp_attr_flush(&new_attr);
3406 goto filtered;
3407 }
718e3744 3408
05864da7 3409 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3410 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3411 /* remove from RIB previous entry */
3412 bgp_zebra_withdraw(p, pi, bgp, safi);
3413 }
3414
7f323236
DW
3415 if (peer->sort == BGP_PEER_EBGP) {
3416
a4d82a8a
PZ
3417 /* If we receive the graceful-shutdown community from an eBGP
3418 * peer we must lower local-preference */
3419 if (new_attr.community
3420 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3421 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3422 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3423
a4d82a8a
PZ
3424 /* If graceful-shutdown is configured then add the GSHUT
3425 * community to all paths received from eBGP peers */
3426 } else if (bgp_flag_check(peer->bgp,
3427 BGP_FLAG_GRACEFUL_SHUTDOWN)) {
7f323236
DW
3428 bgp_attr_add_gshut_community(&new_attr);
3429 }
3430 }
3431
949b0f24 3432 if (pi) {
3433 pi_type = pi->type;
3434 pi_sub_type = pi->sub_type;
3435 }
3436
d62a17ae 3437 /* next hop check. */
a4d82a8a 3438 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
949b0f24 3439 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type,
3440 pi_sub_type, &new_attr, rn)) {
b4d46cc9 3441 peer->stat_pfx_nh_invalid++;
d62a17ae 3442 reason = "martian or self next-hop;";
3443 bgp_attr_flush(&new_attr);
3444 goto filtered;
3445 }
718e3744 3446
5c14a191 3447 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3448 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3449 reason = "self mac;";
3450 goto filtered;
3451 }
3452
d62a17ae 3453 attr_new = bgp_attr_intern(&new_attr);
3454
3455 /* If the update is implicit withdraw. */
40381db7
DS
3456 if (pi) {
3457 pi->uptime = bgp_clock();
3458 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3459
4a11bf2c
DL
3460 hook_call(bgp_process, bgp, afi, safi, rn, peer, true);
3461
d62a17ae 3462 /* Same attribute comes in. */
40381db7
DS
3463 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3464 && attrhash_cmp(pi->attr, attr_new)
d62a17ae 3465 && (!has_valid_label
40381db7 3466 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3467 num_labels * sizeof(mpls_label_t))
d62a17ae 3468 == 0)
3469 && (overlay_index_equal(
40381db7 3470 afi, pi, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3471 evpn == NULL ? NULL : &evpn->gw_ip))) {
3472 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3473 BGP_CONFIG_DAMPENING)
3474 && peer->sort == BGP_PEER_EBGP
40381db7 3475 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3476 if (bgp_debug_update(peer, p, NULL, 1)) {
3477 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3478 afi, safi, prd, p, label,
3479 num_labels, addpath_id ? 1 : 0,
3480 addpath_id, pfx_buf,
3481 sizeof(pfx_buf));
d62a17ae 3482 zlog_debug("%s rcvd %s", peer->host,
3483 pfx_buf);
3484 }
3485
40381db7 3486 if (bgp_damp_update(pi, rn, afi, safi)
d62a17ae 3487 != BGP_DAMP_SUPPRESSED) {
40381db7 3488 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3489 safi);
3490 bgp_process(bgp, rn, afi, safi);
3491 }
3492 } else /* Duplicate - odd */
3493 {
3494 if (bgp_debug_update(peer, p, NULL, 1)) {
3495 if (!peer->rcvd_attr_printed) {
3496 zlog_debug(
3497 "%s rcvd UPDATE w/ attr: %s",
3498 peer->host,
3499 peer->rcvd_attr_str);
3500 peer->rcvd_attr_printed = 1;
3501 }
3502
3503 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3504 afi, safi, prd, p, label,
3505 num_labels, addpath_id ? 1 : 0,
3506 addpath_id, pfx_buf,
3507 sizeof(pfx_buf));
d62a17ae 3508 zlog_debug(
3509 "%s rcvd %s...duplicate ignored",
3510 peer->host, pfx_buf);
3511 }
3512
3513 /* graceful restart STALE flag unset. */
40381db7 3514 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3515 bgp_path_info_unset_flag(
40381db7 3516 rn, pi, BGP_PATH_STALE);
f009ff26 3517 bgp_node_set_defer_flag(rn, false);
d62a17ae 3518 bgp_process(bgp, rn, afi, safi);
3519 }
3520 }
3521
3522 bgp_unlock_node(rn);
3523 bgp_attr_unintern(&attr_new);
3524
3525 return 0;
3526 }
718e3744 3527
d62a17ae 3528 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3529 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3530 if (bgp_debug_update(peer, p, NULL, 1)) {
3531 bgp_debug_rdpfxpath2str(
a4d82a8a 3532 afi, safi, prd, p, label, num_labels,
d62a17ae 3533 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3534 sizeof(pfx_buf));
3535 zlog_debug(
3536 "%s rcvd %s, flapped quicker than processing",
3537 peer->host, pfx_buf);
3538 }
3539
40381db7 3540 bgp_path_info_restore(rn, pi);
d62a17ae 3541 }
718e3744 3542
d62a17ae 3543 /* Received Logging. */
3544 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3545 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3546 num_labels, addpath_id ? 1 : 0,
3547 addpath_id, pfx_buf,
3548 sizeof(pfx_buf));
d62a17ae 3549 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3550 }
718e3744 3551
d62a17ae 3552 /* graceful restart STALE flag unset. */
f009ff26 3553 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
40381db7 3554 bgp_path_info_unset_flag(rn, pi, BGP_PATH_STALE);
f009ff26 3555 bgp_node_set_defer_flag(rn, false);
3556 }
d62a17ae 3557
3558 /* The attribute is changed. */
40381db7 3559 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3560
3561 /* implicit withdraw, decrement aggregate and pcount here.
3562 * only if update is accepted, they'll increment below.
3563 */
40381db7 3564 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3565
3566 /* Update bgp route dampening information. */
3567 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3568 && peer->sort == BGP_PEER_EBGP) {
3569 /* This is implicit withdraw so we should update
3570 dampening
3571 information. */
40381db7
DS
3572 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
3573 bgp_damp_withdraw(pi, rn, afi, safi, 1);
d62a17ae 3574 }
65efcfce 3575#if ENABLE_BGP_VNC
d62a17ae 3576 if (safi == SAFI_MPLS_VPN) {
3577 struct bgp_node *prn = NULL;
3578 struct bgp_table *table = NULL;
3579
3580 prn = bgp_node_get(bgp->rib[afi][safi],
3581 (struct prefix *)prd);
67009e22
DS
3582 if (bgp_node_has_bgp_path_info_data(prn)) {
3583 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3584
3585 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3586 bgp, prd, table, p, pi);
d62a17ae 3587 }
3588 bgp_unlock_node(prn);
3589 }
3590 if ((afi == AFI_IP || afi == AFI_IP6)
3591 && (safi == SAFI_UNICAST)) {
40381db7 3592 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3593 /*
3594 * Implicit withdraw case.
3595 */
3596 ++vnc_implicit_withdraw;
40381db7
DS
3597 vnc_import_bgp_del_route(bgp, p, pi);
3598 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3599 }
3600 }
65efcfce 3601#endif
128ea8ab 3602
d62a17ae 3603 /* Special handling for EVPN update of an existing route. If the
3604 * extended community attribute has changed, we need to
3605 * un-import
3606 * the route using its existing extended community. It will be
3607 * subsequently processed for import with the new extended
3608 * community.
3609 */
3610 if (safi == SAFI_EVPN && !same_attr) {
40381db7 3611 if ((pi->attr->flag
d62a17ae 3612 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3613 && (attr_new->flag
3614 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3615 int cmp;
3616
40381db7 3617 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3618 attr_new->ecommunity);
3619 if (!cmp) {
3620 if (bgp_debug_update(peer, p, NULL, 1))
3621 zlog_debug(
3622 "Change in EXT-COMM, existing %s new %s",
3623 ecommunity_str(
40381db7 3624 pi->attr->ecommunity),
d62a17ae 3625 ecommunity_str(
3626 attr_new->ecommunity));
3627 bgp_evpn_unimport_route(bgp, afi, safi,
40381db7 3628 p, pi);
d62a17ae 3629 }
3630 }
3631 }
718e3744 3632
d62a17ae 3633 /* Update to new attribute. */
40381db7
DS
3634 bgp_attr_unintern(&pi->attr);
3635 pi->attr = attr_new;
d62a17ae 3636
3637 /* Update MPLS label */
3638 if (has_valid_label) {
40381db7 3639 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3640 if (extra->label != label) {
3641 memcpy(&extra->label, label,
dbd587da 3642 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3643 extra->num_labels = num_labels;
3644 }
b57ba6d2
MK
3645 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3646 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3647 }
718e3744 3648
e496b420
HS
3649 /* Update SRv6 SID */
3650 if (attr->srv6_l3vpn) {
3651 extra = bgp_path_info_extra_get(pi);
3652 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
3653 sid_copy(&extra->sid[0],
3654 &attr->srv6_l3vpn->sid);
3655 extra->num_sids = 1;
3656 }
3657 } else if (attr->srv6_vpn) {
3658 extra = bgp_path_info_extra_get(pi);
3659 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
3660 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3661 extra->num_sids = 1;
3662 }
3663 }
3664
65efcfce 3665#if ENABLE_BGP_VNC
d62a17ae 3666 if ((afi == AFI_IP || afi == AFI_IP6)
3667 && (safi == SAFI_UNICAST)) {
3668 if (vnc_implicit_withdraw) {
3669 /*
3670 * Add back the route with its new attributes
3671 * (e.g., nexthop).
3672 * The route is still selected, until the route
3673 * selection
3674 * queued by bgp_process actually runs. We have
3675 * to make this
3676 * update to the VNC side immediately to avoid
3677 * racing against
3678 * configuration changes (e.g., route-map
3679 * changes) which
3680 * trigger re-importation of the entire RIB.
3681 */
40381db7
DS
3682 vnc_import_bgp_add_route(bgp, p, pi);
3683 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 3684 }
3685 }
65efcfce 3686#endif
d62a17ae 3687 /* Update Overlay Index */
3688 if (afi == AFI_L2VPN) {
3689 overlay_index_update(
40381db7 3690 pi->attr, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3691 evpn == NULL ? NULL : &evpn->gw_ip);
3692 }
65efcfce 3693
d62a17ae 3694 /* Update bgp route dampening information. */
3695 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3696 && peer->sort == BGP_PEER_EBGP) {
3697 /* Now we do normal update dampening. */
40381db7 3698 ret = bgp_damp_update(pi, rn, afi, safi);
d62a17ae 3699 if (ret == BGP_DAMP_SUPPRESSED) {
3700 bgp_unlock_node(rn);
3701 return 0;
3702 }
3703 }
128ea8ab 3704
d62a17ae 3705 /* Nexthop reachability check - for unicast and
3706 * labeled-unicast.. */
7c312383
AD
3707 if (((afi == AFI_IP || afi == AFI_IP6)
3708 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3709 || (safi == SAFI_EVPN &&
3710 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
3711 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
3712 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 3713 && !CHECK_FLAG(peer->flags,
3714 PEER_FLAG_DISABLE_CONNECTED_CHECK)
3715 && !bgp_flag_check(
3716 bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
3717 connected = 1;
3718 else
3719 connected = 0;
3720
960035b2
PZ
3721 struct bgp *bgp_nexthop = bgp;
3722
40381db7
DS
3723 if (pi->extra && pi->extra->bgp_orig)
3724 bgp_nexthop = pi->extra->bgp_orig;
960035b2 3725
7c312383
AD
3726 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
3727
3728 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
3729 pi, NULL, connected)
a4d82a8a 3730 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
40381db7 3731 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 3732 else {
3733 if (BGP_DEBUG(nht, NHT)) {
3734 char buf1[INET6_ADDRSTRLEN];
3735 inet_ntop(AF_INET,
3736 (const void *)&attr_new
3737 ->nexthop,
3738 buf1, INET6_ADDRSTRLEN);
3739 zlog_debug("%s(%s): NH unresolved",
3740 __FUNCTION__, buf1);
3741 }
40381db7 3742 bgp_path_info_unset_flag(rn, pi,
18ee8310 3743 BGP_PATH_VALID);
d62a17ae 3744 }
3745 } else
40381db7 3746 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 3747
3748#if ENABLE_BGP_VNC
3749 if (safi == SAFI_MPLS_VPN) {
3750 struct bgp_node *prn = NULL;
3751 struct bgp_table *table = NULL;
3752
3753 prn = bgp_node_get(bgp->rib[afi][safi],
3754 (struct prefix *)prd);
67009e22
DS
3755 if (bgp_node_has_bgp_path_info_data(prn)) {
3756 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3757
3758 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 3759 bgp, prd, table, p, pi);
d62a17ae 3760 }
3761 bgp_unlock_node(prn);
3762 }
3763#endif
718e3744 3764
d62a17ae 3765 /* If this is an EVPN route and some attribute has changed,
3766 * process
3767 * route for import. If the extended community has changed, we
3768 * would
3769 * have done the un-import earlier and the import would result
3770 * in the
3771 * route getting injected into appropriate L2 VNIs. If it is
3772 * just
3773 * some other attribute change, the import will result in
3774 * updating
3775 * the attributes for the route in the VNI(s).
3776 */
7c312383
AD
3777 if (safi == SAFI_EVPN && !same_attr &&
3778 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 3779 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 3780
3781 /* Process change. */
40381db7 3782 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 3783
3784 bgp_process(bgp, rn, afi, safi);
3785 bgp_unlock_node(rn);
558d1fec 3786
ddb5b488
PZ
3787 if (SAFI_UNICAST == safi
3788 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3789 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3790
40381db7 3791 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3792 }
3793 if ((SAFI_MPLS_VPN == safi)
3794 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3795
40381db7 3796 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
3797 }
3798
28070ee3 3799#if ENABLE_BGP_VNC
d62a17ae 3800 if (SAFI_MPLS_VPN == safi) {
3801 mpls_label_t label_decoded = decode_label(label);
28070ee3 3802
d62a17ae 3803 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3804 type, sub_type, &label_decoded);
3805 }
3806 if (SAFI_ENCAP == safi) {
3807 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3808 type, sub_type, NULL);
3809 }
28070ee3
PZ
3810#endif
3811
d62a17ae 3812 return 0;
3813 } // End of implicit withdraw
718e3744 3814
d62a17ae 3815 /* Received Logging. */
3816 if (bgp_debug_update(peer, p, NULL, 1)) {
3817 if (!peer->rcvd_attr_printed) {
3818 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3819 peer->rcvd_attr_str);
3820 peer->rcvd_attr_printed = 1;
3821 }
718e3744 3822
a4d82a8a 3823 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3824 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3825 sizeof(pfx_buf));
3826 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3827 }
718e3744 3828
d62a17ae 3829 /* Make new BGP info. */
3830 new = info_make(type, sub_type, 0, peer, attr_new, rn);
718e3744 3831
d62a17ae 3832 /* Update MPLS label */
3833 if (has_valid_label) {
18ee8310 3834 extra = bgp_path_info_extra_get(new);
8ba71050 3835 if (extra->label != label) {
dbd587da
QY
3836 memcpy(&extra->label, label,
3837 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3838 extra->num_labels = num_labels;
3839 }
b57ba6d2
MK
3840 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3841 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3842 }
718e3744 3843
e496b420
HS
3844 /* Update SRv6 SID */
3845 if (safi == SAFI_MPLS_VPN) {
3846 extra = bgp_path_info_extra_get(new);
3847 if (attr->srv6_l3vpn) {
3848 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
3849 extra->num_sids = 1;
3850 } else if (attr->srv6_vpn) {
3851 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3852 extra->num_sids = 1;
3853 }
3854 }
3855
d62a17ae 3856 /* Update Overlay Index */
3857 if (afi == AFI_L2VPN) {
3858 overlay_index_update(new->attr,
3859 evpn == NULL ? NULL : &evpn->eth_s_id,
3860 evpn == NULL ? NULL : &evpn->gw_ip);
3861 }
3862 /* Nexthop reachability check. */
7c312383
AD
3863 if (((afi == AFI_IP || afi == AFI_IP6)
3864 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3865 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
3866 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
3867 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 3868 && !CHECK_FLAG(peer->flags,
3869 PEER_FLAG_DISABLE_CONNECTED_CHECK)
3870 && !bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
3871 connected = 1;
3872 else
3873 connected = 0;
3874
7c312383
AD
3875 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
3876
3877 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, new, NULL,
3878 connected)
a4d82a8a 3879 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
18ee8310 3880 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
d62a17ae 3881 else {
3882 if (BGP_DEBUG(nht, NHT)) {
3883 char buf1[INET6_ADDRSTRLEN];
3884 inet_ntop(AF_INET,
3885 (const void *)&attr_new->nexthop,
3886 buf1, INET6_ADDRSTRLEN);
3887 zlog_debug("%s(%s): NH unresolved",
3888 __FUNCTION__, buf1);
3889 }
18ee8310 3890 bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID);
d62a17ae 3891 }
3892 } else
18ee8310 3893 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
a82478b9 3894
d62a17ae 3895 /* Addpath ID */
3896 new->addpath_rx_id = addpath_id;
3897
3898 /* Increment prefix */
3899 bgp_aggregate_increment(bgp, p, new, afi, safi);
3900
3901 /* Register new BGP information. */
18ee8310 3902 bgp_path_info_add(rn, new);
d62a17ae 3903
3904 /* route_node_get lock */
3905 bgp_unlock_node(rn);
558d1fec 3906
65efcfce 3907#if ENABLE_BGP_VNC
d62a17ae 3908 if (safi == SAFI_MPLS_VPN) {
3909 struct bgp_node *prn = NULL;
3910 struct bgp_table *table = NULL;
3911
3912 prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
67009e22
DS
3913 if (bgp_node_has_bgp_path_info_data(prn)) {
3914 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3915
3916 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3917 bgp, prd, table, p, new);
3918 }
3919 bgp_unlock_node(prn);
3920 }
65efcfce
LB
3921#endif
3922
d62a17ae 3923 /* If maximum prefix count is configured and current prefix
3924 count exeed it. */
3925 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3926 return -1;
718e3744 3927
d62a17ae 3928 /* If this is an EVPN route, process for import. */
7c312383 3929 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 3930 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 3931
4a11bf2c
DL
3932 hook_call(bgp_process, bgp, afi, safi, rn, peer, false);
3933
d62a17ae 3934 /* Process change. */
3935 bgp_process(bgp, rn, afi, safi);
718e3744 3936
ddb5b488
PZ
3937 if (SAFI_UNICAST == safi
3938 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3939 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3940 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
3941 }
3942 if ((SAFI_MPLS_VPN == safi)
3943 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3944
3945 vpn_leak_to_vrf_update(bgp, new);
3946 }
28070ee3 3947#if ENABLE_BGP_VNC
d62a17ae 3948 if (SAFI_MPLS_VPN == safi) {
3949 mpls_label_t label_decoded = decode_label(label);
28070ee3 3950
d62a17ae 3951 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3952 sub_type, &label_decoded);
3953 }
3954 if (SAFI_ENCAP == safi) {
3955 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3956 sub_type, NULL);
3957 }
28070ee3
PZ
3958#endif
3959
d62a17ae 3960 return 0;
718e3744 3961
d62a17ae 3962/* This BGP update is filtered. Log the reason then update BGP
3963 entry. */
3964filtered:
4a11bf2c
DL
3965 hook_call(bgp_process, bgp, afi, safi, rn, peer, true);
3966
d62a17ae 3967 if (bgp_debug_update(peer, p, NULL, 1)) {
3968 if (!peer->rcvd_attr_printed) {
3969 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3970 peer->rcvd_attr_str);
3971 peer->rcvd_attr_printed = 1;
3972 }
718e3744 3973
a4d82a8a 3974 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3975 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3976 sizeof(pfx_buf));
3977 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3978 peer->host, pfx_buf, reason);
3979 }
128ea8ab 3980
40381db7 3981 if (pi) {
d62a17ae 3982 /* If this is an EVPN route, un-import it as it is now filtered.
3983 */
3984 if (safi == SAFI_EVPN)
40381db7 3985 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 3986
ddb5b488
PZ
3987 if (SAFI_UNICAST == safi
3988 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3989 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3990
40381db7 3991 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3992 }
3993 if ((SAFI_MPLS_VPN == safi)
3994 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3995
40381db7 3996 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
3997 }
3998
40381db7 3999 bgp_rib_remove(rn, pi, peer, afi, safi);
d62a17ae 4000 }
4001
4002 bgp_unlock_node(rn);
558d1fec 4003
97736e32 4004#if ENABLE_BGP_VNC
d62a17ae 4005 /*
4006 * Filtered update is treated as an implicit withdrawal (see
4007 * bgp_rib_remove()
4008 * a few lines above)
4009 */
4010 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4011 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4012 0);
4013 }
97736e32
PZ
4014#endif
4015
d62a17ae 4016 return 0;
718e3744 4017}
4018
d7c0a89a 4019int bgp_withdraw(struct peer *peer, struct prefix *p, uint32_t addpath_id,
d62a17ae 4020 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4021 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4022 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4023{
d62a17ae 4024 struct bgp *bgp;
4025 char pfx_buf[BGP_PRD_PATH_STRLEN];
4026 struct bgp_node *rn;
40381db7 4027 struct bgp_path_info *pi;
718e3744 4028
28070ee3 4029#if ENABLE_BGP_VNC
d62a17ae 4030 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4031 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4032 0);
4033 }
28070ee3
PZ
4034#endif
4035
d62a17ae 4036 bgp = peer->bgp;
4037
4038 /* Lookup node. */
4039 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
4040
4041 /* If peer is soft reconfiguration enabled. Record input packet for
4042 * further calculation.
4043 *
4044 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4045 * routes that are filtered. This tanks out Quagga RS pretty badly due
4046 * to
4047 * the iteration over all RS clients.
4048 * Since we need to remove the entry from adj_in anyway, do that first
4049 * and
4050 * if there was no entry, we don't need to do anything more.
4051 */
4052 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4053 && peer != bgp->peer_self)
4054 if (!bgp_adj_in_unset(rn, peer, addpath_id)) {
b4d46cc9
DL
4055 peer->stat_pfx_dup_withdraw++;
4056
d62a17ae 4057 if (bgp_debug_update(peer, p, NULL, 1)) {
4058 bgp_debug_rdpfxpath2str(
a4d82a8a 4059 afi, safi, prd, p, label, num_labels,
d62a17ae 4060 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4061 sizeof(pfx_buf));
4062 zlog_debug(
4063 "%s withdrawing route %s not in adj-in",
4064 peer->host, pfx_buf);
4065 }
4066 bgp_unlock_node(rn);
4067 return 0;
4068 }
cd808e74 4069
d62a17ae 4070 /* Lookup withdrawn route. */
6f94b685 4071 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4072 if (pi->peer == peer && pi->type == type
4073 && pi->sub_type == sub_type
4074 && pi->addpath_rx_id == addpath_id)
d62a17ae 4075 break;
4076
4077 /* Logging. */
4078 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4079 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4080 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4081 sizeof(pfx_buf));
4082 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4083 pfx_buf);
4084 }
718e3744 4085
d62a17ae 4086 /* Withdraw specified route from routing table. */
40381db7
DS
4087 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
4088 bgp_rib_withdraw(rn, pi, peer, afi, safi, prd);
ddb5b488
PZ
4089 if (SAFI_UNICAST == safi
4090 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4091 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4092 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4093 }
4094 if ((SAFI_MPLS_VPN == safi)
4095 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4096
40381db7 4097 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4098 }
4099 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4100 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4101 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4102 sizeof(pfx_buf));
4103 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4104 }
718e3744 4105
d62a17ae 4106 /* Unlock bgp_node_get() lock. */
4107 bgp_unlock_node(rn);
4108
4109 return 0;
718e3744 4110}
6b0655a2 4111
d62a17ae 4112void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4113 int withdraw)
718e3744 4114{
d62a17ae 4115 struct update_subgroup *subgrp;
4116 subgrp = peer_subgroup(peer, afi, safi);
4117 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4118}
6182d65b 4119
718e3744 4120
3f9c7369
DS
4121/*
4122 * bgp_stop_announce_route_timer
4123 */
d62a17ae 4124void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4125{
d62a17ae 4126 if (!paf->t_announce_route)
4127 return;
4128
4129 THREAD_TIMER_OFF(paf->t_announce_route);
718e3744 4130}
6b0655a2 4131
3f9c7369
DS
4132/*
4133 * bgp_announce_route_timer_expired
4134 *
4135 * Callback that is invoked when the route announcement timer for a
4136 * peer_af expires.
4137 */
d62a17ae 4138static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4139{
d62a17ae 4140 struct peer_af *paf;
4141 struct peer *peer;
558d1fec 4142
d62a17ae 4143 paf = THREAD_ARG(t);
4144 peer = paf->peer;
718e3744 4145
d62a17ae 4146 if (peer->status != Established)
4147 return 0;
3f9c7369 4148
d62a17ae 4149 if (!peer->afc_nego[paf->afi][paf->safi])
4150 return 0;
3f9c7369 4151
d62a17ae 4152 peer_af_announce_route(paf, 1);
4153 return 0;
718e3744 4154}
4155
3f9c7369
DS
4156/*
4157 * bgp_announce_route
4158 *
4159 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4160 */
d62a17ae 4161void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4162{
4163 struct peer_af *paf;
4164 struct update_subgroup *subgrp;
4165
4166 paf = peer_af_find(peer, afi, safi);
4167 if (!paf)
4168 return;
4169 subgrp = PAF_SUBGRP(paf);
4170
4171 /*
4172 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4173 * or a refresh has already been triggered.
4174 */
4175 if (!subgrp || paf->t_announce_route)
4176 return;
4177
4178 /*
4179 * Start a timer to stagger/delay the announce. This serves
4180 * two purposes - announcement can potentially be combined for
4181 * multiple peers and the announcement doesn't happen in the
4182 * vty context.
4183 */
4184 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4185 (subgrp->peer_count == 1)
4186 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4187 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4188 &paf->t_announce_route);
3f9c7369
DS
4189}
4190
4191/*
4192 * Announce routes from all AF tables to a peer.
4193 *
4194 * This should ONLY be called when there is a need to refresh the
4195 * routes to the peer based on a policy change for this peer alone
4196 * or a route refresh request received from the peer.
4197 * The operation will result in splitting the peer from its existing
4198 * subgroups and putting it in new subgroups.
4199 */
d62a17ae 4200void bgp_announce_route_all(struct peer *peer)
718e3744 4201{
d62a17ae 4202 afi_t afi;
4203 safi_t safi;
4204
05c7a1cc
QY
4205 FOREACH_AFI_SAFI (afi, safi)
4206 bgp_announce_route(peer, afi, safi);
718e3744 4207}
6b0655a2 4208
d62a17ae 4209static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4210 struct bgp_table *table,
4211 struct prefix_rd *prd)
718e3744 4212{
d62a17ae 4213 int ret;
4214 struct bgp_node *rn;
4215 struct bgp_adj_in *ain;
718e3744 4216
d62a17ae 4217 if (!table)
4218 table = peer->bgp->rib[afi][safi];
718e3744 4219
d62a17ae 4220 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
4221 for (ain = rn->adj_in; ain; ain = ain->next) {
ea47320b
DL
4222 if (ain->peer != peer)
4223 continue;
8692c506 4224
d7d15889 4225 struct bgp_path_info *pi;
d7c0a89a 4226 uint32_t num_labels = 0;
b57ba6d2 4227 mpls_label_t *label_pnt = NULL;
8cb687c2 4228 struct bgp_route_evpn evpn;
b57ba6d2 4229
d7d15889
DS
4230 for (pi = bgp_node_get_bgp_path_info(rn); pi;
4231 pi = pi->next)
4232 if (pi->peer == peer)
4233 break;
4234
40381db7
DS
4235 if (pi && pi->extra)
4236 num_labels = pi->extra->num_labels;
b57ba6d2 4237 if (num_labels)
40381db7 4238 label_pnt = &pi->extra->label[0];
8cb687c2
DS
4239 if (pi)
4240 memcpy(&evpn, &pi->attr->evpn_overlay,
4241 sizeof(evpn));
4242 else
4243 memset(&evpn, 0, sizeof(evpn));
8692c506 4244
ea47320b
DL
4245 ret = bgp_update(peer, &rn->p, ain->addpath_rx_id,
4246 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
a4d82a8a 4247 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 4248 num_labels, 1, &evpn);
ea47320b
DL
4249
4250 if (ret < 0) {
4251 bgp_unlock_node(rn);
4252 return;
d62a17ae 4253 }
4254 }
718e3744 4255}
4256
d62a17ae 4257void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4258{
d62a17ae 4259 struct bgp_node *rn;
4260 struct bgp_table *table;
718e3744 4261
d62a17ae 4262 if (peer->status != Established)
4263 return;
718e3744 4264
d62a17ae 4265 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4266 && (safi != SAFI_EVPN))
4267 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4268 else
4269 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
67009e22
DS
4270 rn = bgp_route_next(rn)) {
4271 table = bgp_node_get_bgp_table_info(rn);
4272 if (table != NULL) {
d62a17ae 4273 struct prefix_rd prd;
67009e22 4274
d62a17ae 4275 prd.family = AF_UNSPEC;
4276 prd.prefixlen = 64;
4277 memcpy(&prd.val, rn->p.u.val, 8);
8692c506 4278
d62a17ae 4279 bgp_soft_reconfig_table(peer, afi, safi, table,
4280 &prd);
4281 }
67009e22 4282 }
718e3744 4283}
6b0655a2 4284
228da428 4285
d62a17ae 4286struct bgp_clear_node_queue {
4287 struct bgp_node *rn;
228da428
CC
4288};
4289
d62a17ae 4290static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4291{
d62a17ae 4292 struct bgp_clear_node_queue *cnq = data;
4293 struct bgp_node *rn = cnq->rn;
4294 struct peer *peer = wq->spec.data;
40381db7 4295 struct bgp_path_info *pi;
3103e8d2 4296 struct bgp *bgp;
d62a17ae 4297 afi_t afi = bgp_node_table(rn)->afi;
4298 safi_t safi = bgp_node_table(rn)->safi;
4299
4300 assert(rn && peer);
3103e8d2 4301 bgp = peer->bgp;
d62a17ae 4302
4303 /* It is possible that we have multiple paths for a prefix from a peer
4304 * if that peer is using AddPath.
4305 */
6f94b685 4306 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 4307 if (pi->peer != peer)
ea47320b
DL
4308 continue;
4309
4310 /* graceful restart STALE flag set. */
4311 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4312 && peer->nsf[afi][safi]
40381db7
DS
4313 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4314 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
4315 bgp_path_info_set_flag(rn, pi, BGP_PATH_STALE);
ea47320b
DL
4316 else {
4317 /* If this is an EVPN route, process for
4318 * un-import. */
4319 if (safi == SAFI_EVPN)
40381db7
DS
4320 bgp_evpn_unimport_route(bgp, afi, safi, &rn->p,
4321 pi);
3103e8d2
DS
4322 /* Handle withdraw for VRF route-leaking and L3VPN */
4323 if (SAFI_UNICAST == safi
4324 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4325 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4326 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4327 bgp, pi);
960035b2 4328 }
3103e8d2 4329 if (SAFI_MPLS_VPN == safi &&
960035b2 4330 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4331 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4332 }
3103e8d2 4333
40381db7 4334 bgp_rib_remove(rn, pi, peer, afi, safi);
d62a17ae 4335 }
ea47320b 4336 }
d62a17ae 4337 return WQ_SUCCESS;
200df115 4338}
4339
d62a17ae 4340static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4341{
d62a17ae 4342 struct bgp_clear_node_queue *cnq = data;
4343 struct bgp_node *rn = cnq->rn;
4344 struct bgp_table *table = bgp_node_table(rn);
228da428 4345
d62a17ae 4346 bgp_unlock_node(rn);
4347 bgp_table_unlock(table);
4348 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4349}
4350
d62a17ae 4351static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4352{
d62a17ae 4353 struct peer *peer = wq->spec.data;
64e580a7 4354
d62a17ae 4355 /* Tickle FSM to start moving again */
4356 BGP_EVENT_ADD(peer, Clearing_Completed);
4357
4358 peer_unlock(peer); /* bgp_clear_route */
200df115 4359}
718e3744 4360
d62a17ae 4361static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4362{
d62a17ae 4363 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4364
4365 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4366#undef CLEAR_QUEUE_NAME_LEN
4367
0ce1ca80 4368 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4369 peer->clear_node_queue->spec.hold = 10;
4370 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4371 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4372 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4373 peer->clear_node_queue->spec.max_retries = 0;
4374
4375 /* we only 'lock' this peer reference when the queue is actually active
4376 */
4377 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4378}
4379
d62a17ae 4380static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4381 struct bgp_table *table)
65ca75e0 4382{
d62a17ae 4383 struct bgp_node *rn;
4384 int force = bm->process_main_queue ? 0 : 1;
6cf159b9 4385
d62a17ae 4386 if (!table)
4387 table = peer->bgp->rib[afi][safi];
dc83d712 4388
d62a17ae 4389 /* If still no table => afi/safi isn't configured at all or smth. */
4390 if (!table)
4391 return;
dc83d712 4392
d62a17ae 4393 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
40381db7 4394 struct bgp_path_info *pi, *next;
d62a17ae 4395 struct bgp_adj_in *ain;
4396 struct bgp_adj_in *ain_next;
4397
4398 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4399 * queued for every clearing peer, regardless of whether it is
4400 * relevant to the peer at hand.
4401 *
4402 * Overview: There are 3 different indices which need to be
4403 * scrubbed, potentially, when a peer is removed:
4404 *
4405 * 1 peer's routes visible via the RIB (ie accepted routes)
4406 * 2 peer's routes visible by the (optional) peer's adj-in index
4407 * 3 other routes visible by the peer's adj-out index
4408 *
4409 * 3 there is no hurry in scrubbing, once the struct peer is
4410 * removed from bgp->peer, we could just GC such deleted peer's
4411 * adj-outs at our leisure.
4412 *
4413 * 1 and 2 must be 'scrubbed' in some way, at least made
4414 * invisible via RIB index before peer session is allowed to be
4415 * brought back up. So one needs to know when such a 'search' is
4416 * complete.
4417 *
4418 * Ideally:
4419 *
4420 * - there'd be a single global queue or a single RIB walker
4421 * - rather than tracking which route_nodes still need to be
4422 * examined on a peer basis, we'd track which peers still
4423 * aren't cleared
4424 *
4425 * Given that our per-peer prefix-counts now should be reliable,
4426 * this may actually be achievable. It doesn't seem to be a huge
4427 * problem at this time,
4428 *
4429 * It is possible that we have multiple paths for a prefix from
4430 * a peer
4431 * if that peer is using AddPath.
4432 */
4433 ain = rn->adj_in;
4434 while (ain) {
4435 ain_next = ain->next;
4436
4437 if (ain->peer == peer) {
4438 bgp_adj_in_remove(rn, ain);
4439 bgp_unlock_node(rn);
4440 }
4441
4442 ain = ain_next;
4443 }
4444
6f94b685 4445 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
40381db7
DS
4446 next = pi->next;
4447 if (pi->peer != peer)
d62a17ae 4448 continue;
4449
4450 if (force)
40381db7 4451 bgp_path_info_reap(rn, pi);
d62a17ae 4452 else {
4453 struct bgp_clear_node_queue *cnq;
4454
4455 /* both unlocked in bgp_clear_node_queue_del */
4456 bgp_table_lock(bgp_node_table(rn));
4457 bgp_lock_node(rn);
4458 cnq = XCALLOC(
4459 MTYPE_BGP_CLEAR_NODE_QUEUE,
4460 sizeof(struct bgp_clear_node_queue));
4461 cnq->rn = rn;
4462 work_queue_add(peer->clear_node_queue, cnq);
4463 break;
4464 }
4465 }
4466 }
4467 return;
4468}
4469
4470void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4471{
4472 struct bgp_node *rn;
4473 struct bgp_table *table;
4474
4475 if (peer->clear_node_queue == NULL)
4476 bgp_clear_node_queue_init(peer);
4477
4478 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4479 * Idle until it receives a Clearing_Completed event. This protects
4480 * against peers which flap faster than we can we clear, which could
4481 * lead to:
4482 *
4483 * a) race with routes from the new session being installed before
4484 * clear_route_node visits the node (to delete the route of that
4485 * peer)
4486 * b) resource exhaustion, clear_route_node likely leads to an entry
4487 * on the process_main queue. Fast-flapping could cause that queue
4488 * to grow and grow.
4489 */
4490
4491 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4492 * the unlock will happen upon work-queue completion; other wise, the
4493 * unlock happens at the end of this function.
4494 */
4495 if (!peer->clear_node_queue->thread)
4496 peer_lock(peer);
4497
4498 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4499 bgp_clear_route_table(peer, afi, safi, NULL);
4500 else
4501 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
67009e22
DS
4502 rn = bgp_route_next(rn)) {
4503 table = bgp_node_get_bgp_table_info(rn);
4504 if (!table)
4505 continue;
4506
4507 bgp_clear_route_table(peer, afi, safi, table);
4508 }
d62a17ae 4509
4510 /* unlock if no nodes got added to the clear-node-queue. */
4511 if (!peer->clear_node_queue->thread)
4512 peer_unlock(peer);
718e3744 4513}
d62a17ae 4514
4515void bgp_clear_route_all(struct peer *peer)
718e3744 4516{
d62a17ae 4517 afi_t afi;
4518 safi_t safi;
718e3744 4519
05c7a1cc
QY
4520 FOREACH_AFI_SAFI (afi, safi)
4521 bgp_clear_route(peer, afi, safi);
65efcfce
LB
4522
4523#if ENABLE_BGP_VNC
d62a17ae 4524 rfapiProcessPeerDown(peer);
65efcfce 4525#endif
718e3744 4526}
4527
d62a17ae 4528void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4529{
d62a17ae 4530 struct bgp_table *table;
4531 struct bgp_node *rn;
4532 struct bgp_adj_in *ain;
4533 struct bgp_adj_in *ain_next;
718e3744 4534
d62a17ae 4535 table = peer->bgp->rib[afi][safi];
718e3744 4536
d62a17ae 4537 /* It is possible that we have multiple paths for a prefix from a peer
4538 * if that peer is using AddPath.
4539 */
4540 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
4541 ain = rn->adj_in;
43143c8f 4542
d62a17ae 4543 while (ain) {
4544 ain_next = ain->next;
43143c8f 4545
d62a17ae 4546 if (ain->peer == peer) {
4547 bgp_adj_in_remove(rn, ain);
4548 bgp_unlock_node(rn);
4549 }
43143c8f 4550
d62a17ae 4551 ain = ain_next;
4552 }
4553 }
718e3744 4554}
93406d87 4555
d62a17ae 4556void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4557{
4558 struct bgp_node *rn;
40381db7 4559 struct bgp_path_info *pi;
d62a17ae 4560 struct bgp_table *table;
4561
4562 if (safi == SAFI_MPLS_VPN) {
4563 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4564 rn = bgp_route_next(rn)) {
4565 struct bgp_node *rm;
d62a17ae 4566
4567 /* look for neighbor in tables */
67009e22
DS
4568 table = bgp_node_get_bgp_table_info(rn);
4569 if (!table)
ea47320b
DL
4570 continue;
4571
4572 for (rm = bgp_table_top(table); rm;
4573 rm = bgp_route_next(rm))
6f94b685
DS
4574 for (pi = bgp_node_get_bgp_path_info(rm); pi;
4575 pi = pi->next) {
40381db7 4576 if (pi->peer != peer)
ea47320b 4577 continue;
40381db7 4578 if (!CHECK_FLAG(pi->flags,
1defdda8 4579 BGP_PATH_STALE))
ea47320b
DL
4580 break;
4581
40381db7 4582 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4583 break;
4584 }
d62a17ae 4585 }
4586 } else {
4587 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4588 rn = bgp_route_next(rn))
6f94b685
DS
4589 for (pi = bgp_node_get_bgp_path_info(rn); pi;
4590 pi = pi->next) {
40381db7 4591 if (pi->peer != peer)
ea47320b 4592 continue;
40381db7 4593 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4594 break;
40381db7 4595 bgp_rib_remove(rn, pi, peer, afi, safi);
ea47320b
DL
4596 break;
4597 }
d62a17ae 4598 }
93406d87 4599}
6b0655a2 4600
9dac9fc8
DA
4601int bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
4602{
e0df4c04
DA
4603 if (peer->sort == BGP_PEER_IBGP)
4604 return 1;
4605
9dac9fc8
DA
4606 if (peer->sort == BGP_PEER_EBGP
4607 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
4608 || FILTER_LIST_OUT_NAME(filter)
4609 || DISTRIBUTE_OUT_NAME(filter)))
4610 return 1;
4611 return 0;
4612}
4613
4614int bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
4615{
e0df4c04
DA
4616 if (peer->sort == BGP_PEER_IBGP)
4617 return 1;
4618
9dac9fc8
DA
4619 if (peer->sort == BGP_PEER_EBGP
4620 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
4621 || FILTER_LIST_IN_NAME(filter)
4622 || DISTRIBUTE_IN_NAME(filter)))
4623 return 1;
4624 return 0;
4625}
4626
568e10ca 4627static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
4628 safi_t safi)
bb86c601 4629{
d62a17ae 4630 struct bgp_node *rn;
40381db7 4631 struct bgp_path_info *pi;
4b7e6066 4632 struct bgp_path_info *next;
bb86c601 4633
d62a17ae 4634 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
6f94b685 4635 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
40381db7 4636 next = pi->next;
1b7bb747
CS
4637
4638 /* Unimport EVPN routes from VRFs */
4639 if (safi == SAFI_EVPN)
4640 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
4641 SAFI_EVPN,
4642 &rn->p, pi);
4643
40381db7
DS
4644 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
4645 && pi->type == ZEBRA_ROUTE_BGP
4646 && (pi->sub_type == BGP_ROUTE_NORMAL
4647 || pi->sub_type == BGP_ROUTE_AGGREGATE
4648 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 4649
d62a17ae 4650 if (bgp_fibupd_safi(safi))
40381db7
DS
4651 bgp_zebra_withdraw(&rn->p, pi, bgp,
4652 safi);
4653 bgp_path_info_reap(rn, pi);
d62a17ae 4654 }
4655 }
bb86c601
LB
4656}
4657
718e3744 4658/* Delete all kernel routes. */
d62a17ae 4659void bgp_cleanup_routes(struct bgp *bgp)
4660{
4661 afi_t afi;
4662 struct bgp_node *rn;
67009e22 4663 struct bgp_table *table;
d62a17ae 4664
4665 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
4666 if (afi == AFI_L2VPN)
4667 continue;
568e10ca 4668 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
4669 SAFI_UNICAST);
d62a17ae 4670 /*
4671 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4672 */
4673 if (afi != AFI_L2VPN) {
4674 safi_t safi;
4675 safi = SAFI_MPLS_VPN;
4676 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4677 rn = bgp_route_next(rn)) {
67009e22
DS
4678 table = bgp_node_get_bgp_table_info(rn);
4679 if (table != NULL) {
4680 bgp_cleanup_table(bgp, table, safi);
4681 bgp_table_finish(&table);
4682 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4683 bgp_unlock_node(rn);
4684 }
4685 }
4686 safi = SAFI_ENCAP;
4687 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4688 rn = bgp_route_next(rn)) {
67009e22
DS
4689 table = bgp_node_get_bgp_table_info(rn);
4690 if (table != NULL) {
4691 bgp_cleanup_table(bgp, table, safi);
4692 bgp_table_finish(&table);
4693 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4694 bgp_unlock_node(rn);
4695 }
4696 }
4697 }
4698 }
4699 for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn;
4700 rn = bgp_route_next(rn)) {
67009e22
DS
4701 table = bgp_node_get_bgp_table_info(rn);
4702 if (table != NULL) {
4703 bgp_cleanup_table(bgp, table, SAFI_EVPN);
4704 bgp_table_finish(&table);
4705 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4706 bgp_unlock_node(rn);
4707 }
bb86c601 4708 }
718e3744 4709}
4710
d62a17ae 4711void bgp_reset(void)
718e3744 4712{
d62a17ae 4713 vty_reset();
4714 bgp_zclient_reset();
4715 access_list_reset();
4716 prefix_list_reset();
718e3744 4717}
6b0655a2 4718
d62a17ae 4719static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 4720{
d62a17ae 4721 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
4722 && CHECK_FLAG(peer->af_cap[afi][safi],
4723 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
4724}
4725
718e3744 4726/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4727 value. */
d62a17ae 4728int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
4729 struct bgp_nlri *packet)
4730{
d7c0a89a
QY
4731 uint8_t *pnt;
4732 uint8_t *lim;
d62a17ae 4733 struct prefix p;
4734 int psize;
4735 int ret;
4736 afi_t afi;
4737 safi_t safi;
4738 int addpath_encoded;
d7c0a89a 4739 uint32_t addpath_id;
d62a17ae 4740
d62a17ae 4741 pnt = packet->nlri;
4742 lim = pnt + packet->length;
4743 afi = packet->afi;
4744 safi = packet->safi;
4745 addpath_id = 0;
4746 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
4747
4748 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4749 syntactic validity. If the field is syntactically incorrect,
4750 then the Error Subcode is set to Invalid Network Field. */
4751 for (; pnt < lim; pnt += psize) {
4752 /* Clear prefix structure. */
4753 memset(&p, 0, sizeof(struct prefix));
4754
4755 if (addpath_encoded) {
4756
4757 /* When packet overflow occurs return immediately. */
761ed665 4758 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 4759 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4760
a3a850a1 4761 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 4762 addpath_id = ntohl(addpath_id);
d62a17ae 4763 pnt += BGP_ADDPATH_ID_LEN;
4764 }
718e3744 4765
d62a17ae 4766 /* Fetch prefix length. */
4767 p.prefixlen = *pnt++;
4768 /* afi/safi validity already verified by caller,
4769 * bgp_update_receive */
4770 p.family = afi2family(afi);
4771
4772 /* Prefix length check. */
4773 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 4774 flog_err(
e50f7cfd 4775 EC_BGP_UPDATE_RCV,
14454c9f 4776 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 4777 peer->host, p.prefixlen, packet->afi);
513386b5 4778 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 4779 }
6b0655a2 4780
d62a17ae 4781 /* Packet size overflow check. */
4782 psize = PSIZE(p.prefixlen);
4783
4784 /* When packet overflow occur return immediately. */
4785 if (pnt + psize > lim) {
af4c2728 4786 flog_err(
e50f7cfd 4787 EC_BGP_UPDATE_RCV,
d62a17ae 4788 "%s [Error] Update packet error (prefix length %d overflows packet)",
4789 peer->host, p.prefixlen);
513386b5 4790 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4791 }
4792
4793 /* Defensive coding, double-check the psize fits in a struct
4794 * prefix */
4795 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 4796 flog_err(
e50f7cfd 4797 EC_BGP_UPDATE_RCV,
d62a17ae 4798 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4799 peer->host, p.prefixlen, sizeof(p.u));
513386b5 4800 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4801 }
4802
4803 /* Fetch prefix from NLRI packet. */
a85297a7 4804 memcpy(p.u.val, pnt, psize);
d62a17ae 4805
4806 /* Check address. */
4807 if (afi == AFI_IP && safi == SAFI_UNICAST) {
4808 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
4809 /* From RFC4271 Section 6.3:
4810 *
4811 * If a prefix in the NLRI field is semantically
4812 * incorrect
4813 * (e.g., an unexpected multicast IP address),
4814 * an error SHOULD
4815 * be logged locally, and the prefix SHOULD be
4816 * ignored.
a4d82a8a 4817 */
af4c2728 4818 flog_err(
e50f7cfd 4819 EC_BGP_UPDATE_RCV,
d62a17ae 4820 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4821 peer->host, inet_ntoa(p.u.prefix4));
4822 continue;
4823 }
4824 }
4825
4826 /* Check address. */
4827 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
4828 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4829 char buf[BUFSIZ];
4830
af4c2728 4831 flog_err(
e50f7cfd 4832 EC_BGP_UPDATE_RCV,
d62a17ae 4833 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4834 peer->host,
4835 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4836 BUFSIZ));
4837
4838 continue;
4839 }
4840 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
4841 char buf[BUFSIZ];
4842
af4c2728 4843 flog_err(
e50f7cfd 4844 EC_BGP_UPDATE_RCV,
d62a17ae 4845 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4846 peer->host,
4847 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4848 BUFSIZ));
4849
4850 continue;
4851 }
4852 }
4853
4854 /* Normal process. */
4855 if (attr)
4856 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
4857 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 4858 NULL, NULL, 0, 0, NULL);
d62a17ae 4859 else
4860 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
4861 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
4862 BGP_ROUTE_NORMAL, NULL, NULL, 0,
4863 NULL);
d62a17ae 4864
513386b5
DA
4865 /* Do not send BGP notification twice when maximum-prefix count
4866 * overflow. */
4867 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4868 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
4869
4870 /* Address family configuration mismatch. */
d62a17ae 4871 if (ret < 0)
513386b5 4872 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 4873 }
4874
4875 /* Packet length consistency check. */
4876 if (pnt != lim) {
af4c2728 4877 flog_err(
e50f7cfd 4878 EC_BGP_UPDATE_RCV,
d62a17ae 4879 "%s [Error] Update packet error (prefix length mismatch with total length)",
4880 peer->host);
513386b5 4881 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4882 }
6b0655a2 4883
513386b5 4884 return BGP_NLRI_PARSE_OK;
718e3744 4885}
4886
d62a17ae 4887static struct bgp_static *bgp_static_new(void)
718e3744 4888{
d62a17ae 4889 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 4890}
4891
d62a17ae 4892static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 4893{
0a22ddfb 4894 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 4895 route_map_counter_decrement(bgp_static->rmap.map);
4896
0a22ddfb 4897 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 4898 XFREE(MTYPE_BGP_STATIC, bgp_static);
4899}
4900
4901void bgp_static_update(struct bgp *bgp, struct prefix *p,
4902 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
4903{
4904 struct bgp_node *rn;
40381db7 4905 struct bgp_path_info *pi;
4b7e6066 4906 struct bgp_path_info *new;
40381db7 4907 struct bgp_path_info rmap_path;
d62a17ae 4908 struct attr attr;
4909 struct attr *attr_new;
b68885f9 4910 route_map_result_t ret;
65efcfce 4911#if ENABLE_BGP_VNC
d62a17ae 4912 int vnc_implicit_withdraw = 0;
65efcfce 4913#endif
fee0f4c6 4914
d62a17ae 4915 assert(bgp_static);
4916 if (!bgp_static)
4917 return;
dd8103a9 4918
d62a17ae 4919 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4920
d62a17ae 4921 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 4922
d62a17ae 4923 attr.nexthop = bgp_static->igpnexthop;
4924 attr.med = bgp_static->igpmetric;
4925 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 4926
d62a17ae 4927 if (bgp_static->atomic)
4928 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 4929
d62a17ae 4930 /* Store label index, if required. */
4931 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
4932 attr.label_index = bgp_static->label_index;
4933 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
4934 }
718e3744 4935
d62a17ae 4936 /* Apply route-map. */
4937 if (bgp_static->rmap.name) {
4938 struct attr attr_tmp = attr;
80ced710 4939
40381db7
DS
4940 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
4941 rmap_path.peer = bgp->peer_self;
4942 rmap_path.attr = &attr_tmp;
fee0f4c6 4943
d62a17ae 4944 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 4945
40381db7
DS
4946 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
4947 &rmap_path);
fee0f4c6 4948
d62a17ae 4949 bgp->peer_self->rmap_type = 0;
718e3744 4950
d62a17ae 4951 if (ret == RMAP_DENYMATCH) {
4952 /* Free uninterned attribute. */
4953 bgp_attr_flush(&attr_tmp);
718e3744 4954
d62a17ae 4955 /* Unintern original. */
4956 aspath_unintern(&attr.aspath);
4957 bgp_static_withdraw(bgp, p, afi, safi);
4958 return;
4959 }
7f323236
DW
4960
4961 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
4962 bgp_attr_add_gshut_community(&attr_tmp);
4963
d62a17ae 4964 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
4965 } else {
4966
4967 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
4968 bgp_attr_add_gshut_community(&attr);
4969
d62a17ae 4970 attr_new = bgp_attr_intern(&attr);
7f323236 4971 }
718e3744 4972
6f94b685 4973 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4974 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4975 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4976 break;
4977
40381db7
DS
4978 if (pi) {
4979 if (attrhash_cmp(pi->attr, attr_new)
4980 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
d62a17ae 4981 && !bgp_flag_check(bgp, BGP_FLAG_FORCE_STATIC_PROCESS)) {
4982 bgp_unlock_node(rn);
4983 bgp_attr_unintern(&attr_new);
4984 aspath_unintern(&attr.aspath);
4985 return;
4986 } else {
4987 /* The attribute is changed. */
40381db7 4988 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4989
4990 /* Rewrite BGP route information. */
40381db7
DS
4991 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
4992 bgp_path_info_restore(rn, pi);
d62a17ae 4993 else
40381db7 4994 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
65efcfce 4995#if ENABLE_BGP_VNC
d62a17ae 4996 if ((afi == AFI_IP || afi == AFI_IP6)
4997 && (safi == SAFI_UNICAST)) {
40381db7 4998 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4999 /*
5000 * Implicit withdraw case.
40381db7 5001 * We have to do this before pi is
d62a17ae 5002 * changed
5003 */
5004 ++vnc_implicit_withdraw;
40381db7 5005 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5006 vnc_import_bgp_exterior_del_route(
40381db7 5007 bgp, p, pi);
d62a17ae 5008 }
5009 }
65efcfce 5010#endif
40381db7
DS
5011 bgp_attr_unintern(&pi->attr);
5012 pi->attr = attr_new;
5013 pi->uptime = bgp_clock();
65efcfce 5014#if ENABLE_BGP_VNC
d62a17ae 5015 if ((afi == AFI_IP || afi == AFI_IP6)
5016 && (safi == SAFI_UNICAST)) {
5017 if (vnc_implicit_withdraw) {
40381db7 5018 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5019 vnc_import_bgp_exterior_add_route(
40381db7 5020 bgp, p, pi);
d62a17ae 5021 }
5022 }
65efcfce 5023#endif
718e3744 5024
d62a17ae 5025 /* Nexthop reachability check. */
5026 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
5027 && (safi == SAFI_UNICAST
5028 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5029
5030 struct bgp *bgp_nexthop = bgp;
5031
40381db7
DS
5032 if (pi->extra && pi->extra->bgp_orig)
5033 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5034
5035 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
40381db7
DS
5036 afi, pi, NULL, 0))
5037 bgp_path_info_set_flag(rn, pi,
18ee8310 5038 BGP_PATH_VALID);
d62a17ae 5039 else {
5040 if (BGP_DEBUG(nht, NHT)) {
5041 char buf1[INET6_ADDRSTRLEN];
5042 inet_ntop(p->family,
5043 &p->u.prefix, buf1,
5044 INET6_ADDRSTRLEN);
5045 zlog_debug(
5046 "%s(%s): Route not in table, not advertising",
5047 __FUNCTION__, buf1);
5048 }
18ee8310 5049 bgp_path_info_unset_flag(
40381db7 5050 rn, pi, BGP_PATH_VALID);
d62a17ae 5051 }
5052 } else {
5053 /* Delete the NHT structure if any, if we're
5054 * toggling between
5055 * enabling/disabling import check. We
5056 * deregister the route
5057 * from NHT to avoid overloading NHT and the
5058 * process interaction
5059 */
40381db7
DS
5060 bgp_unlink_nexthop(pi);
5061 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 5062 }
5063 /* Process change. */
40381db7 5064 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 5065 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
5066
5067 if (SAFI_UNICAST == safi
5068 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5069 || bgp->inst_type
5070 == BGP_INSTANCE_TYPE_DEFAULT)) {
5071 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5072 pi);
ddb5b488
PZ
5073 }
5074
d62a17ae 5075 bgp_unlock_node(rn);
5076 aspath_unintern(&attr.aspath);
5077 return;
5078 }
718e3744 5079 }
718e3744 5080
d62a17ae 5081 /* Make new BGP info. */
5082 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
5083 attr_new, rn);
5084 /* Nexthop reachability check. */
5085 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
5086 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 5087 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
18ee8310 5088 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
d62a17ae 5089 else {
5090 if (BGP_DEBUG(nht, NHT)) {
5091 char buf1[INET6_ADDRSTRLEN];
5092 inet_ntop(p->family, &p->u.prefix, buf1,
5093 INET6_ADDRSTRLEN);
5094 zlog_debug(
5095 "%s(%s): Route not in table, not advertising",
5096 __FUNCTION__, buf1);
5097 }
18ee8310 5098 bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID);
d62a17ae 5099 }
5100 } else {
5101 /* Delete the NHT structure if any, if we're toggling between
5102 * enabling/disabling import check. We deregister the route
5103 * from NHT to avoid overloading NHT and the process interaction
5104 */
5105 bgp_unlink_nexthop(new);
5106
18ee8310 5107 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
fc9a856f 5108 }
078430f6 5109
d62a17ae 5110 /* Aggregate address increment. */
5111 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5112
d62a17ae 5113 /* Register new BGP information. */
18ee8310 5114 bgp_path_info_add(rn, new);
718e3744 5115
d62a17ae 5116 /* route_node_get lock */
5117 bgp_unlock_node(rn);
5118
5119 /* Process change. */
5120 bgp_process(bgp, rn, afi, safi);
5121
ddb5b488
PZ
5122 if (SAFI_UNICAST == safi
5123 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5124 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5125 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5126 }
5127
d62a17ae 5128 /* Unintern original. */
5129 aspath_unintern(&attr.aspath);
718e3744 5130}
5131
d62a17ae 5132void bgp_static_withdraw(struct bgp *bgp, struct prefix *p, afi_t afi,
5133 safi_t safi)
718e3744 5134{
d62a17ae 5135 struct bgp_node *rn;
40381db7 5136 struct bgp_path_info *pi;
718e3744 5137
d62a17ae 5138 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5139
d62a17ae 5140 /* Check selected route and self inserted route. */
6f94b685 5141 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
5142 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5143 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5144 break;
5145
5146 /* Withdraw static BGP route from routing table. */
40381db7 5147 if (pi) {
ddb5b488
PZ
5148 if (SAFI_UNICAST == safi
5149 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5150 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5151 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5152 }
40381db7
DS
5153 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5154 bgp_unlink_nexthop(pi);
5155 bgp_path_info_delete(rn, pi);
d62a17ae 5156 bgp_process(bgp, rn, afi, safi);
5157 }
718e3744 5158
d62a17ae 5159 /* Unlock bgp_node_lookup. */
5160 bgp_unlock_node(rn);
718e3744 5161}
5162
137446f9
LB
5163/*
5164 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5165 */
d62a17ae 5166static void bgp_static_withdraw_safi(struct bgp *bgp, struct prefix *p,
5167 afi_t afi, safi_t safi,
5168 struct prefix_rd *prd)
718e3744 5169{
d62a17ae 5170 struct bgp_node *rn;
40381db7 5171 struct bgp_path_info *pi;
718e3744 5172
d62a17ae 5173 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5174
d62a17ae 5175 /* Check selected route and self inserted route. */
6f94b685 5176 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
5177 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5178 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5179 break;
718e3744 5180
d62a17ae 5181 /* Withdraw static BGP route from routing table. */
40381db7 5182 if (pi) {
65efcfce 5183#if ENABLE_BGP_VNC
d62a17ae 5184 rfapiProcessWithdraw(
40381db7 5185 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5186 1); /* Kill, since it is an administrative change */
65efcfce 5187#endif
ddb5b488
PZ
5188 if (SAFI_MPLS_VPN == safi
5189 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5190 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5191 }
40381db7
DS
5192 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5193 bgp_path_info_delete(rn, pi);
d62a17ae 5194 bgp_process(bgp, rn, afi, safi);
5195 }
718e3744 5196
d62a17ae 5197 /* Unlock bgp_node_lookup. */
5198 bgp_unlock_node(rn);
718e3744 5199}
5200
d62a17ae 5201static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p,
5202 struct bgp_static *bgp_static, afi_t afi,
5203 safi_t safi)
137446f9 5204{
d62a17ae 5205 struct bgp_node *rn;
4b7e6066 5206 struct bgp_path_info *new;
d62a17ae 5207 struct attr *attr_new;
5208 struct attr attr = {0};
40381db7 5209 struct bgp_path_info *pi;
65efcfce 5210#if ENABLE_BGP_VNC
d62a17ae 5211 mpls_label_t label = 0;
65efcfce 5212#endif
d7c0a89a 5213 uint32_t num_labels = 0;
d62a17ae 5214 union gw_addr add;
137446f9 5215
d62a17ae 5216 assert(bgp_static);
137446f9 5217
b57ba6d2
MK
5218 if (bgp_static->label != MPLS_INVALID_LABEL)
5219 num_labels = 1;
d62a17ae 5220 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5221 &bgp_static->prd);
137446f9 5222
d62a17ae 5223 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5224
d62a17ae 5225 attr.nexthop = bgp_static->igpnexthop;
5226 attr.med = bgp_static->igpmetric;
5227 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5228
d62a17ae 5229 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5230 || (safi == SAFI_ENCAP)) {
5231 if (afi == AFI_IP) {
5232 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5233 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5234 }
5235 }
5236 if (afi == AFI_L2VPN) {
5237 if (bgp_static->gatewayIp.family == AF_INET)
5238 add.ipv4.s_addr =
5239 bgp_static->gatewayIp.u.prefix4.s_addr;
5240 else if (bgp_static->gatewayIp.family == AF_INET6)
5241 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5242 sizeof(struct in6_addr));
5243 overlay_index_update(&attr, bgp_static->eth_s_id, &add);
5244 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5245 struct bgp_encap_type_vxlan bet;
5246 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5247 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5248 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5249 }
5250 if (bgp_static->router_mac) {
5251 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5252 }
5253 }
5254 /* Apply route-map. */
5255 if (bgp_static->rmap.name) {
5256 struct attr attr_tmp = attr;
40381db7 5257 struct bgp_path_info rmap_path;
b68885f9 5258 route_map_result_t ret;
137446f9 5259
40381db7
DS
5260 rmap_path.peer = bgp->peer_self;
5261 rmap_path.attr = &attr_tmp;
137446f9 5262
d62a17ae 5263 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5264
40381db7
DS
5265 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
5266 &rmap_path);
137446f9 5267
d62a17ae 5268 bgp->peer_self->rmap_type = 0;
137446f9 5269
d62a17ae 5270 if (ret == RMAP_DENYMATCH) {
5271 /* Free uninterned attribute. */
5272 bgp_attr_flush(&attr_tmp);
137446f9 5273
d62a17ae 5274 /* Unintern original. */
5275 aspath_unintern(&attr.aspath);
5276 bgp_static_withdraw_safi(bgp, p, afi, safi,
5277 &bgp_static->prd);
5278 return;
5279 }
137446f9 5280
d62a17ae 5281 attr_new = bgp_attr_intern(&attr_tmp);
5282 } else {
5283 attr_new = bgp_attr_intern(&attr);
5284 }
137446f9 5285
6f94b685 5286 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
5287 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5288 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5289 break;
5290
40381db7 5291 if (pi) {
d62a17ae 5292 memset(&add, 0, sizeof(union gw_addr));
40381db7
DS
5293 if (attrhash_cmp(pi->attr, attr_new)
5294 && overlay_index_equal(afi, pi, bgp_static->eth_s_id, &add)
5295 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 5296 bgp_unlock_node(rn);
5297 bgp_attr_unintern(&attr_new);
5298 aspath_unintern(&attr.aspath);
5299 return;
5300 } else {
5301 /* The attribute is changed. */
40381db7 5302 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5303
5304 /* Rewrite BGP route information. */
40381db7
DS
5305 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
5306 bgp_path_info_restore(rn, pi);
d62a17ae 5307 else
40381db7
DS
5308 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5309 bgp_attr_unintern(&pi->attr);
5310 pi->attr = attr_new;
5311 pi->uptime = bgp_clock();
65efcfce 5312#if ENABLE_BGP_VNC
40381db7
DS
5313 if (pi->extra)
5314 label = decode_label(&pi->extra->label[0]);
65efcfce 5315#endif
137446f9 5316
d62a17ae 5317 /* Process change. */
40381db7 5318 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 5319 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
5320
5321 if (SAFI_MPLS_VPN == safi
5322 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5323 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5324 }
65efcfce 5325#if ENABLE_BGP_VNC
40381db7
DS
5326 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5327 pi->attr, afi, safi, pi->type,
5328 pi->sub_type, &label);
65efcfce 5329#endif
d62a17ae 5330 bgp_unlock_node(rn);
5331 aspath_unintern(&attr.aspath);
5332 return;
5333 }
5334 }
137446f9
LB
5335
5336
d62a17ae 5337 /* Make new BGP info. */
5338 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
5339 attr_new, rn);
1defdda8 5340 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5341 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5342 if (num_labels) {
5343 new->extra->label[0] = bgp_static->label;
5344 new->extra->num_labels = num_labels;
5345 }
65efcfce 5346#if ENABLE_BGP_VNC
d62a17ae 5347 label = decode_label(&bgp_static->label);
65efcfce 5348#endif
137446f9 5349
d62a17ae 5350 /* Aggregate address increment. */
5351 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5352
d62a17ae 5353 /* Register new BGP information. */
18ee8310 5354 bgp_path_info_add(rn, new);
d62a17ae 5355 /* route_node_get lock */
5356 bgp_unlock_node(rn);
137446f9 5357
d62a17ae 5358 /* Process change. */
5359 bgp_process(bgp, rn, afi, safi);
137446f9 5360
ddb5b488
PZ
5361 if (SAFI_MPLS_VPN == safi
5362 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5363 vpn_leak_to_vrf_update(bgp, new);
5364 }
65efcfce 5365#if ENABLE_BGP_VNC
d62a17ae 5366 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5367 safi, new->type, new->sub_type, &label);
65efcfce
LB
5368#endif
5369
d62a17ae 5370 /* Unintern original. */
5371 aspath_unintern(&attr.aspath);
137446f9
LB
5372}
5373
718e3744 5374/* Configure static BGP network. When user don't run zebra, static
5375 route should be installed as valid. */
e2a86ad9
DS
5376static int bgp_static_set(struct vty *vty, const char *negate,
5377 const char *ip_str, afi_t afi, safi_t safi,
d7c0a89a 5378 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 5379{
5380 VTY_DECLVAR_CONTEXT(bgp, bgp);
5381 int ret;
5382 struct prefix p;
5383 struct bgp_static *bgp_static;
5384 struct bgp_node *rn;
d7c0a89a 5385 uint8_t need_update = 0;
d62a17ae 5386
5387 /* Convert IP prefix string to struct prefix. */
5388 ret = str2prefix(ip_str, &p);
5389 if (!ret) {
5390 vty_out(vty, "%% Malformed prefix\n");
5391 return CMD_WARNING_CONFIG_FAILED;
5392 }
5393 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5394 vty_out(vty, "%% Malformed prefix (link-local address)\n");
5395 return CMD_WARNING_CONFIG_FAILED;
5396 }
718e3744 5397
d62a17ae 5398 apply_mask(&p);
718e3744 5399
e2a86ad9 5400 if (negate) {
718e3744 5401
e2a86ad9
DS
5402 /* Set BGP static route configuration. */
5403 rn = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5404
e2a86ad9 5405 if (!rn) {
a4d82a8a 5406 vty_out(vty, "%% Can't find static route specified\n");
d62a17ae 5407 return CMD_WARNING_CONFIG_FAILED;
5408 }
5409
5a8ba9fc 5410 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 5411
e2a86ad9
DS
5412 if ((label_index != BGP_INVALID_LABEL_INDEX)
5413 && (label_index != bgp_static->label_index)) {
5414 vty_out(vty,
5415 "%% label-index doesn't match static route\n");
5416 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5417 }
d62a17ae 5418
e2a86ad9
DS
5419 if ((rmap && bgp_static->rmap.name)
5420 && strcmp(rmap, bgp_static->rmap.name)) {
5421 vty_out(vty,
5422 "%% route-map name doesn't match static route\n");
5423 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5424 }
718e3744 5425
e2a86ad9
DS
5426 /* Update BGP RIB. */
5427 if (!bgp_static->backdoor)
5428 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5429
e2a86ad9
DS
5430 /* Clear configuration. */
5431 bgp_static_free(bgp_static);
5a8ba9fc 5432 bgp_node_set_bgp_static_info(rn, NULL);
e2a86ad9
DS
5433 bgp_unlock_node(rn);
5434 bgp_unlock_node(rn);
5435 } else {
718e3744 5436
e2a86ad9
DS
5437 /* Set BGP static route configuration. */
5438 rn = bgp_node_get(bgp->route[afi][safi], &p);
718e3744 5439
5a8ba9fc 5440 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 5441 if (bgp_static) {
e2a86ad9 5442 /* Configuration change. */
e2a86ad9
DS
5443 /* Label index cannot be changed. */
5444 if (bgp_static->label_index != label_index) {
5445 vty_out(vty, "%% cannot change label-index\n");
5446 return CMD_WARNING_CONFIG_FAILED;
5447 }
d62a17ae 5448
e2a86ad9 5449 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5450 if (bgp_static->valid
5451 && bgp_static->backdoor != backdoor)
e2a86ad9 5452 need_update = 1;
718e3744 5453
e2a86ad9 5454 bgp_static->backdoor = backdoor;
718e3744 5455
e2a86ad9 5456 if (rmap) {
0a22ddfb
QY
5457 XFREE(MTYPE_ROUTE_MAP_NAME,
5458 bgp_static->rmap.name);
b4897fa5 5459 route_map_counter_decrement(
5460 bgp_static->rmap.map);
e2a86ad9
DS
5461 bgp_static->rmap.name =
5462 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5463 bgp_static->rmap.map =
5464 route_map_lookup_by_name(rmap);
b4897fa5 5465 route_map_counter_increment(
5466 bgp_static->rmap.map);
e2a86ad9 5467 } else {
0a22ddfb
QY
5468 XFREE(MTYPE_ROUTE_MAP_NAME,
5469 bgp_static->rmap.name);
b4897fa5 5470 route_map_counter_decrement(
5471 bgp_static->rmap.map);
e2a86ad9
DS
5472 bgp_static->rmap.name = NULL;
5473 bgp_static->rmap.map = NULL;
5474 bgp_static->valid = 0;
5475 }
5476 bgp_unlock_node(rn);
5477 } else {
5478 /* New configuration. */
5479 bgp_static = bgp_static_new();
5480 bgp_static->backdoor = backdoor;
5481 bgp_static->valid = 0;
5482 bgp_static->igpmetric = 0;
5483 bgp_static->igpnexthop.s_addr = 0;
5484 bgp_static->label_index = label_index;
718e3744 5485
e2a86ad9 5486 if (rmap) {
0a22ddfb
QY
5487 XFREE(MTYPE_ROUTE_MAP_NAME,
5488 bgp_static->rmap.name);
b4897fa5 5489 route_map_counter_decrement(
5490 bgp_static->rmap.map);
e2a86ad9
DS
5491 bgp_static->rmap.name =
5492 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5493 bgp_static->rmap.map =
5494 route_map_lookup_by_name(rmap);
b4897fa5 5495 route_map_counter_increment(
5496 bgp_static->rmap.map);
e2a86ad9 5497 }
5a8ba9fc 5498 bgp_node_set_bgp_static_info(rn, bgp_static);
e2a86ad9 5499 }
d62a17ae 5500
e2a86ad9
DS
5501 bgp_static->valid = 1;
5502 if (need_update)
5503 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5504
e2a86ad9
DS
5505 if (!bgp_static->backdoor)
5506 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5507 }
d62a17ae 5508
5509 return CMD_SUCCESS;
5510}
5511
5512void bgp_static_add(struct bgp *bgp)
5513{
5514 afi_t afi;
5515 safi_t safi;
5516 struct bgp_node *rn;
5517 struct bgp_node *rm;
5518 struct bgp_table *table;
5519 struct bgp_static *bgp_static;
5520
05c7a1cc
QY
5521 FOREACH_AFI_SAFI (afi, safi)
5522 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5523 rn = bgp_route_next(rn)) {
67009e22 5524 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5525 continue;
ea47320b 5526
05c7a1cc
QY
5527 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5528 || (safi == SAFI_EVPN)) {
67009e22 5529 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5530
5531 for (rm = bgp_table_top(table); rm;
5532 rm = bgp_route_next(rm)) {
a78beeb5 5533 bgp_static =
5a8ba9fc
DS
5534 bgp_node_get_bgp_static_info(
5535 rm);
05c7a1cc
QY
5536 bgp_static_update_safi(bgp, &rm->p,
5537 bgp_static, afi,
5538 safi);
d62a17ae 5539 }
05c7a1cc 5540 } else {
5a8ba9fc
DS
5541 bgp_static_update(
5542 bgp, &rn->p,
5543 bgp_node_get_bgp_static_info(rn), afi,
5544 safi);
ea47320b 5545 }
05c7a1cc 5546 }
6aeb9e78
DS
5547}
5548
718e3744 5549/* Called from bgp_delete(). Delete all static routes from the BGP
5550 instance. */
d62a17ae 5551void bgp_static_delete(struct bgp *bgp)
5552{
5553 afi_t afi;
5554 safi_t safi;
5555 struct bgp_node *rn;
5556 struct bgp_node *rm;
5557 struct bgp_table *table;
5558 struct bgp_static *bgp_static;
5559
05c7a1cc
QY
5560 FOREACH_AFI_SAFI (afi, safi)
5561 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5562 rn = bgp_route_next(rn)) {
67009e22 5563 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5564 continue;
ea47320b 5565
05c7a1cc
QY
5566 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5567 || (safi == SAFI_EVPN)) {
67009e22 5568 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5569
5570 for (rm = bgp_table_top(table); rm;
5571 rm = bgp_route_next(rm)) {
a78beeb5 5572 bgp_static =
5a8ba9fc
DS
5573 bgp_node_get_bgp_static_info(
5574 rm);
c7d14ba6
PG
5575 if (!bgp_static)
5576 continue;
5577
05c7a1cc
QY
5578 bgp_static_withdraw_safi(
5579 bgp, &rm->p, AFI_IP, safi,
5580 (struct prefix_rd *)&rn->p);
ea47320b 5581 bgp_static_free(bgp_static);
5a8ba9fc 5582 bgp_node_set_bgp_static_info(rn, NULL);
ea47320b 5583 bgp_unlock_node(rn);
d62a17ae 5584 }
05c7a1cc 5585 } else {
5a8ba9fc 5586 bgp_static = bgp_node_get_bgp_static_info(rn);
05c7a1cc
QY
5587 bgp_static_withdraw(bgp, &rn->p, afi, safi);
5588 bgp_static_free(bgp_static);
5a8ba9fc 5589 bgp_node_set_bgp_static_info(rn, NULL);
05c7a1cc 5590 bgp_unlock_node(rn);
ea47320b 5591 }
05c7a1cc 5592 }
d62a17ae 5593}
5594
5595void bgp_static_redo_import_check(struct bgp *bgp)
5596{
5597 afi_t afi;
5598 safi_t safi;
5599 struct bgp_node *rn;
5600 struct bgp_node *rm;
5601 struct bgp_table *table;
5602 struct bgp_static *bgp_static;
5603
5604 /* Use this flag to force reprocessing of the route */
5605 bgp_flag_set(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc
QY
5606 FOREACH_AFI_SAFI (afi, safi) {
5607 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5608 rn = bgp_route_next(rn)) {
67009e22 5609 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5610 continue;
ea47320b 5611
05c7a1cc
QY
5612 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5613 || (safi == SAFI_EVPN)) {
67009e22 5614 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5615
5616 for (rm = bgp_table_top(table); rm;
5617 rm = bgp_route_next(rm)) {
a78beeb5 5618 bgp_static =
5a8ba9fc
DS
5619 bgp_node_get_bgp_static_info(
5620 rm);
05c7a1cc
QY
5621 bgp_static_update_safi(bgp, &rm->p,
5622 bgp_static, afi,
5623 safi);
d62a17ae 5624 }
05c7a1cc 5625 } else {
5a8ba9fc 5626 bgp_static = bgp_node_get_bgp_static_info(rn);
05c7a1cc
QY
5627 bgp_static_update(bgp, &rn->p, bgp_static, afi,
5628 safi);
ea47320b 5629 }
05c7a1cc
QY
5630 }
5631 }
d62a17ae 5632 bgp_flag_unset(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
5633}
5634
5635static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
5636 safi_t safi)
5637{
5638 struct bgp_table *table;
5639 struct bgp_node *rn;
40381db7 5640 struct bgp_path_info *pi;
d62a17ae 5641
dfb6fd1d
NT
5642 /* Do not install the aggregate route if BGP is in the
5643 * process of termination.
5644 */
5645 if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS) ||
5646 (bgp->peer_self == NULL))
5647 return;
5648
d62a17ae 5649 table = bgp->rib[afi][safi];
5650 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685 5651 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7
DS
5652 if (pi->peer == bgp->peer_self
5653 && ((pi->type == ZEBRA_ROUTE_BGP
5654 && pi->sub_type == BGP_ROUTE_STATIC)
5655 || (pi->type != ZEBRA_ROUTE_BGP
5656 && pi->sub_type
d62a17ae 5657 == BGP_ROUTE_REDISTRIBUTE))) {
40381db7 5658 bgp_aggregate_decrement(bgp, &rn->p, pi, afi,
d62a17ae 5659 safi);
40381db7
DS
5660 bgp_unlink_nexthop(pi);
5661 bgp_path_info_delete(rn, pi);
d62a17ae 5662 bgp_process(bgp, rn, afi, safi);
5663 }
5664 }
5665 }
ad4cbda1 5666}
5667
5668/*
5669 * Purge all networks and redistributed routes from routing table.
5670 * Invoked upon the instance going down.
5671 */
d62a17ae 5672void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 5673{
d62a17ae 5674 afi_t afi;
5675 safi_t safi;
ad4cbda1 5676
05c7a1cc
QY
5677 FOREACH_AFI_SAFI (afi, safi)
5678 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 5679}
5680
137446f9
LB
5681/*
5682 * gpz 110624
5683 * Currently this is used to set static routes for VPN and ENCAP.
5684 * I think it can probably be factored with bgp_static_set.
5685 */
d62a17ae 5686int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
5687 const char *ip_str, const char *rd_str,
5688 const char *label_str, const char *rmap_str,
5689 int evpn_type, const char *esi, const char *gwip,
5690 const char *ethtag, const char *routermac)
5691{
5692 VTY_DECLVAR_CONTEXT(bgp, bgp);
5693 int ret;
5694 struct prefix p;
5695 struct prefix_rd prd;
5696 struct bgp_node *prn;
5697 struct bgp_node *rn;
5698 struct bgp_table *table;
5699 struct bgp_static *bgp_static;
5700 mpls_label_t label = MPLS_INVALID_LABEL;
5701 struct prefix gw_ip;
5702
5703 /* validate ip prefix */
5704 ret = str2prefix(ip_str, &p);
5705 if (!ret) {
5706 vty_out(vty, "%% Malformed prefix\n");
5707 return CMD_WARNING_CONFIG_FAILED;
5708 }
5709 apply_mask(&p);
5710 if ((afi == AFI_L2VPN)
5711 && (bgp_build_evpn_prefix(evpn_type,
5712 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5713 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5714 return CMD_WARNING_CONFIG_FAILED;
5715 }
718e3744 5716
d62a17ae 5717 ret = str2prefix_rd(rd_str, &prd);
5718 if (!ret) {
5719 vty_out(vty, "%% Malformed rd\n");
5720 return CMD_WARNING_CONFIG_FAILED;
5721 }
718e3744 5722
d62a17ae 5723 if (label_str) {
5724 unsigned long label_val;
5725 label_val = strtoul(label_str, NULL, 10);
5726 encode_label(label_val, &label);
5727 }
9bedbb1e 5728
d62a17ae 5729 if (safi == SAFI_EVPN) {
5730 if (esi && str2esi(esi, NULL) == 0) {
5731 vty_out(vty, "%% Malformed ESI\n");
5732 return CMD_WARNING_CONFIG_FAILED;
5733 }
5734 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
5735 vty_out(vty, "%% Malformed Router MAC\n");
5736 return CMD_WARNING_CONFIG_FAILED;
5737 }
5738 if (gwip) {
5739 memset(&gw_ip, 0, sizeof(struct prefix));
5740 ret = str2prefix(gwip, &gw_ip);
5741 if (!ret) {
5742 vty_out(vty, "%% Malformed GatewayIp\n");
5743 return CMD_WARNING_CONFIG_FAILED;
5744 }
5745 if ((gw_ip.family == AF_INET
3714a385 5746 && is_evpn_prefix_ipaddr_v6(
d62a17ae 5747 (struct prefix_evpn *)&p))
5748 || (gw_ip.family == AF_INET6
3714a385 5749 && is_evpn_prefix_ipaddr_v4(
d62a17ae 5750 (struct prefix_evpn *)&p))) {
5751 vty_out(vty,
5752 "%% GatewayIp family differs with IP prefix\n");
5753 return CMD_WARNING_CONFIG_FAILED;
5754 }
5755 }
5756 }
5757 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
67009e22
DS
5758 if (!bgp_node_has_bgp_path_info_data(prn))
5759 bgp_node_set_bgp_table_info(prn,
5760 bgp_table_init(bgp, afi, safi));
67009e22 5761 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 5762
5763 rn = bgp_node_get(table, &p);
5764
67009e22 5765 if (bgp_node_has_bgp_path_info_data(rn)) {
d62a17ae 5766 vty_out(vty, "%% Same network configuration exists\n");
5767 bgp_unlock_node(rn);
5768 } else {
5769 /* New configuration. */
5770 bgp_static = bgp_static_new();
5771 bgp_static->backdoor = 0;
5772 bgp_static->valid = 0;
5773 bgp_static->igpmetric = 0;
5774 bgp_static->igpnexthop.s_addr = 0;
5775 bgp_static->label = label;
5776 bgp_static->prd = prd;
5777
5778 if (rmap_str) {
0a22ddfb 5779 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5780 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 5781 bgp_static->rmap.name =
5782 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
5783 bgp_static->rmap.map =
5784 route_map_lookup_by_name(rmap_str);
b4897fa5 5785 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 5786 }
718e3744 5787
d62a17ae 5788 if (safi == SAFI_EVPN) {
5789 if (esi) {
5790 bgp_static->eth_s_id =
5791 XCALLOC(MTYPE_ATTR,
5792 sizeof(struct eth_segment_id));
5793 str2esi(esi, bgp_static->eth_s_id);
5794 }
5795 if (routermac) {
5796 bgp_static->router_mac =
28328ea9 5797 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
5798 (void)prefix_str2mac(routermac,
5799 bgp_static->router_mac);
d62a17ae 5800 }
5801 if (gwip)
5802 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
5803 }
5a8ba9fc 5804 bgp_node_set_bgp_static_info(rn, bgp_static);
718e3744 5805
d62a17ae 5806 bgp_static->valid = 1;
5807 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
5808 }
718e3744 5809
d62a17ae 5810 return CMD_SUCCESS;
718e3744 5811}
5812
5813/* Configure static BGP network. */
d62a17ae 5814int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
5815 const char *ip_str, const char *rd_str,
5816 const char *label_str, int evpn_type, const char *esi,
5817 const char *gwip, const char *ethtag)
5818{
5819 VTY_DECLVAR_CONTEXT(bgp, bgp);
5820 int ret;
5821 struct prefix p;
5822 struct prefix_rd prd;
5823 struct bgp_node *prn;
5824 struct bgp_node *rn;
5825 struct bgp_table *table;
5826 struct bgp_static *bgp_static;
5827 mpls_label_t label = MPLS_INVALID_LABEL;
5828
5829 /* Convert IP prefix string to struct prefix. */
5830 ret = str2prefix(ip_str, &p);
5831 if (!ret) {
5832 vty_out(vty, "%% Malformed prefix\n");
5833 return CMD_WARNING_CONFIG_FAILED;
5834 }
5835 apply_mask(&p);
5836 if ((afi == AFI_L2VPN)
5837 && (bgp_build_evpn_prefix(evpn_type,
5838 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5839 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5840 return CMD_WARNING_CONFIG_FAILED;
5841 }
5842 ret = str2prefix_rd(rd_str, &prd);
5843 if (!ret) {
5844 vty_out(vty, "%% Malformed rd\n");
5845 return CMD_WARNING_CONFIG_FAILED;
5846 }
718e3744 5847
d62a17ae 5848 if (label_str) {
5849 unsigned long label_val;
5850 label_val = strtoul(label_str, NULL, 10);
5851 encode_label(label_val, &label);
5852 }
718e3744 5853
d62a17ae 5854 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
67009e22
DS
5855 if (!bgp_node_has_bgp_path_info_data(prn))
5856 bgp_node_set_bgp_table_info(prn,
5857 bgp_table_init(bgp, afi, safi));
d62a17ae 5858 else
5859 bgp_unlock_node(prn);
67009e22 5860 table = bgp_node_get_bgp_table_info(prn);
718e3744 5861
d62a17ae 5862 rn = bgp_node_lookup(table, &p);
6b0655a2 5863
d62a17ae 5864 if (rn) {
5865 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 5866
5a8ba9fc 5867 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 5868 bgp_static_free(bgp_static);
5a8ba9fc 5869 bgp_node_set_bgp_static_info(rn, NULL);
d62a17ae 5870 bgp_unlock_node(rn);
5871 bgp_unlock_node(rn);
5872 } else
5873 vty_out(vty, "%% Can't find the route\n");
5874
5875 return CMD_SUCCESS;
5876}
5877
5878static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
5879 const char *rmap_name)
5880{
5881 VTY_DECLVAR_CONTEXT(bgp, bgp);
5882 struct bgp_rmap *rmap;
5883
5884 rmap = &bgp->table_map[afi][safi];
5885 if (rmap_name) {
0a22ddfb 5886 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5887 route_map_counter_decrement(rmap->map);
d62a17ae 5888 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
5889 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 5890 route_map_counter_increment(rmap->map);
d62a17ae 5891 } else {
0a22ddfb 5892 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5893 route_map_counter_decrement(rmap->map);
d62a17ae 5894 rmap->name = NULL;
5895 rmap->map = NULL;
5896 }
73ac8160 5897
d62a17ae 5898 if (bgp_fibupd_safi(safi))
5899 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5900
d62a17ae 5901 return CMD_SUCCESS;
73ac8160
DS
5902}
5903
d62a17ae 5904static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
5905 const char *rmap_name)
73ac8160 5906{
d62a17ae 5907 VTY_DECLVAR_CONTEXT(bgp, bgp);
5908 struct bgp_rmap *rmap;
73ac8160 5909
d62a17ae 5910 rmap = &bgp->table_map[afi][safi];
0a22ddfb 5911 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5912 route_map_counter_decrement(rmap->map);
d62a17ae 5913 rmap->name = NULL;
5914 rmap->map = NULL;
73ac8160 5915
d62a17ae 5916 if (bgp_fibupd_safi(safi))
5917 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5918
d62a17ae 5919 return CMD_SUCCESS;
73ac8160
DS
5920}
5921
2b791107 5922void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 5923 safi_t safi)
73ac8160 5924{
d62a17ae 5925 if (bgp->table_map[afi][safi].name) {
d62a17ae 5926 vty_out(vty, " table-map %s\n",
5927 bgp->table_map[afi][safi].name);
5928 }
73ac8160
DS
5929}
5930
73ac8160
DS
5931DEFUN (bgp_table_map,
5932 bgp_table_map_cmd,
5933 "table-map WORD",
5934 "BGP table to RIB route download filter\n"
5935 "Name of the route map\n")
5936{
d62a17ae 5937 int idx_word = 1;
5938 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5939 argv[idx_word]->arg);
73ac8160
DS
5940}
5941DEFUN (no_bgp_table_map,
5942 no_bgp_table_map_cmd,
5943 "no table-map WORD",
3a2d747c 5944 NO_STR
73ac8160
DS
5945 "BGP table to RIB route download filter\n"
5946 "Name of the route map\n")
5947{
d62a17ae 5948 int idx_word = 2;
5949 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5950 argv[idx_word]->arg);
73ac8160
DS
5951}
5952
e2a86ad9
DS
5953DEFPY(bgp_network,
5954 bgp_network_cmd,
5955 "[no] network \
5956 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5957 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5958 backdoor$backdoor}]",
5959 NO_STR
5960 "Specify a network to announce via BGP\n"
5961 "IPv4 prefix\n"
5962 "Network number\n"
5963 "Network mask\n"
5964 "Network mask\n"
5965 "Route-map to modify the attributes\n"
5966 "Name of the route map\n"
5967 "Label index to associate with the prefix\n"
5968 "Label index value\n"
5969 "Specify a BGP backdoor route\n")
5970{
5971 char addr_prefix_str[BUFSIZ];
5972
5973 if (address_str) {
5974 int ret;
718e3744 5975
e2a86ad9
DS
5976 ret = netmask_str2prefix_str(address_str, netmask_str,
5977 addr_prefix_str);
5978 if (!ret) {
5979 vty_out(vty, "%% Inconsistent address and mask\n");
5980 return CMD_WARNING_CONFIG_FAILED;
5981 }
d62a17ae 5982 }
718e3744 5983
a4d82a8a
PZ
5984 return bgp_static_set(
5985 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
5986 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
5987 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 5988}
5989
e2a86ad9
DS
5990DEFPY(ipv6_bgp_network,
5991 ipv6_bgp_network_cmd,
5992 "[no] network X:X::X:X/M$prefix \
5993 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5994 NO_STR
5995 "Specify a network to announce via BGP\n"
5996 "IPv6 prefix\n"
5997 "Route-map to modify the attributes\n"
5998 "Name of the route map\n"
5999 "Label index to associate with the prefix\n"
6000 "Label index value\n")
718e3744 6001{
a4d82a8a
PZ
6002 return bgp_static_set(
6003 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
6004 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
6005}
6006
d62a17ae 6007static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6008{
d62a17ae 6009 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6010}
6011
d62a17ae 6012static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6013{
20894f50
DA
6014 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6015 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6016 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6017}
718e3744 6018
40381db7 6019static int bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
29f7d023 6020 struct aspath *aspath,
3da2cc32 6021 struct community *comm,
dd18c5a9
DS
6022 struct ecommunity *ecomm,
6023 struct lcommunity *lcomm)
eaaf8adb
DS
6024{
6025 static struct aspath *ae = NULL;
6026
6027 if (!ae)
6028 ae = aspath_empty();
6029
40381db7 6030 if (!pi)
eaaf8adb
DS
6031 return 0;
6032
40381db7 6033 if (origin != pi->attr->origin)
eaaf8adb
DS
6034 return 0;
6035
40381db7 6036 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
29f7d023
DS
6037 return 0;
6038
40381db7 6039 if (!community_cmp(pi->attr->community, comm))
eaaf8adb
DS
6040 return 0;
6041
3da2cc32 6042 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
eaaf8adb
DS
6043 return 0;
6044
dd18c5a9
DS
6045 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
6046 return 0;
6047
40381db7 6048 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
7ce8a8e0
DS
6049 return 0;
6050
eaaf8adb
DS
6051 return 1;
6052}
6053
c701010e
DS
6054static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi,
6055 struct prefix *p, uint8_t origin,
6056 struct aspath *aspath,
6057 struct community *community,
3da2cc32 6058 struct ecommunity *ecommunity,
dd18c5a9 6059 struct lcommunity *lcommunity,
c701010e
DS
6060 uint8_t atomic_aggregate,
6061 struct bgp_aggregate *aggregate)
6062{
6063 struct bgp_node *rn;
6064 struct bgp_table *table;
6f94b685 6065 struct bgp_path_info *pi, *orig, *new;
20894f50 6066 struct attr *attr;
c701010e
DS
6067
6068 table = bgp->rib[afi][safi];
6069
6070 rn = bgp_node_get(table, p);
eaaf8adb 6071
6f94b685 6072 for (orig = pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
6073 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6074 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6075 break;
6076
c701010e 6077 if (aggregate->count > 0) {
eaaf8adb
DS
6078 /*
6079 * If the aggregate information has not changed
6080 * no need to re-install it again.
6081 */
6f94b685 6082 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6083 ecommunity, lcommunity)) {
eaaf8adb
DS
6084 bgp_unlock_node(rn);
6085
6086 if (aspath)
6087 aspath_free(aspath);
6088 if (community)
3c1f53de 6089 community_free(&community);
3da2cc32
DS
6090 if (ecommunity)
6091 ecommunity_free(&ecommunity);
dd18c5a9
DS
6092 if (lcommunity)
6093 lcommunity_free(&lcommunity);
eaaf8adb
DS
6094
6095 return;
6096 }
6097
6098 /*
6099 * Mark the old as unusable
6100 */
40381db7
DS
6101 if (pi)
6102 bgp_path_info_delete(rn, pi);
eaaf8adb 6103
20894f50
DA
6104 attr = bgp_attr_aggregate_intern(
6105 bgp, origin, aspath, community, ecommunity, lcommunity,
6106 aggregate, atomic_aggregate, p);
6107
6108 if (!attr) {
6109 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
6110 return;
6111 }
6112
3da2cc32 6113 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
20894f50
DA
6114 bgp->peer_self, attr, rn);
6115
1defdda8 6116 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6117
18ee8310 6118 bgp_path_info_add(rn, new);
c701010e
DS
6119 bgp_process(bgp, rn, afi, safi);
6120 } else {
6f94b685 6121 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6122 if (pi->peer == bgp->peer_self
6123 && pi->type == ZEBRA_ROUTE_BGP
6124 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6125 break;
6126
6127 /* Withdraw static BGP route from routing table. */
40381db7
DS
6128 if (pi) {
6129 bgp_path_info_delete(rn, pi);
c701010e
DS
6130 bgp_process(bgp, rn, afi, safi);
6131 }
6132 }
6133
6134 bgp_unlock_node(rn);
6135}
6136
b5d58c32 6137/* Update an aggregate as routes are added/removed from the BGP table */
20894f50 6138void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
fc968841 6139 afi_t afi, safi_t safi,
d62a17ae 6140 struct bgp_aggregate *aggregate)
6141{
6142 struct bgp_table *table;
6143 struct bgp_node *top;
6144 struct bgp_node *rn;
d7c0a89a 6145 uint8_t origin;
d62a17ae 6146 struct aspath *aspath = NULL;
d62a17ae 6147 struct community *community = NULL;
3da2cc32 6148 struct ecommunity *ecommunity = NULL;
dd18c5a9 6149 struct lcommunity *lcommunity = NULL;
40381db7 6150 struct bgp_path_info *pi;
d62a17ae 6151 unsigned long match = 0;
d7c0a89a 6152 uint8_t atomic_aggregate = 0;
d62a17ae 6153
9f822fa2
S
6154 /* If the bgp instance is being deleted or self peer is deleted
6155 * then do not create aggregate route
6156 */
6157 if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS) ||
6158 (bgp->peer_self == NULL))
6159 return;
6160
d62a17ae 6161 /* ORIGIN attribute: If at least one route among routes that are
6162 aggregated has ORIGIN with the value INCOMPLETE, then the
6163 aggregated route must have the ORIGIN attribute with the value
6164 INCOMPLETE. Otherwise, if at least one route among routes that
6165 are aggregated has ORIGIN with the value EGP, then the aggregated
6166 route must have the origin attribute with the value EGP. In all
6167 other case the value of the ORIGIN attribute of the aggregated
6168 route is INTERNAL. */
6169 origin = BGP_ORIGIN_IGP;
718e3744 6170
d62a17ae 6171 table = bgp->rib[afi][safi];
718e3744 6172
d62a17ae 6173 top = bgp_node_get(table, p);
6174 for (rn = bgp_node_get(table, p); rn;
c2ff8b3e
DS
6175 rn = bgp_route_next_until(rn, top)) {
6176 if (rn->p.prefixlen <= p->prefixlen)
6177 continue;
d62a17ae 6178
c2ff8b3e 6179 match = 0;
d62a17ae 6180
6f94b685 6181 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 6182 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 6183 continue;
718e3744 6184
40381db7 6185 if (pi->attr->flag
c2ff8b3e
DS
6186 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
6187 atomic_aggregate = 1;
d62a17ae 6188
40381db7 6189 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 6190 continue;
d62a17ae 6191
f273fef1
DS
6192 /*
6193 * summary-only aggregate route suppress
6194 * aggregated route announcements.
6195 */
c2ff8b3e 6196 if (aggregate->summary_only) {
40381db7
DS
6197 (bgp_path_info_extra_get(pi))->suppress++;
6198 bgp_path_info_set_flag(rn, pi,
18ee8310 6199 BGP_PATH_ATTR_CHANGED);
c2ff8b3e 6200 match++;
d62a17ae 6201 }
c2ff8b3e
DS
6202
6203 aggregate->count++;
6204
f273fef1
DS
6205 /*
6206 * If at least one route among routes that are
6207 * aggregated has ORIGIN with the value INCOMPLETE,
6208 * then the aggregated route MUST have the ORIGIN
6209 * attribute with the value INCOMPLETE. Otherwise, if
6210 * at least one route among routes that are aggregated
6211 * has ORIGIN with the value EGP, then the aggregated
6212 * route MUST have the ORIGIN attribute with the value
6213 * EGP.
6214 */
fc968841
NT
6215 switch (pi->attr->origin) {
6216 case BGP_ORIGIN_INCOMPLETE:
6217 aggregate->incomplete_origin_count++;
6218 break;
6219 case BGP_ORIGIN_EGP:
6220 aggregate->egp_origin_count++;
6221 break;
6222 default:
6223 /*Do nothing.
6224 */
6225 break;
6226 }
c2ff8b3e
DS
6227
6228 if (!aggregate->as_set)
6229 continue;
6230
f273fef1
DS
6231 /*
6232 * as-set aggregate route generate origin, as path,
6233 * and community aggregation.
6234 */
fc968841
NT
6235 /* Compute aggregate route's as-path.
6236 */
ef51a7d8 6237 bgp_compute_aggregate_aspath_hash(aggregate,
6238 pi->attr->aspath);
c2ff8b3e 6239
fc968841
NT
6240 /* Compute aggregate route's community.
6241 */
6242 if (pi->attr->community)
21fec674 6243 bgp_compute_aggregate_community_hash(
fc968841
NT
6244 aggregate,
6245 pi->attr->community);
dd18c5a9 6246
fc968841
NT
6247 /* Compute aggregate route's extended community.
6248 */
6249 if (pi->attr->ecommunity)
4edd83f9 6250 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
6251 aggregate,
6252 pi->attr->ecommunity);
6253
6254 /* Compute aggregate route's large community.
6255 */
6256 if (pi->attr->lcommunity)
f1eb1f05 6257 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
6258 aggregate,
6259 pi->attr->lcommunity);
d62a17ae 6260 }
c2ff8b3e
DS
6261 if (match)
6262 bgp_process(bgp, rn, afi, safi);
6263 }
21fec674 6264 if (aggregate->as_set) {
ef51a7d8 6265 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 6266 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 6267 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 6268 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 6269 }
6270
f1eb1f05 6271
d62a17ae 6272 bgp_unlock_node(top);
718e3744 6273
718e3744 6274
fc968841
NT
6275 if (aggregate->incomplete_origin_count > 0)
6276 origin = BGP_ORIGIN_INCOMPLETE;
6277 else if (aggregate->egp_origin_count > 0)
6278 origin = BGP_ORIGIN_EGP;
d62a17ae 6279
fc968841
NT
6280 if (aggregate->as_set) {
6281 if (aggregate->aspath)
6282 /* Retrieve aggregate route's as-path.
6283 */
6284 aspath = aspath_dup(aggregate->aspath);
d62a17ae 6285
fc968841
NT
6286 if (aggregate->community)
6287 /* Retrieve aggregate route's community.
6288 */
6289 community = community_dup(aggregate->community);
3da2cc32 6290
fc968841
NT
6291 if (aggregate->ecommunity)
6292 /* Retrieve aggregate route's ecommunity.
6293 */
6294 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 6295
fc968841
NT
6296 if (aggregate->lcommunity)
6297 /* Retrieve aggregate route's lcommunity.
6298 */
6299 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 6300 }
718e3744 6301
c701010e 6302 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
6303 ecommunity, lcommunity, atomic_aggregate,
6304 aggregate);
718e3744 6305}
6306
20894f50 6307void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
3b7db173
DS
6308 safi_t safi, struct bgp_aggregate *aggregate)
6309{
6310 struct bgp_table *table;
6311 struct bgp_node *top;
6312 struct bgp_node *rn;
40381db7 6313 struct bgp_path_info *pi;
3b7db173
DS
6314 unsigned long match;
6315
6316 table = bgp->rib[afi][safi];
6317
6318 /* If routes exists below this node, generate aggregate routes. */
6319 top = bgp_node_get(table, p);
6320 for (rn = bgp_node_get(table, p); rn;
6321 rn = bgp_route_next_until(rn, top)) {
6322 if (rn->p.prefixlen <= p->prefixlen)
6323 continue;
6324 match = 0;
6325
6f94b685 6326 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 6327 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
6328 continue;
6329
40381db7 6330 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
6331 continue;
6332
40381db7
DS
6333 if (aggregate->summary_only && pi->extra) {
6334 pi->extra->suppress--;
3b7db173 6335
40381db7 6336 if (pi->extra->suppress == 0) {
18ee8310 6337 bgp_path_info_set_flag(
40381db7 6338 rn, pi, BGP_PATH_ATTR_CHANGED);
3b7db173
DS
6339 match++;
6340 }
6341 }
6342 aggregate->count--;
fc968841
NT
6343
6344 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6345 aggregate->incomplete_origin_count--;
6346 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6347 aggregate->egp_origin_count--;
6348
6349 if (aggregate->as_set) {
6350 /* Remove as-path from aggregate.
6351 */
ef51a7d8 6352 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
6353 aggregate,
6354 pi->attr->aspath);
6355
6356 if (pi->attr->community)
6357 /* Remove community from aggregate.
6358 */
21fec674 6359 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
6360 aggregate,
6361 pi->attr->community);
6362
6363 if (pi->attr->ecommunity)
6364 /* Remove ecommunity from aggregate.
6365 */
4edd83f9 6366 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
6367 aggregate,
6368 pi->attr->ecommunity);
6369
6370 if (pi->attr->lcommunity)
6371 /* Remove lcommunity from aggregate.
6372 */
f1eb1f05 6373 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
6374 aggregate,
6375 pi->attr->lcommunity);
6376 }
6377
3b7db173
DS
6378 }
6379
6380 /* If this node was suppressed, process the change. */
6381 if (match)
6382 bgp_process(bgp, rn, afi, safi);
6383 }
f1eb1f05 6384 if (aggregate->as_set) {
ef51a7d8 6385 aspath_free(aggregate->aspath);
6386 aggregate->aspath = NULL;
21fec674 6387 if (aggregate->community)
6388 community_free(&aggregate->community);
4edd83f9 6389 if (aggregate->ecommunity)
6390 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 6391 if (aggregate->lcommunity)
6392 lcommunity_free(&aggregate->lcommunity);
6393 }
6394
3b7db173
DS
6395 bgp_unlock_node(top);
6396}
718e3744 6397
fc968841
NT
6398static void bgp_add_route_to_aggregate(struct bgp *bgp, struct prefix *aggr_p,
6399 struct bgp_path_info *pinew, afi_t afi,
6400 safi_t safi,
6401 struct bgp_aggregate *aggregate)
6402{
6403 uint8_t origin;
6404 struct aspath *aspath = NULL;
6405 uint8_t atomic_aggregate = 0;
6406 struct community *community = NULL;
6407 struct ecommunity *ecommunity = NULL;
6408 struct lcommunity *lcommunity = NULL;
6409
6410 /* ORIGIN attribute: If at least one route among routes that are
6411 * aggregated has ORIGIN with the value INCOMPLETE, then the
6412 * aggregated route must have the ORIGIN attribute with the value
6413 * INCOMPLETE. Otherwise, if at least one route among routes that
6414 * are aggregated has ORIGIN with the value EGP, then the aggregated
6415 * route must have the origin attribute with the value EGP. In all
6416 * other case the value of the ORIGIN attribute of the aggregated
6417 * route is INTERNAL.
6418 */
6419 origin = BGP_ORIGIN_IGP;
6420
6421 aggregate->count++;
6422
6423 if (aggregate->summary_only)
6424 (bgp_path_info_extra_get(pinew))->suppress++;
6425
6426 switch (pinew->attr->origin) {
6427 case BGP_ORIGIN_INCOMPLETE:
6428 aggregate->incomplete_origin_count++;
6429 break;
6430 case BGP_ORIGIN_EGP:
6431 aggregate->egp_origin_count++;
6432 break;
6433 default:
6434 /* Do nothing.
6435 */
6436 break;
6437 }
6438
6439 if (aggregate->incomplete_origin_count > 0)
6440 origin = BGP_ORIGIN_INCOMPLETE;
6441 else if (aggregate->egp_origin_count > 0)
6442 origin = BGP_ORIGIN_EGP;
6443
6444 if (aggregate->as_set) {
6445 /* Compute aggregate route's as-path.
6446 */
6447 bgp_compute_aggregate_aspath(aggregate,
6448 pinew->attr->aspath);
6449
6450 /* Compute aggregate route's community.
6451 */
6452 if (pinew->attr->community)
6453 bgp_compute_aggregate_community(
6454 aggregate,
6455 pinew->attr->community);
6456
6457 /* Compute aggregate route's extended community.
6458 */
6459 if (pinew->attr->ecommunity)
6460 bgp_compute_aggregate_ecommunity(
6461 aggregate,
6462 pinew->attr->ecommunity);
6463
6464 /* Compute aggregate route's large community.
6465 */
6466 if (pinew->attr->lcommunity)
6467 bgp_compute_aggregate_lcommunity(
6468 aggregate,
6469 pinew->attr->lcommunity);
6470
6471 /* Retrieve aggregate route's as-path.
6472 */
6473 if (aggregate->aspath)
6474 aspath = aspath_dup(aggregate->aspath);
6475
6476 /* Retrieve aggregate route's community.
6477 */
6478 if (aggregate->community)
6479 community = community_dup(aggregate->community);
6480
6481 /* Retrieve aggregate route's ecommunity.
6482 */
6483 if (aggregate->ecommunity)
6484 ecommunity = ecommunity_dup(aggregate->ecommunity);
6485
6486 /* Retrieve aggregate route's lcommunity.
6487 */
6488 if (aggregate->lcommunity)
6489 lcommunity = lcommunity_dup(aggregate->lcommunity);
6490 }
6491
6492 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6493 aspath, community, ecommunity,
6494 lcommunity, atomic_aggregate, aggregate);
6495}
6496
6497static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
6498 safi_t safi,
6499 struct bgp_path_info *pi,
6500 struct bgp_aggregate *aggregate,
6501 struct prefix *aggr_p)
6502{
6503 uint8_t origin;
6504 struct aspath *aspath = NULL;
6505 uint8_t atomic_aggregate = 0;
6506 struct community *community = NULL;
6507 struct ecommunity *ecommunity = NULL;
6508 struct lcommunity *lcommunity = NULL;
6509 unsigned long match = 0;
6510
6511 if (BGP_PATH_HOLDDOWN(pi))
6512 return;
6513
6514 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6515 return;
6516
6517 if (aggregate->summary_only
6518 && pi->extra
6519 && pi->extra->suppress > 0) {
6520 pi->extra->suppress--;
6521
6522 if (pi->extra->suppress == 0) {
6523 bgp_path_info_set_flag(pi->net, pi,
6524 BGP_PATH_ATTR_CHANGED);
6525 match++;
6526 }
6527 }
6528
6529 if (aggregate->count > 0)
6530 aggregate->count--;
6531
6532 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6533 aggregate->incomplete_origin_count--;
6534 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6535 aggregate->egp_origin_count--;
6536
6537 if (aggregate->as_set) {
6538 /* Remove as-path from aggregate.
6539 */
6540 bgp_remove_aspath_from_aggregate(aggregate,
6541 pi->attr->aspath);
6542
6543 if (pi->attr->community)
6544 /* Remove community from aggregate.
6545 */
6546 bgp_remove_community_from_aggregate(
6547 aggregate,
6548 pi->attr->community);
6549
6550 if (pi->attr->ecommunity)
6551 /* Remove ecommunity from aggregate.
6552 */
6553 bgp_remove_ecommunity_from_aggregate(
6554 aggregate,
6555 pi->attr->ecommunity);
6556
6557 if (pi->attr->lcommunity)
6558 /* Remove lcommunity from aggregate.
6559 */
6560 bgp_remove_lcommunity_from_aggregate(
6561 aggregate,
6562 pi->attr->lcommunity);
6563 }
6564
6565 /* If this node was suppressed, process the change. */
6566 if (match)
6567 bgp_process(bgp, pi->net, afi, safi);
6568
6569 origin = BGP_ORIGIN_IGP;
6570 if (aggregate->incomplete_origin_count > 0)
6571 origin = BGP_ORIGIN_INCOMPLETE;
6572 else if (aggregate->egp_origin_count > 0)
6573 origin = BGP_ORIGIN_EGP;
6574
6575 if (aggregate->as_set) {
6576 /* Retrieve aggregate route's as-path.
6577 */
6578 if (aggregate->aspath)
6579 aspath = aspath_dup(aggregate->aspath);
6580
6581 /* Retrieve aggregate route's community.
6582 */
6583 if (aggregate->community)
6584 community = community_dup(aggregate->community);
6585
6586 /* Retrieve aggregate route's ecommunity.
6587 */
6588 if (aggregate->ecommunity)
6589 ecommunity = ecommunity_dup(aggregate->ecommunity);
6590
6591 /* Retrieve aggregate route's lcommunity.
6592 */
6593 if (aggregate->lcommunity)
6594 lcommunity = lcommunity_dup(aggregate->lcommunity);
6595 }
6596
6597 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6598 aspath, community, ecommunity,
6599 lcommunity, atomic_aggregate, aggregate);
6600}
6601
d62a17ae 6602void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p,
40381db7 6603 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 6604{
d62a17ae 6605 struct bgp_node *child;
6606 struct bgp_node *rn;
6607 struct bgp_aggregate *aggregate;
6608 struct bgp_table *table;
718e3744 6609
d62a17ae 6610 table = bgp->aggregate[afi][safi];
f018db83 6611
d62a17ae 6612 /* No aggregates configured. */
6613 if (bgp_table_top_nolock(table) == NULL)
6614 return;
f018db83 6615
d62a17ae 6616 if (p->prefixlen == 0)
6617 return;
718e3744 6618
40381db7 6619 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 6620 return;
718e3744 6621
d62a17ae 6622 child = bgp_node_get(table, p);
718e3744 6623
d62a17ae 6624 /* Aggregate address configuration check. */
b1e62edd 6625 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
b613a918 6626 aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 6627 if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
fc968841
NT
6628 bgp_add_route_to_aggregate(bgp, &rn->p, pi, afi,
6629 safi, aggregate);
d62a17ae 6630 }
b1e62edd 6631 }
d62a17ae 6632 bgp_unlock_node(child);
718e3744 6633}
6634
d62a17ae 6635void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p,
4b7e6066 6636 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 6637{
d62a17ae 6638 struct bgp_node *child;
6639 struct bgp_node *rn;
6640 struct bgp_aggregate *aggregate;
6641 struct bgp_table *table;
718e3744 6642
d62a17ae 6643 table = bgp->aggregate[afi][safi];
718e3744 6644
d62a17ae 6645 /* No aggregates configured. */
6646 if (bgp_table_top_nolock(table) == NULL)
6647 return;
718e3744 6648
d62a17ae 6649 if (p->prefixlen == 0)
6650 return;
718e3744 6651
d62a17ae 6652 child = bgp_node_get(table, p);
718e3744 6653
d62a17ae 6654 /* Aggregate address configuration check. */
b1e62edd 6655 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
b613a918 6656 aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 6657 if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
fc968841
NT
6658 bgp_remove_route_from_aggregate(bgp, afi, safi,
6659 del, aggregate, &rn->p);
d62a17ae 6660 }
b1e62edd 6661 }
d62a17ae 6662 bgp_unlock_node(child);
6663}
718e3744 6664
718e3744 6665/* Aggregate route attribute. */
6666#define AGGREGATE_SUMMARY_ONLY 1
6667#define AGGREGATE_AS_SET 1
fb29348a 6668#define AGGREGATE_AS_UNSET 0
718e3744 6669
d62a17ae 6670static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
6671 afi_t afi, safi_t safi)
718e3744 6672{
d62a17ae 6673 VTY_DECLVAR_CONTEXT(bgp, bgp);
6674 int ret;
6675 struct prefix p;
6676 struct bgp_node *rn;
6677 struct bgp_aggregate *aggregate;
718e3744 6678
d62a17ae 6679 /* Convert string to prefix structure. */
6680 ret = str2prefix(prefix_str, &p);
6681 if (!ret) {
6682 vty_out(vty, "Malformed prefix\n");
6683 return CMD_WARNING_CONFIG_FAILED;
6684 }
6685 apply_mask(&p);
6686
6687 /* Old configuration check. */
6688 rn = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
6689 if (!rn) {
6690 vty_out(vty,
6691 "%% There is no aggregate-address configuration.\n");
6692 return CMD_WARNING_CONFIG_FAILED;
6693 }
f6269b4f 6694
b613a918 6695 aggregate = bgp_node_get_bgp_aggregate_info(rn);
09990cdd 6696 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
dd18c5a9
DS
6697 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
6698 NULL, NULL, 0, aggregate);
d62a17ae 6699
6700 /* Unlock aggregate address configuration. */
b613a918 6701 bgp_node_set_bgp_aggregate_info(rn, NULL);
fc968841
NT
6702
6703 if (aggregate->community)
6704 community_free(&aggregate->community);
6705
6706 if (aggregate->community_hash) {
6707 /* Delete all communities in the hash.
6708 */
6709 hash_clean(aggregate->community_hash,
6710 bgp_aggr_community_remove);
6711 /* Free up the community_hash.
6712 */
6713 hash_free(aggregate->community_hash);
6714 }
6715
6716 if (aggregate->ecommunity)
6717 ecommunity_free(&aggregate->ecommunity);
6718
6719 if (aggregate->ecommunity_hash) {
6720 /* Delete all ecommunities in the hash.
6721 */
6722 hash_clean(aggregate->ecommunity_hash,
6723 bgp_aggr_ecommunity_remove);
6724 /* Free up the ecommunity_hash.
6725 */
6726 hash_free(aggregate->ecommunity_hash);
6727 }
6728
6729 if (aggregate->lcommunity)
6730 lcommunity_free(&aggregate->lcommunity);
6731
6732 if (aggregate->lcommunity_hash) {
6733 /* Delete all lcommunities in the hash.
6734 */
6735 hash_clean(aggregate->lcommunity_hash,
6736 bgp_aggr_lcommunity_remove);
6737 /* Free up the lcommunity_hash.
6738 */
6739 hash_free(aggregate->lcommunity_hash);
6740 }
6741
6742 if (aggregate->aspath)
6743 aspath_free(aggregate->aspath);
6744
6745 if (aggregate->aspath_hash) {
6746 /* Delete all as-paths in the hash.
6747 */
6748 hash_clean(aggregate->aspath_hash,
6749 bgp_aggr_aspath_remove);
6750 /* Free up the aspath_hash.
6751 */
6752 hash_free(aggregate->aspath_hash);
6753 }
6754
d62a17ae 6755 bgp_aggregate_free(aggregate);
6756 bgp_unlock_node(rn);
6757 bgp_unlock_node(rn);
6758
6759 return CMD_SUCCESS;
6760}
6761
6762static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
20894f50
DA
6763 safi_t safi, const char *rmap, uint8_t summary_only,
6764 uint8_t as_set)
d62a17ae 6765{
6766 VTY_DECLVAR_CONTEXT(bgp, bgp);
6767 int ret;
6768 struct prefix p;
6769 struct bgp_node *rn;
6770 struct bgp_aggregate *aggregate;
fb29348a 6771 uint8_t as_set_new = as_set;
d62a17ae 6772
6773 /* Convert string to prefix structure. */
6774 ret = str2prefix(prefix_str, &p);
6775 if (!ret) {
6776 vty_out(vty, "Malformed prefix\n");
6777 return CMD_WARNING_CONFIG_FAILED;
6778 }
6779 apply_mask(&p);
6780
3624ac81
DS
6781 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
6782 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
6783 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6784 prefix_str);
6785 return CMD_WARNING_CONFIG_FAILED;
6786 }
6787
d62a17ae 6788 /* Old configuration check. */
6789 rn = bgp_node_get(bgp->aggregate[afi][safi], &p);
20894f50 6790 aggregate = bgp_node_get_bgp_aggregate_info(rn);
d62a17ae 6791
20894f50 6792 if (aggregate) {
d62a17ae 6793 vty_out(vty, "There is already same aggregate network.\n");
6794 /* try to remove the old entry */
6795 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
6796 if (ret) {
6797 vty_out(vty, "Error deleting aggregate.\n");
6798 bgp_unlock_node(rn);
6799 return CMD_WARNING_CONFIG_FAILED;
6800 }
6801 }
718e3744 6802
d62a17ae 6803 /* Make aggregate address structure. */
6804 aggregate = bgp_aggregate_new();
6805 aggregate->summary_only = summary_only;
fb29348a
DA
6806
6807 /* Network operators MUST NOT locally generate any new
6808 * announcements containing AS_SET or AS_CONFED_SET. If they have
6809 * announced routes with AS_SET or AS_CONFED_SET in them, then they
6810 * SHOULD withdraw those routes and re-announce routes for the
6811 * aggregate or component prefixes (i.e., the more-specific routes
6812 * subsumed by the previously aggregated route) without AS_SET
6813 * or AS_CONFED_SET in the updates.
6814 */
6815 if (bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED) {
6816 if (as_set == AGGREGATE_AS_SET) {
6817 as_set_new = AGGREGATE_AS_UNSET;
6818 zlog_warn(
6819 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.\n",
6820 __func__);
6821 vty_out(vty,
6822 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
6823 }
6824 }
6825
6826 aggregate->as_set = as_set_new;
d62a17ae 6827 aggregate->safi = safi;
20894f50
DA
6828
6829 if (rmap) {
6830 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6831 route_map_counter_decrement(aggregate->rmap.map);
6832 aggregate->rmap.name =
6833 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6834 aggregate->rmap.map = route_map_lookup_by_name(rmap);
6835 route_map_counter_increment(aggregate->rmap.map);
6836 }
b613a918 6837 bgp_node_set_bgp_aggregate_info(rn, aggregate);
718e3744 6838
d62a17ae 6839 /* Aggregate address insert into BGP routing table. */
fc968841 6840 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 6841
d62a17ae 6842 return CMD_SUCCESS;
718e3744 6843}
6844
6845DEFUN (aggregate_address,
6846 aggregate_address_cmd,
20894f50 6847 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6848 "Configure BGP aggregate entries\n"
6849 "Aggregate prefix\n"
6850 "Generate AS set path information\n"
a636c635
DW
6851 "Filter more specific routes from updates\n"
6852 "Filter more specific routes from updates\n"
20894f50
DA
6853 "Generate AS set path information\n"
6854 "Apply route map to aggregate network\n"
6855 "Name of route map\n")
718e3744 6856{
d62a17ae 6857 int idx = 0;
6858 argv_find(argv, argc, "A.B.C.D/M", &idx);
6859 char *prefix = argv[idx]->arg;
20894f50 6860 char *rmap = NULL;
fb29348a
DA
6861 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
6862 : AGGREGATE_AS_UNSET;
d62a17ae 6863 idx = 0;
6864 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6865 ? AGGREGATE_SUMMARY_ONLY
6866 : 0;
e3e6107d 6867
20894f50
DA
6868 idx = 0;
6869 argv_find(argv, argc, "WORD", &idx);
6870 if (idx)
6871 rmap = argv[idx]->arg;
6872
d62a17ae 6873 return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty),
20894f50 6874 rmap, summary_only, as_set);
718e3744 6875}
6876
e3e6107d
QY
6877DEFUN (aggregate_address_mask,
6878 aggregate_address_mask_cmd,
20894f50 6879 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6880 "Configure BGP aggregate entries\n"
6881 "Aggregate address\n"
6882 "Aggregate mask\n"
6883 "Generate AS set path information\n"
a636c635
DW
6884 "Filter more specific routes from updates\n"
6885 "Filter more specific routes from updates\n"
20894f50
DA
6886 "Generate AS set path information\n"
6887 "Apply route map to aggregate network\n"
6888 "Name of route map\n")
718e3744 6889{
d62a17ae 6890 int idx = 0;
6891 argv_find(argv, argc, "A.B.C.D", &idx);
6892 char *prefix = argv[idx]->arg;
6893 char *mask = argv[idx + 1]->arg;
cf40d052 6894 bool rmap_found;
20894f50 6895 char *rmap = NULL;
fb29348a
DA
6896 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
6897 : AGGREGATE_AS_UNSET;
d62a17ae 6898 idx = 0;
6899 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6900 ? AGGREGATE_SUMMARY_ONLY
6901 : 0;
6902
cf40d052
DS
6903 rmap_found = argv_find(argv, argc, "WORD", &idx);
6904 if (rmap_found)
20894f50
DA
6905 rmap = argv[idx]->arg;
6906
d62a17ae 6907 char prefix_str[BUFSIZ];
6908 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
6909
6910 if (!ret) {
6911 vty_out(vty, "%% Inconsistent address and mask\n");
6912 return CMD_WARNING_CONFIG_FAILED;
6913 }
718e3744 6914
d62a17ae 6915 return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
20894f50 6916 rmap, summary_only, as_set);
718e3744 6917}
6918
718e3744 6919DEFUN (no_aggregate_address,
6920 no_aggregate_address_cmd,
b84da0db 6921 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6922 NO_STR
6923 "Configure BGP aggregate entries\n"
a636c635
DW
6924 "Aggregate prefix\n"
6925 "Generate AS set path information\n"
e3e6107d
QY
6926 "Filter more specific routes from updates\n"
6927 "Filter more specific routes from updates\n"
b84da0db
DA
6928 "Generate AS set path information\n"
6929 "Apply route map to aggregate network\n"
6930 "Name of route map\n")
718e3744 6931{
d62a17ae 6932 int idx = 0;
6933 argv_find(argv, argc, "A.B.C.D/M", &idx);
6934 char *prefix = argv[idx]->arg;
6935 return bgp_aggregate_unset(vty, prefix, AFI_IP, bgp_node_safi(vty));
718e3744 6936}
6937
718e3744 6938DEFUN (no_aggregate_address_mask,
6939 no_aggregate_address_mask_cmd,
b84da0db 6940 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6941 NO_STR
6942 "Configure BGP aggregate entries\n"
6943 "Aggregate address\n"
a636c635
DW
6944 "Aggregate mask\n"
6945 "Generate AS set path information\n"
e3e6107d
QY
6946 "Filter more specific routes from updates\n"
6947 "Filter more specific routes from updates\n"
b84da0db
DA
6948 "Generate AS set path information\n"
6949 "Apply route map to aggregate network\n"
6950 "Name of route map\n")
718e3744 6951{
d62a17ae 6952 int idx = 0;
6953 argv_find(argv, argc, "A.B.C.D", &idx);
6954 char *prefix = argv[idx]->arg;
6955 char *mask = argv[idx + 1]->arg;
718e3744 6956
d62a17ae 6957 char prefix_str[BUFSIZ];
6958 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
718e3744 6959
d62a17ae 6960 if (!ret) {
6961 vty_out(vty, "%% Inconsistent address and mask\n");
6962 return CMD_WARNING_CONFIG_FAILED;
6963 }
718e3744 6964
d62a17ae 6965 return bgp_aggregate_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
718e3744 6966}
6967
718e3744 6968DEFUN (ipv6_aggregate_address,
6969 ipv6_aggregate_address_cmd,
20894f50 6970 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6971 "Configure BGP aggregate entries\n"
6972 "Aggregate prefix\n"
5101fece 6973 "Generate AS set path information\n"
6974 "Filter more specific routes from updates\n"
6975 "Filter more specific routes from updates\n"
20894f50
DA
6976 "Generate AS set path information\n"
6977 "Apply route map to aggregate network\n"
6978 "Name of route map\n")
718e3744 6979{
d62a17ae 6980 int idx = 0;
6981 argv_find(argv, argc, "X:X::X:X/M", &idx);
6982 char *prefix = argv[idx]->arg;
20894f50 6983 char *rmap = NULL;
273fae13 6984 bool rmap_found;
fb29348a
DA
6985 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
6986 : AGGREGATE_AS_UNSET;
5101fece 6987
6988 idx = 0;
d62a17ae 6989 int sum_only = argv_find(argv, argc, "summary-only", &idx)
6990 ? AGGREGATE_SUMMARY_ONLY
6991 : 0;
20894f50 6992
273fae13
DA
6993 rmap_found = argv_find(argv, argc, "WORD", &idx);
6994 if (rmap_found)
20894f50
DA
6995 rmap = argv[idx]->arg;
6996
6997 return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, rmap,
6998 sum_only, as_set);
718e3744 6999}
7000
7001DEFUN (no_ipv6_aggregate_address,
7002 no_ipv6_aggregate_address_cmd,
b84da0db 7003 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 7004 NO_STR
7005 "Configure BGP aggregate entries\n"
16cedbb0 7006 "Aggregate prefix\n"
5101fece 7007 "Generate AS set path information\n"
7008 "Filter more specific routes from updates\n"
7009 "Filter more specific routes from updates\n"
b84da0db
DA
7010 "Generate AS set path information\n"
7011 "Apply route map to aggregate network\n"
7012 "Name of route map\n")
718e3744 7013{
d62a17ae 7014 int idx = 0;
7015 argv_find(argv, argc, "X:X::X:X/M", &idx);
7016 char *prefix = argv[idx]->arg;
7017 return bgp_aggregate_unset(vty, prefix, AFI_IP6, SAFI_UNICAST);
718e3744 7018}
7019
718e3744 7020/* Redistribute route treatment. */
d62a17ae 7021void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
7022 const union g_addr *nexthop, ifindex_t ifindex,
7023 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
7024 uint8_t type, unsigned short instance,
7025 route_tag_t tag)
d62a17ae 7026{
4b7e6066 7027 struct bgp_path_info *new;
40381db7
DS
7028 struct bgp_path_info *bpi;
7029 struct bgp_path_info rmap_path;
d62a17ae 7030 struct bgp_node *bn;
7031 struct attr attr;
7032 struct attr *new_attr;
7033 afi_t afi;
b68885f9 7034 route_map_result_t ret;
d62a17ae 7035 struct bgp_redist *red;
7036
7037 /* Make default attribute. */
7038 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
7039 /*
7040 * This must not be NULL to satisfy Coverity SA
7041 */
7042 assert(attr.aspath);
9de1f7ff 7043
a4d82a8a 7044 switch (nhtype) {
9de1f7ff
DS
7045 case NEXTHOP_TYPE_IFINDEX:
7046 break;
7047 case NEXTHOP_TYPE_IPV4:
7048 case NEXTHOP_TYPE_IPV4_IFINDEX:
7049 attr.nexthop = nexthop->ipv4;
7050 break;
7051 case NEXTHOP_TYPE_IPV6:
7052 case NEXTHOP_TYPE_IPV6_IFINDEX:
7053 attr.mp_nexthop_global = nexthop->ipv6;
7054 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
7055 break;
7056 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
7057 switch (p->family) {
7058 case AF_INET:
9de1f7ff 7059 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
7060 break;
7061 case AF_INET6:
9de1f7ff
DS
7062 memset(&attr.mp_nexthop_global, 0,
7063 sizeof(attr.mp_nexthop_global));
74489921 7064 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 7065 break;
74489921 7066 }
9de1f7ff 7067 break;
d62a17ae 7068 }
74489921 7069 attr.nh_ifindex = ifindex;
f04a80a5 7070
d62a17ae 7071 attr.med = metric;
7072 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
7073 attr.tag = tag;
718e3744 7074
d62a17ae 7075 afi = family2afi(p->family);
6aeb9e78 7076
d62a17ae 7077 red = bgp_redist_lookup(bgp, afi, type, instance);
7078 if (red) {
7079 struct attr attr_new;
718e3744 7080
d62a17ae 7081 /* Copy attribute for modification. */
6f4f49b2 7082 attr_new = attr;
718e3744 7083
d62a17ae 7084 if (red->redist_metric_flag)
7085 attr_new.med = red->redist_metric;
718e3744 7086
d62a17ae 7087 /* Apply route-map. */
7088 if (red->rmap.name) {
40381db7
DS
7089 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
7090 rmap_path.peer = bgp->peer_self;
7091 rmap_path.attr = &attr_new;
718e3744 7092
d62a17ae 7093 SET_FLAG(bgp->peer_self->rmap_type,
7094 PEER_RMAP_TYPE_REDISTRIBUTE);
7095
7096 ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
40381db7 7097 &rmap_path);
d62a17ae 7098
7099 bgp->peer_self->rmap_type = 0;
7100
7101 if (ret == RMAP_DENYMATCH) {
7102 /* Free uninterned attribute. */
7103 bgp_attr_flush(&attr_new);
7104
7105 /* Unintern original. */
7106 aspath_unintern(&attr.aspath);
7107 bgp_redistribute_delete(bgp, p, type, instance);
7108 return;
7109 }
7110 }
7111
7f323236
DW
7112 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
7113 bgp_attr_add_gshut_community(&attr_new);
7114
d62a17ae 7115 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7116 SAFI_UNICAST, p, NULL);
7117
7118 new_attr = bgp_attr_intern(&attr_new);
7119
6f94b685
DS
7120 for (bpi = bgp_node_get_bgp_path_info(bn); bpi;
7121 bpi = bpi->next)
40381db7
DS
7122 if (bpi->peer == bgp->peer_self
7123 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 7124 break;
7125
40381db7 7126 if (bpi) {
d62a17ae 7127 /* Ensure the (source route) type is updated. */
40381db7
DS
7128 bpi->type = type;
7129 if (attrhash_cmp(bpi->attr, new_attr)
7130 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 7131 bgp_attr_unintern(&new_attr);
7132 aspath_unintern(&attr.aspath);
7133 bgp_unlock_node(bn);
7134 return;
7135 } else {
7136 /* The attribute is changed. */
40381db7 7137 bgp_path_info_set_flag(bn, bpi,
18ee8310 7138 BGP_PATH_ATTR_CHANGED);
d62a17ae 7139
7140 /* Rewrite BGP route information. */
40381db7
DS
7141 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
7142 bgp_path_info_restore(bn, bpi);
d62a17ae 7143 else
40381db7
DS
7144 bgp_aggregate_decrement(
7145 bgp, p, bpi, afi, SAFI_UNICAST);
7146 bgp_attr_unintern(&bpi->attr);
7147 bpi->attr = new_attr;
7148 bpi->uptime = bgp_clock();
d62a17ae 7149
7150 /* Process change. */
40381db7 7151 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 7152 SAFI_UNICAST);
7153 bgp_process(bgp, bn, afi, SAFI_UNICAST);
7154 bgp_unlock_node(bn);
7155 aspath_unintern(&attr.aspath);
ddb5b488
PZ
7156
7157 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7158 || (bgp->inst_type
7159 == BGP_INSTANCE_TYPE_DEFAULT)) {
7160
7161 vpn_leak_from_vrf_update(
40381db7 7162 bgp_get_default(), bgp, bpi);
ddb5b488 7163 }
d62a17ae 7164 return;
7165 }
7166 }
7167
7168 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
7169 bgp->peer_self, new_attr, bn);
1defdda8 7170 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 7171
7172 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 7173 bgp_path_info_add(bn, new);
d62a17ae 7174 bgp_unlock_node(bn);
7175 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
7176
7177 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7178 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7179
7180 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
7181 }
d62a17ae 7182 }
7183
7184 /* Unintern original. */
7185 aspath_unintern(&attr.aspath);
718e3744 7186}
7187
d7c0a89a
QY
7188void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
7189 unsigned short instance)
718e3744 7190{
d62a17ae 7191 afi_t afi;
7192 struct bgp_node *rn;
40381db7 7193 struct bgp_path_info *pi;
d62a17ae 7194 struct bgp_redist *red;
718e3744 7195
d62a17ae 7196 afi = family2afi(p->family);
718e3744 7197
d62a17ae 7198 red = bgp_redist_lookup(bgp, afi, type, instance);
7199 if (red) {
7200 rn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7201 SAFI_UNICAST, p, NULL);
7202
6f94b685 7203 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7 7204 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 7205 break;
7206
40381db7 7207 if (pi) {
ddb5b488
PZ
7208 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7209 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7210
7211 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7212 bgp, pi);
ddb5b488 7213 }
40381db7
DS
7214 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
7215 bgp_path_info_delete(rn, pi);
d62a17ae 7216 bgp_process(bgp, rn, afi, SAFI_UNICAST);
7217 }
7218 bgp_unlock_node(rn);
7219 }
7220}
7221
7222/* Withdraw specified route type's route. */
7223void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 7224 unsigned short instance)
d62a17ae 7225{
7226 struct bgp_node *rn;
40381db7 7227 struct bgp_path_info *pi;
d62a17ae 7228 struct bgp_table *table;
7229
7230 table = bgp->rib[afi][SAFI_UNICAST];
7231
7232 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685 7233 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
7234 if (pi->peer == bgp->peer_self && pi->type == type
7235 && pi->instance == instance)
d62a17ae 7236 break;
7237
40381db7 7238 if (pi) {
ddb5b488
PZ
7239 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7240 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7241
7242 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7243 bgp, pi);
ddb5b488 7244 }
40381db7 7245 bgp_aggregate_decrement(bgp, &rn->p, pi, afi,
d62a17ae 7246 SAFI_UNICAST);
40381db7 7247 bgp_path_info_delete(rn, pi);
d62a17ae 7248 bgp_process(bgp, rn, afi, SAFI_UNICAST);
7249 }
718e3744 7250 }
718e3744 7251}
6b0655a2 7252
718e3744 7253/* Static function to display route. */
9c92b5f7
MK
7254static void route_vty_out_route(struct prefix *p, struct vty *vty,
7255 json_object *json)
718e3744 7256{
be054588 7257 int len = 0;
d62a17ae 7258 char buf[BUFSIZ];
50e05855 7259 char buf2[BUFSIZ];
718e3744 7260
d62a17ae 7261 if (p->family == AF_INET) {
c6462ff4 7262 if (!json) {
89e5e9f0
PM
7263 len = vty_out(
7264 vty, "%s/%d",
7265 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
7266 p->prefixlen);
c6462ff4
MK
7267 } else {
7268 json_object_string_add(json, "prefix",
7269 inet_ntop(p->family,
7270 &p->u.prefix, buf,
7271 BUFSIZ));
7272 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 7273 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 7274 json_object_string_add(json, "network", buf2);
c6462ff4 7275 }
d62a17ae 7276 } else if (p->family == AF_ETHERNET) {
b03b8898
DS
7277 prefix2str(p, buf, PREFIX_STRLEN);
7278 len = vty_out(vty, "%s", buf);
7279 } else if (p->family == AF_EVPN) {
57f7feb6 7280 if (!json)
60466a63
QY
7281 len = vty_out(
7282 vty, "%s",
7283 bgp_evpn_route2str((struct prefix_evpn *)p, buf,
7284 BUFSIZ));
57f7feb6 7285 else
60466a63 7286 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
7287 } else if (p->family == AF_FLOWSPEC) {
7288 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
7289 json ?
7290 NLRI_STRING_FORMAT_JSON_SIMPLE :
7291 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 7292 } else {
c6462ff4 7293 if (!json)
60466a63
QY
7294 len = vty_out(
7295 vty, "%s/%d",
7296 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
7297 p->prefixlen);
50e05855
AD
7298 else {
7299 json_object_string_add(json, "prefix",
7300 inet_ntop(p->family,
7301 &p->u.prefix, buf,
7302 BUFSIZ));
7303 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
7304 prefix2str(p, buf2, PREFIX_STRLEN);
7305 json_object_string_add(json, "network", buf2);
7306 }
9c92b5f7 7307 }
d62a17ae 7308
9c92b5f7
MK
7309 if (!json) {
7310 len = 17 - len;
7311 if (len < 1)
7312 vty_out(vty, "\n%*s", 20, " ");
7313 else
7314 vty_out(vty, "%*s", len, " ");
7315 }
718e3744 7316}
7317
d62a17ae 7318enum bgp_display_type {
7319 normal_list,
718e3744 7320};
7321
18ee8310 7322/* Print the short form route status for a bgp_path_info */
4b7e6066 7323static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 7324 struct bgp_path_info *path,
d62a17ae 7325 json_object *json_path)
718e3744 7326{
d62a17ae 7327 if (json_path) {
b05a1c8b 7328
d62a17ae 7329 /* Route status display. */
9b6d8fcf 7330 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7331 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 7332
9b6d8fcf 7333 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7334 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 7335
9b6d8fcf 7336 if (path->extra && path->extra->suppress)
d62a17ae 7337 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 7338
9b6d8fcf
DS
7339 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7340 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7341 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 7342
d62a17ae 7343 /* Selected */
9b6d8fcf 7344 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7345 json_object_boolean_true_add(json_path, "history");
b05a1c8b 7346
9b6d8fcf 7347 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7348 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 7349
9b6d8fcf 7350 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7351 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b 7352
9b6d8fcf 7353 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7354 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 7355
d62a17ae 7356 /* Internal route. */
9b6d8fcf
DS
7357 if ((path->peer->as)
7358 && (path->peer->as == path->peer->local_as))
d62a17ae 7359 json_object_string_add(json_path, "pathFrom",
7360 "internal");
7361 else
7362 json_object_string_add(json_path, "pathFrom",
7363 "external");
b05a1c8b 7364
d62a17ae 7365 return;
7366 }
b05a1c8b 7367
d62a17ae 7368 /* Route status display. */
9b6d8fcf 7369 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7370 vty_out(vty, "R");
9b6d8fcf 7371 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7372 vty_out(vty, "S");
9b6d8fcf 7373 else if (path->extra && path->extra->suppress)
d62a17ae 7374 vty_out(vty, "s");
9b6d8fcf
DS
7375 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7376 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7377 vty_out(vty, "*");
7378 else
7379 vty_out(vty, " ");
7380
7381 /* Selected */
9b6d8fcf 7382 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7383 vty_out(vty, "h");
9b6d8fcf 7384 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7385 vty_out(vty, "d");
9b6d8fcf 7386 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7387 vty_out(vty, ">");
9b6d8fcf 7388 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7389 vty_out(vty, "=");
7390 else
7391 vty_out(vty, " ");
718e3744 7392
d62a17ae 7393 /* Internal route. */
9b6d8fcf
DS
7394 if (path->peer && (path->peer->as)
7395 && (path->peer->as == path->peer->local_as))
d62a17ae 7396 vty_out(vty, "i");
7397 else
7398 vty_out(vty, " ");
b40d939b 7399}
7400
515c2602 7401static char *bgp_nexthop_hostname(struct peer *peer, struct attr *attr)
25b5da8d 7402{
515c2602
DA
7403 if (peer->hostname && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)
7404 && !(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))
25b5da8d
DA
7405 return peer->hostname;
7406 return NULL;
7407}
7408
b40d939b 7409/* called from terminal list command */
4b7e6066 7410void route_vty_out(struct vty *vty, struct prefix *p,
9b6d8fcf 7411 struct bgp_path_info *path, int display, safi_t safi,
4b7e6066 7412 json_object *json_paths)
d62a17ae 7413{
515c2602 7414 struct attr *attr = path->attr;
d62a17ae 7415 json_object *json_path = NULL;
7416 json_object *json_nexthops = NULL;
7417 json_object *json_nexthop_global = NULL;
7418 json_object *json_nexthop_ll = NULL;
6f214dd3 7419 json_object *json_ext_community = NULL;
9df8b37c 7420 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 7421 bool nexthop_self =
9b6d8fcf 7422 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 7423 bool nexthop_othervrf = false;
43089216 7424 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 7425 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
515c2602 7426 char *nexthop_hostname = bgp_nexthop_hostname(path->peer, attr);
d62a17ae 7427
7428 if (json_paths)
7429 json_path = json_object_new_object();
7430
7431 /* short status lead text */
9b6d8fcf 7432 route_vty_short_status_out(vty, path, json_path);
d62a17ae 7433
7434 if (!json_paths) {
7435 /* print prefix and mask */
7436 if (!display)
9c92b5f7 7437 route_vty_out_route(p, vty, json_path);
d62a17ae 7438 else
7439 vty_out(vty, "%*s", 17, " ");
9c92b5f7 7440 } else {
b682f6de 7441 route_vty_out_route(p, vty, json_path);
d62a17ae 7442 }
47fc97cc 7443
9df8b37c
PZ
7444 /*
7445 * If vrf id of nexthop is different from that of prefix,
7446 * set up printable string to append
7447 */
9b6d8fcf 7448 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
7449 const char *self = "";
7450
7451 if (nexthop_self)
7452 self = "<";
7453
7454 nexthop_othervrf = true;
9b6d8fcf 7455 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 7456
9b6d8fcf 7457 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
7458 snprintf(vrf_id_str, sizeof(vrf_id_str),
7459 "@%s%s", VRFID_NONE_STR, self);
7460 else
7461 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 7462 path->extra->bgp_orig->vrf_id, self);
9df8b37c 7463
9b6d8fcf
DS
7464 if (path->extra->bgp_orig->inst_type
7465 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 7466
9b6d8fcf 7467 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
7468 } else {
7469 const char *self = "";
7470
7471 if (nexthop_self)
7472 self = "<";
7473
7474 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
7475 }
7476
445c2480
DS
7477 /*
7478 * For ENCAP and EVPN routes, nexthop address family is not
7479 * neccessarily the same as the prefix address family.
7480 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7481 * EVPN routes are also exchanged with a MP nexthop. Currently,
7482 * this
7483 * is only IPv4, the value will be present in either
7484 * attr->nexthop or
7485 * attr->mp_nexthop_global_in
7486 */
7487 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
7488 char buf[BUFSIZ];
7489 char nexthop[128];
7490 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
7491
7492 switch (af) {
7493 case AF_INET:
7494 sprintf(nexthop, "%s",
a4d82a8a
PZ
7495 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
7496 BUFSIZ));
445c2480
DS
7497 break;
7498 case AF_INET6:
7499 sprintf(nexthop, "%s",
a4d82a8a
PZ
7500 inet_ntop(af, &attr->mp_nexthop_global, buf,
7501 BUFSIZ));
445c2480
DS
7502 break;
7503 default:
7504 sprintf(nexthop, "?");
7505 break;
d62a17ae 7506 }
d62a17ae 7507
445c2480
DS
7508 if (json_paths) {
7509 json_nexthop_global = json_object_new_object();
7510
515c2602
DA
7511 json_object_string_add(json_nexthop_global, "ip",
7512 nexthop);
7513
7514 if (nexthop_hostname)
7515 json_object_string_add(json_nexthop_global,
7516 "hostname",
7517 nexthop_hostname);
7518
7519 json_object_string_add(json_nexthop_global, "afi",
7520 (af == AF_INET) ? "ipv4"
7521 : "ipv6");
445c2480
DS
7522 json_object_boolean_true_add(json_nexthop_global,
7523 "used");
7524 } else
25b5da8d 7525 vty_out(vty, "%s%s",
515c2602 7526 nexthop_hostname ? nexthop_hostname : nexthop,
25b5da8d 7527 vrf_id_str);
445c2480
DS
7528 } else if (safi == SAFI_EVPN) {
7529 if (json_paths) {
7530 json_nexthop_global = json_object_new_object();
7531
515c2602
DA
7532 json_object_string_add(json_nexthop_global, "ip",
7533 inet_ntoa(attr->nexthop));
7534
7535 if (nexthop_hostname)
7536 json_object_string_add(json_nexthop_global,
7537 "hostname",
7538 nexthop_hostname);
7539
a4d82a8a
PZ
7540 json_object_string_add(json_nexthop_global, "afi",
7541 "ipv4");
445c2480
DS
7542 json_object_boolean_true_add(json_nexthop_global,
7543 "used");
7544 } else
25b5da8d 7545 vty_out(vty, "%-16s%s",
515c2602
DA
7546 nexthop_hostname ? nexthop_hostname
7547 : inet_ntoa(attr->nexthop),
9df8b37c 7548 vrf_id_str);
d33fc23b 7549 } else if (safi == SAFI_FLOWSPEC) {
026b914a
PG
7550 if (attr->nexthop.s_addr != 0) {
7551 if (json_paths) {
7552 json_nexthop_global = json_object_new_object();
515c2602 7553
026b914a
PG
7554 json_object_string_add(json_nexthop_global,
7555 "afi", "ipv4");
515c2602
DA
7556 json_object_string_add(
7557 json_nexthop_global, "ip",
7558 inet_ntoa(attr->nexthop));
7559
7560 if (nexthop_hostname)
7561 json_object_string_add(
7562 json_nexthop_global, "hostname",
7563 nexthop_hostname);
7564
50e05855
AD
7565 json_object_boolean_true_add(
7566 json_nexthop_global,
026b914a
PG
7567 "used");
7568 } else {
25b5da8d 7569 vty_out(vty, "%-16s",
515c2602
DA
7570 nexthop_hostname
7571 ? nexthop_hostname
25b5da8d 7572 : inet_ntoa(attr->nexthop));
026b914a
PG
7573 }
7574 }
d33fc23b 7575 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
7576 if (json_paths) {
7577 json_nexthop_global = json_object_new_object();
d62a17ae 7578
515c2602
DA
7579 json_object_string_add(json_nexthop_global, "ip",
7580 inet_ntoa(attr->nexthop));
7581
7582 if (nexthop_hostname)
7583 json_object_string_add(json_nexthop_global,
7584 "hostname",
7585 nexthop_hostname);
445c2480 7586
a4d82a8a
PZ
7587 json_object_string_add(json_nexthop_global, "afi",
7588 "ipv4");
445c2480
DS
7589 json_object_boolean_true_add(json_nexthop_global,
7590 "used");
7591 } else {
9df8b37c
PZ
7592 char buf[BUFSIZ];
7593
d87ff2dd 7594 snprintf(buf, sizeof(buf), "%s%s",
515c2602
DA
7595 nexthop_hostname ? nexthop_hostname
7596 : inet_ntoa(attr->nexthop),
25b5da8d 7597 vrf_id_str);
9df8b37c 7598 vty_out(vty, "%-16s", buf);
d62a17ae 7599 }
445c2480 7600 }
b05a1c8b 7601
445c2480 7602 /* IPv6 Next Hop */
a4d82a8a 7603 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
7604 int len;
7605 char buf[BUFSIZ];
d62a17ae 7606
445c2480
DS
7607 if (json_paths) {
7608 json_nexthop_global = json_object_new_object();
a4d82a8a 7609 json_object_string_add(
515c2602
DA
7610 json_nexthop_global, "ip",
7611 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
7612 buf, BUFSIZ));
7613
7614 if (nexthop_hostname)
7615 json_object_string_add(json_nexthop_global,
7616 "hostname",
7617 nexthop_hostname);
7618
a4d82a8a
PZ
7619 json_object_string_add(json_nexthop_global, "afi",
7620 "ipv6");
7621 json_object_string_add(json_nexthop_global, "scope",
7622 "global");
445c2480
DS
7623
7624 /* We display both LL & GL if both have been
7625 * received */
0606039c
DA
7626 if ((attr->mp_nexthop_len
7627 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 7628 || (path->peer->conf_if)) {
a4d82a8a 7629 json_nexthop_ll = json_object_new_object();
d62a17ae 7630 json_object_string_add(
515c2602
DA
7631 json_nexthop_ll, "ip",
7632 inet_ntop(AF_INET6,
7633 &attr->mp_nexthop_local, buf,
7634 BUFSIZ));
7635
7636 if (nexthop_hostname)
7637 json_object_string_add(
7638 json_nexthop_ll, "hostname",
7639 nexthop_hostname);
7640
a4d82a8a
PZ
7641 json_object_string_add(json_nexthop_ll, "afi",
7642 "ipv6");
7643 json_object_string_add(json_nexthop_ll, "scope",
445c2480 7644 "link-local");
d62a17ae 7645
a4d82a8a
PZ
7646 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
7647 &attr->mp_nexthop_local)
445c2480
DS
7648 != 0)
7649 && !attr->mp_nexthop_prefer_global)
d62a17ae 7650 json_object_boolean_true_add(
a4d82a8a 7651 json_nexthop_ll, "used");
445c2480
DS
7652 else
7653 json_object_boolean_true_add(
a4d82a8a 7654 json_nexthop_global, "used");
445c2480
DS
7655 } else
7656 json_object_boolean_true_add(
7657 json_nexthop_global, "used");
7658 } else {
7659 /* Display LL if LL/Global both in table unless
7660 * prefer-global is set */
0606039c
DA
7661 if (((attr->mp_nexthop_len
7662 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 7663 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
7664 || (path->peer->conf_if)) {
7665 if (path->peer->conf_if) {
a4d82a8a 7666 len = vty_out(vty, "%s",
9b6d8fcf 7667 path->peer->conf_if);
445c2480
DS
7668 len = 16 - len; /* len of IPv6
7669 addr + max
7670 len of def
7671 ifname */
7672
7673 if (len < 1)
a4d82a8a 7674 vty_out(vty, "\n%*s", 36, " ");
445c2480 7675 else
a4d82a8a 7676 vty_out(vty, "%*s", len, " ");
d62a17ae 7677 } else {
7678 len = vty_out(
9df8b37c 7679 vty, "%s%s",
515c2602
DA
7680 nexthop_hostname
7681 ? nexthop_hostname
25b5da8d
DA
7682 : inet_ntop(
7683 AF_INET6,
7684 &attr->mp_nexthop_local,
7685 buf, BUFSIZ),
9df8b37c 7686 vrf_id_str);
d62a17ae 7687 len = 16 - len;
7688
7689 if (len < 1)
a4d82a8a 7690 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 7691 else
a4d82a8a 7692 vty_out(vty, "%*s", len, " ");
d62a17ae 7693 }
445c2480 7694 } else {
a4d82a8a 7695 len = vty_out(
9df8b37c 7696 vty, "%s%s",
515c2602
DA
7697 nexthop_hostname
7698 ? nexthop_hostname
25b5da8d
DA
7699 : inet_ntop(
7700 AF_INET6,
7701 &attr->mp_nexthop_global,
7702 buf, BUFSIZ),
7703 vrf_id_str);
445c2480
DS
7704 len = 16 - len;
7705
7706 if (len < 1)
7707 vty_out(vty, "\n%*s", 36, " ");
7708 else
7709 vty_out(vty, "%*s", len, " ");
d62a17ae 7710 }
7711 }
445c2480 7712 }
718e3744 7713
445c2480
DS
7714 /* MED/Metric */
7715 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
50e05855
AD
7716 if (json_paths) {
7717
7718 /*
7719 * Adding "metric" field to match with corresponding
7720 * CLI. "med" will be deprecated in future.
7721 */
a4d82a8a 7722 json_object_int_add(json_path, "med", attr->med);
50e05855
AD
7723 json_object_int_add(json_path, "metric", attr->med);
7724 } else
445c2480
DS
7725 vty_out(vty, "%10u", attr->med);
7726 else if (!json_paths)
7727 vty_out(vty, " ");
d62a17ae 7728
445c2480
DS
7729 /* Local Pref */
7730 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855
AD
7731 if (json_paths) {
7732
7733 /*
7734 * Adding "locPrf" field to match with corresponding
7735 * CLI. "localPref" will be deprecated in future.
7736 */
445c2480
DS
7737 json_object_int_add(json_path, "localpref",
7738 attr->local_pref);
50e05855
AD
7739 json_object_int_add(json_path, "locPrf",
7740 attr->local_pref);
7741 } else
445c2480
DS
7742 vty_out(vty, "%7u", attr->local_pref);
7743 else if (!json_paths)
7744 vty_out(vty, " ");
d62a17ae 7745
445c2480
DS
7746 if (json_paths)
7747 json_object_int_add(json_path, "weight", attr->weight);
7748 else
7749 vty_out(vty, "%7u ", attr->weight);
47fc97cc 7750
445c2480
DS
7751 if (json_paths) {
7752 char buf[BUFSIZ];
a4d82a8a
PZ
7753 json_object_string_add(
7754 json_path, "peerId",
9b6d8fcf 7755 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 7756 }
b05a1c8b 7757
445c2480
DS
7758 /* Print aspath */
7759 if (attr->aspath) {
50e05855
AD
7760 if (json_paths) {
7761
7762 /*
7763 * Adding "path" field to match with corresponding
7764 * CLI. "aspath" will be deprecated in future.
7765 */
445c2480
DS
7766 json_object_string_add(json_path, "aspath",
7767 attr->aspath->str);
50e05855
AD
7768 json_object_string_add(json_path, "path",
7769 attr->aspath->str);
7770 } else
445c2480 7771 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 7772 }
f1aa5d8a 7773
445c2480
DS
7774 /* Print origin */
7775 if (json_paths)
a4d82a8a
PZ
7776 json_object_string_add(json_path, "origin",
7777 bgp_origin_long_str[attr->origin]);
445c2480
DS
7778 else
7779 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7780
9df8b37c 7781 if (json_paths) {
6f214dd3
CS
7782 if (safi == SAFI_EVPN &&
7783 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7784 json_ext_community = json_object_new_object();
7785 json_object_string_add(json_ext_community,
7786 "string",
7787 attr->ecommunity->str);
7788 json_object_object_add(json_path,
7789 "extendedCommunity",
7790 json_ext_community);
7791 }
7792
9df8b37c
PZ
7793 if (nexthop_self)
7794 json_object_boolean_true_add(json_path,
7795 "announceNexthopSelf");
7796 if (nexthop_othervrf) {
7797 json_object_string_add(json_path, "nhVrfName",
7798 nexthop_vrfname);
7799
7800 json_object_int_add(json_path, "nhVrfId",
7801 ((nexthop_vrfid == VRF_UNKNOWN)
7802 ? -1
7803 : (int)nexthop_vrfid));
7804 }
7805 }
7806
d62a17ae 7807 if (json_paths) {
7808 if (json_nexthop_global || json_nexthop_ll) {
7809 json_nexthops = json_object_new_array();
f1aa5d8a 7810
d62a17ae 7811 if (json_nexthop_global)
7812 json_object_array_add(json_nexthops,
7813 json_nexthop_global);
f1aa5d8a 7814
d62a17ae 7815 if (json_nexthop_ll)
7816 json_object_array_add(json_nexthops,
7817 json_nexthop_ll);
f1aa5d8a 7818
d62a17ae 7819 json_object_object_add(json_path, "nexthops",
7820 json_nexthops);
7821 }
7822
7823 json_object_array_add(json_paths, json_path);
7824 } else {
7825 vty_out(vty, "\n");
6f214dd3
CS
7826
7827 if (safi == SAFI_EVPN &&
7828 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7829 vty_out(vty, "%*s", 20, " ");
7830 vty_out(vty, "%s\n", attr->ecommunity->str);
7831 }
7832
65efcfce 7833#if ENABLE_BGP_VNC
d62a17ae 7834 /* prints an additional line, indented, with VNC info, if
7835 * present */
7836 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 7837 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 7838#endif
d62a17ae 7839 }
7840}
718e3744 7841
7842/* called from terminal list command */
d62a17ae 7843void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr,
9f049418 7844 safi_t safi, bool use_json, json_object *json_ar)
d62a17ae 7845{
7846 json_object *json_status = NULL;
7847 json_object *json_net = NULL;
7848 char buff[BUFSIZ];
dc387b0f 7849
d62a17ae 7850 /* Route status display. */
7851 if (use_json) {
7852 json_status = json_object_new_object();
7853 json_net = json_object_new_object();
7854 } else {
7855 vty_out(vty, "*");
7856 vty_out(vty, ">");
7857 vty_out(vty, " ");
7858 }
718e3744 7859
d62a17ae 7860 /* print prefix and mask */
50e05855 7861 if (use_json) {
dc387b0f
LK
7862 if (safi == SAFI_EVPN)
7863 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
7864 else if (p->family == AF_INET || p->family == AF_INET6) {
7865 json_object_string_add(
7866 json_net, "addrPrefix",
7867 inet_ntop(p->family, &p->u.prefix, buff,
7868 BUFSIZ));
7869 json_object_int_add(json_net, "prefixLen",
7870 p->prefixlen);
7871 prefix2str(p, buff, PREFIX_STRLEN);
7872 json_object_string_add(json_net, "network", buff);
7873 }
50e05855 7874 } else
9c92b5f7 7875 route_vty_out_route(p, vty, NULL);
d62a17ae 7876
7877 /* Print attribute */
7878 if (attr) {
7879 if (use_json) {
7880 if (p->family == AF_INET
7881 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 7882 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 7883 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 7884 json_object_string_add(
7885 json_net, "nextHop",
7886 inet_ntoa(
7887 attr->mp_nexthop_global_in));
7888 else
7889 json_object_string_add(
7890 json_net, "nextHop",
7891 inet_ntoa(attr->nexthop));
7892 } else if (p->family == AF_INET6
7893 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
7894 char buf[BUFSIZ];
7895
7896 json_object_string_add(
aa0a10fc 7897 json_net, "nextHopGlobal",
d62a17ae 7898 inet_ntop(AF_INET6,
7899 &attr->mp_nexthop_global, buf,
7900 BUFSIZ));
dc387b0f
LK
7901 } else if (p->family == AF_EVPN &&
7902 !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
7903 json_object_string_add(json_net,
7904 "nextHop", inet_ntoa(
7905 attr->mp_nexthop_global_in));
d62a17ae 7906
7907 if (attr->flag
7908 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
7909 json_object_int_add(json_net, "metric",
7910 attr->med);
7911
50e05855
AD
7912 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
7913
7914 /*
7915 * Adding "locPrf" field to match with
7916 * corresponding CLI. "localPref" will be
7917 * deprecated in future.
7918 */
d62a17ae 7919 json_object_int_add(json_net, "localPref",
7920 attr->local_pref);
50e05855
AD
7921 json_object_int_add(json_net, "locPrf",
7922 attr->local_pref);
7923 }
d62a17ae 7924
7925 json_object_int_add(json_net, "weight", attr->weight);
7926
7927 /* Print aspath */
50e05855
AD
7928 if (attr->aspath) {
7929
7930 /*
7931 * Adding "path" field to match with
7932 * corresponding CLI. "localPref" will be
7933 * deprecated in future.
7934 */
d62a17ae 7935 json_object_string_add(json_net, "asPath",
7936 attr->aspath->str);
50e05855
AD
7937 json_object_string_add(json_net, "path",
7938 attr->aspath->str);
7939 }
d62a17ae 7940
7941 /* Print origin */
7942 json_object_string_add(json_net, "bgpOriginCode",
7943 bgp_origin_str[attr->origin]);
7944 } else {
7945 if (p->family == AF_INET
7946 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7947 || safi == SAFI_EVPN
7948 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7949 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7950 || safi == SAFI_EVPN)
7951 vty_out(vty, "%-16s",
7952 inet_ntoa(
7953 attr->mp_nexthop_global_in));
7954 else
7955 vty_out(vty, "%-16s",
7956 inet_ntoa(attr->nexthop));
7957 } else if (p->family == AF_INET6
7958 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
7959 int len;
7960 char buf[BUFSIZ];
7961
7962 len = vty_out(
7963 vty, "%s",
7964 inet_ntop(AF_INET6,
7965 &attr->mp_nexthop_global, buf,
7966 BUFSIZ));
7967 len = 16 - len;
7968 if (len < 1)
7969 vty_out(vty, "\n%*s", 36, " ");
7970 else
7971 vty_out(vty, "%*s", len, " ");
7972 }
7973 if (attr->flag
7974 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
7975 vty_out(vty, "%10u", attr->med);
7976 else
7977 vty_out(vty, " ");
718e3744 7978
d62a17ae 7979 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
7980 vty_out(vty, "%7u", attr->local_pref);
7981 else
7982 vty_out(vty, " ");
7983
7984 vty_out(vty, "%7u ", attr->weight);
7985
7986 /* Print aspath */
7987 if (attr->aspath)
7988 aspath_print_vty(vty, "%s", attr->aspath, " ");
7989
7990 /* Print origin */
7991 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7992 }
7993 }
7994 if (use_json) {
7995 json_object_boolean_true_add(json_status, "*");
7996 json_object_boolean_true_add(json_status, ">");
7997 json_object_object_add(json_net, "appliedStatusSymbols",
7998 json_status);
1608ff77 7999
dc387b0f
LK
8000 prefix2str(p, buff, PREFIX_STRLEN);
8001 json_object_object_add(json_ar, buff, json_net);
d62a17ae 8002 } else
8003 vty_out(vty, "\n");
8004}
8005
8006void route_vty_out_tag(struct vty *vty, struct prefix *p,
9b6d8fcf 8007 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 8008 json_object *json)
8009{
8010 json_object *json_out = NULL;
8011 struct attr *attr;
8012 mpls_label_t label = MPLS_INVALID_LABEL;
8013
9b6d8fcf 8014 if (!path->extra)
d62a17ae 8015 return;
8016
8017 if (json)
8018 json_out = json_object_new_object();
8019
8020 /* short status lead text */
9b6d8fcf 8021 route_vty_short_status_out(vty, path, json_out);
d62a17ae 8022
8023 /* print prefix and mask */
8024 if (json == NULL) {
8025 if (!display)
9c92b5f7 8026 route_vty_out_route(p, vty, NULL);
d62a17ae 8027 else
8028 vty_out(vty, "%*s", 17, " ");
8029 }
8030
8031 /* Print attribute */
9b6d8fcf 8032 attr = path->attr;
05864da7
DS
8033 if (((p->family == AF_INET)
8034 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8035 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8036 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8037 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8038 || safi == SAFI_EVPN) {
8039 if (json)
8040 json_object_string_add(
8041 json_out, "mpNexthopGlobalIn",
8042 inet_ntoa(attr->mp_nexthop_global_in));
8043 else
8044 vty_out(vty, "%-16s",
8045 inet_ntoa(attr->mp_nexthop_global_in));
8046 } else {
8047 if (json)
8048 json_object_string_add(
8049 json_out, "nexthop",
8050 inet_ntoa(attr->nexthop));
8051 else
8052 vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
8053 }
8054 } else if (((p->family == AF_INET6)
8055 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8056 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8057 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8058 char buf_a[512];
8059
8060 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
8061 if (json)
8062 json_object_string_add(
8063 json_out, "mpNexthopGlobalIn",
8064 inet_ntop(AF_INET6,
8065 &attr->mp_nexthop_global,
8066 buf_a, sizeof(buf_a)));
8067 else
8068 vty_out(vty, "%s",
8069 inet_ntop(AF_INET6,
8070 &attr->mp_nexthop_global,
8071 buf_a, sizeof(buf_a)));
8072 } else if (attr->mp_nexthop_len
8073 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
8074 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
8075 &attr->mp_nexthop_global,
8076 &attr->mp_nexthop_local);
8077 if (json)
8078 json_object_string_add(json_out,
8079 "mpNexthopGlobalLocal",
8080 buf_a);
8081 else
8082 vty_out(vty, "%s", buf_a);
d62a17ae 8083 }
8084 }
8085
9b6d8fcf 8086 label = decode_label(&path->extra->label[0]);
d62a17ae 8087
8088 if (bgp_is_valid_label(&label)) {
8089 if (json) {
8090 json_object_int_add(json_out, "notag", label);
8091 json_object_array_add(json, json_out);
8092 } else {
8093 vty_out(vty, "notag/%d", label);
8094 vty_out(vty, "\n");
8095 }
8096 }
8097}
718e3744 8098
d62a17ae 8099void route_vty_out_overlay(struct vty *vty, struct prefix *p,
9b6d8fcf 8100 struct bgp_path_info *path, int display,
d62a17ae 8101 json_object *json_paths)
718e3744 8102{
d62a17ae 8103 struct attr *attr;
14f51eba 8104 char buf[BUFSIZ] = {0};
d62a17ae 8105 json_object *json_path = NULL;
14f51eba
LK
8106 json_object *json_nexthop = NULL;
8107 json_object *json_overlay = NULL;
856ca177 8108
9b6d8fcf 8109 if (!path->extra)
d62a17ae 8110 return;
718e3744 8111
14f51eba
LK
8112 if (json_paths) {
8113 json_path = json_object_new_object();
8114 json_overlay = json_object_new_object();
8115 json_nexthop = json_object_new_object();
8116 }
8117
d62a17ae 8118 /* short status lead text */
9b6d8fcf 8119 route_vty_short_status_out(vty, path, json_path);
856ca177 8120
d62a17ae 8121 /* print prefix and mask */
8122 if (!display)
14f51eba 8123 route_vty_out_route(p, vty, json_path);
d62a17ae 8124 else
8125 vty_out(vty, "%*s", 17, " ");
8126
8127 /* Print attribute */
9b6d8fcf 8128 attr = path->attr;
05864da7
DS
8129 char buf1[BUFSIZ];
8130 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 8131
05864da7
DS
8132 switch (af) {
8133 case AF_INET:
8134 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
8135 if (!json_path) {
8136 vty_out(vty, "%-16s", buf);
8137 } else {
8138 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 8139
05864da7 8140 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 8141
05864da7
DS
8142 json_object_object_add(json_path, "nexthop",
8143 json_nexthop);
8144 }
8145 break;
8146 case AF_INET6:
8147 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
8148 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
8149 if (!json_path) {
8150 vty_out(vty, "%s(%s)", buf, buf1);
8151 } else {
8152 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 8153
05864da7
DS
8154 json_object_string_add(json_nexthop, "ipv6LinkLocal",
8155 buf1);
14f51eba 8156
05864da7 8157 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 8158
05864da7
DS
8159 json_object_object_add(json_path, "nexthop",
8160 json_nexthop);
8161 }
8162 break;
8163 default:
8164 if (!json_path) {
8165 vty_out(vty, "?");
8166 } else {
8167 json_object_string_add(json_nexthop, "Error",
8168 "Unsupported address-family");
d62a17ae 8169 }
05864da7 8170 }
988258b4 8171
05864da7 8172 char *str = esi2str(&(attr->evpn_overlay.eth_s_id));
988258b4 8173
05864da7
DS
8174 if (!json_path)
8175 vty_out(vty, "%s", str);
8176 else
8177 json_object_string_add(json_overlay, "esi", str);
25b5da8d 8178
05864da7 8179 XFREE(MTYPE_TMP, str);
988258b4 8180
05864da7
DS
8181 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
8182 inet_ntop(AF_INET, &(attr->evpn_overlay.gw_ip.ipv4), buf,
8183 BUFSIZ);
8184 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
8185 inet_ntop(AF_INET6, &(attr->evpn_overlay.gw_ip.ipv6), buf,
8186 BUFSIZ);
8187 }
14f51eba 8188
05864da7
DS
8189 if (!json_path)
8190 vty_out(vty, "/%s", buf);
8191 else
8192 json_object_string_add(json_overlay, "gw", buf);
8193
8194 if (attr->ecommunity) {
8195 char *mac = NULL;
8196 struct ecommunity_val *routermac = ecommunity_lookup(
8197 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
8198 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
8199
8200 if (routermac)
8201 mac = ecom_mac2str((char *)routermac->val);
8202 if (mac) {
8203 if (!json_path) {
8204 vty_out(vty, "/%s", (char *)mac);
8205 } else {
8206 json_object_string_add(json_overlay, "rmac",
8207 mac);
988258b4 8208 }
05864da7 8209 XFREE(MTYPE_TMP, mac);
988258b4 8210 }
05864da7 8211 }
718e3744 8212
05864da7
DS
8213 if (!json_path) {
8214 vty_out(vty, "\n");
8215 } else {
8216 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 8217
05864da7 8218 json_object_array_add(json_paths, json_path);
14f51eba 8219 }
d62a17ae 8220}
718e3744 8221
d62a17ae 8222/* dampening route */
8223static void damp_route_vty_out(struct vty *vty, struct prefix *p,
a935f597 8224 struct bgp_path_info *path, int display, afi_t afi,
4b7e6066 8225 safi_t safi, bool use_json, json_object *json)
d62a17ae 8226{
8227 struct attr *attr;
8228 int len;
8229 char timebuf[BGP_UPTIME_LEN];
8230
8231 /* short status lead text */
9b6d8fcf 8232 route_vty_short_status_out(vty, path, json);
d62a17ae 8233
8234 /* print prefix and mask */
8235 if (!use_json) {
8236 if (!display)
9c92b5f7 8237 route_vty_out_route(p, vty, NULL);
d62a17ae 8238 else
8239 vty_out(vty, "%*s", 17, " ");
8240 }
8241
9b6d8fcf 8242 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 8243 len = 17 - len;
8244 if (len < 1) {
8245 if (!use_json)
8246 vty_out(vty, "\n%*s", 34, " ");
8247 } else {
8248 if (use_json)
8249 json_object_int_add(json, "peerHost", len);
8250 else
8251 vty_out(vty, "%*s", len, " ");
8252 }
8253
8254 if (use_json)
a935f597
DA
8255 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
8256 safi, use_json, json);
d62a17ae 8257 else
9b6d8fcf
DS
8258 vty_out(vty, "%s ",
8259 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8260 BGP_UPTIME_LEN, afi, safi,
8261 use_json, json));
d62a17ae 8262
8263 /* Print attribute */
9b6d8fcf 8264 attr = path->attr;
d62a17ae 8265
05864da7
DS
8266 /* Print aspath */
8267 if (attr->aspath) {
d62a17ae 8268 if (use_json)
05864da7
DS
8269 json_object_string_add(json, "asPath",
8270 attr->aspath->str);
d62a17ae 8271 else
05864da7 8272 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8273 }
05864da7
DS
8274
8275 /* Print origin */
8276 if (use_json)
8277 json_object_string_add(json, "origin",
8278 bgp_origin_str[attr->origin]);
8279 else
8280 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8281
d62a17ae 8282 if (!use_json)
8283 vty_out(vty, "\n");
8284}
718e3744 8285
d62a17ae 8286/* flap route */
8287static void flap_route_vty_out(struct vty *vty, struct prefix *p,
a935f597 8288 struct bgp_path_info *path, int display, afi_t afi,
4b7e6066 8289 safi_t safi, bool use_json, json_object *json)
784d3a42 8290{
d62a17ae 8291 struct attr *attr;
8292 struct bgp_damp_info *bdi;
8293 char timebuf[BGP_UPTIME_LEN];
8294 int len;
784d3a42 8295
9b6d8fcf 8296 if (!path->extra)
d62a17ae 8297 return;
784d3a42 8298
9b6d8fcf 8299 bdi = path->extra->damp_info;
784d3a42 8300
d62a17ae 8301 /* short status lead text */
9b6d8fcf 8302 route_vty_short_status_out(vty, path, json);
784d3a42 8303
d62a17ae 8304 /* print prefix and mask */
8305 if (!use_json) {
8306 if (!display)
9c92b5f7 8307 route_vty_out_route(p, vty, NULL);
d62a17ae 8308 else
8309 vty_out(vty, "%*s", 17, " ");
8310 }
784d3a42 8311
9b6d8fcf 8312 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 8313 len = 16 - len;
8314 if (len < 1) {
8315 if (!use_json)
8316 vty_out(vty, "\n%*s", 33, " ");
8317 } else {
8318 if (use_json)
8319 json_object_int_add(json, "peerHost", len);
8320 else
8321 vty_out(vty, "%*s", len, " ");
8322 }
784d3a42 8323
d62a17ae 8324 len = vty_out(vty, "%d", bdi->flap);
8325 len = 5 - len;
8326 if (len < 1) {
8327 if (!use_json)
8328 vty_out(vty, " ");
8329 } else {
8330 if (use_json)
8331 json_object_int_add(json, "bdiFlap", len);
8332 else
8333 vty_out(vty, "%*s", len, " ");
8334 }
8335
8336 if (use_json)
8337 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
8338 json);
8339 else
996c9314
LB
8340 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
8341 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 8342
9b6d8fcf
DS
8343 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
8344 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 8345 if (use_json)
9b6d8fcf 8346 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8347 BGP_UPTIME_LEN, afi, safi,
8348 use_json, json);
d62a17ae 8349 else
8350 vty_out(vty, "%s ",
9b6d8fcf 8351 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8352 BGP_UPTIME_LEN, afi,
8353 safi, use_json, json));
d62a17ae 8354 } else {
8355 if (!use_json)
8356 vty_out(vty, "%*s ", 8, " ");
8357 }
8358
8359 /* Print attribute */
9b6d8fcf 8360 attr = path->attr;
d62a17ae 8361
05864da7
DS
8362 /* Print aspath */
8363 if (attr->aspath) {
d62a17ae 8364 if (use_json)
05864da7
DS
8365 json_object_string_add(json, "asPath",
8366 attr->aspath->str);
d62a17ae 8367 else
05864da7 8368 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8369 }
05864da7
DS
8370
8371 /* Print origin */
8372 if (use_json)
8373 json_object_string_add(json, "origin",
8374 bgp_origin_str[attr->origin]);
8375 else
8376 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8377
d62a17ae 8378 if (!use_json)
8379 vty_out(vty, "\n");
8380}
8381
8382static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
8383 int *first, const char *header,
8384 json_object *json_adv_to)
8385{
8386 char buf1[INET6_ADDRSTRLEN];
8387 json_object *json_peer = NULL;
8388
8389 if (json_adv_to) {
8390 /* 'advertised-to' is a dictionary of peers we have advertised
8391 * this
8392 * prefix too. The key is the peer's IP or swpX, the value is
8393 * the
8394 * hostname if we know it and "" if not.
8395 */
8396 json_peer = json_object_new_object();
8397
8398 if (peer->hostname)
8399 json_object_string_add(json_peer, "hostname",
8400 peer->hostname);
8401
8402 if (peer->conf_if)
8403 json_object_object_add(json_adv_to, peer->conf_if,
8404 json_peer);
8405 else
8406 json_object_object_add(
8407 json_adv_to,
8408 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
8409 json_peer);
8410 } else {
8411 if (*first) {
8412 vty_out(vty, "%s", header);
8413 *first = 0;
8414 }
8415
8416 if (peer->hostname
8417 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
8418 if (peer->conf_if)
8419 vty_out(vty, " %s(%s)", peer->hostname,
8420 peer->conf_if);
8421 else
8422 vty_out(vty, " %s(%s)", peer->hostname,
8423 sockunion2str(&peer->su, buf1,
8424 SU_ADDRSTRLEN));
8425 } else {
8426 if (peer->conf_if)
8427 vty_out(vty, " %s", peer->conf_if);
8428 else
8429 vty_out(vty, " %s",
8430 sockunion2str(&peer->su, buf1,
8431 SU_ADDRSTRLEN));
8432 }
8433 }
784d3a42
PG
8434}
8435
dcc68b5e
MS
8436static void route_vty_out_tx_ids(struct vty *vty,
8437 struct bgp_addpath_info_data *d)
8438{
8439 int i;
8440
8441 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
8442 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
8443 d->addpath_tx_id[i],
8444 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
8445 }
8446}
8447
0dc8ee70
DS
8448static const char *bgp_path_selection_reason2str(
8449 enum bgp_path_selection_reason reason)
8450{
8451 switch (reason) {
8452 case bgp_path_selection_none:
8453 return "Nothing to Select";
8454 break;
8455 case bgp_path_selection_first:
8456 return "First path received";
8457 break;
8458 case bgp_path_selection_evpn_sticky_mac:
8459 return "EVPN Sticky Mac";
8460 break;
8461 case bgp_path_selection_evpn_seq:
8462 return "EVPN sequence number";
8463 break;
8464 case bgp_path_selection_evpn_lower_ip:
8465 return "EVPN lower IP";
8466 break;
8467 case bgp_path_selection_weight:
8468 return "Weight";
8469 break;
8470 case bgp_path_selection_local_pref:
8471 return "Local Pref";
8472 break;
8473 case bgp_path_selection_local_route:
8474 return "Local Route";
8475 break;
8476 case bgp_path_selection_confed_as_path:
8477 return "Confederation based AS Path";
8478 break;
8479 case bgp_path_selection_as_path:
8480 return "AS Path";
8481 break;
8482 case bgp_path_selection_origin:
8483 return "Origin";
8484 break;
8485 case bgp_path_selection_med:
8486 return "MED";
8487 break;
8488 case bgp_path_selection_peer:
8489 return "Peer Type";
8490 break;
8491 case bgp_path_selection_confed:
8492 return "Confed Peer Type";
8493 break;
8494 case bgp_path_selection_igp_metric:
8495 return "IGP Metric";
8496 break;
8497 case bgp_path_selection_older:
8498 return "Older Path";
8499 break;
8500 case bgp_path_selection_router_id:
8501 return "Router ID";
8502 break;
8503 case bgp_path_selection_cluster_length:
8504 return "Cluser length";
8505 break;
8506 case bgp_path_selection_stale:
8507 return "Path Staleness";
8508 break;
8509 case bgp_path_selection_local_configured:
8510 return "Locally configured route";
8511 break;
8512 case bgp_path_selection_neighbor_ip:
8513 return "Neighbor IP";
8514 break;
8515 case bgp_path_selection_default:
8516 return "Nothing left to compare";
8517 break;
8518 }
a74879b2 8519 return "Invalid (internal error)";
0dc8ee70
DS
8520}
8521
f08b5ca0
DS
8522void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
8523 struct bgp_node *bn, struct bgp_path_info *path,
8524 afi_t afi, safi_t safi, json_object *json_paths)
d62a17ae 8525{
8526 char buf[INET6_ADDRSTRLEN];
8527 char buf1[BUFSIZ];
d62a17ae 8528 char buf2[EVPN_ROUTE_STRLEN];
515c2602 8529 struct attr *attr = path->attr;
d62a17ae 8530 int sockunion_vty_out(struct vty *, union sockunion *);
8531 time_t tbuf;
8532 json_object *json_bestpath = NULL;
8533 json_object *json_cluster_list = NULL;
8534 json_object *json_cluster_list_list = NULL;
8535 json_object *json_ext_community = NULL;
8536 json_object *json_last_update = NULL;
7fd077aa 8537 json_object *json_pmsi = NULL;
d62a17ae 8538 json_object *json_nexthop_global = NULL;
8539 json_object *json_nexthop_ll = NULL;
8540 json_object *json_nexthops = NULL;
8541 json_object *json_path = NULL;
8542 json_object *json_peer = NULL;
8543 json_object *json_string = NULL;
8544 json_object *json_adv_to = NULL;
8545 int first = 0;
8546 struct listnode *node, *nnode;
8547 struct peer *peer;
8548 int addpath_capable;
8549 int has_adj;
8550 unsigned int first_as;
1defdda8 8551 bool nexthop_self =
9b6d8fcf 8552 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 8553 int i;
515c2602 8554 char *nexthop_hostname = bgp_nexthop_hostname(path->peer, attr);
d62a17ae 8555
8556 if (json_paths) {
8557 json_path = json_object_new_object();
8558 json_peer = json_object_new_object();
8559 json_nexthop_global = json_object_new_object();
8560 }
8561
44c69747 8562 if (path->extra) {
b57ba6d2 8563 char tag_buf[30];
d62a17ae 8564
d7325ee7 8565 buf2[0] = '\0';
d62a17ae 8566 tag_buf[0] = '\0';
9b6d8fcf
DS
8567 if (path->extra && path->extra->num_labels) {
8568 bgp_evpn_label2str(path->extra->label,
8569 path->extra->num_labels, tag_buf,
a4d82a8a 8570 sizeof(tag_buf));
d62a17ae 8571 }
d7325ee7 8572 if (safi == SAFI_EVPN) {
44c69747
LK
8573 if (!json_paths) {
8574 bgp_evpn_route2str((struct prefix_evpn *)&bn->p,
8575 buf2, sizeof(buf2));
8576 vty_out(vty, " Route %s", buf2);
8577 if (tag_buf[0] != '\0')
8578 vty_out(vty, " VNI %s", tag_buf);
8579 vty_out(vty, "\n");
8580 } else {
8581 if (tag_buf[0])
8582 json_object_string_add(json_path, "VNI",
8583 tag_buf);
8584 }
d7325ee7
DD
8585 }
8586
44c69747 8587 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 8588 struct bgp_path_info *parent_ri;
d62a17ae 8589 struct bgp_node *rn, *prn;
8590
9b6d8fcf 8591 parent_ri = (struct bgp_path_info *)path->extra->parent;
d62a17ae 8592 rn = parent_ri->net;
8593 if (rn && rn->prn) {
8594 prn = rn->prn;
d7325ee7
DD
8595 prefix_rd2str((struct prefix_rd *)&prn->p,
8596 buf1, sizeof(buf1));
8597 if (is_pi_family_evpn(parent_ri)) {
8598 bgp_evpn_route2str((struct prefix_evpn *)&rn->p,
8599 buf2, sizeof(buf2));
8600 vty_out(vty, " Imported from %s:%s, VNI %s\n", buf1, buf2, tag_buf);
8601 } else
8602 vty_out(vty, " Imported from %s:%s\n", buf1, buf2);
d62a17ae 8603 }
8604 }
8605 }
d62a17ae 8606
05864da7
DS
8607 /* Line1 display AS-path, Aggregator */
8608 if (attr->aspath) {
8609 if (json_paths) {
8610 if (!attr->aspath->json)
8611 aspath_str_update(attr->aspath, true);
8612 json_object_lock(attr->aspath->json);
8613 json_object_object_add(json_path, "aspath",
8614 attr->aspath->json);
8615 } else {
8616 if (attr->aspath->segments)
8617 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 8618 else
05864da7 8619 vty_out(vty, " Local");
d62a17ae 8620 }
05864da7 8621 }
d62a17ae 8622
05864da7
DS
8623 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
8624 if (json_paths)
8625 json_object_boolean_true_add(json_path, "removed");
8626 else
8627 vty_out(vty, ", (removed)");
8628 }
d62a17ae 8629
05864da7
DS
8630 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
8631 if (json_paths)
8632 json_object_boolean_true_add(json_path, "stale");
8633 else
8634 vty_out(vty, ", (stale)");
8635 }
d62a17ae 8636
05864da7
DS
8637 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
8638 if (json_paths) {
8639 json_object_int_add(json_path, "aggregatorAs",
8640 attr->aggregator_as);
8641 json_object_string_add(
8642 json_path, "aggregatorId",
8643 inet_ntoa(attr->aggregator_addr));
8644 } else {
8645 vty_out(vty, ", (aggregated by %u %s)",
8646 attr->aggregator_as,
8647 inet_ntoa(attr->aggregator_addr));
d62a17ae 8648 }
05864da7 8649 }
d62a17ae 8650
05864da7
DS
8651 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
8652 PEER_FLAG_REFLECTOR_CLIENT)) {
8653 if (json_paths)
8654 json_object_boolean_true_add(json_path,
8655 "rxedFromRrClient");
8656 else
8657 vty_out(vty, ", (Received from a RR-client)");
8658 }
d62a17ae 8659
05864da7
DS
8660 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
8661 PEER_FLAG_RSERVER_CLIENT)) {
8662 if (json_paths)
8663 json_object_boolean_true_add(json_path,
8664 "rxedFromRsClient");
8665 else
8666 vty_out(vty, ", (Received from a RS-client)");
8667 }
d62a17ae 8668
05864da7
DS
8669 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
8670 if (json_paths)
8671 json_object_boolean_true_add(json_path,
8672 "dampeningHistoryEntry");
8673 else
8674 vty_out(vty, ", (history entry)");
8675 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
8676 if (json_paths)
8677 json_object_boolean_true_add(json_path,
8678 "dampeningSuppressed");
8679 else
8680 vty_out(vty, ", (suppressed due to dampening)");
8681 }
d62a17ae 8682
05864da7
DS
8683 if (!json_paths)
8684 vty_out(vty, "\n");
d62a17ae 8685
05864da7
DS
8686 /* Line2 display Next-hop, Neighbor, Router-id */
8687 /* Display the nexthop */
8688 if ((bn->p.family == AF_INET || bn->p.family == AF_ETHERNET
8689 || bn->p.family == AF_EVPN)
8690 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
8691 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8692 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8693 || safi == SAFI_EVPN) {
515c2602 8694 if (json_paths) {
d62a17ae 8695 json_object_string_add(
515c2602
DA
8696 json_nexthop_global, "ip",
8697 inet_ntoa(attr->mp_nexthop_global_in));
8698
8699 if (nexthop_hostname)
8700 json_object_string_add(
8701 json_nexthop_global, "hostname",
8702 nexthop_hostname);
8703 } else
d62a17ae 8704 vty_out(vty, " %s",
515c2602
DA
8705 nexthop_hostname
8706 ? nexthop_hostname
05864da7 8707 : inet_ntoa(
515c2602 8708 attr->mp_nexthop_global_in));
d62a17ae 8709 } else {
515c2602 8710 if (json_paths) {
05864da7 8711 json_object_string_add(
515c2602
DA
8712 json_nexthop_global, "ip",
8713 inet_ntoa(attr->nexthop));
8714
8715 if (nexthop_hostname)
8716 json_object_string_add(
8717 json_nexthop_global, "hostname",
8718 nexthop_hostname);
8719 } else
05864da7 8720 vty_out(vty, " %s",
515c2602
DA
8721 nexthop_hostname
8722 ? nexthop_hostname
05864da7 8723 : inet_ntoa(attr->nexthop));
d62a17ae 8724 }
8725
05864da7
DS
8726 if (json_paths)
8727 json_object_string_add(json_nexthop_global, "afi",
8728 "ipv4");
8729 } else {
8730 if (json_paths) {
8731 json_object_string_add(
515c2602
DA
8732 json_nexthop_global, "ip",
8733 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8734 buf, INET6_ADDRSTRLEN));
8735
8736 if (nexthop_hostname)
8737 json_object_string_add(json_nexthop_global,
8738 "hostname",
8739 nexthop_hostname);
8740
05864da7
DS
8741 json_object_string_add(json_nexthop_global, "afi",
8742 "ipv6");
8743 json_object_string_add(json_nexthop_global, "scope",
8744 "global");
8745 } else {
8746 vty_out(vty, " %s",
515c2602
DA
8747 nexthop_hostname
8748 ? nexthop_hostname
05864da7
DS
8749 : inet_ntop(AF_INET6,
8750 &attr->mp_nexthop_global,
8751 buf, INET6_ADDRSTRLEN));
d62a17ae 8752 }
05864da7 8753 }
d62a17ae 8754
05864da7
DS
8755 /* Display the IGP cost or 'inaccessible' */
8756 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
8757 if (json_paths)
8758 json_object_boolean_false_add(json_nexthop_global,
8759 "accessible");
8760 else
8761 vty_out(vty, " (inaccessible)");
8762 } else {
8763 if (path->extra && path->extra->igpmetric) {
d62a17ae 8764 if (json_paths)
05864da7
DS
8765 json_object_int_add(json_nexthop_global,
8766 "metric",
8767 path->extra->igpmetric);
d62a17ae 8768 else
05864da7
DS
8769 vty_out(vty, " (metric %u)",
8770 path->extra->igpmetric);
d62a17ae 8771 }
8772
05864da7 8773 /* IGP cost is 0, display this only for json */
d62a17ae 8774 else {
d62a17ae 8775 if (json_paths)
05864da7
DS
8776 json_object_int_add(json_nexthop_global,
8777 "metric", 0);
d62a17ae 8778 }
d62a17ae 8779
05864da7
DS
8780 if (json_paths)
8781 json_object_boolean_true_add(json_nexthop_global,
8782 "accessible");
8783 }
d62a17ae 8784
05864da7
DS
8785 /* Display peer "from" output */
8786 /* This path was originated locally */
8787 if (path->peer == bgp->peer_self) {
d62a17ae 8788
05864da7
DS
8789 if (safi == SAFI_EVPN
8790 || (bn->p.family == AF_INET
8791 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 8792 if (json_paths)
05864da7
DS
8793 json_object_string_add(json_peer, "peerId",
8794 "0.0.0.0");
d62a17ae 8795 else
05864da7
DS
8796 vty_out(vty, " from 0.0.0.0 ");
8797 } else {
d62a17ae 8798 if (json_paths)
05864da7
DS
8799 json_object_string_add(json_peer, "peerId",
8800 "::");
d62a17ae 8801 else
05864da7 8802 vty_out(vty, " from :: ");
d62a17ae 8803 }
d62a17ae 8804
05864da7
DS
8805 if (json_paths)
8806 json_object_string_add(json_peer, "routerId",
8807 inet_ntoa(bgp->router_id));
8808 else
8809 vty_out(vty, "(%s)", inet_ntoa(bgp->router_id));
8810 }
d62a17ae 8811
05864da7
DS
8812 /* We RXed this path from one of our peers */
8813 else {
8814
8815 if (json_paths) {
8816 json_object_string_add(json_peer, "peerId",
8817 sockunion2str(&path->peer->su,
8818 buf,
8819 SU_ADDRSTRLEN));
8820 json_object_string_add(json_peer, "routerId",
8821 inet_ntop(AF_INET,
8822 &path->peer->remote_id,
8823 buf1, sizeof(buf1)));
8824
8825 if (path->peer->hostname)
8826 json_object_string_add(json_peer, "hostname",
8827 path->peer->hostname);
8828
8829 if (path->peer->domainname)
8830 json_object_string_add(json_peer, "domainname",
8831 path->peer->domainname);
8832
8833 if (path->peer->conf_if)
8834 json_object_string_add(json_peer, "interface",
8835 path->peer->conf_if);
8836 } else {
8837 if (path->peer->conf_if) {
8838 if (path->peer->hostname
8839 && bgp_flag_check(path->peer->bgp,
8840 BGP_FLAG_SHOW_HOSTNAME))
8841 vty_out(vty, " from %s(%s)",
8842 path->peer->hostname,
8843 path->peer->conf_if);
d62a17ae 8844 else
05864da7 8845 vty_out(vty, " from %s",
9b6d8fcf 8846 path->peer->conf_if);
d62a17ae 8847 } else {
05864da7
DS
8848 if (path->peer->hostname
8849 && bgp_flag_check(path->peer->bgp,
8850 BGP_FLAG_SHOW_HOSTNAME))
8851 vty_out(vty, " from %s(%s)",
8852 path->peer->hostname,
8853 path->peer->host);
d62a17ae 8854 else
05864da7
DS
8855 vty_out(vty, " from %s",
8856 sockunion2str(&path->peer->su,
8857 buf,
8858 SU_ADDRSTRLEN));
d62a17ae 8859 }
d62a17ae 8860
05864da7
DS
8861 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
8862 vty_out(vty, " (%s)",
8863 inet_ntoa(attr->originator_id));
8864 else
8865 vty_out(vty, " (%s)",
8866 inet_ntop(AF_INET,
8867 &path->peer->remote_id, buf1,
8868 sizeof(buf1)));
d62a17ae 8869 }
05864da7 8870 }
9df8b37c 8871
05864da7
DS
8872 /*
8873 * Note when vrfid of nexthop is different from that of prefix
8874 */
8875 if (path->extra && path->extra->bgp_orig) {
8876 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8877
05864da7
DS
8878 if (json_paths) {
8879 const char *vn;
9df8b37c 8880
05864da7
DS
8881 if (path->extra->bgp_orig->inst_type
8882 == BGP_INSTANCE_TYPE_DEFAULT)
8883 vn = VRF_DEFAULT_NAME;
8884 else
8885 vn = path->extra->bgp_orig->name;
9df8b37c 8886
05864da7 8887 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 8888
05864da7
DS
8889 if (nexthop_vrfid == VRF_UNKNOWN) {
8890 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 8891 } else {
05864da7
DS
8892 json_object_int_add(json_path, "nhVrfId",
8893 (int)nexthop_vrfid);
9df8b37c 8894 }
05864da7
DS
8895 } else {
8896 if (nexthop_vrfid == VRF_UNKNOWN)
8897 vty_out(vty, " vrf ?");
d62a17ae 8898 else
05864da7 8899 vty_out(vty, " vrf %u", nexthop_vrfid);
9df8b37c 8900 }
05864da7 8901 }
9df8b37c 8902
05864da7
DS
8903 if (nexthop_self) {
8904 if (json_paths) {
8905 json_object_boolean_true_add(json_path,
8906 "announceNexthopSelf");
8907 } else {
8908 vty_out(vty, " announce-nh-self");
9df8b37c 8909 }
05864da7 8910 }
9df8b37c 8911
05864da7
DS
8912 if (!json_paths)
8913 vty_out(vty, "\n");
d62a17ae 8914
05864da7
DS
8915 /* display the link-local nexthop */
8916 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
8917 if (json_paths) {
8918 json_nexthop_ll = json_object_new_object();
8919 json_object_string_add(
515c2602
DA
8920 json_nexthop_ll, "ip",
8921 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
8922 buf, INET6_ADDRSTRLEN));
8923
8924 if (nexthop_hostname)
8925 json_object_string_add(json_nexthop_ll,
8926 "hostname",
8927 nexthop_hostname);
8928
05864da7
DS
8929 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
8930 json_object_string_add(json_nexthop_ll, "scope",
8931 "link-local");
d62a17ae 8932
05864da7
DS
8933 json_object_boolean_true_add(json_nexthop_ll,
8934 "accessible");
d62a17ae 8935
05864da7 8936 if (!attr->mp_nexthop_prefer_global)
d62a17ae 8937 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
8938 "used");
8939 else
8940 json_object_boolean_true_add(
8941 json_nexthop_global, "used");
8942 } else {
8943 vty_out(vty, " (%s) %s\n",
8944 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
8945 buf, INET6_ADDRSTRLEN),
8946 attr->mp_nexthop_prefer_global
8947 ? "(prefer-global)"
8948 : "(used)");
d62a17ae 8949 }
05864da7
DS
8950 }
8951 /* If we do not have a link-local nexthop then we must flag the
8952 global as "used" */
8953 else {
8954 if (json_paths)
8955 json_object_boolean_true_add(json_nexthop_global,
8956 "used");
8957 }
d62a17ae 8958
05864da7
DS
8959 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8960 * Int/Ext/Local, Atomic, best */
8961 if (json_paths)
8962 json_object_string_add(json_path, "origin",
8963 bgp_origin_long_str[attr->origin]);
8964 else
8965 vty_out(vty, " Origin %s",
8966 bgp_origin_long_str[attr->origin]);
9df8b37c 8967
05864da7
DS
8968 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
8969 if (json_paths) {
8970 /*
8971 * Adding "metric" field to match with
8972 * corresponding CLI. "med" will be
8973 * deprecated in future.
8974 */
8975 json_object_int_add(json_path, "med", attr->med);
8976 json_object_int_add(json_path, "metric", attr->med);
8977 } else
8978 vty_out(vty, ", metric %u", attr->med);
8979 }
9df8b37c 8980
05864da7
DS
8981 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
8982 if (json_paths)
8983 json_object_int_add(json_path, "localpref",
8984 attr->local_pref);
8985 else
8986 vty_out(vty, ", localpref %u", attr->local_pref);
8987 }
9df8b37c 8988
05864da7
DS
8989 if (attr->weight != 0) {
8990 if (json_paths)
8991 json_object_int_add(json_path, "weight", attr->weight);
8992 else
8993 vty_out(vty, ", weight %u", attr->weight);
8994 }
9df8b37c 8995
05864da7
DS
8996 if (attr->tag != 0) {
8997 if (json_paths)
8998 json_object_int_add(json_path, "tag", attr->tag);
8999 else
9000 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
9001 }
9df8b37c 9002
05864da7
DS
9003 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9004 if (json_paths)
9005 json_object_boolean_false_add(json_path, "valid");
9006 else
9007 vty_out(vty, ", invalid");
9008 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9009 if (json_paths)
9010 json_object_boolean_true_add(json_path, "valid");
9011 else
9012 vty_out(vty, ", valid");
9013 }
9df8b37c 9014
05864da7
DS
9015 if (path->peer != bgp->peer_self) {
9016 if (path->peer->as == path->peer->local_as) {
9017 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
9018 if (json_paths)
9019 json_object_string_add(
9020 json_peer, "type",
9021 "confed-internal");
d62a17ae 9022 else
05864da7 9023 vty_out(vty, ", confed-internal");
d62a17ae 9024 } else {
05864da7
DS
9025 if (json_paths)
9026 json_object_string_add(
9027 json_peer, "type", "internal");
9028 else
9029 vty_out(vty, ", internal");
9df8b37c 9030 }
05864da7
DS
9031 } else {
9032 if (bgp_confederation_peers_check(bgp,
9033 path->peer->as)) {
9034 if (json_paths)
9035 json_object_string_add(
9036 json_peer, "type",
9037 "confed-external");
d62a17ae 9038 else
05864da7 9039 vty_out(vty, ", confed-external");
d62a17ae 9040 } else {
05864da7
DS
9041 if (json_paths)
9042 json_object_string_add(
9043 json_peer, "type", "external");
9044 else
9045 vty_out(vty, ", external");
d62a17ae 9046 }
9047 }
05864da7
DS
9048 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
9049 if (json_paths) {
9050 json_object_boolean_true_add(json_path, "aggregated");
9051 json_object_boolean_true_add(json_path, "local");
9052 } else {
9053 vty_out(vty, ", aggregated, local");
9054 }
9055 } else if (path->type != ZEBRA_ROUTE_BGP) {
9056 if (json_paths)
9057 json_object_boolean_true_add(json_path, "sourced");
9058 else
9059 vty_out(vty, ", sourced");
9060 } else {
9061 if (json_paths) {
9062 json_object_boolean_true_add(json_path, "sourced");
9063 json_object_boolean_true_add(json_path, "local");
9064 } else {
9065 vty_out(vty, ", sourced, local");
d62a17ae 9066 }
05864da7 9067 }
718e3744 9068
05864da7 9069 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 9070 if (json_paths)
05864da7
DS
9071 json_object_boolean_true_add(json_path,
9072 "atomicAggregate");
d62a17ae 9073 else
05864da7
DS
9074 vty_out(vty, ", atomic-aggregate");
9075 }
d62a17ae 9076
05864da7
DS
9077 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
9078 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
9079 && bgp_path_info_mpath_count(path))) {
9080 if (json_paths)
9081 json_object_boolean_true_add(json_path, "multipath");
9082 else
9083 vty_out(vty, ", multipath");
9084 }
50e05855 9085
05864da7
DS
9086 // Mark the bestpath(s)
9087 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
9088 first_as = aspath_get_first_as(attr->aspath);
718e3744 9089
05864da7
DS
9090 if (json_paths) {
9091 if (!json_bestpath)
9092 json_bestpath = json_object_new_object();
9093 json_object_int_add(json_bestpath, "bestpathFromAs",
9094 first_as);
9095 } else {
9096 if (first_as)
9097 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 9098 else
05864da7 9099 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 9100 }
05864da7 9101 }
718e3744 9102
05864da7
DS
9103 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
9104 if (json_paths) {
9105 if (!json_bestpath)
9106 json_bestpath = json_object_new_object();
9107 json_object_boolean_true_add(json_bestpath, "overall");
9108 json_object_string_add(
9109 json_bestpath, "selectionReason",
9110 bgp_path_selection_reason2str(bn->reason));
9111 } else {
9112 vty_out(vty, ", best");
9113 vty_out(vty, " (%s)",
9114 bgp_path_selection_reason2str(bn->reason));
d62a17ae 9115 }
05864da7 9116 }
718e3744 9117
05864da7
DS
9118 if (json_bestpath)
9119 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 9120
05864da7
DS
9121 if (!json_paths)
9122 vty_out(vty, "\n");
9123
9124 /* Line 4 display Community */
9125 if (attr->community) {
9126 if (json_paths) {
9127 if (!attr->community->json)
9128 community_str(attr->community, true);
9129 json_object_lock(attr->community->json);
9130 json_object_object_add(json_path, "community",
9131 attr->community->json);
9132 } else {
9133 vty_out(vty, " Community: %s\n",
9134 attr->community->str);
d62a17ae 9135 }
05864da7 9136 }
718e3744 9137
05864da7
DS
9138 /* Line 5 display Extended-community */
9139 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9140 if (json_paths) {
9141 json_ext_community = json_object_new_object();
9142 json_object_string_add(json_ext_community, "string",
9143 attr->ecommunity->str);
9144 json_object_object_add(json_path, "extendedCommunity",
9145 json_ext_community);
d62a17ae 9146 } else {
05864da7
DS
9147 vty_out(vty, " Extended Community: %s\n",
9148 attr->ecommunity->str);
d62a17ae 9149 }
05864da7 9150 }
718e3744 9151
05864da7
DS
9152 /* Line 6 display Large community */
9153 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
9154 if (json_paths) {
9155 if (!attr->lcommunity->json)
9156 lcommunity_str(attr->lcommunity, true);
9157 json_object_lock(attr->lcommunity->json);
9158 json_object_object_add(json_path, "largeCommunity",
9159 attr->lcommunity->json);
9160 } else {
9161 vty_out(vty, " Large Community: %s\n",
9162 attr->lcommunity->str);
d62a17ae 9163 }
05864da7 9164 }
718e3744 9165
05864da7
DS
9166 /* Line 7 display Originator, Cluster-id */
9167 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
9168 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
9169 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 9170 if (json_paths)
05864da7
DS
9171 json_object_string_add(
9172 json_path, "originatorId",
9173 inet_ntoa(attr->originator_id));
d62a17ae 9174 else
05864da7
DS
9175 vty_out(vty, " Originator: %s",
9176 inet_ntoa(attr->originator_id));
d62a17ae 9177 }
856ca177 9178
05864da7
DS
9179 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
9180 int i;
d62a17ae 9181
9182 if (json_paths) {
05864da7
DS
9183 json_cluster_list = json_object_new_object();
9184 json_cluster_list_list =
9185 json_object_new_array();
9186
9187 for (i = 0; i < attr->cluster->length / 4;
9188 i++) {
9189 json_string = json_object_new_string(
9190 inet_ntoa(attr->cluster
9191 ->list[i]));
9192 json_object_array_add(
9193 json_cluster_list_list,
9194 json_string);
9195 }
718e3744 9196
05864da7
DS
9197 /*
9198 * struct cluster_list does not have
9199 * "str" variable like aspath and community
9200 * do. Add this someday if someone asks
9201 * for it.
9202 * json_object_string_add(json_cluster_list,
9203 * "string", attr->cluster->str);
9204 */
9205 json_object_object_add(json_cluster_list,
9206 "list",
9207 json_cluster_list_list);
9208 json_object_object_add(json_path, "clusterList",
9209 json_cluster_list);
0dc8ee70 9210 } else {
05864da7
DS
9211 vty_out(vty, ", Cluster list: ");
9212
9213 for (i = 0; i < attr->cluster->length / 4;
9214 i++) {
9215 vty_out(vty, "%s ",
9216 inet_ntoa(attr->cluster
9217 ->list[i]));
9218 }
0dc8ee70 9219 }
d62a17ae 9220 }
718e3744 9221
d62a17ae 9222 if (!json_paths)
9223 vty_out(vty, "\n");
05864da7 9224 }
d62a17ae 9225
05864da7 9226 if (path->extra && path->extra->damp_info)
a935f597 9227 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 9228
05864da7
DS
9229 /* Remote Label */
9230 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
9231 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
9232 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 9233
05864da7
DS
9234 if (json_paths)
9235 json_object_int_add(json_path, "remoteLabel", label);
9236 else
9237 vty_out(vty, " Remote label: %d\n", label);
9238 }
d62a17ae 9239
e496b420
HS
9240 /* Remote SID */
9241 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
9242 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
9243 if (json_paths)
9244 json_object_string_add(json_path, "remoteSid", buf);
9245 else
9246 vty_out(vty, " Remote SID: %s\n", buf);
9247 }
9248
05864da7
DS
9249 /* Label Index */
9250 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
9251 if (json_paths)
9252 json_object_int_add(json_path, "labelIndex",
9253 attr->label_index);
9254 else
9255 vty_out(vty, " Label Index: %d\n",
9256 attr->label_index);
9257 }
d62a17ae 9258
05864da7
DS
9259 /* Line 8 display Addpath IDs */
9260 if (path->addpath_rx_id
9261 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
9262 if (json_paths) {
9263 json_object_int_add(json_path, "addpathRxId",
9264 path->addpath_rx_id);
d62a17ae 9265
05864da7
DS
9266 /* Keep backwards compatibility with the old API
9267 * by putting TX All's ID in the old field
9268 */
9269 json_object_int_add(
9270 json_path, "addpathTxId",
9271 path->tx_addpath
9272 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 9273
05864da7
DS
9274 /* ... but create a specific field for each
9275 * strategy
9276 */
9277 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9278 json_object_int_add(
9279 json_path,
9280 bgp_addpath_names(i)->id_json_name,
9281 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 9282 }
05864da7
DS
9283 } else {
9284 vty_out(vty, " AddPath ID: RX %u, ",
9285 path->addpath_rx_id);
d62a17ae 9286
05864da7 9287 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 9288 }
05864da7 9289 }
520d5d76 9290
05864da7
DS
9291 /* If we used addpath to TX a non-bestpath we need to display
9292 * "Advertised to" on a path-by-path basis
9293 */
9294 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9295 first = 1;
dcc68b5e 9296
05864da7
DS
9297 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9298 addpath_capable =
9299 bgp_addpath_encode_tx(peer, afi, safi);
9300 has_adj = bgp_adj_out_lookup(
9301 peer, path->net,
9302 bgp_addpath_id_for_peer(peer, afi, safi,
9303 &path->tx_addpath));
9304
9305 if ((addpath_capable && has_adj)
9306 || (!addpath_capable && has_adj
9307 && CHECK_FLAG(path->flags,
9308 BGP_PATH_SELECTED))) {
9309 if (json_path && !json_adv_to)
9310 json_adv_to = json_object_new_object();
dcc68b5e 9311
05864da7
DS
9312 route_vty_out_advertised_to(
9313 vty, peer, &first,
9314 " Advertised to:", json_adv_to);
d62a17ae 9315 }
9316 }
718e3744 9317
05864da7
DS
9318 if (json_path) {
9319 if (json_adv_to) {
9320 json_object_object_add(
9321 json_path, "advertisedTo", json_adv_to);
d62a17ae 9322 }
05864da7
DS
9323 } else {
9324 if (!first) {
9325 vty_out(vty, "\n");
d62a17ae 9326 }
9327 }
05864da7 9328 }
b05a1c8b 9329
05864da7
DS
9330 /* Line 9 display Uptime */
9331 tbuf = time(NULL) - (bgp_clock() - path->uptime);
9332 if (json_paths) {
9333 json_last_update = json_object_new_object();
9334 json_object_int_add(json_last_update, "epoch", tbuf);
9335 json_object_string_add(json_last_update, "string",
9336 ctime(&tbuf));
9337 json_object_object_add(json_path, "lastUpdate",
9338 json_last_update);
9339 } else
9340 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 9341
05864da7
DS
9342 /* Line 10 display PMSI tunnel attribute, if present */
9343 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
9344 const char *str =
9345 lookup_msg(bgp_pmsi_tnltype_str, attr->pmsi_tnl_type,
9346 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 9347
05864da7
DS
9348 if (json_paths) {
9349 json_pmsi = json_object_new_object();
9350 json_object_string_add(json_pmsi, "tunnelType", str);
9351 json_object_int_add(json_pmsi, "label",
9352 label2vni(&attr->label));
9353 json_object_object_add(json_path, "pmsi", json_pmsi);
9354 } else
9355 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
9356 str, label2vni(&attr->label));
d62a17ae 9357 }
f1aa5d8a 9358
d62a17ae 9359 /* We've constructed the json object for this path, add it to the json
9360 * array of paths
9361 */
9362 if (json_paths) {
9363 if (json_nexthop_global || json_nexthop_ll) {
9364 json_nexthops = json_object_new_array();
f1aa5d8a 9365
d62a17ae 9366 if (json_nexthop_global)
9367 json_object_array_add(json_nexthops,
9368 json_nexthop_global);
f1aa5d8a 9369
d62a17ae 9370 if (json_nexthop_ll)
9371 json_object_array_add(json_nexthops,
9372 json_nexthop_ll);
f1aa5d8a 9373
d62a17ae 9374 json_object_object_add(json_path, "nexthops",
9375 json_nexthops);
9376 }
9377
9378 json_object_object_add(json_path, "peer", json_peer);
9379 json_object_array_add(json_paths, json_path);
05864da7 9380 }
b366b518
BB
9381}
9382
96ade3ed 9383#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
9384#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9385#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 9386
d62a17ae 9387static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
9388 const char *prefix_list_str, afi_t afi,
9389 safi_t safi, enum bgp_show_type type);
9390static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
9391 const char *filter, afi_t afi, safi_t safi,
9392 enum bgp_show_type type);
9393static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
9394 const char *rmap_str, afi_t afi, safi_t safi,
9395 enum bgp_show_type type);
9396static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
9397 const char *com, int exact, afi_t afi,
9398 safi_t safi);
9399static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
9400 const char *prefix, afi_t afi, safi_t safi,
9401 enum bgp_show_type type);
a4d82a8a 9402static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
9403 afi_t afi, safi_t safi, enum bgp_show_type type,
9404 bool use_json);
7f323236
DW
9405static int bgp_show_community(struct vty *vty, struct bgp *bgp,
9406 const char *comstr, int exact, afi_t afi,
9f049418 9407 safi_t safi, bool use_json);
d62a17ae 9408
1ae44dfc
LB
9409
9410static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 9411 struct bgp_table *table, enum bgp_show_type type,
9f049418 9412 void *output_arg, bool use_json, char *rd,
a4d82a8a
PZ
9413 int is_last, unsigned long *output_cum,
9414 unsigned long *total_cum,
9386b588 9415 unsigned long *json_header_depth)
d62a17ae 9416{
40381db7 9417 struct bgp_path_info *pi;
d62a17ae 9418 struct bgp_node *rn;
9419 int header = 1;
9420 int display;
1ae44dfc
LB
9421 unsigned long output_count = 0;
9422 unsigned long total_count = 0;
d62a17ae 9423 struct prefix *p;
d62a17ae 9424 char buf2[BUFSIZ];
9425 json_object *json_paths = NULL;
9426 int first = 1;
9427
1ae44dfc
LB
9428 if (output_cum && *output_cum != 0)
9429 header = 0;
9430
9386b588 9431 if (use_json && !*json_header_depth) {
d62a17ae 9432 vty_out(vty,
66f80d74 9433 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
01eced22
AD
9434 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9435 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 9436 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b
DS
9437 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
9438 ? VRF_DEFAULT_NAME
9439 : bgp->name,
01eced22
AD
9440 table->version, inet_ntoa(bgp->router_id),
9441 bgp->default_local_pref, bgp->as);
9386b588
PZ
9442 *json_header_depth = 2;
9443 if (rd) {
445c2480 9444 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
9445 ++*json_header_depth;
9446 }
d62a17ae 9447 }
718e3744 9448
445c2480
DS
9449 if (use_json && rd) {
9450 vty_out(vty, " \"%s\" : { ", rd);
9451 }
9452
d62a17ae 9453 /* Start processing of routes. */
98ce9a06 9454 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685
DS
9455 pi = bgp_node_get_bgp_path_info(rn);
9456 if (pi == NULL)
98ce9a06 9457 continue;
d62a17ae 9458
98ce9a06 9459 display = 0;
98ce9a06
DS
9460 if (use_json)
9461 json_paths = json_object_new_array();
9462 else
9463 json_paths = NULL;
d62a17ae 9464
6f94b685 9465 for (; pi; pi = pi->next) {
98ce9a06
DS
9466 total_count++;
9467 if (type == bgp_show_type_flap_statistics
9468 || type == bgp_show_type_flap_neighbor
9469 || type == bgp_show_type_dampend_paths
9470 || type == bgp_show_type_damp_neighbor) {
40381db7 9471 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
9472 continue;
9473 }
9474 if (type == bgp_show_type_regexp) {
9475 regex_t *regex = output_arg;
d62a17ae 9476
40381db7 9477 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
9478 == REG_NOMATCH)
9479 continue;
9480 }
9481 if (type == bgp_show_type_prefix_list) {
9482 struct prefix_list *plist = output_arg;
d62a17ae 9483
98ce9a06
DS
9484 if (prefix_list_apply(plist, &rn->p)
9485 != PREFIX_PERMIT)
9486 continue;
9487 }
9488 if (type == bgp_show_type_filter_list) {
9489 struct as_list *as_list = output_arg;
d62a17ae 9490
40381db7 9491 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
9492 != AS_FILTER_PERMIT)
9493 continue;
9494 }
9495 if (type == bgp_show_type_route_map) {
9496 struct route_map *rmap = output_arg;
9b6d8fcf 9497 struct bgp_path_info path;
98ce9a06 9498 struct attr dummy_attr;
b68885f9 9499 route_map_result_t ret;
d62a17ae 9500
6f4f49b2 9501 dummy_attr = *pi->attr;
d62a17ae 9502
40381db7 9503 path.peer = pi->peer;
9b6d8fcf 9504 path.attr = &dummy_attr;
d62a17ae 9505
a4d82a8a 9506 ret = route_map_apply(rmap, &rn->p, RMAP_BGP,
9b6d8fcf 9507 &path);
98ce9a06
DS
9508 if (ret == RMAP_DENYMATCH)
9509 continue;
9510 }
9511 if (type == bgp_show_type_neighbor
9512 || type == bgp_show_type_flap_neighbor
9513 || type == bgp_show_type_damp_neighbor) {
9514 union sockunion *su = output_arg;
9515
40381db7
DS
9516 if (pi->peer == NULL
9517 || pi->peer->su_remote == NULL
9518 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
9519 continue;
9520 }
9521 if (type == bgp_show_type_cidr_only) {
d7c0a89a 9522 uint32_t destination;
d62a17ae 9523
98ce9a06
DS
9524 destination = ntohl(rn->p.u.prefix4.s_addr);
9525 if (IN_CLASSC(destination)
9526 && rn->p.prefixlen == 24)
9527 continue;
9528 if (IN_CLASSB(destination)
9529 && rn->p.prefixlen == 16)
9530 continue;
9531 if (IN_CLASSA(destination)
9532 && rn->p.prefixlen == 8)
9533 continue;
9534 }
9535 if (type == bgp_show_type_prefix_longer) {
f7813c7c 9536 p = output_arg;
98ce9a06
DS
9537 if (!prefix_match(p, &rn->p))
9538 continue;
9539 }
9540 if (type == bgp_show_type_community_all) {
40381db7 9541 if (!pi->attr->community)
98ce9a06
DS
9542 continue;
9543 }
9544 if (type == bgp_show_type_community) {
9545 struct community *com = output_arg;
d62a17ae 9546
40381db7
DS
9547 if (!pi->attr->community
9548 || !community_match(pi->attr->community,
98ce9a06
DS
9549 com))
9550 continue;
9551 }
9552 if (type == bgp_show_type_community_exact) {
9553 struct community *com = output_arg;
d62a17ae 9554
40381db7
DS
9555 if (!pi->attr->community
9556 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
9557 continue;
9558 }
9559 if (type == bgp_show_type_community_list) {
9560 struct community_list *list = output_arg;
d62a17ae 9561
40381db7 9562 if (!community_list_match(pi->attr->community,
a4d82a8a 9563 list))
98ce9a06
DS
9564 continue;
9565 }
a4d82a8a 9566 if (type == bgp_show_type_community_list_exact) {
98ce9a06 9567 struct community_list *list = output_arg;
d62a17ae 9568
98ce9a06 9569 if (!community_list_exact_match(
40381db7 9570 pi->attr->community, list))
98ce9a06
DS
9571 continue;
9572 }
9573 if (type == bgp_show_type_lcommunity) {
9574 struct lcommunity *lcom = output_arg;
d62a17ae 9575
40381db7
DS
9576 if (!pi->attr->lcommunity
9577 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
9578 lcom))
9579 continue;
9580 }
36a206db 9581
9582 if (type == bgp_show_type_lcommunity_exact) {
9583 struct lcommunity *lcom = output_arg;
9584
9585 if (!pi->attr->lcommunity
9586 || !lcommunity_cmp(pi->attr->lcommunity,
9587 lcom))
9588 continue;
9589 }
98ce9a06
DS
9590 if (type == bgp_show_type_lcommunity_list) {
9591 struct community_list *list = output_arg;
d62a17ae 9592
40381db7 9593 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 9594 list))
98ce9a06
DS
9595 continue;
9596 }
36a206db 9597 if (type
9598 == bgp_show_type_lcommunity_list_exact) {
9599 struct community_list *list = output_arg;
9600
9601 if (!lcommunity_list_exact_match(
9602 pi->attr->lcommunity, list))
9603 continue;
9604 }
98ce9a06 9605 if (type == bgp_show_type_lcommunity_all) {
40381db7 9606 if (!pi->attr->lcommunity)
98ce9a06
DS
9607 continue;
9608 }
9609 if (type == bgp_show_type_dampend_paths
9610 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
9611 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
9612 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
9613 continue;
9614 }
9615
9616 if (!use_json && header) {
996c9314 9617 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 9618 ", local router ID is %s, vrf id ",
98ce9a06
DS
9619 table->version,
9620 inet_ntoa(bgp->router_id));
9df8b37c
PZ
9621 if (bgp->vrf_id == VRF_UNKNOWN)
9622 vty_out(vty, "%s", VRFID_NONE_STR);
9623 else
9624 vty_out(vty, "%u", bgp->vrf_id);
9625 vty_out(vty, "\n");
01eced22
AD
9626 vty_out(vty, "Default local pref %u, ",
9627 bgp->default_local_pref);
9628 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 9629 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 9630 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 9631 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 9632 if (type == bgp_show_type_dampend_paths
9633 || type == bgp_show_type_damp_neighbor)
98ce9a06 9634 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
9635 else if (type == bgp_show_type_flap_statistics
9636 || type == bgp_show_type_flap_neighbor)
98ce9a06 9637 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 9638 else
98ce9a06
DS
9639 vty_out(vty, BGP_SHOW_HEADER);
9640 header = 0;
d62a17ae 9641 }
98ce9a06
DS
9642 if (rd != NULL && !display && !output_count) {
9643 if (!use_json)
9644 vty_out(vty,
9645 "Route Distinguisher: %s\n",
9646 rd);
d62a17ae 9647 }
98ce9a06
DS
9648 if (type == bgp_show_type_dampend_paths
9649 || type == bgp_show_type_damp_neighbor)
a935f597 9650 damp_route_vty_out(vty, &rn->p, pi, display, AFI_IP,
a4d82a8a 9651 safi, use_json, json_paths);
98ce9a06
DS
9652 else if (type == bgp_show_type_flap_statistics
9653 || type == bgp_show_type_flap_neighbor)
a935f597 9654 flap_route_vty_out(vty, &rn->p, pi, display, AFI_IP,
a4d82a8a 9655 safi, use_json, json_paths);
98ce9a06 9656 else
40381db7 9657 route_vty_out(vty, &rn->p, pi, display, safi,
a4d82a8a 9658 json_paths);
98ce9a06 9659 display++;
d62a17ae 9660 }
9661
98ce9a06
DS
9662 if (display) {
9663 output_count++;
9664 if (!use_json)
9665 continue;
9666
9667 p = &rn->p;
625d2931
PG
9668 /* encode prefix */
9669 if (p->family == AF_FLOWSPEC) {
9670 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
9671
9672 bgp_fs_nlri_get_string((unsigned char *)
9673 p->u.prefix_flowspec.ptr,
9674 p->u.prefix_flowspec
9675 .prefixlen,
9676 retstr,
9677 NLRI_STRING_FORMAT_MIN,
9678 NULL);
9679 if (first)
9680 vty_out(vty, "\"%s/%d\": ",
9681 retstr,
9682 p->u.prefix_flowspec.prefixlen);
9683 else
9684 vty_out(vty, ",\"%s/%d\": ",
9685 retstr,
9686 p->u.prefix_flowspec.prefixlen);
9687 } else {
9688 prefix2str(p, buf2, sizeof(buf2));
9689 if (first)
9690 vty_out(vty, "\"%s\": ", buf2);
9691 else
9692 vty_out(vty, ",\"%s\": ", buf2);
9693 }
98ce9a06 9694 vty_out(vty, "%s",
f4ec52f7
DA
9695 json_object_to_json_string_ext(
9696 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 9697 json_object_free(json_paths);
449feb8e 9698 json_paths = NULL;
98ce9a06 9699 first = 0;
1f83ed02
DS
9700 } else
9701 json_object_free(json_paths);
98ce9a06
DS
9702 }
9703
1ae44dfc
LB
9704 if (output_cum) {
9705 output_count += *output_cum;
9706 *output_cum = output_count;
9707 }
9708 if (total_cum) {
9709 total_count += *total_cum;
9710 *total_cum = total_count;
9711 }
d62a17ae 9712 if (use_json) {
9386b588 9713 if (rd) {
a4d82a8a 9714 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
9715 }
9716 if (is_last) {
a4d82a8a
PZ
9717 unsigned long i;
9718 for (i = 0; i < *json_header_depth; ++i)
9719 vty_out(vty, " } ");
faf6559a 9720 vty_out(vty, "\n");
9386b588 9721 }
d62a17ae 9722 } else {
1ae44dfc
LB
9723 if (is_last) {
9724 /* No route is displayed */
9725 if (output_count == 0) {
9726 if (type == bgp_show_type_normal)
9727 vty_out(vty,
9728 "No BGP prefixes displayed, %ld exist\n",
9729 total_count);
9730 } else
d62a17ae 9731 vty_out(vty,
1ae44dfc
LB
9732 "\nDisplayed %ld routes and %ld total paths\n",
9733 output_count, total_count);
9734 }
d62a17ae 9735 }
718e3744 9736
d62a17ae 9737 return CMD_SUCCESS;
718e3744 9738}
9739
1ae44dfc
LB
9740int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
9741 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 9742 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc
LB
9743{
9744 struct bgp_node *rn, *next;
9745 unsigned long output_cum = 0;
9746 unsigned long total_cum = 0;
9386b588 9747 unsigned long json_header_depth = 0;
67009e22 9748 struct bgp_table *itable;
0136788c
LB
9749 bool show_msg;
9750
9751 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc
LB
9752
9753 for (rn = bgp_table_top(table); rn; rn = next) {
9754 next = bgp_route_next(rn);
9755 if (prd_match && memcmp(rn->p.u.val, prd_match->val, 8) != 0)
9756 continue;
67009e22
DS
9757
9758 itable = bgp_node_get_bgp_table_info(rn);
9759 if (itable != NULL) {
1ae44dfc 9760 struct prefix_rd prd;
06b9f471 9761 char rd[RD_ADDRSTRLEN];
1ae44dfc
LB
9762
9763 memcpy(&prd, &(rn->p), sizeof(struct prefix_rd));
06b9f471 9764 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22
DS
9765 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
9766 use_json, rd, next == NULL, &output_cum,
9767 &total_cum, &json_header_depth);
0136788c
LB
9768 if (next == NULL)
9769 show_msg = false;
1ae44dfc
LB
9770 }
9771 }
0136788c
LB
9772 if (show_msg) {
9773 if (output_cum == 0)
9774 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
9775 total_cum);
9776 else
9777 vty_out(vty,
9778 "\nDisplayed %ld routes and %ld total paths\n",
9779 output_cum, total_cum);
9780 }
1ae44dfc
LB
9781 return CMD_SUCCESS;
9782}
d62a17ae 9783static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
9f049418 9784 enum bgp_show_type type, void *output_arg, bool use_json)
fee0f4c6 9785{
d62a17ae 9786 struct bgp_table *table;
9386b588 9787 unsigned long json_header_depth = 0;
fee0f4c6 9788
d62a17ae 9789 if (bgp == NULL) {
9790 bgp = bgp_get_default();
9791 }
fee0f4c6 9792
d62a17ae 9793 if (bgp == NULL) {
9794 if (!use_json)
9795 vty_out(vty, "No BGP process is configured\n");
16307668
RW
9796 else
9797 vty_out(vty, "{}\n");
d62a17ae 9798 return CMD_WARNING;
9799 }
4dd6177e 9800
1ae44dfc 9801 table = bgp->rib[afi][safi];
d62a17ae 9802 /* use MPLS and ENCAP specific shows until they are merged */
9803 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
9804 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
9805 output_arg, use_json);
d62a17ae 9806 }
dba3c1d3
PG
9807
9808 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
9809 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
9810 output_arg, use_json,
9811 1, NULL, NULL);
9812 }
d62a17ae 9813 /* labeled-unicast routes live in the unicast table */
9814 else if (safi == SAFI_LABELED_UNICAST)
9815 safi = SAFI_UNICAST;
fee0f4c6 9816
1ae44dfc 9817 return bgp_show_table(vty, bgp, safi, table, type, output_arg, use_json,
9386b588 9818 NULL, 1, NULL, NULL, &json_header_depth);
fee0f4c6 9819}
9820
d62a17ae 9821static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
9f049418 9822 safi_t safi, bool use_json)
f186de26 9823{
d62a17ae 9824 struct listnode *node, *nnode;
9825 struct bgp *bgp;
9826 int is_first = 1;
9f049418 9827 bool route_output = false;
f186de26 9828
d62a17ae 9829 if (use_json)
9830 vty_out(vty, "{\n");
9f689658 9831
d62a17ae 9832 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 9833 route_output = true;
d62a17ae 9834 if (use_json) {
9835 if (!is_first)
9836 vty_out(vty, ",\n");
9837 else
9838 is_first = 0;
9839
9840 vty_out(vty, "\"%s\":",
9841 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 9842 ? VRF_DEFAULT_NAME
d62a17ae 9843 : bgp->name);
9844 } else {
9845 vty_out(vty, "\nInstance %s:\n",
9846 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 9847 ? VRF_DEFAULT_NAME
d62a17ae 9848 : bgp->name);
9849 }
9850 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
9851 use_json);
9852 }
9f689658 9853
d62a17ae 9854 if (use_json)
9855 vty_out(vty, "}\n");
9f049418
DS
9856 else if (!route_output)
9857 vty_out(vty, "%% BGP instance not found\n");
f186de26 9858}
9859
718e3744 9860/* Header of detailed BGP route information */
d62a17ae 9861void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9862 struct bgp_node *rn, struct prefix_rd *prd,
9863 afi_t afi, safi_t safi, json_object *json)
9864{
40381db7 9865 struct bgp_path_info *pi;
d62a17ae 9866 struct prefix *p;
9867 struct peer *peer;
9868 struct listnode *node, *nnode;
06b9f471 9869 char buf1[RD_ADDRSTRLEN];
d62a17ae 9870 char buf2[INET6_ADDRSTRLEN];
d62a17ae 9871 char buf3[EVPN_ROUTE_STRLEN];
0291c246 9872 char prefix_str[BUFSIZ];
d62a17ae 9873 int count = 0;
9874 int best = 0;
9875 int suppress = 0;
c5f1e1b2
C
9876 int accept_own = 0;
9877 int route_filter_translated_v4 = 0;
9878 int route_filter_v4 = 0;
9879 int route_filter_translated_v6 = 0;
9880 int route_filter_v6 = 0;
9881 int llgr_stale = 0;
9882 int no_llgr = 0;
9883 int accept_own_nexthop = 0;
9884 int blackhole = 0;
d62a17ae 9885 int no_export = 0;
9886 int no_advertise = 0;
9887 int local_as = 0;
c5f1e1b2 9888 int no_peer = 0;
d62a17ae 9889 int first = 1;
9890 int has_valid_label = 0;
9891 mpls_label_t label = 0;
9892 json_object *json_adv_to = NULL;
9bedbb1e 9893
d62a17ae 9894 p = &rn->p;
9895 has_valid_label = bgp_is_valid_label(&rn->local_label);
9896
9897 if (has_valid_label)
9898 label = label_pton(&rn->local_label);
9899
44c69747 9900 if (safi == SAFI_EVPN) {
d62a17ae 9901
44c69747 9902 if (!json) {
d62a17ae 9903 vty_out(vty, "BGP routing table entry for %s%s%s\n",
06b9f471 9904 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
44c69747 9905 : "", prd ? ":" : "",
d62a17ae 9906 bgp_evpn_route2str((struct prefix_evpn *)p,
44c69747
LK
9907 buf3, sizeof(buf3)));
9908 } else {
9909 json_object_string_add(json, "rd",
9910 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
9911 "");
9912 bgp_evpn_route2json((struct prefix_evpn *)p, json);
9913 }
9914 } else {
9915 if (!json) {
d62a17ae 9916 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
9917 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
44c69747
LK
9918 ? prefix_rd2str(prd, buf1,
9919 sizeof(buf1))
9920 : ""),
d62a17ae 9921 safi == SAFI_MPLS_VPN ? ":" : "",
9922 inet_ntop(p->family, &p->u.prefix, buf2,
44c69747 9923 INET6_ADDRSTRLEN),
d62a17ae 9924 p->prefixlen);
cd1964ff 9925
44c69747
LK
9926 } else
9927 json_object_string_add(json, "prefix",
9928 prefix2str(p, prefix_str, sizeof(prefix_str)));
9929 }
9930
9931 if (has_valid_label) {
9932 if (json)
9933 json_object_int_add(json, "localLabel", label);
9934 else
d62a17ae 9935 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
9936 }
9937
9938 if (!json)
d62a17ae 9939 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 9940 vty_out(vty, "not allocated\n");
718e3744 9941
6f94b685 9942 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
d62a17ae 9943 count++;
40381db7 9944 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 9945 best = count;
40381db7 9946 if (pi->extra && pi->extra->suppress)
d62a17ae 9947 suppress = 1;
cee9c031 9948
40381db7 9949 if (pi->attr->community == NULL)
cee9c031
QY
9950 continue;
9951
9952 no_advertise += community_include(
40381db7
DS
9953 pi->attr->community, COMMUNITY_NO_ADVERTISE);
9954 no_export += community_include(pi->attr->community,
cee9c031 9955 COMMUNITY_NO_EXPORT);
40381db7 9956 local_as += community_include(pi->attr->community,
cee9c031 9957 COMMUNITY_LOCAL_AS);
40381db7 9958 accept_own += community_include(pi->attr->community,
cee9c031
QY
9959 COMMUNITY_ACCEPT_OWN);
9960 route_filter_translated_v4 += community_include(
40381db7 9961 pi->attr->community,
cee9c031
QY
9962 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
9963 route_filter_translated_v6 += community_include(
40381db7 9964 pi->attr->community,
cee9c031
QY
9965 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
9966 route_filter_v4 += community_include(
40381db7 9967 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 9968 route_filter_v6 += community_include(
40381db7
DS
9969 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
9970 llgr_stale += community_include(pi->attr->community,
cee9c031 9971 COMMUNITY_LLGR_STALE);
40381db7 9972 no_llgr += community_include(pi->attr->community,
cee9c031
QY
9973 COMMUNITY_NO_LLGR);
9974 accept_own_nexthop +=
40381db7 9975 community_include(pi->attr->community,
cee9c031 9976 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 9977 blackhole += community_include(pi->attr->community,
cee9c031 9978 COMMUNITY_BLACKHOLE);
40381db7 9979 no_peer += community_include(pi->attr->community,
cee9c031 9980 COMMUNITY_NO_PEER);
d62a17ae 9981 }
718e3744 9982 }
718e3744 9983
d62a17ae 9984 if (!json) {
9985 vty_out(vty, "Paths: (%d available", count);
9986 if (best) {
9987 vty_out(vty, ", best #%d", best);
b84060bb
PG
9988 if (safi == SAFI_UNICAST) {
9989 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
9990 vty_out(vty, ", table %s",
9991 VRF_DEFAULT_NAME);
9992 else
9993 vty_out(vty, ", vrf %s",
9994 bgp->name);
9995 }
d62a17ae 9996 } else
9997 vty_out(vty, ", no best path");
9998
c5f1e1b2
C
9999 if (accept_own)
10000 vty_out(vty,
10001 ", accept own local route exported and imported in different VRF");
10002 else if (route_filter_translated_v4)
10003 vty_out(vty,
10004 ", mark translated RTs for VPNv4 route filtering");
10005 else if (route_filter_v4)
10006 vty_out(vty,
10007 ", attach RT as-is for VPNv4 route filtering");
10008 else if (route_filter_translated_v6)
10009 vty_out(vty,
10010 ", mark translated RTs for VPNv6 route filtering");
10011 else if (route_filter_v6)
10012 vty_out(vty,
10013 ", attach RT as-is for VPNv6 route filtering");
10014 else if (llgr_stale)
10015 vty_out(vty,
10016 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
10017 else if (no_llgr)
10018 vty_out(vty,
10019 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
10020 else if (accept_own_nexthop)
10021 vty_out(vty,
10022 ", accept local nexthop");
10023 else if (blackhole)
10024 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 10025 else if (no_export)
10026 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
10027 else if (no_advertise)
10028 vty_out(vty, ", not advertised to any peer");
d62a17ae 10029 else if (local_as)
10030 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
10031 else if (no_peer)
10032 vty_out(vty,
10033 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 10034
10035 if (suppress)
10036 vty_out(vty,
10037 ", Advertisements suppressed by an aggregate.");
10038 vty_out(vty, ")\n");
10039 }
718e3744 10040
d62a17ae 10041 /* If we are not using addpath then we can display Advertised to and
10042 * that will
10043 * show what peers we advertised the bestpath to. If we are using
10044 * addpath
10045 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 10046 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 10047 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10048 if (bgp_adj_out_lookup(peer, rn, 0)) {
10049 if (json && !json_adv_to)
10050 json_adv_to = json_object_new_object();
10051
10052 route_vty_out_advertised_to(
10053 vty, peer, &first,
10054 " Advertised to non peer-group peers:\n ",
10055 json_adv_to);
10056 }
10057 }
10058
10059 if (json) {
10060 if (json_adv_to) {
10061 json_object_object_add(json, "advertisedTo",
10062 json_adv_to);
10063 }
10064 } else {
10065 if (first)
10066 vty_out(vty, " Not advertised to any peer");
10067 vty_out(vty, "\n");
10068 }
10069 }
718e3744 10070}
10071
44c69747
LK
10072static void bgp_show_path_info(struct prefix_rd *pfx_rd,
10073 struct bgp_node *bgp_node, struct vty *vty,
10074 struct bgp *bgp, afi_t afi,
10075 safi_t safi, json_object *json,
10076 enum bgp_path_type pathtype, int *display)
10077{
10078 struct bgp_path_info *pi;
10079 int header = 1;
10080 char rdbuf[RD_ADDRSTRLEN];
10081 json_object *json_header = NULL;
10082 json_object *json_paths = NULL;
10083
10084 for (pi = bgp_node_get_bgp_path_info(bgp_node); pi;
10085 pi = pi->next) {
10086
10087 if (json && !json_paths) {
10088 /* Instantiate json_paths only if path is valid */
10089 json_paths = json_object_new_array();
10090 if (pfx_rd) {
10091 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
10092 json_header = json_object_new_object();
10093 } else
10094 json_header = json;
10095 }
10096
10097 if (header) {
10098 route_vty_out_detail_header(
10099 vty, bgp, bgp_node, pfx_rd,
10100 AFI_IP, safi, json_header);
10101 header = 0;
10102 }
10103 (*display)++;
10104
10105 if (pathtype == BGP_PATH_SHOW_ALL
10106 || (pathtype == BGP_PATH_SHOW_BESTPATH
10107 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
10108 || (pathtype == BGP_PATH_SHOW_MULTIPATH
10109 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
10110 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
10111 route_vty_out_detail(vty, bgp, bgp_node,
10112 pi, AFI_IP, safi,
10113 json_paths);
10114 }
10115
10116 if (json && json_paths) {
10117 json_object_object_add(json_header, "paths", json_paths);
10118
10119 if (pfx_rd)
10120 json_object_object_add(json, rdbuf, json_header);
10121 }
10122}
10123
718e3744 10124/* Display specified route of BGP table. */
d62a17ae 10125static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
10126 struct bgp_table *rib, const char *ip_str,
10127 afi_t afi, safi_t safi,
10128 struct prefix_rd *prd, int prefix_check,
9f049418 10129 enum bgp_path_type pathtype, bool use_json)
d62a17ae 10130{
10131 int ret;
d62a17ae 10132 int display = 0;
10133 struct prefix match;
10134 struct bgp_node *rn;
10135 struct bgp_node *rm;
d62a17ae 10136 struct bgp_table *table;
10137 json_object *json = NULL;
10138 json_object *json_paths = NULL;
10139
10140 /* Check IP address argument. */
10141 ret = str2prefix(ip_str, &match);
10142 if (!ret) {
10143 vty_out(vty, "address is malformed\n");
10144 return CMD_WARNING;
10145 }
718e3744 10146
d62a17ae 10147 match.family = afi2family(afi);
b05a1c8b 10148
44c69747 10149 if (use_json)
d62a17ae 10150 json = json_object_new_object();
718e3744 10151
44c69747 10152 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
d62a17ae 10153 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
10154 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
10155 continue;
67009e22
DS
10156 table = bgp_node_get_bgp_table_info(rn);
10157 if (!table)
ea47320b 10158 continue;
d62a17ae 10159
ea47320b
DL
10160 if ((rm = bgp_node_match(table, &match)) == NULL)
10161 continue;
d62a17ae 10162
ea47320b
DL
10163 if (prefix_check
10164 && rm->p.prefixlen != match.prefixlen) {
10165 bgp_unlock_node(rm);
10166 continue;
10167 }
d62a17ae 10168
44c69747
LK
10169 bgp_show_path_info((struct prefix_rd *)&rn->p, rm,
10170 vty, bgp, afi, safi, json,
10171 pathtype, &display);
10172
10173 bgp_unlock_node(rm);
10174 }
10175 } else if (safi == SAFI_EVPN) {
10176 struct bgp_node *longest_pfx;
10177 bool is_exact_pfxlen_match = FALSE;
10178
10179 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
10180 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
10181 continue;
10182 table = bgp_node_get_bgp_table_info(rn);
10183 if (!table)
10184 continue;
10185
10186 longest_pfx = NULL;
10187 is_exact_pfxlen_match = FALSE;
10188 /*
10189 * Search through all the prefixes for a match. The
10190 * pfx's are enumerated in ascending order of pfxlens.
10191 * So, the last pfx match is the longest match. Set
10192 * is_exact_pfxlen_match when we get exact pfxlen match
10193 */
10194 for (rm = bgp_table_top(table); rm;
10195 rm = bgp_route_next(rm)) {
10196 /*
10197 * Get prefixlen of the ip-prefix within type5
10198 * evpn route
10199 */
10200 if (evpn_type5_prefix_match(&rm->p,
10201 &match) && rm->info) {
10202 longest_pfx = rm;
10203 int type5_pfxlen =
10204 bgp_evpn_get_type5_prefixlen(&rm->p);
10205 if (type5_pfxlen == match.prefixlen) {
10206 is_exact_pfxlen_match = TRUE;
10207 bgp_unlock_node(rm);
10208 break;
10209 }
d62a17ae 10210 }
10211 }
ea47320b 10212
44c69747
LK
10213 if (!longest_pfx)
10214 continue;
10215
10216 if (prefix_check && !is_exact_pfxlen_match)
10217 continue;
10218
10219 rm = longest_pfx;
10220 bgp_lock_node(rm);
10221
10222 bgp_show_path_info((struct prefix_rd *)&rn->p, rm,
10223 vty, bgp, afi, safi, json,
10224 pathtype, &display);
10225
ea47320b 10226 bgp_unlock_node(rm);
d62a17ae 10227 }
98a9dbc7 10228 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
10229 if (use_json)
10230 json_paths = json_object_new_array();
10231
63a0b7a9
PG
10232 display = bgp_flowspec_display_match_per_ip(afi, rib,
10233 &match, prefix_check,
10234 vty,
10235 use_json,
10236 json_paths);
44c69747
LK
10237 if (use_json && display)
10238 json_object_object_add(json, "paths", json_paths);
d62a17ae 10239 } else {
d62a17ae 10240 if ((rn = bgp_node_match(rib, &match)) != NULL) {
10241 if (!prefix_check
10242 || rn->p.prefixlen == match.prefixlen) {
44c69747
LK
10243 bgp_show_path_info(NULL, rn, vty, bgp, afi,
10244 safi, json,
10245 pathtype, &display);
d62a17ae 10246 }
10247
10248 bgp_unlock_node(rn);
10249 }
10250 }
e5eee9af 10251
d62a17ae 10252 if (use_json) {
996c9314 10253 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
10254 json, JSON_C_TO_STRING_PRETTY |
10255 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 10256 json_object_free(json);
10257 } else {
10258 if (!display) {
10259 vty_out(vty, "%% Network not in table\n");
10260 return CMD_WARNING;
10261 }
10262 }
b05a1c8b 10263
d62a17ae 10264 return CMD_SUCCESS;
718e3744 10265}
10266
fee0f4c6 10267/* Display specified route of Main RIB */
d62a17ae 10268static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
10269 afi_t afi, safi_t safi, struct prefix_rd *prd,
10270 int prefix_check, enum bgp_path_type pathtype,
9f049418 10271 bool use_json)
d62a17ae 10272{
9b86009a 10273 if (!bgp) {
d62a17ae 10274 bgp = bgp_get_default();
9b86009a
RW
10275 if (!bgp) {
10276 if (!use_json)
10277 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10278 else
10279 vty_out(vty, "{}\n");
9b86009a
RW
10280 return CMD_WARNING;
10281 }
10282 }
d62a17ae 10283
10284 /* labeled-unicast routes live in the unicast table */
10285 if (safi == SAFI_LABELED_UNICAST)
10286 safi = SAFI_UNICAST;
10287
10288 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
10289 afi, safi, prd, prefix_check, pathtype,
10290 use_json);
10291}
10292
10293static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 10294 struct cmd_token **argv, bool exact, afi_t afi,
10295 safi_t safi, bool uj)
d62a17ae 10296{
10297 struct lcommunity *lcom;
10298 struct buffer *b;
10299 int i;
10300 char *str;
10301 int first = 0;
10302
10303 b = buffer_new(1024);
10304 for (i = 0; i < argc; i++) {
10305 if (first)
10306 buffer_putc(b, ' ');
10307 else {
10308 if (strmatch(argv[i]->text, "AA:BB:CC")) {
10309 first = 1;
10310 buffer_putstr(b, argv[i]->arg);
10311 }
10312 }
10313 }
10314 buffer_putc(b, '\0');
57d187bc 10315
d62a17ae 10316 str = buffer_getstr(b);
10317 buffer_free(b);
57d187bc 10318
d62a17ae 10319 lcom = lcommunity_str2com(str);
10320 XFREE(MTYPE_TMP, str);
10321 if (!lcom) {
10322 vty_out(vty, "%% Large-community malformed\n");
10323 return CMD_WARNING;
10324 }
57d187bc 10325
36a206db 10326 return bgp_show(vty, bgp, afi, safi,
10327 (exact ? bgp_show_type_lcommunity_exact
10328 : bgp_show_type_lcommunity),
10329 lcom, uj);
57d187bc
JS
10330}
10331
d62a17ae 10332static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 10333 const char *lcom, bool exact, afi_t afi,
10334 safi_t safi, bool uj)
57d187bc 10335{
d62a17ae 10336 struct community_list *list;
57d187bc 10337
e237b0d2 10338 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 10339 LARGE_COMMUNITY_LIST_MASTER);
10340 if (list == NULL) {
10341 vty_out(vty, "%% %s is not a valid large-community-list name\n",
10342 lcom);
10343 return CMD_WARNING;
10344 }
57d187bc 10345
36a206db 10346 return bgp_show(vty, bgp, afi, safi,
10347 (exact ? bgp_show_type_lcommunity_list_exact
10348 : bgp_show_type_lcommunity_list),
d62a17ae 10349 list, uj);
fee0f4c6 10350}
10351
52951b63
DS
10352DEFUN (show_ip_bgp_large_community_list,
10353 show_ip_bgp_large_community_list_cmd,
36a206db 10354 "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
10355 SHOW_STR
10356 IP_STR
10357 BGP_STR
10358 BGP_INSTANCE_HELP_STR
9bedbb1e 10359 BGP_AFI_HELP_STR
4dd6177e 10360 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10361 "Display routes matching the large-community-list\n"
10362 "large-community-list number\n"
10363 "large-community-list name\n"
36a206db 10364 "Exact match of the large-communities\n"
52951b63
DS
10365 JSON_STR)
10366{
d62a17ae 10367 char *vrf = NULL;
10368 afi_t afi = AFI_IP6;
10369 safi_t safi = SAFI_UNICAST;
10370 int idx = 0;
36a206db 10371 bool exact_match = 0;
d62a17ae 10372
10373 if (argv_find(argv, argc, "ip", &idx))
10374 afi = AFI_IP;
10375 if (argv_find(argv, argc, "view", &idx)
10376 || argv_find(argv, argc, "vrf", &idx))
10377 vrf = argv[++idx]->arg;
10378 if (argv_find(argv, argc, "ipv4", &idx)
10379 || argv_find(argv, argc, "ipv6", &idx)) {
10380 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
10381 if (argv_find(argv, argc, "unicast", &idx)
10382 || argv_find(argv, argc, "multicast", &idx))
10383 safi = bgp_vty_safi_from_str(argv[idx]->text);
10384 }
10385
9f049418 10386 bool uj = use_json(argc, argv);
d62a17ae 10387
10388 struct bgp *bgp = bgp_lookup_by_name(vrf);
10389 if (bgp == NULL) {
10390 vty_out(vty, "Can't find BGP instance %s\n", vrf);
10391 return CMD_WARNING;
10392 }
10393
10394 argv_find(argv, argc, "large-community-list", &idx);
36a206db 10395
10396 const char *clist_number_or_name = argv[++idx]->arg;
10397
10398 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10399 exact_match = 1;
10400
10401 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
10402 exact_match, afi, safi, uj);
52951b63
DS
10403}
10404DEFUN (show_ip_bgp_large_community,
10405 show_ip_bgp_large_community_cmd,
36a206db 10406 "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
10407 SHOW_STR
10408 IP_STR
10409 BGP_STR
10410 BGP_INSTANCE_HELP_STR
9bedbb1e 10411 BGP_AFI_HELP_STR
4dd6177e 10412 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10413 "Display routes matching the large-communities\n"
10414 "List of large-community numbers\n"
36a206db 10415 "Exact match of the large-communities\n"
52951b63
DS
10416 JSON_STR)
10417{
d62a17ae 10418 char *vrf = NULL;
10419 afi_t afi = AFI_IP6;
10420 safi_t safi = SAFI_UNICAST;
10421 int idx = 0;
36a206db 10422 bool exact_match = 0;
d62a17ae 10423
10424 if (argv_find(argv, argc, "ip", &idx))
10425 afi = AFI_IP;
10426 if (argv_find(argv, argc, "view", &idx)
10427 || argv_find(argv, argc, "vrf", &idx))
10428 vrf = argv[++idx]->arg;
10429 if (argv_find(argv, argc, "ipv4", &idx)
10430 || argv_find(argv, argc, "ipv6", &idx)) {
10431 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
10432 if (argv_find(argv, argc, "unicast", &idx)
10433 || argv_find(argv, argc, "multicast", &idx))
10434 safi = bgp_vty_safi_from_str(argv[idx]->text);
10435 }
10436
9f049418 10437 bool uj = use_json(argc, argv);
d62a17ae 10438
10439 struct bgp *bgp = bgp_lookup_by_name(vrf);
10440 if (bgp == NULL) {
10441 vty_out(vty, "Can't find BGP instance %s\n", vrf);
10442 return CMD_WARNING;
10443 }
10444
36a206db 10445 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
10446 if (argv_find(argv, argc, "exact-match", &idx))
10447 exact_match = 1;
10448 return bgp_show_lcommunity(vty, bgp, argc, argv,
10449 exact_match, afi, safi, uj);
10450 } else
d62a17ae 10451 return bgp_show(vty, bgp, afi, safi,
10452 bgp_show_type_lcommunity_all, NULL, uj);
52951b63
DS
10453}
10454
d62a17ae 10455static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
10456 safi_t safi);
e01ca200 10457
7b2ff250
DW
10458
10459/* BGP route print out function without JSON */
af462945
DS
10460DEFUN (show_ip_bgp,
10461 show_ip_bgp_cmd,
4dd6177e 10462 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
7b2ff250
DW
10463 <dampening <parameters>\
10464 |route-map WORD\
10465 |prefix-list WORD\
10466 |filter-list WORD\
10467 |statistics\
7b2ff250
DW
10468 |community-list <(1-500)|WORD> [exact-match]\
10469 |A.B.C.D/M longer-prefixes\
10470 |X:X::X:X/M longer-prefixes\
10471 >",
718e3744 10472 SHOW_STR
10473 IP_STR
10474 BGP_STR
a636c635 10475 BGP_INSTANCE_HELP_STR
4f280b15 10476 BGP_AFI_HELP_STR
4dd6177e 10477 BGP_SAFI_WITH_LABEL_HELP_STR
a636c635 10478 "Display detailed information about dampening\n"
af462945 10479 "Display detail of configured dampening parameters\n"
a636c635
DW
10480 "Display routes matching the route-map\n"
10481 "A route-map to match on\n"
10482 "Display routes conforming to the prefix-list\n"
8c3deaae 10483 "Prefix-list name\n"
a636c635
DW
10484 "Display routes conforming to the filter-list\n"
10485 "Regular expression access list name\n"
e01ca200 10486 "BGP RIB advertisement statistics\n"
a636c635
DW
10487 "Display routes matching the community-list\n"
10488 "community-list number\n"
10489 "community-list name\n"
10490 "Exact match of the communities\n"
0c7b1b01 10491 "IPv4 prefix\n"
8c3deaae 10492 "Display route and more specific routes\n"
0c7b1b01 10493 "IPv6 prefix\n"
7b2ff250 10494 "Display route and more specific routes\n")
718e3744 10495{
d62a17ae 10496 afi_t afi = AFI_IP6;
10497 safi_t safi = SAFI_UNICAST;
10498 int exact_match = 0;
d62a17ae 10499 struct bgp *bgp = NULL;
10500 int idx = 0;
10501
10502 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10503 &bgp, false);
d62a17ae 10504 if (!idx)
10505 return CMD_WARNING;
10506
d62a17ae 10507 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 10508 if (argv_find(argv, argc, "parameters", &idx))
d62a17ae 10509 return bgp_show_dampening_parameters(vty, afi, safi);
10510 }
c016b6c7 10511
d62a17ae 10512 if (argv_find(argv, argc, "prefix-list", &idx))
10513 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
10514 safi, bgp_show_type_prefix_list);
10515
10516 if (argv_find(argv, argc, "filter-list", &idx))
10517 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
10518 safi, bgp_show_type_filter_list);
10519
10520 if (argv_find(argv, argc, "statistics", &idx))
10521 return bgp_table_stats(vty, bgp, afi, safi);
10522
10523 if (argv_find(argv, argc, "route-map", &idx))
10524 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
10525 safi, bgp_show_type_route_map);
10526
d62a17ae 10527 if (argv_find(argv, argc, "community-list", &idx)) {
10528 const char *clist_number_or_name = argv[++idx]->arg;
10529 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10530 exact_match = 1;
10531 return bgp_show_community_list(vty, bgp, clist_number_or_name,
10532 exact_match, afi, safi);
10533 }
10534 /* prefix-longer */
10535 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10536 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10537 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
10538 safi,
10539 bgp_show_type_prefix_longer);
10540
7b2ff250
DW
10541 return CMD_WARNING;
10542}
10543
10544/* BGP route print out function with JSON */
10545DEFUN (show_ip_bgp_json,
10546 show_ip_bgp_json_cmd,
10547 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
cf4898bc
QY
10548 [cidr-only\
10549 |dampening <flap-statistics|dampened-paths>\
10550 |community [AA:NN|local-AS|no-advertise|no-export\
10551 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10552 |accept-own|accept-own-nexthop|route-filter-v6\
10553 |route-filter-v4|route-filter-translated-v6\
10554 |route-filter-translated-v4] [exact-match]\
10555 ] [json]",
7b2ff250
DW
10556 SHOW_STR
10557 IP_STR
10558 BGP_STR
10559 BGP_INSTANCE_HELP_STR
10560 BGP_AFI_HELP_STR
10561 BGP_SAFI_WITH_LABEL_HELP_STR
10562 "Display only routes with non-natural netmasks\n"
10563 "Display detailed information about dampening\n"
10564 "Display flap statistics of routes\n"
10565 "Display paths suppressed due to dampening\n"
10566 "Display routes matching the communities\n"
d0086e8e
AD
10567 COMMUNITY_AANN_STR
10568 "Do not send outside local AS (well-known community)\n"
10569 "Do not advertise to any peer (well-known community)\n"
10570 "Do not export to next AS (well-known community)\n"
10571 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
10572 "Do not export to any peer (well-known community)\n"
10573 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10574 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10575 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10576 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10577 "Should accept VPN route with local nexthop (well-known community)\n"
10578 "RT VPNv6 route filtering (well-known community)\n"
10579 "RT VPNv4 route filtering (well-known community)\n"
10580 "RT translated VPNv6 route filtering (well-known community)\n"
10581 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 10582 "Exact match of the communities\n"
7b2ff250
DW
10583 JSON_STR)
10584{
10585 afi_t afi = AFI_IP6;
10586 safi_t safi = SAFI_UNICAST;
10587 enum bgp_show_type sh_type = bgp_show_type_normal;
10588 struct bgp *bgp = NULL;
10589 int idx = 0;
d0086e8e 10590 int exact_match = 0;
9f049418
DS
10591 bool uj = use_json(argc, argv);
10592
10593 if (uj)
10594 argc--;
7b2ff250
DW
10595
10596 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10597 &bgp, uj);
7b2ff250
DW
10598 if (!idx)
10599 return CMD_WARNING;
10600
7b2ff250
DW
10601 if (argv_find(argv, argc, "cidr-only", &idx))
10602 return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
10603 NULL, uj);
10604
10605 if (argv_find(argv, argc, "dampening", &idx)) {
10606 if (argv_find(argv, argc, "dampened-paths", &idx))
10607 return bgp_show(vty, bgp, afi, safi,
10608 bgp_show_type_dampend_paths, NULL, uj);
10609 else if (argv_find(argv, argc, "flap-statistics", &idx))
10610 return bgp_show(vty, bgp, afi, safi,
10611 bgp_show_type_flap_statistics, NULL,
10612 uj);
10613 }
10614
10615 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 10616 char *maybecomm = NULL;
cf4898bc 10617 char *community = NULL;
d0086e8e 10618
79bc257a
RW
10619 if (idx + 1 < argc) {
10620 if (argv[idx + 1]->type == VARIABLE_TKN)
10621 maybecomm = argv[idx + 1]->arg;
10622 else
10623 maybecomm = argv[idx + 1]->text;
10624 }
10625
cf4898bc
QY
10626 if (maybecomm && !strmatch(maybecomm, "json")
10627 && !strmatch(maybecomm, "exact-match"))
10628 community = maybecomm;
d0086e8e 10629
cf4898bc
QY
10630 if (argv_find(argv, argc, "exact-match", &idx))
10631 exact_match = 1;
d0086e8e 10632
cf4898bc
QY
10633 if (community)
10634 return bgp_show_community(vty, bgp, community,
10635 exact_match, afi, safi, uj);
10636 else
d0086e8e 10637 return (bgp_show(vty, bgp, afi, safi,
cf4898bc
QY
10638 bgp_show_type_community_all, NULL,
10639 uj));
7b2ff250 10640 }
d0086e8e 10641
1ae44dfc 10642 return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj);
a636c635 10643}
47fc97cc 10644
718e3744 10645DEFUN (show_ip_bgp_route,
10646 show_ip_bgp_route_cmd,
4dd6177e 10647 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]"
ae19d7dd 10648 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
718e3744 10649 SHOW_STR
10650 IP_STR
10651 BGP_STR
a636c635 10652 BGP_INSTANCE_HELP_STR
4f280b15 10653 BGP_AFI_HELP_STR
4dd6177e 10654 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 10655 "Network in the BGP routing table to display\n"
0c7b1b01 10656 "IPv4 prefix\n"
8c3deaae 10657 "Network in the BGP routing table to display\n"
0c7b1b01 10658 "IPv6 prefix\n"
4092b06c 10659 "Display only the bestpath\n"
b05a1c8b 10660 "Display only multipaths\n"
9973d184 10661 JSON_STR)
4092b06c 10662{
d62a17ae 10663 int prefix_check = 0;
ae19d7dd 10664
d62a17ae 10665 afi_t afi = AFI_IP6;
10666 safi_t safi = SAFI_UNICAST;
10667 char *prefix = NULL;
10668 struct bgp *bgp = NULL;
10669 enum bgp_path_type path_type;
9f049418 10670 bool uj = use_json(argc, argv);
b05a1c8b 10671
d62a17ae 10672 int idx = 0;
ae19d7dd 10673
d62a17ae 10674 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10675 &bgp, uj);
d62a17ae 10676 if (!idx)
10677 return CMD_WARNING;
c41247f5 10678
d62a17ae 10679 if (!bgp) {
10680 vty_out(vty,
10681 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10682 return CMD_WARNING;
10683 }
a636c635 10684
d62a17ae 10685 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10686 if (argv_find(argv, argc, "A.B.C.D", &idx)
10687 || argv_find(argv, argc, "X:X::X:X", &idx))
10688 prefix_check = 0;
10689 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10690 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10691 prefix_check = 1;
10692
10693 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
10694 && afi != AFI_IP6) {
10695 vty_out(vty,
10696 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10697 return CMD_WARNING;
10698 }
10699 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
10700 && afi != AFI_IP) {
10701 vty_out(vty,
10702 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10703 return CMD_WARNING;
10704 }
10705
10706 prefix = argv[idx]->arg;
10707
10708 /* [<bestpath|multipath>] */
10709 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 10710 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 10711 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 10712 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 10713 else
360660c6 10714 path_type = BGP_PATH_SHOW_ALL;
a636c635 10715
d62a17ae 10716 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
10717 path_type, uj);
4092b06c
DS
10718}
10719
8c3deaae
QY
10720DEFUN (show_ip_bgp_regexp,
10721 show_ip_bgp_regexp_cmd,
3e5b31b3 10722 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
10723 SHOW_STR
10724 IP_STR
10725 BGP_STR
b00b230a 10726 BGP_INSTANCE_HELP_STR
4f280b15 10727 BGP_AFI_HELP_STR
4dd6177e 10728 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 10729 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
10730 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
10731 JSON_STR)
8c3deaae 10732{
d62a17ae 10733 afi_t afi = AFI_IP6;
10734 safi_t safi = SAFI_UNICAST;
10735 struct bgp *bgp = NULL;
3e5b31b3
DA
10736 bool uj = use_json(argc, argv);
10737 char *regstr = NULL;
8c3deaae 10738
d62a17ae 10739 int idx = 0;
10740 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10741 &bgp, false);
d62a17ae 10742 if (!idx)
10743 return CMD_WARNING;
8c3deaae 10744
d62a17ae 10745 // get index of regex
3e5b31b3
DA
10746 if (argv_find(argv, argc, "REGEX", &idx))
10747 regstr = argv[idx]->arg;
8c3deaae 10748
5f71d11c 10749 assert(regstr);
3e5b31b3
DA
10750 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
10751 bgp_show_type_regexp, uj);
8c3deaae
QY
10752}
10753
a636c635
DW
10754DEFUN (show_ip_bgp_instance_all,
10755 show_ip_bgp_instance_all_cmd,
4dd6177e 10756 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json]",
4092b06c 10757 SHOW_STR
a636c635 10758 IP_STR
4092b06c 10759 BGP_STR
a636c635 10760 BGP_INSTANCE_ALL_HELP_STR
4f280b15 10761 BGP_AFI_HELP_STR
4dd6177e 10762 BGP_SAFI_WITH_LABEL_HELP_STR
9973d184 10763 JSON_STR)
4092b06c 10764{
d62a17ae 10765 afi_t afi = AFI_IP;
10766 safi_t safi = SAFI_UNICAST;
10767 struct bgp *bgp = NULL;
d62a17ae 10768 int idx = 0;
9f049418 10769 bool uj = use_json(argc, argv);
ae19d7dd 10770
d62a17ae 10771 if (uj)
10772 argc--;
e3e29b32 10773
9f049418
DS
10774 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10775 &bgp, uj);
10776 if (!idx)
10777 return CMD_WARNING;
10778
d62a17ae 10779 bgp_show_all_instances_routes_vty(vty, afi, safi, uj);
10780 return CMD_SUCCESS;
e3e29b32
LB
10781}
10782
a4d82a8a 10783static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10784 afi_t afi, safi_t safi, enum bgp_show_type type,
10785 bool use_json)
718e3744 10786{
d62a17ae 10787 regex_t *regex;
10788 int rc;
e3e29b32 10789
c3900853 10790 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 10791 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
10792 regstr);
10793 return CMD_WARNING_CONFIG_FAILED;
10794 }
10795
d62a17ae 10796 regex = bgp_regcomp(regstr);
10797 if (!regex) {
10798 vty_out(vty, "Can't compile regexp %s\n", regstr);
10799 return CMD_WARNING;
10800 }
a636c635 10801
3e5b31b3 10802 rc = bgp_show(vty, bgp, afi, safi, type, regex, use_json);
d62a17ae 10803 bgp_regex_free(regex);
10804 return rc;
e3e29b32
LB
10805}
10806
d62a17ae 10807static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10808 const char *prefix_list_str, afi_t afi,
10809 safi_t safi, enum bgp_show_type type)
e3e29b32 10810{
d62a17ae 10811 struct prefix_list *plist;
718e3744 10812
d62a17ae 10813 plist = prefix_list_lookup(afi, prefix_list_str);
10814 if (plist == NULL) {
10815 vty_out(vty, "%% %s is not a valid prefix-list name\n",
10816 prefix_list_str);
10817 return CMD_WARNING;
10818 }
718e3744 10819
d62a17ae 10820 return bgp_show(vty, bgp, afi, safi, type, plist, 0);
4092b06c
DS
10821}
10822
d62a17ae 10823static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10824 const char *filter, afi_t afi, safi_t safi,
10825 enum bgp_show_type type)
4092b06c 10826{
d62a17ae 10827 struct as_list *as_list;
718e3744 10828
d62a17ae 10829 as_list = as_list_lookup(filter);
10830 if (as_list == NULL) {
10831 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
10832 filter);
10833 return CMD_WARNING;
10834 }
a636c635 10835
d62a17ae 10836 return bgp_show(vty, bgp, afi, safi, type, as_list, 0);
718e3744 10837}
10838
d62a17ae 10839static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10840 const char *rmap_str, afi_t afi, safi_t safi,
10841 enum bgp_show_type type)
718e3744 10842{
d62a17ae 10843 struct route_map *rmap;
bb46e94f 10844
d62a17ae 10845 rmap = route_map_lookup_by_name(rmap_str);
10846 if (!rmap) {
10847 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
10848 return CMD_WARNING;
10849 }
10850
10851 return bgp_show(vty, bgp, afi, safi, type, rmap, 0);
10852}
10853
7f323236
DW
10854static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10855 const char *comstr, int exact, afi_t afi,
9f049418 10856 safi_t safi, bool use_json)
d62a17ae 10857{
10858 struct community *com;
d62a17ae 10859 int ret = 0;
10860
7f323236 10861 com = community_str2com(comstr);
d62a17ae 10862 if (!com) {
7f323236 10863 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 10864 return CMD_WARNING;
10865 }
10866
10867 ret = bgp_show(vty, bgp, afi, safi,
10868 (exact ? bgp_show_type_community_exact
10869 : bgp_show_type_community),
d0086e8e 10870 com, use_json);
3c1f53de 10871 community_free(&com);
46c3ce83 10872
d62a17ae 10873 return ret;
718e3744 10874}
10875
d62a17ae 10876static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10877 const char *com, int exact, afi_t afi,
10878 safi_t safi)
50ef26d4 10879{
d62a17ae 10880 struct community_list *list;
50ef26d4 10881
e237b0d2 10882 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 10883 if (list == NULL) {
10884 vty_out(vty, "%% %s is not a valid community-list name\n", com);
10885 return CMD_WARNING;
10886 }
718e3744 10887
d62a17ae 10888 return bgp_show(vty, bgp, afi, safi,
10889 (exact ? bgp_show_type_community_list_exact
10890 : bgp_show_type_community_list),
10891 list, 0);
50ef26d4 10892}
10893
d62a17ae 10894static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10895 const char *prefix, afi_t afi, safi_t safi,
10896 enum bgp_show_type type)
718e3744 10897{
d62a17ae 10898 int ret;
10899 struct prefix *p;
47fc97cc 10900
d62a17ae 10901 p = prefix_new();
95cbbd2a 10902
d62a17ae 10903 ret = str2prefix(prefix, p);
10904 if (!ret) {
10905 vty_out(vty, "%% Malformed Prefix\n");
10906 return CMD_WARNING;
10907 }
47e9b292 10908
d62a17ae 10909 ret = bgp_show(vty, bgp, afi, safi, type, p, 0);
63265b5c 10910 prefix_free(&p);
d62a17ae 10911 return ret;
10912}
10913
d62a17ae 10914enum bgp_stats {
10915 BGP_STATS_MAXBITLEN = 0,
10916 BGP_STATS_RIB,
10917 BGP_STATS_PREFIXES,
10918 BGP_STATS_TOTPLEN,
10919 BGP_STATS_UNAGGREGATEABLE,
10920 BGP_STATS_MAX_AGGREGATEABLE,
10921 BGP_STATS_AGGREGATES,
10922 BGP_STATS_SPACE,
10923 BGP_STATS_ASPATH_COUNT,
10924 BGP_STATS_ASPATH_MAXHOPS,
10925 BGP_STATS_ASPATH_TOTHOPS,
10926 BGP_STATS_ASPATH_MAXSIZE,
10927 BGP_STATS_ASPATH_TOTSIZE,
10928 BGP_STATS_ASN_HIGHEST,
10929 BGP_STATS_MAX,
a636c635 10930};
2815e61f 10931
2b64873d 10932static const char *const table_stats_strs[] = {
9d303b37
DL
10933 [BGP_STATS_PREFIXES] = "Total Prefixes",
10934 [BGP_STATS_TOTPLEN] = "Average prefix length",
10935 [BGP_STATS_RIB] = "Total Advertisements",
10936 [BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes",
10937 [BGP_STATS_MAX_AGGREGATEABLE] =
10938 "Maximum aggregateable prefixes",
10939 [BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements",
10940 [BGP_STATS_SPACE] = "Address space advertised",
10941 [BGP_STATS_ASPATH_COUNT] = "Advertisements with paths",
10942 [BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)",
10943 [BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)",
10944 [BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)",
10945 [BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)",
10946 [BGP_STATS_ASN_HIGHEST] = "Highest public ASN",
10947 [BGP_STATS_MAX] = NULL,
a636c635 10948};
2815e61f 10949
d62a17ae 10950struct bgp_table_stats {
10951 struct bgp_table *table;
10952 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 10953 double total_space;
ff7924f6
PJ
10954};
10955
a636c635
DW
10956#if 0
10957#define TALLY_SIGFIG 100000
10958static unsigned long
10959ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 10960{
a636c635
DW
10961 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
10962 unsigned long res = (newtot * TALLY_SIGFIG) / count;
10963 unsigned long ret = newtot / count;
07d0c4ed 10964
a636c635
DW
10965 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
10966 return ret + 1;
10967 else
10968 return ret;
10969}
10970#endif
ff7924f6 10971
9c14ec72
RW
10972static void bgp_table_stats_rn(struct bgp_node *rn, struct bgp_node *top,
10973 struct bgp_table_stats *ts, unsigned int space)
2815e61f 10974{
9c14ec72
RW
10975 struct bgp_node *prn = bgp_node_parent_nolock(rn);
10976 struct bgp_path_info *pi;
d62a17ae 10977
9c14ec72
RW
10978 if (rn == top)
10979 return;
d62a17ae 10980
9c14ec72
RW
10981 if (!bgp_node_has_bgp_path_info_data(rn))
10982 return;
d62a17ae 10983
9c14ec72
RW
10984 ts->counts[BGP_STATS_PREFIXES]++;
10985 ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
ff7924f6 10986
a636c635
DW
10987#if 0
10988 ts->counts[BGP_STATS_AVGPLEN]
10989 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
10990 ts->counts[BGP_STATS_AVGPLEN],
10991 rn->p.prefixlen);
10992#endif
d62a17ae 10993
9c14ec72
RW
10994 /* check if the prefix is included by any other announcements */
10995 while (prn && !bgp_node_has_bgp_path_info_data(prn))
10996 prn = bgp_node_parent_nolock(prn);
d62a17ae 10997
9c14ec72
RW
10998 if (prn == NULL || prn == top) {
10999 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
11000 /* announced address space */
11001 if (space)
11002 ts->total_space += pow(2.0, space - rn->p.prefixlen);
11003 } else if (bgp_node_has_bgp_path_info_data(prn))
11004 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 11005
9c14ec72
RW
11006
11007 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
11008 ts->counts[BGP_STATS_RIB]++;
11009
05864da7
DS
11010 if (CHECK_FLAG(pi->attr->flag,
11011 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
11012 ts->counts[BGP_STATS_AGGREGATES]++;
11013
11014 /* as-path stats */
05864da7 11015 if (pi->attr->aspath) {
9c14ec72
RW
11016 unsigned int hops = aspath_count_hops(pi->attr->aspath);
11017 unsigned int size = aspath_size(pi->attr->aspath);
11018 as_t highest = aspath_highest(pi->attr->aspath);
11019
11020 ts->counts[BGP_STATS_ASPATH_COUNT]++;
11021
11022 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
11023 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
11024
11025 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
11026 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
11027
11028 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
11029 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 11030#if 0
07d0c4ed 11031 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
11032 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
11033 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
11034 hops);
11035 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
11036 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
11037 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
11038 size);
11039#endif
9c14ec72
RW
11040 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
11041 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
11042 }
11043 }
11044}
11045
11046static int bgp_table_stats_walker(struct thread *t)
11047{
11048 struct bgp_node *rn, *nrn;
11049 struct bgp_node *top;
11050 struct bgp_table_stats *ts = THREAD_ARG(t);
11051 unsigned int space = 0;
11052
11053 if (!(top = bgp_table_top(ts->table)))
11054 return 0;
11055
11056 switch (ts->table->afi) {
11057 case AFI_IP:
11058 space = IPV4_MAX_BITLEN;
11059 break;
11060 case AFI_IP6:
11061 space = IPV6_MAX_BITLEN;
11062 break;
11063 default:
11064 return 0;
11065 }
11066
11067 ts->counts[BGP_STATS_MAXBITLEN] = space;
11068
11069 for (rn = top; rn; rn = bgp_route_next(rn)) {
11070 if (ts->table->safi == SAFI_MPLS_VPN) {
11071 struct bgp_table *table;
11072
11073 table = bgp_node_get_bgp_table_info(rn);
11074 if (!table)
11075 continue;
11076
11077 top = bgp_table_top(table);
11078 for (nrn = bgp_table_top(table); nrn;
11079 nrn = bgp_route_next(nrn))
11080 bgp_table_stats_rn(nrn, top, ts, space);
11081 } else {
11082 bgp_table_stats_rn(rn, top, ts, space);
d62a17ae 11083 }
11084 }
9c14ec72 11085
d62a17ae 11086 return 0;
2815e61f 11087}
ff7924f6 11088
d62a17ae 11089static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
11090 safi_t safi)
2815e61f 11091{
d62a17ae 11092 struct bgp_table_stats ts;
11093 unsigned int i;
019386c2 11094
d62a17ae 11095 if (!bgp->rib[afi][safi]) {
11096 vty_out(vty, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
11097 afi, safi);
11098 return CMD_WARNING;
11099 }
019386c2 11100
5cb5f4d0 11101 vty_out(vty, "BGP %s RIB statistics\n", get_afi_safi_str(afi, safi, false));
019386c2 11102
d62a17ae 11103 /* labeled-unicast routes live in the unicast table */
11104 if (safi == SAFI_LABELED_UNICAST)
11105 safi = SAFI_UNICAST;
019386c2 11106
d62a17ae 11107 memset(&ts, 0, sizeof(ts));
11108 ts.table = bgp->rib[afi][safi];
11109 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 11110
d62a17ae 11111 for (i = 0; i < BGP_STATS_MAX; i++) {
11112 if (!table_stats_strs[i])
11113 continue;
11114
11115 switch (i) {
a636c635
DW
11116#if 0
11117 case BGP_STATS_ASPATH_AVGHOPS:
11118 case BGP_STATS_ASPATH_AVGSIZE:
11119 case BGP_STATS_AVGPLEN:
11120 vty_out (vty, "%-30s: ", table_stats_strs[i]);
11121 vty_out (vty, "%12.2f",
11122 (float)ts.counts[i] / (float)TALLY_SIGFIG);
11123 break;
11124#endif
d62a17ae 11125 case BGP_STATS_ASPATH_TOTHOPS:
11126 case BGP_STATS_ASPATH_TOTSIZE:
11127 vty_out(vty, "%-30s: ", table_stats_strs[i]);
11128 vty_out(vty, "%12.2f",
11129 ts.counts[i]
11130 ? (float)ts.counts[i]
11131 / (float)ts.counts
11132 [BGP_STATS_ASPATH_COUNT]
11133 : 0);
11134 break;
11135 case BGP_STATS_TOTPLEN:
11136 vty_out(vty, "%-30s: ", table_stats_strs[i]);
11137 vty_out(vty, "%12.2f",
11138 ts.counts[i]
11139 ? (float)ts.counts[i]
11140 / (float)ts.counts
11141 [BGP_STATS_PREFIXES]
11142 : 0);
11143 break;
11144 case BGP_STATS_SPACE:
11145 vty_out(vty, "%-30s: ", table_stats_strs[i]);
8d0ab76d
DL
11146 vty_out(vty, "%12g\n", ts.total_space);
11147
11148 if (afi == AFI_IP6) {
11149 vty_out(vty, "%30s: ", "/32 equivalent ");
11150 vty_out(vty, "%12g\n",
a4d82a8a 11151 ts.total_space * pow(2.0, -128 + 32));
8d0ab76d
DL
11152 vty_out(vty, "%30s: ", "/48 equivalent ");
11153 vty_out(vty, "%12g\n",
a4d82a8a 11154 ts.total_space * pow(2.0, -128 + 48));
8d0ab76d
DL
11155 } else {
11156 vty_out(vty, "%30s: ", "% announced ");
11157 vty_out(vty, "%12.2f\n",
11158 ts.total_space * 100. * pow(2.0, -32));
11159 vty_out(vty, "%30s: ", "/8 equivalent ");
11160 vty_out(vty, "%12.2f\n",
a4d82a8a 11161 ts.total_space * pow(2.0, -32 + 8));
8d0ab76d
DL
11162 vty_out(vty, "%30s: ", "/24 equivalent ");
11163 vty_out(vty, "%12.2f\n",
a4d82a8a 11164 ts.total_space * pow(2.0, -32 + 24));
8d0ab76d 11165 }
d62a17ae 11166 break;
11167 default:
11168 vty_out(vty, "%-30s: ", table_stats_strs[i]);
11169 vty_out(vty, "%12llu", ts.counts[i]);
11170 }
ff7924f6 11171
d62a17ae 11172 vty_out(vty, "\n");
11173 }
11174 return CMD_SUCCESS;
11175}
11176
11177enum bgp_pcounts {
11178 PCOUNT_ADJ_IN = 0,
11179 PCOUNT_DAMPED,
11180 PCOUNT_REMOVED,
11181 PCOUNT_HISTORY,
11182 PCOUNT_STALE,
11183 PCOUNT_VALID,
11184 PCOUNT_ALL,
11185 PCOUNT_COUNTED,
11186 PCOUNT_PFCNT, /* the figure we display to users */
11187 PCOUNT_MAX,
a636c635 11188};
718e3744 11189
2b64873d 11190static const char *const pcount_strs[] = {
9d303b37
DL
11191 [PCOUNT_ADJ_IN] = "Adj-in",
11192 [PCOUNT_DAMPED] = "Damped",
11193 [PCOUNT_REMOVED] = "Removed",
11194 [PCOUNT_HISTORY] = "History",
11195 [PCOUNT_STALE] = "Stale",
11196 [PCOUNT_VALID] = "Valid",
11197 [PCOUNT_ALL] = "All RIB",
11198 [PCOUNT_COUNTED] = "PfxCt counted",
11199 [PCOUNT_PFCNT] = "Useable",
11200 [PCOUNT_MAX] = NULL,
a636c635 11201};
718e3744 11202
d62a17ae 11203struct peer_pcounts {
11204 unsigned int count[PCOUNT_MAX];
11205 const struct peer *peer;
11206 const struct bgp_table *table;
54317cba 11207 safi_t safi;
a636c635 11208};
47fc97cc 11209
54317cba
JW
11210static void bgp_peer_count_proc(struct bgp_node *rn,
11211 struct peer_pcounts *pc)
d62a17ae 11212{
54317cba
JW
11213 const struct bgp_adj_in *ain;
11214 const struct bgp_path_info *pi;
d62a17ae 11215 const struct peer *peer = pc->peer;
11216
54317cba
JW
11217 for (ain = rn->adj_in; ain; ain = ain->next)
11218 if (ain->peer == peer)
11219 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 11220
54317cba 11221 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 11222
54317cba
JW
11223 if (pi->peer != peer)
11224 continue;
d62a17ae 11225
54317cba 11226 pc->count[PCOUNT_ALL]++;
d62a17ae 11227
54317cba
JW
11228 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
11229 pc->count[PCOUNT_DAMPED]++;
11230 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
11231 pc->count[PCOUNT_HISTORY]++;
11232 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
11233 pc->count[PCOUNT_REMOVED]++;
11234 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
11235 pc->count[PCOUNT_STALE]++;
11236 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
11237 pc->count[PCOUNT_VALID]++;
11238 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
11239 pc->count[PCOUNT_PFCNT]++;
11240
11241 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
11242 pc->count[PCOUNT_COUNTED]++;
11243 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
11244 flog_err(
11245 EC_LIB_DEVELOPMENT,
11246 "Attempting to count but flags say it is unusable");
11247 } else {
40381db7 11248 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
11249 flog_err(
11250 EC_LIB_DEVELOPMENT,
11251 "Not counted but flags say we should");
d62a17ae 11252 }
11253 }
54317cba
JW
11254}
11255
11256static int bgp_peer_count_walker(struct thread *t)
11257{
11258 struct bgp_node *rn, *rm;
11259 const struct bgp_table *table;
11260 struct peer_pcounts *pc = THREAD_ARG(t);
11261
11262 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
11263 || pc->safi == SAFI_EVPN) {
11264 /* Special handling for 2-level routing tables. */
11265 for (rn = bgp_table_top(pc->table); rn;
11266 rn = bgp_route_next(rn)) {
11267 table = bgp_node_get_bgp_table_info(rn);
11268 if (table != NULL)
11269 for (rm = bgp_table_top(table); rm;
11270 rm = bgp_route_next(rm))
11271 bgp_peer_count_proc(rm, pc);
11272 }
11273 } else
11274 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
11275 bgp_peer_count_proc(rn, pc);
11276
d62a17ae 11277 return 0;
718e3744 11278}
11279
d62a17ae 11280static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 11281 safi_t safi, bool use_json)
856ca177 11282{
d62a17ae 11283 struct peer_pcounts pcounts = {.peer = peer};
11284 unsigned int i;
11285 json_object *json = NULL;
11286 json_object *json_loop = NULL;
856ca177 11287
d62a17ae 11288 if (use_json) {
11289 json = json_object_new_object();
11290 json_loop = json_object_new_object();
11291 }
718e3744 11292
d62a17ae 11293 if (!peer || !peer->bgp || !peer->afc[afi][safi]
11294 || !peer->bgp->rib[afi][safi]) {
11295 if (use_json) {
11296 json_object_string_add(
11297 json, "warning",
11298 "No such neighbor or address family");
11299 vty_out(vty, "%s\n", json_object_to_json_string(json));
11300 json_object_free(json);
11301 } else
11302 vty_out(vty, "%% No such neighbor or address family\n");
11303
11304 return CMD_WARNING;
11305 }
2a71e9ce 11306
d62a17ae 11307 memset(&pcounts, 0, sizeof(pcounts));
11308 pcounts.peer = peer;
11309 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 11310 pcounts.safi = safi;
d62a17ae 11311
11312 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
11313 * stats for the thread-walk (i.e. ensure this can't be blamed on
11314 * on just vty_read()).
11315 */
d62a17ae 11316 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
11317
11318 if (use_json) {
11319 json_object_string_add(json, "prefixCountsFor", peer->host);
11320 json_object_string_add(json, "multiProtocol",
5cb5f4d0 11321 get_afi_safi_str(afi, safi, true));
d62a17ae 11322 json_object_int_add(json, "pfxCounter",
11323 peer->pcount[afi][safi]);
11324
11325 for (i = 0; i < PCOUNT_MAX; i++)
11326 json_object_int_add(json_loop, pcount_strs[i],
11327 pcounts.count[i]);
11328
11329 json_object_object_add(json, "ribTableWalkCounters", json_loop);
11330
11331 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
11332 json_object_string_add(json, "pfxctDriftFor",
11333 peer->host);
11334 json_object_string_add(
11335 json, "recommended",
11336 "Please report this bug, with the above command output");
11337 }
996c9314
LB
11338 vty_out(vty, "%s\n", json_object_to_json_string_ext(
11339 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 11340 json_object_free(json);
11341 } else {
11342
11343 if (peer->hostname
11344 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
11345 vty_out(vty, "Prefix counts for %s/%s, %s\n",
11346 peer->hostname, peer->host,
5cb5f4d0 11347 get_afi_safi_str(afi, safi, false));
d62a17ae 11348 } else {
11349 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 11350 get_afi_safi_str(afi, safi, false));
d62a17ae 11351 }
11352
a0a87037 11353 vty_out(vty, "PfxCt: %" PRIu32 "\n", peer->pcount[afi][safi]);
d62a17ae 11354 vty_out(vty, "\nCounts from RIB table walk:\n\n");
11355
11356 for (i = 0; i < PCOUNT_MAX; i++)
11357 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
11358 pcounts.count[i]);
11359
11360 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
11361 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
11362 vty_out(vty,
11363 "Please report this bug, with the above command output\n");
11364 }
11365 }
11366
11367 return CMD_SUCCESS;
718e3744 11368}
11369
a636c635
DW
11370DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
11371 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
c1a44e43 11372 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] "
30a6a167 11373 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
718e3744 11374 SHOW_STR
11375 IP_STR
11376 BGP_STR
8386ac43 11377 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
11378 BGP_AFI_HELP_STR
11379 BGP_SAFI_HELP_STR
0b16f239
DS
11380 "Detailed information on TCP and BGP neighbor connections\n"
11381 "Neighbor to display information about\n"
11382 "Neighbor to display information about\n"
91d37724 11383 "Neighbor on BGP configured interface\n"
a636c635 11384 "Display detailed prefix count information\n"
9973d184 11385 JSON_STR)
0b16f239 11386{
d62a17ae 11387 afi_t afi = AFI_IP6;
11388 safi_t safi = SAFI_UNICAST;
11389 struct peer *peer;
11390 int idx = 0;
11391 struct bgp *bgp = NULL;
9f049418
DS
11392 bool uj = use_json(argc, argv);
11393
11394 if (uj)
11395 argc--;
856ca177 11396
d62a17ae 11397 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11398 &bgp, uj);
d62a17ae 11399 if (!idx)
11400 return CMD_WARNING;
0b16f239 11401
d62a17ae 11402 argv_find(argv, argc, "neighbors", &idx);
11403 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
11404 if (!peer)
11405 return CMD_WARNING;
bb46e94f 11406
29c8d9da 11407 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 11408}
0b16f239 11409
d6902373
PG
11410#ifdef KEEP_OLD_VPN_COMMANDS
11411DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
11412 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
11413 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
11414 SHOW_STR
11415 IP_STR
11416 BGP_STR
d6902373 11417 BGP_VPNVX_HELP_STR
91d37724 11418 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
11419 "Detailed information on TCP and BGP neighbor connections\n"
11420 "Neighbor to display information about\n"
11421 "Neighbor to display information about\n"
91d37724 11422 "Neighbor on BGP configured interface\n"
a636c635 11423 "Display detailed prefix count information\n"
9973d184 11424 JSON_STR)
a636c635 11425{
d62a17ae 11426 int idx_peer = 6;
11427 struct peer *peer;
9f049418 11428 bool uj = use_json(argc, argv);
a636c635 11429
d62a17ae 11430 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
11431 if (!peer)
11432 return CMD_WARNING;
11433
11434 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
11435}
11436
d6902373
PG
11437DEFUN (show_ip_bgp_vpn_all_route_prefix,
11438 show_ip_bgp_vpn_all_route_prefix_cmd,
11439 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
11440 SHOW_STR
11441 IP_STR
11442 BGP_STR
d6902373 11443 BGP_VPNVX_HELP_STR
91d37724
QY
11444 "Display information about all VPNv4 NLRIs\n"
11445 "Network in the BGP routing table to display\n"
3a2d747c 11446 "Network in the BGP routing table to display\n"
9973d184 11447 JSON_STR)
91d37724 11448{
d62a17ae 11449 int idx = 0;
11450 char *network = NULL;
11451 struct bgp *bgp = bgp_get_default();
11452 if (!bgp) {
11453 vty_out(vty, "Can't find default instance\n");
11454 return CMD_WARNING;
11455 }
87e34b58 11456
d62a17ae 11457 if (argv_find(argv, argc, "A.B.C.D", &idx))
11458 network = argv[idx]->arg;
11459 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
11460 network = argv[idx]->arg;
11461 else {
11462 vty_out(vty, "Unable to figure out Network\n");
11463 return CMD_WARNING;
11464 }
87e34b58 11465
d62a17ae 11466 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 11467 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 11468}
d6902373 11469#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 11470
44c69747
LK
11471DEFUN (show_bgp_l2vpn_evpn_route_prefix,
11472 show_bgp_l2vpn_evpn_route_prefix_cmd,
11473 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 11474 SHOW_STR
4c63a661
PG
11475 BGP_STR
11476 L2VPN_HELP_STR
11477 EVPN_HELP_STR
44c69747
LK
11478 "Network in the BGP routing table to display\n"
11479 "Network in the BGP routing table to display\n"
4c63a661
PG
11480 "Network in the BGP routing table to display\n"
11481 "Network in the BGP routing table to display\n"
11482 JSON_STR)
11483{
d62a17ae 11484 int idx = 0;
11485 char *network = NULL;
44c69747 11486 int prefix_check = 0;
a636c635 11487
44c69747
LK
11488 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
11489 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 11490 network = argv[idx]->arg;
44c69747 11491 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 11492 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 11493 network = argv[idx]->arg;
44c69747
LK
11494 prefix_check = 1;
11495 } else {
d62a17ae 11496 vty_out(vty, "Unable to figure out Network\n");
11497 return CMD_WARNING;
11498 }
44c69747
LK
11499 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
11500 prefix_check, BGP_PATH_SHOW_ALL,
11501 use_json(argc, argv));
d62a17ae 11502}
11503
11504static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 11505 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 11506 const char *rmap_name, bool use_json,
6392aaa6 11507 json_object *json)
d62a17ae 11508{
11509 struct bgp_table *table;
11510 struct bgp_adj_in *ain;
11511 struct bgp_adj_out *adj;
11512 unsigned long output_count;
11513 unsigned long filtered_count;
11514 struct bgp_node *rn;
11515 int header1 = 1;
11516 struct bgp *bgp;
11517 int header2 = 1;
11518 struct attr attr;
11519 int ret;
11520 struct update_subgroup *subgrp;
11521 json_object *json_scode = NULL;
11522 json_object *json_ocode = NULL;
11523 json_object *json_ar = NULL;
11524 struct peer_af *paf;
f99def61 11525 bool route_filtered;
d62a17ae 11526
11527 if (use_json) {
11528 json_scode = json_object_new_object();
11529 json_ocode = json_object_new_object();
11530 json_ar = json_object_new_object();
11531
11532 json_object_string_add(json_scode, "suppressed", "s");
11533 json_object_string_add(json_scode, "damped", "d");
11534 json_object_string_add(json_scode, "history", "h");
11535 json_object_string_add(json_scode, "valid", "*");
11536 json_object_string_add(json_scode, "best", ">");
11537 json_object_string_add(json_scode, "multipath", "=");
11538 json_object_string_add(json_scode, "internal", "i");
11539 json_object_string_add(json_scode, "ribFailure", "r");
11540 json_object_string_add(json_scode, "stale", "S");
11541 json_object_string_add(json_scode, "removed", "R");
11542
11543 json_object_string_add(json_ocode, "igp", "i");
11544 json_object_string_add(json_ocode, "egp", "e");
11545 json_object_string_add(json_ocode, "incomplete", "?");
11546 }
a636c635 11547
d62a17ae 11548 bgp = peer->bgp;
a636c635 11549
d62a17ae 11550 if (!bgp) {
11551 if (use_json) {
11552 json_object_string_add(json, "alert", "no BGP");
11553 vty_out(vty, "%s\n", json_object_to_json_string(json));
11554 json_object_free(json);
11555 } else
11556 vty_out(vty, "%% No bgp\n");
11557 return;
11558 }
a636c635 11559
c512a642
EDP
11560 /* labeled-unicast routes live in the unicast table */
11561 if (safi == SAFI_LABELED_UNICAST)
11562 table = bgp->rib[afi][SAFI_UNICAST];
11563 else
11564 table = bgp->rib[afi][safi];
d62a17ae 11565
11566 output_count = filtered_count = 0;
11567 subgrp = peer_subgroup(peer, afi, safi);
11568
6392aaa6 11569 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 11570 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
11571 if (use_json) {
11572 json_object_int_add(json, "bgpTableVersion",
11573 table->version);
11574 json_object_string_add(json, "bgpLocalRouterId",
11575 inet_ntoa(bgp->router_id));
01eced22
AD
11576 json_object_int_add(json, "defaultLocPrf",
11577 bgp->default_local_pref);
11578 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 11579 json_object_object_add(json, "bgpStatusCodes",
11580 json_scode);
11581 json_object_object_add(json, "bgpOriginCodes",
11582 json_ocode);
07d0c4ed
DA
11583 json_object_string_add(
11584 json, "bgpOriginatingDefaultNetwork",
11585 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 11586 } else {
996c9314 11587 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 11588 ", local router ID is %s, vrf id ",
d62a17ae 11589 table->version, inet_ntoa(bgp->router_id));
9df8b37c
PZ
11590 if (bgp->vrf_id == VRF_UNKNOWN)
11591 vty_out(vty, "%s", VRFID_NONE_STR);
11592 else
11593 vty_out(vty, "%u", bgp->vrf_id);
11594 vty_out(vty, "\n");
01eced22
AD
11595 vty_out(vty, "Default local pref %u, ",
11596 bgp->default_local_pref);
11597 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 11598 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11599 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 11600 vty_out(vty, BGP_SHOW_OCODE_HEADER);
11601
07d0c4ed
DA
11602 vty_out(vty, "Originating default network %s\n\n",
11603 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 11604 }
11605 header1 = 0;
11606 }
a636c635 11607
d62a17ae 11608 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6392aaa6
PM
11609 if (type == bgp_show_adj_route_received
11610 || type == bgp_show_adj_route_filtered) {
d62a17ae 11611 for (ain = rn->adj_in; ain; ain = ain->next) {
05864da7 11612 if (ain->peer != peer)
ea47320b 11613 continue;
6392aaa6 11614
ea47320b
DL
11615 if (header1) {
11616 if (use_json) {
11617 json_object_int_add(
60466a63 11618 json, "bgpTableVersion",
ea47320b
DL
11619 0);
11620 json_object_string_add(
11621 json,
11622 "bgpLocalRouterId",
11623 inet_ntoa(
11624 bgp->router_id));
01eced22
AD
11625 json_object_int_add(json,
11626 "defaultLocPrf",
11627 bgp->default_local_pref);
11628 json_object_int_add(json,
11629 "localAS", bgp->as);
ea47320b 11630 json_object_object_add(
60466a63 11631 json, "bgpStatusCodes",
ea47320b
DL
11632 json_scode);
11633 json_object_object_add(
60466a63 11634 json, "bgpOriginCodes",
ea47320b
DL
11635 json_ocode);
11636 } else {
11637 vty_out(vty,
9df8b37c 11638 "BGP table version is 0, local router ID is %s, vrf id ",
ea47320b 11639 inet_ntoa(
9df8b37c
PZ
11640 bgp->router_id));
11641 if (bgp->vrf_id == VRF_UNKNOWN)
11642 vty_out(vty, "%s",
11643 VRFID_NONE_STR);
11644 else
11645 vty_out(vty, "%u",
11646 bgp->vrf_id);
11647 vty_out(vty, "\n");
01eced22
AD
11648 vty_out(vty,
11649 "Default local pref %u, ",
11650 bgp->default_local_pref);
11651 vty_out(vty, "local AS %u\n",
11652 bgp->as);
ea47320b
DL
11653 vty_out(vty,
11654 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
11655 vty_out(vty,
11656 BGP_SHOW_NCODE_HEADER);
ea47320b
DL
11657 vty_out(vty,
11658 BGP_SHOW_OCODE_HEADER);
d62a17ae 11659 }
ea47320b
DL
11660 header1 = 0;
11661 }
11662 if (header2) {
11663 if (!use_json)
11664 vty_out(vty, BGP_SHOW_HEADER);
11665 header2 = 0;
11666 }
6392aaa6 11667
6f4f49b2 11668 attr = *ain->attr;
f99def61
AD
11669 route_filtered = false;
11670
11671 /* Filter prefix using distribute list,
11672 * filter list or prefix list
11673 */
11674 if ((bgp_input_filter(peer, &rn->p, &attr, afi,
11675 safi)) == FILTER_DENY)
11676 route_filtered = true;
11677
11678 /* Filter prefix using route-map */
6392aaa6 11679 ret = bgp_input_modifier(peer, &rn->p, &attr,
196c6b09
LK
11680 afi, safi, rmap_name, NULL, 0,
11681 NULL);
6392aaa6 11682
13c8e163
AD
11683 if (type == bgp_show_adj_route_filtered &&
11684 !route_filtered && ret != RMAP_DENY) {
b755861b 11685 bgp_attr_undup(&attr, ain->attr);
6392aaa6 11686 continue;
d62a17ae 11687 }
6392aaa6 11688
13c8e163
AD
11689 if (type == bgp_show_adj_route_received &&
11690 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
11691 filtered_count++;
11692
11693 route_vty_out_tmp(vty, &rn->p, &attr, safi,
11694 use_json, json_ar);
b755861b 11695 bgp_attr_undup(&attr, ain->attr);
6392aaa6 11696 output_count++;
d62a17ae 11697 }
6392aaa6 11698 } else if (type == bgp_show_adj_route_advertised) {
a79c04e7 11699 RB_FOREACH (adj, bgp_adj_out_rb, &rn->adj_out)
924c3f6a 11700 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 11701 if (paf->peer != peer || !adj->attr)
924c3f6a 11702 continue;
d62a17ae 11703
924c3f6a
DS
11704 if (header1) {
11705 if (use_json) {
11706 json_object_int_add(
11707 json,
11708 "bgpTableVersion",
11709 table->version);
11710 json_object_string_add(
11711 json,
11712 "bgpLocalRouterId",
11713 inet_ntoa(
11714 bgp->router_id));
01eced22
AD
11715 json_object_int_add(
11716 json, "defaultLocPrf",
11717 bgp->default_local_pref
11718 );
11719 json_object_int_add(
11720 json, "localAS",
11721 bgp->as);
924c3f6a
DS
11722 json_object_object_add(
11723 json,
11724 "bgpStatusCodes",
11725 json_scode);
11726 json_object_object_add(
11727 json,
11728 "bgpOriginCodes",
11729 json_ocode);
11730 } else {
11731 vty_out(vty,
11732 "BGP table version is %" PRIu64
9df8b37c 11733 ", local router ID is %s, vrf id ",
924c3f6a
DS
11734 table->version,
11735 inet_ntoa(
11736 bgp->router_id));
9df8b37c
PZ
11737 if (bgp->vrf_id ==
11738 VRF_UNKNOWN)
11739 vty_out(vty,
11740 "%s",
11741 VRFID_NONE_STR);
11742 else
11743 vty_out(vty,
11744 "%u",
11745 bgp->vrf_id);
11746 vty_out(vty, "\n");
01eced22
AD
11747 vty_out(vty,
11748 "Default local pref %u, ",
11749 bgp->default_local_pref
11750 );
11751 vty_out(vty,
11752 "local AS %u\n",
11753 bgp->as);
924c3f6a
DS
11754 vty_out(vty,
11755 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
11756 vty_out(vty,
11757 BGP_SHOW_NCODE_HEADER);
924c3f6a
DS
11758 vty_out(vty,
11759 BGP_SHOW_OCODE_HEADER);
a2addae8 11760 }
924c3f6a
DS
11761 header1 = 0;
11762 }
924c3f6a
DS
11763 if (header2) {
11764 if (!use_json)
11765 vty_out(vty,
11766 BGP_SHOW_HEADER);
11767 header2 = 0;
11768 }
d62a17ae 11769
6f4f49b2 11770 attr = *adj->attr;
b755861b
PM
11771 ret = bgp_output_modifier(
11772 peer, &rn->p, &attr, afi, safi,
11773 rmap_name);
f46d8e1e 11774
b755861b
PM
11775 if (ret != RMAP_DENY) {
11776 route_vty_out_tmp(vty, &rn->p,
11777 &attr, safi,
11778 use_json,
11779 json_ar);
11780 output_count++;
11781 } else {
11782 filtered_count++;
a2addae8 11783 }
b755861b
PM
11784
11785 bgp_attr_undup(&attr, adj->attr);
924c3f6a 11786 }
d62a17ae 11787 }
11788 }
d62a17ae 11789
d62a17ae 11790 if (use_json) {
6392aaa6
PM
11791 json_object_object_add(json, "advertisedRoutes", json_ar);
11792 json_object_int_add(json, "totalPrefixCounter", output_count);
11793 json_object_int_add(json, "filteredPrefixCounter",
11794 filtered_count);
11795
996c9314
LB
11796 vty_out(vty, "%s\n", json_object_to_json_string_ext(
11797 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 11798 json_object_free(json);
6392aaa6
PM
11799 } else if (output_count > 0) {
11800 if (filtered_count > 0)
11801 vty_out(vty,
11802 "\nTotal number of prefixes %ld (%ld filtered)\n",
11803 output_count, filtered_count);
11804 else
11805 vty_out(vty, "\nTotal number of prefixes %ld\n",
11806 output_count);
d62a17ae 11807 }
a636c635 11808}
2a71e9ce 11809
d62a17ae 11810static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 11811 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 11812 const char *rmap_name, bool use_json)
0b16f239 11813{
d62a17ae 11814 json_object *json = NULL;
0b16f239 11815
d62a17ae 11816 if (use_json)
11817 json = json_object_new_object();
0b16f239 11818
d62a17ae 11819 if (!peer || !peer->afc[afi][safi]) {
11820 if (use_json) {
11821 json_object_string_add(
11822 json, "warning",
11823 "No such neighbor or address family");
11824 vty_out(vty, "%s\n", json_object_to_json_string(json));
11825 json_object_free(json);
11826 } else
11827 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 11828
d62a17ae 11829 return CMD_WARNING;
11830 }
11831
6392aaa6
PM
11832 if ((type == bgp_show_adj_route_received
11833 || type == bgp_show_adj_route_filtered)
d62a17ae 11834 && !CHECK_FLAG(peer->af_flags[afi][safi],
11835 PEER_FLAG_SOFT_RECONFIG)) {
11836 if (use_json) {
11837 json_object_string_add(
11838 json, "warning",
11839 "Inbound soft reconfiguration not enabled");
11840 vty_out(vty, "%s\n", json_object_to_json_string(json));
11841 json_object_free(json);
11842 } else
11843 vty_out(vty,
11844 "%% Inbound soft reconfiguration not enabled\n");
11845
11846 return CMD_WARNING;
11847 }
0b16f239 11848
6392aaa6 11849 show_adj_route(vty, peer, afi, safi, type, rmap_name, use_json, json);
0b16f239 11850
d62a17ae 11851 return CMD_SUCCESS;
a636c635 11852}
50ef26d4 11853
a636c635
DW
11854DEFUN (show_ip_bgp_instance_neighbor_advertised_route,
11855 show_ip_bgp_instance_neighbor_advertised_route_cmd,
4dd6177e 11856 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
6392aaa6 11857 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
718e3744 11858 SHOW_STR
11859 IP_STR
11860 BGP_STR
a636c635 11861 BGP_INSTANCE_HELP_STR
7395a2c9 11862 BGP_AFI_HELP_STR
4dd6177e 11863 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 11864 "Detailed information on TCP and BGP neighbor connections\n"
11865 "Neighbor to display information about\n"
11866 "Neighbor to display information about\n"
91d37724 11867 "Neighbor on BGP configured interface\n"
a636c635 11868 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
11869 "Display the received routes from neighbor\n"
11870 "Display the filtered routes received from neighbor\n"
a636c635
DW
11871 "Route-map to modify the attributes\n"
11872 "Name of the route map\n"
9973d184 11873 JSON_STR)
718e3744 11874{
d62a17ae 11875 afi_t afi = AFI_IP6;
11876 safi_t safi = SAFI_UNICAST;
11877 char *rmap_name = NULL;
11878 char *peerstr = NULL;
d62a17ae 11879 struct bgp *bgp = NULL;
11880 struct peer *peer;
6392aaa6 11881 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 11882 int idx = 0;
9f049418 11883 bool uj = use_json(argc, argv);
6392aaa6 11884
d62a17ae 11885 if (uj)
11886 argc--;
30a6a167 11887
9f049418
DS
11888 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11889 &bgp, uj);
11890 if (!idx)
11891 return CMD_WARNING;
11892
d62a17ae 11893 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11894 argv_find(argv, argc, "neighbors", &idx);
11895 peerstr = argv[++idx]->arg;
8c3deaae 11896
d62a17ae 11897 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
11898 if (!peer)
11899 return CMD_WARNING;
856ca177 11900
d62a17ae 11901 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
11902 type = bgp_show_adj_route_advertised;
11903 else if (argv_find(argv, argc, "received-routes", &idx))
11904 type = bgp_show_adj_route_received;
11905 else if (argv_find(argv, argc, "filtered-routes", &idx))
11906 type = bgp_show_adj_route_filtered;
11907
d62a17ae 11908 if (argv_find(argv, argc, "route-map", &idx))
11909 rmap_name = argv[++idx]->arg;
95cbbd2a 11910
6392aaa6 11911 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj);
95cbbd2a
ML
11912}
11913
718e3744 11914DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
11915 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 11916 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 11917 SHOW_STR
11918 IP_STR
11919 BGP_STR
8c3deaae
QY
11920 "Address Family\n"
11921 "Address Family\n"
718e3744 11922 "Address Family modifier\n"
11923 "Detailed information on TCP and BGP neighbor connections\n"
11924 "Neighbor to display information about\n"
11925 "Neighbor to display information about\n"
91d37724 11926 "Neighbor on BGP configured interface\n"
718e3744 11927 "Display information received from a BGP neighbor\n"
856ca177 11928 "Display the prefixlist filter\n"
9973d184 11929 JSON_STR)
718e3744 11930{
d62a17ae 11931 afi_t afi = AFI_IP6;
11932 safi_t safi = SAFI_UNICAST;
11933 char *peerstr = NULL;
11934
11935 char name[BUFSIZ];
11936 union sockunion su;
11937 struct peer *peer;
11938 int count, ret;
11939
11940 int idx = 0;
11941
11942 /* show [ip] bgp */
11943 if (argv_find(argv, argc, "ip", &idx))
11944 afi = AFI_IP;
11945 /* [<ipv4|ipv6> [unicast]] */
11946 if (argv_find(argv, argc, "ipv4", &idx))
11947 afi = AFI_IP;
11948 if (argv_find(argv, argc, "ipv6", &idx))
11949 afi = AFI_IP6;
11950 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11951 argv_find(argv, argc, "neighbors", &idx);
11952 peerstr = argv[++idx]->arg;
11953
9f049418 11954 bool uj = use_json(argc, argv);
d62a17ae 11955
11956 ret = str2sockunion(peerstr, &su);
11957 if (ret < 0) {
11958 peer = peer_lookup_by_conf_if(NULL, peerstr);
11959 if (!peer) {
11960 if (uj)
11961 vty_out(vty, "{}\n");
11962 else
11963 vty_out(vty,
11964 "%% Malformed address or name: %s\n",
11965 peerstr);
11966 return CMD_WARNING;
11967 }
11968 } else {
11969 peer = peer_lookup(NULL, &su);
11970 if (!peer) {
11971 if (uj)
11972 vty_out(vty, "{}\n");
11973 else
11974 vty_out(vty, "No peer\n");
11975 return CMD_WARNING;
11976 }
11977 }
718e3744 11978
d62a17ae 11979 sprintf(name, "%s.%d.%d", peer->host, afi, safi);
11980 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
11981 if (count) {
11982 if (!uj)
11983 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 11984 get_afi_safi_str(afi, safi, false));
d62a17ae 11985 prefix_bgp_show_prefix_list(vty, afi, name, uj);
11986 } else {
11987 if (uj)
11988 vty_out(vty, "{}\n");
11989 else
11990 vty_out(vty, "No functional output\n");
11991 }
718e3744 11992
d62a17ae 11993 return CMD_SUCCESS;
11994}
11995
11996static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
11997 afi_t afi, safi_t safi,
9f049418 11998 enum bgp_show_type type, bool use_json)
d62a17ae 11999{
8a893163
DW
12000 /* labeled-unicast routes live in the unicast table */
12001 if (safi == SAFI_LABELED_UNICAST)
12002 safi = SAFI_UNICAST;
12003
d62a17ae 12004 if (!peer || !peer->afc[afi][safi]) {
12005 if (use_json) {
12006 json_object *json_no = NULL;
12007 json_no = json_object_new_object();
12008 json_object_string_add(
12009 json_no, "warning",
12010 "No such neighbor or address family");
12011 vty_out(vty, "%s\n",
12012 json_object_to_json_string(json_no));
12013 json_object_free(json_no);
12014 } else
12015 vty_out(vty, "%% No such neighbor or address family\n");
12016 return CMD_WARNING;
12017 }
47fc97cc 12018
d62a17ae 12019 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json);
718e3744 12020}
12021
dba3c1d3
PG
12022DEFUN (show_ip_bgp_flowspec_routes_detailed,
12023 show_ip_bgp_flowspec_routes_detailed_cmd,
12024 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
12025 SHOW_STR
12026 IP_STR
12027 BGP_STR
12028 BGP_INSTANCE_HELP_STR
12029 BGP_AFI_HELP_STR
12030 "SAFI Flowspec\n"
12031 "Detailed information on flowspec entries\n"
12032 JSON_STR)
12033{
12034 afi_t afi = AFI_IP;
12035 safi_t safi = SAFI_UNICAST;
12036 struct bgp *bgp = NULL;
12037 int idx = 0;
9f049418
DS
12038 bool uj = use_json(argc, argv);
12039
12040 if (uj)
12041 argc--;
dba3c1d3
PG
12042
12043 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12044 &bgp, uj);
dba3c1d3
PG
12045 if (!idx)
12046 return CMD_WARNING;
12047
9f049418 12048 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL, uj);
dba3c1d3
PG
12049}
12050
718e3744 12051DEFUN (show_ip_bgp_neighbor_routes,
12052 show_ip_bgp_neighbor_routes_cmd,
4dd6177e 12053 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
30a6a167 12054 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
50ef26d4 12055 SHOW_STR
12056 IP_STR
12057 BGP_STR
8386ac43 12058 BGP_INSTANCE_HELP_STR
4f280b15 12059 BGP_AFI_HELP_STR
4dd6177e 12060 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 12061 "Detailed information on TCP and BGP neighbor connections\n"
12062 "Neighbor to display information about\n"
12063 "Neighbor to display information about\n"
91d37724 12064 "Neighbor on BGP configured interface\n"
2525cf39 12065 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
12066 "Display the dampened routes received from neighbor\n"
12067 "Display routes learned from neighbor\n"
9973d184 12068 JSON_STR)
718e3744 12069{
d62a17ae 12070 char *peerstr = NULL;
12071 struct bgp *bgp = NULL;
12072 afi_t afi = AFI_IP6;
12073 safi_t safi = SAFI_UNICAST;
12074 struct peer *peer;
12075 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 12076 int idx = 0;
9f049418
DS
12077 bool uj = use_json(argc, argv);
12078
12079 if (uj)
12080 argc--;
bb46e94f 12081
d62a17ae 12082 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12083 &bgp, uj);
d62a17ae 12084 if (!idx)
12085 return CMD_WARNING;
c493f2d8 12086
d62a17ae 12087 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12088 argv_find(argv, argc, "neighbors", &idx);
12089 peerstr = argv[++idx]->arg;
8c3deaae 12090
d62a17ae 12091 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 12092 if (!peer)
d62a17ae 12093 return CMD_WARNING;
bb46e94f 12094
d62a17ae 12095 if (argv_find(argv, argc, "flap-statistics", &idx))
12096 sh_type = bgp_show_type_flap_neighbor;
12097 else if (argv_find(argv, argc, "dampened-routes", &idx))
12098 sh_type = bgp_show_type_damp_neighbor;
12099 else if (argv_find(argv, argc, "routes", &idx))
12100 sh_type = bgp_show_type_neighbor;
2525cf39 12101
d62a17ae 12102 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 12103}
6b0655a2 12104
734b349e 12105struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 12106
d62a17ae 12107struct bgp_distance {
12108 /* Distance value for the IP source prefix. */
d7c0a89a 12109 uint8_t distance;
718e3744 12110
d62a17ae 12111 /* Name of the access-list to be matched. */
12112 char *access_list;
718e3744 12113};
12114
4f280b15
LB
12115DEFUN (show_bgp_afi_vpn_rd_route,
12116 show_bgp_afi_vpn_rd_route_cmd,
d114b977 12117 "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
12118 SHOW_STR
12119 BGP_STR
12120 BGP_AFI_HELP_STR
12121 "Address Family modifier\n"
12122 "Display information for a route distinguisher\n"
12123 "Route Distinguisher\n"
7395a2c9
DS
12124 "Network in the BGP routing table to display\n"
12125 "Network in the BGP routing table to display\n"
12126 JSON_STR)
4f280b15 12127{
d62a17ae 12128 int ret;
12129 struct prefix_rd prd;
12130 afi_t afi = AFI_MAX;
12131 int idx = 0;
4f280b15 12132
ff6566f3
DS
12133 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
12134 vty_out(vty, "%% Malformed Address Family\n");
12135 return CMD_WARNING;
12136 }
12137
d62a17ae 12138 ret = str2prefix_rd(argv[5]->arg, &prd);
12139 if (!ret) {
12140 vty_out(vty, "%% Malformed Route Distinguisher\n");
12141 return CMD_WARNING;
12142 }
ff6566f3 12143
d62a17ae 12144 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 12145 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
12146}
12147
d62a17ae 12148static struct bgp_distance *bgp_distance_new(void)
718e3744 12149{
d62a17ae 12150 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 12151}
12152
d62a17ae 12153static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 12154{
d62a17ae 12155 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 12156}
12157
d62a17ae 12158static int bgp_distance_set(struct vty *vty, const char *distance_str,
12159 const char *ip_str, const char *access_list_str)
718e3744 12160{
d62a17ae 12161 int ret;
12162 afi_t afi;
12163 safi_t safi;
12164 struct prefix p;
d7c0a89a 12165 uint8_t distance;
d62a17ae 12166 struct bgp_node *rn;
12167 struct bgp_distance *bdistance;
718e3744 12168
d62a17ae 12169 afi = bgp_node_afi(vty);
12170 safi = bgp_node_safi(vty);
734b349e 12171
d62a17ae 12172 ret = str2prefix(ip_str, &p);
12173 if (ret == 0) {
12174 vty_out(vty, "Malformed prefix\n");
12175 return CMD_WARNING_CONFIG_FAILED;
12176 }
718e3744 12177
d62a17ae 12178 distance = atoi(distance_str);
718e3744 12179
d62a17ae 12180 /* Get BGP distance node. */
12181 rn = bgp_node_get(bgp_distance_table[afi][safi], (struct prefix *)&p);
5b00b40e 12182 bdistance = bgp_node_get_bgp_distance_info(rn);
ca2e160d 12183 if (bdistance)
d62a17ae 12184 bgp_unlock_node(rn);
ca2e160d 12185 else {
d62a17ae 12186 bdistance = bgp_distance_new();
5b00b40e 12187 bgp_node_set_bgp_distance_info(rn, bdistance);
d62a17ae 12188 }
718e3744 12189
d62a17ae 12190 /* Set distance value. */
12191 bdistance->distance = distance;
718e3744 12192
d62a17ae 12193 /* Reset access-list configuration. */
12194 if (bdistance->access_list) {
12195 XFREE(MTYPE_AS_LIST, bdistance->access_list);
12196 bdistance->access_list = NULL;
12197 }
12198 if (access_list_str)
12199 bdistance->access_list =
12200 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 12201
d62a17ae 12202 return CMD_SUCCESS;
718e3744 12203}
12204
d62a17ae 12205static int bgp_distance_unset(struct vty *vty, const char *distance_str,
12206 const char *ip_str, const char *access_list_str)
718e3744 12207{
d62a17ae 12208 int ret;
12209 afi_t afi;
12210 safi_t safi;
12211 struct prefix p;
12212 int distance;
12213 struct bgp_node *rn;
12214 struct bgp_distance *bdistance;
718e3744 12215
d62a17ae 12216 afi = bgp_node_afi(vty);
12217 safi = bgp_node_safi(vty);
734b349e 12218
d62a17ae 12219 ret = str2prefix(ip_str, &p);
12220 if (ret == 0) {
12221 vty_out(vty, "Malformed prefix\n");
12222 return CMD_WARNING_CONFIG_FAILED;
12223 }
718e3744 12224
d62a17ae 12225 rn = bgp_node_lookup(bgp_distance_table[afi][safi],
12226 (struct prefix *)&p);
12227 if (!rn) {
12228 vty_out(vty, "Can't find specified prefix\n");
12229 return CMD_WARNING_CONFIG_FAILED;
12230 }
718e3744 12231
5b00b40e 12232 bdistance = bgp_node_get_bgp_distance_info(rn);
d62a17ae 12233 distance = atoi(distance_str);
1f9a9fff 12234
d62a17ae 12235 if (bdistance->distance != distance) {
12236 vty_out(vty, "Distance does not match configured\n");
12237 return CMD_WARNING_CONFIG_FAILED;
12238 }
718e3744 12239
0a22ddfb 12240 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 12241 bgp_distance_free(bdistance);
718e3744 12242
6f94b685 12243 bgp_node_set_bgp_path_info(rn, NULL);
d62a17ae 12244 bgp_unlock_node(rn);
12245 bgp_unlock_node(rn);
718e3744 12246
d62a17ae 12247 return CMD_SUCCESS;
718e3744 12248}
12249
718e3744 12250/* Apply BGP information to distance method. */
40381db7 12251uint8_t bgp_distance_apply(struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 12252 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 12253{
12254 struct bgp_node *rn;
12255 struct prefix q;
12256 struct peer *peer;
12257 struct bgp_distance *bdistance;
12258 struct access_list *alist;
12259 struct bgp_static *bgp_static;
12260
12261 if (!bgp)
12262 return 0;
12263
40381db7 12264 peer = pinfo->peer;
d62a17ae 12265
7b7d48e5
DS
12266 if (pinfo->attr->distance)
12267 return pinfo->attr->distance;
12268
d62a17ae 12269 /* Check source address. */
12270 sockunion2hostprefix(&peer->su, &q);
12271 rn = bgp_node_match(bgp_distance_table[afi][safi], &q);
12272 if (rn) {
5b00b40e 12273 bdistance = bgp_node_get_bgp_distance_info(rn);
d62a17ae 12274 bgp_unlock_node(rn);
12275
12276 if (bdistance->access_list) {
12277 alist = access_list_lookup(afi, bdistance->access_list);
12278 if (alist
12279 && access_list_apply(alist, p) == FILTER_PERMIT)
12280 return bdistance->distance;
12281 } else
12282 return bdistance->distance;
718e3744 12283 }
718e3744 12284
d62a17ae 12285 /* Backdoor check. */
12286 rn = bgp_node_lookup(bgp->route[afi][safi], p);
12287 if (rn) {
5a8ba9fc 12288 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 12289 bgp_unlock_node(rn);
718e3744 12290
d62a17ae 12291 if (bgp_static->backdoor) {
12292 if (bgp->distance_local[afi][safi])
12293 return bgp->distance_local[afi][safi];
12294 else
12295 return ZEBRA_IBGP_DISTANCE_DEFAULT;
12296 }
718e3744 12297 }
718e3744 12298
d62a17ae 12299 if (peer->sort == BGP_PEER_EBGP) {
12300 if (bgp->distance_ebgp[afi][safi])
12301 return bgp->distance_ebgp[afi][safi];
12302 return ZEBRA_EBGP_DISTANCE_DEFAULT;
12303 } else {
12304 if (bgp->distance_ibgp[afi][safi])
12305 return bgp->distance_ibgp[afi][safi];
12306 return ZEBRA_IBGP_DISTANCE_DEFAULT;
12307 }
718e3744 12308}
12309
a612fb77
DA
12310/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
12311 * we should tell ZEBRA update the routes for a specific
12312 * AFI/SAFI to reflect changes in RIB.
12313 */
8b54bc30
DA
12314static void bgp_announce_routes_distance_update(struct bgp *bgp,
12315 afi_t update_afi,
12316 safi_t update_safi)
a612fb77
DA
12317{
12318 afi_t afi;
12319 safi_t safi;
12320
12321 FOREACH_AFI_SAFI (afi, safi) {
12322 if (!bgp_fibupd_safi(safi))
12323 continue;
12324
8b54bc30
DA
12325 if (afi != update_afi && safi != update_safi)
12326 continue;
12327
12328 if (BGP_DEBUG(zebra, ZEBRA))
12329 zlog_debug(
12330 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
12331 __func__, afi, safi);
12332 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
12333 }
12334}
12335
718e3744 12336DEFUN (bgp_distance,
12337 bgp_distance_cmd,
6147e2c6 12338 "distance bgp (1-255) (1-255) (1-255)",
718e3744 12339 "Define an administrative distance\n"
12340 "BGP distance\n"
12341 "Distance for routes external to the AS\n"
12342 "Distance for routes internal to the AS\n"
12343 "Distance for local routes\n")
12344{
d62a17ae 12345 VTY_DECLVAR_CONTEXT(bgp, bgp);
12346 int idx_number = 2;
12347 int idx_number_2 = 3;
12348 int idx_number_3 = 4;
8b54bc30
DA
12349 int distance_ebgp = atoi(argv[idx_number]->arg);
12350 int distance_ibgp = atoi(argv[idx_number_2]->arg);
12351 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 12352 afi_t afi;
12353 safi_t safi;
718e3744 12354
d62a17ae 12355 afi = bgp_node_afi(vty);
12356 safi = bgp_node_safi(vty);
718e3744 12357
8b54bc30
DA
12358 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
12359 || bgp->distance_ibgp[afi][safi] != distance_ibgp
12360 || bgp->distance_local[afi][safi] != distance_local) {
12361 bgp->distance_ebgp[afi][safi] = distance_ebgp;
12362 bgp->distance_ibgp[afi][safi] = distance_ibgp;
12363 bgp->distance_local[afi][safi] = distance_local;
12364 bgp_announce_routes_distance_update(bgp, afi, safi);
12365 }
d62a17ae 12366 return CMD_SUCCESS;
718e3744 12367}
12368
12369DEFUN (no_bgp_distance,
12370 no_bgp_distance_cmd,
a636c635 12371 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 12372 NO_STR
12373 "Define an administrative distance\n"
12374 "BGP distance\n"
12375 "Distance for routes external to the AS\n"
12376 "Distance for routes internal to the AS\n"
12377 "Distance for local routes\n")
12378{
d62a17ae 12379 VTY_DECLVAR_CONTEXT(bgp, bgp);
12380 afi_t afi;
12381 safi_t safi;
718e3744 12382
d62a17ae 12383 afi = bgp_node_afi(vty);
12384 safi = bgp_node_safi(vty);
718e3744 12385
8b54bc30
DA
12386 if (bgp->distance_ebgp[afi][safi] != 0
12387 || bgp->distance_ibgp[afi][safi] != 0
12388 || bgp->distance_local[afi][safi] != 0) {
12389 bgp->distance_ebgp[afi][safi] = 0;
12390 bgp->distance_ibgp[afi][safi] = 0;
12391 bgp->distance_local[afi][safi] = 0;
12392 bgp_announce_routes_distance_update(bgp, afi, safi);
12393 }
d62a17ae 12394 return CMD_SUCCESS;
718e3744 12395}
12396
718e3744 12397
12398DEFUN (bgp_distance_source,
12399 bgp_distance_source_cmd,
6147e2c6 12400 "distance (1-255) A.B.C.D/M",
718e3744 12401 "Define an administrative distance\n"
12402 "Administrative distance\n"
12403 "IP source prefix\n")
12404{
d62a17ae 12405 int idx_number = 1;
12406 int idx_ipv4_prefixlen = 2;
12407 bgp_distance_set(vty, argv[idx_number]->arg,
12408 argv[idx_ipv4_prefixlen]->arg, NULL);
12409 return CMD_SUCCESS;
718e3744 12410}
12411
12412DEFUN (no_bgp_distance_source,
12413 no_bgp_distance_source_cmd,
6147e2c6 12414 "no distance (1-255) A.B.C.D/M",
718e3744 12415 NO_STR
12416 "Define an administrative distance\n"
12417 "Administrative distance\n"
12418 "IP source prefix\n")
12419{
d62a17ae 12420 int idx_number = 2;
12421 int idx_ipv4_prefixlen = 3;
12422 bgp_distance_unset(vty, argv[idx_number]->arg,
12423 argv[idx_ipv4_prefixlen]->arg, NULL);
12424 return CMD_SUCCESS;
718e3744 12425}
12426
12427DEFUN (bgp_distance_source_access_list,
12428 bgp_distance_source_access_list_cmd,
6147e2c6 12429 "distance (1-255) A.B.C.D/M WORD",
718e3744 12430 "Define an administrative distance\n"
12431 "Administrative distance\n"
12432 "IP source prefix\n"
12433 "Access list name\n")
12434{
d62a17ae 12435 int idx_number = 1;
12436 int idx_ipv4_prefixlen = 2;
12437 int idx_word = 3;
12438 bgp_distance_set(vty, argv[idx_number]->arg,
12439 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12440 return CMD_SUCCESS;
718e3744 12441}
12442
12443DEFUN (no_bgp_distance_source_access_list,
12444 no_bgp_distance_source_access_list_cmd,
6147e2c6 12445 "no distance (1-255) A.B.C.D/M WORD",
718e3744 12446 NO_STR
12447 "Define an administrative distance\n"
12448 "Administrative distance\n"
12449 "IP source prefix\n"
12450 "Access list name\n")
12451{
d62a17ae 12452 int idx_number = 2;
12453 int idx_ipv4_prefixlen = 3;
12454 int idx_word = 4;
12455 bgp_distance_unset(vty, argv[idx_number]->arg,
12456 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12457 return CMD_SUCCESS;
718e3744 12458}
6b0655a2 12459
734b349e
MZ
12460DEFUN (ipv6_bgp_distance_source,
12461 ipv6_bgp_distance_source_cmd,
39e92c06 12462 "distance (1-255) X:X::X:X/M",
734b349e
MZ
12463 "Define an administrative distance\n"
12464 "Administrative distance\n"
12465 "IP source prefix\n")
12466{
d62a17ae 12467 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
12468 return CMD_SUCCESS;
734b349e
MZ
12469}
12470
12471DEFUN (no_ipv6_bgp_distance_source,
12472 no_ipv6_bgp_distance_source_cmd,
39e92c06 12473 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
12474 NO_STR
12475 "Define an administrative distance\n"
12476 "Administrative distance\n"
12477 "IP source prefix\n")
12478{
d62a17ae 12479 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
12480 return CMD_SUCCESS;
734b349e
MZ
12481}
12482
12483DEFUN (ipv6_bgp_distance_source_access_list,
12484 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12485 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12486 "Define an administrative distance\n"
12487 "Administrative distance\n"
12488 "IP source prefix\n"
12489 "Access list name\n")
12490{
d62a17ae 12491 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
12492 return CMD_SUCCESS;
734b349e
MZ
12493}
12494
12495DEFUN (no_ipv6_bgp_distance_source_access_list,
12496 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12497 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12498 NO_STR
12499 "Define an administrative distance\n"
12500 "Administrative distance\n"
12501 "IP source prefix\n"
12502 "Access list name\n")
12503{
d62a17ae 12504 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
12505 return CMD_SUCCESS;
734b349e
MZ
12506}
12507
718e3744 12508DEFUN (bgp_damp_set,
12509 bgp_damp_set_cmd,
31500417 12510 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 12511 "BGP Specific commands\n"
12512 "Enable route-flap dampening\n"
12513 "Half-life time for the penalty\n"
12514 "Value to start reusing a route\n"
12515 "Value to start suppressing a route\n"
12516 "Maximum duration to suppress a stable route\n")
12517{
d62a17ae 12518 VTY_DECLVAR_CONTEXT(bgp, bgp);
12519 int idx_half_life = 2;
12520 int idx_reuse = 3;
12521 int idx_suppress = 4;
12522 int idx_max_suppress = 5;
12523 int half = DEFAULT_HALF_LIFE * 60;
12524 int reuse = DEFAULT_REUSE;
12525 int suppress = DEFAULT_SUPPRESS;
12526 int max = 4 * half;
12527
12528 if (argc == 6) {
12529 half = atoi(argv[idx_half_life]->arg) * 60;
12530 reuse = atoi(argv[idx_reuse]->arg);
12531 suppress = atoi(argv[idx_suppress]->arg);
12532 max = atoi(argv[idx_max_suppress]->arg) * 60;
12533 } else if (argc == 3) {
12534 half = atoi(argv[idx_half_life]->arg) * 60;
12535 max = 4 * half;
12536 }
718e3744 12537
6d24b7cc
DS
12538 /*
12539 * These can't be 0 but our SA doesn't understand the
12540 * way our cli is constructed
12541 */
12542 assert(reuse);
12543 assert(half);
d62a17ae 12544 if (suppress < reuse) {
12545 vty_out(vty,
12546 "Suppress value cannot be less than reuse value \n");
12547 return 0;
12548 }
7ebe9748 12549
d62a17ae 12550 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
12551 reuse, suppress, max);
718e3744 12552}
12553
718e3744 12554DEFUN (bgp_damp_unset,
12555 bgp_damp_unset_cmd,
d04c479d 12556 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 12557 NO_STR
12558 "BGP Specific commands\n"
16cedbb0
QY
12559 "Enable route-flap dampening\n"
12560 "Half-life time for the penalty\n"
12561 "Value to start reusing a route\n"
12562 "Value to start suppressing a route\n"
12563 "Maximum duration to suppress a stable route\n")
718e3744 12564{
d62a17ae 12565 VTY_DECLVAR_CONTEXT(bgp, bgp);
12566 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 12567}
12568
718e3744 12569/* Display specified route of BGP table. */
d62a17ae 12570static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
12571 const char *ip_str, afi_t afi, safi_t safi,
12572 struct prefix_rd *prd, int prefix_check)
12573{
12574 int ret;
12575 struct prefix match;
12576 struct bgp_node *rn;
12577 struct bgp_node *rm;
40381db7
DS
12578 struct bgp_path_info *pi;
12579 struct bgp_path_info *pi_temp;
d62a17ae 12580 struct bgp *bgp;
12581 struct bgp_table *table;
12582
12583 /* BGP structure lookup. */
12584 if (view_name) {
12585 bgp = bgp_lookup_by_name(view_name);
12586 if (bgp == NULL) {
12587 vty_out(vty, "%% Can't find BGP instance %s\n",
12588 view_name);
12589 return CMD_WARNING;
12590 }
12591 } else {
12592 bgp = bgp_get_default();
12593 if (bgp == NULL) {
12594 vty_out(vty, "%% No BGP process is configured\n");
12595 return CMD_WARNING;
12596 }
718e3744 12597 }
718e3744 12598
d62a17ae 12599 /* Check IP address argument. */
12600 ret = str2prefix(ip_str, &match);
12601 if (!ret) {
12602 vty_out(vty, "%% address is malformed\n");
12603 return CMD_WARNING;
12604 }
718e3744 12605
d62a17ae 12606 match.family = afi2family(afi);
12607
12608 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
12609 || (safi == SAFI_EVPN)) {
12610 for (rn = bgp_table_top(bgp->rib[AFI_IP][safi]); rn;
12611 rn = bgp_route_next(rn)) {
12612 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
12613 continue;
67009e22
DS
12614 table = bgp_node_get_bgp_table_info(rn);
12615 if (!table)
ea47320b
DL
12616 continue;
12617 if ((rm = bgp_node_match(table, &match)) == NULL)
12618 continue;
d62a17ae 12619
ea47320b
DL
12620 if (!prefix_check
12621 || rm->p.prefixlen == match.prefixlen) {
6f94b685 12622 pi = bgp_node_get_bgp_path_info(rm);
40381db7
DS
12623 while (pi) {
12624 if (pi->extra && pi->extra->damp_info) {
12625 pi_temp = pi->next;
ea47320b 12626 bgp_damp_info_free(
40381db7 12627 pi->extra->damp_info,
a935f597 12628 1, afi, safi);
40381db7 12629 pi = pi_temp;
ea47320b 12630 } else
40381db7 12631 pi = pi->next;
d62a17ae 12632 }
ea47320b
DL
12633 }
12634
12635 bgp_unlock_node(rm);
d62a17ae 12636 }
12637 } else {
12638 if ((rn = bgp_node_match(bgp->rib[afi][safi], &match))
12639 != NULL) {
12640 if (!prefix_check
12641 || rn->p.prefixlen == match.prefixlen) {
6f94b685 12642 pi = bgp_node_get_bgp_path_info(rn);
40381db7
DS
12643 while (pi) {
12644 if (pi->extra && pi->extra->damp_info) {
12645 pi_temp = pi->next;
d62a17ae 12646 bgp_damp_info_free(
40381db7 12647 pi->extra->damp_info,
a935f597 12648 1, afi, safi);
40381db7 12649 pi = pi_temp;
d62a17ae 12650 } else
40381db7 12651 pi = pi->next;
d62a17ae 12652 }
12653 }
12654
12655 bgp_unlock_node(rn);
12656 }
12657 }
718e3744 12658
d62a17ae 12659 return CMD_SUCCESS;
718e3744 12660}
12661
12662DEFUN (clear_ip_bgp_dampening,
12663 clear_ip_bgp_dampening_cmd,
12664 "clear ip bgp dampening",
12665 CLEAR_STR
12666 IP_STR
12667 BGP_STR
12668 "Clear route flap dampening information\n")
12669{
a935f597 12670 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 12671 return CMD_SUCCESS;
718e3744 12672}
12673
12674DEFUN (clear_ip_bgp_dampening_prefix,
12675 clear_ip_bgp_dampening_prefix_cmd,
12676 "clear ip bgp dampening A.B.C.D/M",
12677 CLEAR_STR
12678 IP_STR
12679 BGP_STR
12680 "Clear route flap dampening information\n"
0c7b1b01 12681 "IPv4 prefix\n")
718e3744 12682{
d62a17ae 12683 int idx_ipv4_prefixlen = 4;
12684 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
12685 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 12686}
12687
12688DEFUN (clear_ip_bgp_dampening_address,
12689 clear_ip_bgp_dampening_address_cmd,
12690 "clear ip bgp dampening A.B.C.D",
12691 CLEAR_STR
12692 IP_STR
12693 BGP_STR
12694 "Clear route flap dampening information\n"
12695 "Network to clear damping information\n")
12696{
d62a17ae 12697 int idx_ipv4 = 4;
12698 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
12699 SAFI_UNICAST, NULL, 0);
718e3744 12700}
12701
12702DEFUN (clear_ip_bgp_dampening_address_mask,
12703 clear_ip_bgp_dampening_address_mask_cmd,
12704 "clear ip bgp dampening A.B.C.D A.B.C.D",
12705 CLEAR_STR
12706 IP_STR
12707 BGP_STR
12708 "Clear route flap dampening information\n"
12709 "Network to clear damping information\n"
12710 "Network mask\n")
12711{
d62a17ae 12712 int idx_ipv4 = 4;
12713 int idx_ipv4_2 = 5;
12714 int ret;
12715 char prefix_str[BUFSIZ];
718e3744 12716
d62a17ae 12717 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
12718 prefix_str);
12719 if (!ret) {
12720 vty_out(vty, "%% Inconsistent address and mask\n");
12721 return CMD_WARNING;
12722 }
718e3744 12723
d62a17ae 12724 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
12725 NULL, 0);
718e3744 12726}
6b0655a2 12727
e3b78da8 12728static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
12729{
12730 struct vty *vty = arg;
e3b78da8 12731 struct peer *peer = bucket->data;
825d9834
DS
12732 char buf[SU_ADDRSTRLEN];
12733
12734 vty_out(vty, "\tPeer: %s %s\n", peer->host,
12735 sockunion2str(&peer->su, buf, sizeof(buf)));
12736}
12737
12738DEFUN (show_bgp_peerhash,
12739 show_bgp_peerhash_cmd,
12740 "show bgp peerhash",
12741 SHOW_STR
12742 BGP_STR
12743 "Display information about the BGP peerhash\n")
12744{
12745 struct list *instances = bm->bgp;
12746 struct listnode *node;
12747 struct bgp *bgp;
12748
12749 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
12750 vty_out(vty, "BGP: %s\n", bgp->name);
12751 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
12752 vty);
12753 }
12754
12755 return CMD_SUCCESS;
12756}
12757
587ff0fd 12758/* also used for encap safi */
2b791107
DL
12759static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
12760 afi_t afi, safi_t safi)
d62a17ae 12761{
12762 struct bgp_node *prn;
12763 struct bgp_node *rn;
12764 struct bgp_table *table;
12765 struct prefix *p;
12766 struct prefix_rd *prd;
12767 struct bgp_static *bgp_static;
12768 mpls_label_t label;
12769 char buf[SU_ADDRSTRLEN];
12770 char rdbuf[RD_ADDRSTRLEN];
12771
12772 /* Network configuration. */
12773 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b 12774 prn = bgp_route_next(prn)) {
67009e22
DS
12775 table = bgp_node_get_bgp_table_info(prn);
12776 if (!table)
ea47320b 12777 continue;
d62a17ae 12778
60466a63 12779 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5a8ba9fc 12780 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12781 if (bgp_static == NULL)
ea47320b 12782 continue;
d62a17ae 12783
ea47320b
DL
12784 p = &rn->p;
12785 prd = (struct prefix_rd *)&prn->p;
d62a17ae 12786
ea47320b 12787 /* "network" configuration display. */
06b9f471 12788 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
12789 label = decode_label(&bgp_static->label);
12790
12791 vty_out(vty, " network %s/%d rd %s",
12792 inet_ntop(p->family, &p->u.prefix, buf,
12793 SU_ADDRSTRLEN),
12794 p->prefixlen, rdbuf);
12795 if (safi == SAFI_MPLS_VPN)
12796 vty_out(vty, " label %u", label);
12797
12798 if (bgp_static->rmap.name)
12799 vty_out(vty, " route-map %s",
12800 bgp_static->rmap.name);
e2a86ad9
DS
12801
12802 if (bgp_static->backdoor)
12803 vty_out(vty, " backdoor");
12804
ea47320b
DL
12805 vty_out(vty, "\n");
12806 }
12807 }
d62a17ae 12808}
12809
2b791107
DL
12810static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
12811 afi_t afi, safi_t safi)
d62a17ae 12812{
12813 struct bgp_node *prn;
12814 struct bgp_node *rn;
12815 struct bgp_table *table;
12816 struct prefix *p;
12817 struct prefix_rd *prd;
12818 struct bgp_static *bgp_static;
ff44f570 12819 char buf[PREFIX_STRLEN * 2];
d62a17ae 12820 char buf2[SU_ADDRSTRLEN];
12821 char rdbuf[RD_ADDRSTRLEN];
12822
12823 /* Network configuration. */
12824 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b 12825 prn = bgp_route_next(prn)) {
67009e22
DS
12826 table = bgp_node_get_bgp_table_info(prn);
12827 if (!table)
ea47320b 12828 continue;
d62a17ae 12829
60466a63 12830 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5a8ba9fc 12831 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12832 if (bgp_static == NULL)
ea47320b 12833 continue;
d62a17ae 12834
ea47320b
DL
12835 char *macrouter = NULL;
12836 char *esi = NULL;
d62a17ae 12837
ea47320b
DL
12838 if (bgp_static->router_mac)
12839 macrouter = prefix_mac2str(
12840 bgp_static->router_mac, NULL, 0);
12841 if (bgp_static->eth_s_id)
12842 esi = esi2str(bgp_static->eth_s_id);
12843 p = &rn->p;
12844 prd = (struct prefix_rd *)&prn->p;
d62a17ae 12845
ea47320b 12846 /* "network" configuration display. */
06b9f471 12847 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
12848 if (p->u.prefix_evpn.route_type == 5) {
12849 char local_buf[PREFIX_STRLEN];
3714a385 12850 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
12851 struct prefix_evpn *)p)
12852 ? AF_INET
12853 : AF_INET6;
3714a385 12854 inet_ntop(family,
12855 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a
PZ
12856 local_buf, PREFIX_STRLEN);
12857 sprintf(buf, "%s/%u", local_buf,
3714a385 12858 p->u.prefix_evpn.prefix_addr.ip_prefix_length);
197cb530
PG
12859 } else {
12860 prefix2str(p, buf, sizeof(buf));
12861 }
ea47320b 12862
a4d82a8a
PZ
12863 if (bgp_static->gatewayIp.family == AF_INET
12864 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
12865 inet_ntop(bgp_static->gatewayIp.family,
12866 &bgp_static->gatewayIp.u.prefix, buf2,
12867 sizeof(buf2));
ea47320b 12868 vty_out(vty,
7bcc8dac 12869 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 12870 buf, rdbuf,
12871 p->u.prefix_evpn.prefix_addr.eth_tag,
60466a63 12872 decode_label(&bgp_static->label), esi, buf2,
ea47320b
DL
12873 macrouter);
12874
0a22ddfb
QY
12875 XFREE(MTYPE_TMP, macrouter);
12876 XFREE(MTYPE_TMP, esi);
ea47320b
DL
12877 }
12878 }
3da6fcd5
PG
12879}
12880
718e3744 12881/* Configuration of static route announcement and aggregate
12882 information. */
2b791107
DL
12883void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
12884 safi_t safi)
d62a17ae 12885{
12886 struct bgp_node *rn;
12887 struct prefix *p;
12888 struct bgp_static *bgp_static;
12889 struct bgp_aggregate *bgp_aggregate;
12890 char buf[SU_ADDRSTRLEN];
12891
2b791107
DL
12892 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
12893 bgp_config_write_network_vpn(vty, bgp, afi, safi);
12894 return;
12895 }
d62a17ae 12896
2b791107
DL
12897 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
12898 bgp_config_write_network_evpn(vty, bgp, afi, safi);
12899 return;
12900 }
d62a17ae 12901
12902 /* Network configuration. */
12903 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
ea47320b 12904 rn = bgp_route_next(rn)) {
5a8ba9fc 12905 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12906 if (bgp_static == NULL)
ea47320b 12907 continue;
d62a17ae 12908
ea47320b 12909 p = &rn->p;
d62a17ae 12910
d8a9922d
DS
12911 vty_out(vty, " network %s/%d",
12912 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
12913 p->prefixlen);
d62a17ae 12914
ea47320b
DL
12915 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
12916 vty_out(vty, " label-index %u",
12917 bgp_static->label_index);
d62a17ae 12918
ea47320b
DL
12919 if (bgp_static->rmap.name)
12920 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
12921
12922 if (bgp_static->backdoor)
12923 vty_out(vty, " backdoor");
718e3744 12924
ea47320b
DL
12925 vty_out(vty, "\n");
12926 }
12927
d62a17ae 12928 /* Aggregate-address configuration. */
12929 for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn;
ea47320b 12930 rn = bgp_route_next(rn)) {
b613a918 12931 bgp_aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 12932 if (bgp_aggregate == NULL)
ea47320b 12933 continue;
d62a17ae 12934
ea47320b 12935 p = &rn->p;
d62a17ae 12936
d8a9922d
DS
12937 vty_out(vty, " aggregate-address %s/%d",
12938 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
12939 p->prefixlen);
d62a17ae 12940
ea47320b
DL
12941 if (bgp_aggregate->as_set)
12942 vty_out(vty, " as-set");
d62a17ae 12943
ea47320b
DL
12944 if (bgp_aggregate->summary_only)
12945 vty_out(vty, " summary-only");
718e3744 12946
20894f50
DA
12947 if (bgp_aggregate->rmap.name)
12948 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
12949
ea47320b
DL
12950 vty_out(vty, "\n");
12951 }
d62a17ae 12952}
734b349e 12953
2b791107 12954void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 12955 safi_t safi)
d62a17ae 12956{
12957 struct bgp_node *rn;
12958 struct bgp_distance *bdistance;
12959
12960 /* Distance configuration. */
12961 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
12962 && bgp->distance_local[afi][safi]
12963 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
12964 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
12965 || bgp->distance_local[afi][safi]
12966 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 12967 vty_out(vty, " distance bgp %d %d %d\n",
12968 bgp->distance_ebgp[afi][safi],
12969 bgp->distance_ibgp[afi][safi],
12970 bgp->distance_local[afi][safi]);
12971 }
734b349e 12972
d62a17ae 12973 for (rn = bgp_table_top(bgp_distance_table[afi][safi]); rn;
ca2e160d 12974 rn = bgp_route_next(rn)) {
5b00b40e 12975 bdistance = bgp_node_get_bgp_distance_info(rn);
ca2e160d 12976 if (bdistance != NULL) {
d62a17ae 12977 char buf[PREFIX_STRLEN];
12978
d62a17ae 12979 vty_out(vty, " distance %d %s %s\n",
12980 bdistance->distance,
12981 prefix2str(&rn->p, buf, sizeof(buf)),
12982 bdistance->access_list ? bdistance->access_list
12983 : "");
12984 }
ca2e160d 12985 }
718e3744 12986}
12987
12988/* Allocate routing table structure and install commands. */
d62a17ae 12989void bgp_route_init(void)
12990{
12991 afi_t afi;
12992 safi_t safi;
12993
12994 /* Init BGP distance table. */
05c7a1cc 12995 FOREACH_AFI_SAFI (afi, safi)
960035b2 12996 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 12997
12998 /* IPv4 BGP commands. */
12999 install_element(BGP_NODE, &bgp_table_map_cmd);
13000 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 13001 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 13002
13003 install_element(BGP_NODE, &aggregate_address_cmd);
13004 install_element(BGP_NODE, &aggregate_address_mask_cmd);
13005 install_element(BGP_NODE, &no_aggregate_address_cmd);
13006 install_element(BGP_NODE, &no_aggregate_address_mask_cmd);
13007
13008 /* IPv4 unicast configuration. */
13009 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
13010 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 13011 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 13012
13013 install_element(BGP_IPV4_NODE, &aggregate_address_cmd);
13014 install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd);
13015 install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd);
13016 install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
13017
13018 /* IPv4 multicast configuration. */
13019 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
13020 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 13021 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
d62a17ae 13022 install_element(BGP_IPV4M_NODE, &aggregate_address_cmd);
13023 install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
13024 install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd);
13025 install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
13026
13027 /* IPv4 labeled-unicast configuration. */
13028 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
13029 install_element(VIEW_NODE, &show_ip_bgp_cmd);
7b2ff250 13030 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 13031 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
13032 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
13033
13034 install_element(VIEW_NODE,
13035 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
13036 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
13037 install_element(VIEW_NODE,
13038 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 13039#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 13040 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 13041#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 13042 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
13043 install_element(VIEW_NODE,
44c69747 13044 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 13045
d62a17ae 13046 /* BGP dampening clear commands */
13047 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
13048 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 13049
d62a17ae 13050 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
13051 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
13052
13053 /* prefix count */
13054 install_element(ENABLE_NODE,
13055 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 13056#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 13057 install_element(ENABLE_NODE,
13058 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 13059#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 13060
d62a17ae 13061 /* New config IPv6 BGP commands. */
13062 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
13063 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 13064 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 13065
13066 install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
13067 install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
13068
13069 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 13070
d62a17ae 13071 install_element(BGP_NODE, &bgp_distance_cmd);
13072 install_element(BGP_NODE, &no_bgp_distance_cmd);
13073 install_element(BGP_NODE, &bgp_distance_source_cmd);
13074 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
13075 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
13076 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
13077 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
13078 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
13079 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
13080 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
13081 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
13082 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
13083 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
13084 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
13085 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
13086 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
13087 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
13088 install_element(BGP_IPV4M_NODE,
13089 &no_bgp_distance_source_access_list_cmd);
13090 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
13091 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
13092 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
13093 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
13094 install_element(BGP_IPV6_NODE,
13095 &ipv6_bgp_distance_source_access_list_cmd);
13096 install_element(BGP_IPV6_NODE,
13097 &no_ipv6_bgp_distance_source_access_list_cmd);
13098 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
13099 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
13100 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
13101 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
13102 install_element(BGP_IPV6M_NODE,
13103 &ipv6_bgp_distance_source_access_list_cmd);
13104 install_element(BGP_IPV6M_NODE,
13105 &no_ipv6_bgp_distance_source_access_list_cmd);
13106
13107 install_element(BGP_NODE, &bgp_damp_set_cmd);
13108 install_element(BGP_NODE, &bgp_damp_unset_cmd);
13109 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
13110 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
13111
13112 /* IPv4 Multicast Mode */
13113 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
13114 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
13115
13116 /* Large Communities */
13117 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
13118 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
13119
13120 /* show bgp ipv4 flowspec detailed */
13121 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
13122
825d9834 13123 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 13124}
13125
13126void bgp_route_finish(void)
13127{
13128 afi_t afi;
13129 safi_t safi;
13130
05c7a1cc
QY
13131 FOREACH_AFI_SAFI (afi, safi) {
13132 bgp_table_unlock(bgp_distance_table[afi][safi]);
13133 bgp_distance_table[afi][safi] = NULL;
13134 }
228da428 13135}