]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #3543 from donaldsharp/eigrp_router_id_is_the_bee
[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
25#include "prefix.h"
26#include "linklist.h"
27#include "memory.h"
28#include "command.h"
29#include "stream.h"
30#include "filter.h"
718e3744 31#include "log.h"
32#include "routemap.h"
33#include "buffer.h"
34#include "sockunion.h"
35#include "plist.h"
36#include "thread.h"
200df115 37#include "workqueue.h"
3f9c7369 38#include "queue.h"
6e919709 39#include "memory.h"
4dcadbef 40#include "lib/json.h"
d8d084d9 41#include "lib_errors.h"
718e3744 42
43#include "bgpd/bgpd.h"
44#include "bgpd/bgp_table.h"
45#include "bgpd/bgp_route.h"
46#include "bgpd/bgp_attr.h"
47#include "bgpd/bgp_debug.h"
14454c9f 48#include "bgpd/bgp_errors.h"
718e3744 49#include "bgpd/bgp_aspath.h"
50#include "bgpd/bgp_regex.h"
51#include "bgpd/bgp_community.h"
52#include "bgpd/bgp_ecommunity.h"
57d187bc 53#include "bgpd/bgp_lcommunity.h"
718e3744 54#include "bgpd/bgp_clist.h"
55#include "bgpd/bgp_packet.h"
56#include "bgpd/bgp_filter.h"
57#include "bgpd/bgp_fsm.h"
58#include "bgpd/bgp_mplsvpn.h"
59#include "bgpd/bgp_nexthop.h"
60#include "bgpd/bgp_damp.h"
61#include "bgpd/bgp_advertise.h"
62#include "bgpd/bgp_zebra.h"
0a486e5f 63#include "bgpd/bgp_vty.h"
96450faf 64#include "bgpd/bgp_mpath.h"
fc9a856f 65#include "bgpd/bgp_nht.h"
3f9c7369 66#include "bgpd/bgp_updgrp.h"
cd1964ff 67#include "bgpd/bgp_label.h"
dcc68b5e 68#include "bgpd/bgp_addpath.h"
718e3744 69
65efcfce 70#if ENABLE_BGP_VNC
f8b6f499
LB
71#include "bgpd/rfapi/rfapi_backend.h"
72#include "bgpd/rfapi/vnc_import_bgp.h"
73#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 74#endif
aee875b5
PG
75#include "bgpd/bgp_encap_types.h"
76#include "bgpd/bgp_encap_tlv.h"
684a7227 77#include "bgpd/bgp_evpn.h"
3da6fcd5 78#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 79#include "bgpd/bgp_flowspec.h"
98a9dbc7 80#include "bgpd/bgp_flowspec_util.h"
45918cfb 81#include "bgpd/bgp_pbr.h"
65efcfce 82
e2a86ad9
DS
83#ifndef VTYSH_EXTRACT_PL
84#include "bgpd/bgp_route_clippy.c"
85#endif
aee875b5 86
718e3744 87/* Extern from bgp_dump.c */
dde72586
SH
88extern const char *bgp_origin_str[];
89extern const char *bgp_origin_long_str[];
6b0655a2 90
b7d08f5a 91/* PMSI strings. */
92#define PMSI_TNLTYPE_STR_NO_INFO "No info"
93#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
94static const struct message bgp_pmsi_tnltype_str[] = {
95 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
96 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
97 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
98 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
99 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
100 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
101 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
102 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 103 {0}
104};
b7d08f5a 105
9df8b37c
PZ
106#define VRFID_NONE_STR "-"
107
d62a17ae 108struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
109 safi_t safi, struct prefix *p,
110 struct prefix_rd *prd)
111{
112 struct bgp_node *rn;
113 struct bgp_node *prn = NULL;
114
115 assert(table);
116 if (!table)
117 return NULL;
118
119 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
120 || (safi == SAFI_EVPN)) {
121 prn = bgp_node_get(table, (struct prefix *)prd);
122
67009e22
DS
123 if (!bgp_node_has_bgp_path_info_data(prn))
124 bgp_node_set_bgp_table_info(
125 prn, bgp_table_init(table->bgp, afi, safi));
d62a17ae 126 else
127 bgp_unlock_node(prn);
67009e22 128 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 129 }
718e3744 130
d62a17ae 131 rn = bgp_node_get(table, p);
718e3744 132
d62a17ae 133 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
134 || (safi == SAFI_EVPN))
135 rn->prn = prn;
718e3744 136
d62a17ae 137 return rn;
718e3744 138}
6b0655a2 139
d62a17ae 140struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
141 safi_t safi, struct prefix *p,
142 struct prefix_rd *prd)
128ea8ab 143{
d62a17ae 144 struct bgp_node *rn;
145 struct bgp_node *prn = NULL;
128ea8ab 146
d62a17ae 147 if (!table)
148 return NULL;
128ea8ab 149
d62a17ae 150 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
151 || (safi == SAFI_EVPN)) {
152 prn = bgp_node_lookup(table, (struct prefix *)prd);
153 if (!prn)
154 return NULL;
128ea8ab 155
6f94b685 156 if (!bgp_node_has_bgp_path_info_data(prn)) {
d62a17ae 157 bgp_unlock_node(prn);
158 return NULL;
159 }
128ea8ab 160
67009e22 161 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 162 }
128ea8ab 163
d62a17ae 164 rn = bgp_node_lookup(table, p);
128ea8ab 165
d62a17ae 166 return rn;
128ea8ab 167}
168
18ee8310
DS
169/* Allocate bgp_path_info_extra */
170static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 171{
4b7e6066
DS
172 struct bgp_path_info_extra *new;
173 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
174 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
175 new->label[0] = MPLS_INVALID_LABEL;
176 new->num_labels = 0;
d62a17ae 177 return new;
fb982c25
PJ
178}
179
a2e219fe 180void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 181{
4b7e6066 182 struct bgp_path_info_extra *e;
d62a17ae 183
c93a3b77
DS
184 if (!extra || !*extra)
185 return;
d62a17ae 186
c93a3b77
DS
187 e = *extra;
188 if (e->damp_info)
189 bgp_damp_info_free(e->damp_info, 0);
d62a17ae 190
c93a3b77
DS
191 e->damp_info = NULL;
192 if (e->parent) {
40381db7 193 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 194
40381db7 195 if (bpi->net) {
0e70e6c8
DL
196 /* FIXME: since multiple e may have the same e->parent
197 * and e->parent->net is holding a refcount for each
198 * of them, we need to do some fudging here.
199 *
40381db7
DS
200 * WARNING: if bpi->net->lock drops to 0, bpi may be
201 * freed as well (because bpi->net was holding the
202 * last reference to bpi) => write after free!
0e70e6c8
DL
203 */
204 unsigned refcount;
205
40381db7
DS
206 bpi = bgp_path_info_lock(bpi);
207 refcount = bpi->net->lock - 1;
208 bgp_unlock_node((struct bgp_node *)bpi->net);
0e70e6c8 209 if (!refcount)
40381db7
DS
210 bpi->net = NULL;
211 bgp_path_info_unlock(bpi);
0e70e6c8 212 }
18ee8310 213 bgp_path_info_unlock(e->parent);
c93a3b77 214 e->parent = NULL;
d62a17ae 215 }
c93a3b77
DS
216
217 if (e->bgp_orig)
218 bgp_unlock(e->bgp_orig);
c26edcda
PG
219
220 if ((*extra)->bgp_fs_pbr)
6a154c88 221 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77
DS
222 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
223
224 *extra = NULL;
fb982c25
PJ
225}
226
18ee8310
DS
227/* Get bgp_path_info extra information for the given bgp_path_info, lazy
228 * allocated if required.
fb982c25 229 */
40381db7 230struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 231{
40381db7
DS
232 if (!pi->extra)
233 pi->extra = bgp_path_info_extra_new();
234 return pi->extra;
fb982c25
PJ
235}
236
65efcfce 237/* Allocate new bgp info structure. */
18ee8310 238struct bgp_path_info *bgp_path_info_new(void)
65efcfce 239{
4b7e6066 240 return XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
65efcfce
LB
241}
242
718e3744 243/* Free bgp route information. */
9b6d8fcf 244static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 245{
9b6d8fcf
DS
246 if (path->attr)
247 bgp_attr_unintern(&path->attr);
fb018d25 248
9b6d8fcf
DS
249 bgp_unlink_nexthop(path);
250 bgp_path_info_extra_free(&path->extra);
251 bgp_path_info_mpath_free(&path->mpath);
dcc68b5e
MS
252 bgp_addpath_free_info_data(&path->tx_addpath,
253 path->net ? &path->net->tx_addpath : NULL);
718e3744 254
9b6d8fcf 255 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 256
9b6d8fcf 257 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 258}
259
9b6d8fcf 260struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 261{
9b6d8fcf
DS
262 path->lock++;
263 return path;
200df115 264}
265
9b6d8fcf 266struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 267{
9b6d8fcf
DS
268 assert(path && path->lock > 0);
269 path->lock--;
d62a17ae 270
9b6d8fcf 271 if (path->lock == 0) {
200df115 272#if 0
273 zlog_debug ("%s: unlocked and freeing", __func__);
274 zlog_backtrace (LOG_DEBUG);
275#endif
9b6d8fcf 276 bgp_path_info_free(path);
d62a17ae 277 return NULL;
278 }
200df115 279
280#if 0
9b6d8fcf 281 if (path->lock == 1)
200df115 282 {
283 zlog_debug ("%s: unlocked to 1", __func__);
284 zlog_backtrace (LOG_DEBUG);
285 }
286#endif
d62a17ae 287
9b6d8fcf 288 return path;
200df115 289}
290
40381db7 291void bgp_path_info_add(struct bgp_node *rn, struct bgp_path_info *pi)
718e3744 292{
4b7e6066 293 struct bgp_path_info *top;
718e3744 294
6f94b685 295 top = bgp_node_get_bgp_path_info(rn);
d62a17ae 296
6f94b685 297 pi->next = top;
40381db7 298 pi->prev = NULL;
d62a17ae 299 if (top)
40381db7 300 top->prev = pi;
6f94b685 301 bgp_node_set_bgp_path_info(rn, pi);
d62a17ae 302
40381db7 303 bgp_path_info_lock(pi);
d62a17ae 304 bgp_lock_node(rn);
40381db7 305 peer_lock(pi->peer); /* bgp_path_info peer reference */
718e3744 306}
307
d62a17ae 308/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 309 completion callback *only* */
40381db7 310void bgp_path_info_reap(struct bgp_node *rn, struct bgp_path_info *pi)
718e3744 311{
40381db7
DS
312 if (pi->next)
313 pi->next->prev = pi->prev;
314 if (pi->prev)
315 pi->prev->next = pi->next;
d62a17ae 316 else
6f94b685 317 bgp_node_set_bgp_path_info(rn, pi->next);
d62a17ae 318
40381db7
DS
319 bgp_path_info_mpath_dequeue(pi);
320 bgp_path_info_unlock(pi);
d62a17ae 321 bgp_unlock_node(rn);
718e3744 322}
323
40381db7 324void bgp_path_info_delete(struct bgp_node *rn, struct bgp_path_info *pi)
b40d939b 325{
40381db7 326 bgp_path_info_set_flag(rn, pi, BGP_PATH_REMOVED);
d62a17ae 327 /* set of previous already took care of pcount */
40381db7 328 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 329}
330
18ee8310 331/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
332 called when a route is deleted and then quickly re-added before the
333 deletion has been processed */
40381db7 334void bgp_path_info_restore(struct bgp_node *rn, struct bgp_path_info *pi)
8d45210e 335{
40381db7 336 bgp_path_info_unset_flag(rn, pi, BGP_PATH_REMOVED);
d62a17ae 337 /* unset of previous already took care of pcount */
40381db7 338 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
339}
340
d62a17ae 341/* Adjust pcount as required */
40381db7 342static void bgp_pcount_adjust(struct bgp_node *rn, struct bgp_path_info *pi)
1a392d46 343{
d62a17ae 344 struct bgp_table *table;
67174041 345
d62a17ae 346 assert(rn && bgp_node_table(rn));
40381db7 347 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 348
d62a17ae 349 table = bgp_node_table(rn);
67174041 350
40381db7 351 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 352 return;
353
40381db7
DS
354 if (!BGP_PATH_COUNTABLE(pi)
355 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 356
40381db7 357 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 358
359 /* slight hack, but more robust against errors. */
40381db7
DS
360 if (pi->peer->pcount[table->afi][table->safi])
361 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 362 else
450971aa 363 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 364 "Asked to decrement 0 prefix count for peer");
40381db7
DS
365 } else if (BGP_PATH_COUNTABLE(pi)
366 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
367 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
368 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 369 }
1a392d46
PJ
370}
371
40381db7
DS
372static int bgp_label_index_differs(struct bgp_path_info *pi1,
373 struct bgp_path_info *pi2)
28d58fd7 374{
40381db7 375 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 376}
1a392d46 377
18ee8310 378/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
379 * This is here primarily to keep prefix-count in check.
380 */
40381db7 381void bgp_path_info_set_flag(struct bgp_node *rn, struct bgp_path_info *pi,
18ee8310 382 uint32_t flag)
1a392d46 383{
40381db7 384 SET_FLAG(pi->flags, flag);
d62a17ae 385
386 /* early bath if we know it's not a flag that changes countability state
387 */
388 if (!CHECK_FLAG(flag,
1defdda8 389 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 390 return;
391
40381db7 392 bgp_pcount_adjust(rn, pi);
1a392d46
PJ
393}
394
40381db7 395void bgp_path_info_unset_flag(struct bgp_node *rn, struct bgp_path_info *pi,
18ee8310 396 uint32_t flag)
1a392d46 397{
40381db7 398 UNSET_FLAG(pi->flags, flag);
d62a17ae 399
400 /* early bath if we know it's not a flag that changes countability state
401 */
402 if (!CHECK_FLAG(flag,
1defdda8 403 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 404 return;
405
40381db7 406 bgp_pcount_adjust(rn, pi);
1a392d46
PJ
407}
408
718e3744 409/* Get MED value. If MED value is missing and "bgp bestpath
410 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 411static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 412{
413 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
414 return attr->med;
415 else {
416 if (bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST))
417 return BGP_MED_MAX;
418 else
419 return 0;
420 }
718e3744 421}
422
40381db7 423void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf)
2ec1e66f 424{
40381db7
DS
425 if (pi->addpath_rx_id)
426 sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
427 pi->addpath_rx_id);
d62a17ae 428 else
40381db7 429 sprintf(buf, "path %s", pi->peer->host);
d62a17ae 430}
9fbdd100 431
d62a17ae 432/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
433 */
18ee8310
DS
434static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
435 struct bgp_path_info *exist, int *paths_eq,
436 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
437 char *pfx_buf, afi_t afi, safi_t safi)
d62a17ae 438{
439 struct attr *newattr, *existattr;
440 bgp_peer_sort_t new_sort;
441 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
442 uint32_t new_pref;
443 uint32_t exist_pref;
444 uint32_t new_med;
445 uint32_t exist_med;
446 uint32_t new_weight;
447 uint32_t exist_weight;
d62a17ae 448 uint32_t newm, existm;
449 struct in_addr new_id;
450 struct in_addr exist_id;
451 int new_cluster;
452 int exist_cluster;
453 int internal_as_route;
454 int confed_as_route;
04d14c8b 455 int ret = 0;
d62a17ae 456 char new_buf[PATH_ADDPATH_STR_BUFFER];
457 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
458 uint32_t new_mm_seq;
459 uint32_t exist_mm_seq;
6d8c603a 460 int nh_cmp;
d62a17ae 461
462 *paths_eq = 0;
463
464 /* 0. Null check. */
465 if (new == NULL) {
466 if (debug)
467 zlog_debug("%s: new is NULL", pfx_buf);
468 return 0;
469 }
2ec1e66f 470
d62a17ae 471 if (debug)
18ee8310 472 bgp_path_info_path_with_addpath_rx_str(new, new_buf);
718e3744 473
d62a17ae 474 if (exist == NULL) {
475 if (debug)
476 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
477 new_buf);
478 return 1;
479 }
2ec1e66f 480
d62a17ae 481 if (debug) {
18ee8310 482 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
d62a17ae 483 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
484 pfx_buf, new_buf, new->flags, exist_buf,
485 exist->flags);
486 }
8ff56318 487
d62a17ae 488 newattr = new->attr;
489 existattr = exist->attr;
490
491 /* For EVPN routes, we cannot just go by local vs remote, we have to
492 * look at the MAC mobility sequence number, if present.
493 */
494 if (safi == SAFI_EVPN) {
495 /* This is an error condition described in RFC 7432 Section
496 * 15.2. The RFC
497 * states that in this scenario "the PE MUST alert the operator"
498 * but it
499 * does not state what other action to take. In order to provide
500 * some
501 * consistency in this scenario we are going to prefer the path
502 * with the
503 * sticky flag.
504 */
505 if (newattr->sticky != existattr->sticky) {
506 if (!debug) {
507 prefix2str(&new->net->p, pfx_buf,
508 sizeof(*pfx_buf)
509 * PREFIX2STR_BUFFER);
18ee8310
DS
510 bgp_path_info_path_with_addpath_rx_str(new,
511 new_buf);
512 bgp_path_info_path_with_addpath_rx_str(
513 exist, exist_buf);
d62a17ae 514 }
515
516 if (newattr->sticky && !existattr->sticky) {
deff24ca
DS
517 if (debug)
518 zlog_debug(
519 "%s: %s wins over %s due to sticky MAC flag",
520 pfx_buf, new_buf, exist_buf);
d62a17ae 521 return 1;
522 }
523
524 if (!newattr->sticky && existattr->sticky) {
deff24ca
DS
525 if (debug)
526 zlog_debug(
527 "%s: %s loses to %s due to sticky MAC flag",
528 pfx_buf, new_buf, exist_buf);
d62a17ae 529 return 0;
530 }
531 }
128ea8ab 532
d62a17ae 533 new_mm_seq = mac_mobility_seqnum(newattr);
534 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 535
d62a17ae 536 if (new_mm_seq > exist_mm_seq) {
537 if (debug)
538 zlog_debug(
539 "%s: %s wins over %s due to MM seq %u > %u",
540 pfx_buf, new_buf, exist_buf, new_mm_seq,
541 exist_mm_seq);
542 return 1;
543 }
8ff56318 544
d62a17ae 545 if (new_mm_seq < exist_mm_seq) {
546 if (debug)
547 zlog_debug(
548 "%s: %s loses to %s due to MM seq %u < %u",
549 pfx_buf, new_buf, exist_buf, new_mm_seq,
550 exist_mm_seq);
551 return 0;
552 }
6d8c603a
AK
553
554 /*
555 * if sequence numbers are the same path with the lowest IP
556 * wins
557 */
558 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
559 if (nh_cmp < 0) {
560 if (debug)
561 zlog_debug(
562 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
563 pfx_buf, new_buf, exist_buf, new_mm_seq,
564 inet_ntoa(new->attr->nexthop));
565 return 1;
566 }
567 if (nh_cmp > 0) {
568 if (debug)
569 zlog_debug(
570 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
571 pfx_buf, new_buf, exist_buf, new_mm_seq,
572 inet_ntoa(new->attr->nexthop));
573 return 0;
574 }
d62a17ae 575 }
9fbdd100 576
d62a17ae 577 /* 1. Weight check. */
d62a17ae 578 new_weight = newattr->weight;
579 exist_weight = existattr->weight;
8ff56318 580
d62a17ae 581 if (new_weight > exist_weight) {
582 if (debug)
583 zlog_debug("%s: %s wins over %s due to weight %d > %d",
584 pfx_buf, new_buf, exist_buf, new_weight,
585 exist_weight);
586 return 1;
587 }
718e3744 588
d62a17ae 589 if (new_weight < exist_weight) {
590 if (debug)
591 zlog_debug("%s: %s loses to %s due to weight %d < %d",
592 pfx_buf, new_buf, exist_buf, new_weight,
593 exist_weight);
594 return 0;
595 }
9fbdd100 596
d62a17ae 597 /* 2. Local preference check. */
598 new_pref = exist_pref = bgp->default_local_pref;
599
600 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
601 new_pref = newattr->local_pref;
602 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
603 exist_pref = existattr->local_pref;
604
605 if (new_pref > exist_pref) {
606 if (debug)
607 zlog_debug(
608 "%s: %s wins over %s due to localpref %d > %d",
609 pfx_buf, new_buf, exist_buf, new_pref,
610 exist_pref);
611 return 1;
612 }
718e3744 613
d62a17ae 614 if (new_pref < exist_pref) {
615 if (debug)
616 zlog_debug(
617 "%s: %s loses to %s due to localpref %d < %d",
618 pfx_buf, new_buf, exist_buf, new_pref,
619 exist_pref);
620 return 0;
621 }
9fbdd100 622
d62a17ae 623 /* 3. Local route check. We prefer:
624 * - BGP_ROUTE_STATIC
625 * - BGP_ROUTE_AGGREGATE
626 * - BGP_ROUTE_REDISTRIBUTE
627 */
90f4f482 628 if (!(new->sub_type == BGP_ROUTE_NORMAL ||
629 new->sub_type == BGP_ROUTE_IMPORTED)) {
d62a17ae 630 if (debug)
631 zlog_debug(
632 "%s: %s wins over %s due to preferred BGP_ROUTE type",
633 pfx_buf, new_buf, exist_buf);
634 return 1;
635 }
718e3744 636
90f4f482 637 if (!(exist->sub_type == BGP_ROUTE_NORMAL ||
88493076 638 exist->sub_type == BGP_ROUTE_IMPORTED)) {
d62a17ae 639 if (debug)
640 zlog_debug(
641 "%s: %s loses to %s due to preferred BGP_ROUTE type",
642 pfx_buf, new_buf, exist_buf);
643 return 0;
6811845b 644 }
718e3744 645
d62a17ae 646 /* 4. AS path length check. */
647 if (!bgp_flag_check(bgp, BGP_FLAG_ASPATH_IGNORE)) {
648 int exist_hops = aspath_count_hops(existattr->aspath);
649 int exist_confeds = aspath_count_confeds(existattr->aspath);
650
651 if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_CONFED)) {
652 int aspath_hops;
653
654 aspath_hops = aspath_count_hops(newattr->aspath);
655 aspath_hops += aspath_count_confeds(newattr->aspath);
656
657 if (aspath_hops < (exist_hops + exist_confeds)) {
658 if (debug)
659 zlog_debug(
660 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
661 pfx_buf, new_buf, exist_buf,
662 aspath_hops,
663 (exist_hops + exist_confeds));
664 return 1;
665 }
666
667 if (aspath_hops > (exist_hops + exist_confeds)) {
668 if (debug)
669 zlog_debug(
670 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
671 pfx_buf, new_buf, exist_buf,
672 aspath_hops,
673 (exist_hops + exist_confeds));
674 return 0;
675 }
676 } else {
677 int newhops = aspath_count_hops(newattr->aspath);
678
679 if (newhops < exist_hops) {
680 if (debug)
681 zlog_debug(
682 "%s: %s wins over %s due to aspath hopcount %d < %d",
683 pfx_buf, new_buf, exist_buf,
684 newhops, exist_hops);
685 return 1;
686 }
687
688 if (newhops > exist_hops) {
689 if (debug)
690 zlog_debug(
691 "%s: %s loses to %s due to aspath hopcount %d > %d",
692 pfx_buf, new_buf, exist_buf,
693 newhops, exist_hops);
694 return 0;
695 }
696 }
697 }
9fbdd100 698
d62a17ae 699 /* 5. Origin check. */
700 if (newattr->origin < existattr->origin) {
701 if (debug)
702 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
703 pfx_buf, new_buf, exist_buf,
704 bgp_origin_long_str[newattr->origin],
705 bgp_origin_long_str[existattr->origin]);
706 return 1;
707 }
718e3744 708
d62a17ae 709 if (newattr->origin > existattr->origin) {
710 if (debug)
711 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
712 pfx_buf, new_buf, exist_buf,
713 bgp_origin_long_str[newattr->origin],
714 bgp_origin_long_str[existattr->origin]);
715 return 0;
716 }
718e3744 717
d62a17ae 718 /* 6. MED check. */
719 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
720 && aspath_count_hops(existattr->aspath) == 0);
721 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
722 && aspath_count_confeds(existattr->aspath) > 0
723 && aspath_count_hops(newattr->aspath) == 0
724 && aspath_count_hops(existattr->aspath) == 0);
725
726 if (bgp_flag_check(bgp, BGP_FLAG_ALWAYS_COMPARE_MED)
727 || (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED) && confed_as_route)
728 || aspath_cmp_left(newattr->aspath, existattr->aspath)
729 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
730 || internal_as_route) {
731 new_med = bgp_med_value(new->attr, bgp);
732 exist_med = bgp_med_value(exist->attr, bgp);
733
734 if (new_med < exist_med) {
735 if (debug)
736 zlog_debug(
737 "%s: %s wins over %s due to MED %d < %d",
738 pfx_buf, new_buf, exist_buf, new_med,
739 exist_med);
740 return 1;
741 }
8ff56318 742
d62a17ae 743 if (new_med > exist_med) {
744 if (debug)
745 zlog_debug(
746 "%s: %s loses to %s due to MED %d > %d",
747 pfx_buf, new_buf, exist_buf, new_med,
748 exist_med);
749 return 0;
750 }
751 }
9fbdd100 752
d62a17ae 753 /* 7. Peer type check. */
754 new_sort = new->peer->sort;
755 exist_sort = exist->peer->sort;
756
757 if (new_sort == BGP_PEER_EBGP
758 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
759 if (debug)
760 zlog_debug(
761 "%s: %s wins over %s due to eBGP peer > iBGP peer",
762 pfx_buf, new_buf, exist_buf);
763 return 1;
764 }
718e3744 765
d62a17ae 766 if (exist_sort == BGP_PEER_EBGP
767 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
768 if (debug)
769 zlog_debug(
770 "%s: %s loses to %s due to iBGP peer < eBGP peer",
771 pfx_buf, new_buf, exist_buf);
772 return 0;
773 }
8ff56318 774
d62a17ae 775 /* 8. IGP metric check. */
776 newm = existm = 0;
8ff56318 777
d62a17ae 778 if (new->extra)
779 newm = new->extra->igpmetric;
780 if (exist->extra)
781 existm = exist->extra->igpmetric;
9fbdd100 782
d62a17ae 783 if (newm < existm) {
784 if (debug)
785 zlog_debug(
786 "%s: %s wins over %s due to IGP metric %d < %d",
787 pfx_buf, new_buf, exist_buf, newm, existm);
788 ret = 1;
789 }
718e3744 790
d62a17ae 791 if (newm > existm) {
792 if (debug)
793 zlog_debug(
794 "%s: %s loses to %s due to IGP metric %d > %d",
795 pfx_buf, new_buf, exist_buf, newm, existm);
796 ret = 0;
5e242b0d 797 }
5e242b0d 798
d62a17ae 799 /* 9. Same IGP metric. Compare the cluster list length as
800 representative of IGP hops metric. Rewrite the metric value
801 pair (newm, existm) with the cluster list length. Prefer the
802 path with smaller cluster list length. */
803 if (newm == existm) {
804 if (peer_sort(new->peer) == BGP_PEER_IBGP
805 && peer_sort(exist->peer) == BGP_PEER_IBGP
806 && (mpath_cfg == NULL
807 || CHECK_FLAG(
808 mpath_cfg->ibgp_flags,
809 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
810 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
811 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
812
813 if (newm < existm) {
814 if (debug)
815 zlog_debug(
816 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
817 pfx_buf, new_buf, exist_buf,
818 newm, existm);
819 ret = 1;
820 }
821
822 if (newm > existm) {
823 if (debug)
824 zlog_debug(
825 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
826 pfx_buf, new_buf, exist_buf,
827 newm, existm);
828 ret = 0;
829 }
830 }
831 }
31a4638f 832
d62a17ae 833 /* 10. confed-external vs. confed-internal */
834 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
835 if (new_sort == BGP_PEER_CONFED
836 && exist_sort == BGP_PEER_IBGP) {
837 if (debug)
838 zlog_debug(
839 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
840 pfx_buf, new_buf, exist_buf);
841 return 1;
842 }
718e3744 843
d62a17ae 844 if (exist_sort == BGP_PEER_CONFED
845 && new_sort == BGP_PEER_IBGP) {
846 if (debug)
847 zlog_debug(
848 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
849 pfx_buf, new_buf, exist_buf);
850 return 0;
851 }
852 }
718e3744 853
d62a17ae 854 /* 11. Maximum path check. */
855 if (newm == existm) {
856 /* If one path has a label but the other does not, do not treat
857 * them as equals for multipath
858 */
a4d82a8a 859 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 860 != (exist->extra
b57ba6d2 861 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 862 if (debug)
863 zlog_debug(
864 "%s: %s and %s cannot be multipath, one has a label while the other does not",
865 pfx_buf, new_buf, exist_buf);
866 } else if (bgp_flag_check(bgp,
867 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
868
869 /*
870 * For the two paths, all comparison steps till IGP
871 * metric
872 * have succeeded - including AS_PATH hop count. Since
873 * 'bgp
874 * bestpath as-path multipath-relax' knob is on, we
875 * don't need
876 * an exact match of AS_PATH. Thus, mark the paths are
877 * equal.
878 * That will trigger both these paths to get into the
879 * multipath
880 * array.
881 */
882 *paths_eq = 1;
883
884 if (debug)
885 zlog_debug(
886 "%s: %s and %s are equal via multipath-relax",
887 pfx_buf, new_buf, exist_buf);
888 } else if (new->peer->sort == BGP_PEER_IBGP) {
889 if (aspath_cmp(new->attr->aspath,
890 exist->attr->aspath)) {
891 *paths_eq = 1;
892
893 if (debug)
894 zlog_debug(
895 "%s: %s and %s are equal via matching aspaths",
896 pfx_buf, new_buf, exist_buf);
897 }
898 } else if (new->peer->as == exist->peer->as) {
899 *paths_eq = 1;
900
901 if (debug)
902 zlog_debug(
903 "%s: %s and %s are equal via same remote-as",
904 pfx_buf, new_buf, exist_buf);
905 }
906 } else {
907 /*
908 * TODO: If unequal cost ibgp multipath is enabled we can
909 * mark the paths as equal here instead of returning
910 */
911 if (debug) {
912 if (ret == 1)
913 zlog_debug(
914 "%s: %s wins over %s after IGP metric comparison",
915 pfx_buf, new_buf, exist_buf);
916 else
917 zlog_debug(
918 "%s: %s loses to %s after IGP metric comparison",
919 pfx_buf, new_buf, exist_buf);
920 }
921 return ret;
922 }
718e3744 923
d62a17ae 924 /* 12. If both paths are external, prefer the path that was received
925 first (the oldest one). This step minimizes route-flap, since a
926 newer path won't displace an older one, even if it was the
927 preferred route based on the additional decision criteria below. */
928 if (!bgp_flag_check(bgp, BGP_FLAG_COMPARE_ROUTER_ID)
929 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 930 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
d62a17ae 931 if (debug)
932 zlog_debug(
933 "%s: %s wins over %s due to oldest external",
934 pfx_buf, new_buf, exist_buf);
935 return 1;
936 }
9fbdd100 937
1defdda8 938 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
d62a17ae 939 if (debug)
940 zlog_debug(
941 "%s: %s loses to %s due to oldest external",
942 pfx_buf, new_buf, exist_buf);
943 return 0;
944 }
945 }
718e3744 946
d62a17ae 947 /* 13. Router-ID comparision. */
948 /* If one of the paths is "stale", the corresponding peer router-id will
949 * be 0 and would always win over the other path. If originator id is
950 * used for the comparision, it will decide which path is better.
951 */
952 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
953 new_id.s_addr = newattr->originator_id.s_addr;
954 else
955 new_id.s_addr = new->peer->remote_id.s_addr;
956 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
957 exist_id.s_addr = existattr->originator_id.s_addr;
958 else
959 exist_id.s_addr = exist->peer->remote_id.s_addr;
960
961 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
962 if (debug)
963 zlog_debug(
964 "%s: %s wins over %s due to Router-ID comparison",
965 pfx_buf, new_buf, exist_buf);
966 return 1;
967 }
718e3744 968
d62a17ae 969 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
970 if (debug)
971 zlog_debug(
972 "%s: %s loses to %s due to Router-ID comparison",
973 pfx_buf, new_buf, exist_buf);
974 return 0;
975 }
9fbdd100 976
d62a17ae 977 /* 14. Cluster length comparision. */
978 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
979 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
980
981 if (new_cluster < exist_cluster) {
982 if (debug)
983 zlog_debug(
984 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
985 pfx_buf, new_buf, exist_buf, new_cluster,
986 exist_cluster);
987 return 1;
988 }
718e3744 989
d62a17ae 990 if (new_cluster > exist_cluster) {
991 if (debug)
992 zlog_debug(
993 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
994 pfx_buf, new_buf, exist_buf, new_cluster,
995 exist_cluster);
996 return 0;
997 }
9fbdd100 998
d62a17ae 999 /* 15. Neighbor address comparision. */
1000 /* Do this only if neither path is "stale" as stale paths do not have
1001 * valid peer information (as the connection may or may not be up).
1002 */
1defdda8 1003 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
d62a17ae 1004 if (debug)
1005 zlog_debug(
1006 "%s: %s wins over %s due to latter path being STALE",
1007 pfx_buf, new_buf, exist_buf);
1008 return 1;
1009 }
0de5153c 1010
1defdda8 1011 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
d62a17ae 1012 if (debug)
1013 zlog_debug(
1014 "%s: %s loses to %s due to former path being STALE",
1015 pfx_buf, new_buf, exist_buf);
1016 return 0;
1017 }
718e3744 1018
d62a17ae 1019 /* locally configured routes to advertise do not have su_remote */
1020 if (new->peer->su_remote == NULL)
1021 return 0;
1022 if (exist->peer->su_remote == NULL)
1023 return 1;
9fbdd100 1024
d62a17ae 1025 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1026
1027 if (ret == 1) {
1028 if (debug)
1029 zlog_debug(
1030 "%s: %s loses to %s due to Neighor IP comparison",
1031 pfx_buf, new_buf, exist_buf);
1032 return 0;
1033 }
1034
1035 if (ret == -1) {
1036 if (debug)
1037 zlog_debug(
1038 "%s: %s wins over %s due to Neighor IP comparison",
1039 pfx_buf, new_buf, exist_buf);
1040 return 1;
1041 }
9fbdd100 1042
d62a17ae 1043 if (debug)
1044 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1045 pfx_buf, new_buf, exist_buf);
718e3744 1046
d62a17ae 1047 return 1;
718e3744 1048}
1049
65efcfce
LB
1050/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1051 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1052 * multipath is enabled
65efcfce 1053 * This version is compatible with */
18ee8310
DS
1054int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1055 struct bgp_path_info *exist, char *pfx_buf,
1056 afi_t afi, safi_t safi)
d62a17ae 1057{
1058 int paths_eq;
1059 int ret;
18ee8310
DS
1060 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
1061 afi, safi);
d62a17ae 1062
1063 if (paths_eq)
1064 ret = 0;
1065 else {
1066 if (ret == 1)
1067 ret = -1;
1068 else
1069 ret = 1;
1070 }
1071 return ret;
65efcfce
LB
1072}
1073
d62a17ae 1074static enum filter_type bgp_input_filter(struct peer *peer, struct prefix *p,
1075 struct attr *attr, afi_t afi,
1076 safi_t safi)
718e3744 1077{
d62a17ae 1078 struct bgp_filter *filter;
718e3744 1079
d62a17ae 1080 filter = &peer->filter[afi][safi];
718e3744 1081
d62a17ae 1082#define FILTER_EXIST_WARN(F, f, filter) \
1083 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1084 zlog_debug("%s: Could not find configured input %s-list %s!", \
1085 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1086
1087 if (DISTRIBUTE_IN_NAME(filter)) {
1088 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1089
1090 if (access_list_apply(DISTRIBUTE_IN(filter), p) == FILTER_DENY)
1091 return FILTER_DENY;
1092 }
1093
1094 if (PREFIX_LIST_IN_NAME(filter)) {
1095 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1096
1097 if (prefix_list_apply(PREFIX_LIST_IN(filter), p) == PREFIX_DENY)
1098 return FILTER_DENY;
1099 }
1100
1101 if (FILTER_LIST_IN_NAME(filter)) {
1102 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1103
1104 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
1105 == AS_FILTER_DENY)
1106 return FILTER_DENY;
1107 }
1108
1109 return FILTER_PERMIT;
650f76c2 1110#undef FILTER_EXIST_WARN
718e3744 1111}
1112
d62a17ae 1113static enum filter_type bgp_output_filter(struct peer *peer, struct prefix *p,
1114 struct attr *attr, afi_t afi,
1115 safi_t safi)
718e3744 1116{
d62a17ae 1117 struct bgp_filter *filter;
1118
1119 filter = &peer->filter[afi][safi];
1120
1121#define FILTER_EXIST_WARN(F, f, filter) \
1122 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1123 zlog_debug("%s: Could not find configured output %s-list %s!", \
1124 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1125
d62a17ae 1126 if (DISTRIBUTE_OUT_NAME(filter)) {
1127 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1128
d62a17ae 1129 if (access_list_apply(DISTRIBUTE_OUT(filter), p) == FILTER_DENY)
1130 return FILTER_DENY;
1131 }
1132
1133 if (PREFIX_LIST_OUT_NAME(filter)) {
1134 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1135
d62a17ae 1136 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
1137 == PREFIX_DENY)
1138 return FILTER_DENY;
1139 }
718e3744 1140
d62a17ae 1141 if (FILTER_LIST_OUT_NAME(filter)) {
1142 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1143
d62a17ae 1144 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
1145 == AS_FILTER_DENY)
1146 return FILTER_DENY;
1147 }
718e3744 1148
d62a17ae 1149 return FILTER_PERMIT;
650f76c2 1150#undef FILTER_EXIST_WARN
718e3744 1151}
1152
1153/* If community attribute includes no_export then return 1. */
d62a17ae 1154static int bgp_community_filter(struct peer *peer, struct attr *attr)
1155{
1156 if (attr->community) {
1157 /* NO_ADVERTISE check. */
1158 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
1159 return 1;
1160
1161 /* NO_EXPORT check. */
1162 if (peer->sort == BGP_PEER_EBGP
1163 && community_include(attr->community, COMMUNITY_NO_EXPORT))
1164 return 1;
1165
1166 /* NO_EXPORT_SUBCONFED check. */
1167 if (peer->sort == BGP_PEER_EBGP
1168 || peer->sort == BGP_PEER_CONFED)
1169 if (community_include(attr->community,
1170 COMMUNITY_NO_EXPORT_SUBCONFED))
1171 return 1;
1172 }
1173 return 0;
718e3744 1174}
1175
1176/* Route reflection loop check. */
d62a17ae 1177static int bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1178{
d62a17ae 1179 struct in_addr cluster_id;
718e3744 1180
d62a17ae 1181 if (attr->cluster) {
1182 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1183 cluster_id = peer->bgp->cluster_id;
1184 else
1185 cluster_id = peer->bgp->router_id;
1186
1187 if (cluster_loop_check(attr->cluster, cluster_id))
1188 return 1;
1189 }
1190 return 0;
718e3744 1191}
6b0655a2 1192
d62a17ae 1193static int bgp_input_modifier(struct peer *peer, struct prefix *p,
1194 struct attr *attr, afi_t afi, safi_t safi,
1195 const char *rmap_name)
718e3744 1196{
d62a17ae 1197 struct bgp_filter *filter;
40381db7 1198 struct bgp_path_info rmap_path;
d62a17ae 1199 route_map_result_t ret;
1200 struct route_map *rmap = NULL;
718e3744 1201
d62a17ae 1202 filter = &peer->filter[afi][safi];
718e3744 1203
d62a17ae 1204 /* Apply default weight value. */
1205 if (peer->weight[afi][safi])
1206 attr->weight = peer->weight[afi][safi];
718e3744 1207
d62a17ae 1208 if (rmap_name) {
1209 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1210
d62a17ae 1211 if (rmap == NULL)
1212 return RMAP_DENY;
1213 } else {
1214 if (ROUTE_MAP_IN_NAME(filter)) {
1215 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1216
d62a17ae 1217 if (rmap == NULL)
1218 return RMAP_DENY;
1219 }
1220 }
0b16f239 1221
d62a17ae 1222 /* Route map apply. */
1223 if (rmap) {
40381db7 1224 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1225 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1226 rmap_path.peer = peer;
1227 rmap_path.attr = attr;
718e3744 1228
d62a17ae 1229 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1230
d62a17ae 1231 /* Apply BGP route map to the attribute. */
40381db7 1232 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
0b16f239 1233
d62a17ae 1234 peer->rmap_type = 0;
0b16f239 1235
1f2263be 1236 if (ret == RMAP_DENYMATCH)
d62a17ae 1237 return RMAP_DENY;
0b16f239 1238 }
d62a17ae 1239 return RMAP_PERMIT;
0b16f239
DS
1240}
1241
d62a17ae 1242static int bgp_output_modifier(struct peer *peer, struct prefix *p,
1243 struct attr *attr, afi_t afi, safi_t safi,
1244 const char *rmap_name)
0b16f239 1245{
40381db7 1246 struct bgp_path_info rmap_path;
d62a17ae 1247 route_map_result_t ret;
1248 struct route_map *rmap = NULL;
d7c0a89a 1249 uint8_t rmap_type;
0b16f239 1250
b787157a
DS
1251 /*
1252 * So if we get to this point and have no rmap_name
1253 * we want to just show the output as it currently
1254 * exists.
1255 */
1256 if (!rmap_name)
1257 return RMAP_PERMIT;
0b16f239 1258
d62a17ae 1259 /* Apply default weight value. */
1260 if (peer->weight[afi][safi])
1261 attr->weight = peer->weight[afi][safi];
0b16f239 1262
b787157a 1263 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1264
b787157a
DS
1265 /*
1266 * If we have a route map name and we do not find
1267 * the routemap that means we have an implicit
1268 * deny.
1269 */
1270 if (rmap == NULL)
1271 return RMAP_DENY;
0b16f239 1272
40381db7 1273 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1274 /* Route map apply. */
b787157a 1275 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1276 rmap_path.peer = peer;
1277 rmap_path.attr = attr;
0b16f239 1278
0f672529 1279 rmap_type = peer->rmap_type;
b787157a 1280 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1281
b787157a 1282 /* Apply BGP route map to the attribute. */
40381db7 1283 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
ac41b2a2 1284
0f672529 1285 peer->rmap_type = rmap_type;
b787157a
DS
1286
1287 if (ret == RMAP_DENYMATCH)
1288 /*
1289 * caller has multiple error paths with bgp_attr_flush()
1290 */
1291 return RMAP_DENY;
ac41b2a2 1292
d62a17ae 1293 return RMAP_PERMIT;
718e3744 1294}
6b0655a2 1295
5000f21c 1296/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1297static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1298 struct peer *peer, struct attr *attr)
1299{
1300 if (peer->sort == BGP_PEER_EBGP
1301 && (peer_af_flag_check(peer, afi, safi,
1302 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1303 || peer_af_flag_check(peer, afi, safi,
1304 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1305 || peer_af_flag_check(peer, afi, safi,
1306 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1307 || peer_af_flag_check(peer, afi, safi,
1308 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1309 // Take action on the entire aspath
1310 if (peer_af_flag_check(peer, afi, safi,
1311 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1312 || peer_af_flag_check(peer, afi, safi,
1313 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1314 if (peer_af_flag_check(
1315 peer, afi, safi,
1316 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1317 attr->aspath = aspath_replace_private_asns(
1318 attr->aspath, bgp->as);
1319
1320 // The entire aspath consists of private ASNs so create
1321 // an empty aspath
1322 else if (aspath_private_as_check(attr->aspath))
1323 attr->aspath = aspath_empty_get();
1324
1325 // There are some public and some private ASNs, remove
1326 // the private ASNs
1327 else
1328 attr->aspath = aspath_remove_private_asns(
1329 attr->aspath);
1330 }
1331
1332 // 'all' was not specified so the entire aspath must be private
1333 // ASNs
1334 // for us to do anything
1335 else if (aspath_private_as_check(attr->aspath)) {
1336 if (peer_af_flag_check(
1337 peer, afi, safi,
1338 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1339 attr->aspath = aspath_replace_private_asns(
1340 attr->aspath, bgp->as);
1341 else
1342 attr->aspath = aspath_empty_get();
1343 }
1344 }
5000f21c
DS
1345}
1346
c7122e14 1347/* If this is an EBGP peer with as-override */
d62a17ae 1348static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1349 struct peer *peer, struct attr *attr)
1350{
1351 if (peer->sort == BGP_PEER_EBGP
1352 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1353 if (aspath_single_asn_check(attr->aspath, peer->as))
1354 attr->aspath = aspath_replace_specific_asn(
1355 attr->aspath, peer->as, bgp->as);
1356 }
1357}
1358
7f323236
DW
1359void bgp_attr_add_gshut_community(struct attr *attr)
1360{
1361 struct community *old;
1362 struct community *new;
1363 struct community *merge;
1364 struct community *gshut;
1365
1366 old = attr->community;
1367 gshut = community_str2com("graceful-shutdown");
1368
990f4f91 1369 assert(gshut);
1370
7f323236
DW
1371 if (old) {
1372 merge = community_merge(community_dup(old), gshut);
1373
a4d82a8a 1374 if (old->refcnt == 0)
3c1f53de 1375 community_free(&old);
7f323236
DW
1376
1377 new = community_uniq_sort(merge);
3c1f53de 1378 community_free(&merge);
7f323236
DW
1379 } else {
1380 new = community_dup(gshut);
1381 }
1382
3c1f53de 1383 community_free(&gshut);
7f323236
DW
1384 attr->community = new;
1385 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1386
1387 /* When we add the graceful-shutdown community we must also
1388 * lower the local-preference */
1389 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1390 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1391}
1392
1393
d7c0a89a 1394static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1395{
960035b2 1396 if (family == AF_INET) {
d62a17ae 1397 attr->nexthop.s_addr = 0;
960035b2
PZ
1398 attr->mp_nexthop_global_in.s_addr = 0;
1399 }
d62a17ae 1400 if (family == AF_INET6)
1401 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1402 if (family == AF_EVPN)
1403 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1404}
1405
40381db7 1406int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
d62a17ae 1407 struct update_subgroup *subgrp, struct prefix *p,
1408 struct attr *attr)
1409{
1410 struct bgp_filter *filter;
1411 struct peer *from;
1412 struct peer *peer;
1413 struct peer *onlypeer;
1414 struct bgp *bgp;
40381db7 1415 struct attr *piattr;
d62a17ae 1416 char buf[PREFIX_STRLEN];
1417 int ret;
1418 int transparent;
1419 int reflect;
1420 afi_t afi;
1421 safi_t safi;
1422 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
1423
1424 if (DISABLE_BGP_ANNOUNCE)
1425 return 0;
1426
1427 afi = SUBGRP_AFI(subgrp);
1428 safi = SUBGRP_SAFI(subgrp);
1429 peer = SUBGRP_PEER(subgrp);
1430 onlypeer = NULL;
1431 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1432 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1433
40381db7 1434 from = pi->peer;
d62a17ae 1435 filter = &peer->filter[afi][safi];
1436 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1437 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1438 : pi->attr;
3f9c7369 1439
65efcfce 1440#if ENABLE_BGP_VNC
d62a17ae 1441 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1442 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1443 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1444
1445 /*
1446 * direct and direct_ext type routes originate internally even
1447 * though they can have peer pointers that reference other
1448 * systems
1449 */
1450 prefix2str(p, buf, PREFIX_STRLEN);
1451 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1452 __func__, buf);
1453 samepeer_safe = 1;
1454 }
65efcfce
LB
1455#endif
1456
ddb5b488
PZ
1457 if (((afi == AFI_IP) || (afi == AFI_IP6))
1458 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1459 && (pi->type == ZEBRA_ROUTE_BGP)
1460 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1461
1462 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1463
1464 samepeer_safe = 1;
1465 }
1466
d62a17ae 1467 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1468 * pi is valid */
1469 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1470 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1471 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 1472 return 0;
1473 }
adbac85e 1474
d62a17ae 1475 /* If this is not the bestpath then check to see if there is an enabled
1476 * addpath
1477 * feature that requires us to advertise it */
40381db7 1478 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1479 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
d62a17ae 1480 return 0;
1481 }
1482 }
06370dac 1483
d62a17ae 1484 /* Aggregate-address suppress check. */
40381db7 1485 if (pi->extra && pi->extra->suppress)
d62a17ae 1486 if (!UNSUPPRESS_MAP_NAME(filter)) {
1487 return 0;
1488 }
3f9c7369 1489
13b7e7f0
DS
1490 /*
1491 * If we are doing VRF 2 VRF leaking via the import
1492 * statement, we want to prevent the route going
1493 * off box as that the RT and RD created are localy
1494 * significant and globaly useless.
1495 */
40381db7
DS
1496 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1497 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
13b7e7f0
DS
1498 return 0;
1499
d62a17ae 1500 /* If it's labeled safi, make sure the route has a valid label. */
1501 if (safi == SAFI_LABELED_UNICAST) {
40381db7 1502 mpls_label_t label = bgp_adv_label(rn, pi, peer, afi, safi);
d62a17ae 1503 if (!bgp_is_valid_label(&label)) {
1504 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1505 zlog_debug("u%" PRIu64 ":s%" PRIu64
1506 " %s/%d is filtered - no label (%p)",
1507 subgrp->update_group->id, subgrp->id,
1508 inet_ntop(p->family, &p->u.prefix,
1509 buf, SU_ADDRSTRLEN),
1510 p->prefixlen, &label);
1511 return 0;
1512 }
1513 }
cd1964ff 1514
d62a17ae 1515 /* Do not send back route to sender. */
1516 if (onlypeer && from == onlypeer) {
1517 return 0;
1518 }
3f9c7369 1519
d62a17ae 1520 /* Do not send the default route in the BGP table if the neighbor is
1521 * configured for default-originate */
1522 if (CHECK_FLAG(peer->af_flags[afi][safi],
1523 PEER_FLAG_DEFAULT_ORIGINATE)) {
1524 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
1525 return 0;
1526 else if (p->family == AF_INET6 && p->prefixlen == 0)
1527 return 0;
1528 }
4125bb67 1529
d62a17ae 1530 /* Transparency check. */
1531 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1532 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1533 transparent = 1;
1534 else
1535 transparent = 0;
1536
1537 /* If community is not disabled check the no-export and local. */
40381db7 1538 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1539 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1540 zlog_debug(
1541 "subgrpannouncecheck: community filter check fail");
1542 return 0;
1543 }
3f9c7369 1544
d62a17ae 1545 /* If the attribute has originator-id and it is same as remote
1546 peer's id. */
40381db7
DS
1547 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1548 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1549 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1550 zlog_debug(
1551 "%s [Update:SEND] %s originator-id is same as "
1552 "remote router-id",
1553 onlypeer->host,
1554 prefix2str(p, buf, sizeof(buf)));
1555 return 0;
1556 }
3f9c7369 1557
d62a17ae 1558 /* ORF prefix-list filter check */
1559 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1560 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1561 || CHECK_FLAG(peer->af_cap[afi][safi],
1562 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1563 if (peer->orf_plist[afi][safi]) {
1564 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1565 == PREFIX_DENY) {
1566 if (bgp_debug_update(NULL, p,
1567 subgrp->update_group, 0))
1568 zlog_debug(
1569 "%s [Update:SEND] %s is filtered via ORF",
1570 peer->host,
1571 prefix2str(p, buf,
1572 sizeof(buf)));
1573 return 0;
1574 }
1575 }
1576
1577 /* Output filter check. */
40381db7 1578 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1579 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1580 zlog_debug("%s [Update:SEND] %s is filtered",
1581 peer->host, prefix2str(p, buf, sizeof(buf)));
1582 return 0;
1583 }
3f9c7369
DS
1584
1585#ifdef BGP_SEND_ASPATH_CHECK
d62a17ae 1586 /* AS path loop check. */
40381db7 1587 if (onlypeer && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1588 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1589 zlog_debug(
1590 "%s [Update:SEND] suppress announcement to peer AS %u "
1591 "that is part of AS path.",
1592 onlypeer->host, onlypeer->as);
1593 return 0;
1594 }
3f9c7369
DS
1595#endif /* BGP_SEND_ASPATH_CHECK */
1596
d62a17ae 1597 /* If we're a CONFED we need to loop check the CONFED ID too */
1598 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1599 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1600 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1601 zlog_debug(
1602 "%s [Update:SEND] suppress announcement to peer AS %u"
1603 " is AS path.",
1604 peer->host, bgp->confed_id);
1605 return 0;
1606 }
3f9c7369 1607 }
3f9c7369 1608
d62a17ae 1609 /* Route-Reflect check. */
1610 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1611 reflect = 1;
1612 else
1613 reflect = 0;
1614
1615 /* IBGP reflection check. */
1616 if (reflect && !samepeer_safe) {
1617 /* A route from a Client peer. */
1618 if (CHECK_FLAG(from->af_flags[afi][safi],
1619 PEER_FLAG_REFLECTOR_CLIENT)) {
1620 /* Reflect to all the Non-Client peers and also to the
1621 Client peers other than the originator. Originator
1622 check
1623 is already done. So there is noting to do. */
1624 /* no bgp client-to-client reflection check. */
1625 if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
1626 if (CHECK_FLAG(peer->af_flags[afi][safi],
1627 PEER_FLAG_REFLECTOR_CLIENT))
1628 return 0;
1629 } else {
1630 /* A route from a Non-client peer. Reflect to all other
1631 clients. */
1632 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1633 PEER_FLAG_REFLECTOR_CLIENT))
1634 return 0;
1635 }
1636 }
3f9c7369 1637
d62a17ae 1638 /* For modify attribute, copy it to temporary structure. */
40381db7 1639 bgp_attr_dup(attr, piattr);
d62a17ae 1640
1641 /* If local-preference is not set. */
1642 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1643 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1644 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1645 attr->local_pref = bgp->default_local_pref;
3f9c7369 1646 }
3f9c7369 1647
d62a17ae 1648 /* If originator-id is not set and the route is to be reflected,
1649 set the originator id */
1650 if (reflect
1651 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1652 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1653 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1654 }
3f9c7369 1655
d62a17ae 1656 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1657 */
1658 if (peer->sort == BGP_PEER_EBGP
1659 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1660 if (from != bgp->peer_self && !transparent
1661 && !CHECK_FLAG(peer->af_flags[afi][safi],
1662 PEER_FLAG_MED_UNCHANGED))
1663 attr->flag &=
1664 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1665 }
3f9c7369 1666
d62a17ae 1667 /* Since the nexthop attribute can vary per peer, it is not explicitly
1668 * set
1669 * in announce check, only certain flags and length (or number of
1670 * nexthops
1671 * -- for IPv6/MP_REACH) are set here in order to guide the update
1672 * formation
1673 * code in setting the nexthop(s) on a per peer basis in
1674 * reformat_peer().
1675 * Typically, the source nexthop in the attribute is preserved but in
1676 * the
1677 * scenarios where we know it will always be overwritten, we reset the
1678 * nexthop to "0" in an attempt to achieve better Update packing. An
1679 * example of this is when a prefix from each of 2 IBGP peers needs to
1680 * be
1681 * announced to an EBGP peer (and they have the same attributes barring
1682 * their nexthop).
1683 */
1684 if (reflect)
1685 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1686
1687#define NEXTHOP_IS_V6 \
1688 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1689 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1690 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1691 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1692
1693 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1694 * if
1695 * the peer (group) is configured to receive link-local nexthop
1696 * unchanged
1697 * and it is available in the prefix OR we're not reflecting the route
1698 * and
1699 * the peer (group) to whom we're going to announce is on a shared
1700 * network
1701 * and this is either a self-originated route or the peer is EBGP.
1702 */
1703 if (NEXTHOP_IS_V6) {
1704 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
1705 if ((CHECK_FLAG(peer->af_flags[afi][safi],
1706 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
1707 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
1708 || (!reflect && peer->shared_network
1709 && (from == bgp->peer_self
1710 || peer->sort == BGP_PEER_EBGP))) {
1711 attr->mp_nexthop_len =
1712 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
1713 }
3f9c7369 1714
d62a17ae 1715 /* Clear off link-local nexthop in source, whenever it is not
1716 * needed to
1717 * ensure more prefixes share the same attribute for
1718 * announcement.
1719 */
1720 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
1721 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
1722 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
1723 }
3f9c7369 1724
d62a17ae 1725 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
1726 bgp_peer_as_override(bgp, afi, safi, peer, attr);
1727
1728 /* Route map & unsuppress-map apply. */
40381db7
DS
1729 if (ROUTE_MAP_OUT_NAME(filter) || (pi->extra && pi->extra->suppress)) {
1730 struct bgp_path_info rmap_path;
1731 struct bgp_path_info_extra dummy_rmap_path_extra;
d62a17ae 1732 struct attr dummy_attr;
1733
40381db7
DS
1734 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
1735 rmap_path.peer = peer;
1736 rmap_path.attr = attr;
d37ba549 1737
40381db7
DS
1738 if (pi->extra) {
1739 memcpy(&dummy_rmap_path_extra, pi->extra,
4b7e6066 1740 sizeof(struct bgp_path_info_extra));
40381db7 1741 rmap_path.extra = &dummy_rmap_path_extra;
16f7ce2b
MK
1742 }
1743
d62a17ae 1744 /* don't confuse inbound and outbound setting */
1745 RESET_FLAG(attr->rmap_change_flags);
1746
1747 /*
1748 * The route reflector is not allowed to modify the attributes
1749 * of the reflected IBGP routes unless explicitly allowed.
1750 */
1751 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1752 && !bgp_flag_check(bgp,
1753 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
1754 bgp_attr_dup(&dummy_attr, attr);
40381db7 1755 rmap_path.attr = &dummy_attr;
d62a17ae 1756 }
3f9c7369 1757
d62a17ae 1758 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 1759
40381db7 1760 if (pi->extra && pi->extra->suppress)
d62a17ae 1761 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
40381db7 1762 RMAP_BGP, &rmap_path);
d62a17ae 1763 else
1764 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
40381db7 1765 RMAP_BGP, &rmap_path);
d62a17ae 1766
1767 peer->rmap_type = 0;
1768
1769 if (ret == RMAP_DENYMATCH) {
1770 bgp_attr_flush(attr);
1771 return 0;
1772 }
3f9c7369 1773 }
3f9c7369 1774
7f323236 1775 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
a4d82a8a
PZ
1776 if (peer->sort == BGP_PEER_IBGP
1777 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
1778 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1779 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1780 } else {
1781 bgp_attr_add_gshut_community(attr);
1782 }
1783 }
1784
d62a17ae 1785 /* After route-map has been applied, we check to see if the nexthop to
1786 * be carried in the attribute (that is used for the announcement) can
1787 * be cleared off or not. We do this in all cases where we would be
1788 * setting the nexthop to "ourselves". For IPv6, we only need to
1789 * consider
1790 * the global nexthop here; the link-local nexthop would have been
1791 * cleared
1792 * already, and if not, it is required by the update formation code.
1793 * Also see earlier comments in this function.
1794 */
1795 /*
1796 * If route-map has performed some operation on the nexthop or the peer
1797 * configuration says to pass it unchanged, we cannot reset the nexthop
1798 * here, so only attempt to do it if these aren't true. Note that the
1799 * route-map handler itself might have cleared the nexthop, if for
1800 * example,
1801 * it is configured as 'peer-address'.
1802 */
1803 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 1804 piattr->rmap_change_flags)
d62a17ae 1805 && !transparent
1806 && !CHECK_FLAG(peer->af_flags[afi][safi],
1807 PEER_FLAG_NEXTHOP_UNCHANGED)) {
1808 /* We can reset the nexthop, if setting (or forcing) it to
1809 * 'self' */
1810 if (CHECK_FLAG(peer->af_flags[afi][safi],
1811 PEER_FLAG_NEXTHOP_SELF)
1812 || CHECK_FLAG(peer->af_flags[afi][safi],
1813 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
1814 if (!reflect
1815 || CHECK_FLAG(peer->af_flags[afi][safi],
1816 PEER_FLAG_FORCE_NEXTHOP_SELF))
1817 subgroup_announce_reset_nhop(
1818 (peer_cap_enhe(peer, afi, safi)
1819 ? AF_INET6
1820 : p->family),
1821 attr);
1822 } else if (peer->sort == BGP_PEER_EBGP) {
1823 /* Can also reset the nexthop if announcing to EBGP, but
1824 * only if
1825 * no peer in the subgroup is on a shared subnet.
1826 * Note: 3rd party nexthop currently implemented for
1827 * IPv4 only.
1828 */
40381db7 1829 if (!bgp_subgrp_multiaccess_check_v4(piattr->nexthop,
65d4e0c6 1830 subgrp))
d62a17ae 1831 subgroup_announce_reset_nhop(
1832 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
1833 ? AF_INET6
1834 : p->family),
d62a17ae 1835 attr);
40381db7 1836 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
1837 /*
1838 * This flag is used for leaked vpn-vrf routes
1839 */
1840 int family = p->family;
1841
1842 if (peer_cap_enhe(peer, afi, safi))
1843 family = AF_INET6;
1844
1845 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1846 zlog_debug(
1defdda8 1847 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
1848 __func__, family2str(family));
1849 subgroup_announce_reset_nhop(family, attr);
d62a17ae 1850 }
960035b2 1851
d62a17ae 1852 /* If IPv6/MP and nexthop does not have any override and happens
1853 * to
1854 * be a link-local address, reset it so that we don't pass along
1855 * the
1856 * source's link-local IPv6 address to recipients who may not be
1857 * on
1858 * the same interface.
1859 */
1860 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
1861 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global))
1862 subgroup_announce_reset_nhop(AF_INET6, attr);
1863 }
1864 }
3f9c7369 1865
d62a17ae 1866 return 1;
3f9c7369
DS
1867}
1868
d62a17ae 1869void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
1870 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
1871 struct bgp_path_info_pair *result, afi_t afi,
1872 safi_t safi)
1873{
1874 struct bgp_path_info *new_select;
1875 struct bgp_path_info *old_select;
40381db7
DS
1876 struct bgp_path_info *pi;
1877 struct bgp_path_info *pi1;
1878 struct bgp_path_info *pi2;
1879 struct bgp_path_info *nextpi = NULL;
d62a17ae 1880 int paths_eq, do_mpath, debug;
1881 struct list mp_list;
1882 char pfx_buf[PREFIX2STR_BUFFER];
1883 char path_buf[PATH_ADDPATH_STR_BUFFER];
1884
1885 bgp_mp_list_init(&mp_list);
1886 do_mpath =
1887 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
1888
1889 debug = bgp_debug_bestpath(&rn->p);
1890
1891 if (debug)
1892 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
1893
1894 /* bgp deterministic-med */
1895 new_select = NULL;
1896 if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)) {
1897
1defdda8 1898 /* Clear BGP_PATH_DMED_SELECTED for all paths */
6f94b685
DS
1899 for (pi1 = bgp_node_get_bgp_path_info(rn); pi1;
1900 pi1 = pi1->next)
40381db7 1901 bgp_path_info_unset_flag(rn, pi1,
18ee8310 1902 BGP_PATH_DMED_SELECTED);
d62a17ae 1903
6f94b685
DS
1904 for (pi1 = bgp_node_get_bgp_path_info(rn); pi1;
1905 pi1 = pi1->next) {
40381db7 1906 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 1907 continue;
40381db7 1908 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 1909 continue;
40381db7
DS
1910 if (pi1->peer && pi1->peer != bgp->peer_self)
1911 if (pi1->peer->status != Established)
d62a17ae 1912 continue;
1913
40381db7
DS
1914 new_select = pi1;
1915 if (pi1->next) {
1916 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
1917 if (CHECK_FLAG(pi2->flags,
1defdda8 1918 BGP_PATH_DMED_CHECK))
d62a17ae 1919 continue;
40381db7 1920 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 1921 continue;
40381db7
DS
1922 if (pi2->peer
1923 && pi2->peer != bgp->peer_self
d62a17ae 1924 && !CHECK_FLAG(
40381db7 1925 pi2->peer->sflags,
d62a17ae 1926 PEER_STATUS_NSF_WAIT))
40381db7 1927 if (pi2->peer->status
d62a17ae 1928 != Established)
1929 continue;
1930
121e245d
DS
1931 if (!aspath_cmp_left(pi1->attr->aspath,
1932 pi2->attr->aspath)
1933 && !aspath_cmp_left_confed(
40381db7 1934 pi1->attr->aspath,
121e245d
DS
1935 pi2->attr->aspath))
1936 continue;
d62a17ae 1937
121e245d
DS
1938 if (bgp_path_info_cmp(
1939 bgp, pi2, new_select,
1940 &paths_eq, mpath_cfg, debug,
1941 pfx_buf, afi, safi)) {
1942 bgp_path_info_unset_flag(
1943 rn, new_select,
1944 BGP_PATH_DMED_SELECTED);
1945 new_select = pi2;
d62a17ae 1946 }
121e245d
DS
1947
1948 bgp_path_info_set_flag(
1949 rn, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 1950 }
1951 }
18ee8310
DS
1952 bgp_path_info_set_flag(rn, new_select,
1953 BGP_PATH_DMED_CHECK);
1954 bgp_path_info_set_flag(rn, new_select,
1955 BGP_PATH_DMED_SELECTED);
d62a17ae 1956
1957 if (debug) {
18ee8310
DS
1958 bgp_path_info_path_with_addpath_rx_str(
1959 new_select, path_buf);
c66faab1 1960 zlog_debug("%s: %s is the bestpath from AS %u",
d62a17ae 1961 pfx_buf, path_buf,
1962 aspath_get_first_as(
1963 new_select->attr->aspath));
1964 }
1965 }
1966 }
96450faf 1967
d62a17ae 1968 /* Check old selected route and new selected route. */
1969 old_select = NULL;
1970 new_select = NULL;
6f94b685
DS
1971 for (pi = bgp_node_get_bgp_path_info(rn);
1972 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
40381db7
DS
1973 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
1974 old_select = pi;
d62a17ae 1975
40381db7 1976 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 1977 /* reap REMOVED routes, if needs be
1978 * selected route must stay for a while longer though
1979 */
40381db7
DS
1980 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
1981 && (pi != old_select))
1982 bgp_path_info_reap(rn, pi);
d62a17ae 1983
ddb5b488 1984 if (debug)
40381db7
DS
1985 zlog_debug("%s: pi %p in holddown", __func__,
1986 pi);
ddb5b488 1987
d62a17ae 1988 continue;
1989 }
96450faf 1990
40381db7
DS
1991 if (pi->peer && pi->peer != bgp->peer_self
1992 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
1993 if (pi->peer->status != Established) {
ddb5b488
PZ
1994
1995 if (debug)
1996 zlog_debug(
40381db7
DS
1997 "%s: pi %p non self peer %s not estab state",
1998 __func__, pi, pi->peer->host);
ddb5b488 1999
d62a17ae 2000 continue;
ddb5b488 2001 }
9fbdd100 2002
d62a17ae 2003 if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)
40381db7
DS
2004 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
2005 bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2006 if (debug)
40381db7 2007 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2008 continue;
2009 }
9fbdd100 2010
40381db7 2011 bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK);
06370dac 2012
40381db7 2013 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
18ee8310 2014 debug, pfx_buf, afi, safi)) {
40381db7 2015 new_select = pi;
d62a17ae 2016 }
2017 }
718e3744 2018
d62a17ae 2019 /* Now that we know which path is the bestpath see if any of the other
2020 * paths
2021 * qualify as multipaths
2022 */
2023 if (debug) {
2024 if (new_select)
18ee8310
DS
2025 bgp_path_info_path_with_addpath_rx_str(new_select,
2026 path_buf);
d62a17ae 2027 else
2028 sprintf(path_buf, "NONE");
2029 zlog_debug(
2030 "%s: After path selection, newbest is %s oldbest was %s",
2031 pfx_buf, path_buf,
2032 old_select ? old_select->peer->host : "NONE");
96450faf 2033 }
9fbdd100 2034
d62a17ae 2035 if (do_mpath && new_select) {
6f94b685
DS
2036 for (pi = bgp_node_get_bgp_path_info(rn);
2037 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2038
2039 if (debug)
18ee8310 2040 bgp_path_info_path_with_addpath_rx_str(
40381db7 2041 pi, path_buf);
d62a17ae 2042
40381db7 2043 if (pi == new_select) {
d62a17ae 2044 if (debug)
2045 zlog_debug(
2046 "%s: %s is the bestpath, add to the multipath list",
2047 pfx_buf, path_buf);
40381db7 2048 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2049 continue;
2050 }
2051
40381db7 2052 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2053 continue;
2054
40381db7
DS
2055 if (pi->peer && pi->peer != bgp->peer_self
2056 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2057 PEER_STATUS_NSF_WAIT))
40381db7 2058 if (pi->peer->status != Established)
d62a17ae 2059 continue;
2060
40381db7 2061 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2062 if (debug)
2063 zlog_debug(
2064 "%s: %s has the same nexthop as the bestpath, skip it",
2065 pfx_buf, path_buf);
2066 continue;
2067 }
2068
40381db7 2069 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
18ee8310 2070 mpath_cfg, debug, pfx_buf, afi, safi);
d62a17ae 2071
2072 if (paths_eq) {
2073 if (debug)
2074 zlog_debug(
2075 "%s: %s is equivalent to the bestpath, add to the multipath list",
2076 pfx_buf, path_buf);
40381db7 2077 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2078 }
2079 }
2080 }
fee0f4c6 2081
18ee8310
DS
2082 bgp_path_info_mpath_update(rn, new_select, old_select, &mp_list,
2083 mpath_cfg);
2084 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2085 bgp_mp_list_clear(&mp_list);
96450faf 2086
dcc68b5e
MS
2087 bgp_addpath_update_ids(bgp, rn, afi, safi);
2088
d62a17ae 2089 result->old = old_select;
2090 result->new = new_select;
96450faf 2091
d62a17ae 2092 return;
fee0f4c6 2093}
2094
3f9c7369
DS
2095/*
2096 * A new route/change in bestpath of an existing route. Evaluate the path
2097 * for advertisement to the subgroup.
2098 */
d62a17ae 2099int subgroup_process_announce_selected(struct update_subgroup *subgrp,
4b7e6066 2100 struct bgp_path_info *selected,
d62a17ae 2101 struct bgp_node *rn,
d7c0a89a 2102 uint32_t addpath_tx_id)
d62a17ae 2103{
2104 struct prefix *p;
2105 struct peer *onlypeer;
2106 struct attr attr;
2107 afi_t afi;
2108 safi_t safi;
adbac85e 2109
d62a17ae 2110 p = &rn->p;
2111 afi = SUBGRP_AFI(subgrp);
2112 safi = SUBGRP_SAFI(subgrp);
2113 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2114 : NULL);
2115
e0207895
PZ
2116 if (BGP_DEBUG(update, UPDATE_OUT)) {
2117 char buf_prefix[PREFIX_STRLEN];
2118 prefix2str(p, buf_prefix, sizeof(buf_prefix));
ddb5b488
PZ
2119 zlog_debug("%s: p=%s, selected=%p", __func__, buf_prefix,
2120 selected);
e0207895
PZ
2121 }
2122
d62a17ae 2123 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2124 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2125 PEER_STATUS_ORF_WAIT_REFRESH))
d62a17ae 2126 return 0;
2127
2128 memset(&attr, 0, sizeof(struct attr));
2129 /* It's initialized in bgp_announce_check() */
2130
2131 /* Announcement to the subgroup. If the route is filtered withdraw it.
2132 */
2133 if (selected) {
2134 if (subgroup_announce_check(rn, selected, subgrp, p, &attr))
2135 bgp_adj_out_set_subgroup(rn, subgrp, &attr, selected);
2136 else
2137 bgp_adj_out_unset_subgroup(rn, subgrp, 1,
dcc68b5e 2138 addpath_tx_id);
d62a17ae 2139 }
2140
2141 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2142 else {
2143 bgp_adj_out_unset_subgroup(rn, subgrp, 1, addpath_tx_id);
2144 }
558d1fec 2145
d62a17ae 2146 return 0;
200df115 2147}
fee0f4c6 2148
3064bf43 2149/*
e1072051 2150 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2151 * This is called at the end of route processing.
3064bf43 2152 */
d62a17ae 2153void bgp_zebra_clear_route_change_flags(struct bgp_node *rn)
3064bf43 2154{
40381db7 2155 struct bgp_path_info *pi;
3064bf43 2156
6f94b685 2157 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 2158 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2159 continue;
40381db7
DS
2160 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2161 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2162 }
3064bf43 2163}
2164
2165/*
2166 * Has the route changed from the RIB's perspective? This is invoked only
2167 * if the route selection returns the same best route as earlier - to
2168 * determine if we need to update zebra or not.
2169 */
4b7e6066
DS
2170int bgp_zebra_has_route_changed(struct bgp_node *rn,
2171 struct bgp_path_info *selected)
d62a17ae 2172{
4b7e6066 2173 struct bgp_path_info *mpinfo;
d62a17ae 2174
2bb9eff4
DS
2175 /* If this is multipath, check all selected paths for any nexthop
2176 * change or attribute change. Some attribute changes (e.g., community)
2177 * aren't of relevance to the RIB, but we'll update zebra to ensure
2178 * we handle the case of BGP nexthop change. This is the behavior
2179 * when the best path has an attribute change anyway.
d62a17ae 2180 */
1defdda8
DS
2181 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
2182 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG))
d62a17ae 2183 return 1;
2184
2bb9eff4
DS
2185 /*
2186 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2187 */
18ee8310
DS
2188 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2189 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2190 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2191 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
d62a17ae 2192 return 1;
2193 }
3064bf43 2194
d62a17ae 2195 /* Nothing has changed from the RIB's perspective. */
2196 return 0;
3064bf43 2197}
2198
d62a17ae 2199struct bgp_process_queue {
2200 struct bgp *bgp;
a4d82a8a 2201 STAILQ_HEAD(, bgp_node) pqueue;
aac24838
JB
2202#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2203 unsigned int flags;
2204 unsigned int queued;
200df115 2205};
2206
3103e8d2
DS
2207/*
2208 * old_select = The old best path
2209 * new_select = the new best path
2210 *
2211 * if (!old_select && new_select)
2212 * We are sending new information on.
2213 *
2214 * if (old_select && new_select) {
2215 * if (new_select != old_select)
2216 * We have a new best path send a change
2217 * else
2218 * We've received a update with new attributes that needs
2219 * to be passed on.
2220 * }
2221 *
2222 * if (old_select && !new_select)
2223 * We have no eligible route that we can announce or the rn
2224 * is being removed.
2225 */
aac24838
JB
2226static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
2227 afi_t afi, safi_t safi)
d62a17ae 2228{
4b7e6066
DS
2229 struct bgp_path_info *new_select;
2230 struct bgp_path_info *old_select;
2231 struct bgp_path_info_pair old_and_new;
ddb5b488
PZ
2232 char pfx_buf[PREFIX2STR_BUFFER];
2233 int debug = 0;
d62a17ae 2234
2235 /* Is it end of initial update? (after startup) */
2236 if (!rn) {
2237 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2238 sizeof(bgp->update_delay_zebra_resume_time));
2239
2240 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2241 FOREACH_AFI_SAFI (afi, safi) {
2242 if (bgp_fibupd_safi(safi))
2243 bgp_zebra_announce_table(bgp, afi, safi);
2244 }
d62a17ae 2245 bgp->main_peers_update_hold = 0;
2246
2247 bgp_start_routeadv(bgp);
aac24838 2248 return;
d62a17ae 2249 }
cb1faec9 2250
b575a12c
A
2251 struct prefix *p = &rn->p;
2252
ddb5b488
PZ
2253 debug = bgp_debug_bestpath(&rn->p);
2254 if (debug) {
2255 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2256 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__, pfx_buf,
2257 afi2str(afi), safi2str(safi));
2258 }
2259
d62a17ae 2260 /* Best path selection. */
2261 bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new,
2262 afi, safi);
2263 old_select = old_and_new.old;
2264 new_select = old_and_new.new;
2265
2266 /* Do we need to allocate or free labels?
2267 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2268 * necessary to do this upon changes to best path. Exceptions:
2269 * - label index has changed -> recalculate resulting label
2270 * - path_info sub_type changed -> switch to/from implicit-null
2271 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2272 */
318cac96 2273 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2274 if (new_select) {
2275 if (!old_select
2276 || bgp_label_index_differs(new_select, old_select)
57592a53
AD
2277 || new_select->sub_type != old_select->sub_type
2278 || !bgp_is_valid_label(&rn->local_label)) {
2279 /* Enforced penultimate hop popping:
2280 * implicit-null for local routes, aggregate
2281 * and redistributed routes
2282 */
d62a17ae 2283 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2284 || new_select->sub_type
2285 == BGP_ROUTE_AGGREGATE
2286 || new_select->sub_type
2287 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2288 if (CHECK_FLAG(
2289 rn->flags,
2290 BGP_NODE_REGISTERED_FOR_LABEL))
2291 bgp_unregister_for_label(rn);
70e98a7f 2292 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
d62a17ae 2293 &rn->local_label);
2294 bgp_set_valid_label(&rn->local_label);
2295 } else
2296 bgp_register_for_label(rn, new_select);
2297 }
a4d82a8a
PZ
2298 } else if (CHECK_FLAG(rn->flags,
2299 BGP_NODE_REGISTERED_FOR_LABEL)) {
d62a17ae 2300 bgp_unregister_for_label(rn);
318cac96
DW
2301 }
2302 } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
2303 bgp_unregister_for_label(rn);
d62a17ae 2304 }
cd1964ff 2305
ddb5b488
PZ
2306 if (debug) {
2307 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2308 zlog_debug(
2309 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2310 __func__, pfx_buf, afi2str(afi), safi2str(safi),
2311 old_select, new_select);
2312 }
2313
d62a17ae 2314 /* If best route remains the same and this is not due to user-initiated
2315 * clear, see exactly what needs to be done.
2316 */
d62a17ae 2317 if (old_select && old_select == new_select
2318 && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
1defdda8 2319 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2320 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 2321 if (bgp_zebra_has_route_changed(rn, old_select)) {
65efcfce 2322#if ENABLE_BGP_VNC
d62a17ae 2323 vnc_import_bgp_add_route(bgp, p, old_select);
2324 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2325#endif
bb744275 2326 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2327 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2328
2329 if (new_select->type == ZEBRA_ROUTE_BGP
2330 && (new_select->sub_type == BGP_ROUTE_NORMAL
2331 || new_select->sub_type
2332 == BGP_ROUTE_IMPORTED))
2333
2334 bgp_zebra_announce(rn, p, old_select,
2335 bgp, afi, safi);
2336 }
d62a17ae 2337 }
1defdda8 2338 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
d62a17ae 2339 bgp_zebra_clear_route_change_flags(rn);
2340
2341 /* If there is a change of interest to peers, reannounce the
2342 * route. */
1defdda8 2343 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
d62a17ae 2344 || CHECK_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED)) {
2345 group_announce_route(bgp, afi, safi, rn, new_select);
2346
2347 /* unicast routes must also be annouced to
2348 * labeled-unicast update-groups */
2349 if (safi == SAFI_UNICAST)
2350 group_announce_route(bgp, afi,
2351 SAFI_LABELED_UNICAST, rn,
2352 new_select);
2353
1defdda8 2354 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2355 UNSET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED);
2356 }
fee0f4c6 2357
d62a17ae 2358 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2359 return;
d62a17ae 2360 }
8ad7271d 2361
d62a17ae 2362 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2363 */
2364 UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR);
2365
2366 /* bestpath has changed; bump version */
2367 if (old_select || new_select) {
2368 bgp_bump_version(rn);
2369
2370 if (!bgp->t_rmap_def_originate_eval) {
2371 bgp_lock(bgp);
2372 thread_add_timer(
2373 bm->master,
2374 update_group_refresh_default_originate_route_map,
2375 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2376 &bgp->t_rmap_def_originate_eval);
2377 }
2378 }
3f9c7369 2379
d62a17ae 2380 if (old_select)
18ee8310 2381 bgp_path_info_unset_flag(rn, old_select, BGP_PATH_SELECTED);
d62a17ae 2382 if (new_select) {
ddb5b488
PZ
2383 if (debug)
2384 zlog_debug("%s: setting SELECTED flag", __func__);
18ee8310
DS
2385 bgp_path_info_set_flag(rn, new_select, BGP_PATH_SELECTED);
2386 bgp_path_info_unset_flag(rn, new_select, BGP_PATH_ATTR_CHANGED);
1defdda8 2387 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
d62a17ae 2388 }
338b3424 2389
65efcfce 2390#if ENABLE_BGP_VNC
d62a17ae 2391 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2392 if (old_select != new_select) {
2393 if (old_select) {
2394 vnc_import_bgp_exterior_del_route(bgp, p,
2395 old_select);
2396 vnc_import_bgp_del_route(bgp, p, old_select);
2397 }
2398 if (new_select) {
2399 vnc_import_bgp_exterior_add_route(bgp, p,
2400 new_select);
2401 vnc_import_bgp_add_route(bgp, p, new_select);
2402 }
2403 }
2404 }
65efcfce
LB
2405#endif
2406
d62a17ae 2407 group_announce_route(bgp, afi, safi, rn, new_select);
2408
2409 /* unicast routes must also be annouced to labeled-unicast update-groups
2410 */
2411 if (safi == SAFI_UNICAST)
2412 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, rn,
2413 new_select);
2414
2415 /* FIB update. */
2416 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2417 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2418 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2419 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2420 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2421 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2422
2423 /* if this is an evpn imported type-5 prefix,
2424 * we need to withdraw the route first to clear
2425 * the nh neigh and the RMAC entry.
2426 */
2427 if (old_select &&
2428 is_route_parent_evpn(old_select))
2429 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2430
d62a17ae 2431 bgp_zebra_announce(rn, p, new_select, bgp, afi, safi);
2b659f33 2432 } else {
d62a17ae 2433 /* Withdraw the route from the kernel. */
2434 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2435 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2436 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2437 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2438
568e10ca 2439 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2440 }
718e3744 2441 }
3064bf43 2442
5424b7ba
MK
2443 /* advertise/withdraw type-5 routes */
2444 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
7b1bf203 2445 if (advertise_type5_routes(bgp, afi) && new_select &&
7e4ed18e
MK
2446 (!new_select->extra || !new_select->extra->parent)) {
2447
2448 /* apply the route-map */
2449 if (bgp->adv_cmd_rmap[afi][safi].map) {
2450 int ret = 0;
2451
3518f352
DS
2452 ret = route_map_apply(
2453 bgp->adv_cmd_rmap[afi][safi].map,
2454 &rn->p, RMAP_BGP, new_select);
7e4ed18e 2455 if (ret == RMAP_MATCH)
3518f352
DS
2456 bgp_evpn_advertise_type5_route(
2457 bgp, &rn->p, new_select->attr,
2458 afi, safi);
7e4ed18e
MK
2459 } else {
2460 bgp_evpn_advertise_type5_route(bgp,
2461 &rn->p,
2462 new_select->attr,
2463 afi, safi);
2464
2465 }
2466 } else if (advertise_type5_routes(bgp, afi) && old_select &&
2467 (!old_select->extra || !old_select->extra->parent))
31310b25 2468 bgp_evpn_withdraw_type5_route(bgp, &rn->p, afi, safi);
5424b7ba
MK
2469 }
2470
d62a17ae 2471 /* Clear any route change flags. */
2472 bgp_zebra_clear_route_change_flags(rn);
3064bf43 2473
18ee8310 2474 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2475 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
18ee8310 2476 bgp_path_info_reap(rn, old_select);
d62a17ae 2477
2478 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2479 return;
718e3744 2480}
2481
aac24838 2482static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 2483{
aac24838
JB
2484 struct bgp_process_queue *pqnode = data;
2485 struct bgp *bgp = pqnode->bgp;
d62a17ae 2486 struct bgp_table *table;
ac021f40 2487 struct bgp_node *rn;
aac24838
JB
2488
2489 /* eoiu marker */
2490 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
2491 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
2492 /* should always have dedicated wq call */
2493 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
2494 return WQ_SUCCESS;
2495 }
2496
ac021f40
LB
2497 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
2498 rn = STAILQ_FIRST(&pqnode->pqueue);
2499 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
b3e1dd3c 2500 STAILQ_NEXT(rn, pq) = NULL; /* complete unlink */
aac24838 2501 table = bgp_node_table(rn);
ac021f40 2502 /* note, new RNs may be added as part of processing */
aac24838 2503 bgp_process_main_one(bgp, rn, table->afi, table->safi);
cb1faec9 2504
aac24838 2505 bgp_unlock_node(rn);
d62a17ae 2506 bgp_table_unlock(table);
2507 }
aac24838
JB
2508
2509 return WQ_SUCCESS;
2510}
2511
2512static void bgp_processq_del(struct work_queue *wq, void *data)
2513{
2514 struct bgp_process_queue *pqnode = data;
2515
2516 bgp_unlock(pqnode->bgp);
2517
2518 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 2519}
2520
d62a17ae 2521void bgp_process_queue_init(void)
200df115 2522{
0ce1ca80 2523 if (!bm->process_main_queue)
d62a17ae 2524 bm->process_main_queue =
2525 work_queue_new(bm->master, "process_main_queue");
2526
aac24838 2527 bm->process_main_queue->spec.workfunc = &bgp_process_wq;
d62a17ae 2528 bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
2529 bm->process_main_queue->spec.max_retries = 0;
2530 bm->process_main_queue->spec.hold = 50;
2531 /* Use a higher yield value of 50ms for main queue processing */
2532 bm->process_main_queue->spec.yield = 50 * 1000L;
200df115 2533}
2534
cfe8d15a 2535static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
2536{
2537 struct bgp_process_queue *pqnode;
2538
a4d82a8a
PZ
2539 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
2540 sizeof(struct bgp_process_queue));
aac24838
JB
2541
2542 /* unlocked in bgp_processq_del */
2543 pqnode->bgp = bgp_lock(bgp);
2544 STAILQ_INIT(&pqnode->pqueue);
2545
aac24838
JB
2546 return pqnode;
2547}
2548
d62a17ae 2549void bgp_process(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)
fee0f4c6 2550{
aac24838
JB
2551#define ARBITRARY_PROCESS_QLEN 10000
2552 struct work_queue *wq = bm->process_main_queue;
d62a17ae 2553 struct bgp_process_queue *pqnode;
cfe8d15a 2554 int pqnode_reuse = 0;
495f0b13 2555
d62a17ae 2556 /* already scheduled for processing? */
2557 if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED))
2558 return;
2e02b9b2 2559
aac24838 2560 if (wq == NULL)
d62a17ae 2561 return;
2562
aac24838 2563 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
2564 limit only if is from the same BGP view and it's not an EOIU marker
2565 */
aac24838
JB
2566 if (work_queue_item_count(wq)) {
2567 struct work_queue_item *item = work_queue_last_item(wq);
2568 pqnode = item->data;
228da428 2569
a4d82a8a
PZ
2570 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
2571 || pqnode->bgp != bgp
2572 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
2573 pqnode = bgp_processq_alloc(bgp);
2574 else
2575 pqnode_reuse = 1;
aac24838 2576 } else
cfe8d15a 2577 pqnode = bgp_processq_alloc(bgp);
aac24838 2578 /* all unlocked in bgp_process_wq */
d62a17ae 2579 bgp_table_lock(bgp_node_table(rn));
aac24838 2580
d62a17ae 2581 SET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838
JB
2582 bgp_lock_node(rn);
2583
60466a63
QY
2584 /* can't be enqueued twice */
2585 assert(STAILQ_NEXT(rn, pq) == NULL);
aac24838
JB
2586 STAILQ_INSERT_TAIL(&pqnode->pqueue, rn, pq);
2587 pqnode->queued++;
2588
cfe8d15a
LB
2589 if (!pqnode_reuse)
2590 work_queue_add(wq, pqnode);
2591
d62a17ae 2592 return;
fee0f4c6 2593}
0a486e5f 2594
d62a17ae 2595void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 2596{
d62a17ae 2597 struct bgp_process_queue *pqnode;
cb1faec9 2598
d62a17ae 2599 if (bm->process_main_queue == NULL)
2600 return;
2e02b9b2 2601
cfe8d15a 2602 pqnode = bgp_processq_alloc(bgp);
cb1faec9 2603
aac24838 2604 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
cfe8d15a 2605 work_queue_add(bm->process_main_queue, pqnode);
cb1faec9
DS
2606}
2607
d62a17ae 2608static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 2609{
d62a17ae 2610 struct peer *peer;
0a486e5f 2611
d62a17ae 2612 peer = THREAD_ARG(thread);
2613 peer->t_pmax_restart = NULL;
0a486e5f 2614
d62a17ae 2615 if (bgp_debug_neighbor_events(peer))
2616 zlog_debug(
2617 "%s Maximum-prefix restart timer expired, restore peering",
2618 peer->host);
0a486e5f 2619
a9bafa95
DS
2620 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
2621 zlog_debug("%s: %s peer_clear failed",
2622 __PRETTY_FUNCTION__, peer->host);
0a486e5f 2623
d62a17ae 2624 return 0;
0a486e5f 2625}
2626
d62a17ae 2627int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
2628 int always)
718e3744 2629{
d62a17ae 2630 iana_afi_t pkt_afi;
5c525538 2631 iana_safi_t pkt_safi;
9cabb64b 2632
d62a17ae 2633 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
2634 return 0;
e0701b79 2635
d62a17ae 2636 if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) {
2637 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2638 PEER_STATUS_PREFIX_LIMIT)
2639 && !always)
2640 return 0;
e0701b79 2641
d62a17ae 2642 zlog_info(
2643 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2644 "limit %ld",
2645 afi_safi_print(afi, safi), peer->host,
2646 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2647 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
2648
2649 if (CHECK_FLAG(peer->af_flags[afi][safi],
2650 PEER_FLAG_MAX_PREFIX_WARNING))
2651 return 0;
2652
2653 /* Convert AFI, SAFI to values for packet. */
2654 pkt_afi = afi_int2iana(afi);
2655 pkt_safi = safi_int2iana(safi);
2656 {
d7c0a89a 2657 uint8_t ndata[7];
d62a17ae 2658
2659 ndata[0] = (pkt_afi >> 8);
2660 ndata[1] = pkt_afi;
2661 ndata[2] = pkt_safi;
2662 ndata[3] = (peer->pmax[afi][safi] >> 24);
2663 ndata[4] = (peer->pmax[afi][safi] >> 16);
2664 ndata[5] = (peer->pmax[afi][safi] >> 8);
2665 ndata[6] = (peer->pmax[afi][safi]);
2666
2667 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2668 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
2669 BGP_NOTIFY_CEASE_MAX_PREFIX,
2670 ndata, 7);
2671 }
2672
2673 /* Dynamic peers will just close their connection. */
2674 if (peer_dynamic_neighbor(peer))
2675 return 1;
2676
2677 /* restart timer start */
2678 if (peer->pmax_restart[afi][safi]) {
2679 peer->v_pmax_restart =
2680 peer->pmax_restart[afi][safi] * 60;
2681
2682 if (bgp_debug_neighbor_events(peer))
2683 zlog_debug(
2684 "%s Maximum-prefix restart timer started for %d secs",
2685 peer->host, peer->v_pmax_restart);
2686
2687 BGP_TIMER_ON(peer->t_pmax_restart,
2688 bgp_maximum_prefix_restart_timer,
2689 peer->v_pmax_restart);
2690 }
2691
2692 return 1;
2693 } else
2694 UNSET_FLAG(peer->af_sflags[afi][safi],
2695 PEER_STATUS_PREFIX_LIMIT);
2696
2697 if (peer->pcount[afi][safi]
2698 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
2699 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2700 PEER_STATUS_PREFIX_THRESHOLD)
2701 && !always)
2702 return 0;
2703
2704 zlog_info(
2705 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2706 afi_safi_print(afi, safi), peer->host,
2707 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2708 SET_FLAG(peer->af_sflags[afi][safi],
2709 PEER_STATUS_PREFIX_THRESHOLD);
2710 } else
2711 UNSET_FLAG(peer->af_sflags[afi][safi],
2712 PEER_STATUS_PREFIX_THRESHOLD);
2713 return 0;
718e3744 2714}
2715
b40d939b 2716/* Unconditionally remove the route from the RIB, without taking
2717 * damping into consideration (eg, because the session went down)
2718 */
40381db7 2719void bgp_rib_remove(struct bgp_node *rn, struct bgp_path_info *pi,
4b7e6066 2720 struct peer *peer, afi_t afi, safi_t safi)
718e3744 2721{
40381db7 2722 bgp_aggregate_decrement(peer->bgp, &rn->p, pi, afi, safi);
d62a17ae 2723
40381db7
DS
2724 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
2725 bgp_path_info_delete(rn, pi); /* keep historical info */
d62a17ae 2726
2727 bgp_process(peer->bgp, rn, afi, safi);
2728}
2729
40381db7 2730static void bgp_rib_withdraw(struct bgp_node *rn, struct bgp_path_info *pi,
d62a17ae 2731 struct peer *peer, afi_t afi, safi_t safi,
2732 struct prefix_rd *prd)
2733{
d62a17ae 2734 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 2735 * the bgp_path_info in the RIB for historical reference.
d62a17ae 2736 */
2737 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
2738 && peer->sort == BGP_PEER_EBGP)
40381db7 2739 if ((bgp_damp_withdraw(pi, rn, afi, safi, 0))
d62a17ae 2740 == BGP_DAMP_SUPPRESSED) {
40381db7 2741 bgp_aggregate_decrement(peer->bgp, &rn->p, pi, afi,
d62a17ae 2742 safi);
2743 return;
2744 }
2745
65efcfce 2746#if ENABLE_BGP_VNC
d62a17ae 2747 if (safi == SAFI_MPLS_VPN) {
2748 struct bgp_node *prn = NULL;
2749 struct bgp_table *table = NULL;
2750
2751 prn = bgp_node_get(peer->bgp->rib[afi][safi],
2752 (struct prefix *)prd);
67009e22
DS
2753 if (bgp_node_has_bgp_path_info_data(prn)) {
2754 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 2755
2756 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 2757 peer->bgp, prd, table, &rn->p, pi);
d62a17ae 2758 }
2759 bgp_unlock_node(prn);
2760 }
2761 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 2762 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 2763
40381db7 2764 vnc_import_bgp_del_route(peer->bgp, &rn->p, pi);
d62a17ae 2765 vnc_import_bgp_exterior_del_route(peer->bgp, &rn->p,
40381db7 2766 pi);
d62a17ae 2767 }
65efcfce 2768 }
d62a17ae 2769#endif
128ea8ab 2770
d62a17ae 2771 /* If this is an EVPN route, process for un-import. */
2772 if (safi == SAFI_EVPN)
40381db7 2773 bgp_evpn_unimport_route(peer->bgp, afi, safi, &rn->p, pi);
128ea8ab 2774
40381db7 2775 bgp_rib_remove(rn, pi, peer, afi, safi);
718e3744 2776}
2777
4b7e6066
DS
2778struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
2779 struct peer *peer, struct attr *attr,
2780 struct bgp_node *rn)
fb018d25 2781{
4b7e6066 2782 struct bgp_path_info *new;
fb018d25 2783
d62a17ae 2784 /* Make new BGP info. */
4b7e6066 2785 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 2786 new->type = type;
2787 new->instance = instance;
2788 new->sub_type = sub_type;
2789 new->peer = peer;
2790 new->attr = attr;
2791 new->uptime = bgp_clock();
2792 new->net = rn;
d62a17ae 2793 return new;
fb018d25
DS
2794}
2795
d62a17ae 2796static void overlay_index_update(struct attr *attr,
2797 struct eth_segment_id *eth_s_id,
2798 union gw_addr *gw_ip)
684a7227 2799{
d62a17ae 2800 if (!attr)
2801 return;
684a7227 2802
d62a17ae 2803 if (eth_s_id == NULL) {
2804 memset(&(attr->evpn_overlay.eth_s_id), 0,
2805 sizeof(struct eth_segment_id));
2806 } else {
2807 memcpy(&(attr->evpn_overlay.eth_s_id), eth_s_id,
2808 sizeof(struct eth_segment_id));
2809 }
2810 if (gw_ip == NULL) {
2811 memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr));
2812 } else {
2813 memcpy(&(attr->evpn_overlay.gw_ip), gw_ip,
2814 sizeof(union gw_addr));
2815 }
684a7227
PG
2816}
2817
40381db7 2818static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 2819 struct eth_segment_id *eth_s_id,
2820 union gw_addr *gw_ip)
2821{
40381db7
DS
2822 struct eth_segment_id *path_eth_s_id, *path_eth_s_id_remote;
2823 union gw_addr *path_gw_ip, *path_gw_ip_remote;
11ebf4ed
DS
2824 union {
2825 struct eth_segment_id esi;
2826 union gw_addr ip;
2827 } temp;
d62a17ae 2828
2829 if (afi != AFI_L2VPN)
2830 return true;
40381db7 2831 if (!path->attr) {
11ebf4ed 2832 memset(&temp, 0, sizeof(temp));
40381db7
DS
2833 path_eth_s_id = &temp.esi;
2834 path_gw_ip = &temp.ip;
11ebf4ed 2835
d62a17ae 2836 if (eth_s_id == NULL && gw_ip == NULL)
2837 return true;
2838 } else {
40381db7
DS
2839 path_eth_s_id = &(path->attr->evpn_overlay.eth_s_id);
2840 path_gw_ip = &(path->attr->evpn_overlay.gw_ip);
d62a17ae 2841 }
11ebf4ed
DS
2842
2843 if (gw_ip == NULL) {
2844 memset(&temp, 0, sizeof(temp));
40381db7 2845 path_gw_ip_remote = &temp.ip;
11ebf4ed 2846 } else
40381db7 2847 path_gw_ip_remote = gw_ip;
11ebf4ed
DS
2848
2849 if (eth_s_id == NULL) {
2850 memset(&temp, 0, sizeof(temp));
40381db7 2851 path_eth_s_id_remote = &temp.esi;
11ebf4ed 2852 } else
40381db7 2853 path_eth_s_id_remote = eth_s_id;
11ebf4ed 2854
40381db7 2855 if (!memcmp(path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr)))
d62a17ae 2856 return false;
11ebf4ed 2857
40381db7 2858 return !memcmp(path_eth_s_id, path_eth_s_id_remote,
d62a17ae 2859 sizeof(struct eth_segment_id));
684a7227
PG
2860}
2861
c265ee22 2862/* Check if received nexthop is valid or not. */
d62a17ae 2863static int bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
2864 struct attr *attr)
2865{
2866 int ret = 0;
2867
2868 /* Only validated for unicast and multicast currently. */
2869 /* Also valid for EVPN where the nexthop is an IP address. */
2870 if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN)
2871 return 0;
2872
2873 /* If NEXT_HOP is present, validate it. */
2874 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
2875 if (attr->nexthop.s_addr == 0
2876 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
2877 || bgp_nexthop_self(bgp, attr->nexthop))
2878 return 1;
2879 }
c265ee22 2880
d62a17ae 2881 /* If MP_NEXTHOP is present, validate it. */
2882 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2883 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2884 * it is not an IPv6 link-local address.
2885 */
2886 if (attr->mp_nexthop_len) {
2887 switch (attr->mp_nexthop_len) {
2888 case BGP_ATTR_NHLEN_IPV4:
2889 case BGP_ATTR_NHLEN_VPNV4:
2890 ret = (attr->mp_nexthop_global_in.s_addr == 0
2891 || IPV4_CLASS_DE(ntohl(
2892 attr->mp_nexthop_global_in.s_addr))
2893 || bgp_nexthop_self(bgp,
2894 attr->mp_nexthop_global_in));
2895 break;
2896
2897 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
2898 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
2899 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
2900 ret = (IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global)
2901 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
2902 || IN6_IS_ADDR_MULTICAST(
2903 &attr->mp_nexthop_global));
2904 break;
2905
2906 default:
2907 ret = 1;
2908 break;
2909 }
2910 }
c265ee22 2911
d62a17ae 2912 return ret;
2913}
2914
d7c0a89a 2915int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
d62a17ae 2916 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 2917 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 2918 uint32_t num_labels, int soft_reconfig,
a4d82a8a 2919 struct bgp_route_evpn *evpn)
d62a17ae 2920{
2921 int ret;
2922 int aspath_loop_count = 0;
2923 struct bgp_node *rn;
2924 struct bgp *bgp;
2925 struct attr new_attr;
2926 struct attr *attr_new;
40381db7 2927 struct bgp_path_info *pi;
4b7e6066
DS
2928 struct bgp_path_info *new;
2929 struct bgp_path_info_extra *extra;
d62a17ae 2930 const char *reason;
2931 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 2932 int connected = 0;
2933 int do_loop_check = 1;
2934 int has_valid_label = 0;
65efcfce 2935#if ENABLE_BGP_VNC
d62a17ae 2936 int vnc_implicit_withdraw = 0;
65efcfce 2937#endif
d62a17ae 2938 int same_attr = 0;
718e3744 2939
d62a17ae 2940 memset(&new_attr, 0, sizeof(struct attr));
2941 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
2942 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 2943
d62a17ae 2944 bgp = peer->bgp;
2945 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
2946 /* TODO: Check to see if we can get rid of "is_valid_label" */
2947 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
2948 has_valid_label = (num_labels > 0) ? 1 : 0;
2949 else
2950 has_valid_label = bgp_is_valid_label(label);
718e3744 2951
d62a17ae 2952 /* When peer's soft reconfiguration enabled. Record input packet in
2953 Adj-RIBs-In. */
2954 if (!soft_reconfig
2955 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
2956 && peer != bgp->peer_self)
2957 bgp_adj_in_set(rn, peer, attr, addpath_id);
2958
2959 /* Check previously received route. */
6f94b685 2960 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
2961 if (pi->peer == peer && pi->type == type
2962 && pi->sub_type == sub_type
2963 && pi->addpath_rx_id == addpath_id)
d62a17ae 2964 break;
2965
2966 /* AS path local-as loop check. */
2967 if (peer->change_local_as) {
c4368918
DW
2968 if (peer->allowas_in[afi][safi])
2969 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
2970 else if (!CHECK_FLAG(peer->flags,
2971 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 2972 aspath_loop_count = 1;
2973
2974 if (aspath_loop_check(attr->aspath, peer->change_local_as)
2975 > aspath_loop_count) {
2976 reason = "as-path contains our own AS;";
2977 goto filtered;
2978 }
718e3744 2979 }
718e3744 2980
d62a17ae 2981 /* If the peer is configured for "allowas-in origin" and the last ASN in
2982 * the
2983 * as-path is our ASN then we do not need to call aspath_loop_check
2984 */
2985 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
2986 if (aspath_get_last_as(attr->aspath) == bgp->as)
2987 do_loop_check = 0;
2988
2989 /* AS path loop check. */
2990 if (do_loop_check) {
2991 if (aspath_loop_check(attr->aspath, bgp->as)
2992 > peer->allowas_in[afi][safi]
2993 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
2994 && aspath_loop_check(attr->aspath, bgp->confed_id)
2995 > peer->allowas_in[afi][safi])) {
2996 reason = "as-path contains our own AS;";
2997 goto filtered;
2998 }
2999 }
aac9ef6c 3000
d62a17ae 3001 /* Route reflector originator ID check. */
3002 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3003 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
3004 reason = "originator is us;";
3005 goto filtered;
3006 }
718e3744 3007
d62a17ae 3008 /* Route reflector cluster ID check. */
3009 if (bgp_cluster_filter(peer, attr)) {
3010 reason = "reflected from the same cluster;";
3011 goto filtered;
3012 }
718e3744 3013
d62a17ae 3014 /* Apply incoming filter. */
3015 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
3016 reason = "filter;";
3017 goto filtered;
3018 }
718e3744 3019
d62a17ae 3020 bgp_attr_dup(&new_attr, attr);
3021
3022 /* Apply incoming route-map.
3023 * NB: new_attr may now contain newly allocated values from route-map
3024 * "set"
3025 * commands, so we need bgp_attr_flush in the error paths, until we
3026 * intern
3027 * the attr (which takes over the memory references) */
3028 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL)
3029 == RMAP_DENY) {
3030 reason = "route-map;";
3031 bgp_attr_flush(&new_attr);
3032 goto filtered;
3033 }
718e3744 3034
7f323236
DW
3035 if (peer->sort == BGP_PEER_EBGP) {
3036
a4d82a8a
PZ
3037 /* If we receive the graceful-shutdown community from an eBGP
3038 * peer we must lower local-preference */
3039 if (new_attr.community
3040 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3041 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3042 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3043
a4d82a8a
PZ
3044 /* If graceful-shutdown is configured then add the GSHUT
3045 * community to all paths received from eBGP peers */
3046 } else if (bgp_flag_check(peer->bgp,
3047 BGP_FLAG_GRACEFUL_SHUTDOWN)) {
7f323236
DW
3048 bgp_attr_add_gshut_community(&new_attr);
3049 }
3050 }
3051
d62a17ae 3052 /* next hop check. */
a4d82a8a
PZ
3053 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
3054 && bgp_update_martian_nexthop(bgp, afi, safi, &new_attr)) {
d62a17ae 3055 reason = "martian or self next-hop;";
3056 bgp_attr_flush(&new_attr);
3057 goto filtered;
3058 }
718e3744 3059
d62a17ae 3060 attr_new = bgp_attr_intern(&new_attr);
3061
3062 /* If the update is implicit withdraw. */
40381db7
DS
3063 if (pi) {
3064 pi->uptime = bgp_clock();
3065 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3066
3067 /* Same attribute comes in. */
40381db7
DS
3068 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3069 && attrhash_cmp(pi->attr, attr_new)
d62a17ae 3070 && (!has_valid_label
40381db7 3071 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3072 num_labels * sizeof(mpls_label_t))
d62a17ae 3073 == 0)
3074 && (overlay_index_equal(
40381db7 3075 afi, pi, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3076 evpn == NULL ? NULL : &evpn->gw_ip))) {
3077 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3078 BGP_CONFIG_DAMPENING)
3079 && peer->sort == BGP_PEER_EBGP
40381db7 3080 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3081 if (bgp_debug_update(peer, p, NULL, 1)) {
3082 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3083 afi, safi, prd, p, label,
3084 num_labels, addpath_id ? 1 : 0,
3085 addpath_id, pfx_buf,
3086 sizeof(pfx_buf));
d62a17ae 3087 zlog_debug("%s rcvd %s", peer->host,
3088 pfx_buf);
3089 }
3090
40381db7 3091 if (bgp_damp_update(pi, rn, afi, safi)
d62a17ae 3092 != BGP_DAMP_SUPPRESSED) {
40381db7 3093 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3094 safi);
3095 bgp_process(bgp, rn, afi, safi);
3096 }
3097 } else /* Duplicate - odd */
3098 {
3099 if (bgp_debug_update(peer, p, NULL, 1)) {
3100 if (!peer->rcvd_attr_printed) {
3101 zlog_debug(
3102 "%s rcvd UPDATE w/ attr: %s",
3103 peer->host,
3104 peer->rcvd_attr_str);
3105 peer->rcvd_attr_printed = 1;
3106 }
3107
3108 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3109 afi, safi, prd, p, label,
3110 num_labels, addpath_id ? 1 : 0,
3111 addpath_id, pfx_buf,
3112 sizeof(pfx_buf));
d62a17ae 3113 zlog_debug(
3114 "%s rcvd %s...duplicate ignored",
3115 peer->host, pfx_buf);
3116 }
3117
3118 /* graceful restart STALE flag unset. */
40381db7 3119 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3120 bgp_path_info_unset_flag(
40381db7 3121 rn, pi, BGP_PATH_STALE);
d62a17ae 3122 bgp_process(bgp, rn, afi, safi);
3123 }
3124 }
3125
3126 bgp_unlock_node(rn);
3127 bgp_attr_unintern(&attr_new);
3128
3129 return 0;
3130 }
718e3744 3131
d62a17ae 3132 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3133 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3134 if (bgp_debug_update(peer, p, NULL, 1)) {
3135 bgp_debug_rdpfxpath2str(
a4d82a8a 3136 afi, safi, prd, p, label, num_labels,
d62a17ae 3137 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3138 sizeof(pfx_buf));
3139 zlog_debug(
3140 "%s rcvd %s, flapped quicker than processing",
3141 peer->host, pfx_buf);
3142 }
3143
40381db7 3144 bgp_path_info_restore(rn, pi);
d62a17ae 3145 }
718e3744 3146
d62a17ae 3147 /* Received Logging. */
3148 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3149 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3150 num_labels, addpath_id ? 1 : 0,
3151 addpath_id, pfx_buf,
3152 sizeof(pfx_buf));
d62a17ae 3153 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3154 }
718e3744 3155
d62a17ae 3156 /* graceful restart STALE flag unset. */
40381db7
DS
3157 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
3158 bgp_path_info_unset_flag(rn, pi, BGP_PATH_STALE);
d62a17ae 3159
3160 /* The attribute is changed. */
40381db7 3161 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3162
3163 /* implicit withdraw, decrement aggregate and pcount here.
3164 * only if update is accepted, they'll increment below.
3165 */
40381db7 3166 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3167
3168 /* Update bgp route dampening information. */
3169 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3170 && peer->sort == BGP_PEER_EBGP) {
3171 /* This is implicit withdraw so we should update
3172 dampening
3173 information. */
40381db7
DS
3174 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
3175 bgp_damp_withdraw(pi, rn, afi, safi, 1);
d62a17ae 3176 }
65efcfce 3177#if ENABLE_BGP_VNC
d62a17ae 3178 if (safi == SAFI_MPLS_VPN) {
3179 struct bgp_node *prn = NULL;
3180 struct bgp_table *table = NULL;
3181
3182 prn = bgp_node_get(bgp->rib[afi][safi],
3183 (struct prefix *)prd);
67009e22
DS
3184 if (bgp_node_has_bgp_path_info_data(prn)) {
3185 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3186
3187 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3188 bgp, prd, table, p, pi);
d62a17ae 3189 }
3190 bgp_unlock_node(prn);
3191 }
3192 if ((afi == AFI_IP || afi == AFI_IP6)
3193 && (safi == SAFI_UNICAST)) {
40381db7 3194 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3195 /*
3196 * Implicit withdraw case.
3197 */
3198 ++vnc_implicit_withdraw;
40381db7
DS
3199 vnc_import_bgp_del_route(bgp, p, pi);
3200 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3201 }
3202 }
65efcfce 3203#endif
128ea8ab 3204
d62a17ae 3205 /* Special handling for EVPN update of an existing route. If the
3206 * extended community attribute has changed, we need to
3207 * un-import
3208 * the route using its existing extended community. It will be
3209 * subsequently processed for import with the new extended
3210 * community.
3211 */
3212 if (safi == SAFI_EVPN && !same_attr) {
40381db7 3213 if ((pi->attr->flag
d62a17ae 3214 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3215 && (attr_new->flag
3216 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3217 int cmp;
3218
40381db7 3219 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3220 attr_new->ecommunity);
3221 if (!cmp) {
3222 if (bgp_debug_update(peer, p, NULL, 1))
3223 zlog_debug(
3224 "Change in EXT-COMM, existing %s new %s",
3225 ecommunity_str(
40381db7 3226 pi->attr->ecommunity),
d62a17ae 3227 ecommunity_str(
3228 attr_new->ecommunity));
3229 bgp_evpn_unimport_route(bgp, afi, safi,
40381db7 3230 p, pi);
d62a17ae 3231 }
3232 }
3233 }
718e3744 3234
d62a17ae 3235 /* Update to new attribute. */
40381db7
DS
3236 bgp_attr_unintern(&pi->attr);
3237 pi->attr = attr_new;
d62a17ae 3238
3239 /* Update MPLS label */
3240 if (has_valid_label) {
40381db7 3241 extra = bgp_path_info_extra_get(pi);
b57ba6d2
MK
3242 memcpy(&extra->label, label,
3243 num_labels * sizeof(mpls_label_t));
3244 extra->num_labels = num_labels;
3245 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3246 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3247 }
718e3744 3248
65efcfce 3249#if ENABLE_BGP_VNC
d62a17ae 3250 if ((afi == AFI_IP || afi == AFI_IP6)
3251 && (safi == SAFI_UNICAST)) {
3252 if (vnc_implicit_withdraw) {
3253 /*
3254 * Add back the route with its new attributes
3255 * (e.g., nexthop).
3256 * The route is still selected, until the route
3257 * selection
3258 * queued by bgp_process actually runs. We have
3259 * to make this
3260 * update to the VNC side immediately to avoid
3261 * racing against
3262 * configuration changes (e.g., route-map
3263 * changes) which
3264 * trigger re-importation of the entire RIB.
3265 */
40381db7
DS
3266 vnc_import_bgp_add_route(bgp, p, pi);
3267 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 3268 }
3269 }
65efcfce 3270#endif
d62a17ae 3271 /* Update Overlay Index */
3272 if (afi == AFI_L2VPN) {
3273 overlay_index_update(
40381db7 3274 pi->attr, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3275 evpn == NULL ? NULL : &evpn->gw_ip);
3276 }
65efcfce 3277
d62a17ae 3278 /* Update bgp route dampening information. */
3279 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3280 && peer->sort == BGP_PEER_EBGP) {
3281 /* Now we do normal update dampening. */
40381db7 3282 ret = bgp_damp_update(pi, rn, afi, safi);
d62a17ae 3283 if (ret == BGP_DAMP_SUPPRESSED) {
3284 bgp_unlock_node(rn);
3285 return 0;
3286 }
3287 }
128ea8ab 3288
d62a17ae 3289 /* Nexthop reachability check - for unicast and
3290 * labeled-unicast.. */
3291 if ((afi == AFI_IP || afi == AFI_IP6)
3292 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
3293 if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1
3294 && !CHECK_FLAG(peer->flags,
3295 PEER_FLAG_DISABLE_CONNECTED_CHECK)
3296 && !bgp_flag_check(
3297 bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
3298 connected = 1;
3299 else
3300 connected = 0;
3301
960035b2
PZ
3302 struct bgp *bgp_nexthop = bgp;
3303
40381db7
DS
3304 if (pi->extra && pi->extra->bgp_orig)
3305 bgp_nexthop = pi->extra->bgp_orig;
960035b2 3306
40381db7
DS
3307 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, afi, pi,
3308 NULL, connected)
a4d82a8a 3309 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
40381db7 3310 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 3311 else {
3312 if (BGP_DEBUG(nht, NHT)) {
3313 char buf1[INET6_ADDRSTRLEN];
3314 inet_ntop(AF_INET,
3315 (const void *)&attr_new
3316 ->nexthop,
3317 buf1, INET6_ADDRSTRLEN);
3318 zlog_debug("%s(%s): NH unresolved",
3319 __FUNCTION__, buf1);
3320 }
40381db7 3321 bgp_path_info_unset_flag(rn, pi,
18ee8310 3322 BGP_PATH_VALID);
d62a17ae 3323 }
3324 } else
40381db7 3325 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 3326
3327#if ENABLE_BGP_VNC
3328 if (safi == SAFI_MPLS_VPN) {
3329 struct bgp_node *prn = NULL;
3330 struct bgp_table *table = NULL;
3331
3332 prn = bgp_node_get(bgp->rib[afi][safi],
3333 (struct prefix *)prd);
67009e22
DS
3334 if (bgp_node_has_bgp_path_info_data(prn)) {
3335 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3336
3337 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 3338 bgp, prd, table, p, pi);
d62a17ae 3339 }
3340 bgp_unlock_node(prn);
3341 }
3342#endif
718e3744 3343
d62a17ae 3344 /* If this is an EVPN route and some attribute has changed,
3345 * process
3346 * route for import. If the extended community has changed, we
3347 * would
3348 * have done the un-import earlier and the import would result
3349 * in the
3350 * route getting injected into appropriate L2 VNIs. If it is
3351 * just
3352 * some other attribute change, the import will result in
3353 * updating
3354 * the attributes for the route in the VNI(s).
3355 */
3356 if (safi == SAFI_EVPN && !same_attr)
40381db7 3357 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 3358
3359 /* Process change. */
40381db7 3360 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 3361
3362 bgp_process(bgp, rn, afi, safi);
3363 bgp_unlock_node(rn);
558d1fec 3364
ddb5b488
PZ
3365 if (SAFI_UNICAST == safi
3366 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3367 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3368
40381db7 3369 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3370 }
3371 if ((SAFI_MPLS_VPN == safi)
3372 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3373
40381db7 3374 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
3375 }
3376
28070ee3 3377#if ENABLE_BGP_VNC
d62a17ae 3378 if (SAFI_MPLS_VPN == safi) {
3379 mpls_label_t label_decoded = decode_label(label);
28070ee3 3380
d62a17ae 3381 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3382 type, sub_type, &label_decoded);
3383 }
3384 if (SAFI_ENCAP == safi) {
3385 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3386 type, sub_type, NULL);
3387 }
28070ee3
PZ
3388#endif
3389
d62a17ae 3390 return 0;
3391 } // End of implicit withdraw
718e3744 3392
d62a17ae 3393 /* Received Logging. */
3394 if (bgp_debug_update(peer, p, NULL, 1)) {
3395 if (!peer->rcvd_attr_printed) {
3396 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3397 peer->rcvd_attr_str);
3398 peer->rcvd_attr_printed = 1;
3399 }
718e3744 3400
a4d82a8a 3401 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3402 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3403 sizeof(pfx_buf));
3404 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3405 }
718e3744 3406
d62a17ae 3407 /* Make new BGP info. */
3408 new = info_make(type, sub_type, 0, peer, attr_new, rn);
718e3744 3409
d62a17ae 3410 /* Update MPLS label */
3411 if (has_valid_label) {
18ee8310 3412 extra = bgp_path_info_extra_get(new);
a4d82a8a 3413 memcpy(&extra->label, label, num_labels * sizeof(mpls_label_t));
b57ba6d2
MK
3414 extra->num_labels = num_labels;
3415 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3416 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3417 }
718e3744 3418
d62a17ae 3419 /* Update Overlay Index */
3420 if (afi == AFI_L2VPN) {
3421 overlay_index_update(new->attr,
3422 evpn == NULL ? NULL : &evpn->eth_s_id,
3423 evpn == NULL ? NULL : &evpn->gw_ip);
3424 }
3425 /* Nexthop reachability check. */
3426 if ((afi == AFI_IP || afi == AFI_IP6)
3427 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
3428 if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1
3429 && !CHECK_FLAG(peer->flags,
3430 PEER_FLAG_DISABLE_CONNECTED_CHECK)
3431 && !bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
3432 connected = 1;
3433 else
3434 connected = 0;
3435
960035b2 3436 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, connected)
a4d82a8a 3437 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
18ee8310 3438 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
d62a17ae 3439 else {
3440 if (BGP_DEBUG(nht, NHT)) {
3441 char buf1[INET6_ADDRSTRLEN];
3442 inet_ntop(AF_INET,
3443 (const void *)&attr_new->nexthop,
3444 buf1, INET6_ADDRSTRLEN);
3445 zlog_debug("%s(%s): NH unresolved",
3446 __FUNCTION__, buf1);
3447 }
18ee8310 3448 bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID);
d62a17ae 3449 }
3450 } else
18ee8310 3451 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
a82478b9 3452
d62a17ae 3453 /* Addpath ID */
3454 new->addpath_rx_id = addpath_id;
3455
3456 /* Increment prefix */
3457 bgp_aggregate_increment(bgp, p, new, afi, safi);
3458
3459 /* Register new BGP information. */
18ee8310 3460 bgp_path_info_add(rn, new);
d62a17ae 3461
3462 /* route_node_get lock */
3463 bgp_unlock_node(rn);
558d1fec 3464
65efcfce 3465#if ENABLE_BGP_VNC
d62a17ae 3466 if (safi == SAFI_MPLS_VPN) {
3467 struct bgp_node *prn = NULL;
3468 struct bgp_table *table = NULL;
3469
3470 prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
67009e22
DS
3471 if (bgp_node_has_bgp_path_info_data(prn)) {
3472 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3473
3474 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3475 bgp, prd, table, p, new);
3476 }
3477 bgp_unlock_node(prn);
3478 }
65efcfce
LB
3479#endif
3480
d62a17ae 3481 /* If maximum prefix count is configured and current prefix
3482 count exeed it. */
3483 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3484 return -1;
718e3744 3485
d62a17ae 3486 /* If this is an EVPN route, process for import. */
3487 if (safi == SAFI_EVPN)
3488 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 3489
d62a17ae 3490 /* Process change. */
3491 bgp_process(bgp, rn, afi, safi);
718e3744 3492
ddb5b488
PZ
3493 if (SAFI_UNICAST == safi
3494 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3495 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3496 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
3497 }
3498 if ((SAFI_MPLS_VPN == safi)
3499 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3500
3501 vpn_leak_to_vrf_update(bgp, new);
3502 }
28070ee3 3503#if ENABLE_BGP_VNC
d62a17ae 3504 if (SAFI_MPLS_VPN == safi) {
3505 mpls_label_t label_decoded = decode_label(label);
28070ee3 3506
d62a17ae 3507 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3508 sub_type, &label_decoded);
3509 }
3510 if (SAFI_ENCAP == safi) {
3511 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3512 sub_type, NULL);
3513 }
28070ee3
PZ
3514#endif
3515
d62a17ae 3516 return 0;
718e3744 3517
d62a17ae 3518/* This BGP update is filtered. Log the reason then update BGP
3519 entry. */
3520filtered:
3521 if (bgp_debug_update(peer, p, NULL, 1)) {
3522 if (!peer->rcvd_attr_printed) {
3523 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3524 peer->rcvd_attr_str);
3525 peer->rcvd_attr_printed = 1;
3526 }
718e3744 3527
a4d82a8a 3528 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3529 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3530 sizeof(pfx_buf));
3531 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3532 peer->host, pfx_buf, reason);
3533 }
128ea8ab 3534
40381db7 3535 if (pi) {
d62a17ae 3536 /* If this is an EVPN route, un-import it as it is now filtered.
3537 */
3538 if (safi == SAFI_EVPN)
40381db7 3539 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 3540
ddb5b488
PZ
3541 if (SAFI_UNICAST == safi
3542 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3543 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3544
40381db7 3545 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3546 }
3547 if ((SAFI_MPLS_VPN == safi)
3548 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3549
40381db7 3550 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
3551 }
3552
40381db7 3553 bgp_rib_remove(rn, pi, peer, afi, safi);
d62a17ae 3554 }
3555
3556 bgp_unlock_node(rn);
558d1fec 3557
97736e32 3558#if ENABLE_BGP_VNC
d62a17ae 3559 /*
3560 * Filtered update is treated as an implicit withdrawal (see
3561 * bgp_rib_remove()
3562 * a few lines above)
3563 */
3564 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
3565 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
3566 0);
3567 }
97736e32
PZ
3568#endif
3569
d62a17ae 3570 return 0;
718e3744 3571}
3572
d7c0a89a 3573int bgp_withdraw(struct peer *peer, struct prefix *p, uint32_t addpath_id,
d62a17ae 3574 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3575 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3576 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 3577{
d62a17ae 3578 struct bgp *bgp;
3579 char pfx_buf[BGP_PRD_PATH_STRLEN];
3580 struct bgp_node *rn;
40381db7 3581 struct bgp_path_info *pi;
718e3744 3582
28070ee3 3583#if ENABLE_BGP_VNC
d62a17ae 3584 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
3585 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
3586 0);
3587 }
28070ee3
PZ
3588#endif
3589
d62a17ae 3590 bgp = peer->bgp;
3591
3592 /* Lookup node. */
3593 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
3594
3595 /* If peer is soft reconfiguration enabled. Record input packet for
3596 * further calculation.
3597 *
3598 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3599 * routes that are filtered. This tanks out Quagga RS pretty badly due
3600 * to
3601 * the iteration over all RS clients.
3602 * Since we need to remove the entry from adj_in anyway, do that first
3603 * and
3604 * if there was no entry, we don't need to do anything more.
3605 */
3606 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3607 && peer != bgp->peer_self)
3608 if (!bgp_adj_in_unset(rn, peer, addpath_id)) {
3609 if (bgp_debug_update(peer, p, NULL, 1)) {
3610 bgp_debug_rdpfxpath2str(
a4d82a8a 3611 afi, safi, prd, p, label, num_labels,
d62a17ae 3612 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3613 sizeof(pfx_buf));
3614 zlog_debug(
3615 "%s withdrawing route %s not in adj-in",
3616 peer->host, pfx_buf);
3617 }
3618 bgp_unlock_node(rn);
3619 return 0;
3620 }
cd808e74 3621
d62a17ae 3622 /* Lookup withdrawn route. */
6f94b685 3623 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
3624 if (pi->peer == peer && pi->type == type
3625 && pi->sub_type == sub_type
3626 && pi->addpath_rx_id == addpath_id)
d62a17ae 3627 break;
3628
3629 /* Logging. */
3630 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 3631 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3632 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3633 sizeof(pfx_buf));
3634 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
3635 pfx_buf);
3636 }
718e3744 3637
d62a17ae 3638 /* Withdraw specified route from routing table. */
40381db7
DS
3639 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
3640 bgp_rib_withdraw(rn, pi, peer, afi, safi, prd);
ddb5b488
PZ
3641 if (SAFI_UNICAST == safi
3642 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3643 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 3644 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3645 }
3646 if ((SAFI_MPLS_VPN == safi)
3647 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3648
40381db7 3649 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
3650 }
3651 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 3652 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3653 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3654 sizeof(pfx_buf));
3655 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
3656 }
718e3744 3657
d62a17ae 3658 /* Unlock bgp_node_get() lock. */
3659 bgp_unlock_node(rn);
3660
3661 return 0;
718e3744 3662}
6b0655a2 3663
d62a17ae 3664void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
3665 int withdraw)
718e3744 3666{
d62a17ae 3667 struct update_subgroup *subgrp;
3668 subgrp = peer_subgroup(peer, afi, safi);
3669 subgroup_default_originate(subgrp, withdraw);
3f9c7369 3670}
6182d65b 3671
718e3744 3672
3f9c7369
DS
3673/*
3674 * bgp_stop_announce_route_timer
3675 */
d62a17ae 3676void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 3677{
d62a17ae 3678 if (!paf->t_announce_route)
3679 return;
3680
3681 THREAD_TIMER_OFF(paf->t_announce_route);
718e3744 3682}
6b0655a2 3683
3f9c7369
DS
3684/*
3685 * bgp_announce_route_timer_expired
3686 *
3687 * Callback that is invoked when the route announcement timer for a
3688 * peer_af expires.
3689 */
d62a17ae 3690static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 3691{
d62a17ae 3692 struct peer_af *paf;
3693 struct peer *peer;
558d1fec 3694
d62a17ae 3695 paf = THREAD_ARG(t);
3696 peer = paf->peer;
718e3744 3697
d62a17ae 3698 if (peer->status != Established)
3699 return 0;
3f9c7369 3700
d62a17ae 3701 if (!peer->afc_nego[paf->afi][paf->safi])
3702 return 0;
3f9c7369 3703
d62a17ae 3704 peer_af_announce_route(paf, 1);
3705 return 0;
718e3744 3706}
3707
3f9c7369
DS
3708/*
3709 * bgp_announce_route
3710 *
3711 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3712 */
d62a17ae 3713void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
3714{
3715 struct peer_af *paf;
3716 struct update_subgroup *subgrp;
3717
3718 paf = peer_af_find(peer, afi, safi);
3719 if (!paf)
3720 return;
3721 subgrp = PAF_SUBGRP(paf);
3722
3723 /*
3724 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3725 * or a refresh has already been triggered.
3726 */
3727 if (!subgrp || paf->t_announce_route)
3728 return;
3729
3730 /*
3731 * Start a timer to stagger/delay the announce. This serves
3732 * two purposes - announcement can potentially be combined for
3733 * multiple peers and the announcement doesn't happen in the
3734 * vty context.
3735 */
3736 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
3737 (subgrp->peer_count == 1)
3738 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3739 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
3740 &paf->t_announce_route);
3f9c7369
DS
3741}
3742
3743/*
3744 * Announce routes from all AF tables to a peer.
3745 *
3746 * This should ONLY be called when there is a need to refresh the
3747 * routes to the peer based on a policy change for this peer alone
3748 * or a route refresh request received from the peer.
3749 * The operation will result in splitting the peer from its existing
3750 * subgroups and putting it in new subgroups.
3751 */
d62a17ae 3752void bgp_announce_route_all(struct peer *peer)
718e3744 3753{
d62a17ae 3754 afi_t afi;
3755 safi_t safi;
3756
05c7a1cc
QY
3757 FOREACH_AFI_SAFI (afi, safi)
3758 bgp_announce_route(peer, afi, safi);
718e3744 3759}
6b0655a2 3760
d62a17ae 3761static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
3762 struct bgp_table *table,
3763 struct prefix_rd *prd)
718e3744 3764{
d62a17ae 3765 int ret;
3766 struct bgp_node *rn;
3767 struct bgp_adj_in *ain;
718e3744 3768
d62a17ae 3769 if (!table)
3770 table = peer->bgp->rib[afi][safi];
718e3744 3771
d62a17ae 3772 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
3773 for (ain = rn->adj_in; ain; ain = ain->next) {
ea47320b
DL
3774 if (ain->peer != peer)
3775 continue;
8692c506 3776
6f94b685
DS
3777 struct bgp_path_info *pi =
3778 bgp_node_get_bgp_path_info(rn);
d7c0a89a 3779 uint32_t num_labels = 0;
b57ba6d2
MK
3780 mpls_label_t *label_pnt = NULL;
3781
40381db7
DS
3782 if (pi && pi->extra)
3783 num_labels = pi->extra->num_labels;
b57ba6d2 3784 if (num_labels)
40381db7 3785 label_pnt = &pi->extra->label[0];
8692c506 3786
ea47320b
DL
3787 ret = bgp_update(peer, &rn->p, ain->addpath_rx_id,
3788 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
3789 BGP_ROUTE_NORMAL, prd, label_pnt,
3790 num_labels, 1, NULL);
ea47320b
DL
3791
3792 if (ret < 0) {
3793 bgp_unlock_node(rn);
3794 return;
d62a17ae 3795 }
3796 }
718e3744 3797}
3798
d62a17ae 3799void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 3800{
d62a17ae 3801 struct bgp_node *rn;
3802 struct bgp_table *table;
718e3744 3803
d62a17ae 3804 if (peer->status != Established)
3805 return;
718e3744 3806
d62a17ae 3807 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
3808 && (safi != SAFI_EVPN))
3809 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
3810 else
3811 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
67009e22
DS
3812 rn = bgp_route_next(rn)) {
3813 table = bgp_node_get_bgp_table_info(rn);
3814 if (table != NULL) {
d62a17ae 3815 struct prefix_rd prd;
67009e22 3816
d62a17ae 3817 prd.family = AF_UNSPEC;
3818 prd.prefixlen = 64;
3819 memcpy(&prd.val, rn->p.u.val, 8);
8692c506 3820
d62a17ae 3821 bgp_soft_reconfig_table(peer, afi, safi, table,
3822 &prd);
3823 }
67009e22 3824 }
718e3744 3825}
6b0655a2 3826
228da428 3827
d62a17ae 3828struct bgp_clear_node_queue {
3829 struct bgp_node *rn;
228da428
CC
3830};
3831
d62a17ae 3832static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 3833{
d62a17ae 3834 struct bgp_clear_node_queue *cnq = data;
3835 struct bgp_node *rn = cnq->rn;
3836 struct peer *peer = wq->spec.data;
40381db7 3837 struct bgp_path_info *pi;
3103e8d2 3838 struct bgp *bgp;
d62a17ae 3839 afi_t afi = bgp_node_table(rn)->afi;
3840 safi_t safi = bgp_node_table(rn)->safi;
3841
3842 assert(rn && peer);
3103e8d2 3843 bgp = peer->bgp;
d62a17ae 3844
3845 /* It is possible that we have multiple paths for a prefix from a peer
3846 * if that peer is using AddPath.
3847 */
6f94b685 3848 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 3849 if (pi->peer != peer)
ea47320b
DL
3850 continue;
3851
3852 /* graceful restart STALE flag set. */
3853 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
3854 && peer->nsf[afi][safi]
40381db7
DS
3855 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
3856 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
3857 bgp_path_info_set_flag(rn, pi, BGP_PATH_STALE);
ea47320b
DL
3858 else {
3859 /* If this is an EVPN route, process for
3860 * un-import. */
3861 if (safi == SAFI_EVPN)
40381db7
DS
3862 bgp_evpn_unimport_route(bgp, afi, safi, &rn->p,
3863 pi);
3103e8d2
DS
3864 /* Handle withdraw for VRF route-leaking and L3VPN */
3865 if (SAFI_UNICAST == safi
3866 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 3867 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 3868 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 3869 bgp, pi);
960035b2 3870 }
3103e8d2 3871 if (SAFI_MPLS_VPN == safi &&
960035b2 3872 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 3873 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 3874 }
3103e8d2 3875
40381db7 3876 bgp_rib_remove(rn, pi, peer, afi, safi);
d62a17ae 3877 }
ea47320b 3878 }
d62a17ae 3879 return WQ_SUCCESS;
200df115 3880}
3881
d62a17ae 3882static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 3883{
d62a17ae 3884 struct bgp_clear_node_queue *cnq = data;
3885 struct bgp_node *rn = cnq->rn;
3886 struct bgp_table *table = bgp_node_table(rn);
228da428 3887
d62a17ae 3888 bgp_unlock_node(rn);
3889 bgp_table_unlock(table);
3890 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 3891}
3892
d62a17ae 3893static void bgp_clear_node_complete(struct work_queue *wq)
200df115 3894{
d62a17ae 3895 struct peer *peer = wq->spec.data;
64e580a7 3896
d62a17ae 3897 /* Tickle FSM to start moving again */
3898 BGP_EVENT_ADD(peer, Clearing_Completed);
3899
3900 peer_unlock(peer); /* bgp_clear_route */
200df115 3901}
718e3744 3902
d62a17ae 3903static void bgp_clear_node_queue_init(struct peer *peer)
200df115 3904{
d62a17ae 3905 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3906
3907 snprintf(wname, sizeof(wname), "clear %s", peer->host);
3908#undef CLEAR_QUEUE_NAME_LEN
3909
0ce1ca80 3910 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 3911 peer->clear_node_queue->spec.hold = 10;
3912 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
3913 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
3914 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
3915 peer->clear_node_queue->spec.max_retries = 0;
3916
3917 /* we only 'lock' this peer reference when the queue is actually active
3918 */
3919 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
3920}
3921
d62a17ae 3922static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
3923 struct bgp_table *table)
65ca75e0 3924{
d62a17ae 3925 struct bgp_node *rn;
3926 int force = bm->process_main_queue ? 0 : 1;
6cf159b9 3927
d62a17ae 3928 if (!table)
3929 table = peer->bgp->rib[afi][safi];
dc83d712 3930
d62a17ae 3931 /* If still no table => afi/safi isn't configured at all or smth. */
3932 if (!table)
3933 return;
dc83d712 3934
d62a17ae 3935 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
40381db7 3936 struct bgp_path_info *pi, *next;
d62a17ae 3937 struct bgp_adj_in *ain;
3938 struct bgp_adj_in *ain_next;
3939
3940 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3941 * queued for every clearing peer, regardless of whether it is
3942 * relevant to the peer at hand.
3943 *
3944 * Overview: There are 3 different indices which need to be
3945 * scrubbed, potentially, when a peer is removed:
3946 *
3947 * 1 peer's routes visible via the RIB (ie accepted routes)
3948 * 2 peer's routes visible by the (optional) peer's adj-in index
3949 * 3 other routes visible by the peer's adj-out index
3950 *
3951 * 3 there is no hurry in scrubbing, once the struct peer is
3952 * removed from bgp->peer, we could just GC such deleted peer's
3953 * adj-outs at our leisure.
3954 *
3955 * 1 and 2 must be 'scrubbed' in some way, at least made
3956 * invisible via RIB index before peer session is allowed to be
3957 * brought back up. So one needs to know when such a 'search' is
3958 * complete.
3959 *
3960 * Ideally:
3961 *
3962 * - there'd be a single global queue or a single RIB walker
3963 * - rather than tracking which route_nodes still need to be
3964 * examined on a peer basis, we'd track which peers still
3965 * aren't cleared
3966 *
3967 * Given that our per-peer prefix-counts now should be reliable,
3968 * this may actually be achievable. It doesn't seem to be a huge
3969 * problem at this time,
3970 *
3971 * It is possible that we have multiple paths for a prefix from
3972 * a peer
3973 * if that peer is using AddPath.
3974 */
3975 ain = rn->adj_in;
3976 while (ain) {
3977 ain_next = ain->next;
3978
3979 if (ain->peer == peer) {
3980 bgp_adj_in_remove(rn, ain);
3981 bgp_unlock_node(rn);
3982 }
3983
3984 ain = ain_next;
3985 }
3986
6f94b685 3987 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
40381db7
DS
3988 next = pi->next;
3989 if (pi->peer != peer)
d62a17ae 3990 continue;
3991
3992 if (force)
40381db7 3993 bgp_path_info_reap(rn, pi);
d62a17ae 3994 else {
3995 struct bgp_clear_node_queue *cnq;
3996
3997 /* both unlocked in bgp_clear_node_queue_del */
3998 bgp_table_lock(bgp_node_table(rn));
3999 bgp_lock_node(rn);
4000 cnq = XCALLOC(
4001 MTYPE_BGP_CLEAR_NODE_QUEUE,
4002 sizeof(struct bgp_clear_node_queue));
4003 cnq->rn = rn;
4004 work_queue_add(peer->clear_node_queue, cnq);
4005 break;
4006 }
4007 }
4008 }
4009 return;
4010}
4011
4012void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4013{
4014 struct bgp_node *rn;
4015 struct bgp_table *table;
4016
4017 if (peer->clear_node_queue == NULL)
4018 bgp_clear_node_queue_init(peer);
4019
4020 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4021 * Idle until it receives a Clearing_Completed event. This protects
4022 * against peers which flap faster than we can we clear, which could
4023 * lead to:
4024 *
4025 * a) race with routes from the new session being installed before
4026 * clear_route_node visits the node (to delete the route of that
4027 * peer)
4028 * b) resource exhaustion, clear_route_node likely leads to an entry
4029 * on the process_main queue. Fast-flapping could cause that queue
4030 * to grow and grow.
4031 */
4032
4033 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4034 * the unlock will happen upon work-queue completion; other wise, the
4035 * unlock happens at the end of this function.
4036 */
4037 if (!peer->clear_node_queue->thread)
4038 peer_lock(peer);
4039
4040 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4041 bgp_clear_route_table(peer, afi, safi, NULL);
4042 else
4043 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
67009e22
DS
4044 rn = bgp_route_next(rn)) {
4045 table = bgp_node_get_bgp_table_info(rn);
4046 if (!table)
4047 continue;
4048
4049 bgp_clear_route_table(peer, afi, safi, table);
4050 }
d62a17ae 4051
4052 /* unlock if no nodes got added to the clear-node-queue. */
4053 if (!peer->clear_node_queue->thread)
4054 peer_unlock(peer);
718e3744 4055}
d62a17ae 4056
4057void bgp_clear_route_all(struct peer *peer)
718e3744 4058{
d62a17ae 4059 afi_t afi;
4060 safi_t safi;
718e3744 4061
05c7a1cc
QY
4062 FOREACH_AFI_SAFI (afi, safi)
4063 bgp_clear_route(peer, afi, safi);
65efcfce
LB
4064
4065#if ENABLE_BGP_VNC
d62a17ae 4066 rfapiProcessPeerDown(peer);
65efcfce 4067#endif
718e3744 4068}
4069
d62a17ae 4070void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4071{
d62a17ae 4072 struct bgp_table *table;
4073 struct bgp_node *rn;
4074 struct bgp_adj_in *ain;
4075 struct bgp_adj_in *ain_next;
718e3744 4076
d62a17ae 4077 table = peer->bgp->rib[afi][safi];
718e3744 4078
d62a17ae 4079 /* It is possible that we have multiple paths for a prefix from a peer
4080 * if that peer is using AddPath.
4081 */
4082 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
4083 ain = rn->adj_in;
43143c8f 4084
d62a17ae 4085 while (ain) {
4086 ain_next = ain->next;
43143c8f 4087
d62a17ae 4088 if (ain->peer == peer) {
4089 bgp_adj_in_remove(rn, ain);
4090 bgp_unlock_node(rn);
4091 }
43143c8f 4092
d62a17ae 4093 ain = ain_next;
4094 }
4095 }
718e3744 4096}
93406d87 4097
d62a17ae 4098void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4099{
4100 struct bgp_node *rn;
40381db7 4101 struct bgp_path_info *pi;
d62a17ae 4102 struct bgp_table *table;
4103
4104 if (safi == SAFI_MPLS_VPN) {
4105 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4106 rn = bgp_route_next(rn)) {
4107 struct bgp_node *rm;
d62a17ae 4108
4109 /* look for neighbor in tables */
67009e22
DS
4110 table = bgp_node_get_bgp_table_info(rn);
4111 if (!table)
ea47320b
DL
4112 continue;
4113
4114 for (rm = bgp_table_top(table); rm;
4115 rm = bgp_route_next(rm))
6f94b685
DS
4116 for (pi = bgp_node_get_bgp_path_info(rm); pi;
4117 pi = pi->next) {
40381db7 4118 if (pi->peer != peer)
ea47320b 4119 continue;
40381db7 4120 if (!CHECK_FLAG(pi->flags,
1defdda8 4121 BGP_PATH_STALE))
ea47320b
DL
4122 break;
4123
40381db7 4124 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4125 break;
4126 }
d62a17ae 4127 }
4128 } else {
4129 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4130 rn = bgp_route_next(rn))
6f94b685
DS
4131 for (pi = bgp_node_get_bgp_path_info(rn); pi;
4132 pi = pi->next) {
40381db7 4133 if (pi->peer != peer)
ea47320b 4134 continue;
40381db7 4135 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4136 break;
40381db7 4137 bgp_rib_remove(rn, pi, peer, afi, safi);
ea47320b
DL
4138 break;
4139 }
d62a17ae 4140 }
93406d87 4141}
6b0655a2 4142
568e10ca 4143static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
4144 safi_t safi)
bb86c601 4145{
d62a17ae 4146 struct bgp_node *rn;
40381db7 4147 struct bgp_path_info *pi;
4b7e6066 4148 struct bgp_path_info *next;
bb86c601 4149
d62a17ae 4150 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
6f94b685 4151 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
40381db7
DS
4152 next = pi->next;
4153 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
4154 && pi->type == ZEBRA_ROUTE_BGP
4155 && (pi->sub_type == BGP_ROUTE_NORMAL
4156 || pi->sub_type == BGP_ROUTE_AGGREGATE
4157 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 4158
d62a17ae 4159 if (bgp_fibupd_safi(safi))
40381db7
DS
4160 bgp_zebra_withdraw(&rn->p, pi, bgp,
4161 safi);
4162 bgp_path_info_reap(rn, pi);
d62a17ae 4163 }
4164 }
bb86c601
LB
4165}
4166
718e3744 4167/* Delete all kernel routes. */
d62a17ae 4168void bgp_cleanup_routes(struct bgp *bgp)
4169{
4170 afi_t afi;
4171 struct bgp_node *rn;
67009e22 4172 struct bgp_table *table;
d62a17ae 4173
4174 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
4175 if (afi == AFI_L2VPN)
4176 continue;
568e10ca 4177 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
4178 SAFI_UNICAST);
d62a17ae 4179 /*
4180 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4181 */
4182 if (afi != AFI_L2VPN) {
4183 safi_t safi;
4184 safi = SAFI_MPLS_VPN;
4185 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4186 rn = bgp_route_next(rn)) {
67009e22
DS
4187 table = bgp_node_get_bgp_table_info(rn);
4188 if (table != NULL) {
4189 bgp_cleanup_table(bgp, table, safi);
4190 bgp_table_finish(&table);
4191 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4192 bgp_unlock_node(rn);
4193 }
4194 }
4195 safi = SAFI_ENCAP;
4196 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4197 rn = bgp_route_next(rn)) {
67009e22
DS
4198 table = bgp_node_get_bgp_table_info(rn);
4199 if (table != NULL) {
4200 bgp_cleanup_table(bgp, table, safi);
4201 bgp_table_finish(&table);
4202 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4203 bgp_unlock_node(rn);
4204 }
4205 }
4206 }
4207 }
4208 for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn;
4209 rn = bgp_route_next(rn)) {
67009e22
DS
4210 table = bgp_node_get_bgp_table_info(rn);
4211 if (table != NULL) {
4212 bgp_cleanup_table(bgp, table, SAFI_EVPN);
4213 bgp_table_finish(&table);
4214 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4215 bgp_unlock_node(rn);
4216 }
bb86c601 4217 }
718e3744 4218}
4219
d62a17ae 4220void bgp_reset(void)
718e3744 4221{
d62a17ae 4222 vty_reset();
4223 bgp_zclient_reset();
4224 access_list_reset();
4225 prefix_list_reset();
718e3744 4226}
6b0655a2 4227
d62a17ae 4228static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 4229{
d62a17ae 4230 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
4231 && CHECK_FLAG(peer->af_cap[afi][safi],
4232 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
4233}
4234
718e3744 4235/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4236 value. */
d62a17ae 4237int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
4238 struct bgp_nlri *packet)
4239{
d7c0a89a
QY
4240 uint8_t *pnt;
4241 uint8_t *lim;
d62a17ae 4242 struct prefix p;
4243 int psize;
4244 int ret;
4245 afi_t afi;
4246 safi_t safi;
4247 int addpath_encoded;
d7c0a89a 4248 uint32_t addpath_id;
d62a17ae 4249
d62a17ae 4250 pnt = packet->nlri;
4251 lim = pnt + packet->length;
4252 afi = packet->afi;
4253 safi = packet->safi;
4254 addpath_id = 0;
4255 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
4256
4257 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4258 syntactic validity. If the field is syntactically incorrect,
4259 then the Error Subcode is set to Invalid Network Field. */
4260 for (; pnt < lim; pnt += psize) {
4261 /* Clear prefix structure. */
4262 memset(&p, 0, sizeof(struct prefix));
4263
4264 if (addpath_encoded) {
4265
4266 /* When packet overflow occurs return immediately. */
4267 if (pnt + BGP_ADDPATH_ID_LEN > lim)
4268 return -1;
4269
4270 addpath_id = ntohl(*((uint32_t *)pnt));
4271 pnt += BGP_ADDPATH_ID_LEN;
4272 }
718e3744 4273
d62a17ae 4274 /* Fetch prefix length. */
4275 p.prefixlen = *pnt++;
4276 /* afi/safi validity already verified by caller,
4277 * bgp_update_receive */
4278 p.family = afi2family(afi);
4279
4280 /* Prefix length check. */
4281 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 4282 flog_err(
e50f7cfd 4283 EC_BGP_UPDATE_RCV,
14454c9f 4284 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 4285 peer->host, p.prefixlen, packet->afi);
4286 return -1;
4287 }
6b0655a2 4288
d62a17ae 4289 /* Packet size overflow check. */
4290 psize = PSIZE(p.prefixlen);
4291
4292 /* When packet overflow occur return immediately. */
4293 if (pnt + psize > lim) {
af4c2728 4294 flog_err(
e50f7cfd 4295 EC_BGP_UPDATE_RCV,
d62a17ae 4296 "%s [Error] Update packet error (prefix length %d overflows packet)",
4297 peer->host, p.prefixlen);
4298 return -1;
4299 }
4300
4301 /* Defensive coding, double-check the psize fits in a struct
4302 * prefix */
4303 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 4304 flog_err(
e50f7cfd 4305 EC_BGP_UPDATE_RCV,
d62a17ae 4306 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4307 peer->host, p.prefixlen, sizeof(p.u));
4308 return -1;
4309 }
4310
4311 /* Fetch prefix from NLRI packet. */
a85297a7 4312 memcpy(p.u.val, pnt, psize);
d62a17ae 4313
4314 /* Check address. */
4315 if (afi == AFI_IP && safi == SAFI_UNICAST) {
4316 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
4317 /* From RFC4271 Section 6.3:
4318 *
4319 * If a prefix in the NLRI field is semantically
4320 * incorrect
4321 * (e.g., an unexpected multicast IP address),
4322 * an error SHOULD
4323 * be logged locally, and the prefix SHOULD be
4324 * ignored.
a4d82a8a 4325 */
af4c2728 4326 flog_err(
e50f7cfd 4327 EC_BGP_UPDATE_RCV,
d62a17ae 4328 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4329 peer->host, inet_ntoa(p.u.prefix4));
4330 continue;
4331 }
4332 }
4333
4334 /* Check address. */
4335 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
4336 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4337 char buf[BUFSIZ];
4338
af4c2728 4339 flog_err(
e50f7cfd 4340 EC_BGP_UPDATE_RCV,
d62a17ae 4341 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4342 peer->host,
4343 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4344 BUFSIZ));
4345
4346 continue;
4347 }
4348 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
4349 char buf[BUFSIZ];
4350
af4c2728 4351 flog_err(
e50f7cfd 4352 EC_BGP_UPDATE_RCV,
d62a17ae 4353 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4354 peer->host,
4355 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4356 BUFSIZ));
4357
4358 continue;
4359 }
4360 }
4361
4362 /* Normal process. */
4363 if (attr)
4364 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
4365 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 4366 NULL, NULL, 0, 0, NULL);
d62a17ae 4367 else
4368 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
4369 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
4370 BGP_ROUTE_NORMAL, NULL, NULL, 0,
4371 NULL);
d62a17ae 4372
4373 /* Address family configuration mismatch or maximum-prefix count
4374 overflow. */
4375 if (ret < 0)
4376 return -1;
4377 }
4378
4379 /* Packet length consistency check. */
4380 if (pnt != lim) {
af4c2728 4381 flog_err(
e50f7cfd 4382 EC_BGP_UPDATE_RCV,
d62a17ae 4383 "%s [Error] Update packet error (prefix length mismatch with total length)",
4384 peer->host);
4385 return -1;
4386 }
6b0655a2 4387
d62a17ae 4388 return 0;
718e3744 4389}
4390
d62a17ae 4391static struct bgp_static *bgp_static_new(void)
718e3744 4392{
d62a17ae 4393 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 4394}
4395
d62a17ae 4396static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 4397{
d62a17ae 4398 if (bgp_static->rmap.name)
4399 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
4400 if (bgp_static->eth_s_id)
4401 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
4402 XFREE(MTYPE_BGP_STATIC, bgp_static);
4403}
4404
4405void bgp_static_update(struct bgp *bgp, struct prefix *p,
4406 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
4407{
4408 struct bgp_node *rn;
40381db7 4409 struct bgp_path_info *pi;
4b7e6066 4410 struct bgp_path_info *new;
40381db7 4411 struct bgp_path_info rmap_path;
d62a17ae 4412 struct attr attr;
4413 struct attr *attr_new;
4414 int ret;
65efcfce 4415#if ENABLE_BGP_VNC
d62a17ae 4416 int vnc_implicit_withdraw = 0;
65efcfce 4417#endif
fee0f4c6 4418
d62a17ae 4419 assert(bgp_static);
4420 if (!bgp_static)
4421 return;
dd8103a9 4422
d62a17ae 4423 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4424
d62a17ae 4425 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 4426
d62a17ae 4427 attr.nexthop = bgp_static->igpnexthop;
4428 attr.med = bgp_static->igpmetric;
4429 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 4430
d62a17ae 4431 if (bgp_static->atomic)
4432 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 4433
d62a17ae 4434 /* Store label index, if required. */
4435 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
4436 attr.label_index = bgp_static->label_index;
4437 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
4438 }
718e3744 4439
d62a17ae 4440 /* Apply route-map. */
4441 if (bgp_static->rmap.name) {
4442 struct attr attr_tmp = attr;
80ced710 4443
40381db7
DS
4444 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
4445 rmap_path.peer = bgp->peer_self;
4446 rmap_path.attr = &attr_tmp;
fee0f4c6 4447
d62a17ae 4448 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 4449
40381db7
DS
4450 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
4451 &rmap_path);
fee0f4c6 4452
d62a17ae 4453 bgp->peer_self->rmap_type = 0;
718e3744 4454
d62a17ae 4455 if (ret == RMAP_DENYMATCH) {
4456 /* Free uninterned attribute. */
4457 bgp_attr_flush(&attr_tmp);
718e3744 4458
d62a17ae 4459 /* Unintern original. */
4460 aspath_unintern(&attr.aspath);
4461 bgp_static_withdraw(bgp, p, afi, safi);
4462 return;
4463 }
7f323236
DW
4464
4465 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
4466 bgp_attr_add_gshut_community(&attr_tmp);
4467
d62a17ae 4468 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
4469 } else {
4470
4471 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
4472 bgp_attr_add_gshut_community(&attr);
4473
d62a17ae 4474 attr_new = bgp_attr_intern(&attr);
7f323236 4475 }
718e3744 4476
6f94b685 4477 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4478 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4479 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4480 break;
4481
40381db7
DS
4482 if (pi) {
4483 if (attrhash_cmp(pi->attr, attr_new)
4484 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
d62a17ae 4485 && !bgp_flag_check(bgp, BGP_FLAG_FORCE_STATIC_PROCESS)) {
4486 bgp_unlock_node(rn);
4487 bgp_attr_unintern(&attr_new);
4488 aspath_unintern(&attr.aspath);
4489 return;
4490 } else {
4491 /* The attribute is changed. */
40381db7 4492 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4493
4494 /* Rewrite BGP route information. */
40381db7
DS
4495 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
4496 bgp_path_info_restore(rn, pi);
d62a17ae 4497 else
40381db7 4498 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
65efcfce 4499#if ENABLE_BGP_VNC
d62a17ae 4500 if ((afi == AFI_IP || afi == AFI_IP6)
4501 && (safi == SAFI_UNICAST)) {
40381db7 4502 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4503 /*
4504 * Implicit withdraw case.
40381db7 4505 * We have to do this before pi is
d62a17ae 4506 * changed
4507 */
4508 ++vnc_implicit_withdraw;
40381db7 4509 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 4510 vnc_import_bgp_exterior_del_route(
40381db7 4511 bgp, p, pi);
d62a17ae 4512 }
4513 }
65efcfce 4514#endif
40381db7
DS
4515 bgp_attr_unintern(&pi->attr);
4516 pi->attr = attr_new;
4517 pi->uptime = bgp_clock();
65efcfce 4518#if ENABLE_BGP_VNC
d62a17ae 4519 if ((afi == AFI_IP || afi == AFI_IP6)
4520 && (safi == SAFI_UNICAST)) {
4521 if (vnc_implicit_withdraw) {
40381db7 4522 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 4523 vnc_import_bgp_exterior_add_route(
40381db7 4524 bgp, p, pi);
d62a17ae 4525 }
4526 }
65efcfce 4527#endif
718e3744 4528
d62a17ae 4529 /* Nexthop reachability check. */
4530 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
4531 && (safi == SAFI_UNICAST
4532 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
4533
4534 struct bgp *bgp_nexthop = bgp;
4535
40381db7
DS
4536 if (pi->extra && pi->extra->bgp_orig)
4537 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
4538
4539 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
40381db7
DS
4540 afi, pi, NULL, 0))
4541 bgp_path_info_set_flag(rn, pi,
18ee8310 4542 BGP_PATH_VALID);
d62a17ae 4543 else {
4544 if (BGP_DEBUG(nht, NHT)) {
4545 char buf1[INET6_ADDRSTRLEN];
4546 inet_ntop(p->family,
4547 &p->u.prefix, buf1,
4548 INET6_ADDRSTRLEN);
4549 zlog_debug(
4550 "%s(%s): Route not in table, not advertising",
4551 __FUNCTION__, buf1);
4552 }
18ee8310 4553 bgp_path_info_unset_flag(
40381db7 4554 rn, pi, BGP_PATH_VALID);
d62a17ae 4555 }
4556 } else {
4557 /* Delete the NHT structure if any, if we're
4558 * toggling between
4559 * enabling/disabling import check. We
4560 * deregister the route
4561 * from NHT to avoid overloading NHT and the
4562 * process interaction
4563 */
40381db7
DS
4564 bgp_unlink_nexthop(pi);
4565 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 4566 }
4567 /* Process change. */
40381db7 4568 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4569 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
4570
4571 if (SAFI_UNICAST == safi
4572 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4573 || bgp->inst_type
4574 == BGP_INSTANCE_TYPE_DEFAULT)) {
4575 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 4576 pi);
ddb5b488
PZ
4577 }
4578
d62a17ae 4579 bgp_unlock_node(rn);
4580 aspath_unintern(&attr.aspath);
4581 return;
4582 }
718e3744 4583 }
718e3744 4584
d62a17ae 4585 /* Make new BGP info. */
4586 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
4587 attr_new, rn);
4588 /* Nexthop reachability check. */
4589 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
4590 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 4591 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
18ee8310 4592 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
d62a17ae 4593 else {
4594 if (BGP_DEBUG(nht, NHT)) {
4595 char buf1[INET6_ADDRSTRLEN];
4596 inet_ntop(p->family, &p->u.prefix, buf1,
4597 INET6_ADDRSTRLEN);
4598 zlog_debug(
4599 "%s(%s): Route not in table, not advertising",
4600 __FUNCTION__, buf1);
4601 }
18ee8310 4602 bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID);
d62a17ae 4603 }
4604 } else {
4605 /* Delete the NHT structure if any, if we're toggling between
4606 * enabling/disabling import check. We deregister the route
4607 * from NHT to avoid overloading NHT and the process interaction
4608 */
4609 bgp_unlink_nexthop(new);
4610
18ee8310 4611 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
fc9a856f 4612 }
078430f6 4613
d62a17ae 4614 /* Aggregate address increment. */
4615 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 4616
d62a17ae 4617 /* Register new BGP information. */
18ee8310 4618 bgp_path_info_add(rn, new);
718e3744 4619
d62a17ae 4620 /* route_node_get lock */
4621 bgp_unlock_node(rn);
4622
4623 /* Process change. */
4624 bgp_process(bgp, rn, afi, safi);
4625
ddb5b488
PZ
4626 if (SAFI_UNICAST == safi
4627 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4628 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4629 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4630 }
4631
d62a17ae 4632 /* Unintern original. */
4633 aspath_unintern(&attr.aspath);
718e3744 4634}
4635
d62a17ae 4636void bgp_static_withdraw(struct bgp *bgp, struct prefix *p, afi_t afi,
4637 safi_t safi)
718e3744 4638{
d62a17ae 4639 struct bgp_node *rn;
40381db7 4640 struct bgp_path_info *pi;
718e3744 4641
d62a17ae 4642 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4643
d62a17ae 4644 /* Check selected route and self inserted route. */
6f94b685 4645 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4646 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4647 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4648 break;
4649
4650 /* Withdraw static BGP route from routing table. */
40381db7 4651 if (pi) {
ddb5b488
PZ
4652 if (SAFI_UNICAST == safi
4653 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4654 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4655 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 4656 }
40381db7
DS
4657 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
4658 bgp_unlink_nexthop(pi);
4659 bgp_path_info_delete(rn, pi);
d62a17ae 4660 bgp_process(bgp, rn, afi, safi);
4661 }
718e3744 4662
d62a17ae 4663 /* Unlock bgp_node_lookup. */
4664 bgp_unlock_node(rn);
718e3744 4665}
4666
137446f9
LB
4667/*
4668 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4669 */
d62a17ae 4670static void bgp_static_withdraw_safi(struct bgp *bgp, struct prefix *p,
4671 afi_t afi, safi_t safi,
4672 struct prefix_rd *prd)
718e3744 4673{
d62a17ae 4674 struct bgp_node *rn;
40381db7 4675 struct bgp_path_info *pi;
718e3744 4676
d62a17ae 4677 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 4678
d62a17ae 4679 /* Check selected route and self inserted route. */
6f94b685 4680 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4681 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4682 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4683 break;
718e3744 4684
d62a17ae 4685 /* Withdraw static BGP route from routing table. */
40381db7 4686 if (pi) {
65efcfce 4687#if ENABLE_BGP_VNC
d62a17ae 4688 rfapiProcessWithdraw(
40381db7 4689 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 4690 1); /* Kill, since it is an administrative change */
65efcfce 4691#endif
ddb5b488
PZ
4692 if (SAFI_MPLS_VPN == safi
4693 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4694 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 4695 }
40381db7
DS
4696 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
4697 bgp_path_info_delete(rn, pi);
d62a17ae 4698 bgp_process(bgp, rn, afi, safi);
4699 }
718e3744 4700
d62a17ae 4701 /* Unlock bgp_node_lookup. */
4702 bgp_unlock_node(rn);
718e3744 4703}
4704
d62a17ae 4705static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p,
4706 struct bgp_static *bgp_static, afi_t afi,
4707 safi_t safi)
137446f9 4708{
d62a17ae 4709 struct bgp_node *rn;
4b7e6066 4710 struct bgp_path_info *new;
d62a17ae 4711 struct attr *attr_new;
4712 struct attr attr = {0};
40381db7 4713 struct bgp_path_info *pi;
65efcfce 4714#if ENABLE_BGP_VNC
d62a17ae 4715 mpls_label_t label = 0;
65efcfce 4716#endif
d7c0a89a 4717 uint32_t num_labels = 0;
d62a17ae 4718 union gw_addr add;
137446f9 4719
d62a17ae 4720 assert(bgp_static);
137446f9 4721
b57ba6d2
MK
4722 if (bgp_static->label != MPLS_INVALID_LABEL)
4723 num_labels = 1;
d62a17ae 4724 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
4725 &bgp_static->prd);
137446f9 4726
d62a17ae 4727 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 4728
d62a17ae 4729 attr.nexthop = bgp_static->igpnexthop;
4730 attr.med = bgp_static->igpmetric;
4731 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 4732
d62a17ae 4733 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
4734 || (safi == SAFI_ENCAP)) {
4735 if (afi == AFI_IP) {
4736 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
4737 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
4738 }
4739 }
4740 if (afi == AFI_L2VPN) {
4741 if (bgp_static->gatewayIp.family == AF_INET)
4742 add.ipv4.s_addr =
4743 bgp_static->gatewayIp.u.prefix4.s_addr;
4744 else if (bgp_static->gatewayIp.family == AF_INET6)
4745 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
4746 sizeof(struct in6_addr));
4747 overlay_index_update(&attr, bgp_static->eth_s_id, &add);
4748 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
4749 struct bgp_encap_type_vxlan bet;
4750 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 4751 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 4752 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
4753 }
4754 if (bgp_static->router_mac) {
4755 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
4756 }
4757 }
4758 /* Apply route-map. */
4759 if (bgp_static->rmap.name) {
4760 struct attr attr_tmp = attr;
40381db7 4761 struct bgp_path_info rmap_path;
d62a17ae 4762 int ret;
137446f9 4763
40381db7
DS
4764 rmap_path.peer = bgp->peer_self;
4765 rmap_path.attr = &attr_tmp;
137446f9 4766
d62a17ae 4767 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 4768
40381db7
DS
4769 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
4770 &rmap_path);
137446f9 4771
d62a17ae 4772 bgp->peer_self->rmap_type = 0;
137446f9 4773
d62a17ae 4774 if (ret == RMAP_DENYMATCH) {
4775 /* Free uninterned attribute. */
4776 bgp_attr_flush(&attr_tmp);
137446f9 4777
d62a17ae 4778 /* Unintern original. */
4779 aspath_unintern(&attr.aspath);
4780 bgp_static_withdraw_safi(bgp, p, afi, safi,
4781 &bgp_static->prd);
4782 return;
4783 }
137446f9 4784
d62a17ae 4785 attr_new = bgp_attr_intern(&attr_tmp);
4786 } else {
4787 attr_new = bgp_attr_intern(&attr);
4788 }
137446f9 4789
6f94b685 4790 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4791 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4792 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4793 break;
4794
40381db7 4795 if (pi) {
d62a17ae 4796 memset(&add, 0, sizeof(union gw_addr));
40381db7
DS
4797 if (attrhash_cmp(pi->attr, attr_new)
4798 && overlay_index_equal(afi, pi, bgp_static->eth_s_id, &add)
4799 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4800 bgp_unlock_node(rn);
4801 bgp_attr_unintern(&attr_new);
4802 aspath_unintern(&attr.aspath);
4803 return;
4804 } else {
4805 /* The attribute is changed. */
40381db7 4806 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4807
4808 /* Rewrite BGP route information. */
40381db7
DS
4809 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
4810 bgp_path_info_restore(rn, pi);
d62a17ae 4811 else
40381db7
DS
4812 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
4813 bgp_attr_unintern(&pi->attr);
4814 pi->attr = attr_new;
4815 pi->uptime = bgp_clock();
65efcfce 4816#if ENABLE_BGP_VNC
40381db7
DS
4817 if (pi->extra)
4818 label = decode_label(&pi->extra->label[0]);
65efcfce 4819#endif
137446f9 4820
d62a17ae 4821 /* Process change. */
40381db7 4822 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4823 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
4824
4825 if (SAFI_MPLS_VPN == safi
4826 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4827 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 4828 }
65efcfce 4829#if ENABLE_BGP_VNC
40381db7
DS
4830 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
4831 pi->attr, afi, safi, pi->type,
4832 pi->sub_type, &label);
65efcfce 4833#endif
d62a17ae 4834 bgp_unlock_node(rn);
4835 aspath_unintern(&attr.aspath);
4836 return;
4837 }
4838 }
137446f9
LB
4839
4840
d62a17ae 4841 /* Make new BGP info. */
4842 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
4843 attr_new, rn);
1defdda8 4844 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 4845 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
4846 if (num_labels) {
4847 new->extra->label[0] = bgp_static->label;
4848 new->extra->num_labels = num_labels;
4849 }
65efcfce 4850#if ENABLE_BGP_VNC
d62a17ae 4851 label = decode_label(&bgp_static->label);
65efcfce 4852#endif
137446f9 4853
d62a17ae 4854 /* Aggregate address increment. */
4855 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 4856
d62a17ae 4857 /* Register new BGP information. */
18ee8310 4858 bgp_path_info_add(rn, new);
d62a17ae 4859 /* route_node_get lock */
4860 bgp_unlock_node(rn);
137446f9 4861
d62a17ae 4862 /* Process change. */
4863 bgp_process(bgp, rn, afi, safi);
137446f9 4864
ddb5b488
PZ
4865 if (SAFI_MPLS_VPN == safi
4866 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
4867 vpn_leak_to_vrf_update(bgp, new);
4868 }
65efcfce 4869#if ENABLE_BGP_VNC
d62a17ae 4870 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
4871 safi, new->type, new->sub_type, &label);
65efcfce
LB
4872#endif
4873
d62a17ae 4874 /* Unintern original. */
4875 aspath_unintern(&attr.aspath);
137446f9
LB
4876}
4877
718e3744 4878/* Configure static BGP network. When user don't run zebra, static
4879 route should be installed as valid. */
e2a86ad9
DS
4880static int bgp_static_set(struct vty *vty, const char *negate,
4881 const char *ip_str, afi_t afi, safi_t safi,
d7c0a89a 4882 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 4883{
4884 VTY_DECLVAR_CONTEXT(bgp, bgp);
4885 int ret;
4886 struct prefix p;
4887 struct bgp_static *bgp_static;
4888 struct bgp_node *rn;
d7c0a89a 4889 uint8_t need_update = 0;
d62a17ae 4890
4891 /* Convert IP prefix string to struct prefix. */
4892 ret = str2prefix(ip_str, &p);
4893 if (!ret) {
4894 vty_out(vty, "%% Malformed prefix\n");
4895 return CMD_WARNING_CONFIG_FAILED;
4896 }
4897 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4898 vty_out(vty, "%% Malformed prefix (link-local address)\n");
4899 return CMD_WARNING_CONFIG_FAILED;
4900 }
718e3744 4901
d62a17ae 4902 apply_mask(&p);
718e3744 4903
e2a86ad9 4904 if (negate) {
718e3744 4905
e2a86ad9
DS
4906 /* Set BGP static route configuration. */
4907 rn = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 4908
e2a86ad9 4909 if (!rn) {
a4d82a8a 4910 vty_out(vty, "%% Can't find static route specified\n");
d62a17ae 4911 return CMD_WARNING_CONFIG_FAILED;
4912 }
4913
5a8ba9fc 4914 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 4915
e2a86ad9
DS
4916 if ((label_index != BGP_INVALID_LABEL_INDEX)
4917 && (label_index != bgp_static->label_index)) {
4918 vty_out(vty,
4919 "%% label-index doesn't match static route\n");
4920 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 4921 }
d62a17ae 4922
e2a86ad9
DS
4923 if ((rmap && bgp_static->rmap.name)
4924 && strcmp(rmap, bgp_static->rmap.name)) {
4925 vty_out(vty,
4926 "%% route-map name doesn't match static route\n");
4927 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 4928 }
718e3744 4929
e2a86ad9
DS
4930 /* Update BGP RIB. */
4931 if (!bgp_static->backdoor)
4932 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 4933
e2a86ad9
DS
4934 /* Clear configuration. */
4935 bgp_static_free(bgp_static);
5a8ba9fc 4936 bgp_node_set_bgp_static_info(rn, NULL);
e2a86ad9
DS
4937 bgp_unlock_node(rn);
4938 bgp_unlock_node(rn);
4939 } else {
718e3744 4940
e2a86ad9
DS
4941 /* Set BGP static route configuration. */
4942 rn = bgp_node_get(bgp->route[afi][safi], &p);
718e3744 4943
5a8ba9fc 4944 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 4945 if (bgp_static) {
e2a86ad9 4946 /* Configuration change. */
e2a86ad9
DS
4947 /* Label index cannot be changed. */
4948 if (bgp_static->label_index != label_index) {
4949 vty_out(vty, "%% cannot change label-index\n");
4950 return CMD_WARNING_CONFIG_FAILED;
4951 }
d62a17ae 4952
e2a86ad9 4953 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
4954 if (bgp_static->valid
4955 && bgp_static->backdoor != backdoor)
e2a86ad9 4956 need_update = 1;
718e3744 4957
e2a86ad9 4958 bgp_static->backdoor = backdoor;
718e3744 4959
e2a86ad9
DS
4960 if (rmap) {
4961 if (bgp_static->rmap.name)
4962 XFREE(MTYPE_ROUTE_MAP_NAME,
a4d82a8a 4963 bgp_static->rmap.name);
e2a86ad9
DS
4964 bgp_static->rmap.name =
4965 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
4966 bgp_static->rmap.map =
4967 route_map_lookup_by_name(rmap);
4968 } else {
4969 if (bgp_static->rmap.name)
4970 XFREE(MTYPE_ROUTE_MAP_NAME,
a4d82a8a 4971 bgp_static->rmap.name);
e2a86ad9
DS
4972 bgp_static->rmap.name = NULL;
4973 bgp_static->rmap.map = NULL;
4974 bgp_static->valid = 0;
4975 }
4976 bgp_unlock_node(rn);
4977 } else {
4978 /* New configuration. */
4979 bgp_static = bgp_static_new();
4980 bgp_static->backdoor = backdoor;
4981 bgp_static->valid = 0;
4982 bgp_static->igpmetric = 0;
4983 bgp_static->igpnexthop.s_addr = 0;
4984 bgp_static->label_index = label_index;
718e3744 4985
e2a86ad9
DS
4986 if (rmap) {
4987 if (bgp_static->rmap.name)
4988 XFREE(MTYPE_ROUTE_MAP_NAME,
a4d82a8a 4989 bgp_static->rmap.name);
e2a86ad9
DS
4990 bgp_static->rmap.name =
4991 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
4992 bgp_static->rmap.map =
4993 route_map_lookup_by_name(rmap);
4994 }
5a8ba9fc 4995 bgp_node_set_bgp_static_info(rn, bgp_static);
e2a86ad9 4996 }
d62a17ae 4997
e2a86ad9
DS
4998 bgp_static->valid = 1;
4999 if (need_update)
5000 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5001
e2a86ad9
DS
5002 if (!bgp_static->backdoor)
5003 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5004 }
d62a17ae 5005
5006 return CMD_SUCCESS;
5007}
5008
5009void bgp_static_add(struct bgp *bgp)
5010{
5011 afi_t afi;
5012 safi_t safi;
5013 struct bgp_node *rn;
5014 struct bgp_node *rm;
5015 struct bgp_table *table;
5016 struct bgp_static *bgp_static;
5017
05c7a1cc
QY
5018 FOREACH_AFI_SAFI (afi, safi)
5019 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5020 rn = bgp_route_next(rn)) {
67009e22 5021 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5022 continue;
ea47320b 5023
05c7a1cc
QY
5024 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5025 || (safi == SAFI_EVPN)) {
67009e22 5026 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5027
5028 for (rm = bgp_table_top(table); rm;
5029 rm = bgp_route_next(rm)) {
a78beeb5 5030 bgp_static =
5a8ba9fc
DS
5031 bgp_node_get_bgp_static_info(
5032 rm);
05c7a1cc
QY
5033 bgp_static_update_safi(bgp, &rm->p,
5034 bgp_static, afi,
5035 safi);
d62a17ae 5036 }
05c7a1cc 5037 } else {
5a8ba9fc
DS
5038 bgp_static_update(
5039 bgp, &rn->p,
5040 bgp_node_get_bgp_static_info(rn), afi,
5041 safi);
ea47320b 5042 }
05c7a1cc 5043 }
6aeb9e78
DS
5044}
5045
718e3744 5046/* Called from bgp_delete(). Delete all static routes from the BGP
5047 instance. */
d62a17ae 5048void bgp_static_delete(struct bgp *bgp)
5049{
5050 afi_t afi;
5051 safi_t safi;
5052 struct bgp_node *rn;
5053 struct bgp_node *rm;
5054 struct bgp_table *table;
5055 struct bgp_static *bgp_static;
5056
05c7a1cc
QY
5057 FOREACH_AFI_SAFI (afi, safi)
5058 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5059 rn = bgp_route_next(rn)) {
67009e22 5060 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5061 continue;
ea47320b 5062
05c7a1cc
QY
5063 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5064 || (safi == SAFI_EVPN)) {
67009e22 5065 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5066
5067 for (rm = bgp_table_top(table); rm;
5068 rm = bgp_route_next(rm)) {
a78beeb5 5069 bgp_static =
5a8ba9fc
DS
5070 bgp_node_get_bgp_static_info(
5071 rm);
05c7a1cc
QY
5072 bgp_static_withdraw_safi(
5073 bgp, &rm->p, AFI_IP, safi,
5074 (struct prefix_rd *)&rn->p);
ea47320b 5075 bgp_static_free(bgp_static);
5a8ba9fc 5076 bgp_node_set_bgp_static_info(rn, NULL);
ea47320b 5077 bgp_unlock_node(rn);
d62a17ae 5078 }
05c7a1cc 5079 } else {
5a8ba9fc 5080 bgp_static = bgp_node_get_bgp_static_info(rn);
05c7a1cc
QY
5081 bgp_static_withdraw(bgp, &rn->p, afi, safi);
5082 bgp_static_free(bgp_static);
5a8ba9fc 5083 bgp_node_set_bgp_static_info(rn, NULL);
05c7a1cc 5084 bgp_unlock_node(rn);
ea47320b 5085 }
05c7a1cc 5086 }
d62a17ae 5087}
5088
5089void bgp_static_redo_import_check(struct bgp *bgp)
5090{
5091 afi_t afi;
5092 safi_t safi;
5093 struct bgp_node *rn;
5094 struct bgp_node *rm;
5095 struct bgp_table *table;
5096 struct bgp_static *bgp_static;
5097
5098 /* Use this flag to force reprocessing of the route */
5099 bgp_flag_set(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc
QY
5100 FOREACH_AFI_SAFI (afi, safi) {
5101 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5102 rn = bgp_route_next(rn)) {
67009e22 5103 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5104 continue;
ea47320b 5105
05c7a1cc
QY
5106 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5107 || (safi == SAFI_EVPN)) {
67009e22 5108 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5109
5110 for (rm = bgp_table_top(table); rm;
5111 rm = bgp_route_next(rm)) {
a78beeb5 5112 bgp_static =
5a8ba9fc
DS
5113 bgp_node_get_bgp_static_info(
5114 rm);
05c7a1cc
QY
5115 bgp_static_update_safi(bgp, &rm->p,
5116 bgp_static, afi,
5117 safi);
d62a17ae 5118 }
05c7a1cc 5119 } else {
5a8ba9fc 5120 bgp_static = bgp_node_get_bgp_static_info(rn);
05c7a1cc
QY
5121 bgp_static_update(bgp, &rn->p, bgp_static, afi,
5122 safi);
ea47320b 5123 }
05c7a1cc
QY
5124 }
5125 }
d62a17ae 5126 bgp_flag_unset(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
5127}
5128
5129static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
5130 safi_t safi)
5131{
5132 struct bgp_table *table;
5133 struct bgp_node *rn;
40381db7 5134 struct bgp_path_info *pi;
d62a17ae 5135
5136 table = bgp->rib[afi][safi];
5137 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685 5138 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7
DS
5139 if (pi->peer == bgp->peer_self
5140 && ((pi->type == ZEBRA_ROUTE_BGP
5141 && pi->sub_type == BGP_ROUTE_STATIC)
5142 || (pi->type != ZEBRA_ROUTE_BGP
5143 && pi->sub_type
d62a17ae 5144 == BGP_ROUTE_REDISTRIBUTE))) {
40381db7 5145 bgp_aggregate_decrement(bgp, &rn->p, pi, afi,
d62a17ae 5146 safi);
40381db7
DS
5147 bgp_unlink_nexthop(pi);
5148 bgp_path_info_delete(rn, pi);
d62a17ae 5149 bgp_process(bgp, rn, afi, safi);
5150 }
5151 }
5152 }
ad4cbda1 5153}
5154
5155/*
5156 * Purge all networks and redistributed routes from routing table.
5157 * Invoked upon the instance going down.
5158 */
d62a17ae 5159void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 5160{
d62a17ae 5161 afi_t afi;
5162 safi_t safi;
ad4cbda1 5163
05c7a1cc
QY
5164 FOREACH_AFI_SAFI (afi, safi)
5165 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 5166}
5167
137446f9
LB
5168/*
5169 * gpz 110624
5170 * Currently this is used to set static routes for VPN and ENCAP.
5171 * I think it can probably be factored with bgp_static_set.
5172 */
d62a17ae 5173int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
5174 const char *ip_str, const char *rd_str,
5175 const char *label_str, const char *rmap_str,
5176 int evpn_type, const char *esi, const char *gwip,
5177 const char *ethtag, const char *routermac)
5178{
5179 VTY_DECLVAR_CONTEXT(bgp, bgp);
5180 int ret;
5181 struct prefix p;
5182 struct prefix_rd prd;
5183 struct bgp_node *prn;
5184 struct bgp_node *rn;
5185 struct bgp_table *table;
5186 struct bgp_static *bgp_static;
5187 mpls_label_t label = MPLS_INVALID_LABEL;
5188 struct prefix gw_ip;
5189
5190 /* validate ip prefix */
5191 ret = str2prefix(ip_str, &p);
5192 if (!ret) {
5193 vty_out(vty, "%% Malformed prefix\n");
5194 return CMD_WARNING_CONFIG_FAILED;
5195 }
5196 apply_mask(&p);
5197 if ((afi == AFI_L2VPN)
5198 && (bgp_build_evpn_prefix(evpn_type,
5199 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5200 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5201 return CMD_WARNING_CONFIG_FAILED;
5202 }
718e3744 5203
d62a17ae 5204 ret = str2prefix_rd(rd_str, &prd);
5205 if (!ret) {
5206 vty_out(vty, "%% Malformed rd\n");
5207 return CMD_WARNING_CONFIG_FAILED;
5208 }
718e3744 5209
d62a17ae 5210 if (label_str) {
5211 unsigned long label_val;
5212 label_val = strtoul(label_str, NULL, 10);
5213 encode_label(label_val, &label);
5214 }
9bedbb1e 5215
d62a17ae 5216 if (safi == SAFI_EVPN) {
5217 if (esi && str2esi(esi, NULL) == 0) {
5218 vty_out(vty, "%% Malformed ESI\n");
5219 return CMD_WARNING_CONFIG_FAILED;
5220 }
5221 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
5222 vty_out(vty, "%% Malformed Router MAC\n");
5223 return CMD_WARNING_CONFIG_FAILED;
5224 }
5225 if (gwip) {
5226 memset(&gw_ip, 0, sizeof(struct prefix));
5227 ret = str2prefix(gwip, &gw_ip);
5228 if (!ret) {
5229 vty_out(vty, "%% Malformed GatewayIp\n");
5230 return CMD_WARNING_CONFIG_FAILED;
5231 }
5232 if ((gw_ip.family == AF_INET
3714a385 5233 && is_evpn_prefix_ipaddr_v6(
d62a17ae 5234 (struct prefix_evpn *)&p))
5235 || (gw_ip.family == AF_INET6
3714a385 5236 && is_evpn_prefix_ipaddr_v4(
d62a17ae 5237 (struct prefix_evpn *)&p))) {
5238 vty_out(vty,
5239 "%% GatewayIp family differs with IP prefix\n");
5240 return CMD_WARNING_CONFIG_FAILED;
5241 }
5242 }
5243 }
5244 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
67009e22
DS
5245 if (!bgp_node_has_bgp_path_info_data(prn))
5246 bgp_node_set_bgp_table_info(prn,
5247 bgp_table_init(bgp, afi, safi));
d62a17ae 5248 else
5249 bgp_unlock_node(prn);
67009e22 5250 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 5251
5252 rn = bgp_node_get(table, &p);
5253
67009e22 5254 if (bgp_node_has_bgp_path_info_data(rn)) {
d62a17ae 5255 vty_out(vty, "%% Same network configuration exists\n");
5256 bgp_unlock_node(rn);
5257 } else {
5258 /* New configuration. */
5259 bgp_static = bgp_static_new();
5260 bgp_static->backdoor = 0;
5261 bgp_static->valid = 0;
5262 bgp_static->igpmetric = 0;
5263 bgp_static->igpnexthop.s_addr = 0;
5264 bgp_static->label = label;
5265 bgp_static->prd = prd;
5266
5267 if (rmap_str) {
5268 if (bgp_static->rmap.name)
5269 XFREE(MTYPE_ROUTE_MAP_NAME,
5270 bgp_static->rmap.name);
5271 bgp_static->rmap.name =
5272 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
5273 bgp_static->rmap.map =
5274 route_map_lookup_by_name(rmap_str);
5275 }
718e3744 5276
d62a17ae 5277 if (safi == SAFI_EVPN) {
5278 if (esi) {
5279 bgp_static->eth_s_id =
5280 XCALLOC(MTYPE_ATTR,
5281 sizeof(struct eth_segment_id));
5282 str2esi(esi, bgp_static->eth_s_id);
5283 }
5284 if (routermac) {
5285 bgp_static->router_mac =
28328ea9 5286 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
5287 (void)prefix_str2mac(routermac,
5288 bgp_static->router_mac);
d62a17ae 5289 }
5290 if (gwip)
5291 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
5292 }
5a8ba9fc 5293 bgp_node_set_bgp_static_info(rn, bgp_static);
718e3744 5294
d62a17ae 5295 bgp_static->valid = 1;
5296 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
5297 }
718e3744 5298
d62a17ae 5299 return CMD_SUCCESS;
718e3744 5300}
5301
5302/* Configure static BGP network. */
d62a17ae 5303int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
5304 const char *ip_str, const char *rd_str,
5305 const char *label_str, int evpn_type, const char *esi,
5306 const char *gwip, const char *ethtag)
5307{
5308 VTY_DECLVAR_CONTEXT(bgp, bgp);
5309 int ret;
5310 struct prefix p;
5311 struct prefix_rd prd;
5312 struct bgp_node *prn;
5313 struct bgp_node *rn;
5314 struct bgp_table *table;
5315 struct bgp_static *bgp_static;
5316 mpls_label_t label = MPLS_INVALID_LABEL;
5317
5318 /* Convert IP prefix string to struct prefix. */
5319 ret = str2prefix(ip_str, &p);
5320 if (!ret) {
5321 vty_out(vty, "%% Malformed prefix\n");
5322 return CMD_WARNING_CONFIG_FAILED;
5323 }
5324 apply_mask(&p);
5325 if ((afi == AFI_L2VPN)
5326 && (bgp_build_evpn_prefix(evpn_type,
5327 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5328 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5329 return CMD_WARNING_CONFIG_FAILED;
5330 }
5331 ret = str2prefix_rd(rd_str, &prd);
5332 if (!ret) {
5333 vty_out(vty, "%% Malformed rd\n");
5334 return CMD_WARNING_CONFIG_FAILED;
5335 }
718e3744 5336
d62a17ae 5337 if (label_str) {
5338 unsigned long label_val;
5339 label_val = strtoul(label_str, NULL, 10);
5340 encode_label(label_val, &label);
5341 }
718e3744 5342
d62a17ae 5343 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
67009e22
DS
5344 if (!bgp_node_has_bgp_path_info_data(prn))
5345 bgp_node_set_bgp_table_info(prn,
5346 bgp_table_init(bgp, afi, safi));
d62a17ae 5347 else
5348 bgp_unlock_node(prn);
67009e22 5349 table = bgp_node_get_bgp_table_info(prn);
718e3744 5350
d62a17ae 5351 rn = bgp_node_lookup(table, &p);
6b0655a2 5352
d62a17ae 5353 if (rn) {
5354 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 5355
5a8ba9fc 5356 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 5357 bgp_static_free(bgp_static);
5a8ba9fc 5358 bgp_node_set_bgp_static_info(rn, NULL);
d62a17ae 5359 bgp_unlock_node(rn);
5360 bgp_unlock_node(rn);
5361 } else
5362 vty_out(vty, "%% Can't find the route\n");
5363
5364 return CMD_SUCCESS;
5365}
5366
5367static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
5368 const char *rmap_name)
5369{
5370 VTY_DECLVAR_CONTEXT(bgp, bgp);
5371 struct bgp_rmap *rmap;
5372
5373 rmap = &bgp->table_map[afi][safi];
5374 if (rmap_name) {
5375 if (rmap->name)
5376 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
5377 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
5378 rmap->map = route_map_lookup_by_name(rmap_name);
5379 } else {
5380 if (rmap->name)
5381 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
5382 rmap->name = NULL;
5383 rmap->map = NULL;
5384 }
73ac8160 5385
d62a17ae 5386 if (bgp_fibupd_safi(safi))
5387 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5388
d62a17ae 5389 return CMD_SUCCESS;
73ac8160
DS
5390}
5391
d62a17ae 5392static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
5393 const char *rmap_name)
73ac8160 5394{
d62a17ae 5395 VTY_DECLVAR_CONTEXT(bgp, bgp);
5396 struct bgp_rmap *rmap;
73ac8160 5397
d62a17ae 5398 rmap = &bgp->table_map[afi][safi];
5399 if (rmap->name)
5400 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
5401 rmap->name = NULL;
5402 rmap->map = NULL;
73ac8160 5403
d62a17ae 5404 if (bgp_fibupd_safi(safi))
5405 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5406
d62a17ae 5407 return CMD_SUCCESS;
73ac8160
DS
5408}
5409
2b791107 5410void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 5411 safi_t safi)
73ac8160 5412{
d62a17ae 5413 if (bgp->table_map[afi][safi].name) {
d62a17ae 5414 vty_out(vty, " table-map %s\n",
5415 bgp->table_map[afi][safi].name);
5416 }
73ac8160
DS
5417}
5418
73ac8160
DS
5419DEFUN (bgp_table_map,
5420 bgp_table_map_cmd,
5421 "table-map WORD",
5422 "BGP table to RIB route download filter\n"
5423 "Name of the route map\n")
5424{
d62a17ae 5425 int idx_word = 1;
5426 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5427 argv[idx_word]->arg);
73ac8160
DS
5428}
5429DEFUN (no_bgp_table_map,
5430 no_bgp_table_map_cmd,
5431 "no table-map WORD",
3a2d747c 5432 NO_STR
73ac8160
DS
5433 "BGP table to RIB route download filter\n"
5434 "Name of the route map\n")
5435{
d62a17ae 5436 int idx_word = 2;
5437 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5438 argv[idx_word]->arg);
73ac8160
DS
5439}
5440
e2a86ad9
DS
5441DEFPY(bgp_network,
5442 bgp_network_cmd,
5443 "[no] network \
5444 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5445 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5446 backdoor$backdoor}]",
5447 NO_STR
5448 "Specify a network to announce via BGP\n"
5449 "IPv4 prefix\n"
5450 "Network number\n"
5451 "Network mask\n"
5452 "Network mask\n"
5453 "Route-map to modify the attributes\n"
5454 "Name of the route map\n"
5455 "Label index to associate with the prefix\n"
5456 "Label index value\n"
5457 "Specify a BGP backdoor route\n")
5458{
5459 char addr_prefix_str[BUFSIZ];
5460
5461 if (address_str) {
5462 int ret;
718e3744 5463
e2a86ad9
DS
5464 ret = netmask_str2prefix_str(address_str, netmask_str,
5465 addr_prefix_str);
5466 if (!ret) {
5467 vty_out(vty, "%% Inconsistent address and mask\n");
5468 return CMD_WARNING_CONFIG_FAILED;
5469 }
d62a17ae 5470 }
718e3744 5471
a4d82a8a
PZ
5472 return bgp_static_set(
5473 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
5474 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
5475 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 5476}
5477
e2a86ad9
DS
5478DEFPY(ipv6_bgp_network,
5479 ipv6_bgp_network_cmd,
5480 "[no] network X:X::X:X/M$prefix \
5481 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5482 NO_STR
5483 "Specify a network to announce via BGP\n"
5484 "IPv6 prefix\n"
5485 "Route-map to modify the attributes\n"
5486 "Name of the route map\n"
5487 "Label index to associate with the prefix\n"
5488 "Label index value\n")
718e3744 5489{
a4d82a8a
PZ
5490 return bgp_static_set(
5491 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
5492 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
5493}
5494
718e3744 5495/* Aggreagete address:
5496
5497 advertise-map Set condition to advertise attribute
5498 as-set Generate AS set path information
5499 attribute-map Set attributes of aggregate
5500 route-map Set parameters of aggregate
5501 summary-only Filter more specific routes from updates
5502 suppress-map Conditionally filter more specific routes from updates
5503 <cr>
5504 */
d62a17ae 5505struct bgp_aggregate {
5506 /* Summary-only flag. */
d7c0a89a 5507 uint8_t summary_only;
718e3744 5508
d62a17ae 5509 /* AS set generation. */
d7c0a89a 5510 uint8_t as_set;
718e3744 5511
d62a17ae 5512 /* Route-map for aggregated route. */
5513 struct route_map *map;
718e3744 5514
d62a17ae 5515 /* Suppress-count. */
5516 unsigned long count;
718e3744 5517
d62a17ae 5518 /* SAFI configuration. */
5519 safi_t safi;
718e3744 5520};
5521
d62a17ae 5522static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 5523{
d62a17ae 5524 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 5525}
5526
d62a17ae 5527static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 5528{
d62a17ae 5529 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
5530}
718e3744 5531
40381db7 5532static int bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
29f7d023 5533 struct aspath *aspath,
3da2cc32 5534 struct community *comm,
dd18c5a9
DS
5535 struct ecommunity *ecomm,
5536 struct lcommunity *lcomm)
eaaf8adb
DS
5537{
5538 static struct aspath *ae = NULL;
5539
5540 if (!ae)
5541 ae = aspath_empty();
5542
40381db7 5543 if (!pi)
eaaf8adb
DS
5544 return 0;
5545
40381db7 5546 if (origin != pi->attr->origin)
eaaf8adb
DS
5547 return 0;
5548
40381db7 5549 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
29f7d023
DS
5550 return 0;
5551
40381db7 5552 if (!community_cmp(pi->attr->community, comm))
eaaf8adb
DS
5553 return 0;
5554
3da2cc32 5555 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
eaaf8adb
DS
5556 return 0;
5557
dd18c5a9
DS
5558 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
5559 return 0;
5560
40381db7 5561 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
7ce8a8e0
DS
5562 return 0;
5563
eaaf8adb
DS
5564 return 1;
5565}
5566
c701010e
DS
5567static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi,
5568 struct prefix *p, uint8_t origin,
5569 struct aspath *aspath,
5570 struct community *community,
3da2cc32 5571 struct ecommunity *ecommunity,
dd18c5a9 5572 struct lcommunity *lcommunity,
c701010e
DS
5573 uint8_t atomic_aggregate,
5574 struct bgp_aggregate *aggregate)
5575{
5576 struct bgp_node *rn;
5577 struct bgp_table *table;
6f94b685 5578 struct bgp_path_info *pi, *orig, *new;
c701010e
DS
5579
5580 table = bgp->rib[afi][safi];
5581
5582 rn = bgp_node_get(table, p);
eaaf8adb 5583
6f94b685 5584 for (orig = pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
5585 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5586 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
5587 break;
5588
c701010e 5589 if (aggregate->count > 0) {
eaaf8adb
DS
5590 /*
5591 * If the aggregate information has not changed
5592 * no need to re-install it again.
5593 */
6f94b685 5594 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 5595 ecommunity, lcommunity)) {
eaaf8adb
DS
5596 bgp_unlock_node(rn);
5597
5598 if (aspath)
5599 aspath_free(aspath);
5600 if (community)
3c1f53de 5601 community_free(&community);
3da2cc32
DS
5602 if (ecommunity)
5603 ecommunity_free(&ecommunity);
dd18c5a9
DS
5604 if (lcommunity)
5605 lcommunity_free(&lcommunity);
eaaf8adb
DS
5606
5607 return;
5608 }
5609
5610 /*
5611 * Mark the old as unusable
5612 */
40381db7
DS
5613 if (pi)
5614 bgp_path_info_delete(rn, pi);
eaaf8adb 5615
3da2cc32
DS
5616 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
5617 bgp->peer_self,
5618 bgp_attr_aggregate_intern(bgp, origin, aspath,
5619 community, ecommunity,
dd18c5a9 5620 lcommunity,
3da2cc32
DS
5621 aggregate->as_set,
5622 atomic_aggregate),
5623 rn);
1defdda8 5624 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 5625
18ee8310 5626 bgp_path_info_add(rn, new);
c701010e
DS
5627 bgp_process(bgp, rn, afi, safi);
5628 } else {
6f94b685 5629 for (pi = orig; pi; pi = pi->next)
40381db7
DS
5630 if (pi->peer == bgp->peer_self
5631 && pi->type == ZEBRA_ROUTE_BGP
5632 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
5633 break;
5634
5635 /* Withdraw static BGP route from routing table. */
40381db7
DS
5636 if (pi) {
5637 bgp_path_info_delete(rn, pi);
c701010e
DS
5638 bgp_process(bgp, rn, afi, safi);
5639 }
5640 }
5641
5642 bgp_unlock_node(rn);
5643}
5644
b5d58c32 5645/* Update an aggregate as routes are added/removed from the BGP table */
d62a17ae 5646static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
40381db7 5647 struct bgp_path_info *pinew, afi_t afi,
4b7e6066 5648 safi_t safi, struct bgp_path_info *del,
d62a17ae 5649 struct bgp_aggregate *aggregate)
5650{
5651 struct bgp_table *table;
5652 struct bgp_node *top;
5653 struct bgp_node *rn;
d7c0a89a 5654 uint8_t origin;
d62a17ae 5655 struct aspath *aspath = NULL;
5656 struct aspath *asmerge = NULL;
5657 struct community *community = NULL;
5658 struct community *commerge = NULL;
3da2cc32
DS
5659 struct ecommunity *ecommunity = NULL;
5660 struct ecommunity *ecommerge = NULL;
dd18c5a9
DS
5661 struct lcommunity *lcommunity = NULL;
5662 struct lcommunity *lcommerge = NULL;
40381db7 5663 struct bgp_path_info *pi;
d62a17ae 5664 unsigned long match = 0;
d7c0a89a 5665 uint8_t atomic_aggregate = 0;
d62a17ae 5666
d62a17ae 5667 /* ORIGIN attribute: If at least one route among routes that are
5668 aggregated has ORIGIN with the value INCOMPLETE, then the
5669 aggregated route must have the ORIGIN attribute with the value
5670 INCOMPLETE. Otherwise, if at least one route among routes that
5671 are aggregated has ORIGIN with the value EGP, then the aggregated
5672 route must have the origin attribute with the value EGP. In all
5673 other case the value of the ORIGIN attribute of the aggregated
5674 route is INTERNAL. */
5675 origin = BGP_ORIGIN_IGP;
718e3744 5676
d62a17ae 5677 table = bgp->rib[afi][safi];
718e3744 5678
d62a17ae 5679 top = bgp_node_get(table, p);
5680 for (rn = bgp_node_get(table, p); rn;
c2ff8b3e
DS
5681 rn = bgp_route_next_until(rn, top)) {
5682 if (rn->p.prefixlen <= p->prefixlen)
5683 continue;
d62a17ae 5684
c2ff8b3e 5685 match = 0;
d62a17ae 5686
6f94b685 5687 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 5688 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 5689 continue;
718e3744 5690
40381db7 5691 if (del && pi == del)
c2ff8b3e 5692 continue;
718e3744 5693
40381db7 5694 if (pi->attr->flag
c2ff8b3e
DS
5695 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
5696 atomic_aggregate = 1;
d62a17ae 5697
40381db7 5698 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 5699 continue;
d62a17ae 5700
f273fef1
DS
5701 /*
5702 * summary-only aggregate route suppress
5703 * aggregated route announcements.
5704 */
c2ff8b3e 5705 if (aggregate->summary_only) {
40381db7
DS
5706 (bgp_path_info_extra_get(pi))->suppress++;
5707 bgp_path_info_set_flag(rn, pi,
18ee8310 5708 BGP_PATH_ATTR_CHANGED);
c2ff8b3e 5709 match++;
d62a17ae 5710 }
c2ff8b3e
DS
5711
5712 aggregate->count++;
5713
f273fef1
DS
5714 /*
5715 * If at least one route among routes that are
5716 * aggregated has ORIGIN with the value INCOMPLETE,
5717 * then the aggregated route MUST have the ORIGIN
5718 * attribute with the value INCOMPLETE. Otherwise, if
5719 * at least one route among routes that are aggregated
5720 * has ORIGIN with the value EGP, then the aggregated
5721 * route MUST have the ORIGIN attribute with the value
5722 * EGP.
5723 */
40381db7
DS
5724 if (origin < pi->attr->origin)
5725 origin = pi->attr->origin;
c2ff8b3e
DS
5726
5727 if (!aggregate->as_set)
5728 continue;
5729
f273fef1
DS
5730 /*
5731 * as-set aggregate route generate origin, as path,
5732 * and community aggregation.
5733 */
c2ff8b3e
DS
5734 if (aspath) {
5735 asmerge = aspath_aggregate(aspath,
40381db7 5736 pi->attr->aspath);
c2ff8b3e
DS
5737 aspath_free(aspath);
5738 aspath = asmerge;
5739 } else
40381db7 5740 aspath = aspath_dup(pi->attr->aspath);
c2ff8b3e 5741
3da2cc32
DS
5742 if (pi->attr->community) {
5743 if (community) {
5744 commerge = community_merge(
5745 community, pi->attr->community);
5746 community =
5747 community_uniq_sort(commerge);
3c1f53de 5748 community_free(&commerge);
3da2cc32
DS
5749 } else
5750 community = community_dup(
5751 pi->attr->community);
5752 }
c2ff8b3e 5753
3da2cc32
DS
5754 if (pi->attr->ecommunity) {
5755 if (ecommunity) {
5756 ecommerge = ecommunity_merge(
5757 ecommunity,
5758 pi->attr->ecommunity);
5759 ecommunity =
5760 ecommunity_uniq_sort(ecommerge);
5761 ecommunity_free(&ecommerge);
5762 } else
5763 ecommunity = ecommunity_dup(
5764 pi->attr->ecommunity);
5765 }
dd18c5a9
DS
5766
5767 if (pi->attr->lcommunity) {
5768 if (lcommunity) {
5769 lcommerge = lcommunity_merge(
5770 lcommunity,
5771 pi->attr->lcommunity);
5772 lcommunity =
5773 lcommunity_uniq_sort(lcommerge);
5774 lcommunity_free(&lcommerge);
5775 } else
5776 lcommunity = lcommunity_dup(
5777 pi->attr->lcommunity);
5778 }
d62a17ae 5779 }
c2ff8b3e
DS
5780 if (match)
5781 bgp_process(bgp, rn, afi, safi);
5782 }
d62a17ae 5783 bgp_unlock_node(top);
718e3744 5784
40381db7 5785 if (pinew) {
718e3744 5786 aggregate->count++;
5787
d62a17ae 5788 if (aggregate->summary_only)
40381db7 5789 (bgp_path_info_extra_get(pinew))->suppress++;
d62a17ae 5790
40381db7
DS
5791 if (origin < pinew->attr->origin)
5792 origin = pinew->attr->origin;
d62a17ae 5793
5794 if (aggregate->as_set) {
5795 if (aspath) {
5796 asmerge = aspath_aggregate(aspath,
40381db7 5797 pinew->attr->aspath);
d62a17ae 5798 aspath_free(aspath);
5799 aspath = asmerge;
5800 } else
40381db7 5801 aspath = aspath_dup(pinew->attr->aspath);
d62a17ae 5802
40381db7 5803 if (pinew->attr->community) {
d62a17ae 5804 if (community) {
5805 commerge = community_merge(
5806 community,
40381db7 5807 pinew->attr->community);
d62a17ae 5808 community =
5809 community_uniq_sort(commerge);
3c1f53de 5810 community_free(&commerge);
d62a17ae 5811 } else
5812 community = community_dup(
40381db7 5813 pinew->attr->community);
d62a17ae 5814 }
3da2cc32
DS
5815
5816 if (pinew->attr->ecommunity) {
5817 if (ecommunity) {
5818 ecommerge = ecommunity_merge(
5819 ecommunity,
5820 pinew->attr->ecommunity);
5821 ecommunity =
5822 ecommunity_uniq_sort(ecommerge);
5823 ecommunity_free(&ecommerge);
5824 } else
5825 ecommunity = ecommunity_dup(
5826 pinew->attr->ecommunity);
5827 }
dd18c5a9
DS
5828
5829 if (pinew->attr->lcommunity) {
5830 if (lcommunity) {
5831 lcommerge = lcommunity_merge(
5832 lcommunity,
5833 pinew->attr->lcommunity);
5834 lcommunity =
5835 lcommunity_uniq_sort(lcommerge);
5836 lcommunity_free(&lcommerge);
5837 } else
5838 lcommunity = lcommunity_dup(
5839 pinew->attr->lcommunity);
d62a17ae 5840 }
718e3744 5841 }
718e3744 5842 }
718e3744 5843
c701010e 5844 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
5845 ecommunity, lcommunity, atomic_aggregate,
5846 aggregate);
d62a17ae 5847
c701010e 5848 if (aggregate->count == 0) {
d62a17ae 5849 if (aspath)
5850 aspath_free(aspath);
5851 if (community)
3c1f53de 5852 community_free(&community);
3da2cc32
DS
5853 if (ecommunity)
5854 ecommunity_free(&ecommunity);
dd18c5a9
DS
5855 if (lcommunity)
5856 lcommunity_free(&lcommunity);
d62a17ae 5857 }
718e3744 5858}
5859
3b7db173
DS
5860static void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
5861 safi_t safi, struct bgp_aggregate *aggregate)
5862{
5863 struct bgp_table *table;
5864 struct bgp_node *top;
5865 struct bgp_node *rn;
40381db7 5866 struct bgp_path_info *pi;
3b7db173
DS
5867 unsigned long match;
5868
5869 table = bgp->rib[afi][safi];
5870
5871 /* If routes exists below this node, generate aggregate routes. */
5872 top = bgp_node_get(table, p);
5873 for (rn = bgp_node_get(table, p); rn;
5874 rn = bgp_route_next_until(rn, top)) {
5875 if (rn->p.prefixlen <= p->prefixlen)
5876 continue;
5877 match = 0;
5878
6f94b685 5879 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 5880 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
5881 continue;
5882
40381db7 5883 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
5884 continue;
5885
40381db7
DS
5886 if (aggregate->summary_only && pi->extra) {
5887 pi->extra->suppress--;
3b7db173 5888
40381db7 5889 if (pi->extra->suppress == 0) {
18ee8310 5890 bgp_path_info_set_flag(
40381db7 5891 rn, pi, BGP_PATH_ATTR_CHANGED);
3b7db173
DS
5892 match++;
5893 }
5894 }
5895 aggregate->count--;
5896 }
5897
5898 /* If this node was suppressed, process the change. */
5899 if (match)
5900 bgp_process(bgp, rn, afi, safi);
5901 }
5902 bgp_unlock_node(top);
5903}
718e3744 5904
d62a17ae 5905void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p,
40381db7 5906 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 5907{
d62a17ae 5908 struct bgp_node *child;
5909 struct bgp_node *rn;
5910 struct bgp_aggregate *aggregate;
5911 struct bgp_table *table;
718e3744 5912
d62a17ae 5913 table = bgp->aggregate[afi][safi];
f018db83 5914
d62a17ae 5915 /* No aggregates configured. */
5916 if (bgp_table_top_nolock(table) == NULL)
5917 return;
f018db83 5918
d62a17ae 5919 if (p->prefixlen == 0)
5920 return;
718e3744 5921
40381db7 5922 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 5923 return;
718e3744 5924
d62a17ae 5925 child = bgp_node_get(table, p);
718e3744 5926
d62a17ae 5927 /* Aggregate address configuration check. */
b1e62edd 5928 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
b613a918 5929 aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 5930 if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
d62a17ae 5931 bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate);
40381db7 5932 bgp_aggregate_route(bgp, &rn->p, pi, afi, safi, NULL,
d62a17ae 5933 aggregate);
5934 }
b1e62edd 5935 }
d62a17ae 5936 bgp_unlock_node(child);
718e3744 5937}
5938
d62a17ae 5939void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p,
4b7e6066 5940 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 5941{
d62a17ae 5942 struct bgp_node *child;
5943 struct bgp_node *rn;
5944 struct bgp_aggregate *aggregate;
5945 struct bgp_table *table;
718e3744 5946
d62a17ae 5947 table = bgp->aggregate[afi][safi];
718e3744 5948
d62a17ae 5949 /* No aggregates configured. */
5950 if (bgp_table_top_nolock(table) == NULL)
5951 return;
718e3744 5952
d62a17ae 5953 if (p->prefixlen == 0)
5954 return;
718e3744 5955
d62a17ae 5956 child = bgp_node_get(table, p);
718e3744 5957
d62a17ae 5958 /* Aggregate address configuration check. */
b1e62edd 5959 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
b613a918 5960 aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 5961 if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
d62a17ae 5962 bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate);
5963 bgp_aggregate_route(bgp, &rn->p, NULL, afi, safi, del,
5964 aggregate);
5965 }
b1e62edd 5966 }
d62a17ae 5967 bgp_unlock_node(child);
5968}
718e3744 5969
718e3744 5970/* Aggregate route attribute. */
5971#define AGGREGATE_SUMMARY_ONLY 1
5972#define AGGREGATE_AS_SET 1
5973
d62a17ae 5974static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
5975 afi_t afi, safi_t safi)
718e3744 5976{
d62a17ae 5977 VTY_DECLVAR_CONTEXT(bgp, bgp);
5978 int ret;
5979 struct prefix p;
5980 struct bgp_node *rn;
5981 struct bgp_aggregate *aggregate;
718e3744 5982
d62a17ae 5983 /* Convert string to prefix structure. */
5984 ret = str2prefix(prefix_str, &p);
5985 if (!ret) {
5986 vty_out(vty, "Malformed prefix\n");
5987 return CMD_WARNING_CONFIG_FAILED;
5988 }
5989 apply_mask(&p);
5990
5991 /* Old configuration check. */
5992 rn = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
5993 if (!rn) {
5994 vty_out(vty,
5995 "%% There is no aggregate-address configuration.\n");
5996 return CMD_WARNING_CONFIG_FAILED;
5997 }
f6269b4f 5998
b613a918 5999 aggregate = bgp_node_get_bgp_aggregate_info(rn);
09990cdd 6000 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
dd18c5a9
DS
6001 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
6002 NULL, NULL, 0, aggregate);
d62a17ae 6003
6004 /* Unlock aggregate address configuration. */
b613a918 6005 bgp_node_set_bgp_aggregate_info(rn, NULL);
d62a17ae 6006 bgp_aggregate_free(aggregate);
6007 bgp_unlock_node(rn);
6008 bgp_unlock_node(rn);
6009
6010 return CMD_SUCCESS;
6011}
6012
6013static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
d7c0a89a 6014 safi_t safi, uint8_t summary_only, uint8_t as_set)
d62a17ae 6015{
6016 VTY_DECLVAR_CONTEXT(bgp, bgp);
6017 int ret;
6018 struct prefix p;
6019 struct bgp_node *rn;
6020 struct bgp_aggregate *aggregate;
6021
6022 /* Convert string to prefix structure. */
6023 ret = str2prefix(prefix_str, &p);
6024 if (!ret) {
6025 vty_out(vty, "Malformed prefix\n");
6026 return CMD_WARNING_CONFIG_FAILED;
6027 }
6028 apply_mask(&p);
6029
3624ac81
DS
6030 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
6031 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
6032 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6033 prefix_str);
6034 return CMD_WARNING_CONFIG_FAILED;
6035 }
6036
d62a17ae 6037 /* Old configuration check. */
6038 rn = bgp_node_get(bgp->aggregate[afi][safi], &p);
6039
67009e22 6040 if (bgp_node_has_bgp_path_info_data(rn)) {
d62a17ae 6041 vty_out(vty, "There is already same aggregate network.\n");
6042 /* try to remove the old entry */
6043 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
6044 if (ret) {
6045 vty_out(vty, "Error deleting aggregate.\n");
6046 bgp_unlock_node(rn);
6047 return CMD_WARNING_CONFIG_FAILED;
6048 }
6049 }
718e3744 6050
d62a17ae 6051 /* Make aggregate address structure. */
6052 aggregate = bgp_aggregate_new();
6053 aggregate->summary_only = summary_only;
6054 aggregate->as_set = as_set;
6055 aggregate->safi = safi;
b613a918 6056 bgp_node_set_bgp_aggregate_info(rn, aggregate);
718e3744 6057
d62a17ae 6058 /* Aggregate address insert into BGP routing table. */
f273fef1 6059 bgp_aggregate_route(bgp, &p, NULL, afi, safi, NULL, aggregate);
718e3744 6060
d62a17ae 6061 return CMD_SUCCESS;
718e3744 6062}
6063
6064DEFUN (aggregate_address,
6065 aggregate_address_cmd,
e3e6107d 6066 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 6067 "Configure BGP aggregate entries\n"
6068 "Aggregate prefix\n"
6069 "Generate AS set path information\n"
a636c635
DW
6070 "Filter more specific routes from updates\n"
6071 "Filter more specific routes from updates\n"
6072 "Generate AS set path information\n")
718e3744 6073{
d62a17ae 6074 int idx = 0;
6075 argv_find(argv, argc, "A.B.C.D/M", &idx);
6076 char *prefix = argv[idx]->arg;
6077 int as_set =
6078 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
6079 idx = 0;
6080 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6081 ? AGGREGATE_SUMMARY_ONLY
6082 : 0;
e3e6107d 6083
d62a17ae 6084 return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty),
6085 summary_only, as_set);
718e3744 6086}
6087
e3e6107d
QY
6088DEFUN (aggregate_address_mask,
6089 aggregate_address_mask_cmd,
6090 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 6091 "Configure BGP aggregate entries\n"
6092 "Aggregate address\n"
6093 "Aggregate mask\n"
6094 "Generate AS set path information\n"
a636c635
DW
6095 "Filter more specific routes from updates\n"
6096 "Filter more specific routes from updates\n"
6097 "Generate AS set path information\n")
718e3744 6098{
d62a17ae 6099 int idx = 0;
6100 argv_find(argv, argc, "A.B.C.D", &idx);
6101 char *prefix = argv[idx]->arg;
6102 char *mask = argv[idx + 1]->arg;
6103 int as_set =
6104 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
6105 idx = 0;
6106 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6107 ? AGGREGATE_SUMMARY_ONLY
6108 : 0;
6109
6110 char prefix_str[BUFSIZ];
6111 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
6112
6113 if (!ret) {
6114 vty_out(vty, "%% Inconsistent address and mask\n");
6115 return CMD_WARNING_CONFIG_FAILED;
6116 }
718e3744 6117
d62a17ae 6118 return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
6119 summary_only, as_set);
718e3744 6120}
6121
718e3744 6122DEFUN (no_aggregate_address,
6123 no_aggregate_address_cmd,
e3e6107d 6124 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 6125 NO_STR
6126 "Configure BGP aggregate entries\n"
a636c635
DW
6127 "Aggregate prefix\n"
6128 "Generate AS set path information\n"
e3e6107d
QY
6129 "Filter more specific routes from updates\n"
6130 "Filter more specific routes from updates\n"
6131 "Generate AS set path information\n")
718e3744 6132{
d62a17ae 6133 int idx = 0;
6134 argv_find(argv, argc, "A.B.C.D/M", &idx);
6135 char *prefix = argv[idx]->arg;
6136 return bgp_aggregate_unset(vty, prefix, AFI_IP, bgp_node_safi(vty));
718e3744 6137}
6138
718e3744 6139DEFUN (no_aggregate_address_mask,
6140 no_aggregate_address_mask_cmd,
e3e6107d 6141 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 6142 NO_STR
6143 "Configure BGP aggregate entries\n"
6144 "Aggregate address\n"
a636c635
DW
6145 "Aggregate mask\n"
6146 "Generate AS set path information\n"
e3e6107d
QY
6147 "Filter more specific routes from updates\n"
6148 "Filter more specific routes from updates\n"
6149 "Generate AS set path information\n")
718e3744 6150{
d62a17ae 6151 int idx = 0;
6152 argv_find(argv, argc, "A.B.C.D", &idx);
6153 char *prefix = argv[idx]->arg;
6154 char *mask = argv[idx + 1]->arg;
718e3744 6155
d62a17ae 6156 char prefix_str[BUFSIZ];
6157 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
718e3744 6158
d62a17ae 6159 if (!ret) {
6160 vty_out(vty, "%% Inconsistent address and mask\n");
6161 return CMD_WARNING_CONFIG_FAILED;
6162 }
718e3744 6163
d62a17ae 6164 return bgp_aggregate_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
718e3744 6165}
6166
718e3744 6167DEFUN (ipv6_aggregate_address,
6168 ipv6_aggregate_address_cmd,
e3e6107d 6169 "aggregate-address X:X::X:X/M [summary-only]",
718e3744 6170 "Configure BGP aggregate entries\n"
6171 "Aggregate prefix\n"
6172 "Filter more specific routes from updates\n")
6173{
d62a17ae 6174 int idx = 0;
6175 argv_find(argv, argc, "X:X::X:X/M", &idx);
6176 char *prefix = argv[idx]->arg;
6177 int sum_only = argv_find(argv, argc, "summary-only", &idx)
6178 ? AGGREGATE_SUMMARY_ONLY
6179 : 0;
6180 return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, sum_only,
6181 0);
718e3744 6182}
6183
6184DEFUN (no_ipv6_aggregate_address,
6185 no_ipv6_aggregate_address_cmd,
e3e6107d 6186 "no aggregate-address X:X::X:X/M [summary-only]",
718e3744 6187 NO_STR
6188 "Configure BGP aggregate entries\n"
16cedbb0
QY
6189 "Aggregate prefix\n"
6190 "Filter more specific routes from updates\n")
718e3744 6191{
d62a17ae 6192 int idx = 0;
6193 argv_find(argv, argc, "X:X::X:X/M", &idx);
6194 char *prefix = argv[idx]->arg;
6195 return bgp_aggregate_unset(vty, prefix, AFI_IP6, SAFI_UNICAST);
718e3744 6196}
6197
718e3744 6198/* Redistribute route treatment. */
d62a17ae 6199void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
6200 const union g_addr *nexthop, ifindex_t ifindex,
6201 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
6202 uint8_t type, unsigned short instance,
6203 route_tag_t tag)
d62a17ae 6204{
4b7e6066 6205 struct bgp_path_info *new;
40381db7
DS
6206 struct bgp_path_info *bpi;
6207 struct bgp_path_info rmap_path;
d62a17ae 6208 struct bgp_node *bn;
6209 struct attr attr;
6210 struct attr *new_attr;
6211 afi_t afi;
6212 int ret;
6213 struct bgp_redist *red;
6214
6215 /* Make default attribute. */
6216 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
9de1f7ff 6217
a4d82a8a 6218 switch (nhtype) {
9de1f7ff
DS
6219 case NEXTHOP_TYPE_IFINDEX:
6220 break;
6221 case NEXTHOP_TYPE_IPV4:
6222 case NEXTHOP_TYPE_IPV4_IFINDEX:
6223 attr.nexthop = nexthop->ipv4;
6224 break;
6225 case NEXTHOP_TYPE_IPV6:
6226 case NEXTHOP_TYPE_IPV6_IFINDEX:
6227 attr.mp_nexthop_global = nexthop->ipv6;
6228 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
6229 break;
6230 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
6231 switch (p->family) {
6232 case AF_INET:
9de1f7ff 6233 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
6234 break;
6235 case AF_INET6:
9de1f7ff
DS
6236 memset(&attr.mp_nexthop_global, 0,
6237 sizeof(attr.mp_nexthop_global));
74489921 6238 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 6239 break;
74489921 6240 }
9de1f7ff 6241 break;
d62a17ae 6242 }
74489921 6243 attr.nh_ifindex = ifindex;
f04a80a5 6244
d62a17ae 6245 attr.med = metric;
6246 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
6247 attr.tag = tag;
718e3744 6248
d62a17ae 6249 afi = family2afi(p->family);
6aeb9e78 6250
d62a17ae 6251 red = bgp_redist_lookup(bgp, afi, type, instance);
6252 if (red) {
6253 struct attr attr_new;
718e3744 6254
d62a17ae 6255 /* Copy attribute for modification. */
6256 bgp_attr_dup(&attr_new, &attr);
718e3744 6257
d62a17ae 6258 if (red->redist_metric_flag)
6259 attr_new.med = red->redist_metric;
718e3744 6260
d62a17ae 6261 /* Apply route-map. */
6262 if (red->rmap.name) {
40381db7
DS
6263 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
6264 rmap_path.peer = bgp->peer_self;
6265 rmap_path.attr = &attr_new;
718e3744 6266
d62a17ae 6267 SET_FLAG(bgp->peer_self->rmap_type,
6268 PEER_RMAP_TYPE_REDISTRIBUTE);
6269
6270 ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
40381db7 6271 &rmap_path);
d62a17ae 6272
6273 bgp->peer_self->rmap_type = 0;
6274
6275 if (ret == RMAP_DENYMATCH) {
6276 /* Free uninterned attribute. */
6277 bgp_attr_flush(&attr_new);
6278
6279 /* Unintern original. */
6280 aspath_unintern(&attr.aspath);
6281 bgp_redistribute_delete(bgp, p, type, instance);
6282 return;
6283 }
6284 }
6285
7f323236
DW
6286 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
6287 bgp_attr_add_gshut_community(&attr_new);
6288
d62a17ae 6289 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
6290 SAFI_UNICAST, p, NULL);
6291
6292 new_attr = bgp_attr_intern(&attr_new);
6293
6f94b685
DS
6294 for (bpi = bgp_node_get_bgp_path_info(bn); bpi;
6295 bpi = bpi->next)
40381db7
DS
6296 if (bpi->peer == bgp->peer_self
6297 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 6298 break;
6299
40381db7 6300 if (bpi) {
d62a17ae 6301 /* Ensure the (source route) type is updated. */
40381db7
DS
6302 bpi->type = type;
6303 if (attrhash_cmp(bpi->attr, new_attr)
6304 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 6305 bgp_attr_unintern(&new_attr);
6306 aspath_unintern(&attr.aspath);
6307 bgp_unlock_node(bn);
6308 return;
6309 } else {
6310 /* The attribute is changed. */
40381db7 6311 bgp_path_info_set_flag(bn, bpi,
18ee8310 6312 BGP_PATH_ATTR_CHANGED);
d62a17ae 6313
6314 /* Rewrite BGP route information. */
40381db7
DS
6315 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
6316 bgp_path_info_restore(bn, bpi);
d62a17ae 6317 else
40381db7
DS
6318 bgp_aggregate_decrement(
6319 bgp, p, bpi, afi, SAFI_UNICAST);
6320 bgp_attr_unintern(&bpi->attr);
6321 bpi->attr = new_attr;
6322 bpi->uptime = bgp_clock();
d62a17ae 6323
6324 /* Process change. */
40381db7 6325 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 6326 SAFI_UNICAST);
6327 bgp_process(bgp, bn, afi, SAFI_UNICAST);
6328 bgp_unlock_node(bn);
6329 aspath_unintern(&attr.aspath);
ddb5b488
PZ
6330
6331 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6332 || (bgp->inst_type
6333 == BGP_INSTANCE_TYPE_DEFAULT)) {
6334
6335 vpn_leak_from_vrf_update(
40381db7 6336 bgp_get_default(), bgp, bpi);
ddb5b488 6337 }
d62a17ae 6338 return;
6339 }
6340 }
6341
6342 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
6343 bgp->peer_self, new_attr, bn);
1defdda8 6344 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 6345
6346 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 6347 bgp_path_info_add(bn, new);
d62a17ae 6348 bgp_unlock_node(bn);
6349 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
6350
6351 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6352 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6353
6354 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6355 }
d62a17ae 6356 }
6357
6358 /* Unintern original. */
6359 aspath_unintern(&attr.aspath);
718e3744 6360}
6361
d7c0a89a
QY
6362void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
6363 unsigned short instance)
718e3744 6364{
d62a17ae 6365 afi_t afi;
6366 struct bgp_node *rn;
40381db7 6367 struct bgp_path_info *pi;
d62a17ae 6368 struct bgp_redist *red;
718e3744 6369
d62a17ae 6370 afi = family2afi(p->family);
718e3744 6371
d62a17ae 6372 red = bgp_redist_lookup(bgp, afi, type, instance);
6373 if (red) {
6374 rn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
6375 SAFI_UNICAST, p, NULL);
6376
6f94b685 6377 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7 6378 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 6379 break;
6380
40381db7 6381 if (pi) {
ddb5b488
PZ
6382 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6383 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6384
6385 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 6386 bgp, pi);
ddb5b488 6387 }
40381db7
DS
6388 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
6389 bgp_path_info_delete(rn, pi);
d62a17ae 6390 bgp_process(bgp, rn, afi, SAFI_UNICAST);
6391 }
6392 bgp_unlock_node(rn);
6393 }
6394}
6395
6396/* Withdraw specified route type's route. */
6397void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 6398 unsigned short instance)
d62a17ae 6399{
6400 struct bgp_node *rn;
40381db7 6401 struct bgp_path_info *pi;
d62a17ae 6402 struct bgp_table *table;
6403
6404 table = bgp->rib[afi][SAFI_UNICAST];
6405
6406 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685 6407 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
6408 if (pi->peer == bgp->peer_self && pi->type == type
6409 && pi->instance == instance)
d62a17ae 6410 break;
6411
40381db7 6412 if (pi) {
ddb5b488
PZ
6413 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6414 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6415
6416 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 6417 bgp, pi);
ddb5b488 6418 }
40381db7 6419 bgp_aggregate_decrement(bgp, &rn->p, pi, afi,
d62a17ae 6420 SAFI_UNICAST);
40381db7 6421 bgp_path_info_delete(rn, pi);
d62a17ae 6422 bgp_process(bgp, rn, afi, SAFI_UNICAST);
6423 }
718e3744 6424 }
718e3744 6425}
6b0655a2 6426
718e3744 6427/* Static function to display route. */
9c92b5f7
MK
6428static void route_vty_out_route(struct prefix *p, struct vty *vty,
6429 json_object *json)
718e3744 6430{
be054588 6431 int len = 0;
d62a17ae 6432 char buf[BUFSIZ];
50e05855 6433 char buf2[BUFSIZ];
718e3744 6434
d62a17ae 6435 if (p->family == AF_INET) {
c6462ff4 6436 if (!json) {
89e5e9f0
PM
6437 len = vty_out(
6438 vty, "%s/%d",
6439 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
6440 p->prefixlen);
c6462ff4
MK
6441 } else {
6442 json_object_string_add(json, "prefix",
6443 inet_ntop(p->family,
6444 &p->u.prefix, buf,
6445 BUFSIZ));
6446 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 6447 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 6448 json_object_string_add(json, "network", buf2);
c6462ff4 6449 }
d62a17ae 6450 } else if (p->family == AF_ETHERNET) {
b03b8898
DS
6451 prefix2str(p, buf, PREFIX_STRLEN);
6452 len = vty_out(vty, "%s", buf);
6453 } else if (p->family == AF_EVPN) {
57f7feb6 6454 if (!json)
60466a63
QY
6455 len = vty_out(
6456 vty, "%s",
6457 bgp_evpn_route2str((struct prefix_evpn *)p, buf,
6458 BUFSIZ));
57f7feb6 6459 else
60466a63 6460 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
6461 } else if (p->family == AF_FLOWSPEC) {
6462 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
6463 json ?
6464 NLRI_STRING_FORMAT_JSON_SIMPLE :
6465 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 6466 } else {
c6462ff4 6467 if (!json)
60466a63
QY
6468 len = vty_out(
6469 vty, "%s/%d",
6470 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
6471 p->prefixlen);
50e05855
AD
6472 else {
6473 json_object_string_add(json, "prefix",
6474 inet_ntop(p->family,
6475 &p->u.prefix, buf,
6476 BUFSIZ));
6477 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
6478 prefix2str(p, buf2, PREFIX_STRLEN);
6479 json_object_string_add(json, "network", buf2);
6480 }
9c92b5f7 6481 }
d62a17ae 6482
9c92b5f7
MK
6483 if (!json) {
6484 len = 17 - len;
6485 if (len < 1)
6486 vty_out(vty, "\n%*s", 20, " ");
6487 else
6488 vty_out(vty, "%*s", len, " ");
6489 }
718e3744 6490}
6491
d62a17ae 6492enum bgp_display_type {
6493 normal_list,
718e3744 6494};
6495
18ee8310 6496/* Print the short form route status for a bgp_path_info */
4b7e6066 6497static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 6498 struct bgp_path_info *path,
d62a17ae 6499 json_object *json_path)
718e3744 6500{
d62a17ae 6501 if (json_path) {
b05a1c8b 6502
d62a17ae 6503 /* Route status display. */
9b6d8fcf 6504 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 6505 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 6506
9b6d8fcf 6507 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 6508 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 6509
9b6d8fcf 6510 if (path->extra && path->extra->suppress)
d62a17ae 6511 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 6512
9b6d8fcf
DS
6513 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
6514 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 6515 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 6516
d62a17ae 6517 /* Selected */
9b6d8fcf 6518 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 6519 json_object_boolean_true_add(json_path, "history");
b05a1c8b 6520
9b6d8fcf 6521 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 6522 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 6523
9b6d8fcf 6524 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 6525 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b 6526
9b6d8fcf 6527 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 6528 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 6529
d62a17ae 6530 /* Internal route. */
9b6d8fcf
DS
6531 if ((path->peer->as)
6532 && (path->peer->as == path->peer->local_as))
d62a17ae 6533 json_object_string_add(json_path, "pathFrom",
6534 "internal");
6535 else
6536 json_object_string_add(json_path, "pathFrom",
6537 "external");
b05a1c8b 6538
d62a17ae 6539 return;
6540 }
b05a1c8b 6541
d62a17ae 6542 /* Route status display. */
9b6d8fcf 6543 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 6544 vty_out(vty, "R");
9b6d8fcf 6545 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 6546 vty_out(vty, "S");
9b6d8fcf 6547 else if (path->extra && path->extra->suppress)
d62a17ae 6548 vty_out(vty, "s");
9b6d8fcf
DS
6549 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
6550 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 6551 vty_out(vty, "*");
6552 else
6553 vty_out(vty, " ");
6554
6555 /* Selected */
9b6d8fcf 6556 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 6557 vty_out(vty, "h");
9b6d8fcf 6558 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 6559 vty_out(vty, "d");
9b6d8fcf 6560 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 6561 vty_out(vty, ">");
9b6d8fcf 6562 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 6563 vty_out(vty, "=");
6564 else
6565 vty_out(vty, " ");
718e3744 6566
d62a17ae 6567 /* Internal route. */
9b6d8fcf
DS
6568 if (path->peer && (path->peer->as)
6569 && (path->peer->as == path->peer->local_as))
d62a17ae 6570 vty_out(vty, "i");
6571 else
6572 vty_out(vty, " ");
b40d939b 6573}
6574
6575/* called from terminal list command */
4b7e6066 6576void route_vty_out(struct vty *vty, struct prefix *p,
9b6d8fcf 6577 struct bgp_path_info *path, int display, safi_t safi,
4b7e6066 6578 json_object *json_paths)
d62a17ae 6579{
6580 struct attr *attr;
6581 json_object *json_path = NULL;
6582 json_object *json_nexthops = NULL;
6583 json_object *json_nexthop_global = NULL;
6584 json_object *json_nexthop_ll = NULL;
9df8b37c 6585 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 6586 bool nexthop_self =
9b6d8fcf 6587 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 6588 bool nexthop_othervrf = false;
43089216 6589 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 6590 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
d62a17ae 6591
6592 if (json_paths)
6593 json_path = json_object_new_object();
6594
6595 /* short status lead text */
9b6d8fcf 6596 route_vty_short_status_out(vty, path, json_path);
d62a17ae 6597
6598 if (!json_paths) {
6599 /* print prefix and mask */
6600 if (!display)
9c92b5f7 6601 route_vty_out_route(p, vty, json_path);
d62a17ae 6602 else
6603 vty_out(vty, "%*s", 17, " ");
9c92b5f7 6604 } else {
b682f6de 6605 route_vty_out_route(p, vty, json_path);
d62a17ae 6606 }
47fc97cc 6607
d62a17ae 6608 /* Print attribute */
9b6d8fcf 6609 attr = path->attr;
445c2480
DS
6610 if (!attr) {
6611 if (json_paths)
6612 json_object_array_add(json_paths, json_path);
6613 else
6614 vty_out(vty, "\n");
d62a17ae 6615
445c2480
DS
6616 return;
6617 }
6618
9df8b37c
PZ
6619 /*
6620 * If vrf id of nexthop is different from that of prefix,
6621 * set up printable string to append
6622 */
9b6d8fcf 6623 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
6624 const char *self = "";
6625
6626 if (nexthop_self)
6627 self = "<";
6628
6629 nexthop_othervrf = true;
9b6d8fcf 6630 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 6631
9b6d8fcf 6632 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
6633 snprintf(vrf_id_str, sizeof(vrf_id_str),
6634 "@%s%s", VRFID_NONE_STR, self);
6635 else
6636 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 6637 path->extra->bgp_orig->vrf_id, self);
9df8b37c 6638
9b6d8fcf
DS
6639 if (path->extra->bgp_orig->inst_type
6640 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 6641
9b6d8fcf 6642 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
6643 } else {
6644 const char *self = "";
6645
6646 if (nexthop_self)
6647 self = "<";
6648
6649 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
6650 }
6651
445c2480
DS
6652 /*
6653 * For ENCAP and EVPN routes, nexthop address family is not
6654 * neccessarily the same as the prefix address family.
6655 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6656 * EVPN routes are also exchanged with a MP nexthop. Currently,
6657 * this
6658 * is only IPv4, the value will be present in either
6659 * attr->nexthop or
6660 * attr->mp_nexthop_global_in
6661 */
6662 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
6663 char buf[BUFSIZ];
6664 char nexthop[128];
6665 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
6666
6667 switch (af) {
6668 case AF_INET:
6669 sprintf(nexthop, "%s",
a4d82a8a
PZ
6670 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
6671 BUFSIZ));
445c2480
DS
6672 break;
6673 case AF_INET6:
6674 sprintf(nexthop, "%s",
a4d82a8a
PZ
6675 inet_ntop(af, &attr->mp_nexthop_global, buf,
6676 BUFSIZ));
445c2480
DS
6677 break;
6678 default:
6679 sprintf(nexthop, "?");
6680 break;
d62a17ae 6681 }
d62a17ae 6682
445c2480
DS
6683 if (json_paths) {
6684 json_nexthop_global = json_object_new_object();
6685
a4d82a8a
PZ
6686 json_object_string_add(json_nexthop_global, "afi",
6687 (af == AF_INET) ? "ip" : "ipv6");
445c2480 6688 json_object_string_add(json_nexthop_global,
a4d82a8a 6689 (af == AF_INET) ? "ip" : "ipv6",
445c2480
DS
6690 nexthop);
6691 json_object_boolean_true_add(json_nexthop_global,
6692 "used");
6693 } else
9df8b37c 6694 vty_out(vty, "%s%s", nexthop, vrf_id_str);
445c2480
DS
6695 } else if (safi == SAFI_EVPN) {
6696 if (json_paths) {
6697 json_nexthop_global = json_object_new_object();
6698
6699 json_object_string_add(json_nexthop_global, "ip",
6700 inet_ntoa(attr->nexthop));
a4d82a8a
PZ
6701 json_object_string_add(json_nexthop_global, "afi",
6702 "ipv4");
445c2480
DS
6703 json_object_boolean_true_add(json_nexthop_global,
6704 "used");
6705 } else
9df8b37c
PZ
6706 vty_out(vty, "%-16s%s", inet_ntoa(attr->nexthop),
6707 vrf_id_str);
d33fc23b 6708 } else if (safi == SAFI_FLOWSPEC) {
026b914a
PG
6709 if (attr->nexthop.s_addr != 0) {
6710 if (json_paths) {
6711 json_nexthop_global = json_object_new_object();
6712 json_object_string_add(
6713 json_nexthop_global, "ip",
6714 inet_ntoa(attr->nexthop));
6715 json_object_string_add(json_nexthop_global,
6716 "afi", "ipv4");
50e05855
AD
6717 json_object_boolean_true_add(
6718 json_nexthop_global,
026b914a
PG
6719 "used");
6720 } else {
6721 vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
6722 }
6723 }
d33fc23b 6724 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
6725 if (json_paths) {
6726 json_nexthop_global = json_object_new_object();
d62a17ae 6727
a4d82a8a
PZ
6728 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN))
6729 json_object_string_add(
6730 json_nexthop_global, "ip",
6731 inet_ntoa(attr->mp_nexthop_global_in));
445c2480 6732 else
a4d82a8a
PZ
6733 json_object_string_add(
6734 json_nexthop_global, "ip",
6735 inet_ntoa(attr->nexthop));
445c2480 6736
a4d82a8a
PZ
6737 json_object_string_add(json_nexthop_global, "afi",
6738 "ipv4");
445c2480
DS
6739 json_object_boolean_true_add(json_nexthop_global,
6740 "used");
6741 } else {
9df8b37c
PZ
6742 char buf[BUFSIZ];
6743
d87ff2dd 6744 snprintf(buf, sizeof(buf), "%s%s",
6745 inet_ntoa(attr->nexthop), vrf_id_str);
9df8b37c 6746 vty_out(vty, "%-16s", buf);
d62a17ae 6747 }
445c2480 6748 }
b05a1c8b 6749
445c2480 6750 /* IPv6 Next Hop */
a4d82a8a 6751 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
6752 int len;
6753 char buf[BUFSIZ];
d62a17ae 6754
445c2480
DS
6755 if (json_paths) {
6756 json_nexthop_global = json_object_new_object();
a4d82a8a
PZ
6757 json_object_string_add(
6758 json_nexthop_global, "ip",
6759 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
6760 buf, BUFSIZ));
6761 json_object_string_add(json_nexthop_global, "afi",
6762 "ipv6");
6763 json_object_string_add(json_nexthop_global, "scope",
6764 "global");
445c2480
DS
6765
6766 /* We display both LL & GL if both have been
6767 * received */
6768 if ((attr->mp_nexthop_len == 32)
9b6d8fcf 6769 || (path->peer->conf_if)) {
a4d82a8a 6770 json_nexthop_ll = json_object_new_object();
d62a17ae 6771 json_object_string_add(
445c2480 6772 json_nexthop_ll, "ip",
a4d82a8a
PZ
6773 inet_ntop(AF_INET6,
6774 &attr->mp_nexthop_local, buf,
6775 BUFSIZ));
6776 json_object_string_add(json_nexthop_ll, "afi",
6777 "ipv6");
6778 json_object_string_add(json_nexthop_ll, "scope",
445c2480 6779 "link-local");
d62a17ae 6780
a4d82a8a
PZ
6781 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
6782 &attr->mp_nexthop_local)
445c2480
DS
6783 != 0)
6784 && !attr->mp_nexthop_prefer_global)
d62a17ae 6785 json_object_boolean_true_add(
a4d82a8a 6786 json_nexthop_ll, "used");
445c2480
DS
6787 else
6788 json_object_boolean_true_add(
a4d82a8a 6789 json_nexthop_global, "used");
445c2480
DS
6790 } else
6791 json_object_boolean_true_add(
6792 json_nexthop_global, "used");
6793 } else {
6794 /* Display LL if LL/Global both in table unless
6795 * prefer-global is set */
6796 if (((attr->mp_nexthop_len == 32)
6797 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
6798 || (path->peer->conf_if)) {
6799 if (path->peer->conf_if) {
a4d82a8a 6800 len = vty_out(vty, "%s",
9b6d8fcf 6801 path->peer->conf_if);
445c2480
DS
6802 len = 16 - len; /* len of IPv6
6803 addr + max
6804 len of def
6805 ifname */
6806
6807 if (len < 1)
a4d82a8a 6808 vty_out(vty, "\n%*s", 36, " ");
445c2480 6809 else
a4d82a8a 6810 vty_out(vty, "%*s", len, " ");
d62a17ae 6811 } else {
6812 len = vty_out(
9df8b37c 6813 vty, "%s%s",
d62a17ae 6814 inet_ntop(
6815 AF_INET6,
445c2480 6816 &attr->mp_nexthop_local,
9df8b37c
PZ
6817 buf, BUFSIZ),
6818 vrf_id_str);
d62a17ae 6819 len = 16 - len;
6820
6821 if (len < 1)
a4d82a8a 6822 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 6823 else
a4d82a8a 6824 vty_out(vty, "%*s", len, " ");
d62a17ae 6825 }
445c2480 6826 } else {
a4d82a8a 6827 len = vty_out(
9df8b37c 6828 vty, "%s%s",
a4d82a8a
PZ
6829 inet_ntop(AF_INET6,
6830 &attr->mp_nexthop_global, buf,
9df8b37c
PZ
6831 BUFSIZ),
6832 vrf_id_str);
445c2480
DS
6833 len = 16 - len;
6834
6835 if (len < 1)
6836 vty_out(vty, "\n%*s", 36, " ");
6837 else
6838 vty_out(vty, "%*s", len, " ");
d62a17ae 6839 }
6840 }
445c2480 6841 }
718e3744 6842
445c2480
DS
6843 /* MED/Metric */
6844 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
50e05855
AD
6845 if (json_paths) {
6846
6847 /*
6848 * Adding "metric" field to match with corresponding
6849 * CLI. "med" will be deprecated in future.
6850 */
a4d82a8a 6851 json_object_int_add(json_path, "med", attr->med);
50e05855
AD
6852 json_object_int_add(json_path, "metric", attr->med);
6853 } else
445c2480
DS
6854 vty_out(vty, "%10u", attr->med);
6855 else if (!json_paths)
6856 vty_out(vty, " ");
d62a17ae 6857
445c2480
DS
6858 /* Local Pref */
6859 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855
AD
6860 if (json_paths) {
6861
6862 /*
6863 * Adding "locPrf" field to match with corresponding
6864 * CLI. "localPref" will be deprecated in future.
6865 */
445c2480
DS
6866 json_object_int_add(json_path, "localpref",
6867 attr->local_pref);
50e05855
AD
6868 json_object_int_add(json_path, "locPrf",
6869 attr->local_pref);
6870 } else
445c2480
DS
6871 vty_out(vty, "%7u", attr->local_pref);
6872 else if (!json_paths)
6873 vty_out(vty, " ");
d62a17ae 6874
445c2480
DS
6875 if (json_paths)
6876 json_object_int_add(json_path, "weight", attr->weight);
6877 else
6878 vty_out(vty, "%7u ", attr->weight);
47fc97cc 6879
445c2480
DS
6880 if (json_paths) {
6881 char buf[BUFSIZ];
a4d82a8a
PZ
6882 json_object_string_add(
6883 json_path, "peerId",
9b6d8fcf 6884 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 6885 }
b05a1c8b 6886
445c2480
DS
6887 /* Print aspath */
6888 if (attr->aspath) {
50e05855
AD
6889 if (json_paths) {
6890
6891 /*
6892 * Adding "path" field to match with corresponding
6893 * CLI. "aspath" will be deprecated in future.
6894 */
445c2480
DS
6895 json_object_string_add(json_path, "aspath",
6896 attr->aspath->str);
50e05855
AD
6897 json_object_string_add(json_path, "path",
6898 attr->aspath->str);
6899 } else
445c2480 6900 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 6901 }
f1aa5d8a 6902
445c2480
DS
6903 /* Print origin */
6904 if (json_paths)
a4d82a8a
PZ
6905 json_object_string_add(json_path, "origin",
6906 bgp_origin_long_str[attr->origin]);
445c2480
DS
6907 else
6908 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
6909
9df8b37c
PZ
6910 if (json_paths) {
6911 if (nexthop_self)
6912 json_object_boolean_true_add(json_path,
6913 "announceNexthopSelf");
6914 if (nexthop_othervrf) {
6915 json_object_string_add(json_path, "nhVrfName",
6916 nexthop_vrfname);
6917
6918 json_object_int_add(json_path, "nhVrfId",
6919 ((nexthop_vrfid == VRF_UNKNOWN)
6920 ? -1
6921 : (int)nexthop_vrfid));
6922 }
6923 }
6924
d62a17ae 6925 if (json_paths) {
6926 if (json_nexthop_global || json_nexthop_ll) {
6927 json_nexthops = json_object_new_array();
f1aa5d8a 6928
d62a17ae 6929 if (json_nexthop_global)
6930 json_object_array_add(json_nexthops,
6931 json_nexthop_global);
f1aa5d8a 6932
d62a17ae 6933 if (json_nexthop_ll)
6934 json_object_array_add(json_nexthops,
6935 json_nexthop_ll);
f1aa5d8a 6936
d62a17ae 6937 json_object_object_add(json_path, "nexthops",
6938 json_nexthops);
6939 }
6940
6941 json_object_array_add(json_paths, json_path);
6942 } else {
6943 vty_out(vty, "\n");
65efcfce 6944#if ENABLE_BGP_VNC
d62a17ae 6945 /* prints an additional line, indented, with VNC info, if
6946 * present */
6947 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 6948 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 6949#endif
d62a17ae 6950 }
6951}
718e3744 6952
6953/* called from terminal list command */
d62a17ae 6954void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr,
9f049418 6955 safi_t safi, bool use_json, json_object *json_ar)
d62a17ae 6956{
6957 json_object *json_status = NULL;
6958 json_object *json_net = NULL;
6959 char buff[BUFSIZ];
50e05855 6960 char buf2[BUFSIZ];
d62a17ae 6961 /* Route status display. */
6962 if (use_json) {
6963 json_status = json_object_new_object();
6964 json_net = json_object_new_object();
6965 } else {
6966 vty_out(vty, "*");
6967 vty_out(vty, ">");
6968 vty_out(vty, " ");
6969 }
718e3744 6970
d62a17ae 6971 /* print prefix and mask */
50e05855 6972 if (use_json) {
d62a17ae 6973 json_object_string_add(
6974 json_net, "addrPrefix",
6975 inet_ntop(p->family, &p->u.prefix, buff, BUFSIZ));
50e05855 6976 json_object_int_add(json_net, "prefixLen", p->prefixlen);
37d4e0df 6977 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855
AD
6978 json_object_string_add(json_net, "network", buf2);
6979 } else
9c92b5f7 6980 route_vty_out_route(p, vty, NULL);
d62a17ae 6981
6982 /* Print attribute */
6983 if (attr) {
6984 if (use_json) {
6985 if (p->family == AF_INET
6986 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6987 || safi == SAFI_EVPN
6988 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
6989 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6990 || safi == SAFI_EVPN)
6991 json_object_string_add(
6992 json_net, "nextHop",
6993 inet_ntoa(
6994 attr->mp_nexthop_global_in));
6995 else
6996 json_object_string_add(
6997 json_net, "nextHop",
6998 inet_ntoa(attr->nexthop));
6999 } else if (p->family == AF_INET6
7000 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
7001 char buf[BUFSIZ];
7002
7003 json_object_string_add(
aa0a10fc 7004 json_net, "nextHopGlobal",
d62a17ae 7005 inet_ntop(AF_INET6,
7006 &attr->mp_nexthop_global, buf,
7007 BUFSIZ));
7008 }
7009
7010 if (attr->flag
7011 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
7012 json_object_int_add(json_net, "metric",
7013 attr->med);
7014
50e05855
AD
7015 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
7016
7017 /*
7018 * Adding "locPrf" field to match with
7019 * corresponding CLI. "localPref" will be
7020 * deprecated in future.
7021 */
d62a17ae 7022 json_object_int_add(json_net, "localPref",
7023 attr->local_pref);
50e05855
AD
7024 json_object_int_add(json_net, "locPrf",
7025 attr->local_pref);
7026 }
d62a17ae 7027
7028 json_object_int_add(json_net, "weight", attr->weight);
7029
7030 /* Print aspath */
50e05855
AD
7031 if (attr->aspath) {
7032
7033 /*
7034 * Adding "path" field to match with
7035 * corresponding CLI. "localPref" will be
7036 * deprecated in future.
7037 */
d62a17ae 7038 json_object_string_add(json_net, "asPath",
7039 attr->aspath->str);
50e05855
AD
7040 json_object_string_add(json_net, "path",
7041 attr->aspath->str);
7042 }
d62a17ae 7043
7044 /* Print origin */
7045 json_object_string_add(json_net, "bgpOriginCode",
7046 bgp_origin_str[attr->origin]);
7047 } else {
7048 if (p->family == AF_INET
7049 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7050 || safi == SAFI_EVPN
7051 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7052 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7053 || safi == SAFI_EVPN)
7054 vty_out(vty, "%-16s",
7055 inet_ntoa(
7056 attr->mp_nexthop_global_in));
7057 else
7058 vty_out(vty, "%-16s",
7059 inet_ntoa(attr->nexthop));
7060 } else if (p->family == AF_INET6
7061 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
7062 int len;
7063 char buf[BUFSIZ];
7064
7065 len = vty_out(
7066 vty, "%s",
7067 inet_ntop(AF_INET6,
7068 &attr->mp_nexthop_global, buf,
7069 BUFSIZ));
7070 len = 16 - len;
7071 if (len < 1)
7072 vty_out(vty, "\n%*s", 36, " ");
7073 else
7074 vty_out(vty, "%*s", len, " ");
7075 }
7076 if (attr->flag
7077 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
7078 vty_out(vty, "%10u", attr->med);
7079 else
7080 vty_out(vty, " ");
718e3744 7081
d62a17ae 7082 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
7083 vty_out(vty, "%7u", attr->local_pref);
7084 else
7085 vty_out(vty, " ");
7086
7087 vty_out(vty, "%7u ", attr->weight);
7088
7089 /* Print aspath */
7090 if (attr->aspath)
7091 aspath_print_vty(vty, "%s", attr->aspath, " ");
7092
7093 /* Print origin */
7094 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7095 }
7096 }
7097 if (use_json) {
7098 json_object_boolean_true_add(json_status, "*");
7099 json_object_boolean_true_add(json_status, ">");
7100 json_object_object_add(json_net, "appliedStatusSymbols",
7101 json_status);
7102 char buf_cut[BUFSIZ];
7103 json_object_object_add(
7104 json_ar,
7105 inet_ntop(p->family, &p->u.prefix, buf_cut, BUFSIZ),
7106 json_net);
7107 } else
7108 vty_out(vty, "\n");
7109}
7110
7111void route_vty_out_tag(struct vty *vty, struct prefix *p,
9b6d8fcf 7112 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 7113 json_object *json)
7114{
7115 json_object *json_out = NULL;
7116 struct attr *attr;
7117 mpls_label_t label = MPLS_INVALID_LABEL;
7118
9b6d8fcf 7119 if (!path->extra)
d62a17ae 7120 return;
7121
7122 if (json)
7123 json_out = json_object_new_object();
7124
7125 /* short status lead text */
9b6d8fcf 7126 route_vty_short_status_out(vty, path, json_out);
d62a17ae 7127
7128 /* print prefix and mask */
7129 if (json == NULL) {
7130 if (!display)
9c92b5f7 7131 route_vty_out_route(p, vty, NULL);
d62a17ae 7132 else
7133 vty_out(vty, "%*s", 17, " ");
7134 }
7135
7136 /* Print attribute */
9b6d8fcf 7137 attr = path->attr;
d62a17ae 7138 if (attr) {
7139 if (((p->family == AF_INET)
7140 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
a4d82a8a 7141 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
d62a17ae 7142 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7143 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7144 || safi == SAFI_EVPN) {
7145 if (json)
7146 json_object_string_add(
7147 json_out, "mpNexthopGlobalIn",
7148 inet_ntoa(
7149 attr->mp_nexthop_global_in));
7150 else
7151 vty_out(vty, "%-16s",
7152 inet_ntoa(
7153 attr->mp_nexthop_global_in));
7154 } else {
7155 if (json)
7156 json_object_string_add(
7157 json_out, "nexthop",
7158 inet_ntoa(attr->nexthop));
7159 else
7160 vty_out(vty, "%-16s",
7161 inet_ntoa(attr->nexthop));
7162 }
7163 } else if (((p->family == AF_INET6)
7164 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
b03b8898 7165 || (safi == SAFI_EVPN
d62a17ae 7166 && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
7167 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
ff44f570
DS
7168 char buf_a[512];
7169 char buf_b[512];
d62a17ae 7170 char buf_c[BUFSIZ];
7171 if (attr->mp_nexthop_len
7172 == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
7173 if (json)
7174 json_object_string_add(
7175 json_out, "mpNexthopGlobalIn",
7176 inet_ntop(
7177 AF_INET6,
7178 &attr->mp_nexthop_global,
11f9b450 7179 buf_a, sizeof(buf_a)));
d62a17ae 7180 else
7181 vty_out(vty, "%s",
7182 inet_ntop(
7183 AF_INET6,
7184 &attr->mp_nexthop_global,
11f9b450 7185 buf_a, sizeof(buf_a)));
d62a17ae 7186 } else if (attr->mp_nexthop_len
7187 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
7188 if (json) {
7189 inet_ntop(AF_INET6,
7190 &attr->mp_nexthop_global,
11f9b450 7191 buf_a, sizeof(buf_a));
d62a17ae 7192 inet_ntop(AF_INET6,
7193 &attr->mp_nexthop_local,
11f9b450 7194 buf_b, sizeof(buf_b));
d62a17ae 7195 sprintf(buf_c, "%s(%s)", buf_a, buf_b);
7196 json_object_string_add(
7197 json_out,
7198 "mpNexthopGlobalLocal", buf_c);
7199 } else
7200 vty_out(vty, "%s(%s)",
7201 inet_ntop(
7202 AF_INET6,
7203 &attr->mp_nexthop_global,
11f9b450 7204 buf_a, sizeof(buf_a)),
d62a17ae 7205 inet_ntop(
7206 AF_INET6,
7207 &attr->mp_nexthop_local,
11f9b450 7208 buf_b, sizeof(buf_b)));
d62a17ae 7209 }
7210 }
7211 }
7212
9b6d8fcf 7213 label = decode_label(&path->extra->label[0]);
d62a17ae 7214
7215 if (bgp_is_valid_label(&label)) {
7216 if (json) {
7217 json_object_int_add(json_out, "notag", label);
7218 json_object_array_add(json, json_out);
7219 } else {
7220 vty_out(vty, "notag/%d", label);
7221 vty_out(vty, "\n");
7222 }
7223 }
7224}
718e3744 7225
d62a17ae 7226void route_vty_out_overlay(struct vty *vty, struct prefix *p,
9b6d8fcf 7227 struct bgp_path_info *path, int display,
d62a17ae 7228 json_object *json_paths)
718e3744 7229{
d62a17ae 7230 struct attr *attr;
7231 char buf[BUFSIZ];
7232 json_object *json_path = NULL;
784d3a42 7233
d62a17ae 7234 if (json_paths)
7235 json_path = json_object_new_object();
856ca177 7236
9b6d8fcf 7237 if (!path->extra)
d62a17ae 7238 return;
718e3744 7239
d62a17ae 7240 /* short status lead text */
9b6d8fcf 7241 route_vty_short_status_out(vty, path, json_path);
856ca177 7242
d62a17ae 7243 /* print prefix and mask */
7244 if (!display)
9c92b5f7 7245 route_vty_out_route(p, vty, NULL);
d62a17ae 7246 else
7247 vty_out(vty, "%*s", 17, " ");
7248
7249 /* Print attribute */
9b6d8fcf 7250 attr = path->attr;
d62a17ae 7251 if (attr) {
7252 char buf1[BUFSIZ];
7253 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
7254
7255 switch (af) {
7256 case AF_INET:
7257 vty_out(vty, "%-16s",
7258 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
7259 BUFSIZ));
7260 break;
7261 case AF_INET6:
7262 vty_out(vty, "%s(%s)",
7263 inet_ntop(af, &attr->mp_nexthop_global, buf,
7264 BUFSIZ),
7265 inet_ntop(af, &attr->mp_nexthop_local, buf1,
7266 BUFSIZ));
7267 break;
7268 default:
7269 vty_out(vty, "?");
7270 }
988258b4
QY
7271
7272 char *str = esi2str(&(attr->evpn_overlay.eth_s_id));
7273
7274 vty_out(vty, "%s", str);
7275 XFREE(MTYPE_TMP, str);
7276
3714a385 7277 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
988258b4
QY
7278 vty_out(vty, "/%s",
7279 inet_ntoa(attr->evpn_overlay.gw_ip.ipv4));
3714a385 7280 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
988258b4
QY
7281 vty_out(vty, "/%s",
7282 inet_ntop(AF_INET6,
7283 &(attr->evpn_overlay.gw_ip.ipv6), buf,
7284 BUFSIZ));
7285 }
7286 if (attr->ecommunity) {
7287 char *mac = NULL;
7288 struct ecommunity_val *routermac = ecommunity_lookup(
7289 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
7290 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
7291 if (routermac)
7292 mac = ecom_mac2str((char *)routermac->val);
7293 if (mac) {
7294 vty_out(vty, "/%s", (char *)mac);
7295 XFREE(MTYPE_TMP, mac);
7296 }
7297 }
7298 vty_out(vty, "\n");
718e3744 7299 }
718e3744 7300
d62a17ae 7301}
718e3744 7302
d62a17ae 7303/* dampening route */
7304static void damp_route_vty_out(struct vty *vty, struct prefix *p,
9b6d8fcf 7305 struct bgp_path_info *path, int display,
4b7e6066 7306 safi_t safi, bool use_json, json_object *json)
d62a17ae 7307{
7308 struct attr *attr;
7309 int len;
7310 char timebuf[BGP_UPTIME_LEN];
7311
7312 /* short status lead text */
9b6d8fcf 7313 route_vty_short_status_out(vty, path, json);
d62a17ae 7314
7315 /* print prefix and mask */
7316 if (!use_json) {
7317 if (!display)
9c92b5f7 7318 route_vty_out_route(p, vty, NULL);
d62a17ae 7319 else
7320 vty_out(vty, "%*s", 17, " ");
7321 }
7322
9b6d8fcf 7323 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 7324 len = 17 - len;
7325 if (len < 1) {
7326 if (!use_json)
7327 vty_out(vty, "\n%*s", 34, " ");
7328 } else {
7329 if (use_json)
7330 json_object_int_add(json, "peerHost", len);
7331 else
7332 vty_out(vty, "%*s", len, " ");
7333 }
7334
7335 if (use_json)
9b6d8fcf 7336 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN,
d62a17ae 7337 use_json, json);
7338 else
9b6d8fcf
DS
7339 vty_out(vty, "%s ",
7340 bgp_damp_reuse_time_vty(vty, path, timebuf,
7341 BGP_UPTIME_LEN, use_json,
7342 json));
d62a17ae 7343
7344 /* Print attribute */
9b6d8fcf 7345 attr = path->attr;
d62a17ae 7346 if (attr) {
7347 /* Print aspath */
7348 if (attr->aspath) {
7349 if (use_json)
7350 json_object_string_add(json, "asPath",
7351 attr->aspath->str);
7352 else
7353 aspath_print_vty(vty, "%s", attr->aspath, " ");
7354 }
7355
7356 /* Print origin */
7357 if (use_json)
7358 json_object_string_add(json, "origin",
7359 bgp_origin_str[attr->origin]);
7360 else
7361 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7362 }
7363 if (!use_json)
7364 vty_out(vty, "\n");
7365}
718e3744 7366
d62a17ae 7367/* flap route */
7368static void flap_route_vty_out(struct vty *vty, struct prefix *p,
9b6d8fcf 7369 struct bgp_path_info *path, int display,
4b7e6066 7370 safi_t safi, bool use_json, json_object *json)
784d3a42 7371{
d62a17ae 7372 struct attr *attr;
7373 struct bgp_damp_info *bdi;
7374 char timebuf[BGP_UPTIME_LEN];
7375 int len;
784d3a42 7376
9b6d8fcf 7377 if (!path->extra)
d62a17ae 7378 return;
784d3a42 7379
9b6d8fcf 7380 bdi = path->extra->damp_info;
784d3a42 7381
d62a17ae 7382 /* short status lead text */
9b6d8fcf 7383 route_vty_short_status_out(vty, path, json);
784d3a42 7384
d62a17ae 7385 /* print prefix and mask */
7386 if (!use_json) {
7387 if (!display)
9c92b5f7 7388 route_vty_out_route(p, vty, NULL);
d62a17ae 7389 else
7390 vty_out(vty, "%*s", 17, " ");
7391 }
784d3a42 7392
9b6d8fcf 7393 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 7394 len = 16 - len;
7395 if (len < 1) {
7396 if (!use_json)
7397 vty_out(vty, "\n%*s", 33, " ");
7398 } else {
7399 if (use_json)
7400 json_object_int_add(json, "peerHost", len);
7401 else
7402 vty_out(vty, "%*s", len, " ");
7403 }
784d3a42 7404
d62a17ae 7405 len = vty_out(vty, "%d", bdi->flap);
7406 len = 5 - len;
7407 if (len < 1) {
7408 if (!use_json)
7409 vty_out(vty, " ");
7410 } else {
7411 if (use_json)
7412 json_object_int_add(json, "bdiFlap", len);
7413 else
7414 vty_out(vty, "%*s", len, " ");
7415 }
7416
7417 if (use_json)
7418 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
7419 json);
7420 else
996c9314
LB
7421 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
7422 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 7423
9b6d8fcf
DS
7424 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
7425 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 7426 if (use_json)
9b6d8fcf 7427 bgp_damp_reuse_time_vty(vty, path, timebuf,
d62a17ae 7428 BGP_UPTIME_LEN, use_json, json);
7429 else
7430 vty_out(vty, "%s ",
9b6d8fcf 7431 bgp_damp_reuse_time_vty(vty, path, timebuf,
d62a17ae 7432 BGP_UPTIME_LEN,
7433 use_json, json));
7434 } else {
7435 if (!use_json)
7436 vty_out(vty, "%*s ", 8, " ");
7437 }
7438
7439 /* Print attribute */
9b6d8fcf 7440 attr = path->attr;
d62a17ae 7441 if (attr) {
7442 /* Print aspath */
7443 if (attr->aspath) {
7444 if (use_json)
7445 json_object_string_add(json, "asPath",
7446 attr->aspath->str);
7447 else
7448 aspath_print_vty(vty, "%s", attr->aspath, " ");
7449 }
7450
7451 /* Print origin */
7452 if (use_json)
7453 json_object_string_add(json, "origin",
7454 bgp_origin_str[attr->origin]);
7455 else
7456 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7457 }
7458 if (!use_json)
7459 vty_out(vty, "\n");
7460}
7461
7462static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
7463 int *first, const char *header,
7464 json_object *json_adv_to)
7465{
7466 char buf1[INET6_ADDRSTRLEN];
7467 json_object *json_peer = NULL;
7468
7469 if (json_adv_to) {
7470 /* 'advertised-to' is a dictionary of peers we have advertised
7471 * this
7472 * prefix too. The key is the peer's IP or swpX, the value is
7473 * the
7474 * hostname if we know it and "" if not.
7475 */
7476 json_peer = json_object_new_object();
7477
7478 if (peer->hostname)
7479 json_object_string_add(json_peer, "hostname",
7480 peer->hostname);
7481
7482 if (peer->conf_if)
7483 json_object_object_add(json_adv_to, peer->conf_if,
7484 json_peer);
7485 else
7486 json_object_object_add(
7487 json_adv_to,
7488 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
7489 json_peer);
7490 } else {
7491 if (*first) {
7492 vty_out(vty, "%s", header);
7493 *first = 0;
7494 }
7495
7496 if (peer->hostname
7497 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
7498 if (peer->conf_if)
7499 vty_out(vty, " %s(%s)", peer->hostname,
7500 peer->conf_if);
7501 else
7502 vty_out(vty, " %s(%s)", peer->hostname,
7503 sockunion2str(&peer->su, buf1,
7504 SU_ADDRSTRLEN));
7505 } else {
7506 if (peer->conf_if)
7507 vty_out(vty, " %s", peer->conf_if);
7508 else
7509 vty_out(vty, " %s",
7510 sockunion2str(&peer->su, buf1,
7511 SU_ADDRSTRLEN));
7512 }
7513 }
784d3a42
PG
7514}
7515
dcc68b5e
MS
7516static void route_vty_out_tx_ids(struct vty *vty,
7517 struct bgp_addpath_info_data *d)
7518{
7519 int i;
7520
7521 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
7522 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
7523 d->addpath_tx_id[i],
7524 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
7525 }
7526}
7527
d62a17ae 7528void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
9b6d8fcf 7529 struct bgp_path_info *path, afi_t afi, safi_t safi,
d62a17ae 7530 json_object *json_paths)
7531{
7532 char buf[INET6_ADDRSTRLEN];
7533 char buf1[BUFSIZ];
d62a17ae 7534 char buf2[EVPN_ROUTE_STRLEN];
d62a17ae 7535 struct attr *attr;
7536 int sockunion_vty_out(struct vty *, union sockunion *);
7537 time_t tbuf;
7538 json_object *json_bestpath = NULL;
7539 json_object *json_cluster_list = NULL;
7540 json_object *json_cluster_list_list = NULL;
7541 json_object *json_ext_community = NULL;
7542 json_object *json_last_update = NULL;
7fd077aa 7543 json_object *json_pmsi = NULL;
d62a17ae 7544 json_object *json_nexthop_global = NULL;
7545 json_object *json_nexthop_ll = NULL;
7546 json_object *json_nexthops = NULL;
7547 json_object *json_path = NULL;
7548 json_object *json_peer = NULL;
7549 json_object *json_string = NULL;
7550 json_object *json_adv_to = NULL;
7551 int first = 0;
7552 struct listnode *node, *nnode;
7553 struct peer *peer;
7554 int addpath_capable;
7555 int has_adj;
7556 unsigned int first_as;
1defdda8 7557 bool nexthop_self =
9b6d8fcf 7558 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 7559 int i;
d62a17ae 7560
7561 if (json_paths) {
7562 json_path = json_object_new_object();
7563 json_peer = json_object_new_object();
7564 json_nexthop_global = json_object_new_object();
7565 }
7566
d62a17ae 7567 if (!json_paths && safi == SAFI_EVPN) {
b57ba6d2 7568 char tag_buf[30];
d62a17ae 7569
7570 bgp_evpn_route2str((struct prefix_evpn *)p, buf2, sizeof(buf2));
7571 vty_out(vty, " Route %s", buf2);
7572 tag_buf[0] = '\0';
9b6d8fcf
DS
7573 if (path->extra && path->extra->num_labels) {
7574 bgp_evpn_label2str(path->extra->label,
7575 path->extra->num_labels, tag_buf,
a4d82a8a 7576 sizeof(tag_buf));
d62a17ae 7577 vty_out(vty, " VNI %s", tag_buf);
7578 }
7579 vty_out(vty, "\n");
9b6d8fcf 7580 if (path->extra && path->extra->parent) {
4b7e6066 7581 struct bgp_path_info *parent_ri;
d62a17ae 7582 struct bgp_node *rn, *prn;
7583
9b6d8fcf 7584 parent_ri = (struct bgp_path_info *)path->extra->parent;
d62a17ae 7585 rn = parent_ri->net;
7586 if (rn && rn->prn) {
7587 prn = rn->prn;
7588 vty_out(vty, " Imported from %s:%s\n",
7589 prefix_rd2str(
7590 (struct prefix_rd *)&prn->p,
06b9f471 7591 buf1, sizeof(buf1)),
d62a17ae 7592 buf2);
7593 }
7594 }
7595 }
d62a17ae 7596
9b6d8fcf 7597 attr = path->attr;
d62a17ae 7598
7599 if (attr) {
7600 /* Line1 display AS-path, Aggregator */
7601 if (attr->aspath) {
7602 if (json_paths) {
68e1a55b
DS
7603 if (!attr->aspath->json)
7604 aspath_str_update(attr->aspath, true);
d62a17ae 7605 json_object_lock(attr->aspath->json);
7606 json_object_object_add(json_path, "aspath",
7607 attr->aspath->json);
7608 } else {
7609 if (attr->aspath->segments)
7610 aspath_print_vty(vty, " %s",
7611 attr->aspath, "");
7612 else
7613 vty_out(vty, " Local");
7614 }
7615 }
7616
9b6d8fcf 7617 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
d62a17ae 7618 if (json_paths)
7619 json_object_boolean_true_add(json_path,
7620 "removed");
7621 else
7622 vty_out(vty, ", (removed)");
7623 }
7624
9b6d8fcf 7625 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
d62a17ae 7626 if (json_paths)
7627 json_object_boolean_true_add(json_path,
7628 "stale");
7629 else
7630 vty_out(vty, ", (stale)");
7631 }
7632
7633 if (CHECK_FLAG(attr->flag,
7634 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
7635 if (json_paths) {
7636 json_object_int_add(json_path, "aggregatorAs",
7637 attr->aggregator_as);
7638 json_object_string_add(
7639 json_path, "aggregatorId",
7640 inet_ntoa(attr->aggregator_addr));
7641 } else {
7642 vty_out(vty, ", (aggregated by %u %s)",
7643 attr->aggregator_as,
7644 inet_ntoa(attr->aggregator_addr));
7645 }
7646 }
7647
9b6d8fcf 7648 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
d62a17ae 7649 PEER_FLAG_REFLECTOR_CLIENT)) {
7650 if (json_paths)
7651 json_object_boolean_true_add(
7652 json_path, "rxedFromRrClient");
7653 else
7654 vty_out(vty, ", (Received from a RR-client)");
7655 }
7656
9b6d8fcf 7657 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
d62a17ae 7658 PEER_FLAG_RSERVER_CLIENT)) {
7659 if (json_paths)
7660 json_object_boolean_true_add(
7661 json_path, "rxedFromRsClient");
7662 else
7663 vty_out(vty, ", (Received from a RS-client)");
7664 }
7665
9b6d8fcf 7666 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 7667 if (json_paths)
7668 json_object_boolean_true_add(
7669 json_path, "dampeningHistoryEntry");
7670 else
7671 vty_out(vty, ", (history entry)");
9b6d8fcf 7672 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
d62a17ae 7673 if (json_paths)
7674 json_object_boolean_true_add(
7675 json_path, "dampeningSuppressed");
7676 else
7677 vty_out(vty, ", (suppressed due to dampening)");
7678 }
7679
7680 if (!json_paths)
7681 vty_out(vty, "\n");
7682
7683 /* Line2 display Next-hop, Neighbor, Router-id */
7684 /* Display the nexthop */
a4d82a8a
PZ
7685 if ((p->family == AF_INET || p->family == AF_ETHERNET
7686 || p->family == AF_EVPN)
d62a17ae 7687 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7688 || safi == SAFI_EVPN
7689 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7690 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7691 || safi == SAFI_EVPN) {
7692 if (json_paths)
7693 json_object_string_add(
7694 json_nexthop_global, "ip",
7695 inet_ntoa(
7696 attr->mp_nexthop_global_in));
7697 else
7698 vty_out(vty, " %s",
7699 inet_ntoa(
7700 attr->mp_nexthop_global_in));
7701 } else {
7702 if (json_paths)
7703 json_object_string_add(
7704 json_nexthop_global, "ip",
7705 inet_ntoa(attr->nexthop));
7706 else
7707 vty_out(vty, " %s",
7708 inet_ntoa(attr->nexthop));
7709 }
7710
7711 if (json_paths)
7712 json_object_string_add(json_nexthop_global,
7713 "afi", "ipv4");
7714 } else {
7715 if (json_paths) {
7716 json_object_string_add(
7717 json_nexthop_global, "ip",
7718 inet_ntop(AF_INET6,
7719 &attr->mp_nexthop_global, buf,
7720 INET6_ADDRSTRLEN));
7721 json_object_string_add(json_nexthop_global,
7722 "afi", "ipv6");
7723 json_object_string_add(json_nexthop_global,
7724 "scope", "global");
7725 } else {
7726 vty_out(vty, " %s",
7727 inet_ntop(AF_INET6,
7728 &attr->mp_nexthop_global, buf,
7729 INET6_ADDRSTRLEN));
7730 }
7731 }
7732
7733 /* Display the IGP cost or 'inaccessible' */
9b6d8fcf 7734 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
d62a17ae 7735 if (json_paths)
7736 json_object_boolean_false_add(
7737 json_nexthop_global, "accessible");
7738 else
7739 vty_out(vty, " (inaccessible)");
7740 } else {
9b6d8fcf 7741 if (path->extra && path->extra->igpmetric) {
d62a17ae 7742 if (json_paths)
7743 json_object_int_add(
7744 json_nexthop_global, "metric",
9b6d8fcf 7745 path->extra->igpmetric);
d62a17ae 7746 else
7747 vty_out(vty, " (metric %u)",
9b6d8fcf 7748 path->extra->igpmetric);
d62a17ae 7749 }
7750
7751 /* IGP cost is 0, display this only for json */
7752 else {
7753 if (json_paths)
7754 json_object_int_add(json_nexthop_global,
7755 "metric", 0);
7756 }
7757
7758 if (json_paths)
7759 json_object_boolean_true_add(
7760 json_nexthop_global, "accessible");
7761 }
7762
7763 /* Display peer "from" output */
7764 /* This path was originated locally */
9b6d8fcf 7765 if (path->peer == bgp->peer_self) {
d62a17ae 7766
7767 if (safi == SAFI_EVPN
7768 || (p->family == AF_INET
7769 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7770 if (json_paths)
7771 json_object_string_add(
7772 json_peer, "peerId", "0.0.0.0");
7773 else
7774 vty_out(vty, " from 0.0.0.0 ");
7775 } else {
7776 if (json_paths)
7777 json_object_string_add(json_peer,
7778 "peerId", "::");
7779 else
7780 vty_out(vty, " from :: ");
7781 }
7782
7783 if (json_paths)
7784 json_object_string_add(
7785 json_peer, "routerId",
7786 inet_ntoa(bgp->router_id));
7787 else
7788 vty_out(vty, "(%s)", inet_ntoa(bgp->router_id));
7789 }
7790
7791 /* We RXed this path from one of our peers */
7792 else {
7793
7794 if (json_paths) {
7795 json_object_string_add(
7796 json_peer, "peerId",
9b6d8fcf 7797 sockunion2str(&path->peer->su, buf,
d62a17ae 7798 SU_ADDRSTRLEN));
7799 json_object_string_add(
7800 json_peer, "routerId",
7801 inet_ntop(AF_INET,
9b6d8fcf 7802 &path->peer->remote_id, buf1,
06b9f471 7803 sizeof(buf1)));
d62a17ae 7804
9b6d8fcf 7805 if (path->peer->hostname)
d62a17ae 7806 json_object_string_add(
7807 json_peer, "hostname",
9b6d8fcf 7808 path->peer->hostname);
d62a17ae 7809
9b6d8fcf 7810 if (path->peer->domainname)
d62a17ae 7811 json_object_string_add(
7812 json_peer, "domainname",
9b6d8fcf 7813 path->peer->domainname);
d62a17ae 7814
9b6d8fcf 7815 if (path->peer->conf_if)
d62a17ae 7816 json_object_string_add(
7817 json_peer, "interface",
9b6d8fcf 7818 path->peer->conf_if);
d62a17ae 7819 } else {
9b6d8fcf
DS
7820 if (path->peer->conf_if) {
7821 if (path->peer->hostname
d62a17ae 7822 && bgp_flag_check(
9b6d8fcf 7823 path->peer->bgp,
d62a17ae 7824 BGP_FLAG_SHOW_HOSTNAME))
7825 vty_out(vty, " from %s(%s)",
9b6d8fcf
DS
7826 path->peer->hostname,
7827 path->peer->conf_if);
d62a17ae 7828 else
7829 vty_out(vty, " from %s",
9b6d8fcf 7830 path->peer->conf_if);
d62a17ae 7831 } else {
9b6d8fcf 7832 if (path->peer->hostname
d62a17ae 7833 && bgp_flag_check(
9b6d8fcf 7834 path->peer->bgp,
d62a17ae 7835 BGP_FLAG_SHOW_HOSTNAME))
7836 vty_out(vty, " from %s(%s)",
9b6d8fcf
DS
7837 path->peer->hostname,
7838 path->peer->host);
d62a17ae 7839 else
7840 vty_out(vty, " from %s",
7841 sockunion2str(
9b6d8fcf 7842 &path->peer->su,
d62a17ae 7843 buf,
7844 SU_ADDRSTRLEN));
7845 }
7846
7847 if (attr->flag
7848 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
7849 vty_out(vty, " (%s)",
7850 inet_ntoa(attr->originator_id));
7851 else
7852 vty_out(vty, " (%s)",
7853 inet_ntop(
7854 AF_INET,
9b6d8fcf 7855 &path->peer->remote_id,
06b9f471 7856 buf1, sizeof(buf1)));
d62a17ae 7857 }
7858 }
7859
9df8b37c
PZ
7860 /*
7861 * Note when vrfid of nexthop is different from that of prefix
7862 */
9b6d8fcf
DS
7863 if (path->extra && path->extra->bgp_orig) {
7864 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c
PZ
7865
7866 if (json_paths) {
7867 const char *vn;
7868
9b6d8fcf
DS
7869 if (path->extra->bgp_orig->inst_type
7870 == BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 7871
03a6facf 7872 vn = VRF_DEFAULT_NAME;
9df8b37c 7873 else
9b6d8fcf 7874 vn = path->extra->bgp_orig->name;
9df8b37c
PZ
7875
7876 json_object_string_add(json_path, "nhVrfName",
7877 vn);
7878
7879 if (nexthop_vrfid == VRF_UNKNOWN) {
7880 json_object_int_add(json_path,
7881 "nhVrfId", -1);
7882 } else {
7883 json_object_int_add(json_path,
7884 "nhVrfId", (int)nexthop_vrfid);
7885 }
7886 } else {
7887 if (nexthop_vrfid == VRF_UNKNOWN)
7888 vty_out(vty, " vrf ?");
7889 else
7890 vty_out(vty, " vrf %u", nexthop_vrfid);
7891 }
7892 }
7893
7894 if (nexthop_self) {
7895 if (json_paths) {
7896 json_object_boolean_true_add(json_path,
7897 "announceNexthopSelf");
7898 } else {
7899 vty_out(vty, " announce-nh-self");
7900 }
7901 }
7902
d62a17ae 7903 if (!json_paths)
7904 vty_out(vty, "\n");
7905
7906 /* display the link-local nexthop */
7907 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
7908 if (json_paths) {
7909 json_nexthop_ll = json_object_new_object();
7910 json_object_string_add(
7911 json_nexthop_ll, "ip",
7912 inet_ntop(AF_INET6,
7913 &attr->mp_nexthop_local, buf,
7914 INET6_ADDRSTRLEN));
7915 json_object_string_add(json_nexthop_ll, "afi",
7916 "ipv6");
7917 json_object_string_add(json_nexthop_ll, "scope",
7918 "link-local");
7919
7920 json_object_boolean_true_add(json_nexthop_ll,
7921 "accessible");
7922
7923 if (!attr->mp_nexthop_prefer_global)
7924 json_object_boolean_true_add(
7925 json_nexthop_ll, "used");
7926 else
7927 json_object_boolean_true_add(
7928 json_nexthop_global, "used");
7929 } else {
7930 vty_out(vty, " (%s) %s\n",
7931 inet_ntop(AF_INET6,
7932 &attr->mp_nexthop_local, buf,
7933 INET6_ADDRSTRLEN),
7934 attr->mp_nexthop_prefer_global
7935 ? "(prefer-global)"
7936 : "(used)");
7937 }
7938 }
7939 /* If we do not have a link-local nexthop then we must flag the
7940 global as "used" */
7941 else {
7942 if (json_paths)
7943 json_object_boolean_true_add(
7944 json_nexthop_global, "used");
7945 }
718e3744 7946
d62a17ae 7947 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7948 * Int/Ext/Local, Atomic, best */
7949 if (json_paths)
7950 json_object_string_add(
7951 json_path, "origin",
7952 bgp_origin_long_str[attr->origin]);
7953 else
7954 vty_out(vty, " Origin %s",
7955 bgp_origin_long_str[attr->origin]);
7956
7957 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
50e05855
AD
7958 if (json_paths) {
7959
7960 /*
7961 * Adding "metric" field to match with
7962 * corresponding CLI. "med" will be
7963 * deprecated in future.
7964 */
d62a17ae 7965 json_object_int_add(json_path, "med",
7966 attr->med);
50e05855
AD
7967 json_object_int_add(json_path, "metric",
7968 attr->med);
7969 } else
d62a17ae 7970 vty_out(vty, ", metric %u", attr->med);
7971 }
718e3744 7972
d62a17ae 7973 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
7974 if (json_paths)
7975 json_object_int_add(json_path, "localpref",
7976 attr->local_pref);
7977 else
7978 vty_out(vty, ", localpref %u",
7979 attr->local_pref);
d62a17ae 7980 }
718e3744 7981
d62a17ae 7982 if (attr->weight != 0) {
7983 if (json_paths)
7984 json_object_int_add(json_path, "weight",
7985 attr->weight);
7986 else
7987 vty_out(vty, ", weight %u", attr->weight);
7988 }
718e3744 7989
d62a17ae 7990 if (attr->tag != 0) {
7991 if (json_paths)
7992 json_object_int_add(json_path, "tag",
7993 attr->tag);
7994 else
7995 vty_out(vty, ", tag %" ROUTE_TAG_PRI,
7996 attr->tag);
7997 }
718e3744 7998
9b6d8fcf 7999 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
d62a17ae 8000 if (json_paths)
8001 json_object_boolean_false_add(json_path,
8002 "valid");
8003 else
8004 vty_out(vty, ", invalid");
9b6d8fcf 8005 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 8006 if (json_paths)
8007 json_object_boolean_true_add(json_path,
8008 "valid");
8009 else
8010 vty_out(vty, ", valid");
8011 }
718e3744 8012
9b6d8fcf
DS
8013 if (path->peer != bgp->peer_self) {
8014 if (path->peer->as == path->peer->local_as) {
d62a17ae 8015 if (CHECK_FLAG(bgp->config,
8016 BGP_CONFIG_CONFEDERATION)) {
8017 if (json_paths)
8018 json_object_string_add(
8019 json_peer, "type",
8020 "confed-internal");
8021 else
8022 vty_out(vty,
8023 ", confed-internal");
8024 } else {
8025 if (json_paths)
8026 json_object_string_add(
8027 json_peer, "type",
8028 "internal");
8029 else
8030 vty_out(vty, ", internal");
8031 }
8032 } else {
8033 if (bgp_confederation_peers_check(
9b6d8fcf 8034 bgp, path->peer->as)) {
d62a17ae 8035 if (json_paths)
8036 json_object_string_add(
8037 json_peer, "type",
8038 "confed-external");
8039 else
8040 vty_out(vty,
8041 ", confed-external");
8042 } else {
8043 if (json_paths)
8044 json_object_string_add(
8045 json_peer, "type",
8046 "external");
8047 else
8048 vty_out(vty, ", external");
8049 }
8050 }
9b6d8fcf 8051 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
d62a17ae 8052 if (json_paths) {
8053 json_object_boolean_true_add(json_path,
8054 "aggregated");
8055 json_object_boolean_true_add(json_path,
8056 "local");
8057 } else {
8058 vty_out(vty, ", aggregated, local");
8059 }
9b6d8fcf 8060 } else if (path->type != ZEBRA_ROUTE_BGP) {
d62a17ae 8061 if (json_paths)
8062 json_object_boolean_true_add(json_path,
8063 "sourced");
8064 else
8065 vty_out(vty, ", sourced");
8066 } else {
8067 if (json_paths) {
8068 json_object_boolean_true_add(json_path,
8069 "sourced");
8070 json_object_boolean_true_add(json_path,
8071 "local");
8072 } else {
8073 vty_out(vty, ", sourced, local");
8074 }
8075 }
718e3744 8076
d62a17ae 8077 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
8078 if (json_paths)
8079 json_object_boolean_true_add(json_path,
8080 "atomicAggregate");
8081 else
8082 vty_out(vty, ", atomic-aggregate");
8083 }
718e3744 8084
9b6d8fcf
DS
8085 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
8086 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
8087 && bgp_path_info_mpath_count(path))) {
d62a17ae 8088 if (json_paths)
8089 json_object_boolean_true_add(json_path,
8090 "multipath");
8091 else
8092 vty_out(vty, ", multipath");
8093 }
856ca177 8094
d62a17ae 8095 // Mark the bestpath(s)
9b6d8fcf 8096 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
d62a17ae 8097 first_as = aspath_get_first_as(attr->aspath);
8098
8099 if (json_paths) {
8100 if (!json_bestpath)
8101 json_bestpath =
8102 json_object_new_object();
8103 json_object_int_add(json_bestpath,
8104 "bestpathFromAs", first_as);
8105 } else {
8106 if (first_as)
fb2b0934 8107 vty_out(vty, ", bestpath-from-AS %u",
d62a17ae 8108 first_as);
8109 else
8110 vty_out(vty,
8111 ", bestpath-from-AS Local");
8112 }
8113 }
718e3744 8114
9b6d8fcf 8115 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8116 if (json_paths) {
8117 if (!json_bestpath)
8118 json_bestpath =
8119 json_object_new_object();
8120 json_object_boolean_true_add(json_bestpath,
8121 "overall");
8122 } else
8123 vty_out(vty, ", best");
8124 }
718e3744 8125
d62a17ae 8126 if (json_bestpath)
8127 json_object_object_add(json_path, "bestpath",
8128 json_bestpath);
8129
8130 if (!json_paths)
8131 vty_out(vty, "\n");
8132
8133 /* Line 4 display Community */
8134 if (attr->community) {
8135 if (json_paths) {
a69ea8ae 8136 if (!attr->community->json)
a4d82a8a 8137 community_str(attr->community, true);
d62a17ae 8138 json_object_lock(attr->community->json);
8139 json_object_object_add(json_path, "community",
8140 attr->community->json);
8141 } else {
8142 vty_out(vty, " Community: %s\n",
8143 attr->community->str);
8144 }
8145 }
718e3744 8146
d62a17ae 8147 /* Line 5 display Extended-community */
8148 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8149 if (json_paths) {
8150 json_ext_community = json_object_new_object();
8151 json_object_string_add(json_ext_community,
8152 "string",
8153 attr->ecommunity->str);
8154 json_object_object_add(json_path,
8155 "extendedCommunity",
8156 json_ext_community);
8157 } else {
8158 vty_out(vty, " Extended Community: %s\n",
8159 attr->ecommunity->str);
8160 }
8161 }
adbac85e 8162
d62a17ae 8163 /* Line 6 display Large community */
b96879c0
DS
8164 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
8165 if (json_paths) {
8d9b8ed9
PM
8166 if (!attr->lcommunity->json)
8167 lcommunity_str(attr->lcommunity, true);
8168 json_object_lock(attr->lcommunity->json);
b96879c0
DS
8169 json_object_object_add(json_path,
8170 "largeCommunity",
8d9b8ed9 8171 attr->lcommunity->json);
b96879c0
DS
8172 } else {
8173 vty_out(vty, " Large Community: %s\n",
8174 attr->lcommunity->str);
8175 }
8176 }
d62a17ae 8177
8178 /* Line 7 display Originator, Cluster-id */
8179 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
8180 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
8181 if (attr->flag
8182 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
8183 if (json_paths)
8184 json_object_string_add(
8185 json_path, "originatorId",
8186 inet_ntoa(attr->originator_id));
8187 else
8188 vty_out(vty, " Originator: %s",
8189 inet_ntoa(attr->originator_id));
8190 }
8191
8192 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
8193 int i;
8194
8195 if (json_paths) {
8196 json_cluster_list =
8197 json_object_new_object();
8198 json_cluster_list_list =
8199 json_object_new_array();
8200
8201 for (i = 0;
8202 i < attr->cluster->length / 4;
8203 i++) {
8204 json_string = json_object_new_string(
8205 inet_ntoa(
8206 attr->cluster->list
8207 [i]));
8208 json_object_array_add(
8209 json_cluster_list_list,
8210 json_string);
8211 }
8212
8213 /* struct cluster_list does not have
8214 "str" variable like
8215 * aspath and community do. Add this
8216 someday if someone
8217 * asks for it.
8218 json_object_string_add(json_cluster_list,
8219 "string", attr->cluster->str);
8220 */
8221 json_object_object_add(
8222 json_cluster_list, "list",
8223 json_cluster_list_list);
8224 json_object_object_add(
8225 json_path, "clusterList",
8226 json_cluster_list);
8227 } else {
8228 vty_out(vty, ", Cluster list: ");
8229
8230 for (i = 0;
8231 i < attr->cluster->length / 4;
8232 i++) {
8233 vty_out(vty, "%s ",
8234 inet_ntoa(
8235 attr->cluster->list
8236 [i]));
8237 }
8238 }
8239 }
8240
8241 if (!json_paths)
8242 vty_out(vty, "\n");
8243 }
adbac85e 8244
9b6d8fcf
DS
8245 if (path->extra && path->extra->damp_info)
8246 bgp_damp_info_vty(vty, path, json_path);
d62a17ae 8247
6a527b2f 8248 /* Remote Label */
9b6d8fcf 8249 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
6a527b2f 8250 && safi != SAFI_EVPN) {
9b6d8fcf 8251 mpls_label_t label = label_pton(&path->extra->label[0]);
121e245d 8252
d62a17ae 8253 if (json_paths)
8254 json_object_int_add(json_path, "remoteLabel",
8255 label);
8256 else
8257 vty_out(vty, " Remote label: %d\n", label);
8258 }
b05a1c8b 8259
d62a17ae 8260 /* Label Index */
8261 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
8262 if (json_paths)
8263 json_object_int_add(json_path, "labelIndex",
8264 attr->label_index);
8265 else
8266 vty_out(vty, " Label Index: %d\n",
8267 attr->label_index);
8268 }
520d5d76 8269
d62a17ae 8270 /* Line 8 display Addpath IDs */
dcc68b5e
MS
8271 if (path->addpath_rx_id
8272 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
d62a17ae 8273 if (json_paths) {
8274 json_object_int_add(json_path, "addpathRxId",
9b6d8fcf 8275 path->addpath_rx_id);
dcc68b5e
MS
8276
8277 /* Keep backwards compatibility with the old API
8278 * by putting TX All's ID in the old field
8279 */
8280 json_object_int_add(
8281 json_path, "addpathTxId",
8282 path->tx_addpath.addpath_tx_id
8283 [BGP_ADDPATH_ALL]);
8284
8285 /* ... but create a specific field for each
8286 * strategy
8287 */
8288 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
8289 json_object_int_add(
8290 json_path,
8291 bgp_addpath_names(i)
8292 ->id_json_name,
8293 path->tx_addpath
8294 .addpath_tx_id[i]);
8295 }
d62a17ae 8296 } else {
dcc68b5e
MS
8297 vty_out(vty, " AddPath ID: RX %u, ",
8298 path->addpath_rx_id);
8299
8300 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 8301 }
8302 }
718e3744 8303
d62a17ae 8304 /* If we used addpath to TX a non-bestpath we need to display
dcc68b5e
MS
8305 * "Advertised to" on a path-by-path basis
8306 */
8307 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 8308 first = 1;
8309
8310 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
8311 addpath_capable =
8312 bgp_addpath_encode_tx(peer, afi, safi);
8313 has_adj = bgp_adj_out_lookup(
dcc68b5e
MS
8314 peer, path->net,
8315 bgp_addpath_id_for_peer(
8316 peer, afi, safi,
8317 &path->tx_addpath));
d62a17ae 8318
8319 if ((addpath_capable && has_adj)
8320 || (!addpath_capable && has_adj
9b6d8fcf 8321 && CHECK_FLAG(path->flags,
1defdda8 8322 BGP_PATH_SELECTED))) {
d62a17ae 8323 if (json_path && !json_adv_to)
8324 json_adv_to =
8325 json_object_new_object();
8326
8327 route_vty_out_advertised_to(
8328 vty, peer, &first,
8329 " Advertised to:",
8330 json_adv_to);
8331 }
8332 }
8333
8334 if (json_path) {
8335 if (json_adv_to) {
8336 json_object_object_add(json_path,
8337 "advertisedTo",
8338 json_adv_to);
8339 }
8340 } else {
8341 if (!first) {
8342 vty_out(vty, "\n");
8343 }
8344 }
8345 }
b05a1c8b 8346
d62a17ae 8347 /* Line 9 display Uptime */
9b6d8fcf 8348 tbuf = time(NULL) - (bgp_clock() - path->uptime);
d62a17ae 8349 if (json_paths) {
8350 json_last_update = json_object_new_object();
8351 json_object_int_add(json_last_update, "epoch", tbuf);
8352 json_object_string_add(json_last_update, "string",
8353 ctime(&tbuf));
8354 json_object_object_add(json_path, "lastUpdate",
8355 json_last_update);
8356 } else
8357 vty_out(vty, " Last update: %s", ctime(&tbuf));
7fd077aa 8358
8359 /* Line 10 display PMSI tunnel attribute, if present */
8360 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
b7d08f5a 8361 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
8362 attr->pmsi_tnl_type,
8363 PMSI_TNLTYPE_STR_DEFAULT);
8364
7fd077aa 8365 if (json_paths) {
8366 json_pmsi = json_object_new_object();
b7d08f5a 8367 json_object_string_add(json_pmsi,
8368 "tunnelType", str);
7fd077aa 8369 json_object_object_add(json_path, "pmsi",
8370 json_pmsi);
8371 } else
8372 vty_out(vty, " PMSI Tunnel Type: %s\n",
b7d08f5a 8373 str);
7fd077aa 8374 }
8375
d62a17ae 8376 }
f1aa5d8a 8377
d62a17ae 8378 /* We've constructed the json object for this path, add it to the json
8379 * array of paths
8380 */
8381 if (json_paths) {
8382 if (json_nexthop_global || json_nexthop_ll) {
8383 json_nexthops = json_object_new_array();
f1aa5d8a 8384
d62a17ae 8385 if (json_nexthop_global)
8386 json_object_array_add(json_nexthops,
8387 json_nexthop_global);
f1aa5d8a 8388
d62a17ae 8389 if (json_nexthop_ll)
8390 json_object_array_add(json_nexthops,
8391 json_nexthop_ll);
f1aa5d8a 8392
d62a17ae 8393 json_object_object_add(json_path, "nexthops",
8394 json_nexthops);
8395 }
8396
8397 json_object_object_add(json_path, "peer", json_peer);
8398 json_object_array_add(json_paths, json_path);
8399 } else
8400 vty_out(vty, "\n");
b366b518
BB
8401}
8402
96ade3ed 8403#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
8404#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8405#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 8406
d62a17ae 8407static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
8408 const char *prefix_list_str, afi_t afi,
8409 safi_t safi, enum bgp_show_type type);
8410static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
8411 const char *filter, afi_t afi, safi_t safi,
8412 enum bgp_show_type type);
8413static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
8414 const char *rmap_str, afi_t afi, safi_t safi,
8415 enum bgp_show_type type);
8416static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
8417 const char *com, int exact, afi_t afi,
8418 safi_t safi);
8419static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
8420 const char *prefix, afi_t afi, safi_t safi,
8421 enum bgp_show_type type);
a4d82a8a
PZ
8422static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
8423 afi_t afi, safi_t safi, enum bgp_show_type type);
7f323236
DW
8424static int bgp_show_community(struct vty *vty, struct bgp *bgp,
8425 const char *comstr, int exact, afi_t afi,
9f049418 8426 safi_t safi, bool use_json);
d62a17ae 8427
1ae44dfc
LB
8428
8429static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 8430 struct bgp_table *table, enum bgp_show_type type,
9f049418 8431 void *output_arg, bool use_json, char *rd,
a4d82a8a
PZ
8432 int is_last, unsigned long *output_cum,
8433 unsigned long *total_cum,
9386b588 8434 unsigned long *json_header_depth)
d62a17ae 8435{
40381db7 8436 struct bgp_path_info *pi;
d62a17ae 8437 struct bgp_node *rn;
8438 int header = 1;
8439 int display;
1ae44dfc
LB
8440 unsigned long output_count = 0;
8441 unsigned long total_count = 0;
d62a17ae 8442 struct prefix *p;
d62a17ae 8443 char buf2[BUFSIZ];
8444 json_object *json_paths = NULL;
8445 int first = 1;
8446
1ae44dfc
LB
8447 if (output_cum && *output_cum != 0)
8448 header = 0;
8449
9386b588 8450 if (use_json && !*json_header_depth) {
d62a17ae 8451 vty_out(vty,
66f80d74 8452 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
01eced22
AD
8453 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
8454 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 8455 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b
DS
8456 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
8457 ? VRF_DEFAULT_NAME
8458 : bgp->name,
01eced22
AD
8459 table->version, inet_ntoa(bgp->router_id),
8460 bgp->default_local_pref, bgp->as);
9386b588
PZ
8461 *json_header_depth = 2;
8462 if (rd) {
445c2480 8463 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
8464 ++*json_header_depth;
8465 }
d62a17ae 8466 }
718e3744 8467
445c2480
DS
8468 if (use_json && rd) {
8469 vty_out(vty, " \"%s\" : { ", rd);
8470 }
8471
d62a17ae 8472 /* Start processing of routes. */
98ce9a06 8473 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685
DS
8474 pi = bgp_node_get_bgp_path_info(rn);
8475 if (pi == NULL)
98ce9a06 8476 continue;
d62a17ae 8477
98ce9a06 8478 display = 0;
98ce9a06
DS
8479 if (use_json)
8480 json_paths = json_object_new_array();
8481 else
8482 json_paths = NULL;
d62a17ae 8483
6f94b685 8484 for (; pi; pi = pi->next) {
98ce9a06
DS
8485 total_count++;
8486 if (type == bgp_show_type_flap_statistics
8487 || type == bgp_show_type_flap_neighbor
8488 || type == bgp_show_type_dampend_paths
8489 || type == bgp_show_type_damp_neighbor) {
40381db7 8490 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
8491 continue;
8492 }
8493 if (type == bgp_show_type_regexp) {
8494 regex_t *regex = output_arg;
d62a17ae 8495
40381db7 8496 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
8497 == REG_NOMATCH)
8498 continue;
8499 }
8500 if (type == bgp_show_type_prefix_list) {
8501 struct prefix_list *plist = output_arg;
d62a17ae 8502
98ce9a06
DS
8503 if (prefix_list_apply(plist, &rn->p)
8504 != PREFIX_PERMIT)
8505 continue;
8506 }
8507 if (type == bgp_show_type_filter_list) {
8508 struct as_list *as_list = output_arg;
d62a17ae 8509
40381db7 8510 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
8511 != AS_FILTER_PERMIT)
8512 continue;
8513 }
8514 if (type == bgp_show_type_route_map) {
8515 struct route_map *rmap = output_arg;
9b6d8fcf 8516 struct bgp_path_info path;
98ce9a06
DS
8517 struct attr dummy_attr;
8518 int ret;
d62a17ae 8519
40381db7 8520 bgp_attr_dup(&dummy_attr, pi->attr);
d62a17ae 8521
40381db7 8522 path.peer = pi->peer;
9b6d8fcf 8523 path.attr = &dummy_attr;
d62a17ae 8524
a4d82a8a 8525 ret = route_map_apply(rmap, &rn->p, RMAP_BGP,
9b6d8fcf 8526 &path);
98ce9a06
DS
8527 if (ret == RMAP_DENYMATCH)
8528 continue;
8529 }
8530 if (type == bgp_show_type_neighbor
8531 || type == bgp_show_type_flap_neighbor
8532 || type == bgp_show_type_damp_neighbor) {
8533 union sockunion *su = output_arg;
8534
40381db7
DS
8535 if (pi->peer == NULL
8536 || pi->peer->su_remote == NULL
8537 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
8538 continue;
8539 }
8540 if (type == bgp_show_type_cidr_only) {
d7c0a89a 8541 uint32_t destination;
d62a17ae 8542
98ce9a06
DS
8543 destination = ntohl(rn->p.u.prefix4.s_addr);
8544 if (IN_CLASSC(destination)
8545 && rn->p.prefixlen == 24)
8546 continue;
8547 if (IN_CLASSB(destination)
8548 && rn->p.prefixlen == 16)
8549 continue;
8550 if (IN_CLASSA(destination)
8551 && rn->p.prefixlen == 8)
8552 continue;
8553 }
8554 if (type == bgp_show_type_prefix_longer) {
f7813c7c 8555 p = output_arg;
98ce9a06
DS
8556 if (!prefix_match(p, &rn->p))
8557 continue;
8558 }
8559 if (type == bgp_show_type_community_all) {
40381db7 8560 if (!pi->attr->community)
98ce9a06
DS
8561 continue;
8562 }
8563 if (type == bgp_show_type_community) {
8564 struct community *com = output_arg;
d62a17ae 8565
40381db7
DS
8566 if (!pi->attr->community
8567 || !community_match(pi->attr->community,
98ce9a06
DS
8568 com))
8569 continue;
8570 }
8571 if (type == bgp_show_type_community_exact) {
8572 struct community *com = output_arg;
d62a17ae 8573
40381db7
DS
8574 if (!pi->attr->community
8575 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
8576 continue;
8577 }
8578 if (type == bgp_show_type_community_list) {
8579 struct community_list *list = output_arg;
d62a17ae 8580
40381db7 8581 if (!community_list_match(pi->attr->community,
a4d82a8a 8582 list))
98ce9a06
DS
8583 continue;
8584 }
a4d82a8a 8585 if (type == bgp_show_type_community_list_exact) {
98ce9a06 8586 struct community_list *list = output_arg;
d62a17ae 8587
98ce9a06 8588 if (!community_list_exact_match(
40381db7 8589 pi->attr->community, list))
98ce9a06
DS
8590 continue;
8591 }
8592 if (type == bgp_show_type_lcommunity) {
8593 struct lcommunity *lcom = output_arg;
d62a17ae 8594
40381db7
DS
8595 if (!pi->attr->lcommunity
8596 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
8597 lcom))
8598 continue;
8599 }
8600 if (type == bgp_show_type_lcommunity_list) {
8601 struct community_list *list = output_arg;
d62a17ae 8602
40381db7 8603 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 8604 list))
98ce9a06
DS
8605 continue;
8606 }
8607 if (type == bgp_show_type_lcommunity_all) {
40381db7 8608 if (!pi->attr->lcommunity)
98ce9a06
DS
8609 continue;
8610 }
8611 if (type == bgp_show_type_dampend_paths
8612 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
8613 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
8614 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
8615 continue;
8616 }
8617
8618 if (!use_json && header) {
996c9314 8619 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 8620 ", local router ID is %s, vrf id ",
98ce9a06
DS
8621 table->version,
8622 inet_ntoa(bgp->router_id));
9df8b37c
PZ
8623 if (bgp->vrf_id == VRF_UNKNOWN)
8624 vty_out(vty, "%s", VRFID_NONE_STR);
8625 else
8626 vty_out(vty, "%u", bgp->vrf_id);
8627 vty_out(vty, "\n");
01eced22
AD
8628 vty_out(vty, "Default local pref %u, ",
8629 bgp->default_local_pref);
8630 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 8631 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 8632 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 8633 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 8634 if (type == bgp_show_type_dampend_paths
8635 || type == bgp_show_type_damp_neighbor)
98ce9a06 8636 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
8637 else if (type == bgp_show_type_flap_statistics
8638 || type == bgp_show_type_flap_neighbor)
98ce9a06 8639 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 8640 else
98ce9a06
DS
8641 vty_out(vty, BGP_SHOW_HEADER);
8642 header = 0;
d62a17ae 8643 }
98ce9a06
DS
8644 if (rd != NULL && !display && !output_count) {
8645 if (!use_json)
8646 vty_out(vty,
8647 "Route Distinguisher: %s\n",
8648 rd);
d62a17ae 8649 }
98ce9a06
DS
8650 if (type == bgp_show_type_dampend_paths
8651 || type == bgp_show_type_damp_neighbor)
40381db7 8652 damp_route_vty_out(vty, &rn->p, pi, display,
a4d82a8a 8653 safi, use_json, json_paths);
98ce9a06
DS
8654 else if (type == bgp_show_type_flap_statistics
8655 || type == bgp_show_type_flap_neighbor)
40381db7 8656 flap_route_vty_out(vty, &rn->p, pi, display,
a4d82a8a 8657 safi, use_json, json_paths);
98ce9a06 8658 else
40381db7 8659 route_vty_out(vty, &rn->p, pi, display, safi,
a4d82a8a 8660 json_paths);
98ce9a06 8661 display++;
d62a17ae 8662 }
8663
98ce9a06
DS
8664 if (display) {
8665 output_count++;
8666 if (!use_json)
8667 continue;
8668
8669 p = &rn->p;
625d2931
PG
8670 /* encode prefix */
8671 if (p->family == AF_FLOWSPEC) {
8672 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
8673
8674 bgp_fs_nlri_get_string((unsigned char *)
8675 p->u.prefix_flowspec.ptr,
8676 p->u.prefix_flowspec
8677 .prefixlen,
8678 retstr,
8679 NLRI_STRING_FORMAT_MIN,
8680 NULL);
8681 if (first)
8682 vty_out(vty, "\"%s/%d\": ",
8683 retstr,
8684 p->u.prefix_flowspec.prefixlen);
8685 else
8686 vty_out(vty, ",\"%s/%d\": ",
8687 retstr,
8688 p->u.prefix_flowspec.prefixlen);
8689 } else {
8690 prefix2str(p, buf2, sizeof(buf2));
8691 if (first)
8692 vty_out(vty, "\"%s\": ", buf2);
8693 else
8694 vty_out(vty, ",\"%s\": ", buf2);
8695 }
98ce9a06 8696 vty_out(vty, "%s",
23b2a7ef 8697 json_object_to_json_string(json_paths));
98ce9a06 8698 json_object_free(json_paths);
449feb8e 8699 json_paths = NULL;
98ce9a06
DS
8700 first = 0;
8701 }
8702 }
8703
1ae44dfc
LB
8704 if (output_cum) {
8705 output_count += *output_cum;
8706 *output_cum = output_count;
8707 }
8708 if (total_cum) {
8709 total_count += *total_cum;
8710 *total_cum = total_count;
8711 }
d62a17ae 8712 if (use_json) {
9386b588 8713 if (rd) {
a4d82a8a 8714 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
8715 }
8716 if (is_last) {
a4d82a8a
PZ
8717 unsigned long i;
8718 for (i = 0; i < *json_header_depth; ++i)
8719 vty_out(vty, " } ");
9386b588 8720 }
d62a17ae 8721 } else {
1ae44dfc
LB
8722 if (is_last) {
8723 /* No route is displayed */
8724 if (output_count == 0) {
8725 if (type == bgp_show_type_normal)
8726 vty_out(vty,
8727 "No BGP prefixes displayed, %ld exist\n",
8728 total_count);
8729 } else
d62a17ae 8730 vty_out(vty,
1ae44dfc
LB
8731 "\nDisplayed %ld routes and %ld total paths\n",
8732 output_count, total_count);
8733 }
d62a17ae 8734 }
718e3744 8735
d62a17ae 8736 return CMD_SUCCESS;
718e3744 8737}
8738
1ae44dfc
LB
8739int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
8740 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 8741 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc
LB
8742{
8743 struct bgp_node *rn, *next;
8744 unsigned long output_cum = 0;
8745 unsigned long total_cum = 0;
9386b588 8746 unsigned long json_header_depth = 0;
67009e22 8747 struct bgp_table *itable;
0136788c
LB
8748 bool show_msg;
8749
8750 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc
LB
8751
8752 for (rn = bgp_table_top(table); rn; rn = next) {
8753 next = bgp_route_next(rn);
8754 if (prd_match && memcmp(rn->p.u.val, prd_match->val, 8) != 0)
8755 continue;
67009e22
DS
8756
8757 itable = bgp_node_get_bgp_table_info(rn);
8758 if (itable != NULL) {
1ae44dfc 8759 struct prefix_rd prd;
06b9f471 8760 char rd[RD_ADDRSTRLEN];
1ae44dfc
LB
8761
8762 memcpy(&prd, &(rn->p), sizeof(struct prefix_rd));
06b9f471 8763 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22
DS
8764 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
8765 use_json, rd, next == NULL, &output_cum,
8766 &total_cum, &json_header_depth);
0136788c
LB
8767 if (next == NULL)
8768 show_msg = false;
1ae44dfc
LB
8769 }
8770 }
0136788c
LB
8771 if (show_msg) {
8772 if (output_cum == 0)
8773 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
8774 total_cum);
8775 else
8776 vty_out(vty,
8777 "\nDisplayed %ld routes and %ld total paths\n",
8778 output_cum, total_cum);
8779 }
1ae44dfc
LB
8780 return CMD_SUCCESS;
8781}
d62a17ae 8782static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
9f049418 8783 enum bgp_show_type type, void *output_arg, bool use_json)
fee0f4c6 8784{
d62a17ae 8785 struct bgp_table *table;
9386b588 8786 unsigned long json_header_depth = 0;
fee0f4c6 8787
d62a17ae 8788 if (bgp == NULL) {
8789 bgp = bgp_get_default();
8790 }
fee0f4c6 8791
d62a17ae 8792 if (bgp == NULL) {
8793 if (!use_json)
8794 vty_out(vty, "No BGP process is configured\n");
16307668
RW
8795 else
8796 vty_out(vty, "{}\n");
d62a17ae 8797 return CMD_WARNING;
8798 }
4dd6177e 8799
1ae44dfc 8800 table = bgp->rib[afi][safi];
d62a17ae 8801 /* use MPLS and ENCAP specific shows until they are merged */
8802 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
8803 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
8804 output_arg, use_json);
d62a17ae 8805 }
dba3c1d3
PG
8806
8807 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
8808 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
8809 output_arg, use_json,
8810 1, NULL, NULL);
8811 }
d62a17ae 8812 /* labeled-unicast routes live in the unicast table */
8813 else if (safi == SAFI_LABELED_UNICAST)
8814 safi = SAFI_UNICAST;
fee0f4c6 8815
1ae44dfc 8816 return bgp_show_table(vty, bgp, safi, table, type, output_arg, use_json,
9386b588 8817 NULL, 1, NULL, NULL, &json_header_depth);
fee0f4c6 8818}
8819
d62a17ae 8820static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
9f049418 8821 safi_t safi, bool use_json)
f186de26 8822{
d62a17ae 8823 struct listnode *node, *nnode;
8824 struct bgp *bgp;
8825 int is_first = 1;
9f049418 8826 bool route_output = false;
f186de26 8827
d62a17ae 8828 if (use_json)
8829 vty_out(vty, "{\n");
9f689658 8830
d62a17ae 8831 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 8832 route_output = true;
d62a17ae 8833 if (use_json) {
8834 if (!is_first)
8835 vty_out(vty, ",\n");
8836 else
8837 is_first = 0;
8838
8839 vty_out(vty, "\"%s\":",
8840 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 8841 ? VRF_DEFAULT_NAME
d62a17ae 8842 : bgp->name);
8843 } else {
8844 vty_out(vty, "\nInstance %s:\n",
8845 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 8846 ? VRF_DEFAULT_NAME
d62a17ae 8847 : bgp->name);
8848 }
8849 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
8850 use_json);
8851 }
9f689658 8852
d62a17ae 8853 if (use_json)
8854 vty_out(vty, "}\n");
9f049418
DS
8855 else if (!route_output)
8856 vty_out(vty, "%% BGP instance not found\n");
f186de26 8857}
8858
718e3744 8859/* Header of detailed BGP route information */
d62a17ae 8860void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
8861 struct bgp_node *rn, struct prefix_rd *prd,
8862 afi_t afi, safi_t safi, json_object *json)
8863{
40381db7 8864 struct bgp_path_info *pi;
d62a17ae 8865 struct prefix *p;
8866 struct peer *peer;
8867 struct listnode *node, *nnode;
06b9f471 8868 char buf1[RD_ADDRSTRLEN];
d62a17ae 8869 char buf2[INET6_ADDRSTRLEN];
d62a17ae 8870 char buf3[EVPN_ROUTE_STRLEN];
0291c246 8871 char prefix_str[BUFSIZ];
d62a17ae 8872 int count = 0;
8873 int best = 0;
8874 int suppress = 0;
c5f1e1b2
C
8875 int accept_own = 0;
8876 int route_filter_translated_v4 = 0;
8877 int route_filter_v4 = 0;
8878 int route_filter_translated_v6 = 0;
8879 int route_filter_v6 = 0;
8880 int llgr_stale = 0;
8881 int no_llgr = 0;
8882 int accept_own_nexthop = 0;
8883 int blackhole = 0;
d62a17ae 8884 int no_export = 0;
8885 int no_advertise = 0;
8886 int local_as = 0;
c5f1e1b2 8887 int no_peer = 0;
d62a17ae 8888 int first = 1;
8889 int has_valid_label = 0;
8890 mpls_label_t label = 0;
8891 json_object *json_adv_to = NULL;
9bedbb1e 8892
d62a17ae 8893 p = &rn->p;
8894 has_valid_label = bgp_is_valid_label(&rn->local_label);
8895
8896 if (has_valid_label)
8897 label = label_pton(&rn->local_label);
8898
8899 if (json) {
8900 if (has_valid_label)
8901 json_object_int_add(json, "localLabel", label);
8902
60466a63
QY
8903 json_object_string_add(
8904 json, "prefix",
8905 prefix2str(p, prefix_str, sizeof(prefix_str)));
d62a17ae 8906 } else {
d62a17ae 8907 if (safi == SAFI_EVPN)
8908 vty_out(vty, "BGP routing table entry for %s%s%s\n",
06b9f471 8909 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
d62a17ae 8910 : "",
8911 prd ? ":" : "",
8912 bgp_evpn_route2str((struct prefix_evpn *)p,
8913 buf3, sizeof(buf3)));
8914 else
8915 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
8916 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8917 ? prefix_rd2str(prd, buf1,
06b9f471 8918 sizeof(buf1))
d62a17ae 8919 : ""),
8920 safi == SAFI_MPLS_VPN ? ":" : "",
8921 inet_ntop(p->family, &p->u.prefix, buf2,
8922 INET6_ADDRSTRLEN),
8923 p->prefixlen);
cd1964ff 8924
d62a17ae 8925 if (has_valid_label)
8926 vty_out(vty, "Local label: %d\n", label);
d62a17ae 8927 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 8928 vty_out(vty, "not allocated\n");
8929 }
718e3744 8930
6f94b685 8931 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
d62a17ae 8932 count++;
40381db7 8933 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 8934 best = count;
40381db7 8935 if (pi->extra && pi->extra->suppress)
d62a17ae 8936 suppress = 1;
cee9c031 8937
40381db7 8938 if (pi->attr->community == NULL)
cee9c031
QY
8939 continue;
8940
8941 no_advertise += community_include(
40381db7
DS
8942 pi->attr->community, COMMUNITY_NO_ADVERTISE);
8943 no_export += community_include(pi->attr->community,
cee9c031 8944 COMMUNITY_NO_EXPORT);
40381db7 8945 local_as += community_include(pi->attr->community,
cee9c031 8946 COMMUNITY_LOCAL_AS);
40381db7 8947 accept_own += community_include(pi->attr->community,
cee9c031
QY
8948 COMMUNITY_ACCEPT_OWN);
8949 route_filter_translated_v4 += community_include(
40381db7 8950 pi->attr->community,
cee9c031
QY
8951 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
8952 route_filter_translated_v6 += community_include(
40381db7 8953 pi->attr->community,
cee9c031
QY
8954 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
8955 route_filter_v4 += community_include(
40381db7 8956 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 8957 route_filter_v6 += community_include(
40381db7
DS
8958 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
8959 llgr_stale += community_include(pi->attr->community,
cee9c031 8960 COMMUNITY_LLGR_STALE);
40381db7 8961 no_llgr += community_include(pi->attr->community,
cee9c031
QY
8962 COMMUNITY_NO_LLGR);
8963 accept_own_nexthop +=
40381db7 8964 community_include(pi->attr->community,
cee9c031 8965 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 8966 blackhole += community_include(pi->attr->community,
cee9c031 8967 COMMUNITY_BLACKHOLE);
40381db7 8968 no_peer += community_include(pi->attr->community,
cee9c031 8969 COMMUNITY_NO_PEER);
d62a17ae 8970 }
718e3744 8971 }
718e3744 8972
d62a17ae 8973 if (!json) {
8974 vty_out(vty, "Paths: (%d available", count);
8975 if (best) {
8976 vty_out(vty, ", best #%d", best);
8977 if (safi == SAFI_UNICAST)
8978 vty_out(vty, ", table %s",
8979 (bgp->inst_type
8980 == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 8981 ? VRF_DEFAULT_NAME
d62a17ae 8982 : bgp->name);
8983 } else
8984 vty_out(vty, ", no best path");
8985
c5f1e1b2
C
8986 if (accept_own)
8987 vty_out(vty,
8988 ", accept own local route exported and imported in different VRF");
8989 else if (route_filter_translated_v4)
8990 vty_out(vty,
8991 ", mark translated RTs for VPNv4 route filtering");
8992 else if (route_filter_v4)
8993 vty_out(vty,
8994 ", attach RT as-is for VPNv4 route filtering");
8995 else if (route_filter_translated_v6)
8996 vty_out(vty,
8997 ", mark translated RTs for VPNv6 route filtering");
8998 else if (route_filter_v6)
8999 vty_out(vty,
9000 ", attach RT as-is for VPNv6 route filtering");
9001 else if (llgr_stale)
9002 vty_out(vty,
9003 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9004 else if (no_llgr)
9005 vty_out(vty,
9006 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9007 else if (accept_own_nexthop)
9008 vty_out(vty,
9009 ", accept local nexthop");
9010 else if (blackhole)
9011 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 9012 else if (no_export)
9013 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
9014 else if (no_advertise)
9015 vty_out(vty, ", not advertised to any peer");
d62a17ae 9016 else if (local_as)
9017 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
9018 else if (no_peer)
9019 vty_out(vty,
9020 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 9021
9022 if (suppress)
9023 vty_out(vty,
9024 ", Advertisements suppressed by an aggregate.");
9025 vty_out(vty, ")\n");
9026 }
718e3744 9027
d62a17ae 9028 /* If we are not using addpath then we can display Advertised to and
9029 * that will
9030 * show what peers we advertised the bestpath to. If we are using
9031 * addpath
9032 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 9033 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 9034 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9035 if (bgp_adj_out_lookup(peer, rn, 0)) {
9036 if (json && !json_adv_to)
9037 json_adv_to = json_object_new_object();
9038
9039 route_vty_out_advertised_to(
9040 vty, peer, &first,
9041 " Advertised to non peer-group peers:\n ",
9042 json_adv_to);
9043 }
9044 }
9045
9046 if (json) {
9047 if (json_adv_to) {
9048 json_object_object_add(json, "advertisedTo",
9049 json_adv_to);
9050 }
9051 } else {
9052 if (first)
9053 vty_out(vty, " Not advertised to any peer");
9054 vty_out(vty, "\n");
9055 }
9056 }
718e3744 9057}
9058
9059/* Display specified route of BGP table. */
d62a17ae 9060static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
9061 struct bgp_table *rib, const char *ip_str,
9062 afi_t afi, safi_t safi,
9063 struct prefix_rd *prd, int prefix_check,
9f049418 9064 enum bgp_path_type pathtype, bool use_json)
d62a17ae 9065{
9066 int ret;
9067 int header;
9068 int display = 0;
9069 struct prefix match;
9070 struct bgp_node *rn;
9071 struct bgp_node *rm;
40381db7 9072 struct bgp_path_info *pi;
d62a17ae 9073 struct bgp_table *table;
9074 json_object *json = NULL;
9075 json_object *json_paths = NULL;
9076
9077 /* Check IP address argument. */
9078 ret = str2prefix(ip_str, &match);
9079 if (!ret) {
9080 vty_out(vty, "address is malformed\n");
9081 return CMD_WARNING;
9082 }
718e3744 9083
d62a17ae 9084 match.family = afi2family(afi);
b05a1c8b 9085
d62a17ae 9086 if (use_json) {
9087 json = json_object_new_object();
9088 json_paths = json_object_new_array();
9089 }
718e3744 9090
d62a17ae 9091 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9092 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
9093 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
9094 continue;
67009e22
DS
9095 table = bgp_node_get_bgp_table_info(rn);
9096 if (!table)
ea47320b 9097 continue;
d62a17ae 9098
ea47320b
DL
9099 header = 1;
9100
9101 if ((rm = bgp_node_match(table, &match)) == NULL)
9102 continue;
d62a17ae 9103
ea47320b
DL
9104 if (prefix_check
9105 && rm->p.prefixlen != match.prefixlen) {
9106 bgp_unlock_node(rm);
9107 continue;
9108 }
d62a17ae 9109
6f94b685
DS
9110 for (pi = bgp_node_get_bgp_path_info(rm); pi;
9111 pi = pi->next) {
ea47320b 9112 if (header) {
60466a63
QY
9113 route_vty_out_detail_header(
9114 vty, bgp, rm,
9115 (struct prefix_rd *)&rn->p,
ea47320b
DL
9116 AFI_IP, safi, json);
9117 header = 0;
d62a17ae 9118 }
ea47320b
DL
9119 display++;
9120
360660c6
DS
9121 if (pathtype == BGP_PATH_SHOW_ALL
9122 || (pathtype == BGP_PATH_SHOW_BESTPATH
40381db7 9123 && CHECK_FLAG(pi->flags,
1defdda8 9124 BGP_PATH_SELECTED))
360660c6 9125 || (pathtype == BGP_PATH_SHOW_MULTIPATH
40381db7 9126 && (CHECK_FLAG(pi->flags,
1defdda8 9127 BGP_PATH_MULTIPATH)
40381db7 9128 || CHECK_FLAG(pi->flags,
1defdda8 9129 BGP_PATH_SELECTED))))
ea47320b 9130 route_vty_out_detail(vty, bgp, &rm->p,
40381db7 9131 pi, AFI_IP, safi,
ea47320b 9132 json_paths);
d62a17ae 9133 }
ea47320b
DL
9134
9135 bgp_unlock_node(rm);
d62a17ae 9136 }
98a9dbc7 9137 } else if (safi == SAFI_FLOWSPEC) {
63a0b7a9
PG
9138 display = bgp_flowspec_display_match_per_ip(afi, rib,
9139 &match, prefix_check,
9140 vty,
9141 use_json,
9142 json_paths);
d62a17ae 9143 } else {
9144 header = 1;
9145
9146 if ((rn = bgp_node_match(rib, &match)) != NULL) {
9147 if (!prefix_check
9148 || rn->p.prefixlen == match.prefixlen) {
6f94b685
DS
9149 for (pi = bgp_node_get_bgp_path_info(rn); pi;
9150 pi = pi->next) {
d62a17ae 9151 if (header) {
9152 route_vty_out_detail_header(
9153 vty, bgp, rn, NULL, afi,
9154 safi, json);
9155 header = 0;
9156 }
9157 display++;
9158
360660c6
DS
9159 if (pathtype == BGP_PATH_SHOW_ALL
9160 || (pathtype
9161 == BGP_PATH_SHOW_BESTPATH
d62a17ae 9162 && CHECK_FLAG(
40381db7 9163 pi->flags,
1defdda8 9164 BGP_PATH_SELECTED))
360660c6
DS
9165 || (pathtype
9166 == BGP_PATH_SHOW_MULTIPATH
d62a17ae 9167 && (CHECK_FLAG(
40381db7 9168 pi->flags,
1defdda8 9169 BGP_PATH_MULTIPATH)
d62a17ae 9170 || CHECK_FLAG(
40381db7 9171 pi->flags,
1defdda8 9172 BGP_PATH_SELECTED))))
d62a17ae 9173 route_vty_out_detail(
40381db7 9174 vty, bgp, &rn->p, pi,
d62a17ae 9175 afi, safi, json_paths);
9176 }
9177 }
9178
9179 bgp_unlock_node(rn);
9180 }
9181 }
e5eee9af 9182
d62a17ae 9183 if (use_json) {
9184 if (display)
9185 json_object_object_add(json, "paths", json_paths);
9186
996c9314
LB
9187 vty_out(vty, "%s\n", json_object_to_json_string_ext(
9188 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 9189 json_object_free(json);
9190 } else {
9191 if (!display) {
9192 vty_out(vty, "%% Network not in table\n");
9193 return CMD_WARNING;
9194 }
9195 }
b05a1c8b 9196
d62a17ae 9197 return CMD_SUCCESS;
718e3744 9198}
9199
fee0f4c6 9200/* Display specified route of Main RIB */
d62a17ae 9201static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
9202 afi_t afi, safi_t safi, struct prefix_rd *prd,
9203 int prefix_check, enum bgp_path_type pathtype,
9f049418 9204 bool use_json)
d62a17ae 9205{
9b86009a 9206 if (!bgp) {
d62a17ae 9207 bgp = bgp_get_default();
9b86009a
RW
9208 if (!bgp) {
9209 if (!use_json)
9210 vty_out(vty, "No BGP process is configured\n");
16307668
RW
9211 else
9212 vty_out(vty, "{}\n");
9b86009a
RW
9213 return CMD_WARNING;
9214 }
9215 }
d62a17ae 9216
9217 /* labeled-unicast routes live in the unicast table */
9218 if (safi == SAFI_LABELED_UNICAST)
9219 safi = SAFI_UNICAST;
9220
9221 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
9222 afi, safi, prd, prefix_check, pathtype,
9223 use_json);
9224}
9225
9226static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
9227 struct cmd_token **argv, afi_t afi, safi_t safi,
088f1098 9228 bool uj)
d62a17ae 9229{
9230 struct lcommunity *lcom;
9231 struct buffer *b;
9232 int i;
9233 char *str;
9234 int first = 0;
9235
9236 b = buffer_new(1024);
9237 for (i = 0; i < argc; i++) {
9238 if (first)
9239 buffer_putc(b, ' ');
9240 else {
9241 if (strmatch(argv[i]->text, "AA:BB:CC")) {
9242 first = 1;
9243 buffer_putstr(b, argv[i]->arg);
9244 }
9245 }
9246 }
9247 buffer_putc(b, '\0');
57d187bc 9248
d62a17ae 9249 str = buffer_getstr(b);
9250 buffer_free(b);
57d187bc 9251
d62a17ae 9252 lcom = lcommunity_str2com(str);
9253 XFREE(MTYPE_TMP, str);
9254 if (!lcom) {
9255 vty_out(vty, "%% Large-community malformed\n");
9256 return CMD_WARNING;
9257 }
57d187bc 9258
d62a17ae 9259 return bgp_show(vty, bgp, afi, safi, bgp_show_type_lcommunity, lcom,
9260 uj);
57d187bc
JS
9261}
9262
d62a17ae 9263static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
9264 const char *lcom, afi_t afi, safi_t safi,
088f1098 9265 bool uj)
57d187bc 9266{
d62a17ae 9267 struct community_list *list;
57d187bc 9268
d62a17ae 9269 list = community_list_lookup(bgp_clist, lcom,
9270 LARGE_COMMUNITY_LIST_MASTER);
9271 if (list == NULL) {
9272 vty_out(vty, "%% %s is not a valid large-community-list name\n",
9273 lcom);
9274 return CMD_WARNING;
9275 }
57d187bc 9276
d62a17ae 9277 return bgp_show(vty, bgp, afi, safi, bgp_show_type_lcommunity_list,
9278 list, uj);
fee0f4c6 9279}
9280
52951b63
DS
9281DEFUN (show_ip_bgp_large_community_list,
9282 show_ip_bgp_large_community_list_cmd,
4dd6177e 9283 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community-list <(1-500)|WORD> [json]",
52951b63
DS
9284 SHOW_STR
9285 IP_STR
9286 BGP_STR
9287 BGP_INSTANCE_HELP_STR
9bedbb1e 9288 BGP_AFI_HELP_STR
4dd6177e 9289 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
9290 "Display routes matching the large-community-list\n"
9291 "large-community-list number\n"
9292 "large-community-list name\n"
9293 JSON_STR)
9294{
d62a17ae 9295 char *vrf = NULL;
9296 afi_t afi = AFI_IP6;
9297 safi_t safi = SAFI_UNICAST;
9298 int idx = 0;
9299
9300 if (argv_find(argv, argc, "ip", &idx))
9301 afi = AFI_IP;
9302 if (argv_find(argv, argc, "view", &idx)
9303 || argv_find(argv, argc, "vrf", &idx))
9304 vrf = argv[++idx]->arg;
9305 if (argv_find(argv, argc, "ipv4", &idx)
9306 || argv_find(argv, argc, "ipv6", &idx)) {
9307 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
9308 if (argv_find(argv, argc, "unicast", &idx)
9309 || argv_find(argv, argc, "multicast", &idx))
9310 safi = bgp_vty_safi_from_str(argv[idx]->text);
9311 }
9312
9f049418 9313 bool uj = use_json(argc, argv);
d62a17ae 9314
9315 struct bgp *bgp = bgp_lookup_by_name(vrf);
9316 if (bgp == NULL) {
9317 vty_out(vty, "Can't find BGP instance %s\n", vrf);
9318 return CMD_WARNING;
9319 }
9320
9321 argv_find(argv, argc, "large-community-list", &idx);
9322 return bgp_show_lcommunity_list(vty, bgp, argv[idx + 1]->arg, afi, safi,
9323 uj);
52951b63
DS
9324}
9325DEFUN (show_ip_bgp_large_community,
9326 show_ip_bgp_large_community_cmd,
4dd6177e 9327 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community [AA:BB:CC] [json]",
52951b63
DS
9328 SHOW_STR
9329 IP_STR
9330 BGP_STR
9331 BGP_INSTANCE_HELP_STR
9bedbb1e 9332 BGP_AFI_HELP_STR
4dd6177e 9333 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
9334 "Display routes matching the large-communities\n"
9335 "List of large-community numbers\n"
9336 JSON_STR)
9337{
d62a17ae 9338 char *vrf = NULL;
9339 afi_t afi = AFI_IP6;
9340 safi_t safi = SAFI_UNICAST;
9341 int idx = 0;
9342
9343 if (argv_find(argv, argc, "ip", &idx))
9344 afi = AFI_IP;
9345 if (argv_find(argv, argc, "view", &idx)
9346 || argv_find(argv, argc, "vrf", &idx))
9347 vrf = argv[++idx]->arg;
9348 if (argv_find(argv, argc, "ipv4", &idx)
9349 || argv_find(argv, argc, "ipv6", &idx)) {
9350 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
9351 if (argv_find(argv, argc, "unicast", &idx)
9352 || argv_find(argv, argc, "multicast", &idx))
9353 safi = bgp_vty_safi_from_str(argv[idx]->text);
9354 }
9355
9f049418 9356 bool uj = use_json(argc, argv);
d62a17ae 9357
9358 struct bgp *bgp = bgp_lookup_by_name(vrf);
9359 if (bgp == NULL) {
9360 vty_out(vty, "Can't find BGP instance %s\n", vrf);
9361 return CMD_WARNING;
9362 }
9363
9364 if (argv_find(argv, argc, "AA:BB:CC", &idx))
9365 return bgp_show_lcommunity(vty, bgp, argc, argv, afi, safi, uj);
9366 else
9367 return bgp_show(vty, bgp, afi, safi,
9368 bgp_show_type_lcommunity_all, NULL, uj);
52951b63
DS
9369}
9370
d62a17ae 9371static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
9372 safi_t safi);
e01ca200 9373
7b2ff250
DW
9374
9375/* BGP route print out function without JSON */
af462945
DS
9376DEFUN (show_ip_bgp,
9377 show_ip_bgp_cmd,
4dd6177e 9378 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
7b2ff250
DW
9379 <dampening <parameters>\
9380 |route-map WORD\
9381 |prefix-list WORD\
9382 |filter-list WORD\
9383 |statistics\
7b2ff250
DW
9384 |community-list <(1-500)|WORD> [exact-match]\
9385 |A.B.C.D/M longer-prefixes\
9386 |X:X::X:X/M longer-prefixes\
9387 >",
718e3744 9388 SHOW_STR
9389 IP_STR
9390 BGP_STR
a636c635 9391 BGP_INSTANCE_HELP_STR
4f280b15 9392 BGP_AFI_HELP_STR
4dd6177e 9393 BGP_SAFI_WITH_LABEL_HELP_STR
a636c635 9394 "Display detailed information about dampening\n"
af462945 9395 "Display detail of configured dampening parameters\n"
a636c635
DW
9396 "Display routes matching the route-map\n"
9397 "A route-map to match on\n"
9398 "Display routes conforming to the prefix-list\n"
8c3deaae 9399 "Prefix-list name\n"
a636c635
DW
9400 "Display routes conforming to the filter-list\n"
9401 "Regular expression access list name\n"
e01ca200 9402 "BGP RIB advertisement statistics\n"
a636c635
DW
9403 "Display routes matching the community-list\n"
9404 "community-list number\n"
9405 "community-list name\n"
9406 "Exact match of the communities\n"
0c7b1b01 9407 "IPv4 prefix\n"
8c3deaae 9408 "Display route and more specific routes\n"
0c7b1b01 9409 "IPv6 prefix\n"
7b2ff250 9410 "Display route and more specific routes\n")
718e3744 9411{
d62a17ae 9412 afi_t afi = AFI_IP6;
9413 safi_t safi = SAFI_UNICAST;
9414 int exact_match = 0;
d62a17ae 9415 struct bgp *bgp = NULL;
9416 int idx = 0;
9417
9418 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 9419 &bgp, false);
d62a17ae 9420 if (!idx)
9421 return CMD_WARNING;
9422
d62a17ae 9423 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 9424 if (argv_find(argv, argc, "parameters", &idx))
d62a17ae 9425 return bgp_show_dampening_parameters(vty, afi, safi);
9426 }
c016b6c7 9427
d62a17ae 9428 if (argv_find(argv, argc, "prefix-list", &idx))
9429 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
9430 safi, bgp_show_type_prefix_list);
9431
9432 if (argv_find(argv, argc, "filter-list", &idx))
9433 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
9434 safi, bgp_show_type_filter_list);
9435
9436 if (argv_find(argv, argc, "statistics", &idx))
9437 return bgp_table_stats(vty, bgp, afi, safi);
9438
9439 if (argv_find(argv, argc, "route-map", &idx))
9440 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
9441 safi, bgp_show_type_route_map);
9442
d62a17ae 9443 if (argv_find(argv, argc, "community-list", &idx)) {
9444 const char *clist_number_or_name = argv[++idx]->arg;
9445 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
9446 exact_match = 1;
9447 return bgp_show_community_list(vty, bgp, clist_number_or_name,
9448 exact_match, afi, safi);
9449 }
9450 /* prefix-longer */
9451 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
9452 || argv_find(argv, argc, "X:X::X:X/M", &idx))
9453 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
9454 safi,
9455 bgp_show_type_prefix_longer);
9456
7b2ff250
DW
9457 return CMD_WARNING;
9458}
9459
9460/* BGP route print out function with JSON */
9461DEFUN (show_ip_bgp_json,
9462 show_ip_bgp_json_cmd,
9463 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
cf4898bc
QY
9464 [cidr-only\
9465 |dampening <flap-statistics|dampened-paths>\
9466 |community [AA:NN|local-AS|no-advertise|no-export\
9467 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
9468 |accept-own|accept-own-nexthop|route-filter-v6\
9469 |route-filter-v4|route-filter-translated-v6\
9470 |route-filter-translated-v4] [exact-match]\
9471 ] [json]",
7b2ff250
DW
9472 SHOW_STR
9473 IP_STR
9474 BGP_STR
9475 BGP_INSTANCE_HELP_STR
9476 BGP_AFI_HELP_STR
9477 BGP_SAFI_WITH_LABEL_HELP_STR
9478 "Display only routes with non-natural netmasks\n"
9479 "Display detailed information about dampening\n"
9480 "Display flap statistics of routes\n"
9481 "Display paths suppressed due to dampening\n"
9482 "Display routes matching the communities\n"
d0086e8e
AD
9483 COMMUNITY_AANN_STR
9484 "Do not send outside local AS (well-known community)\n"
9485 "Do not advertise to any peer (well-known community)\n"
9486 "Do not export to next AS (well-known community)\n"
9487 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
9488 "Do not export to any peer (well-known community)\n"
9489 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
9490 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
9491 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
9492 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
9493 "Should accept VPN route with local nexthop (well-known community)\n"
9494 "RT VPNv6 route filtering (well-known community)\n"
9495 "RT VPNv4 route filtering (well-known community)\n"
9496 "RT translated VPNv6 route filtering (well-known community)\n"
9497 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 9498 "Exact match of the communities\n"
7b2ff250
DW
9499 JSON_STR)
9500{
9501 afi_t afi = AFI_IP6;
9502 safi_t safi = SAFI_UNICAST;
9503 enum bgp_show_type sh_type = bgp_show_type_normal;
9504 struct bgp *bgp = NULL;
9505 int idx = 0;
d0086e8e 9506 int exact_match = 0;
9f049418
DS
9507 bool uj = use_json(argc, argv);
9508
9509 if (uj)
9510 argc--;
7b2ff250
DW
9511
9512 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 9513 &bgp, uj);
7b2ff250
DW
9514 if (!idx)
9515 return CMD_WARNING;
9516
7b2ff250
DW
9517 if (argv_find(argv, argc, "cidr-only", &idx))
9518 return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
9519 NULL, uj);
9520
9521 if (argv_find(argv, argc, "dampening", &idx)) {
9522 if (argv_find(argv, argc, "dampened-paths", &idx))
9523 return bgp_show(vty, bgp, afi, safi,
9524 bgp_show_type_dampend_paths, NULL, uj);
9525 else if (argv_find(argv, argc, "flap-statistics", &idx))
9526 return bgp_show(vty, bgp, afi, safi,
9527 bgp_show_type_flap_statistics, NULL,
9528 uj);
9529 }
9530
9531 if (argv_find(argv, argc, "community", &idx)) {
cf4898bc
QY
9532 char *maybecomm = idx + 1 < argc ? argv[idx + 1]->text : NULL;
9533 char *community = NULL;
d0086e8e 9534
cf4898bc
QY
9535 if (maybecomm && !strmatch(maybecomm, "json")
9536 && !strmatch(maybecomm, "exact-match"))
9537 community = maybecomm;
d0086e8e 9538
cf4898bc
QY
9539 if (argv_find(argv, argc, "exact-match", &idx))
9540 exact_match = 1;
d0086e8e 9541
cf4898bc
QY
9542 if (community)
9543 return bgp_show_community(vty, bgp, community,
9544 exact_match, afi, safi, uj);
9545 else
d0086e8e 9546 return (bgp_show(vty, bgp, afi, safi,
cf4898bc
QY
9547 bgp_show_type_community_all, NULL,
9548 uj));
7b2ff250 9549 }
d0086e8e 9550
1ae44dfc 9551 return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj);
a636c635 9552}
47fc97cc 9553
718e3744 9554DEFUN (show_ip_bgp_route,
9555 show_ip_bgp_route_cmd,
4dd6177e 9556 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]"
ae19d7dd 9557 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
718e3744 9558 SHOW_STR
9559 IP_STR
9560 BGP_STR
a636c635 9561 BGP_INSTANCE_HELP_STR
4f280b15 9562 BGP_AFI_HELP_STR
4dd6177e 9563 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 9564 "Network in the BGP routing table to display\n"
0c7b1b01 9565 "IPv4 prefix\n"
8c3deaae 9566 "Network in the BGP routing table to display\n"
0c7b1b01 9567 "IPv6 prefix\n"
4092b06c 9568 "Display only the bestpath\n"
b05a1c8b 9569 "Display only multipaths\n"
9973d184 9570 JSON_STR)
4092b06c 9571{
d62a17ae 9572 int prefix_check = 0;
ae19d7dd 9573
d62a17ae 9574 afi_t afi = AFI_IP6;
9575 safi_t safi = SAFI_UNICAST;
9576 char *prefix = NULL;
9577 struct bgp *bgp = NULL;
9578 enum bgp_path_type path_type;
9f049418 9579 bool uj = use_json(argc, argv);
b05a1c8b 9580
d62a17ae 9581 int idx = 0;
ae19d7dd 9582
d62a17ae 9583 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 9584 &bgp, uj);
d62a17ae 9585 if (!idx)
9586 return CMD_WARNING;
c41247f5 9587
d62a17ae 9588 if (!bgp) {
9589 vty_out(vty,
9590 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9591 return CMD_WARNING;
9592 }
a636c635 9593
d62a17ae 9594 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9595 if (argv_find(argv, argc, "A.B.C.D", &idx)
9596 || argv_find(argv, argc, "X:X::X:X", &idx))
9597 prefix_check = 0;
9598 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
9599 || argv_find(argv, argc, "X:X::X:X/M", &idx))
9600 prefix_check = 1;
9601
9602 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
9603 && afi != AFI_IP6) {
9604 vty_out(vty,
9605 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9606 return CMD_WARNING;
9607 }
9608 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
9609 && afi != AFI_IP) {
9610 vty_out(vty,
9611 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9612 return CMD_WARNING;
9613 }
9614
9615 prefix = argv[idx]->arg;
9616
9617 /* [<bestpath|multipath>] */
9618 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 9619 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 9620 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 9621 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 9622 else
360660c6 9623 path_type = BGP_PATH_SHOW_ALL;
a636c635 9624
d62a17ae 9625 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
9626 path_type, uj);
4092b06c
DS
9627}
9628
8c3deaae
QY
9629DEFUN (show_ip_bgp_regexp,
9630 show_ip_bgp_regexp_cmd,
4dd6177e 9631 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX...",
8c3deaae
QY
9632 SHOW_STR
9633 IP_STR
9634 BGP_STR
b00b230a 9635 BGP_INSTANCE_HELP_STR
4f280b15 9636 BGP_AFI_HELP_STR
4dd6177e 9637 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae
QY
9638 "Display routes matching the AS path regular expression\n"
9639 "A regular-expression to match the BGP AS paths\n")
9640{
d62a17ae 9641 afi_t afi = AFI_IP6;
9642 safi_t safi = SAFI_UNICAST;
9643 struct bgp *bgp = NULL;
8c3deaae 9644
d62a17ae 9645 int idx = 0;
9646 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 9647 &bgp, false);
d62a17ae 9648 if (!idx)
9649 return CMD_WARNING;
8c3deaae 9650
d62a17ae 9651 // get index of regex
9652 argv_find(argv, argc, "regexp", &idx);
9653 idx++;
8c3deaae 9654
d62a17ae 9655 char *regstr = argv_concat(argv, argc, idx);
e889891d 9656 int rc = bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
d62a17ae 9657 bgp_show_type_regexp);
9658 XFREE(MTYPE_TMP, regstr);
9659 return rc;
8c3deaae
QY
9660}
9661
a636c635
DW
9662DEFUN (show_ip_bgp_instance_all,
9663 show_ip_bgp_instance_all_cmd,
4dd6177e 9664 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json]",
4092b06c 9665 SHOW_STR
a636c635 9666 IP_STR
4092b06c 9667 BGP_STR
a636c635 9668 BGP_INSTANCE_ALL_HELP_STR
4f280b15 9669 BGP_AFI_HELP_STR
4dd6177e 9670 BGP_SAFI_WITH_LABEL_HELP_STR
9973d184 9671 JSON_STR)
4092b06c 9672{
d62a17ae 9673 afi_t afi = AFI_IP;
9674 safi_t safi = SAFI_UNICAST;
9675 struct bgp *bgp = NULL;
d62a17ae 9676 int idx = 0;
9f049418 9677 bool uj = use_json(argc, argv);
ae19d7dd 9678
d62a17ae 9679 if (uj)
9680 argc--;
e3e29b32 9681
9f049418
DS
9682 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9683 &bgp, uj);
9684 if (!idx)
9685 return CMD_WARNING;
9686
d62a17ae 9687 bgp_show_all_instances_routes_vty(vty, afi, safi, uj);
9688 return CMD_SUCCESS;
e3e29b32
LB
9689}
9690
a4d82a8a
PZ
9691static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
9692 afi_t afi, safi_t safi, enum bgp_show_type type)
718e3744 9693{
d62a17ae 9694 regex_t *regex;
9695 int rc;
e3e29b32 9696
d62a17ae 9697 regex = bgp_regcomp(regstr);
9698 if (!regex) {
9699 vty_out(vty, "Can't compile regexp %s\n", regstr);
9700 return CMD_WARNING;
9701 }
a636c635 9702
e889891d 9703 rc = bgp_show(vty, bgp, afi, safi, type, regex, 0);
d62a17ae 9704 bgp_regex_free(regex);
9705 return rc;
e3e29b32
LB
9706}
9707
d62a17ae 9708static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
9709 const char *prefix_list_str, afi_t afi,
9710 safi_t safi, enum bgp_show_type type)
e3e29b32 9711{
d62a17ae 9712 struct prefix_list *plist;
718e3744 9713
d62a17ae 9714 plist = prefix_list_lookup(afi, prefix_list_str);
9715 if (plist == NULL) {
9716 vty_out(vty, "%% %s is not a valid prefix-list name\n",
9717 prefix_list_str);
9718 return CMD_WARNING;
9719 }
718e3744 9720
d62a17ae 9721 return bgp_show(vty, bgp, afi, safi, type, plist, 0);
4092b06c
DS
9722}
9723
d62a17ae 9724static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
9725 const char *filter, afi_t afi, safi_t safi,
9726 enum bgp_show_type type)
4092b06c 9727{
d62a17ae 9728 struct as_list *as_list;
718e3744 9729
d62a17ae 9730 as_list = as_list_lookup(filter);
9731 if (as_list == NULL) {
9732 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
9733 filter);
9734 return CMD_WARNING;
9735 }
a636c635 9736
d62a17ae 9737 return bgp_show(vty, bgp, afi, safi, type, as_list, 0);
718e3744 9738}
9739
d62a17ae 9740static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
9741 const char *rmap_str, afi_t afi, safi_t safi,
9742 enum bgp_show_type type)
718e3744 9743{
d62a17ae 9744 struct route_map *rmap;
bb46e94f 9745
d62a17ae 9746 rmap = route_map_lookup_by_name(rmap_str);
9747 if (!rmap) {
9748 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
9749 return CMD_WARNING;
9750 }
9751
9752 return bgp_show(vty, bgp, afi, safi, type, rmap, 0);
9753}
9754
7f323236
DW
9755static int bgp_show_community(struct vty *vty, struct bgp *bgp,
9756 const char *comstr, int exact, afi_t afi,
9f049418 9757 safi_t safi, bool use_json)
d62a17ae 9758{
9759 struct community *com;
d62a17ae 9760 int ret = 0;
9761
7f323236 9762 com = community_str2com(comstr);
d62a17ae 9763 if (!com) {
7f323236 9764 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 9765 return CMD_WARNING;
9766 }
9767
9768 ret = bgp_show(vty, bgp, afi, safi,
9769 (exact ? bgp_show_type_community_exact
9770 : bgp_show_type_community),
d0086e8e 9771 com, use_json);
3c1f53de 9772 community_free(&com);
46c3ce83 9773
d62a17ae 9774 return ret;
718e3744 9775}
9776
d62a17ae 9777static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
9778 const char *com, int exact, afi_t afi,
9779 safi_t safi)
50ef26d4 9780{
d62a17ae 9781 struct community_list *list;
50ef26d4 9782
d62a17ae 9783 list = community_list_lookup(bgp_clist, com, COMMUNITY_LIST_MASTER);
9784 if (list == NULL) {
9785 vty_out(vty, "%% %s is not a valid community-list name\n", com);
9786 return CMD_WARNING;
9787 }
718e3744 9788
d62a17ae 9789 return bgp_show(vty, bgp, afi, safi,
9790 (exact ? bgp_show_type_community_list_exact
9791 : bgp_show_type_community_list),
9792 list, 0);
50ef26d4 9793}
9794
d62a17ae 9795static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
9796 const char *prefix, afi_t afi, safi_t safi,
9797 enum bgp_show_type type)
718e3744 9798{
d62a17ae 9799 int ret;
9800 struct prefix *p;
47fc97cc 9801
d62a17ae 9802 p = prefix_new();
95cbbd2a 9803
d62a17ae 9804 ret = str2prefix(prefix, p);
9805 if (!ret) {
9806 vty_out(vty, "%% Malformed Prefix\n");
9807 return CMD_WARNING;
9808 }
47e9b292 9809
d62a17ae 9810 ret = bgp_show(vty, bgp, afi, safi, type, p, 0);
9811 prefix_free(p);
9812 return ret;
9813}
9814
9815static struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp,
9f049418 9816 const char *ip_str, bool use_json)
d62a17ae 9817{
9818 int ret;
9819 struct peer *peer;
9820 union sockunion su;
9821
9822 /* Get peer sockunion. */
9823 ret = str2sockunion(ip_str, &su);
9824 if (ret < 0) {
9825 peer = peer_lookup_by_conf_if(bgp, ip_str);
9826 if (!peer) {
9827 peer = peer_lookup_by_hostname(bgp, ip_str);
9828
9829 if (!peer) {
9830 if (use_json) {
9831 json_object *json_no = NULL;
9832 json_no = json_object_new_object();
9833 json_object_string_add(
9834 json_no,
9835 "malformedAddressOrName",
9836 ip_str);
9837 vty_out(vty, "%s\n",
66f80d74 9838 json_object_to_json_string_ext(
a4d82a8a
PZ
9839 json_no,
9840 JSON_C_TO_STRING_PRETTY));
d62a17ae 9841 json_object_free(json_no);
9842 } else
9843 vty_out(vty,
9844 "%% Malformed address or name: %s\n",
9845 ip_str);
9846 return NULL;
9847 }
9848 }
9849 return peer;
9850 }
718e3744 9851
d62a17ae 9852 /* Peer structure lookup. */
9853 peer = peer_lookup(bgp, &su);
9854 if (!peer) {
9855 if (use_json) {
9856 json_object *json_no = NULL;
9857 json_no = json_object_new_object();
9858 json_object_string_add(json_no, "warning",
9e6e6f46 9859 "No such neighbor in this view/vrf");
d62a17ae 9860 vty_out(vty, "%s\n",
a4d82a8a
PZ
9861 json_object_to_json_string_ext(
9862 json_no, JSON_C_TO_STRING_PRETTY));
d62a17ae 9863 json_object_free(json_no);
9864 } else
9e6e6f46 9865 vty_out(vty, "No such neighbor in this view/vrf\n");
d62a17ae 9866 return NULL;
9867 }
2815e61f 9868
d62a17ae 9869 return peer;
9870}
9871
9872enum bgp_stats {
9873 BGP_STATS_MAXBITLEN = 0,
9874 BGP_STATS_RIB,
9875 BGP_STATS_PREFIXES,
9876 BGP_STATS_TOTPLEN,
9877 BGP_STATS_UNAGGREGATEABLE,
9878 BGP_STATS_MAX_AGGREGATEABLE,
9879 BGP_STATS_AGGREGATES,
9880 BGP_STATS_SPACE,
9881 BGP_STATS_ASPATH_COUNT,
9882 BGP_STATS_ASPATH_MAXHOPS,
9883 BGP_STATS_ASPATH_TOTHOPS,
9884 BGP_STATS_ASPATH_MAXSIZE,
9885 BGP_STATS_ASPATH_TOTSIZE,
9886 BGP_STATS_ASN_HIGHEST,
9887 BGP_STATS_MAX,
a636c635 9888};
2815e61f 9889
d62a17ae 9890static const char *table_stats_strs[] = {
9d303b37
DL
9891 [BGP_STATS_PREFIXES] = "Total Prefixes",
9892 [BGP_STATS_TOTPLEN] = "Average prefix length",
9893 [BGP_STATS_RIB] = "Total Advertisements",
9894 [BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes",
9895 [BGP_STATS_MAX_AGGREGATEABLE] =
9896 "Maximum aggregateable prefixes",
9897 [BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements",
9898 [BGP_STATS_SPACE] = "Address space advertised",
9899 [BGP_STATS_ASPATH_COUNT] = "Advertisements with paths",
9900 [BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)",
9901 [BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)",
9902 [BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)",
9903 [BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)",
9904 [BGP_STATS_ASN_HIGHEST] = "Highest public ASN",
9905 [BGP_STATS_MAX] = NULL,
a636c635 9906};
2815e61f 9907
d62a17ae 9908struct bgp_table_stats {
9909 struct bgp_table *table;
9910 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 9911 double total_space;
ff7924f6
PJ
9912};
9913
a636c635
DW
9914#if 0
9915#define TALLY_SIGFIG 100000
9916static unsigned long
9917ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 9918{
a636c635
DW
9919 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
9920 unsigned long res = (newtot * TALLY_SIGFIG) / count;
9921 unsigned long ret = newtot / count;
07d0c4ed 9922
a636c635
DW
9923 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
9924 return ret + 1;
9925 else
9926 return ret;
9927}
9928#endif
ff7924f6 9929
d62a17ae 9930static int bgp_table_stats_walker(struct thread *t)
2815e61f 9931{
d62a17ae 9932 struct bgp_node *rn;
9933 struct bgp_node *top;
9934 struct bgp_table_stats *ts = THREAD_ARG(t);
9935 unsigned int space = 0;
a636c635 9936
d62a17ae 9937 if (!(top = bgp_table_top(ts->table)))
9938 return 0;
2815e61f 9939
d62a17ae 9940 switch (top->p.family) {
9941 case AF_INET:
9942 space = IPV4_MAX_BITLEN;
9943 break;
9944 case AF_INET6:
9945 space = IPV6_MAX_BITLEN;
9946 break;
9947 }
9948
9949 ts->counts[BGP_STATS_MAXBITLEN] = space;
9950
9951 for (rn = top; rn; rn = bgp_route_next(rn)) {
40381db7 9952 struct bgp_path_info *pi;
d62a17ae 9953 struct bgp_node *prn = bgp_node_parent_nolock(rn);
40381db7 9954 unsigned int pinum = 0;
d62a17ae 9955
9956 if (rn == top)
9957 continue;
9958
6f94b685 9959 if (!bgp_node_has_bgp_path_info_data(rn))
d62a17ae 9960 continue;
9961
9962 ts->counts[BGP_STATS_PREFIXES]++;
9963 ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
ff7924f6 9964
a636c635
DW
9965#if 0
9966 ts->counts[BGP_STATS_AVGPLEN]
9967 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
9968 ts->counts[BGP_STATS_AVGPLEN],
9969 rn->p.prefixlen);
9970#endif
d62a17ae 9971
9972 /* check if the prefix is included by any other announcements */
6f94b685 9973 while (prn && !bgp_node_has_bgp_path_info_data(prn))
d62a17ae 9974 prn = bgp_node_parent_nolock(prn);
9975
9976 if (prn == NULL || prn == top) {
9977 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
9978 /* announced address space */
9979 if (space)
a4d82a8a
PZ
9980 ts->total_space +=
9981 pow(2.0, space - rn->p.prefixlen);
6f94b685 9982 } else if (bgp_node_has_bgp_path_info_data(prn))
d62a17ae 9983 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
9984
6f94b685 9985 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 9986 pinum++;
d62a17ae 9987 ts->counts[BGP_STATS_RIB]++;
9988
40381db7
DS
9989 if (pi->attr
9990 && (CHECK_FLAG(pi->attr->flag,
d62a17ae 9991 ATTR_FLAG_BIT(
9992 BGP_ATTR_ATOMIC_AGGREGATE))))
9993 ts->counts[BGP_STATS_AGGREGATES]++;
9994
9995 /* as-path stats */
40381db7 9996 if (pi->attr && pi->attr->aspath) {
d62a17ae 9997 unsigned int hops =
40381db7 9998 aspath_count_hops(pi->attr->aspath);
d62a17ae 9999 unsigned int size =
40381db7
DS
10000 aspath_size(pi->attr->aspath);
10001 as_t highest = aspath_highest(pi->attr->aspath);
d62a17ae 10002
10003 ts->counts[BGP_STATS_ASPATH_COUNT]++;
10004
10005 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
10006 ts->counts[BGP_STATS_ASPATH_MAXHOPS] =
10007 hops;
10008
10009 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
10010 ts->counts[BGP_STATS_ASPATH_MAXSIZE] =
10011 size;
10012
10013 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
10014 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 10015#if 0
07d0c4ed 10016 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
10017 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
10018 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
10019 hops);
10020 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
10021 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
10022 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
10023 size);
10024#endif
d62a17ae 10025 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
10026 ts->counts[BGP_STATS_ASN_HIGHEST] =
10027 highest;
10028 }
10029 }
10030 }
10031 return 0;
2815e61f 10032}
ff7924f6 10033
d62a17ae 10034static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
10035 safi_t safi)
2815e61f 10036{
d62a17ae 10037 struct bgp_table_stats ts;
10038 unsigned int i;
019386c2 10039
d62a17ae 10040 if (!bgp->rib[afi][safi]) {
10041 vty_out(vty, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10042 afi, safi);
10043 return CMD_WARNING;
10044 }
019386c2 10045
d62a17ae 10046 vty_out(vty, "BGP %s RIB statistics\n", afi_safi_print(afi, safi));
019386c2 10047
d62a17ae 10048 /* labeled-unicast routes live in the unicast table */
10049 if (safi == SAFI_LABELED_UNICAST)
10050 safi = SAFI_UNICAST;
019386c2 10051
d62a17ae 10052 memset(&ts, 0, sizeof(ts));
10053 ts.table = bgp->rib[afi][safi];
10054 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 10055
d62a17ae 10056 for (i = 0; i < BGP_STATS_MAX; i++) {
10057 if (!table_stats_strs[i])
10058 continue;
10059
10060 switch (i) {
a636c635
DW
10061#if 0
10062 case BGP_STATS_ASPATH_AVGHOPS:
10063 case BGP_STATS_ASPATH_AVGSIZE:
10064 case BGP_STATS_AVGPLEN:
10065 vty_out (vty, "%-30s: ", table_stats_strs[i]);
10066 vty_out (vty, "%12.2f",
10067 (float)ts.counts[i] / (float)TALLY_SIGFIG);
10068 break;
10069#endif
d62a17ae 10070 case BGP_STATS_ASPATH_TOTHOPS:
10071 case BGP_STATS_ASPATH_TOTSIZE:
10072 vty_out(vty, "%-30s: ", table_stats_strs[i]);
10073 vty_out(vty, "%12.2f",
10074 ts.counts[i]
10075 ? (float)ts.counts[i]
10076 / (float)ts.counts
10077 [BGP_STATS_ASPATH_COUNT]
10078 : 0);
10079 break;
10080 case BGP_STATS_TOTPLEN:
10081 vty_out(vty, "%-30s: ", table_stats_strs[i]);
10082 vty_out(vty, "%12.2f",
10083 ts.counts[i]
10084 ? (float)ts.counts[i]
10085 / (float)ts.counts
10086 [BGP_STATS_PREFIXES]
10087 : 0);
10088 break;
10089 case BGP_STATS_SPACE:
10090 vty_out(vty, "%-30s: ", table_stats_strs[i]);
8d0ab76d
DL
10091 vty_out(vty, "%12g\n", ts.total_space);
10092
10093 if (afi == AFI_IP6) {
10094 vty_out(vty, "%30s: ", "/32 equivalent ");
10095 vty_out(vty, "%12g\n",
a4d82a8a 10096 ts.total_space * pow(2.0, -128 + 32));
8d0ab76d
DL
10097 vty_out(vty, "%30s: ", "/48 equivalent ");
10098 vty_out(vty, "%12g\n",
a4d82a8a 10099 ts.total_space * pow(2.0, -128 + 48));
8d0ab76d
DL
10100 } else {
10101 vty_out(vty, "%30s: ", "% announced ");
10102 vty_out(vty, "%12.2f\n",
10103 ts.total_space * 100. * pow(2.0, -32));
10104 vty_out(vty, "%30s: ", "/8 equivalent ");
10105 vty_out(vty, "%12.2f\n",
a4d82a8a 10106 ts.total_space * pow(2.0, -32 + 8));
8d0ab76d
DL
10107 vty_out(vty, "%30s: ", "/24 equivalent ");
10108 vty_out(vty, "%12.2f\n",
a4d82a8a 10109 ts.total_space * pow(2.0, -32 + 24));
8d0ab76d 10110 }
d62a17ae 10111 break;
10112 default:
10113 vty_out(vty, "%-30s: ", table_stats_strs[i]);
10114 vty_out(vty, "%12llu", ts.counts[i]);
10115 }
ff7924f6 10116
d62a17ae 10117 vty_out(vty, "\n");
10118 }
10119 return CMD_SUCCESS;
10120}
10121
10122enum bgp_pcounts {
10123 PCOUNT_ADJ_IN = 0,
10124 PCOUNT_DAMPED,
10125 PCOUNT_REMOVED,
10126 PCOUNT_HISTORY,
10127 PCOUNT_STALE,
10128 PCOUNT_VALID,
10129 PCOUNT_ALL,
10130 PCOUNT_COUNTED,
10131 PCOUNT_PFCNT, /* the figure we display to users */
10132 PCOUNT_MAX,
a636c635 10133};
718e3744 10134
d62a17ae 10135static const char *pcount_strs[] = {
9d303b37
DL
10136 [PCOUNT_ADJ_IN] = "Adj-in",
10137 [PCOUNT_DAMPED] = "Damped",
10138 [PCOUNT_REMOVED] = "Removed",
10139 [PCOUNT_HISTORY] = "History",
10140 [PCOUNT_STALE] = "Stale",
10141 [PCOUNT_VALID] = "Valid",
10142 [PCOUNT_ALL] = "All RIB",
10143 [PCOUNT_COUNTED] = "PfxCt counted",
10144 [PCOUNT_PFCNT] = "Useable",
10145 [PCOUNT_MAX] = NULL,
a636c635 10146};
718e3744 10147
d62a17ae 10148struct peer_pcounts {
10149 unsigned int count[PCOUNT_MAX];
10150 const struct peer *peer;
10151 const struct bgp_table *table;
a636c635 10152};
47fc97cc 10153
d62a17ae 10154static int bgp_peer_count_walker(struct thread *t)
10155{
10156 struct bgp_node *rn;
10157 struct peer_pcounts *pc = THREAD_ARG(t);
10158 const struct peer *peer = pc->peer;
10159
10160 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn)) {
10161 struct bgp_adj_in *ain;
40381db7 10162 struct bgp_path_info *pi;
d62a17ae 10163
10164 for (ain = rn->adj_in; ain; ain = ain->next)
10165 if (ain->peer == peer)
10166 pc->count[PCOUNT_ADJ_IN]++;
10167
6f94b685
DS
10168 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
10169
40381db7 10170 if (pi->peer != peer)
d62a17ae 10171 continue;
10172
10173 pc->count[PCOUNT_ALL]++;
10174
40381db7 10175 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
d62a17ae 10176 pc->count[PCOUNT_DAMPED]++;
40381db7 10177 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
d62a17ae 10178 pc->count[PCOUNT_HISTORY]++;
40381db7 10179 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
d62a17ae 10180 pc->count[PCOUNT_REMOVED]++;
40381db7 10181 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 10182 pc->count[PCOUNT_STALE]++;
40381db7 10183 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
d62a17ae 10184 pc->count[PCOUNT_VALID]++;
40381db7 10185 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
d62a17ae 10186 pc->count[PCOUNT_PFCNT]++;
10187
40381db7 10188 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 10189 pc->count[PCOUNT_COUNTED]++;
40381db7 10190 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
1c50c1c0
QY
10191 flog_err(
10192 EC_LIB_DEVELOPMENT,
10193 "Attempting to count but flags say it is unusable");
d62a17ae 10194 } else {
40381db7 10195 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
1c50c1c0
QY
10196 flog_err(
10197 EC_LIB_DEVELOPMENT,
10198 "Not counted but flags say we should");
d62a17ae 10199 }
10200 }
10201 }
10202 return 0;
718e3744 10203}
10204
d62a17ae 10205static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 10206 safi_t safi, bool use_json)
856ca177 10207{
d62a17ae 10208 struct peer_pcounts pcounts = {.peer = peer};
10209 unsigned int i;
10210 json_object *json = NULL;
10211 json_object *json_loop = NULL;
856ca177 10212
d62a17ae 10213 if (use_json) {
10214 json = json_object_new_object();
10215 json_loop = json_object_new_object();
10216 }
718e3744 10217
d62a17ae 10218 if (!peer || !peer->bgp || !peer->afc[afi][safi]
10219 || !peer->bgp->rib[afi][safi]) {
10220 if (use_json) {
10221 json_object_string_add(
10222 json, "warning",
10223 "No such neighbor or address family");
10224 vty_out(vty, "%s\n", json_object_to_json_string(json));
10225 json_object_free(json);
10226 } else
10227 vty_out(vty, "%% No such neighbor or address family\n");
10228
10229 return CMD_WARNING;
10230 }
2a71e9ce 10231
d62a17ae 10232 memset(&pcounts, 0, sizeof(pcounts));
10233 pcounts.peer = peer;
10234 pcounts.table = peer->bgp->rib[afi][safi];
10235
10236 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
10237 * stats for the thread-walk (i.e. ensure this can't be blamed on
10238 * on just vty_read()).
10239 */
d62a17ae 10240 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
10241
10242 if (use_json) {
10243 json_object_string_add(json, "prefixCountsFor", peer->host);
10244 json_object_string_add(json, "multiProtocol",
10245 afi_safi_print(afi, safi));
10246 json_object_int_add(json, "pfxCounter",
10247 peer->pcount[afi][safi]);
10248
10249 for (i = 0; i < PCOUNT_MAX; i++)
10250 json_object_int_add(json_loop, pcount_strs[i],
10251 pcounts.count[i]);
10252
10253 json_object_object_add(json, "ribTableWalkCounters", json_loop);
10254
10255 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
10256 json_object_string_add(json, "pfxctDriftFor",
10257 peer->host);
10258 json_object_string_add(
10259 json, "recommended",
10260 "Please report this bug, with the above command output");
10261 }
996c9314
LB
10262 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10263 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 10264 json_object_free(json);
10265 } else {
10266
10267 if (peer->hostname
10268 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
10269 vty_out(vty, "Prefix counts for %s/%s, %s\n",
10270 peer->hostname, peer->host,
10271 afi_safi_print(afi, safi));
10272 } else {
10273 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
10274 afi_safi_print(afi, safi));
10275 }
10276
10277 vty_out(vty, "PfxCt: %ld\n", peer->pcount[afi][safi]);
10278 vty_out(vty, "\nCounts from RIB table walk:\n\n");
10279
10280 for (i = 0; i < PCOUNT_MAX; i++)
10281 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
10282 pcounts.count[i]);
10283
10284 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
10285 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
10286 vty_out(vty,
10287 "Please report this bug, with the above command output\n");
10288 }
10289 }
10290
10291 return CMD_SUCCESS;
718e3744 10292}
10293
a636c635
DW
10294DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
10295 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
c1a44e43 10296 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] "
30a6a167 10297 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
718e3744 10298 SHOW_STR
10299 IP_STR
10300 BGP_STR
8386ac43 10301 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
10302 BGP_AFI_HELP_STR
10303 BGP_SAFI_HELP_STR
0b16f239
DS
10304 "Detailed information on TCP and BGP neighbor connections\n"
10305 "Neighbor to display information about\n"
10306 "Neighbor to display information about\n"
91d37724 10307 "Neighbor on BGP configured interface\n"
a636c635 10308 "Display detailed prefix count information\n"
9973d184 10309 JSON_STR)
0b16f239 10310{
d62a17ae 10311 afi_t afi = AFI_IP6;
10312 safi_t safi = SAFI_UNICAST;
10313 struct peer *peer;
10314 int idx = 0;
10315 struct bgp *bgp = NULL;
9f049418
DS
10316 bool uj = use_json(argc, argv);
10317
10318 if (uj)
10319 argc--;
856ca177 10320
d62a17ae 10321 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10322 &bgp, uj);
d62a17ae 10323 if (!idx)
10324 return CMD_WARNING;
0b16f239 10325
d62a17ae 10326 argv_find(argv, argc, "neighbors", &idx);
10327 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
10328 if (!peer)
10329 return CMD_WARNING;
bb46e94f 10330
d62a17ae 10331 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_UNICAST, uj);
a636c635 10332}
0b16f239 10333
d6902373
PG
10334#ifdef KEEP_OLD_VPN_COMMANDS
10335DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
10336 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
10337 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
10338 SHOW_STR
10339 IP_STR
10340 BGP_STR
d6902373 10341 BGP_VPNVX_HELP_STR
91d37724 10342 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
10343 "Detailed information on TCP and BGP neighbor connections\n"
10344 "Neighbor to display information about\n"
10345 "Neighbor to display information about\n"
91d37724 10346 "Neighbor on BGP configured interface\n"
a636c635 10347 "Display detailed prefix count information\n"
9973d184 10348 JSON_STR)
a636c635 10349{
d62a17ae 10350 int idx_peer = 6;
10351 struct peer *peer;
9f049418 10352 bool uj = use_json(argc, argv);
a636c635 10353
d62a17ae 10354 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
10355 if (!peer)
10356 return CMD_WARNING;
10357
10358 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
10359}
10360
d6902373
PG
10361DEFUN (show_ip_bgp_vpn_all_route_prefix,
10362 show_ip_bgp_vpn_all_route_prefix_cmd,
10363 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
10364 SHOW_STR
10365 IP_STR
10366 BGP_STR
d6902373 10367 BGP_VPNVX_HELP_STR
91d37724
QY
10368 "Display information about all VPNv4 NLRIs\n"
10369 "Network in the BGP routing table to display\n"
3a2d747c 10370 "Network in the BGP routing table to display\n"
9973d184 10371 JSON_STR)
91d37724 10372{
d62a17ae 10373 int idx = 0;
10374 char *network = NULL;
10375 struct bgp *bgp = bgp_get_default();
10376 if (!bgp) {
10377 vty_out(vty, "Can't find default instance\n");
10378 return CMD_WARNING;
10379 }
87e34b58 10380
d62a17ae 10381 if (argv_find(argv, argc, "A.B.C.D", &idx))
10382 network = argv[idx]->arg;
10383 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
10384 network = argv[idx]->arg;
10385 else {
10386 vty_out(vty, "Unable to figure out Network\n");
10387 return CMD_WARNING;
10388 }
87e34b58 10389
d62a17ae 10390 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 10391 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 10392}
d6902373 10393#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 10394
4c63a661
PG
10395DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix,
10396 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd,
10397 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10398 SHOW_STR
10399 IP_STR
10400 BGP_STR
10401 L2VPN_HELP_STR
10402 EVPN_HELP_STR
10403 "Display information about all EVPN NLRIs\n"
10404 "Network in the BGP routing table to display\n"
10405 "Network in the BGP routing table to display\n"
10406 JSON_STR)
10407{
d62a17ae 10408 int idx = 0;
10409 char *network = NULL;
a636c635 10410
d62a17ae 10411 if (argv_find(argv, argc, "A.B.C.D", &idx))
10412 network = argv[idx]->arg;
10413 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
10414 network = argv[idx]->arg;
10415 else {
10416 vty_out(vty, "Unable to figure out Network\n");
10417 return CMD_WARNING;
10418 }
10419 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL, 0,
360660c6 10420 BGP_PATH_SHOW_ALL, use_json(argc, argv));
d62a17ae 10421}
10422
10423static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 10424 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 10425 const char *rmap_name, bool use_json,
6392aaa6 10426 json_object *json)
d62a17ae 10427{
10428 struct bgp_table *table;
10429 struct bgp_adj_in *ain;
10430 struct bgp_adj_out *adj;
10431 unsigned long output_count;
10432 unsigned long filtered_count;
10433 struct bgp_node *rn;
10434 int header1 = 1;
10435 struct bgp *bgp;
10436 int header2 = 1;
10437 struct attr attr;
10438 int ret;
10439 struct update_subgroup *subgrp;
10440 json_object *json_scode = NULL;
10441 json_object *json_ocode = NULL;
10442 json_object *json_ar = NULL;
10443 struct peer_af *paf;
f99def61 10444 bool route_filtered;
d62a17ae 10445
10446 if (use_json) {
10447 json_scode = json_object_new_object();
10448 json_ocode = json_object_new_object();
10449 json_ar = json_object_new_object();
10450
10451 json_object_string_add(json_scode, "suppressed", "s");
10452 json_object_string_add(json_scode, "damped", "d");
10453 json_object_string_add(json_scode, "history", "h");
10454 json_object_string_add(json_scode, "valid", "*");
10455 json_object_string_add(json_scode, "best", ">");
10456 json_object_string_add(json_scode, "multipath", "=");
10457 json_object_string_add(json_scode, "internal", "i");
10458 json_object_string_add(json_scode, "ribFailure", "r");
10459 json_object_string_add(json_scode, "stale", "S");
10460 json_object_string_add(json_scode, "removed", "R");
10461
10462 json_object_string_add(json_ocode, "igp", "i");
10463 json_object_string_add(json_ocode, "egp", "e");
10464 json_object_string_add(json_ocode, "incomplete", "?");
10465 }
a636c635 10466
d62a17ae 10467 bgp = peer->bgp;
a636c635 10468
d62a17ae 10469 if (!bgp) {
10470 if (use_json) {
10471 json_object_string_add(json, "alert", "no BGP");
10472 vty_out(vty, "%s\n", json_object_to_json_string(json));
10473 json_object_free(json);
10474 } else
10475 vty_out(vty, "%% No bgp\n");
10476 return;
10477 }
a636c635 10478
d62a17ae 10479 table = bgp->rib[afi][safi];
10480
10481 output_count = filtered_count = 0;
10482 subgrp = peer_subgroup(peer, afi, safi);
10483
6392aaa6 10484 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 10485 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
10486 if (use_json) {
10487 json_object_int_add(json, "bgpTableVersion",
10488 table->version);
10489 json_object_string_add(json, "bgpLocalRouterId",
10490 inet_ntoa(bgp->router_id));
01eced22
AD
10491 json_object_int_add(json, "defaultLocPrf",
10492 bgp->default_local_pref);
10493 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 10494 json_object_object_add(json, "bgpStatusCodes",
10495 json_scode);
10496 json_object_object_add(json, "bgpOriginCodes",
10497 json_ocode);
07d0c4ed
DA
10498 json_object_string_add(
10499 json, "bgpOriginatingDefaultNetwork",
10500 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 10501 } else {
996c9314 10502 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 10503 ", local router ID is %s, vrf id ",
d62a17ae 10504 table->version, inet_ntoa(bgp->router_id));
9df8b37c
PZ
10505 if (bgp->vrf_id == VRF_UNKNOWN)
10506 vty_out(vty, "%s", VRFID_NONE_STR);
10507 else
10508 vty_out(vty, "%u", bgp->vrf_id);
10509 vty_out(vty, "\n");
01eced22
AD
10510 vty_out(vty, "Default local pref %u, ",
10511 bgp->default_local_pref);
10512 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 10513 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10514 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 10515 vty_out(vty, BGP_SHOW_OCODE_HEADER);
10516
07d0c4ed
DA
10517 vty_out(vty, "Originating default network %s\n\n",
10518 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 10519 }
10520 header1 = 0;
10521 }
a636c635 10522
d62a17ae 10523 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6392aaa6
PM
10524 if (type == bgp_show_adj_route_received
10525 || type == bgp_show_adj_route_filtered) {
d62a17ae 10526 for (ain = rn->adj_in; ain; ain = ain->next) {
6392aaa6 10527 if (ain->peer != peer || !ain->attr)
ea47320b 10528 continue;
6392aaa6 10529
ea47320b
DL
10530 if (header1) {
10531 if (use_json) {
10532 json_object_int_add(
60466a63 10533 json, "bgpTableVersion",
ea47320b
DL
10534 0);
10535 json_object_string_add(
10536 json,
10537 "bgpLocalRouterId",
10538 inet_ntoa(
10539 bgp->router_id));
01eced22
AD
10540 json_object_int_add(json,
10541 "defaultLocPrf",
10542 bgp->default_local_pref);
10543 json_object_int_add(json,
10544 "localAS", bgp->as);
ea47320b 10545 json_object_object_add(
60466a63 10546 json, "bgpStatusCodes",
ea47320b
DL
10547 json_scode);
10548 json_object_object_add(
60466a63 10549 json, "bgpOriginCodes",
ea47320b
DL
10550 json_ocode);
10551 } else {
10552 vty_out(vty,
9df8b37c 10553 "BGP table version is 0, local router ID is %s, vrf id ",
ea47320b 10554 inet_ntoa(
9df8b37c
PZ
10555 bgp->router_id));
10556 if (bgp->vrf_id == VRF_UNKNOWN)
10557 vty_out(vty, "%s",
10558 VRFID_NONE_STR);
10559 else
10560 vty_out(vty, "%u",
10561 bgp->vrf_id);
10562 vty_out(vty, "\n");
01eced22
AD
10563 vty_out(vty,
10564 "Default local pref %u, ",
10565 bgp->default_local_pref);
10566 vty_out(vty, "local AS %u\n",
10567 bgp->as);
ea47320b
DL
10568 vty_out(vty,
10569 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
10570 vty_out(vty,
10571 BGP_SHOW_NCODE_HEADER);
ea47320b
DL
10572 vty_out(vty,
10573 BGP_SHOW_OCODE_HEADER);
d62a17ae 10574 }
ea47320b
DL
10575 header1 = 0;
10576 }
10577 if (header2) {
10578 if (!use_json)
10579 vty_out(vty, BGP_SHOW_HEADER);
10580 header2 = 0;
10581 }
6392aaa6
PM
10582
10583 bgp_attr_dup(&attr, ain->attr);
f99def61
AD
10584 route_filtered = false;
10585
10586 /* Filter prefix using distribute list,
10587 * filter list or prefix list
10588 */
10589 if ((bgp_input_filter(peer, &rn->p, &attr, afi,
10590 safi)) == FILTER_DENY)
10591 route_filtered = true;
10592
10593 /* Filter prefix using route-map */
6392aaa6 10594 ret = bgp_input_modifier(peer, &rn->p, &attr,
13c8e163 10595 afi, safi, rmap_name);
6392aaa6 10596
13c8e163
AD
10597 if (type == bgp_show_adj_route_filtered &&
10598 !route_filtered && ret != RMAP_DENY) {
b755861b 10599 bgp_attr_undup(&attr, ain->attr);
6392aaa6 10600 continue;
d62a17ae 10601 }
6392aaa6 10602
13c8e163
AD
10603 if (type == bgp_show_adj_route_received &&
10604 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
10605 filtered_count++;
10606
10607 route_vty_out_tmp(vty, &rn->p, &attr, safi,
10608 use_json, json_ar);
b755861b 10609 bgp_attr_undup(&attr, ain->attr);
6392aaa6 10610 output_count++;
d62a17ae 10611 }
6392aaa6 10612 } else if (type == bgp_show_adj_route_advertised) {
a79c04e7 10613 RB_FOREACH (adj, bgp_adj_out_rb, &rn->adj_out)
924c3f6a 10614 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 10615 if (paf->peer != peer || !adj->attr)
924c3f6a 10616 continue;
d62a17ae 10617
924c3f6a
DS
10618 if (header1) {
10619 if (use_json) {
10620 json_object_int_add(
10621 json,
10622 "bgpTableVersion",
10623 table->version);
10624 json_object_string_add(
10625 json,
10626 "bgpLocalRouterId",
10627 inet_ntoa(
10628 bgp->router_id));
01eced22
AD
10629 json_object_int_add(
10630 json, "defaultLocPrf",
10631 bgp->default_local_pref
10632 );
10633 json_object_int_add(
10634 json, "localAS",
10635 bgp->as);
924c3f6a
DS
10636 json_object_object_add(
10637 json,
10638 "bgpStatusCodes",
10639 json_scode);
10640 json_object_object_add(
10641 json,
10642 "bgpOriginCodes",
10643 json_ocode);
10644 } else {
10645 vty_out(vty,
10646 "BGP table version is %" PRIu64
9df8b37c 10647 ", local router ID is %s, vrf id ",
924c3f6a
DS
10648 table->version,
10649 inet_ntoa(
10650 bgp->router_id));
9df8b37c
PZ
10651 if (bgp->vrf_id ==
10652 VRF_UNKNOWN)
10653 vty_out(vty,
10654 "%s",
10655 VRFID_NONE_STR);
10656 else
10657 vty_out(vty,
10658 "%u",
10659 bgp->vrf_id);
10660 vty_out(vty, "\n");
01eced22
AD
10661 vty_out(vty,
10662 "Default local pref %u, ",
10663 bgp->default_local_pref
10664 );
10665 vty_out(vty,
10666 "local AS %u\n",
10667 bgp->as);
924c3f6a
DS
10668 vty_out(vty,
10669 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
10670 vty_out(vty,
10671 BGP_SHOW_NCODE_HEADER);
924c3f6a
DS
10672 vty_out(vty,
10673 BGP_SHOW_OCODE_HEADER);
a2addae8 10674 }
924c3f6a
DS
10675 header1 = 0;
10676 }
924c3f6a
DS
10677 if (header2) {
10678 if (!use_json)
10679 vty_out(vty,
10680 BGP_SHOW_HEADER);
10681 header2 = 0;
10682 }
d62a17ae 10683
b755861b
PM
10684 bgp_attr_dup(&attr, adj->attr);
10685 ret = bgp_output_modifier(
10686 peer, &rn->p, &attr, afi, safi,
10687 rmap_name);
f46d8e1e 10688
b755861b
PM
10689 if (ret != RMAP_DENY) {
10690 route_vty_out_tmp(vty, &rn->p,
10691 &attr, safi,
10692 use_json,
10693 json_ar);
10694 output_count++;
10695 } else {
10696 filtered_count++;
a2addae8 10697 }
b755861b
PM
10698
10699 bgp_attr_undup(&attr, adj->attr);
924c3f6a 10700 }
d62a17ae 10701 }
10702 }
d62a17ae 10703
d62a17ae 10704 if (use_json) {
6392aaa6
PM
10705 json_object_object_add(json, "advertisedRoutes", json_ar);
10706 json_object_int_add(json, "totalPrefixCounter", output_count);
10707 json_object_int_add(json, "filteredPrefixCounter",
10708 filtered_count);
10709
996c9314
LB
10710 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10711 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 10712 json_object_free(json);
6392aaa6
PM
10713 } else if (output_count > 0) {
10714 if (filtered_count > 0)
10715 vty_out(vty,
10716 "\nTotal number of prefixes %ld (%ld filtered)\n",
10717 output_count, filtered_count);
10718 else
10719 vty_out(vty, "\nTotal number of prefixes %ld\n",
10720 output_count);
d62a17ae 10721 }
a636c635 10722}
2a71e9ce 10723
d62a17ae 10724static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 10725 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 10726 const char *rmap_name, bool use_json)
0b16f239 10727{
d62a17ae 10728 json_object *json = NULL;
0b16f239 10729
d62a17ae 10730 if (use_json)
10731 json = json_object_new_object();
0b16f239 10732
d62a17ae 10733 /* labeled-unicast routes live in the unicast table */
10734 if (safi == SAFI_LABELED_UNICAST)
10735 safi = SAFI_UNICAST;
4dd6177e 10736
d62a17ae 10737 if (!peer || !peer->afc[afi][safi]) {
10738 if (use_json) {
10739 json_object_string_add(
10740 json, "warning",
10741 "No such neighbor or address family");
10742 vty_out(vty, "%s\n", json_object_to_json_string(json));
10743 json_object_free(json);
10744 } else
10745 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 10746
d62a17ae 10747 return CMD_WARNING;
10748 }
10749
6392aaa6
PM
10750 if ((type == bgp_show_adj_route_received
10751 || type == bgp_show_adj_route_filtered)
d62a17ae 10752 && !CHECK_FLAG(peer->af_flags[afi][safi],
10753 PEER_FLAG_SOFT_RECONFIG)) {
10754 if (use_json) {
10755 json_object_string_add(
10756 json, "warning",
10757 "Inbound soft reconfiguration not enabled");
10758 vty_out(vty, "%s\n", json_object_to_json_string(json));
10759 json_object_free(json);
10760 } else
10761 vty_out(vty,
10762 "%% Inbound soft reconfiguration not enabled\n");
10763
10764 return CMD_WARNING;
10765 }
0b16f239 10766
6392aaa6 10767 show_adj_route(vty, peer, afi, safi, type, rmap_name, use_json, json);
0b16f239 10768
d62a17ae 10769 return CMD_SUCCESS;
a636c635 10770}
50ef26d4 10771
a636c635
DW
10772DEFUN (show_ip_bgp_instance_neighbor_advertised_route,
10773 show_ip_bgp_instance_neighbor_advertised_route_cmd,
4dd6177e 10774 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
6392aaa6 10775 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
718e3744 10776 SHOW_STR
10777 IP_STR
10778 BGP_STR
a636c635 10779 BGP_INSTANCE_HELP_STR
7395a2c9 10780 BGP_AFI_HELP_STR
4dd6177e 10781 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 10782 "Detailed information on TCP and BGP neighbor connections\n"
10783 "Neighbor to display information about\n"
10784 "Neighbor to display information about\n"
91d37724 10785 "Neighbor on BGP configured interface\n"
a636c635 10786 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
10787 "Display the received routes from neighbor\n"
10788 "Display the filtered routes received from neighbor\n"
a636c635
DW
10789 "Route-map to modify the attributes\n"
10790 "Name of the route map\n"
9973d184 10791 JSON_STR)
718e3744 10792{
d62a17ae 10793 afi_t afi = AFI_IP6;
10794 safi_t safi = SAFI_UNICAST;
10795 char *rmap_name = NULL;
10796 char *peerstr = NULL;
d62a17ae 10797 struct bgp *bgp = NULL;
10798 struct peer *peer;
6392aaa6 10799 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 10800 int idx = 0;
9f049418 10801 bool uj = use_json(argc, argv);
6392aaa6 10802
d62a17ae 10803 if (uj)
10804 argc--;
30a6a167 10805
9f049418
DS
10806 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10807 &bgp, uj);
10808 if (!idx)
10809 return CMD_WARNING;
10810
d62a17ae 10811 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10812 argv_find(argv, argc, "neighbors", &idx);
10813 peerstr = argv[++idx]->arg;
8c3deaae 10814
d62a17ae 10815 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
10816 if (!peer)
10817 return CMD_WARNING;
856ca177 10818
d62a17ae 10819 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
10820 type = bgp_show_adj_route_advertised;
10821 else if (argv_find(argv, argc, "received-routes", &idx))
10822 type = bgp_show_adj_route_received;
10823 else if (argv_find(argv, argc, "filtered-routes", &idx))
10824 type = bgp_show_adj_route_filtered;
10825
d62a17ae 10826 if (argv_find(argv, argc, "route-map", &idx))
10827 rmap_name = argv[++idx]->arg;
95cbbd2a 10828
6392aaa6 10829 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj);
95cbbd2a
ML
10830}
10831
718e3744 10832DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
10833 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 10834 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 10835 SHOW_STR
10836 IP_STR
10837 BGP_STR
8c3deaae
QY
10838 "Address Family\n"
10839 "Address Family\n"
718e3744 10840 "Address Family modifier\n"
10841 "Detailed information on TCP and BGP neighbor connections\n"
10842 "Neighbor to display information about\n"
10843 "Neighbor to display information about\n"
91d37724 10844 "Neighbor on BGP configured interface\n"
718e3744 10845 "Display information received from a BGP neighbor\n"
856ca177 10846 "Display the prefixlist filter\n"
9973d184 10847 JSON_STR)
718e3744 10848{
d62a17ae 10849 afi_t afi = AFI_IP6;
10850 safi_t safi = SAFI_UNICAST;
10851 char *peerstr = NULL;
10852
10853 char name[BUFSIZ];
10854 union sockunion su;
10855 struct peer *peer;
10856 int count, ret;
10857
10858 int idx = 0;
10859
10860 /* show [ip] bgp */
10861 if (argv_find(argv, argc, "ip", &idx))
10862 afi = AFI_IP;
10863 /* [<ipv4|ipv6> [unicast]] */
10864 if (argv_find(argv, argc, "ipv4", &idx))
10865 afi = AFI_IP;
10866 if (argv_find(argv, argc, "ipv6", &idx))
10867 afi = AFI_IP6;
10868 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10869 argv_find(argv, argc, "neighbors", &idx);
10870 peerstr = argv[++idx]->arg;
10871
9f049418 10872 bool uj = use_json(argc, argv);
d62a17ae 10873
10874 ret = str2sockunion(peerstr, &su);
10875 if (ret < 0) {
10876 peer = peer_lookup_by_conf_if(NULL, peerstr);
10877 if (!peer) {
10878 if (uj)
10879 vty_out(vty, "{}\n");
10880 else
10881 vty_out(vty,
10882 "%% Malformed address or name: %s\n",
10883 peerstr);
10884 return CMD_WARNING;
10885 }
10886 } else {
10887 peer = peer_lookup(NULL, &su);
10888 if (!peer) {
10889 if (uj)
10890 vty_out(vty, "{}\n");
10891 else
10892 vty_out(vty, "No peer\n");
10893 return CMD_WARNING;
10894 }
10895 }
718e3744 10896
d62a17ae 10897 sprintf(name, "%s.%d.%d", peer->host, afi, safi);
10898 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
10899 if (count) {
10900 if (!uj)
10901 vty_out(vty, "Address Family: %s\n",
10902 afi_safi_print(afi, safi));
10903 prefix_bgp_show_prefix_list(vty, afi, name, uj);
10904 } else {
10905 if (uj)
10906 vty_out(vty, "{}\n");
10907 else
10908 vty_out(vty, "No functional output\n");
10909 }
718e3744 10910
d62a17ae 10911 return CMD_SUCCESS;
10912}
10913
10914static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
10915 afi_t afi, safi_t safi,
9f049418 10916 enum bgp_show_type type, bool use_json)
d62a17ae 10917{
8a893163
DW
10918 /* labeled-unicast routes live in the unicast table */
10919 if (safi == SAFI_LABELED_UNICAST)
10920 safi = SAFI_UNICAST;
10921
d62a17ae 10922 if (!peer || !peer->afc[afi][safi]) {
10923 if (use_json) {
10924 json_object *json_no = NULL;
10925 json_no = json_object_new_object();
10926 json_object_string_add(
10927 json_no, "warning",
10928 "No such neighbor or address family");
10929 vty_out(vty, "%s\n",
10930 json_object_to_json_string(json_no));
10931 json_object_free(json_no);
10932 } else
10933 vty_out(vty, "%% No such neighbor or address family\n");
10934 return CMD_WARNING;
10935 }
47fc97cc 10936
d62a17ae 10937 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json);
718e3744 10938}
10939
dba3c1d3
PG
10940DEFUN (show_ip_bgp_flowspec_routes_detailed,
10941 show_ip_bgp_flowspec_routes_detailed_cmd,
10942 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
10943 SHOW_STR
10944 IP_STR
10945 BGP_STR
10946 BGP_INSTANCE_HELP_STR
10947 BGP_AFI_HELP_STR
10948 "SAFI Flowspec\n"
10949 "Detailed information on flowspec entries\n"
10950 JSON_STR)
10951{
10952 afi_t afi = AFI_IP;
10953 safi_t safi = SAFI_UNICAST;
10954 struct bgp *bgp = NULL;
10955 int idx = 0;
9f049418
DS
10956 bool uj = use_json(argc, argv);
10957
10958 if (uj)
10959 argc--;
dba3c1d3
PG
10960
10961 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10962 &bgp, uj);
dba3c1d3
PG
10963 if (!idx)
10964 return CMD_WARNING;
10965
9f049418 10966 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL, uj);
dba3c1d3
PG
10967}
10968
718e3744 10969DEFUN (show_ip_bgp_neighbor_routes,
10970 show_ip_bgp_neighbor_routes_cmd,
4dd6177e 10971 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
30a6a167 10972 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
50ef26d4 10973 SHOW_STR
10974 IP_STR
10975 BGP_STR
8386ac43 10976 BGP_INSTANCE_HELP_STR
4f280b15 10977 BGP_AFI_HELP_STR
4dd6177e 10978 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 10979 "Detailed information on TCP and BGP neighbor connections\n"
10980 "Neighbor to display information about\n"
10981 "Neighbor to display information about\n"
91d37724 10982 "Neighbor on BGP configured interface\n"
2525cf39 10983 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
10984 "Display the dampened routes received from neighbor\n"
10985 "Display routes learned from neighbor\n"
9973d184 10986 JSON_STR)
718e3744 10987{
d62a17ae 10988 char *peerstr = NULL;
10989 struct bgp *bgp = NULL;
10990 afi_t afi = AFI_IP6;
10991 safi_t safi = SAFI_UNICAST;
10992 struct peer *peer;
10993 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 10994 int idx = 0;
9f049418
DS
10995 bool uj = use_json(argc, argv);
10996
10997 if (uj)
10998 argc--;
bb46e94f 10999
d62a17ae 11000 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11001 &bgp, uj);
d62a17ae 11002 if (!idx)
11003 return CMD_WARNING;
c493f2d8 11004
d62a17ae 11005 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11006 argv_find(argv, argc, "neighbors", &idx);
11007 peerstr = argv[++idx]->arg;
8c3deaae 11008
d62a17ae 11009 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 11010 if (!peer)
d62a17ae 11011 return CMD_WARNING;
bb46e94f 11012
d62a17ae 11013 if (argv_find(argv, argc, "flap-statistics", &idx))
11014 sh_type = bgp_show_type_flap_neighbor;
11015 else if (argv_find(argv, argc, "dampened-routes", &idx))
11016 sh_type = bgp_show_type_damp_neighbor;
11017 else if (argv_find(argv, argc, "routes", &idx))
11018 sh_type = bgp_show_type_neighbor;
2525cf39 11019
d62a17ae 11020 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 11021}
6b0655a2 11022
734b349e 11023struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 11024
d62a17ae 11025struct bgp_distance {
11026 /* Distance value for the IP source prefix. */
d7c0a89a 11027 uint8_t distance;
718e3744 11028
d62a17ae 11029 /* Name of the access-list to be matched. */
11030 char *access_list;
718e3744 11031};
11032
4f280b15
LB
11033DEFUN (show_bgp_afi_vpn_rd_route,
11034 show_bgp_afi_vpn_rd_route_cmd,
d114b977 11035 "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
11036 SHOW_STR
11037 BGP_STR
11038 BGP_AFI_HELP_STR
11039 "Address Family modifier\n"
11040 "Display information for a route distinguisher\n"
11041 "Route Distinguisher\n"
7395a2c9
DS
11042 "Network in the BGP routing table to display\n"
11043 "Network in the BGP routing table to display\n"
11044 JSON_STR)
4f280b15 11045{
d62a17ae 11046 int ret;
11047 struct prefix_rd prd;
11048 afi_t afi = AFI_MAX;
11049 int idx = 0;
4f280b15 11050
ff6566f3
DS
11051 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
11052 vty_out(vty, "%% Malformed Address Family\n");
11053 return CMD_WARNING;
11054 }
11055
d62a17ae 11056 ret = str2prefix_rd(argv[5]->arg, &prd);
11057 if (!ret) {
11058 vty_out(vty, "%% Malformed Route Distinguisher\n");
11059 return CMD_WARNING;
11060 }
ff6566f3 11061
d62a17ae 11062 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 11063 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
11064}
11065
d62a17ae 11066static struct bgp_distance *bgp_distance_new(void)
718e3744 11067{
d62a17ae 11068 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 11069}
11070
d62a17ae 11071static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 11072{
d62a17ae 11073 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 11074}
11075
d62a17ae 11076static int bgp_distance_set(struct vty *vty, const char *distance_str,
11077 const char *ip_str, const char *access_list_str)
718e3744 11078{
d62a17ae 11079 int ret;
11080 afi_t afi;
11081 safi_t safi;
11082 struct prefix p;
d7c0a89a 11083 uint8_t distance;
d62a17ae 11084 struct bgp_node *rn;
11085 struct bgp_distance *bdistance;
718e3744 11086
d62a17ae 11087 afi = bgp_node_afi(vty);
11088 safi = bgp_node_safi(vty);
734b349e 11089
d62a17ae 11090 ret = str2prefix(ip_str, &p);
11091 if (ret == 0) {
11092 vty_out(vty, "Malformed prefix\n");
11093 return CMD_WARNING_CONFIG_FAILED;
11094 }
718e3744 11095
d62a17ae 11096 distance = atoi(distance_str);
718e3744 11097
d62a17ae 11098 /* Get BGP distance node. */
11099 rn = bgp_node_get(bgp_distance_table[afi][safi], (struct prefix *)&p);
5b00b40e 11100 bdistance = bgp_node_get_bgp_distance_info(rn);
ca2e160d 11101 if (bdistance)
d62a17ae 11102 bgp_unlock_node(rn);
ca2e160d 11103 else {
d62a17ae 11104 bdistance = bgp_distance_new();
5b00b40e 11105 bgp_node_set_bgp_distance_info(rn, bdistance);
d62a17ae 11106 }
718e3744 11107
d62a17ae 11108 /* Set distance value. */
11109 bdistance->distance = distance;
718e3744 11110
d62a17ae 11111 /* Reset access-list configuration. */
11112 if (bdistance->access_list) {
11113 XFREE(MTYPE_AS_LIST, bdistance->access_list);
11114 bdistance->access_list = NULL;
11115 }
11116 if (access_list_str)
11117 bdistance->access_list =
11118 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 11119
d62a17ae 11120 return CMD_SUCCESS;
718e3744 11121}
11122
d62a17ae 11123static int bgp_distance_unset(struct vty *vty, const char *distance_str,
11124 const char *ip_str, const char *access_list_str)
718e3744 11125{
d62a17ae 11126 int ret;
11127 afi_t afi;
11128 safi_t safi;
11129 struct prefix p;
11130 int distance;
11131 struct bgp_node *rn;
11132 struct bgp_distance *bdistance;
718e3744 11133
d62a17ae 11134 afi = bgp_node_afi(vty);
11135 safi = bgp_node_safi(vty);
734b349e 11136
d62a17ae 11137 ret = str2prefix(ip_str, &p);
11138 if (ret == 0) {
11139 vty_out(vty, "Malformed prefix\n");
11140 return CMD_WARNING_CONFIG_FAILED;
11141 }
718e3744 11142
d62a17ae 11143 rn = bgp_node_lookup(bgp_distance_table[afi][safi],
11144 (struct prefix *)&p);
11145 if (!rn) {
11146 vty_out(vty, "Can't find specified prefix\n");
11147 return CMD_WARNING_CONFIG_FAILED;
11148 }
718e3744 11149
5b00b40e 11150 bdistance = bgp_node_get_bgp_distance_info(rn);
d62a17ae 11151 distance = atoi(distance_str);
1f9a9fff 11152
d62a17ae 11153 if (bdistance->distance != distance) {
11154 vty_out(vty, "Distance does not match configured\n");
11155 return CMD_WARNING_CONFIG_FAILED;
11156 }
718e3744 11157
d62a17ae 11158 if (bdistance->access_list)
11159 XFREE(MTYPE_AS_LIST, bdistance->access_list);
11160 bgp_distance_free(bdistance);
718e3744 11161
6f94b685 11162 bgp_node_set_bgp_path_info(rn, NULL);
d62a17ae 11163 bgp_unlock_node(rn);
11164 bgp_unlock_node(rn);
718e3744 11165
d62a17ae 11166 return CMD_SUCCESS;
718e3744 11167}
11168
718e3744 11169/* Apply BGP information to distance method. */
40381db7 11170uint8_t bgp_distance_apply(struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 11171 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 11172{
11173 struct bgp_node *rn;
11174 struct prefix q;
11175 struct peer *peer;
11176 struct bgp_distance *bdistance;
11177 struct access_list *alist;
11178 struct bgp_static *bgp_static;
11179
11180 if (!bgp)
11181 return 0;
11182
40381db7 11183 peer = pinfo->peer;
d62a17ae 11184
11185 /* Check source address. */
11186 sockunion2hostprefix(&peer->su, &q);
11187 rn = bgp_node_match(bgp_distance_table[afi][safi], &q);
11188 if (rn) {
5b00b40e 11189 bdistance = bgp_node_get_bgp_distance_info(rn);
d62a17ae 11190 bgp_unlock_node(rn);
11191
11192 if (bdistance->access_list) {
11193 alist = access_list_lookup(afi, bdistance->access_list);
11194 if (alist
11195 && access_list_apply(alist, p) == FILTER_PERMIT)
11196 return bdistance->distance;
11197 } else
11198 return bdistance->distance;
718e3744 11199 }
718e3744 11200
d62a17ae 11201 /* Backdoor check. */
11202 rn = bgp_node_lookup(bgp->route[afi][safi], p);
11203 if (rn) {
5a8ba9fc 11204 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 11205 bgp_unlock_node(rn);
718e3744 11206
d62a17ae 11207 if (bgp_static->backdoor) {
11208 if (bgp->distance_local[afi][safi])
11209 return bgp->distance_local[afi][safi];
11210 else
11211 return ZEBRA_IBGP_DISTANCE_DEFAULT;
11212 }
718e3744 11213 }
718e3744 11214
d62a17ae 11215 if (peer->sort == BGP_PEER_EBGP) {
11216 if (bgp->distance_ebgp[afi][safi])
11217 return bgp->distance_ebgp[afi][safi];
11218 return ZEBRA_EBGP_DISTANCE_DEFAULT;
11219 } else {
11220 if (bgp->distance_ibgp[afi][safi])
11221 return bgp->distance_ibgp[afi][safi];
11222 return ZEBRA_IBGP_DISTANCE_DEFAULT;
11223 }
718e3744 11224}
11225
11226DEFUN (bgp_distance,
11227 bgp_distance_cmd,
6147e2c6 11228 "distance bgp (1-255) (1-255) (1-255)",
718e3744 11229 "Define an administrative distance\n"
11230 "BGP distance\n"
11231 "Distance for routes external to the AS\n"
11232 "Distance for routes internal to the AS\n"
11233 "Distance for local routes\n")
11234{
d62a17ae 11235 VTY_DECLVAR_CONTEXT(bgp, bgp);
11236 int idx_number = 2;
11237 int idx_number_2 = 3;
11238 int idx_number_3 = 4;
11239 afi_t afi;
11240 safi_t safi;
718e3744 11241
d62a17ae 11242 afi = bgp_node_afi(vty);
11243 safi = bgp_node_safi(vty);
718e3744 11244
d62a17ae 11245 bgp->distance_ebgp[afi][safi] = atoi(argv[idx_number]->arg);
11246 bgp->distance_ibgp[afi][safi] = atoi(argv[idx_number_2]->arg);
11247 bgp->distance_local[afi][safi] = atoi(argv[idx_number_3]->arg);
11248 return CMD_SUCCESS;
718e3744 11249}
11250
11251DEFUN (no_bgp_distance,
11252 no_bgp_distance_cmd,
a636c635 11253 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 11254 NO_STR
11255 "Define an administrative distance\n"
11256 "BGP distance\n"
11257 "Distance for routes external to the AS\n"
11258 "Distance for routes internal to the AS\n"
11259 "Distance for local routes\n")
11260{
d62a17ae 11261 VTY_DECLVAR_CONTEXT(bgp, bgp);
11262 afi_t afi;
11263 safi_t safi;
718e3744 11264
d62a17ae 11265 afi = bgp_node_afi(vty);
11266 safi = bgp_node_safi(vty);
718e3744 11267
d62a17ae 11268 bgp->distance_ebgp[afi][safi] = 0;
11269 bgp->distance_ibgp[afi][safi] = 0;
11270 bgp->distance_local[afi][safi] = 0;
11271 return CMD_SUCCESS;
718e3744 11272}
11273
718e3744 11274
11275DEFUN (bgp_distance_source,
11276 bgp_distance_source_cmd,
6147e2c6 11277 "distance (1-255) A.B.C.D/M",
718e3744 11278 "Define an administrative distance\n"
11279 "Administrative distance\n"
11280 "IP source prefix\n")
11281{
d62a17ae 11282 int idx_number = 1;
11283 int idx_ipv4_prefixlen = 2;
11284 bgp_distance_set(vty, argv[idx_number]->arg,
11285 argv[idx_ipv4_prefixlen]->arg, NULL);
11286 return CMD_SUCCESS;
718e3744 11287}
11288
11289DEFUN (no_bgp_distance_source,
11290 no_bgp_distance_source_cmd,
6147e2c6 11291 "no distance (1-255) A.B.C.D/M",
718e3744 11292 NO_STR
11293 "Define an administrative distance\n"
11294 "Administrative distance\n"
11295 "IP source prefix\n")
11296{
d62a17ae 11297 int idx_number = 2;
11298 int idx_ipv4_prefixlen = 3;
11299 bgp_distance_unset(vty, argv[idx_number]->arg,
11300 argv[idx_ipv4_prefixlen]->arg, NULL);
11301 return CMD_SUCCESS;
718e3744 11302}
11303
11304DEFUN (bgp_distance_source_access_list,
11305 bgp_distance_source_access_list_cmd,
6147e2c6 11306 "distance (1-255) A.B.C.D/M WORD",
718e3744 11307 "Define an administrative distance\n"
11308 "Administrative distance\n"
11309 "IP source prefix\n"
11310 "Access list name\n")
11311{
d62a17ae 11312 int idx_number = 1;
11313 int idx_ipv4_prefixlen = 2;
11314 int idx_word = 3;
11315 bgp_distance_set(vty, argv[idx_number]->arg,
11316 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
11317 return CMD_SUCCESS;
718e3744 11318}
11319
11320DEFUN (no_bgp_distance_source_access_list,
11321 no_bgp_distance_source_access_list_cmd,
6147e2c6 11322 "no distance (1-255) A.B.C.D/M WORD",
718e3744 11323 NO_STR
11324 "Define an administrative distance\n"
11325 "Administrative distance\n"
11326 "IP source prefix\n"
11327 "Access list name\n")
11328{
d62a17ae 11329 int idx_number = 2;
11330 int idx_ipv4_prefixlen = 3;
11331 int idx_word = 4;
11332 bgp_distance_unset(vty, argv[idx_number]->arg,
11333 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
11334 return CMD_SUCCESS;
718e3744 11335}
6b0655a2 11336
734b349e
MZ
11337DEFUN (ipv6_bgp_distance_source,
11338 ipv6_bgp_distance_source_cmd,
39e92c06 11339 "distance (1-255) X:X::X:X/M",
734b349e
MZ
11340 "Define an administrative distance\n"
11341 "Administrative distance\n"
11342 "IP source prefix\n")
11343{
d62a17ae 11344 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
11345 return CMD_SUCCESS;
734b349e
MZ
11346}
11347
11348DEFUN (no_ipv6_bgp_distance_source,
11349 no_ipv6_bgp_distance_source_cmd,
39e92c06 11350 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
11351 NO_STR
11352 "Define an administrative distance\n"
11353 "Administrative distance\n"
11354 "IP source prefix\n")
11355{
d62a17ae 11356 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
11357 return CMD_SUCCESS;
734b349e
MZ
11358}
11359
11360DEFUN (ipv6_bgp_distance_source_access_list,
11361 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 11362 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
11363 "Define an administrative distance\n"
11364 "Administrative distance\n"
11365 "IP source prefix\n"
11366 "Access list name\n")
11367{
d62a17ae 11368 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
11369 return CMD_SUCCESS;
734b349e
MZ
11370}
11371
11372DEFUN (no_ipv6_bgp_distance_source_access_list,
11373 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 11374 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
11375 NO_STR
11376 "Define an administrative distance\n"
11377 "Administrative distance\n"
11378 "IP source prefix\n"
11379 "Access list name\n")
11380{
d62a17ae 11381 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
11382 return CMD_SUCCESS;
734b349e
MZ
11383}
11384
718e3744 11385DEFUN (bgp_damp_set,
11386 bgp_damp_set_cmd,
31500417 11387 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 11388 "BGP Specific commands\n"
11389 "Enable route-flap dampening\n"
11390 "Half-life time for the penalty\n"
11391 "Value to start reusing a route\n"
11392 "Value to start suppressing a route\n"
11393 "Maximum duration to suppress a stable route\n")
11394{
d62a17ae 11395 VTY_DECLVAR_CONTEXT(bgp, bgp);
11396 int idx_half_life = 2;
11397 int idx_reuse = 3;
11398 int idx_suppress = 4;
11399 int idx_max_suppress = 5;
11400 int half = DEFAULT_HALF_LIFE * 60;
11401 int reuse = DEFAULT_REUSE;
11402 int suppress = DEFAULT_SUPPRESS;
11403 int max = 4 * half;
11404
11405 if (argc == 6) {
11406 half = atoi(argv[idx_half_life]->arg) * 60;
11407 reuse = atoi(argv[idx_reuse]->arg);
11408 suppress = atoi(argv[idx_suppress]->arg);
11409 max = atoi(argv[idx_max_suppress]->arg) * 60;
11410 } else if (argc == 3) {
11411 half = atoi(argv[idx_half_life]->arg) * 60;
11412 max = 4 * half;
11413 }
718e3744 11414
d62a17ae 11415 if (suppress < reuse) {
11416 vty_out(vty,
11417 "Suppress value cannot be less than reuse value \n");
11418 return 0;
11419 }
7ebe9748 11420
d62a17ae 11421 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
11422 reuse, suppress, max);
718e3744 11423}
11424
718e3744 11425DEFUN (bgp_damp_unset,
11426 bgp_damp_unset_cmd,
d04c479d 11427 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 11428 NO_STR
11429 "BGP Specific commands\n"
16cedbb0
QY
11430 "Enable route-flap dampening\n"
11431 "Half-life time for the penalty\n"
11432 "Value to start reusing a route\n"
11433 "Value to start suppressing a route\n"
11434 "Maximum duration to suppress a stable route\n")
718e3744 11435{
d62a17ae 11436 VTY_DECLVAR_CONTEXT(bgp, bgp);
11437 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 11438}
11439
718e3744 11440/* Display specified route of BGP table. */
d62a17ae 11441static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
11442 const char *ip_str, afi_t afi, safi_t safi,
11443 struct prefix_rd *prd, int prefix_check)
11444{
11445 int ret;
11446 struct prefix match;
11447 struct bgp_node *rn;
11448 struct bgp_node *rm;
40381db7
DS
11449 struct bgp_path_info *pi;
11450 struct bgp_path_info *pi_temp;
d62a17ae 11451 struct bgp *bgp;
11452 struct bgp_table *table;
11453
11454 /* BGP structure lookup. */
11455 if (view_name) {
11456 bgp = bgp_lookup_by_name(view_name);
11457 if (bgp == NULL) {
11458 vty_out(vty, "%% Can't find BGP instance %s\n",
11459 view_name);
11460 return CMD_WARNING;
11461 }
11462 } else {
11463 bgp = bgp_get_default();
11464 if (bgp == NULL) {
11465 vty_out(vty, "%% No BGP process is configured\n");
11466 return CMD_WARNING;
11467 }
718e3744 11468 }
718e3744 11469
d62a17ae 11470 /* Check IP address argument. */
11471 ret = str2prefix(ip_str, &match);
11472 if (!ret) {
11473 vty_out(vty, "%% address is malformed\n");
11474 return CMD_WARNING;
11475 }
718e3744 11476
d62a17ae 11477 match.family = afi2family(afi);
11478
11479 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
11480 || (safi == SAFI_EVPN)) {
11481 for (rn = bgp_table_top(bgp->rib[AFI_IP][safi]); rn;
11482 rn = bgp_route_next(rn)) {
11483 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
11484 continue;
67009e22
DS
11485 table = bgp_node_get_bgp_table_info(rn);
11486 if (!table)
ea47320b
DL
11487 continue;
11488 if ((rm = bgp_node_match(table, &match)) == NULL)
11489 continue;
d62a17ae 11490
ea47320b
DL
11491 if (!prefix_check
11492 || rm->p.prefixlen == match.prefixlen) {
6f94b685 11493 pi = bgp_node_get_bgp_path_info(rm);
40381db7
DS
11494 while (pi) {
11495 if (pi->extra && pi->extra->damp_info) {
11496 pi_temp = pi->next;
ea47320b 11497 bgp_damp_info_free(
40381db7 11498 pi->extra->damp_info,
60466a63 11499 1);
40381db7 11500 pi = pi_temp;
ea47320b 11501 } else
40381db7 11502 pi = pi->next;
d62a17ae 11503 }
ea47320b
DL
11504 }
11505
11506 bgp_unlock_node(rm);
d62a17ae 11507 }
11508 } else {
11509 if ((rn = bgp_node_match(bgp->rib[afi][safi], &match))
11510 != NULL) {
11511 if (!prefix_check
11512 || rn->p.prefixlen == match.prefixlen) {
6f94b685 11513 pi = bgp_node_get_bgp_path_info(rn);
40381db7
DS
11514 while (pi) {
11515 if (pi->extra && pi->extra->damp_info) {
11516 pi_temp = pi->next;
d62a17ae 11517 bgp_damp_info_free(
40381db7 11518 pi->extra->damp_info,
d62a17ae 11519 1);
40381db7 11520 pi = pi_temp;
d62a17ae 11521 } else
40381db7 11522 pi = pi->next;
d62a17ae 11523 }
11524 }
11525
11526 bgp_unlock_node(rn);
11527 }
11528 }
718e3744 11529
d62a17ae 11530 return CMD_SUCCESS;
718e3744 11531}
11532
11533DEFUN (clear_ip_bgp_dampening,
11534 clear_ip_bgp_dampening_cmd,
11535 "clear ip bgp dampening",
11536 CLEAR_STR
11537 IP_STR
11538 BGP_STR
11539 "Clear route flap dampening information\n")
11540{
d62a17ae 11541 bgp_damp_info_clean();
11542 return CMD_SUCCESS;
718e3744 11543}
11544
11545DEFUN (clear_ip_bgp_dampening_prefix,
11546 clear_ip_bgp_dampening_prefix_cmd,
11547 "clear ip bgp dampening A.B.C.D/M",
11548 CLEAR_STR
11549 IP_STR
11550 BGP_STR
11551 "Clear route flap dampening information\n"
0c7b1b01 11552 "IPv4 prefix\n")
718e3744 11553{
d62a17ae 11554 int idx_ipv4_prefixlen = 4;
11555 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
11556 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 11557}
11558
11559DEFUN (clear_ip_bgp_dampening_address,
11560 clear_ip_bgp_dampening_address_cmd,
11561 "clear ip bgp dampening A.B.C.D",
11562 CLEAR_STR
11563 IP_STR
11564 BGP_STR
11565 "Clear route flap dampening information\n"
11566 "Network to clear damping information\n")
11567{
d62a17ae 11568 int idx_ipv4 = 4;
11569 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
11570 SAFI_UNICAST, NULL, 0);
718e3744 11571}
11572
11573DEFUN (clear_ip_bgp_dampening_address_mask,
11574 clear_ip_bgp_dampening_address_mask_cmd,
11575 "clear ip bgp dampening A.B.C.D A.B.C.D",
11576 CLEAR_STR
11577 IP_STR
11578 BGP_STR
11579 "Clear route flap dampening information\n"
11580 "Network to clear damping information\n"
11581 "Network mask\n")
11582{
d62a17ae 11583 int idx_ipv4 = 4;
11584 int idx_ipv4_2 = 5;
11585 int ret;
11586 char prefix_str[BUFSIZ];
718e3744 11587
d62a17ae 11588 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
11589 prefix_str);
11590 if (!ret) {
11591 vty_out(vty, "%% Inconsistent address and mask\n");
11592 return CMD_WARNING;
11593 }
718e3744 11594
d62a17ae 11595 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
11596 NULL, 0);
718e3744 11597}
6b0655a2 11598
825d9834
DS
11599static void show_bgp_peerhash_entry(struct hash_backet *backet, void *arg)
11600{
11601 struct vty *vty = arg;
11602 struct peer *peer = backet->data;
11603 char buf[SU_ADDRSTRLEN];
11604
11605 vty_out(vty, "\tPeer: %s %s\n", peer->host,
11606 sockunion2str(&peer->su, buf, sizeof(buf)));
11607}
11608
11609DEFUN (show_bgp_peerhash,
11610 show_bgp_peerhash_cmd,
11611 "show bgp peerhash",
11612 SHOW_STR
11613 BGP_STR
11614 "Display information about the BGP peerhash\n")
11615{
11616 struct list *instances = bm->bgp;
11617 struct listnode *node;
11618 struct bgp *bgp;
11619
11620 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
11621 vty_out(vty, "BGP: %s\n", bgp->name);
11622 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
11623 vty);
11624 }
11625
11626 return CMD_SUCCESS;
11627}
11628
587ff0fd 11629/* also used for encap safi */
2b791107
DL
11630static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
11631 afi_t afi, safi_t safi)
d62a17ae 11632{
11633 struct bgp_node *prn;
11634 struct bgp_node *rn;
11635 struct bgp_table *table;
11636 struct prefix *p;
11637 struct prefix_rd *prd;
11638 struct bgp_static *bgp_static;
11639 mpls_label_t label;
11640 char buf[SU_ADDRSTRLEN];
11641 char rdbuf[RD_ADDRSTRLEN];
11642
11643 /* Network configuration. */
11644 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b 11645 prn = bgp_route_next(prn)) {
67009e22
DS
11646 table = bgp_node_get_bgp_table_info(prn);
11647 if (!table)
ea47320b 11648 continue;
d62a17ae 11649
60466a63 11650 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5a8ba9fc 11651 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 11652 if (bgp_static == NULL)
ea47320b 11653 continue;
d62a17ae 11654
ea47320b
DL
11655 p = &rn->p;
11656 prd = (struct prefix_rd *)&prn->p;
d62a17ae 11657
ea47320b 11658 /* "network" configuration display. */
06b9f471 11659 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
11660 label = decode_label(&bgp_static->label);
11661
11662 vty_out(vty, " network %s/%d rd %s",
11663 inet_ntop(p->family, &p->u.prefix, buf,
11664 SU_ADDRSTRLEN),
11665 p->prefixlen, rdbuf);
11666 if (safi == SAFI_MPLS_VPN)
11667 vty_out(vty, " label %u", label);
11668
11669 if (bgp_static->rmap.name)
11670 vty_out(vty, " route-map %s",
11671 bgp_static->rmap.name);
e2a86ad9
DS
11672
11673 if (bgp_static->backdoor)
11674 vty_out(vty, " backdoor");
11675
ea47320b
DL
11676 vty_out(vty, "\n");
11677 }
11678 }
d62a17ae 11679}
11680
2b791107
DL
11681static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
11682 afi_t afi, safi_t safi)
d62a17ae 11683{
11684 struct bgp_node *prn;
11685 struct bgp_node *rn;
11686 struct bgp_table *table;
11687 struct prefix *p;
11688 struct prefix_rd *prd;
11689 struct bgp_static *bgp_static;
ff44f570 11690 char buf[PREFIX_STRLEN * 2];
d62a17ae 11691 char buf2[SU_ADDRSTRLEN];
11692 char rdbuf[RD_ADDRSTRLEN];
11693
11694 /* Network configuration. */
11695 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b 11696 prn = bgp_route_next(prn)) {
67009e22
DS
11697 table = bgp_node_get_bgp_table_info(prn);
11698 if (!table)
ea47320b 11699 continue;
d62a17ae 11700
60466a63 11701 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5a8ba9fc 11702 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 11703 if (bgp_static == NULL)
ea47320b 11704 continue;
d62a17ae 11705
ea47320b
DL
11706 char *macrouter = NULL;
11707 char *esi = NULL;
d62a17ae 11708
ea47320b
DL
11709 if (bgp_static->router_mac)
11710 macrouter = prefix_mac2str(
11711 bgp_static->router_mac, NULL, 0);
11712 if (bgp_static->eth_s_id)
11713 esi = esi2str(bgp_static->eth_s_id);
11714 p = &rn->p;
11715 prd = (struct prefix_rd *)&prn->p;
d62a17ae 11716
ea47320b 11717 /* "network" configuration display. */
06b9f471 11718 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
11719 if (p->u.prefix_evpn.route_type == 5) {
11720 char local_buf[PREFIX_STRLEN];
3714a385 11721 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
11722 struct prefix_evpn *)p)
11723 ? AF_INET
11724 : AF_INET6;
3714a385 11725 inet_ntop(family,
11726 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a
PZ
11727 local_buf, PREFIX_STRLEN);
11728 sprintf(buf, "%s/%u", local_buf,
3714a385 11729 p->u.prefix_evpn.prefix_addr.ip_prefix_length);
197cb530
PG
11730 } else {
11731 prefix2str(p, buf, sizeof(buf));
11732 }
ea47320b 11733
a4d82a8a
PZ
11734 if (bgp_static->gatewayIp.family == AF_INET
11735 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
11736 inet_ntop(bgp_static->gatewayIp.family,
11737 &bgp_static->gatewayIp.u.prefix, buf2,
11738 sizeof(buf2));
ea47320b 11739 vty_out(vty,
7bcc8dac 11740 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 11741 buf, rdbuf,
11742 p->u.prefix_evpn.prefix_addr.eth_tag,
60466a63 11743 decode_label(&bgp_static->label), esi, buf2,
ea47320b
DL
11744 macrouter);
11745
11746 if (macrouter)
11747 XFREE(MTYPE_TMP, macrouter);
11748 if (esi)
11749 XFREE(MTYPE_TMP, esi);
11750 }
11751 }
3da6fcd5
PG
11752}
11753
718e3744 11754/* Configuration of static route announcement and aggregate
11755 information. */
2b791107
DL
11756void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
11757 safi_t safi)
d62a17ae 11758{
11759 struct bgp_node *rn;
11760 struct prefix *p;
11761 struct bgp_static *bgp_static;
11762 struct bgp_aggregate *bgp_aggregate;
11763 char buf[SU_ADDRSTRLEN];
11764
2b791107
DL
11765 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
11766 bgp_config_write_network_vpn(vty, bgp, afi, safi);
11767 return;
11768 }
d62a17ae 11769
2b791107
DL
11770 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
11771 bgp_config_write_network_evpn(vty, bgp, afi, safi);
11772 return;
11773 }
d62a17ae 11774
11775 /* Network configuration. */
11776 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
ea47320b 11777 rn = bgp_route_next(rn)) {
5a8ba9fc 11778 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 11779 if (bgp_static == NULL)
ea47320b 11780 continue;
d62a17ae 11781
ea47320b 11782 p = &rn->p;
d62a17ae 11783
ea47320b 11784 /* "network" configuration display. */
60466a63 11785 if (bgp_option_check(BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) {
d7c0a89a 11786 uint32_t destination;
ea47320b 11787 struct in_addr netmask;
d62a17ae 11788
ea47320b
DL
11789 destination = ntohl(p->u.prefix4.s_addr);
11790 masklen2ip(p->prefixlen, &netmask);
11791 vty_out(vty, " network %s",
11792 inet_ntop(p->family, &p->u.prefix, buf,
11793 SU_ADDRSTRLEN));
d62a17ae 11794
ea47320b
DL
11795 if ((IN_CLASSC(destination) && p->prefixlen == 24)
11796 || (IN_CLASSB(destination) && p->prefixlen == 16)
11797 || (IN_CLASSA(destination) && p->prefixlen == 8)
11798 || p->u.prefix4.s_addr == 0) {
11799 /* Natural mask is not display. */
11800 } else
11801 vty_out(vty, " mask %s", inet_ntoa(netmask));
11802 } else {
11803 vty_out(vty, " network %s/%d",
11804 inet_ntop(p->family, &p->u.prefix, buf,
11805 SU_ADDRSTRLEN),
11806 p->prefixlen);
11807 }
d62a17ae 11808
ea47320b
DL
11809 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
11810 vty_out(vty, " label-index %u",
11811 bgp_static->label_index);
d62a17ae 11812
ea47320b
DL
11813 if (bgp_static->rmap.name)
11814 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
11815
11816 if (bgp_static->backdoor)
11817 vty_out(vty, " backdoor");
718e3744 11818
ea47320b
DL
11819 vty_out(vty, "\n");
11820 }
11821
d62a17ae 11822 /* Aggregate-address configuration. */
11823 for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn;
ea47320b 11824 rn = bgp_route_next(rn)) {
b613a918 11825 bgp_aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 11826 if (bgp_aggregate == NULL)
ea47320b 11827 continue;
d62a17ae 11828
ea47320b 11829 p = &rn->p;
d62a17ae 11830
ea47320b
DL
11831 if (bgp_option_check(BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) {
11832 struct in_addr netmask;
d62a17ae 11833
ea47320b
DL
11834 masklen2ip(p->prefixlen, &netmask);
11835 vty_out(vty, " aggregate-address %s %s",
11836 inet_ntop(p->family, &p->u.prefix, buf,
11837 SU_ADDRSTRLEN),
11838 inet_ntoa(netmask));
11839 } else {
11840 vty_out(vty, " aggregate-address %s/%d",
11841 inet_ntop(p->family, &p->u.prefix, buf,
11842 SU_ADDRSTRLEN),
11843 p->prefixlen);
11844 }
d62a17ae 11845
ea47320b
DL
11846 if (bgp_aggregate->as_set)
11847 vty_out(vty, " as-set");
d62a17ae 11848
ea47320b
DL
11849 if (bgp_aggregate->summary_only)
11850 vty_out(vty, " summary-only");
718e3744 11851
ea47320b
DL
11852 vty_out(vty, "\n");
11853 }
d62a17ae 11854}
734b349e 11855
2b791107 11856void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 11857 safi_t safi)
d62a17ae 11858{
11859 struct bgp_node *rn;
11860 struct bgp_distance *bdistance;
11861
11862 /* Distance configuration. */
11863 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
11864 && bgp->distance_local[afi][safi]
11865 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
11866 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
11867 || bgp->distance_local[afi][safi]
11868 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 11869 vty_out(vty, " distance bgp %d %d %d\n",
11870 bgp->distance_ebgp[afi][safi],
11871 bgp->distance_ibgp[afi][safi],
11872 bgp->distance_local[afi][safi]);
11873 }
734b349e 11874
d62a17ae 11875 for (rn = bgp_table_top(bgp_distance_table[afi][safi]); rn;
ca2e160d 11876 rn = bgp_route_next(rn)) {
5b00b40e 11877 bdistance = bgp_node_get_bgp_distance_info(rn);
ca2e160d 11878 if (bdistance != NULL) {
d62a17ae 11879 char buf[PREFIX_STRLEN];
11880
d62a17ae 11881 vty_out(vty, " distance %d %s %s\n",
11882 bdistance->distance,
11883 prefix2str(&rn->p, buf, sizeof(buf)),
11884 bdistance->access_list ? bdistance->access_list
11885 : "");
11886 }
ca2e160d 11887 }
718e3744 11888}
11889
11890/* Allocate routing table structure and install commands. */
d62a17ae 11891void bgp_route_init(void)
11892{
11893 afi_t afi;
11894 safi_t safi;
11895
11896 /* Init BGP distance table. */
05c7a1cc 11897 FOREACH_AFI_SAFI (afi, safi)
960035b2 11898 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 11899
11900 /* IPv4 BGP commands. */
11901 install_element(BGP_NODE, &bgp_table_map_cmd);
11902 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 11903 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 11904
11905 install_element(BGP_NODE, &aggregate_address_cmd);
11906 install_element(BGP_NODE, &aggregate_address_mask_cmd);
11907 install_element(BGP_NODE, &no_aggregate_address_cmd);
11908 install_element(BGP_NODE, &no_aggregate_address_mask_cmd);
11909
11910 /* IPv4 unicast configuration. */
11911 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
11912 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 11913 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 11914
11915 install_element(BGP_IPV4_NODE, &aggregate_address_cmd);
11916 install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd);
11917 install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd);
11918 install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
11919
11920 /* IPv4 multicast configuration. */
11921 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
11922 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 11923 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
d62a17ae 11924 install_element(BGP_IPV4M_NODE, &aggregate_address_cmd);
11925 install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
11926 install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd);
11927 install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
11928
11929 /* IPv4 labeled-unicast configuration. */
11930 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
11931 install_element(VIEW_NODE, &show_ip_bgp_cmd);
7b2ff250 11932 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 11933 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
11934 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
11935
11936 install_element(VIEW_NODE,
11937 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
11938 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
11939 install_element(VIEW_NODE,
11940 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 11941#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 11942 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 11943#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 11944 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
11945 install_element(VIEW_NODE,
11946 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd);
57d187bc 11947
d62a17ae 11948 /* BGP dampening clear commands */
11949 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
11950 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 11951
d62a17ae 11952 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
11953 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
11954
11955 /* prefix count */
11956 install_element(ENABLE_NODE,
11957 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 11958#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 11959 install_element(ENABLE_NODE,
11960 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 11961#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 11962
d62a17ae 11963 /* New config IPv6 BGP commands. */
11964 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
11965 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 11966 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 11967
11968 install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
11969 install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
11970
11971 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 11972
d62a17ae 11973 install_element(BGP_NODE, &bgp_distance_cmd);
11974 install_element(BGP_NODE, &no_bgp_distance_cmd);
11975 install_element(BGP_NODE, &bgp_distance_source_cmd);
11976 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
11977 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
11978 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
11979 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
11980 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
11981 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
11982 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
11983 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
11984 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
11985 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
11986 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
11987 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
11988 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
11989 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
11990 install_element(BGP_IPV4M_NODE,
11991 &no_bgp_distance_source_access_list_cmd);
11992 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
11993 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
11994 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
11995 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
11996 install_element(BGP_IPV6_NODE,
11997 &ipv6_bgp_distance_source_access_list_cmd);
11998 install_element(BGP_IPV6_NODE,
11999 &no_ipv6_bgp_distance_source_access_list_cmd);
12000 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
12001 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
12002 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
12003 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
12004 install_element(BGP_IPV6M_NODE,
12005 &ipv6_bgp_distance_source_access_list_cmd);
12006 install_element(BGP_IPV6M_NODE,
12007 &no_ipv6_bgp_distance_source_access_list_cmd);
12008
12009 install_element(BGP_NODE, &bgp_damp_set_cmd);
12010 install_element(BGP_NODE, &bgp_damp_unset_cmd);
12011 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
12012 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
12013
12014 /* IPv4 Multicast Mode */
12015 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
12016 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
12017
12018 /* Large Communities */
12019 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
12020 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
12021
12022 /* show bgp ipv4 flowspec detailed */
12023 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
12024
825d9834 12025 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 12026}
12027
12028void bgp_route_finish(void)
12029{
12030 afi_t afi;
12031 safi_t safi;
12032
05c7a1cc
QY
12033 FOREACH_AFI_SAFI (afi, safi) {
12034 bgp_table_unlock(bgp_distance_table[afi][safi]);
12035 bgp_distance_table[afi][safi] = NULL;
12036 }
228da428 12037}