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