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