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