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