]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #5300 from ton31337/feature/add_a_test_case_for_sender-as-path...
[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
2618a52e 25#include "printfrr.h"
718e3744 26#include "prefix.h"
27#include "linklist.h"
28#include "memory.h"
29#include "command.h"
30#include "stream.h"
31#include "filter.h"
718e3744 32#include "log.h"
33#include "routemap.h"
34#include "buffer.h"
35#include "sockunion.h"
36#include "plist.h"
37#include "thread.h"
200df115 38#include "workqueue.h"
3f9c7369 39#include "queue.h"
6e919709 40#include "memory.h"
4dcadbef 41#include "lib/json.h"
d8d084d9 42#include "lib_errors.h"
718e3744 43
44#include "bgpd/bgpd.h"
45#include "bgpd/bgp_table.h"
46#include "bgpd/bgp_route.h"
47#include "bgpd/bgp_attr.h"
48#include "bgpd/bgp_debug.h"
14454c9f 49#include "bgpd/bgp_errors.h"
718e3744 50#include "bgpd/bgp_aspath.h"
51#include "bgpd/bgp_regex.h"
52#include "bgpd/bgp_community.h"
53#include "bgpd/bgp_ecommunity.h"
57d187bc 54#include "bgpd/bgp_lcommunity.h"
718e3744 55#include "bgpd/bgp_clist.h"
56#include "bgpd/bgp_packet.h"
57#include "bgpd/bgp_filter.h"
58#include "bgpd/bgp_fsm.h"
59#include "bgpd/bgp_mplsvpn.h"
60#include "bgpd/bgp_nexthop.h"
61#include "bgpd/bgp_damp.h"
62#include "bgpd/bgp_advertise.h"
63#include "bgpd/bgp_zebra.h"
0a486e5f 64#include "bgpd/bgp_vty.h"
96450faf 65#include "bgpd/bgp_mpath.h"
fc9a856f 66#include "bgpd/bgp_nht.h"
3f9c7369 67#include "bgpd/bgp_updgrp.h"
cd1964ff 68#include "bgpd/bgp_label.h"
dcc68b5e 69#include "bgpd/bgp_addpath.h"
4e802e66 70#include "bgpd/bgp_mac.h"
718e3744 71
65efcfce 72#if ENABLE_BGP_VNC
f8b6f499
LB
73#include "bgpd/rfapi/rfapi_backend.h"
74#include "bgpd/rfapi/vnc_import_bgp.h"
75#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 76#endif
aee875b5
PG
77#include "bgpd/bgp_encap_types.h"
78#include "bgpd/bgp_encap_tlv.h"
684a7227 79#include "bgpd/bgp_evpn.h"
3da6fcd5 80#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 81#include "bgpd/bgp_flowspec.h"
98a9dbc7 82#include "bgpd/bgp_flowspec_util.h"
45918cfb 83#include "bgpd/bgp_pbr.h"
65efcfce 84
e2a86ad9
DS
85#ifndef VTYSH_EXTRACT_PL
86#include "bgpd/bgp_route_clippy.c"
87#endif
aee875b5 88
718e3744 89/* Extern from bgp_dump.c */
dde72586
SH
90extern const char *bgp_origin_str[];
91extern const char *bgp_origin_long_str[];
6b0655a2 92
b7d08f5a 93/* PMSI strings. */
94#define PMSI_TNLTYPE_STR_NO_INFO "No info"
95#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
96static const struct message bgp_pmsi_tnltype_str[] = {
97 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
98 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
99 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
100 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
101 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
102 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
103 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
104 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 105 {0}
106};
b7d08f5a 107
9df8b37c
PZ
108#define VRFID_NONE_STR "-"
109
4a11bf2c
DL
110DEFINE_HOOK(bgp_process,
111 (struct bgp *bgp, afi_t afi, safi_t safi,
112 struct bgp_node *bn, struct peer *peer, bool withdraw),
113 (bgp, afi, safi, bn, peer, withdraw))
114
115
d62a17ae 116struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
117 safi_t safi, struct prefix *p,
118 struct prefix_rd *prd)
119{
120 struct bgp_node *rn;
121 struct bgp_node *prn = NULL;
122
123 assert(table);
124 if (!table)
125 return NULL;
126
127 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
128 || (safi == SAFI_EVPN)) {
129 prn = bgp_node_get(table, (struct prefix *)prd);
130
67009e22
DS
131 if (!bgp_node_has_bgp_path_info_data(prn))
132 bgp_node_set_bgp_table_info(
133 prn, bgp_table_init(table->bgp, afi, safi));
d62a17ae 134 else
135 bgp_unlock_node(prn);
67009e22 136 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 137 }
718e3744 138
d62a17ae 139 rn = bgp_node_get(table, p);
718e3744 140
d62a17ae 141 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
142 || (safi == SAFI_EVPN))
143 rn->prn = prn;
718e3744 144
d62a17ae 145 return rn;
718e3744 146}
6b0655a2 147
d62a17ae 148struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
149 safi_t safi, struct prefix *p,
150 struct prefix_rd *prd)
128ea8ab 151{
d62a17ae 152 struct bgp_node *rn;
153 struct bgp_node *prn = NULL;
128ea8ab 154
d62a17ae 155 if (!table)
156 return NULL;
128ea8ab 157
d62a17ae 158 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
159 || (safi == SAFI_EVPN)) {
160 prn = bgp_node_lookup(table, (struct prefix *)prd);
161 if (!prn)
162 return NULL;
128ea8ab 163
6f94b685 164 if (!bgp_node_has_bgp_path_info_data(prn)) {
d62a17ae 165 bgp_unlock_node(prn);
166 return NULL;
167 }
128ea8ab 168
67009e22 169 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 170 }
128ea8ab 171
d62a17ae 172 rn = bgp_node_lookup(table, p);
128ea8ab 173
d62a17ae 174 return rn;
128ea8ab 175}
176
18ee8310
DS
177/* Allocate bgp_path_info_extra */
178static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 179{
4b7e6066
DS
180 struct bgp_path_info_extra *new;
181 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
182 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
183 new->label[0] = MPLS_INVALID_LABEL;
184 new->num_labels = 0;
3e3708cb
PG
185 new->bgp_fs_pbr = NULL;
186 new->bgp_fs_iprule = NULL;
d62a17ae 187 return new;
fb982c25
PJ
188}
189
a2e219fe 190void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 191{
4b7e6066 192 struct bgp_path_info_extra *e;
d62a17ae 193
c93a3b77
DS
194 if (!extra || !*extra)
195 return;
d62a17ae 196
c93a3b77
DS
197 e = *extra;
198 if (e->damp_info)
a935f597
DA
199 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
200 e->damp_info->safi);
d62a17ae 201
c93a3b77
DS
202 e->damp_info = NULL;
203 if (e->parent) {
40381db7 204 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 205
40381db7 206 if (bpi->net) {
0e70e6c8
DL
207 /* FIXME: since multiple e may have the same e->parent
208 * and e->parent->net is holding a refcount for each
209 * of them, we need to do some fudging here.
210 *
40381db7
DS
211 * WARNING: if bpi->net->lock drops to 0, bpi may be
212 * freed as well (because bpi->net was holding the
213 * last reference to bpi) => write after free!
0e70e6c8
DL
214 */
215 unsigned refcount;
216
40381db7
DS
217 bpi = bgp_path_info_lock(bpi);
218 refcount = bpi->net->lock - 1;
219 bgp_unlock_node((struct bgp_node *)bpi->net);
0e70e6c8 220 if (!refcount)
40381db7
DS
221 bpi->net = NULL;
222 bgp_path_info_unlock(bpi);
0e70e6c8 223 }
18ee8310 224 bgp_path_info_unlock(e->parent);
c93a3b77 225 e->parent = NULL;
d62a17ae 226 }
c93a3b77
DS
227
228 if (e->bgp_orig)
229 bgp_unlock(e->bgp_orig);
c26edcda 230
ce3c0614
PG
231 if ((*extra)->bgp_fs_iprule)
232 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 233 if ((*extra)->bgp_fs_pbr)
6a154c88 234 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77
DS
235 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
236
237 *extra = NULL;
fb982c25
PJ
238}
239
18ee8310
DS
240/* Get bgp_path_info extra information for the given bgp_path_info, lazy
241 * allocated if required.
fb982c25 242 */
40381db7 243struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 244{
40381db7
DS
245 if (!pi->extra)
246 pi->extra = bgp_path_info_extra_new();
247 return pi->extra;
fb982c25
PJ
248}
249
718e3744 250/* Free bgp route information. */
9b6d8fcf 251static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 252{
05864da7 253 bgp_attr_unintern(&path->attr);
fb018d25 254
9b6d8fcf
DS
255 bgp_unlink_nexthop(path);
256 bgp_path_info_extra_free(&path->extra);
257 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
258 if (path->net)
259 bgp_addpath_free_info_data(&path->tx_addpath,
260 &path->net->tx_addpath);
718e3744 261
9b6d8fcf 262 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 263
9b6d8fcf 264 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 265}
266
9b6d8fcf 267struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 268{
9b6d8fcf
DS
269 path->lock++;
270 return path;
200df115 271}
272
9b6d8fcf 273struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 274{
9b6d8fcf
DS
275 assert(path && path->lock > 0);
276 path->lock--;
d62a17ae 277
9b6d8fcf 278 if (path->lock == 0) {
200df115 279#if 0
280 zlog_debug ("%s: unlocked and freeing", __func__);
281 zlog_backtrace (LOG_DEBUG);
282#endif
9b6d8fcf 283 bgp_path_info_free(path);
d62a17ae 284 return NULL;
285 }
200df115 286
287#if 0
9b6d8fcf 288 if (path->lock == 1)
200df115 289 {
290 zlog_debug ("%s: unlocked to 1", __func__);
291 zlog_backtrace (LOG_DEBUG);
292 }
293#endif
d62a17ae 294
9b6d8fcf 295 return path;
200df115 296}
297
40381db7 298void bgp_path_info_add(struct bgp_node *rn, struct bgp_path_info *pi)
718e3744 299{
4b7e6066 300 struct bgp_path_info *top;
718e3744 301
6f94b685 302 top = bgp_node_get_bgp_path_info(rn);
d62a17ae 303
6f94b685 304 pi->next = top;
40381db7 305 pi->prev = NULL;
d62a17ae 306 if (top)
40381db7 307 top->prev = pi;
6f94b685 308 bgp_node_set_bgp_path_info(rn, pi);
d62a17ae 309
40381db7 310 bgp_path_info_lock(pi);
d62a17ae 311 bgp_lock_node(rn);
40381db7 312 peer_lock(pi->peer); /* bgp_path_info peer reference */
718e3744 313}
314
d62a17ae 315/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 316 completion callback *only* */
40381db7 317void bgp_path_info_reap(struct bgp_node *rn, struct bgp_path_info *pi)
718e3744 318{
40381db7
DS
319 if (pi->next)
320 pi->next->prev = pi->prev;
321 if (pi->prev)
322 pi->prev->next = pi->next;
d62a17ae 323 else
6f94b685 324 bgp_node_set_bgp_path_info(rn, pi->next);
d62a17ae 325
40381db7
DS
326 bgp_path_info_mpath_dequeue(pi);
327 bgp_path_info_unlock(pi);
d62a17ae 328 bgp_unlock_node(rn);
718e3744 329}
330
40381db7 331void bgp_path_info_delete(struct bgp_node *rn, struct bgp_path_info *pi)
b40d939b 332{
40381db7 333 bgp_path_info_set_flag(rn, pi, BGP_PATH_REMOVED);
d62a17ae 334 /* set of previous already took care of pcount */
40381db7 335 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 336}
337
18ee8310 338/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
339 called when a route is deleted and then quickly re-added before the
340 deletion has been processed */
40381db7 341void bgp_path_info_restore(struct bgp_node *rn, struct bgp_path_info *pi)
8d45210e 342{
40381db7 343 bgp_path_info_unset_flag(rn, pi, BGP_PATH_REMOVED);
d62a17ae 344 /* unset of previous already took care of pcount */
40381db7 345 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
346}
347
d62a17ae 348/* Adjust pcount as required */
40381db7 349static void bgp_pcount_adjust(struct bgp_node *rn, struct bgp_path_info *pi)
1a392d46 350{
d62a17ae 351 struct bgp_table *table;
67174041 352
d62a17ae 353 assert(rn && bgp_node_table(rn));
40381db7 354 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 355
d62a17ae 356 table = bgp_node_table(rn);
67174041 357
40381db7 358 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 359 return;
360
40381db7
DS
361 if (!BGP_PATH_COUNTABLE(pi)
362 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 363
40381db7 364 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 365
366 /* slight hack, but more robust against errors. */
40381db7
DS
367 if (pi->peer->pcount[table->afi][table->safi])
368 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 369 else
450971aa 370 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 371 "Asked to decrement 0 prefix count for peer");
40381db7
DS
372 } else if (BGP_PATH_COUNTABLE(pi)
373 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
374 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
375 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 376 }
1a392d46
PJ
377}
378
40381db7
DS
379static int bgp_label_index_differs(struct bgp_path_info *pi1,
380 struct bgp_path_info *pi2)
28d58fd7 381{
40381db7 382 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 383}
1a392d46 384
18ee8310 385/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
386 * This is here primarily to keep prefix-count in check.
387 */
40381db7 388void bgp_path_info_set_flag(struct bgp_node *rn, struct bgp_path_info *pi,
18ee8310 389 uint32_t flag)
1a392d46 390{
40381db7 391 SET_FLAG(pi->flags, flag);
d62a17ae 392
393 /* early bath if we know it's not a flag that changes countability state
394 */
395 if (!CHECK_FLAG(flag,
1defdda8 396 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 397 return;
398
40381db7 399 bgp_pcount_adjust(rn, pi);
1a392d46
PJ
400}
401
40381db7 402void bgp_path_info_unset_flag(struct bgp_node *rn, struct bgp_path_info *pi,
18ee8310 403 uint32_t flag)
1a392d46 404{
40381db7 405 UNSET_FLAG(pi->flags, flag);
d62a17ae 406
407 /* early bath if we know it's not a flag that changes countability state
408 */
409 if (!CHECK_FLAG(flag,
1defdda8 410 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 411 return;
412
40381db7 413 bgp_pcount_adjust(rn, pi);
1a392d46
PJ
414}
415
718e3744 416/* Get MED value. If MED value is missing and "bgp bestpath
417 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 418static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 419{
420 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
421 return attr->med;
422 else {
423 if (bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST))
424 return BGP_MED_MAX;
425 else
426 return 0;
427 }
718e3744 428}
429
40381db7 430void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf)
2ec1e66f 431{
40381db7
DS
432 if (pi->addpath_rx_id)
433 sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
434 pi->addpath_rx_id);
d62a17ae 435 else
40381db7 436 sprintf(buf, "path %s", pi->peer->host);
d62a17ae 437}
9fbdd100 438
d62a17ae 439/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
440 */
18ee8310
DS
441static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
442 struct bgp_path_info *exist, int *paths_eq,
443 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
444 char *pfx_buf, afi_t afi, safi_t safi,
445 enum bgp_path_selection_reason *reason)
d62a17ae 446{
447 struct attr *newattr, *existattr;
448 bgp_peer_sort_t new_sort;
449 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
450 uint32_t new_pref;
451 uint32_t exist_pref;
452 uint32_t new_med;
453 uint32_t exist_med;
454 uint32_t new_weight;
455 uint32_t exist_weight;
d62a17ae 456 uint32_t newm, existm;
457 struct in_addr new_id;
458 struct in_addr exist_id;
459 int new_cluster;
460 int exist_cluster;
461 int internal_as_route;
462 int confed_as_route;
04d14c8b 463 int ret = 0;
d62a17ae 464 char new_buf[PATH_ADDPATH_STR_BUFFER];
465 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
466 uint32_t new_mm_seq;
467 uint32_t exist_mm_seq;
6d8c603a 468 int nh_cmp;
d62a17ae 469
470 *paths_eq = 0;
471
472 /* 0. Null check. */
473 if (new == NULL) {
fdf81fa0 474 *reason = bgp_path_selection_none;
d62a17ae 475 if (debug)
476 zlog_debug("%s: new is NULL", pfx_buf);
477 return 0;
478 }
2ec1e66f 479
d62a17ae 480 if (debug)
18ee8310 481 bgp_path_info_path_with_addpath_rx_str(new, new_buf);
718e3744 482
d62a17ae 483 if (exist == NULL) {
fdf81fa0 484 *reason = bgp_path_selection_first;
d62a17ae 485 if (debug)
486 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
487 new_buf);
488 return 1;
489 }
2ec1e66f 490
d62a17ae 491 if (debug) {
18ee8310 492 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
d62a17ae 493 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
494 pfx_buf, new_buf, new->flags, exist_buf,
495 exist->flags);
496 }
8ff56318 497
d62a17ae 498 newattr = new->attr;
499 existattr = exist->attr;
500
501 /* For EVPN routes, we cannot just go by local vs remote, we have to
502 * look at the MAC mobility sequence number, if present.
503 */
504 if (safi == SAFI_EVPN) {
505 /* This is an error condition described in RFC 7432 Section
506 * 15.2. The RFC
507 * states that in this scenario "the PE MUST alert the operator"
508 * but it
509 * does not state what other action to take. In order to provide
510 * some
511 * consistency in this scenario we are going to prefer the path
512 * with the
513 * sticky flag.
514 */
515 if (newattr->sticky != existattr->sticky) {
516 if (!debug) {
517 prefix2str(&new->net->p, pfx_buf,
518 sizeof(*pfx_buf)
519 * PREFIX2STR_BUFFER);
18ee8310
DS
520 bgp_path_info_path_with_addpath_rx_str(new,
521 new_buf);
522 bgp_path_info_path_with_addpath_rx_str(
523 exist, exist_buf);
d62a17ae 524 }
525
526 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 527 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
528 if (debug)
529 zlog_debug(
530 "%s: %s wins over %s due to sticky MAC flag",
531 pfx_buf, new_buf, exist_buf);
d62a17ae 532 return 1;
533 }
534
535 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 536 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
537 if (debug)
538 zlog_debug(
539 "%s: %s loses to %s due to sticky MAC flag",
540 pfx_buf, new_buf, exist_buf);
d62a17ae 541 return 0;
542 }
543 }
128ea8ab 544
d62a17ae 545 new_mm_seq = mac_mobility_seqnum(newattr);
546 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 547
d62a17ae 548 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 549 *reason = bgp_path_selection_evpn_seq;
d62a17ae 550 if (debug)
551 zlog_debug(
552 "%s: %s wins over %s due to MM seq %u > %u",
553 pfx_buf, new_buf, exist_buf, new_mm_seq,
554 exist_mm_seq);
555 return 1;
556 }
8ff56318 557
d62a17ae 558 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 559 *reason = bgp_path_selection_evpn_seq;
d62a17ae 560 if (debug)
561 zlog_debug(
562 "%s: %s loses to %s due to MM seq %u < %u",
563 pfx_buf, new_buf, exist_buf, new_mm_seq,
564 exist_mm_seq);
565 return 0;
566 }
6d8c603a
AK
567
568 /*
569 * if sequence numbers are the same path with the lowest IP
570 * wins
571 */
572 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
573 if (nh_cmp < 0) {
fdf81fa0 574 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
575 if (debug)
576 zlog_debug(
577 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
578 pfx_buf, new_buf, exist_buf, new_mm_seq,
579 inet_ntoa(new->attr->nexthop));
580 return 1;
581 }
582 if (nh_cmp > 0) {
fdf81fa0 583 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
584 if (debug)
585 zlog_debug(
586 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
587 pfx_buf, new_buf, exist_buf, new_mm_seq,
588 inet_ntoa(new->attr->nexthop));
589 return 0;
590 }
d62a17ae 591 }
9fbdd100 592
d62a17ae 593 /* 1. Weight check. */
d62a17ae 594 new_weight = newattr->weight;
595 exist_weight = existattr->weight;
8ff56318 596
d62a17ae 597 if (new_weight > exist_weight) {
fdf81fa0 598 *reason = bgp_path_selection_weight;
d62a17ae 599 if (debug)
600 zlog_debug("%s: %s wins over %s due to weight %d > %d",
601 pfx_buf, new_buf, exist_buf, new_weight,
602 exist_weight);
603 return 1;
604 }
718e3744 605
d62a17ae 606 if (new_weight < exist_weight) {
fdf81fa0 607 *reason = bgp_path_selection_weight;
d62a17ae 608 if (debug)
609 zlog_debug("%s: %s loses to %s due to weight %d < %d",
610 pfx_buf, new_buf, exist_buf, new_weight,
611 exist_weight);
612 return 0;
613 }
9fbdd100 614
d62a17ae 615 /* 2. Local preference check. */
616 new_pref = exist_pref = bgp->default_local_pref;
617
618 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
619 new_pref = newattr->local_pref;
620 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
621 exist_pref = existattr->local_pref;
622
623 if (new_pref > exist_pref) {
fdf81fa0 624 *reason = bgp_path_selection_local_pref;
d62a17ae 625 if (debug)
626 zlog_debug(
627 "%s: %s wins over %s due to localpref %d > %d",
628 pfx_buf, new_buf, exist_buf, new_pref,
629 exist_pref);
630 return 1;
631 }
718e3744 632
d62a17ae 633 if (new_pref < exist_pref) {
fdf81fa0 634 *reason = bgp_path_selection_local_pref;
d62a17ae 635 if (debug)
636 zlog_debug(
637 "%s: %s loses to %s due to localpref %d < %d",
638 pfx_buf, new_buf, exist_buf, new_pref,
639 exist_pref);
640 return 0;
641 }
9fbdd100 642
d62a17ae 643 /* 3. Local route check. We prefer:
644 * - BGP_ROUTE_STATIC
645 * - BGP_ROUTE_AGGREGATE
646 * - BGP_ROUTE_REDISTRIBUTE
647 */
90f4f482 648 if (!(new->sub_type == BGP_ROUTE_NORMAL ||
649 new->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 650 *reason = bgp_path_selection_local_route;
d62a17ae 651 if (debug)
652 zlog_debug(
653 "%s: %s wins over %s due to preferred BGP_ROUTE type",
654 pfx_buf, new_buf, exist_buf);
655 return 1;
656 }
718e3744 657
90f4f482 658 if (!(exist->sub_type == BGP_ROUTE_NORMAL ||
88493076 659 exist->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 660 *reason = bgp_path_selection_local_route;
d62a17ae 661 if (debug)
662 zlog_debug(
663 "%s: %s loses to %s due to preferred BGP_ROUTE type",
664 pfx_buf, new_buf, exist_buf);
665 return 0;
6811845b 666 }
718e3744 667
d62a17ae 668 /* 4. AS path length check. */
669 if (!bgp_flag_check(bgp, BGP_FLAG_ASPATH_IGNORE)) {
670 int exist_hops = aspath_count_hops(existattr->aspath);
671 int exist_confeds = aspath_count_confeds(existattr->aspath);
672
673 if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_CONFED)) {
674 int aspath_hops;
675
676 aspath_hops = aspath_count_hops(newattr->aspath);
677 aspath_hops += aspath_count_confeds(newattr->aspath);
678
679 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 680 *reason = bgp_path_selection_confed_as_path;
d62a17ae 681 if (debug)
682 zlog_debug(
683 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
684 pfx_buf, new_buf, exist_buf,
685 aspath_hops,
686 (exist_hops + exist_confeds));
687 return 1;
688 }
689
690 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 691 *reason = bgp_path_selection_confed_as_path;
d62a17ae 692 if (debug)
693 zlog_debug(
694 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
695 pfx_buf, new_buf, exist_buf,
696 aspath_hops,
697 (exist_hops + exist_confeds));
698 return 0;
699 }
700 } else {
701 int newhops = aspath_count_hops(newattr->aspath);
702
703 if (newhops < exist_hops) {
fdf81fa0 704 *reason = bgp_path_selection_as_path;
d62a17ae 705 if (debug)
706 zlog_debug(
707 "%s: %s wins over %s due to aspath hopcount %d < %d",
708 pfx_buf, new_buf, exist_buf,
709 newhops, exist_hops);
710 return 1;
711 }
712
713 if (newhops > exist_hops) {
fdf81fa0 714 *reason = bgp_path_selection_as_path;
d62a17ae 715 if (debug)
716 zlog_debug(
717 "%s: %s loses to %s due to aspath hopcount %d > %d",
718 pfx_buf, new_buf, exist_buf,
719 newhops, exist_hops);
720 return 0;
721 }
722 }
723 }
9fbdd100 724
d62a17ae 725 /* 5. Origin check. */
726 if (newattr->origin < existattr->origin) {
fdf81fa0 727 *reason = bgp_path_selection_origin;
d62a17ae 728 if (debug)
729 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
730 pfx_buf, new_buf, exist_buf,
731 bgp_origin_long_str[newattr->origin],
732 bgp_origin_long_str[existattr->origin]);
733 return 1;
734 }
718e3744 735
d62a17ae 736 if (newattr->origin > existattr->origin) {
fdf81fa0 737 *reason = bgp_path_selection_origin;
d62a17ae 738 if (debug)
739 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
740 pfx_buf, new_buf, exist_buf,
741 bgp_origin_long_str[newattr->origin],
742 bgp_origin_long_str[existattr->origin]);
743 return 0;
744 }
718e3744 745
d62a17ae 746 /* 6. MED check. */
747 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
748 && aspath_count_hops(existattr->aspath) == 0);
749 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
750 && aspath_count_confeds(existattr->aspath) > 0
751 && aspath_count_hops(newattr->aspath) == 0
752 && aspath_count_hops(existattr->aspath) == 0);
753
754 if (bgp_flag_check(bgp, BGP_FLAG_ALWAYS_COMPARE_MED)
755 || (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED) && confed_as_route)
756 || aspath_cmp_left(newattr->aspath, existattr->aspath)
757 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
758 || internal_as_route) {
759 new_med = bgp_med_value(new->attr, bgp);
760 exist_med = bgp_med_value(exist->attr, bgp);
761
762 if (new_med < exist_med) {
fdf81fa0 763 *reason = bgp_path_selection_med;
d62a17ae 764 if (debug)
765 zlog_debug(
766 "%s: %s wins over %s due to MED %d < %d",
767 pfx_buf, new_buf, exist_buf, new_med,
768 exist_med);
769 return 1;
770 }
8ff56318 771
d62a17ae 772 if (new_med > exist_med) {
fdf81fa0 773 *reason = bgp_path_selection_med;
d62a17ae 774 if (debug)
775 zlog_debug(
776 "%s: %s loses to %s due to MED %d > %d",
777 pfx_buf, new_buf, exist_buf, new_med,
778 exist_med);
779 return 0;
780 }
781 }
9fbdd100 782
d62a17ae 783 /* 7. Peer type check. */
784 new_sort = new->peer->sort;
785 exist_sort = exist->peer->sort;
786
787 if (new_sort == BGP_PEER_EBGP
788 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 789 *reason = bgp_path_selection_peer;
d62a17ae 790 if (debug)
791 zlog_debug(
792 "%s: %s wins over %s due to eBGP peer > iBGP peer",
793 pfx_buf, new_buf, exist_buf);
794 return 1;
795 }
718e3744 796
d62a17ae 797 if (exist_sort == BGP_PEER_EBGP
798 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 799 *reason = bgp_path_selection_peer;
d62a17ae 800 if (debug)
801 zlog_debug(
802 "%s: %s loses to %s due to iBGP peer < eBGP peer",
803 pfx_buf, new_buf, exist_buf);
804 return 0;
805 }
8ff56318 806
d62a17ae 807 /* 8. IGP metric check. */
808 newm = existm = 0;
8ff56318 809
d62a17ae 810 if (new->extra)
811 newm = new->extra->igpmetric;
812 if (exist->extra)
813 existm = exist->extra->igpmetric;
9fbdd100 814
d62a17ae 815 if (newm < existm) {
816 if (debug)
817 zlog_debug(
818 "%s: %s wins over %s due to IGP metric %d < %d",
819 pfx_buf, new_buf, exist_buf, newm, existm);
820 ret = 1;
821 }
718e3744 822
d62a17ae 823 if (newm > existm) {
824 if (debug)
825 zlog_debug(
826 "%s: %s loses to %s due to IGP metric %d > %d",
827 pfx_buf, new_buf, exist_buf, newm, existm);
828 ret = 0;
5e242b0d 829 }
5e242b0d 830
d62a17ae 831 /* 9. Same IGP metric. Compare the cluster list length as
832 representative of IGP hops metric. Rewrite the metric value
833 pair (newm, existm) with the cluster list length. Prefer the
834 path with smaller cluster list length. */
835 if (newm == existm) {
836 if (peer_sort(new->peer) == BGP_PEER_IBGP
837 && peer_sort(exist->peer) == BGP_PEER_IBGP
838 && (mpath_cfg == NULL
839 || CHECK_FLAG(
840 mpath_cfg->ibgp_flags,
841 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
842 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
843 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
844
845 if (newm < existm) {
846 if (debug)
847 zlog_debug(
848 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
849 pfx_buf, new_buf, exist_buf,
850 newm, existm);
851 ret = 1;
852 }
853
854 if (newm > existm) {
855 if (debug)
856 zlog_debug(
857 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
858 pfx_buf, new_buf, exist_buf,
859 newm, existm);
860 ret = 0;
861 }
862 }
863 }
31a4638f 864
d62a17ae 865 /* 10. confed-external vs. confed-internal */
866 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
867 if (new_sort == BGP_PEER_CONFED
868 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 869 *reason = bgp_path_selection_confed;
d62a17ae 870 if (debug)
871 zlog_debug(
872 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
873 pfx_buf, new_buf, exist_buf);
874 return 1;
875 }
718e3744 876
d62a17ae 877 if (exist_sort == BGP_PEER_CONFED
878 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 879 *reason = bgp_path_selection_confed;
d62a17ae 880 if (debug)
881 zlog_debug(
882 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
883 pfx_buf, new_buf, exist_buf);
884 return 0;
885 }
886 }
718e3744 887
d62a17ae 888 /* 11. Maximum path check. */
889 if (newm == existm) {
890 /* If one path has a label but the other does not, do not treat
891 * them as equals for multipath
892 */
a4d82a8a 893 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 894 != (exist->extra
b57ba6d2 895 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 896 if (debug)
897 zlog_debug(
898 "%s: %s and %s cannot be multipath, one has a label while the other does not",
899 pfx_buf, new_buf, exist_buf);
900 } else if (bgp_flag_check(bgp,
901 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
902
903 /*
904 * For the two paths, all comparison steps till IGP
905 * metric
906 * have succeeded - including AS_PATH hop count. Since
907 * 'bgp
908 * bestpath as-path multipath-relax' knob is on, we
909 * don't need
910 * an exact match of AS_PATH. Thus, mark the paths are
911 * equal.
912 * That will trigger both these paths to get into the
913 * multipath
914 * array.
915 */
916 *paths_eq = 1;
917
918 if (debug)
919 zlog_debug(
920 "%s: %s and %s are equal via multipath-relax",
921 pfx_buf, new_buf, exist_buf);
922 } else if (new->peer->sort == BGP_PEER_IBGP) {
923 if (aspath_cmp(new->attr->aspath,
924 exist->attr->aspath)) {
925 *paths_eq = 1;
926
927 if (debug)
928 zlog_debug(
929 "%s: %s and %s are equal via matching aspaths",
930 pfx_buf, new_buf, exist_buf);
931 }
932 } else if (new->peer->as == exist->peer->as) {
933 *paths_eq = 1;
934
935 if (debug)
936 zlog_debug(
937 "%s: %s and %s are equal via same remote-as",
938 pfx_buf, new_buf, exist_buf);
939 }
940 } else {
941 /*
942 * TODO: If unequal cost ibgp multipath is enabled we can
943 * mark the paths as equal here instead of returning
944 */
945 if (debug) {
946 if (ret == 1)
947 zlog_debug(
948 "%s: %s wins over %s after IGP metric comparison",
949 pfx_buf, new_buf, exist_buf);
950 else
951 zlog_debug(
952 "%s: %s loses to %s after IGP metric comparison",
953 pfx_buf, new_buf, exist_buf);
954 }
fdf81fa0 955 *reason = bgp_path_selection_igp_metric;
d62a17ae 956 return ret;
957 }
718e3744 958
d62a17ae 959 /* 12. If both paths are external, prefer the path that was received
960 first (the oldest one). This step minimizes route-flap, since a
961 newer path won't displace an older one, even if it was the
962 preferred route based on the additional decision criteria below. */
963 if (!bgp_flag_check(bgp, BGP_FLAG_COMPARE_ROUTER_ID)
964 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 965 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 966 *reason = bgp_path_selection_older;
d62a17ae 967 if (debug)
968 zlog_debug(
969 "%s: %s wins over %s due to oldest external",
970 pfx_buf, new_buf, exist_buf);
971 return 1;
972 }
9fbdd100 973
1defdda8 974 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 975 *reason = bgp_path_selection_older;
d62a17ae 976 if (debug)
977 zlog_debug(
978 "%s: %s loses to %s due to oldest external",
979 pfx_buf, new_buf, exist_buf);
980 return 0;
981 }
982 }
718e3744 983
d62a17ae 984 /* 13. Router-ID comparision. */
985 /* If one of the paths is "stale", the corresponding peer router-id will
986 * be 0 and would always win over the other path. If originator id is
987 * used for the comparision, it will decide which path is better.
988 */
989 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
990 new_id.s_addr = newattr->originator_id.s_addr;
991 else
992 new_id.s_addr = new->peer->remote_id.s_addr;
993 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
994 exist_id.s_addr = existattr->originator_id.s_addr;
995 else
996 exist_id.s_addr = exist->peer->remote_id.s_addr;
997
998 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 999 *reason = bgp_path_selection_router_id;
d62a17ae 1000 if (debug)
1001 zlog_debug(
1002 "%s: %s wins over %s due to Router-ID comparison",
1003 pfx_buf, new_buf, exist_buf);
1004 return 1;
1005 }
718e3744 1006
d62a17ae 1007 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1008 *reason = bgp_path_selection_router_id;
d62a17ae 1009 if (debug)
1010 zlog_debug(
1011 "%s: %s loses to %s due to Router-ID comparison",
1012 pfx_buf, new_buf, exist_buf);
1013 return 0;
1014 }
9fbdd100 1015
d62a17ae 1016 /* 14. Cluster length comparision. */
1017 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1018 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1019
1020 if (new_cluster < exist_cluster) {
fdf81fa0 1021 *reason = bgp_path_selection_cluster_length;
d62a17ae 1022 if (debug)
1023 zlog_debug(
1024 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1025 pfx_buf, new_buf, exist_buf, new_cluster,
1026 exist_cluster);
1027 return 1;
1028 }
718e3744 1029
d62a17ae 1030 if (new_cluster > exist_cluster) {
fdf81fa0 1031 *reason = bgp_path_selection_cluster_length;
d62a17ae 1032 if (debug)
1033 zlog_debug(
1034 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1035 pfx_buf, new_buf, exist_buf, new_cluster,
1036 exist_cluster);
1037 return 0;
1038 }
9fbdd100 1039
d62a17ae 1040 /* 15. Neighbor address comparision. */
1041 /* Do this only if neither path is "stale" as stale paths do not have
1042 * valid peer information (as the connection may or may not be up).
1043 */
1defdda8 1044 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1045 *reason = bgp_path_selection_stale;
d62a17ae 1046 if (debug)
1047 zlog_debug(
1048 "%s: %s wins over %s due to latter path being STALE",
1049 pfx_buf, new_buf, exist_buf);
1050 return 1;
1051 }
0de5153c 1052
1defdda8 1053 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1054 *reason = bgp_path_selection_stale;
d62a17ae 1055 if (debug)
1056 zlog_debug(
1057 "%s: %s loses to %s due to former path being STALE",
1058 pfx_buf, new_buf, exist_buf);
1059 return 0;
1060 }
718e3744 1061
d62a17ae 1062 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1063 if (new->peer->su_remote == NULL) {
1064 *reason = bgp_path_selection_local_configured;
d62a17ae 1065 return 0;
fdf81fa0
DS
1066 }
1067 if (exist->peer->su_remote == NULL) {
1068 *reason = bgp_path_selection_local_configured;
d62a17ae 1069 return 1;
fdf81fa0 1070 }
9fbdd100 1071
d62a17ae 1072 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1073
1074 if (ret == 1) {
fdf81fa0 1075 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1076 if (debug)
1077 zlog_debug(
1078 "%s: %s loses to %s due to Neighor IP comparison",
1079 pfx_buf, new_buf, exist_buf);
1080 return 0;
1081 }
1082
1083 if (ret == -1) {
fdf81fa0 1084 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1085 if (debug)
1086 zlog_debug(
1087 "%s: %s wins over %s due to Neighor IP comparison",
1088 pfx_buf, new_buf, exist_buf);
1089 return 1;
1090 }
9fbdd100 1091
fdf81fa0 1092 *reason = bgp_path_selection_default;
d62a17ae 1093 if (debug)
1094 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1095 pfx_buf, new_buf, exist_buf);
718e3744 1096
d62a17ae 1097 return 1;
718e3744 1098}
1099
65efcfce
LB
1100/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1101 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1102 * multipath is enabled
65efcfce 1103 * This version is compatible with */
18ee8310
DS
1104int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1105 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1106 afi_t afi, safi_t safi,
1107 enum bgp_path_selection_reason *reason)
d62a17ae 1108{
1109 int paths_eq;
1110 int ret;
18ee8310 1111 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1112 afi, safi, reason);
d62a17ae 1113
1114 if (paths_eq)
1115 ret = 0;
1116 else {
1117 if (ret == 1)
1118 ret = -1;
1119 else
1120 ret = 1;
1121 }
1122 return ret;
65efcfce
LB
1123}
1124
d62a17ae 1125static enum filter_type bgp_input_filter(struct peer *peer, struct prefix *p,
1126 struct attr *attr, afi_t afi,
1127 safi_t safi)
718e3744 1128{
d62a17ae 1129 struct bgp_filter *filter;
718e3744 1130
d62a17ae 1131 filter = &peer->filter[afi][safi];
718e3744 1132
d62a17ae 1133#define FILTER_EXIST_WARN(F, f, filter) \
1134 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1135 zlog_debug("%s: Could not find configured input %s-list %s!", \
1136 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1137
1138 if (DISTRIBUTE_IN_NAME(filter)) {
1139 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1140
1141 if (access_list_apply(DISTRIBUTE_IN(filter), p) == FILTER_DENY)
1142 return FILTER_DENY;
1143 }
1144
1145 if (PREFIX_LIST_IN_NAME(filter)) {
1146 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1147
1148 if (prefix_list_apply(PREFIX_LIST_IN(filter), p) == PREFIX_DENY)
1149 return FILTER_DENY;
1150 }
1151
1152 if (FILTER_LIST_IN_NAME(filter)) {
1153 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1154
1155 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
1156 == AS_FILTER_DENY)
1157 return FILTER_DENY;
1158 }
1159
1160 return FILTER_PERMIT;
650f76c2 1161#undef FILTER_EXIST_WARN
718e3744 1162}
1163
d62a17ae 1164static enum filter_type bgp_output_filter(struct peer *peer, struct prefix *p,
1165 struct attr *attr, afi_t afi,
1166 safi_t safi)
718e3744 1167{
d62a17ae 1168 struct bgp_filter *filter;
1169
1170 filter = &peer->filter[afi][safi];
1171
1172#define FILTER_EXIST_WARN(F, f, filter) \
1173 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1174 zlog_debug("%s: Could not find configured output %s-list %s!", \
1175 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1176
d62a17ae 1177 if (DISTRIBUTE_OUT_NAME(filter)) {
1178 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1179
d62a17ae 1180 if (access_list_apply(DISTRIBUTE_OUT(filter), p) == FILTER_DENY)
1181 return FILTER_DENY;
1182 }
1183
1184 if (PREFIX_LIST_OUT_NAME(filter)) {
1185 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1186
d62a17ae 1187 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
1188 == PREFIX_DENY)
1189 return FILTER_DENY;
1190 }
718e3744 1191
d62a17ae 1192 if (FILTER_LIST_OUT_NAME(filter)) {
1193 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1194
d62a17ae 1195 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
1196 == AS_FILTER_DENY)
1197 return FILTER_DENY;
1198 }
718e3744 1199
d62a17ae 1200 return FILTER_PERMIT;
650f76c2 1201#undef FILTER_EXIST_WARN
718e3744 1202}
1203
1204/* If community attribute includes no_export then return 1. */
d62a17ae 1205static int bgp_community_filter(struct peer *peer, struct attr *attr)
1206{
1207 if (attr->community) {
1208 /* NO_ADVERTISE check. */
1209 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
1210 return 1;
1211
1212 /* NO_EXPORT check. */
1213 if (peer->sort == BGP_PEER_EBGP
1214 && community_include(attr->community, COMMUNITY_NO_EXPORT))
1215 return 1;
1216
1217 /* NO_EXPORT_SUBCONFED check. */
1218 if (peer->sort == BGP_PEER_EBGP
1219 || peer->sort == BGP_PEER_CONFED)
1220 if (community_include(attr->community,
1221 COMMUNITY_NO_EXPORT_SUBCONFED))
1222 return 1;
1223 }
1224 return 0;
718e3744 1225}
1226
1227/* Route reflection loop check. */
d62a17ae 1228static int bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1229{
d62a17ae 1230 struct in_addr cluster_id;
718e3744 1231
d62a17ae 1232 if (attr->cluster) {
1233 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1234 cluster_id = peer->bgp->cluster_id;
1235 else
1236 cluster_id = peer->bgp->router_id;
1237
1238 if (cluster_loop_check(attr->cluster, cluster_id))
1239 return 1;
1240 }
1241 return 0;
718e3744 1242}
6b0655a2 1243
d62a17ae 1244static int bgp_input_modifier(struct peer *peer, struct prefix *p,
1245 struct attr *attr, afi_t afi, safi_t safi,
82b692c0
LK
1246 const char *rmap_name, mpls_label_t *label,
1247 uint32_t num_labels)
718e3744 1248{
d62a17ae 1249 struct bgp_filter *filter;
82b692c0
LK
1250 struct bgp_path_info rmap_path = { 0 };
1251 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1252 route_map_result_t ret;
1253 struct route_map *rmap = NULL;
718e3744 1254
d62a17ae 1255 filter = &peer->filter[afi][safi];
718e3744 1256
d62a17ae 1257 /* Apply default weight value. */
1258 if (peer->weight[afi][safi])
1259 attr->weight = peer->weight[afi][safi];
718e3744 1260
d62a17ae 1261 if (rmap_name) {
1262 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1263
d62a17ae 1264 if (rmap == NULL)
1265 return RMAP_DENY;
1266 } else {
1267 if (ROUTE_MAP_IN_NAME(filter)) {
1268 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1269
d62a17ae 1270 if (rmap == NULL)
1271 return RMAP_DENY;
1272 }
1273 }
0b16f239 1274
d62a17ae 1275 /* Route map apply. */
1276 if (rmap) {
40381db7 1277 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1278 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1279 rmap_path.peer = peer;
1280 rmap_path.attr = attr;
82b692c0
LK
1281 rmap_path.extra = &extra;
1282 extra.num_labels = num_labels;
1283 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1284 memcpy(extra.label, label,
1285 num_labels * sizeof(mpls_label_t));
718e3744 1286
d62a17ae 1287 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1288
d62a17ae 1289 /* Apply BGP route map to the attribute. */
40381db7 1290 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
0b16f239 1291
d62a17ae 1292 peer->rmap_type = 0;
0b16f239 1293
1f2263be 1294 if (ret == RMAP_DENYMATCH)
d62a17ae 1295 return RMAP_DENY;
0b16f239 1296 }
d62a17ae 1297 return RMAP_PERMIT;
0b16f239
DS
1298}
1299
d62a17ae 1300static int bgp_output_modifier(struct peer *peer, struct prefix *p,
1301 struct attr *attr, afi_t afi, safi_t safi,
1302 const char *rmap_name)
0b16f239 1303{
40381db7 1304 struct bgp_path_info rmap_path;
d62a17ae 1305 route_map_result_t ret;
1306 struct route_map *rmap = NULL;
d7c0a89a 1307 uint8_t rmap_type;
0b16f239 1308
b787157a
DS
1309 /*
1310 * So if we get to this point and have no rmap_name
1311 * we want to just show the output as it currently
1312 * exists.
1313 */
1314 if (!rmap_name)
1315 return RMAP_PERMIT;
0b16f239 1316
d62a17ae 1317 /* Apply default weight value. */
1318 if (peer->weight[afi][safi])
1319 attr->weight = peer->weight[afi][safi];
0b16f239 1320
b787157a 1321 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1322
b787157a
DS
1323 /*
1324 * If we have a route map name and we do not find
1325 * the routemap that means we have an implicit
1326 * deny.
1327 */
1328 if (rmap == NULL)
1329 return RMAP_DENY;
0b16f239 1330
40381db7 1331 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1332 /* Route map apply. */
b787157a 1333 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1334 rmap_path.peer = peer;
1335 rmap_path.attr = attr;
0b16f239 1336
0f672529 1337 rmap_type = peer->rmap_type;
b787157a 1338 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1339
b787157a 1340 /* Apply BGP route map to the attribute. */
40381db7 1341 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
ac41b2a2 1342
0f672529 1343 peer->rmap_type = rmap_type;
b787157a
DS
1344
1345 if (ret == RMAP_DENYMATCH)
1346 /*
1347 * caller has multiple error paths with bgp_attr_flush()
1348 */
1349 return RMAP_DENY;
ac41b2a2 1350
d62a17ae 1351 return RMAP_PERMIT;
718e3744 1352}
6b0655a2 1353
5000f21c 1354/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1355static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1356 struct peer *peer, struct attr *attr)
1357{
1358 if (peer->sort == BGP_PEER_EBGP
1359 && (peer_af_flag_check(peer, afi, safi,
1360 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1361 || peer_af_flag_check(peer, afi, safi,
1362 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1363 || peer_af_flag_check(peer, afi, safi,
1364 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1365 || peer_af_flag_check(peer, afi, safi,
1366 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1367 // Take action on the entire aspath
1368 if (peer_af_flag_check(peer, afi, safi,
1369 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1370 || peer_af_flag_check(peer, afi, safi,
1371 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1372 if (peer_af_flag_check(
1373 peer, afi, safi,
1374 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1375 attr->aspath = aspath_replace_private_asns(
bf26b80e 1376 attr->aspath, bgp->as, peer->as);
d62a17ae 1377
1378 // The entire aspath consists of private ASNs so create
1379 // an empty aspath
1380 else if (aspath_private_as_check(attr->aspath))
1381 attr->aspath = aspath_empty_get();
1382
1383 // There are some public and some private ASNs, remove
1384 // the private ASNs
1385 else
1386 attr->aspath = aspath_remove_private_asns(
bf26b80e 1387 attr->aspath, peer->as);
d62a17ae 1388 }
1389
1390 // 'all' was not specified so the entire aspath must be private
1391 // ASNs
1392 // for us to do anything
1393 else if (aspath_private_as_check(attr->aspath)) {
1394 if (peer_af_flag_check(
1395 peer, afi, safi,
1396 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1397 attr->aspath = aspath_replace_private_asns(
bf26b80e 1398 attr->aspath, bgp->as, peer->as);
d62a17ae 1399 else
1400 attr->aspath = aspath_empty_get();
1401 }
1402 }
5000f21c
DS
1403}
1404
c7122e14 1405/* If this is an EBGP peer with as-override */
d62a17ae 1406static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1407 struct peer *peer, struct attr *attr)
1408{
1409 if (peer->sort == BGP_PEER_EBGP
1410 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1411 if (aspath_single_asn_check(attr->aspath, peer->as))
1412 attr->aspath = aspath_replace_specific_asn(
1413 attr->aspath, peer->as, bgp->as);
1414 }
1415}
1416
7f323236
DW
1417void bgp_attr_add_gshut_community(struct attr *attr)
1418{
1419 struct community *old;
1420 struct community *new;
1421 struct community *merge;
1422 struct community *gshut;
1423
1424 old = attr->community;
1425 gshut = community_str2com("graceful-shutdown");
1426
990f4f91 1427 assert(gshut);
1428
7f323236
DW
1429 if (old) {
1430 merge = community_merge(community_dup(old), gshut);
1431
a4d82a8a 1432 if (old->refcnt == 0)
3c1f53de 1433 community_free(&old);
7f323236
DW
1434
1435 new = community_uniq_sort(merge);
3c1f53de 1436 community_free(&merge);
7f323236
DW
1437 } else {
1438 new = community_dup(gshut);
1439 }
1440
3c1f53de 1441 community_free(&gshut);
7f323236
DW
1442 attr->community = new;
1443 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1444
1445 /* When we add the graceful-shutdown community we must also
1446 * lower the local-preference */
1447 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1448 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1449}
1450
1451
d7c0a89a 1452static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1453{
960035b2 1454 if (family == AF_INET) {
d62a17ae 1455 attr->nexthop.s_addr = 0;
960035b2
PZ
1456 attr->mp_nexthop_global_in.s_addr = 0;
1457 }
d62a17ae 1458 if (family == AF_INET6)
1459 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1460 if (family == AF_EVPN)
1461 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1462}
1463
40381db7 1464int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
d62a17ae 1465 struct update_subgroup *subgrp, struct prefix *p,
1466 struct attr *attr)
1467{
1468 struct bgp_filter *filter;
1469 struct peer *from;
1470 struct peer *peer;
1471 struct peer *onlypeer;
1472 struct bgp *bgp;
40381db7 1473 struct attr *piattr;
d62a17ae 1474 char buf[PREFIX_STRLEN];
b68885f9 1475 route_map_result_t ret;
d62a17ae 1476 int transparent;
1477 int reflect;
1478 afi_t afi;
1479 safi_t safi;
1480 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
1481
1482 if (DISABLE_BGP_ANNOUNCE)
1483 return 0;
1484
1485 afi = SUBGRP_AFI(subgrp);
1486 safi = SUBGRP_SAFI(subgrp);
1487 peer = SUBGRP_PEER(subgrp);
1488 onlypeer = NULL;
1489 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1490 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1491
40381db7 1492 from = pi->peer;
d62a17ae 1493 filter = &peer->filter[afi][safi];
1494 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1495 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1496 : pi->attr;
3f9c7369 1497
65efcfce 1498#if ENABLE_BGP_VNC
d62a17ae 1499 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1500 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1501 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1502
1503 /*
1504 * direct and direct_ext type routes originate internally even
1505 * though they can have peer pointers that reference other
1506 * systems
1507 */
1508 prefix2str(p, buf, PREFIX_STRLEN);
1509 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1510 __func__, buf);
1511 samepeer_safe = 1;
1512 }
65efcfce
LB
1513#endif
1514
ddb5b488
PZ
1515 if (((afi == AFI_IP) || (afi == AFI_IP6))
1516 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1517 && (pi->type == ZEBRA_ROUTE_BGP)
1518 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1519
1520 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1521
1522 samepeer_safe = 1;
1523 }
1524
d62a17ae 1525 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1526 * pi is valid */
1527 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1528 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1529 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 1530 return 0;
1531 }
adbac85e 1532
d62a17ae 1533 /* If this is not the bestpath then check to see if there is an enabled
1534 * addpath
1535 * feature that requires us to advertise it */
40381db7 1536 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1537 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
d62a17ae 1538 return 0;
1539 }
1540 }
06370dac 1541
d62a17ae 1542 /* Aggregate-address suppress check. */
40381db7 1543 if (pi->extra && pi->extra->suppress)
d62a17ae 1544 if (!UNSUPPRESS_MAP_NAME(filter)) {
1545 return 0;
1546 }
3f9c7369 1547
13b7e7f0
DS
1548 /*
1549 * If we are doing VRF 2 VRF leaking via the import
1550 * statement, we want to prevent the route going
1551 * off box as that the RT and RD created are localy
1552 * significant and globaly useless.
1553 */
40381db7
DS
1554 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1555 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
13b7e7f0
DS
1556 return 0;
1557
d62a17ae 1558 /* If it's labeled safi, make sure the route has a valid label. */
1559 if (safi == SAFI_LABELED_UNICAST) {
40381db7 1560 mpls_label_t label = bgp_adv_label(rn, pi, peer, afi, safi);
d62a17ae 1561 if (!bgp_is_valid_label(&label)) {
1562 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1563 zlog_debug("u%" PRIu64 ":s%" PRIu64
1564 " %s/%d is filtered - no label (%p)",
1565 subgrp->update_group->id, subgrp->id,
1566 inet_ntop(p->family, &p->u.prefix,
1567 buf, SU_ADDRSTRLEN),
1568 p->prefixlen, &label);
1569 return 0;
1570 }
1571 }
cd1964ff 1572
d62a17ae 1573 /* Do not send back route to sender. */
1574 if (onlypeer && from == onlypeer) {
1575 return 0;
1576 }
3f9c7369 1577
d62a17ae 1578 /* Do not send the default route in the BGP table if the neighbor is
1579 * configured for default-originate */
1580 if (CHECK_FLAG(peer->af_flags[afi][safi],
1581 PEER_FLAG_DEFAULT_ORIGINATE)) {
1582 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
1583 return 0;
1584 else if (p->family == AF_INET6 && p->prefixlen == 0)
1585 return 0;
1586 }
4125bb67 1587
d62a17ae 1588 /* Transparency check. */
1589 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1590 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1591 transparent = 1;
1592 else
1593 transparent = 0;
1594
1595 /* If community is not disabled check the no-export and local. */
40381db7 1596 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1597 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1598 zlog_debug(
1599 "subgrpannouncecheck: community filter check fail");
1600 return 0;
1601 }
3f9c7369 1602
d62a17ae 1603 /* If the attribute has originator-id and it is same as remote
1604 peer's id. */
40381db7
DS
1605 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1606 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1607 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1608 zlog_debug(
1609 "%s [Update:SEND] %s originator-id is same as "
1610 "remote router-id",
1611 onlypeer->host,
1612 prefix2str(p, buf, sizeof(buf)));
1613 return 0;
1614 }
3f9c7369 1615
d62a17ae 1616 /* ORF prefix-list filter check */
1617 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1618 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1619 || CHECK_FLAG(peer->af_cap[afi][safi],
1620 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1621 if (peer->orf_plist[afi][safi]) {
1622 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1623 == PREFIX_DENY) {
1624 if (bgp_debug_update(NULL, p,
1625 subgrp->update_group, 0))
1626 zlog_debug(
1627 "%s [Update:SEND] %s is filtered via ORF",
1628 peer->host,
1629 prefix2str(p, buf,
1630 sizeof(buf)));
1631 return 0;
1632 }
1633 }
1634
1635 /* Output filter check. */
40381db7 1636 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1637 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1638 zlog_debug("%s [Update:SEND] %s is filtered",
1639 peer->host, prefix2str(p, buf, sizeof(buf)));
1640 return 0;
1641 }
3f9c7369 1642
d62a17ae 1643 /* AS path loop check. */
2b31007c
RZ
1644 if (onlypeer && onlypeer->as_path_loop_detection
1645 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1646 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1647 zlog_debug(
1648 "%s [Update:SEND] suppress announcement to peer AS %u "
1649 "that is part of AS path.",
1650 onlypeer->host, onlypeer->as);
1651 return 0;
1652 }
3f9c7369 1653
d62a17ae 1654 /* If we're a CONFED we need to loop check the CONFED ID too */
1655 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1656 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1657 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1658 zlog_debug(
1659 "%s [Update:SEND] suppress announcement to peer AS %u"
1660 " is AS path.",
1661 peer->host, bgp->confed_id);
1662 return 0;
1663 }
3f9c7369 1664 }
3f9c7369 1665
d62a17ae 1666 /* Route-Reflect check. */
1667 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1668 reflect = 1;
1669 else
1670 reflect = 0;
1671
1672 /* IBGP reflection check. */
1673 if (reflect && !samepeer_safe) {
1674 /* A route from a Client peer. */
1675 if (CHECK_FLAG(from->af_flags[afi][safi],
1676 PEER_FLAG_REFLECTOR_CLIENT)) {
1677 /* Reflect to all the Non-Client peers and also to the
1678 Client peers other than the originator. Originator
1679 check
1680 is already done. So there is noting to do. */
1681 /* no bgp client-to-client reflection check. */
1682 if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
1683 if (CHECK_FLAG(peer->af_flags[afi][safi],
1684 PEER_FLAG_REFLECTOR_CLIENT))
1685 return 0;
1686 } else {
1687 /* A route from a Non-client peer. Reflect to all other
1688 clients. */
1689 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1690 PEER_FLAG_REFLECTOR_CLIENT))
1691 return 0;
1692 }
1693 }
3f9c7369 1694
d62a17ae 1695 /* For modify attribute, copy it to temporary structure. */
40381db7 1696 bgp_attr_dup(attr, piattr);
d62a17ae 1697
1698 /* If local-preference is not set. */
1699 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1700 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1701 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1702 attr->local_pref = bgp->default_local_pref;
3f9c7369 1703 }
3f9c7369 1704
d62a17ae 1705 /* If originator-id is not set and the route is to be reflected,
1706 set the originator id */
1707 if (reflect
1708 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1709 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1710 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1711 }
3f9c7369 1712
d62a17ae 1713 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1714 */
1715 if (peer->sort == BGP_PEER_EBGP
1716 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1717 if (from != bgp->peer_self && !transparent
1718 && !CHECK_FLAG(peer->af_flags[afi][safi],
1719 PEER_FLAG_MED_UNCHANGED))
1720 attr->flag &=
1721 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1722 }
3f9c7369 1723
d62a17ae 1724 /* Since the nexthop attribute can vary per peer, it is not explicitly
1725 * set
1726 * in announce check, only certain flags and length (or number of
1727 * nexthops
1728 * -- for IPv6/MP_REACH) are set here in order to guide the update
1729 * formation
1730 * code in setting the nexthop(s) on a per peer basis in
1731 * reformat_peer().
1732 * Typically, the source nexthop in the attribute is preserved but in
1733 * the
1734 * scenarios where we know it will always be overwritten, we reset the
1735 * nexthop to "0" in an attempt to achieve better Update packing. An
1736 * example of this is when a prefix from each of 2 IBGP peers needs to
1737 * be
1738 * announced to an EBGP peer (and they have the same attributes barring
1739 * their nexthop).
1740 */
1741 if (reflect)
1742 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1743
1744#define NEXTHOP_IS_V6 \
1745 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1746 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1747 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1748 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1749
1750 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1751 * if
1752 * the peer (group) is configured to receive link-local nexthop
1753 * unchanged
c728d027
DA
1754 * and it is available in the prefix OR we're not reflecting the route,
1755 * link-local nexthop address is valid and
d62a17ae 1756 * the peer (group) to whom we're going to announce is on a shared
1757 * network
1758 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
1759 * By checking if nexthop LL address is valid we are sure that
1760 * we do not announce LL address as `::`.
d62a17ae 1761 */
1762 if (NEXTHOP_IS_V6) {
1763 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
1764 if ((CHECK_FLAG(peer->af_flags[afi][safi],
1765 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
1766 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
1767 || (!reflect
1768 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
1769 && peer->shared_network
d62a17ae 1770 && (from == bgp->peer_self
1771 || peer->sort == BGP_PEER_EBGP))) {
1772 attr->mp_nexthop_len =
1773 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
1774 }
3f9c7369 1775
d62a17ae 1776 /* Clear off link-local nexthop in source, whenever it is not
1777 * needed to
1778 * ensure more prefixes share the same attribute for
1779 * announcement.
1780 */
1781 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
1782 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
1783 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
1784 }
3f9c7369 1785
d62a17ae 1786 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
1787 bgp_peer_as_override(bgp, afi, safi, peer, attr);
1788
1789 /* Route map & unsuppress-map apply. */
40381db7 1790 if (ROUTE_MAP_OUT_NAME(filter) || (pi->extra && pi->extra->suppress)) {
b8694ef4
DS
1791 struct bgp_path_info rmap_path = {0};
1792 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
1793 struct attr dummy_attr = {0};
d62a17ae 1794
40381db7
DS
1795 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
1796 rmap_path.peer = peer;
1797 rmap_path.attr = attr;
d37ba549 1798
40381db7
DS
1799 if (pi->extra) {
1800 memcpy(&dummy_rmap_path_extra, pi->extra,
4b7e6066 1801 sizeof(struct bgp_path_info_extra));
40381db7 1802 rmap_path.extra = &dummy_rmap_path_extra;
16f7ce2b
MK
1803 }
1804
d62a17ae 1805 /* don't confuse inbound and outbound setting */
1806 RESET_FLAG(attr->rmap_change_flags);
1807
1808 /*
1809 * The route reflector is not allowed to modify the attributes
1810 * of the reflected IBGP routes unless explicitly allowed.
1811 */
1812 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1813 && !bgp_flag_check(bgp,
1814 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
1815 bgp_attr_dup(&dummy_attr, attr);
40381db7 1816 rmap_path.attr = &dummy_attr;
d62a17ae 1817 }
3f9c7369 1818
d62a17ae 1819 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 1820
40381db7 1821 if (pi->extra && pi->extra->suppress)
d62a17ae 1822 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
40381db7 1823 RMAP_BGP, &rmap_path);
d62a17ae 1824 else
1825 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
40381db7 1826 RMAP_BGP, &rmap_path);
d62a17ae 1827
1828 peer->rmap_type = 0;
1829
1830 if (ret == RMAP_DENYMATCH) {
778048bf
AD
1831 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1832 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1833 peer->host, prefix2str(p, buf, sizeof(buf)));
1834
d62a17ae 1835 bgp_attr_flush(attr);
1836 return 0;
1837 }
3f9c7369 1838 }
3f9c7369 1839
9dac9fc8
DA
1840 /* RFC 8212 to prevent route leaks.
1841 * This specification intends to improve this situation by requiring the
1842 * explicit configuration of both BGP Import and Export Policies for any
1843 * External BGP (EBGP) session such as customers, peers, or
1844 * confederation boundaries for all enabled address families. Through
1845 * codification of the aforementioned requirement, operators will
1846 * benefit from consistent behavior across different BGP
1847 * implementations.
1848 */
1849 if (peer->bgp->ebgp_requires_policy
1850 == DEFAULT_EBGP_POLICY_ENABLED)
1851 if (!bgp_outbound_policy_exists(peer, filter))
1852 return 0;
1853
7f323236 1854 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
a4d82a8a
PZ
1855 if (peer->sort == BGP_PEER_IBGP
1856 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
1857 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1858 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1859 } else {
1860 bgp_attr_add_gshut_community(attr);
1861 }
1862 }
1863
d62a17ae 1864 /* After route-map has been applied, we check to see if the nexthop to
1865 * be carried in the attribute (that is used for the announcement) can
1866 * be cleared off or not. We do this in all cases where we would be
1867 * setting the nexthop to "ourselves". For IPv6, we only need to
1868 * consider
1869 * the global nexthop here; the link-local nexthop would have been
1870 * cleared
1871 * already, and if not, it is required by the update formation code.
1872 * Also see earlier comments in this function.
1873 */
1874 /*
1875 * If route-map has performed some operation on the nexthop or the peer
1876 * configuration says to pass it unchanged, we cannot reset the nexthop
1877 * here, so only attempt to do it if these aren't true. Note that the
1878 * route-map handler itself might have cleared the nexthop, if for
1879 * example,
1880 * it is configured as 'peer-address'.
1881 */
1882 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 1883 piattr->rmap_change_flags)
d62a17ae 1884 && !transparent
1885 && !CHECK_FLAG(peer->af_flags[afi][safi],
1886 PEER_FLAG_NEXTHOP_UNCHANGED)) {
1887 /* We can reset the nexthop, if setting (or forcing) it to
1888 * 'self' */
1889 if (CHECK_FLAG(peer->af_flags[afi][safi],
1890 PEER_FLAG_NEXTHOP_SELF)
1891 || CHECK_FLAG(peer->af_flags[afi][safi],
1892 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
1893 if (!reflect
1894 || CHECK_FLAG(peer->af_flags[afi][safi],
1895 PEER_FLAG_FORCE_NEXTHOP_SELF))
1896 subgroup_announce_reset_nhop(
1897 (peer_cap_enhe(peer, afi, safi)
1898 ? AF_INET6
1899 : p->family),
1900 attr);
1901 } else if (peer->sort == BGP_PEER_EBGP) {
1902 /* Can also reset the nexthop if announcing to EBGP, but
1903 * only if
1904 * no peer in the subgroup is on a shared subnet.
1905 * Note: 3rd party nexthop currently implemented for
1906 * IPv4 only.
1907 */
737af885
BS
1908 if ((p->family == AF_INET) &&
1909 (!bgp_subgrp_multiaccess_check_v4(
1910 piattr->nexthop,
1911 subgrp)))
d62a17ae 1912 subgroup_announce_reset_nhop(
1913 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
1914 ? AF_INET6
1915 : p->family),
737af885
BS
1916 attr);
1917
1918 if ((p->family == AF_INET6) &&
1919 (!bgp_subgrp_multiaccess_check_v6(
1920 piattr->mp_nexthop_global,
1921 subgrp)))
1922 subgroup_announce_reset_nhop(
1923 (peer_cap_enhe(peer, afi, safi)
1924 ? AF_INET6
1925 : p->family),
1926 attr);
1927
1928
1929
40381db7 1930 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
1931 /*
1932 * This flag is used for leaked vpn-vrf routes
1933 */
1934 int family = p->family;
1935
1936 if (peer_cap_enhe(peer, afi, safi))
1937 family = AF_INET6;
1938
1939 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1940 zlog_debug(
1defdda8 1941 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
1942 __func__, family2str(family));
1943 subgroup_announce_reset_nhop(family, attr);
d62a17ae 1944 }
63696f1d 1945 }
960035b2 1946
63696f1d 1947 /* If IPv6/MP and nexthop does not have any override and happens
1948 * to
1949 * be a link-local address, reset it so that we don't pass along
1950 * the
1951 * source's link-local IPv6 address to recipients who may not be
1952 * on
1953 * the same interface.
1954 */
1955 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
1956 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global))
1957 subgroup_announce_reset_nhop(AF_INET6, attr);
d62a17ae 1958 }
3f9c7369 1959
d62a17ae 1960 return 1;
3f9c7369
DS
1961}
1962
d62a17ae 1963void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
1964 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
1965 struct bgp_path_info_pair *result, afi_t afi,
1966 safi_t safi)
1967{
1968 struct bgp_path_info *new_select;
1969 struct bgp_path_info *old_select;
40381db7
DS
1970 struct bgp_path_info *pi;
1971 struct bgp_path_info *pi1;
1972 struct bgp_path_info *pi2;
1973 struct bgp_path_info *nextpi = NULL;
d62a17ae 1974 int paths_eq, do_mpath, debug;
1975 struct list mp_list;
1976 char pfx_buf[PREFIX2STR_BUFFER];
1977 char path_buf[PATH_ADDPATH_STR_BUFFER];
1978
1979 bgp_mp_list_init(&mp_list);
1980 do_mpath =
1981 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
1982
1983 debug = bgp_debug_bestpath(&rn->p);
1984
1985 if (debug)
1986 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
1987
1988 /* bgp deterministic-med */
1989 new_select = NULL;
1990 if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)) {
1991
1defdda8 1992 /* Clear BGP_PATH_DMED_SELECTED for all paths */
6f94b685
DS
1993 for (pi1 = bgp_node_get_bgp_path_info(rn); pi1;
1994 pi1 = pi1->next)
40381db7 1995 bgp_path_info_unset_flag(rn, pi1,
18ee8310 1996 BGP_PATH_DMED_SELECTED);
d62a17ae 1997
6f94b685
DS
1998 for (pi1 = bgp_node_get_bgp_path_info(rn); pi1;
1999 pi1 = pi1->next) {
40381db7 2000 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2001 continue;
40381db7 2002 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2003 continue;
ea8b2282 2004 if (pi1->peer != bgp->peer_self)
40381db7 2005 if (pi1->peer->status != Established)
d62a17ae 2006 continue;
2007
40381db7
DS
2008 new_select = pi1;
2009 if (pi1->next) {
2010 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2011 if (CHECK_FLAG(pi2->flags,
1defdda8 2012 BGP_PATH_DMED_CHECK))
d62a17ae 2013 continue;
40381db7 2014 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2015 continue;
ea8b2282 2016 if (pi2->peer != bgp->peer_self
d62a17ae 2017 && !CHECK_FLAG(
ea8b2282
DS
2018 pi2->peer->sflags,
2019 PEER_STATUS_NSF_WAIT))
40381db7 2020 if (pi2->peer->status
d62a17ae 2021 != Established)
2022 continue;
2023
121e245d
DS
2024 if (!aspath_cmp_left(pi1->attr->aspath,
2025 pi2->attr->aspath)
2026 && !aspath_cmp_left_confed(
40381db7 2027 pi1->attr->aspath,
121e245d
DS
2028 pi2->attr->aspath))
2029 continue;
d62a17ae 2030
121e245d
DS
2031 if (bgp_path_info_cmp(
2032 bgp, pi2, new_select,
2033 &paths_eq, mpath_cfg, debug,
fdf81fa0
DS
2034 pfx_buf, afi, safi,
2035 &rn->reason)) {
121e245d
DS
2036 bgp_path_info_unset_flag(
2037 rn, new_select,
2038 BGP_PATH_DMED_SELECTED);
2039 new_select = pi2;
d62a17ae 2040 }
121e245d
DS
2041
2042 bgp_path_info_set_flag(
2043 rn, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2044 }
2045 }
18ee8310
DS
2046 bgp_path_info_set_flag(rn, new_select,
2047 BGP_PATH_DMED_CHECK);
2048 bgp_path_info_set_flag(rn, new_select,
2049 BGP_PATH_DMED_SELECTED);
d62a17ae 2050
2051 if (debug) {
18ee8310
DS
2052 bgp_path_info_path_with_addpath_rx_str(
2053 new_select, path_buf);
c66faab1 2054 zlog_debug("%s: %s is the bestpath from AS %u",
d62a17ae 2055 pfx_buf, path_buf,
2056 aspath_get_first_as(
2057 new_select->attr->aspath));
2058 }
2059 }
2060 }
96450faf 2061
d62a17ae 2062 /* Check old selected route and new selected route. */
2063 old_select = NULL;
2064 new_select = NULL;
6f94b685
DS
2065 for (pi = bgp_node_get_bgp_path_info(rn);
2066 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
40381db7
DS
2067 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2068 old_select = pi;
d62a17ae 2069
40381db7 2070 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2071 /* reap REMOVED routes, if needs be
2072 * selected route must stay for a while longer though
2073 */
40381db7
DS
2074 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2075 && (pi != old_select))
2076 bgp_path_info_reap(rn, pi);
d62a17ae 2077
ddb5b488 2078 if (debug)
40381db7
DS
2079 zlog_debug("%s: pi %p in holddown", __func__,
2080 pi);
ddb5b488 2081
d62a17ae 2082 continue;
2083 }
96450faf 2084
40381db7
DS
2085 if (pi->peer && pi->peer != bgp->peer_self
2086 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2087 if (pi->peer->status != Established) {
ddb5b488
PZ
2088
2089 if (debug)
2090 zlog_debug(
40381db7
DS
2091 "%s: pi %p non self peer %s not estab state",
2092 __func__, pi, pi->peer->host);
ddb5b488 2093
d62a17ae 2094 continue;
ddb5b488 2095 }
9fbdd100 2096
d62a17ae 2097 if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)
40381db7
DS
2098 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
2099 bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2100 if (debug)
40381db7 2101 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2102 continue;
2103 }
9fbdd100 2104
40381db7 2105 bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK);
06370dac 2106
40381db7 2107 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
fdf81fa0 2108 debug, pfx_buf, afi, safi, &rn->reason)) {
40381db7 2109 new_select = pi;
d62a17ae 2110 }
2111 }
718e3744 2112
d62a17ae 2113 /* Now that we know which path is the bestpath see if any of the other
2114 * paths
2115 * qualify as multipaths
2116 */
2117 if (debug) {
2118 if (new_select)
18ee8310
DS
2119 bgp_path_info_path_with_addpath_rx_str(new_select,
2120 path_buf);
d62a17ae 2121 else
2122 sprintf(path_buf, "NONE");
2123 zlog_debug(
2124 "%s: After path selection, newbest is %s oldbest was %s",
2125 pfx_buf, path_buf,
2126 old_select ? old_select->peer->host : "NONE");
96450faf 2127 }
9fbdd100 2128
d62a17ae 2129 if (do_mpath && new_select) {
6f94b685
DS
2130 for (pi = bgp_node_get_bgp_path_info(rn);
2131 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2132
2133 if (debug)
18ee8310 2134 bgp_path_info_path_with_addpath_rx_str(
40381db7 2135 pi, path_buf);
d62a17ae 2136
40381db7 2137 if (pi == new_select) {
d62a17ae 2138 if (debug)
2139 zlog_debug(
2140 "%s: %s is the bestpath, add to the multipath list",
2141 pfx_buf, path_buf);
40381db7 2142 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2143 continue;
2144 }
2145
40381db7 2146 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2147 continue;
2148
40381db7
DS
2149 if (pi->peer && pi->peer != bgp->peer_self
2150 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2151 PEER_STATUS_NSF_WAIT))
40381db7 2152 if (pi->peer->status != Established)
d62a17ae 2153 continue;
2154
40381db7 2155 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2156 if (debug)
2157 zlog_debug(
2158 "%s: %s has the same nexthop as the bestpath, skip it",
2159 pfx_buf, path_buf);
2160 continue;
2161 }
2162
40381db7 2163 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0
DS
2164 mpath_cfg, debug, pfx_buf, afi, safi,
2165 &rn->reason);
d62a17ae 2166
2167 if (paths_eq) {
2168 if (debug)
2169 zlog_debug(
2170 "%s: %s is equivalent to the bestpath, add to the multipath list",
2171 pfx_buf, path_buf);
40381db7 2172 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2173 }
2174 }
2175 }
fee0f4c6 2176
18ee8310
DS
2177 bgp_path_info_mpath_update(rn, new_select, old_select, &mp_list,
2178 mpath_cfg);
2179 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2180 bgp_mp_list_clear(&mp_list);
96450faf 2181
dcc68b5e
MS
2182 bgp_addpath_update_ids(bgp, rn, afi, safi);
2183
d62a17ae 2184 result->old = old_select;
2185 result->new = new_select;
96450faf 2186
d62a17ae 2187 return;
fee0f4c6 2188}
2189
3f9c7369
DS
2190/*
2191 * A new route/change in bestpath of an existing route. Evaluate the path
2192 * for advertisement to the subgroup.
2193 */
d62a17ae 2194int subgroup_process_announce_selected(struct update_subgroup *subgrp,
4b7e6066 2195 struct bgp_path_info *selected,
d62a17ae 2196 struct bgp_node *rn,
d7c0a89a 2197 uint32_t addpath_tx_id)
d62a17ae 2198{
2199 struct prefix *p;
2200 struct peer *onlypeer;
2201 struct attr attr;
2202 afi_t afi;
2203 safi_t safi;
adbac85e 2204
d62a17ae 2205 p = &rn->p;
2206 afi = SUBGRP_AFI(subgrp);
2207 safi = SUBGRP_SAFI(subgrp);
2208 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2209 : NULL);
2210
e0207895
PZ
2211 if (BGP_DEBUG(update, UPDATE_OUT)) {
2212 char buf_prefix[PREFIX_STRLEN];
2213 prefix2str(p, buf_prefix, sizeof(buf_prefix));
ddb5b488
PZ
2214 zlog_debug("%s: p=%s, selected=%p", __func__, buf_prefix,
2215 selected);
e0207895
PZ
2216 }
2217
d62a17ae 2218 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2219 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2220 PEER_STATUS_ORF_WAIT_REFRESH))
d62a17ae 2221 return 0;
2222
2223 memset(&attr, 0, sizeof(struct attr));
2224 /* It's initialized in bgp_announce_check() */
2225
2226 /* Announcement to the subgroup. If the route is filtered withdraw it.
2227 */
2228 if (selected) {
2229 if (subgroup_announce_check(rn, selected, subgrp, p, &attr))
2230 bgp_adj_out_set_subgroup(rn, subgrp, &attr, selected);
2231 else
2232 bgp_adj_out_unset_subgroup(rn, subgrp, 1,
dcc68b5e 2233 addpath_tx_id);
d62a17ae 2234 }
2235
2236 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2237 else {
2238 bgp_adj_out_unset_subgroup(rn, subgrp, 1, addpath_tx_id);
2239 }
558d1fec 2240
d62a17ae 2241 return 0;
200df115 2242}
fee0f4c6 2243
3064bf43 2244/*
e1072051 2245 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2246 * This is called at the end of route processing.
3064bf43 2247 */
d62a17ae 2248void bgp_zebra_clear_route_change_flags(struct bgp_node *rn)
3064bf43 2249{
40381db7 2250 struct bgp_path_info *pi;
3064bf43 2251
6f94b685 2252 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 2253 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2254 continue;
40381db7
DS
2255 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2256 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2257 }
3064bf43 2258}
2259
2260/*
2261 * Has the route changed from the RIB's perspective? This is invoked only
2262 * if the route selection returns the same best route as earlier - to
2263 * determine if we need to update zebra or not.
2264 */
4b7e6066
DS
2265int bgp_zebra_has_route_changed(struct bgp_node *rn,
2266 struct bgp_path_info *selected)
d62a17ae 2267{
4b7e6066 2268 struct bgp_path_info *mpinfo;
d62a17ae 2269
2bb9eff4
DS
2270 /* If this is multipath, check all selected paths for any nexthop
2271 * change or attribute change. Some attribute changes (e.g., community)
2272 * aren't of relevance to the RIB, but we'll update zebra to ensure
2273 * we handle the case of BGP nexthop change. This is the behavior
2274 * when the best path has an attribute change anyway.
d62a17ae 2275 */
1defdda8
DS
2276 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
2277 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG))
d62a17ae 2278 return 1;
2279
2bb9eff4
DS
2280 /*
2281 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2282 */
18ee8310
DS
2283 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2284 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2285 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2286 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
d62a17ae 2287 return 1;
2288 }
3064bf43 2289
d62a17ae 2290 /* Nothing has changed from the RIB's perspective. */
2291 return 0;
3064bf43 2292}
2293
d62a17ae 2294struct bgp_process_queue {
2295 struct bgp *bgp;
a4d82a8a 2296 STAILQ_HEAD(, bgp_node) pqueue;
aac24838
JB
2297#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2298 unsigned int flags;
2299 unsigned int queued;
200df115 2300};
2301
3103e8d2
DS
2302/*
2303 * old_select = The old best path
2304 * new_select = the new best path
2305 *
2306 * if (!old_select && new_select)
2307 * We are sending new information on.
2308 *
2309 * if (old_select && new_select) {
2310 * if (new_select != old_select)
2311 * We have a new best path send a change
2312 * else
2313 * We've received a update with new attributes that needs
2314 * to be passed on.
2315 * }
2316 *
2317 * if (old_select && !new_select)
2318 * We have no eligible route that we can announce or the rn
2319 * is being removed.
2320 */
aac24838
JB
2321static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
2322 afi_t afi, safi_t safi)
d62a17ae 2323{
4b7e6066
DS
2324 struct bgp_path_info *new_select;
2325 struct bgp_path_info *old_select;
2326 struct bgp_path_info_pair old_and_new;
ddb5b488
PZ
2327 char pfx_buf[PREFIX2STR_BUFFER];
2328 int debug = 0;
d62a17ae 2329
f4c713ae
LB
2330 if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS)) {
2331 if (rn)
2332 debug = bgp_debug_bestpath(&rn->p);
2333 if (debug) {
2334 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2335 zlog_debug(
2336 "%s: bgp delete in progress, ignoring event, p=%s",
2337 __func__, pfx_buf);
2338 }
2339 return;
2340 }
d62a17ae 2341 /* Is it end of initial update? (after startup) */
2342 if (!rn) {
2343 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2344 sizeof(bgp->update_delay_zebra_resume_time));
2345
2346 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2347 FOREACH_AFI_SAFI (afi, safi) {
2348 if (bgp_fibupd_safi(safi))
2349 bgp_zebra_announce_table(bgp, afi, safi);
2350 }
d62a17ae 2351 bgp->main_peers_update_hold = 0;
2352
2353 bgp_start_routeadv(bgp);
aac24838 2354 return;
d62a17ae 2355 }
cb1faec9 2356
b575a12c
A
2357 struct prefix *p = &rn->p;
2358
ddb5b488
PZ
2359 debug = bgp_debug_bestpath(&rn->p);
2360 if (debug) {
2361 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2362 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__, pfx_buf,
2363 afi2str(afi), safi2str(safi));
2364 }
2365
d62a17ae 2366 /* Best path selection. */
2367 bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new,
2368 afi, safi);
2369 old_select = old_and_new.old;
2370 new_select = old_and_new.new;
2371
2372 /* Do we need to allocate or free labels?
2373 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2374 * necessary to do this upon changes to best path. Exceptions:
2375 * - label index has changed -> recalculate resulting label
2376 * - path_info sub_type changed -> switch to/from implicit-null
2377 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2378 */
318cac96 2379 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2380 if (new_select) {
2381 if (!old_select
2382 || bgp_label_index_differs(new_select, old_select)
57592a53
AD
2383 || new_select->sub_type != old_select->sub_type
2384 || !bgp_is_valid_label(&rn->local_label)) {
2385 /* Enforced penultimate hop popping:
2386 * implicit-null for local routes, aggregate
2387 * and redistributed routes
2388 */
d62a17ae 2389 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2390 || new_select->sub_type
2391 == BGP_ROUTE_AGGREGATE
2392 || new_select->sub_type
2393 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2394 if (CHECK_FLAG(
2395 rn->flags,
2396 BGP_NODE_REGISTERED_FOR_LABEL))
2397 bgp_unregister_for_label(rn);
70e98a7f 2398 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
d62a17ae 2399 &rn->local_label);
2400 bgp_set_valid_label(&rn->local_label);
2401 } else
2402 bgp_register_for_label(rn, new_select);
2403 }
a4d82a8a
PZ
2404 } else if (CHECK_FLAG(rn->flags,
2405 BGP_NODE_REGISTERED_FOR_LABEL)) {
d62a17ae 2406 bgp_unregister_for_label(rn);
318cac96
DW
2407 }
2408 } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
2409 bgp_unregister_for_label(rn);
d62a17ae 2410 }
cd1964ff 2411
ddb5b488
PZ
2412 if (debug) {
2413 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2414 zlog_debug(
2415 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2416 __func__, pfx_buf, afi2str(afi), safi2str(safi),
2417 old_select, new_select);
2418 }
2419
d62a17ae 2420 /* If best route remains the same and this is not due to user-initiated
2421 * clear, see exactly what needs to be done.
2422 */
d62a17ae 2423 if (old_select && old_select == new_select
2424 && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
1defdda8 2425 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2426 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 2427 if (bgp_zebra_has_route_changed(rn, old_select)) {
65efcfce 2428#if ENABLE_BGP_VNC
d62a17ae 2429 vnc_import_bgp_add_route(bgp, p, old_select);
2430 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2431#endif
bb744275 2432 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2433 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2434
2435 if (new_select->type == ZEBRA_ROUTE_BGP
2436 && (new_select->sub_type == BGP_ROUTE_NORMAL
2437 || new_select->sub_type
2438 == BGP_ROUTE_IMPORTED))
2439
2440 bgp_zebra_announce(rn, p, old_select,
2441 bgp, afi, safi);
2442 }
d62a17ae 2443 }
1defdda8 2444 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
d62a17ae 2445 bgp_zebra_clear_route_change_flags(rn);
2446
2447 /* If there is a change of interest to peers, reannounce the
2448 * route. */
1defdda8 2449 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
d62a17ae 2450 || CHECK_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED)) {
2451 group_announce_route(bgp, afi, safi, rn, new_select);
2452
2453 /* unicast routes must also be annouced to
2454 * labeled-unicast update-groups */
2455 if (safi == SAFI_UNICAST)
2456 group_announce_route(bgp, afi,
2457 SAFI_LABELED_UNICAST, rn,
2458 new_select);
2459
1defdda8 2460 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2461 UNSET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED);
2462 }
fee0f4c6 2463
d62a17ae 2464 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2465 return;
d62a17ae 2466 }
8ad7271d 2467
d62a17ae 2468 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2469 */
2470 UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR);
2471
2472 /* bestpath has changed; bump version */
2473 if (old_select || new_select) {
2474 bgp_bump_version(rn);
2475
2476 if (!bgp->t_rmap_def_originate_eval) {
2477 bgp_lock(bgp);
2478 thread_add_timer(
2479 bm->master,
2480 update_group_refresh_default_originate_route_map,
2481 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2482 &bgp->t_rmap_def_originate_eval);
2483 }
2484 }
3f9c7369 2485
d62a17ae 2486 if (old_select)
18ee8310 2487 bgp_path_info_unset_flag(rn, old_select, BGP_PATH_SELECTED);
d62a17ae 2488 if (new_select) {
ddb5b488
PZ
2489 if (debug)
2490 zlog_debug("%s: setting SELECTED flag", __func__);
18ee8310
DS
2491 bgp_path_info_set_flag(rn, new_select, BGP_PATH_SELECTED);
2492 bgp_path_info_unset_flag(rn, new_select, BGP_PATH_ATTR_CHANGED);
1defdda8 2493 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
d62a17ae 2494 }
338b3424 2495
65efcfce 2496#if ENABLE_BGP_VNC
d62a17ae 2497 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2498 if (old_select != new_select) {
2499 if (old_select) {
2500 vnc_import_bgp_exterior_del_route(bgp, p,
2501 old_select);
2502 vnc_import_bgp_del_route(bgp, p, old_select);
2503 }
2504 if (new_select) {
2505 vnc_import_bgp_exterior_add_route(bgp, p,
2506 new_select);
2507 vnc_import_bgp_add_route(bgp, p, new_select);
2508 }
2509 }
2510 }
65efcfce
LB
2511#endif
2512
d62a17ae 2513 group_announce_route(bgp, afi, safi, rn, new_select);
2514
2515 /* unicast routes must also be annouced to labeled-unicast update-groups
2516 */
2517 if (safi == SAFI_UNICAST)
2518 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, rn,
2519 new_select);
2520
2521 /* FIB update. */
2522 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2523 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2524 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2525 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2526 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2527 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2528
2529 /* if this is an evpn imported type-5 prefix,
2530 * we need to withdraw the route first to clear
2531 * the nh neigh and the RMAC entry.
2532 */
2533 if (old_select &&
2534 is_route_parent_evpn(old_select))
2535 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2536
d62a17ae 2537 bgp_zebra_announce(rn, p, new_select, bgp, afi, safi);
2b659f33 2538 } else {
d62a17ae 2539 /* Withdraw the route from the kernel. */
2540 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2541 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2542 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2543 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2544
568e10ca 2545 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2546 }
718e3744 2547 }
3064bf43 2548
5424b7ba
MK
2549 /* advertise/withdraw type-5 routes */
2550 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
f106e3a7 2551 if (advertise_type5_routes(bgp, afi) &&
2552 new_select &&
2553 is_route_injectable_into_evpn(new_select)) {
7e4ed18e
MK
2554
2555 /* apply the route-map */
2556 if (bgp->adv_cmd_rmap[afi][safi].map) {
b68885f9 2557 route_map_result_t ret;
7e4ed18e 2558
3518f352
DS
2559 ret = route_map_apply(
2560 bgp->adv_cmd_rmap[afi][safi].map,
2561 &rn->p, RMAP_BGP, new_select);
b68885f9 2562 if (ret == RMAP_PERMITMATCH)
3518f352
DS
2563 bgp_evpn_advertise_type5_route(
2564 bgp, &rn->p, new_select->attr,
2565 afi, safi);
c27ee4c4 2566 else
2567 bgp_evpn_withdraw_type5_route(
2568 bgp, &rn->p, afi, safi);
7e4ed18e
MK
2569 } else {
2570 bgp_evpn_advertise_type5_route(bgp,
2571 &rn->p,
2572 new_select->attr,
2573 afi, safi);
2574
2575 }
f106e3a7 2576 } else if (advertise_type5_routes(bgp, afi) &&
2577 old_select &&
2578 is_route_injectable_into_evpn(old_select))
31310b25 2579 bgp_evpn_withdraw_type5_route(bgp, &rn->p, afi, safi);
5424b7ba
MK
2580 }
2581
d62a17ae 2582 /* Clear any route change flags. */
2583 bgp_zebra_clear_route_change_flags(rn);
3064bf43 2584
18ee8310 2585 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2586 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
18ee8310 2587 bgp_path_info_reap(rn, old_select);
d62a17ae 2588
2589 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2590 return;
718e3744 2591}
2592
aac24838 2593static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 2594{
aac24838
JB
2595 struct bgp_process_queue *pqnode = data;
2596 struct bgp *bgp = pqnode->bgp;
d62a17ae 2597 struct bgp_table *table;
ac021f40 2598 struct bgp_node *rn;
aac24838
JB
2599
2600 /* eoiu marker */
2601 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
2602 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
2603 /* should always have dedicated wq call */
2604 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
2605 return WQ_SUCCESS;
2606 }
2607
ac021f40
LB
2608 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
2609 rn = STAILQ_FIRST(&pqnode->pqueue);
2610 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
b3e1dd3c 2611 STAILQ_NEXT(rn, pq) = NULL; /* complete unlink */
aac24838 2612 table = bgp_node_table(rn);
ac021f40 2613 /* note, new RNs may be added as part of processing */
aac24838 2614 bgp_process_main_one(bgp, rn, table->afi, table->safi);
cb1faec9 2615
aac24838 2616 bgp_unlock_node(rn);
d62a17ae 2617 bgp_table_unlock(table);
2618 }
aac24838
JB
2619
2620 return WQ_SUCCESS;
2621}
2622
2623static void bgp_processq_del(struct work_queue *wq, void *data)
2624{
2625 struct bgp_process_queue *pqnode = data;
2626
2627 bgp_unlock(pqnode->bgp);
2628
2629 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 2630}
2631
d62a17ae 2632void bgp_process_queue_init(void)
200df115 2633{
0ce1ca80 2634 if (!bm->process_main_queue)
d62a17ae 2635 bm->process_main_queue =
2636 work_queue_new(bm->master, "process_main_queue");
2637
aac24838 2638 bm->process_main_queue->spec.workfunc = &bgp_process_wq;
d62a17ae 2639 bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
2640 bm->process_main_queue->spec.max_retries = 0;
2641 bm->process_main_queue->spec.hold = 50;
2642 /* Use a higher yield value of 50ms for main queue processing */
2643 bm->process_main_queue->spec.yield = 50 * 1000L;
200df115 2644}
2645
cfe8d15a 2646static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
2647{
2648 struct bgp_process_queue *pqnode;
2649
a4d82a8a
PZ
2650 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
2651 sizeof(struct bgp_process_queue));
aac24838
JB
2652
2653 /* unlocked in bgp_processq_del */
2654 pqnode->bgp = bgp_lock(bgp);
2655 STAILQ_INIT(&pqnode->pqueue);
2656
aac24838
JB
2657 return pqnode;
2658}
2659
d62a17ae 2660void bgp_process(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)
fee0f4c6 2661{
aac24838
JB
2662#define ARBITRARY_PROCESS_QLEN 10000
2663 struct work_queue *wq = bm->process_main_queue;
d62a17ae 2664 struct bgp_process_queue *pqnode;
cfe8d15a 2665 int pqnode_reuse = 0;
495f0b13 2666
d62a17ae 2667 /* already scheduled for processing? */
2668 if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED))
2669 return;
2e02b9b2 2670
aac24838 2671 if (wq == NULL)
d62a17ae 2672 return;
2673
aac24838 2674 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
2675 limit only if is from the same BGP view and it's not an EOIU marker
2676 */
aac24838
JB
2677 if (work_queue_item_count(wq)) {
2678 struct work_queue_item *item = work_queue_last_item(wq);
2679 pqnode = item->data;
228da428 2680
a4d82a8a
PZ
2681 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
2682 || pqnode->bgp != bgp
2683 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
2684 pqnode = bgp_processq_alloc(bgp);
2685 else
2686 pqnode_reuse = 1;
aac24838 2687 } else
cfe8d15a 2688 pqnode = bgp_processq_alloc(bgp);
aac24838 2689 /* all unlocked in bgp_process_wq */
d62a17ae 2690 bgp_table_lock(bgp_node_table(rn));
aac24838 2691
d62a17ae 2692 SET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838
JB
2693 bgp_lock_node(rn);
2694
60466a63
QY
2695 /* can't be enqueued twice */
2696 assert(STAILQ_NEXT(rn, pq) == NULL);
aac24838
JB
2697 STAILQ_INSERT_TAIL(&pqnode->pqueue, rn, pq);
2698 pqnode->queued++;
2699
cfe8d15a
LB
2700 if (!pqnode_reuse)
2701 work_queue_add(wq, pqnode);
2702
d62a17ae 2703 return;
fee0f4c6 2704}
0a486e5f 2705
d62a17ae 2706void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 2707{
d62a17ae 2708 struct bgp_process_queue *pqnode;
cb1faec9 2709
d62a17ae 2710 if (bm->process_main_queue == NULL)
2711 return;
2e02b9b2 2712
cfe8d15a 2713 pqnode = bgp_processq_alloc(bgp);
cb1faec9 2714
aac24838 2715 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
cfe8d15a 2716 work_queue_add(bm->process_main_queue, pqnode);
cb1faec9
DS
2717}
2718
d62a17ae 2719static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 2720{
d62a17ae 2721 struct peer *peer;
0a486e5f 2722
d62a17ae 2723 peer = THREAD_ARG(thread);
2724 peer->t_pmax_restart = NULL;
0a486e5f 2725
d62a17ae 2726 if (bgp_debug_neighbor_events(peer))
2727 zlog_debug(
2728 "%s Maximum-prefix restart timer expired, restore peering",
2729 peer->host);
0a486e5f 2730
a9bafa95
DS
2731 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
2732 zlog_debug("%s: %s peer_clear failed",
2733 __PRETTY_FUNCTION__, peer->host);
0a486e5f 2734
d62a17ae 2735 return 0;
0a486e5f 2736}
2737
d62a17ae 2738int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
2739 int always)
718e3744 2740{
d62a17ae 2741 iana_afi_t pkt_afi;
5c525538 2742 iana_safi_t pkt_safi;
9cabb64b 2743
d62a17ae 2744 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
2745 return 0;
e0701b79 2746
d62a17ae 2747 if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) {
2748 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2749 PEER_STATUS_PREFIX_LIMIT)
2750 && !always)
2751 return 0;
e0701b79 2752
d62a17ae 2753 zlog_info(
a0a87037
DA
2754 "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32
2755 " exceed, limit %" PRIu32,
5cb5f4d0 2756 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 2757 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2758 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
2759
2760 if (CHECK_FLAG(peer->af_flags[afi][safi],
2761 PEER_FLAG_MAX_PREFIX_WARNING))
2762 return 0;
2763
2764 /* Convert AFI, SAFI to values for packet. */
2765 pkt_afi = afi_int2iana(afi);
2766 pkt_safi = safi_int2iana(safi);
2767 {
d7c0a89a 2768 uint8_t ndata[7];
d62a17ae 2769
2770 ndata[0] = (pkt_afi >> 8);
2771 ndata[1] = pkt_afi;
2772 ndata[2] = pkt_safi;
2773 ndata[3] = (peer->pmax[afi][safi] >> 24);
2774 ndata[4] = (peer->pmax[afi][safi] >> 16);
2775 ndata[5] = (peer->pmax[afi][safi] >> 8);
2776 ndata[6] = (peer->pmax[afi][safi]);
2777
2778 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2779 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
2780 BGP_NOTIFY_CEASE_MAX_PREFIX,
2781 ndata, 7);
2782 }
2783
2784 /* Dynamic peers will just close their connection. */
2785 if (peer_dynamic_neighbor(peer))
2786 return 1;
2787
2788 /* restart timer start */
2789 if (peer->pmax_restart[afi][safi]) {
2790 peer->v_pmax_restart =
2791 peer->pmax_restart[afi][safi] * 60;
2792
2793 if (bgp_debug_neighbor_events(peer))
2794 zlog_debug(
2795 "%s Maximum-prefix restart timer started for %d secs",
2796 peer->host, peer->v_pmax_restart);
2797
2798 BGP_TIMER_ON(peer->t_pmax_restart,
2799 bgp_maximum_prefix_restart_timer,
2800 peer->v_pmax_restart);
2801 }
2802
2803 return 1;
2804 } else
2805 UNSET_FLAG(peer->af_sflags[afi][safi],
2806 PEER_STATUS_PREFIX_LIMIT);
2807
2808 if (peer->pcount[afi][safi]
2809 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
2810 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2811 PEER_STATUS_PREFIX_THRESHOLD)
2812 && !always)
2813 return 0;
2814
2815 zlog_info(
a0a87037
DA
2816 "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32
2817 ", max %" PRIu32,
5cb5f4d0 2818 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 2819 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2820 SET_FLAG(peer->af_sflags[afi][safi],
2821 PEER_STATUS_PREFIX_THRESHOLD);
2822 } else
2823 UNSET_FLAG(peer->af_sflags[afi][safi],
2824 PEER_STATUS_PREFIX_THRESHOLD);
2825 return 0;
718e3744 2826}
2827
b40d939b 2828/* Unconditionally remove the route from the RIB, without taking
2829 * damping into consideration (eg, because the session went down)
2830 */
40381db7 2831void bgp_rib_remove(struct bgp_node *rn, struct bgp_path_info *pi,
4b7e6066 2832 struct peer *peer, afi_t afi, safi_t safi)
718e3744 2833{
40381db7 2834 bgp_aggregate_decrement(peer->bgp, &rn->p, pi, afi, safi);
d62a17ae 2835
40381db7
DS
2836 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
2837 bgp_path_info_delete(rn, pi); /* keep historical info */
d62a17ae 2838
4a11bf2c
DL
2839 hook_call(bgp_process, peer->bgp, afi, safi, rn, peer, true);
2840
d62a17ae 2841 bgp_process(peer->bgp, rn, afi, safi);
2842}
2843
40381db7 2844static void bgp_rib_withdraw(struct bgp_node *rn, struct bgp_path_info *pi,
d62a17ae 2845 struct peer *peer, afi_t afi, safi_t safi,
2846 struct prefix_rd *prd)
2847{
d62a17ae 2848 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 2849 * the bgp_path_info in the RIB for historical reference.
d62a17ae 2850 */
2851 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
2852 && peer->sort == BGP_PEER_EBGP)
40381db7 2853 if ((bgp_damp_withdraw(pi, rn, afi, safi, 0))
d62a17ae 2854 == BGP_DAMP_SUPPRESSED) {
40381db7 2855 bgp_aggregate_decrement(peer->bgp, &rn->p, pi, afi,
d62a17ae 2856 safi);
2857 return;
2858 }
2859
65efcfce 2860#if ENABLE_BGP_VNC
d62a17ae 2861 if (safi == SAFI_MPLS_VPN) {
2862 struct bgp_node *prn = NULL;
2863 struct bgp_table *table = NULL;
2864
2865 prn = bgp_node_get(peer->bgp->rib[afi][safi],
2866 (struct prefix *)prd);
67009e22
DS
2867 if (bgp_node_has_bgp_path_info_data(prn)) {
2868 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 2869
2870 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 2871 peer->bgp, prd, table, &rn->p, pi);
d62a17ae 2872 }
2873 bgp_unlock_node(prn);
2874 }
2875 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 2876 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 2877
40381db7 2878 vnc_import_bgp_del_route(peer->bgp, &rn->p, pi);
d62a17ae 2879 vnc_import_bgp_exterior_del_route(peer->bgp, &rn->p,
40381db7 2880 pi);
d62a17ae 2881 }
65efcfce 2882 }
d62a17ae 2883#endif
128ea8ab 2884
d62a17ae 2885 /* If this is an EVPN route, process for un-import. */
2886 if (safi == SAFI_EVPN)
40381db7 2887 bgp_evpn_unimport_route(peer->bgp, afi, safi, &rn->p, pi);
128ea8ab 2888
40381db7 2889 bgp_rib_remove(rn, pi, peer, afi, safi);
718e3744 2890}
2891
4b7e6066
DS
2892struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
2893 struct peer *peer, struct attr *attr,
2894 struct bgp_node *rn)
fb018d25 2895{
4b7e6066 2896 struct bgp_path_info *new;
fb018d25 2897
d62a17ae 2898 /* Make new BGP info. */
4b7e6066 2899 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 2900 new->type = type;
2901 new->instance = instance;
2902 new->sub_type = sub_type;
2903 new->peer = peer;
2904 new->attr = attr;
2905 new->uptime = bgp_clock();
2906 new->net = rn;
d62a17ae 2907 return new;
fb018d25
DS
2908}
2909
d62a17ae 2910static void overlay_index_update(struct attr *attr,
2911 struct eth_segment_id *eth_s_id,
2912 union gw_addr *gw_ip)
684a7227 2913{
d62a17ae 2914 if (!attr)
2915 return;
684a7227 2916
d62a17ae 2917 if (eth_s_id == NULL) {
2918 memset(&(attr->evpn_overlay.eth_s_id), 0,
2919 sizeof(struct eth_segment_id));
2920 } else {
2921 memcpy(&(attr->evpn_overlay.eth_s_id), eth_s_id,
2922 sizeof(struct eth_segment_id));
2923 }
2924 if (gw_ip == NULL) {
2925 memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr));
2926 } else {
2927 memcpy(&(attr->evpn_overlay.gw_ip), gw_ip,
2928 sizeof(union gw_addr));
2929 }
684a7227
PG
2930}
2931
40381db7 2932static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 2933 struct eth_segment_id *eth_s_id,
2934 union gw_addr *gw_ip)
2935{
40381db7
DS
2936 struct eth_segment_id *path_eth_s_id, *path_eth_s_id_remote;
2937 union gw_addr *path_gw_ip, *path_gw_ip_remote;
11ebf4ed
DS
2938 union {
2939 struct eth_segment_id esi;
2940 union gw_addr ip;
2941 } temp;
d62a17ae 2942
2943 if (afi != AFI_L2VPN)
2944 return true;
11ebf4ed 2945
05864da7
DS
2946 path_eth_s_id = &(path->attr->evpn_overlay.eth_s_id);
2947 path_gw_ip = &(path->attr->evpn_overlay.gw_ip);
11ebf4ed
DS
2948
2949 if (gw_ip == NULL) {
2950 memset(&temp, 0, sizeof(temp));
40381db7 2951 path_gw_ip_remote = &temp.ip;
11ebf4ed 2952 } else
40381db7 2953 path_gw_ip_remote = gw_ip;
11ebf4ed
DS
2954
2955 if (eth_s_id == NULL) {
2956 memset(&temp, 0, sizeof(temp));
40381db7 2957 path_eth_s_id_remote = &temp.esi;
11ebf4ed 2958 } else
40381db7 2959 path_eth_s_id_remote = eth_s_id;
11ebf4ed 2960
40381db7 2961 if (!memcmp(path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr)))
d62a17ae 2962 return false;
11ebf4ed 2963
40381db7 2964 return !memcmp(path_eth_s_id, path_eth_s_id_remote,
d62a17ae 2965 sizeof(struct eth_segment_id));
684a7227
PG
2966}
2967
c265ee22 2968/* Check if received nexthop is valid or not. */
d62a17ae 2969static int bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
2970 struct attr *attr)
2971{
2972 int ret = 0;
2973
2974 /* Only validated for unicast and multicast currently. */
2975 /* Also valid for EVPN where the nexthop is an IP address. */
2976 if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN)
2977 return 0;
2978
2979 /* If NEXT_HOP is present, validate it. */
2980 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
2981 if (attr->nexthop.s_addr == 0
2982 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
2983 || bgp_nexthop_self(bgp, attr->nexthop))
2984 return 1;
2985 }
c265ee22 2986
d62a17ae 2987 /* If MP_NEXTHOP is present, validate it. */
2988 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2989 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2990 * it is not an IPv6 link-local address.
2991 */
2992 if (attr->mp_nexthop_len) {
2993 switch (attr->mp_nexthop_len) {
2994 case BGP_ATTR_NHLEN_IPV4:
2995 case BGP_ATTR_NHLEN_VPNV4:
2996 ret = (attr->mp_nexthop_global_in.s_addr == 0
2997 || IPV4_CLASS_DE(ntohl(
2998 attr->mp_nexthop_global_in.s_addr))
2999 || bgp_nexthop_self(bgp,
3000 attr->mp_nexthop_global_in));
3001 break;
3002
3003 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
3004 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3005 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
3006 ret = (IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global)
3007 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3008 || IN6_IS_ADDR_MULTICAST(
5e76ce50 3009 &attr->mp_nexthop_global));
d62a17ae 3010 break;
3011
3012 default:
3013 ret = 1;
3014 break;
3015 }
3016 }
c265ee22 3017
d62a17ae 3018 return ret;
3019}
3020
d7c0a89a 3021int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
d62a17ae 3022 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3023 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3024 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3025 struct bgp_route_evpn *evpn)
d62a17ae 3026{
3027 int ret;
3028 int aspath_loop_count = 0;
3029 struct bgp_node *rn;
3030 struct bgp *bgp;
3031 struct attr new_attr;
3032 struct attr *attr_new;
40381db7 3033 struct bgp_path_info *pi;
4b7e6066
DS
3034 struct bgp_path_info *new;
3035 struct bgp_path_info_extra *extra;
d62a17ae 3036 const char *reason;
3037 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3038 int connected = 0;
3039 int do_loop_check = 1;
3040 int has_valid_label = 0;
65efcfce 3041#if ENABLE_BGP_VNC
d62a17ae 3042 int vnc_implicit_withdraw = 0;
65efcfce 3043#endif
d62a17ae 3044 int same_attr = 0;
718e3744 3045
d62a17ae 3046 memset(&new_attr, 0, sizeof(struct attr));
3047 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3048 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3049
d62a17ae 3050 bgp = peer->bgp;
3051 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3052 /* TODO: Check to see if we can get rid of "is_valid_label" */
3053 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3054 has_valid_label = (num_labels > 0) ? 1 : 0;
3055 else
3056 has_valid_label = bgp_is_valid_label(label);
718e3744 3057
d62a17ae 3058 /* When peer's soft reconfiguration enabled. Record input packet in
3059 Adj-RIBs-In. */
3060 if (!soft_reconfig
3061 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3062 && peer != bgp->peer_self)
3063 bgp_adj_in_set(rn, peer, attr, addpath_id);
3064
3065 /* Check previously received route. */
6f94b685 3066 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
3067 if (pi->peer == peer && pi->type == type
3068 && pi->sub_type == sub_type
3069 && pi->addpath_rx_id == addpath_id)
d62a17ae 3070 break;
3071
3072 /* AS path local-as loop check. */
3073 if (peer->change_local_as) {
c4368918
DW
3074 if (peer->allowas_in[afi][safi])
3075 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3076 else if (!CHECK_FLAG(peer->flags,
3077 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3078 aspath_loop_count = 1;
3079
3080 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3081 > aspath_loop_count) {
b4d46cc9 3082 peer->stat_pfx_aspath_loop++;
d62a17ae 3083 reason = "as-path contains our own AS;";
3084 goto filtered;
3085 }
718e3744 3086 }
718e3744 3087
d62a17ae 3088 /* If the peer is configured for "allowas-in origin" and the last ASN in
3089 * the
3090 * as-path is our ASN then we do not need to call aspath_loop_check
3091 */
3092 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3093 if (aspath_get_last_as(attr->aspath) == bgp->as)
3094 do_loop_check = 0;
3095
3096 /* AS path loop check. */
3097 if (do_loop_check) {
3098 if (aspath_loop_check(attr->aspath, bgp->as)
3099 > peer->allowas_in[afi][safi]
3100 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3101 && aspath_loop_check(attr->aspath, bgp->confed_id)
3102 > peer->allowas_in[afi][safi])) {
b4d46cc9 3103 peer->stat_pfx_aspath_loop++;
d62a17ae 3104 reason = "as-path contains our own AS;";
3105 goto filtered;
3106 }
3107 }
aac9ef6c 3108
d62a17ae 3109 /* Route reflector originator ID check. */
3110 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3111 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3112 peer->stat_pfx_originator_loop++;
d62a17ae 3113 reason = "originator is us;";
3114 goto filtered;
3115 }
718e3744 3116
d62a17ae 3117 /* Route reflector cluster ID check. */
3118 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3119 peer->stat_pfx_cluster_loop++;
d62a17ae 3120 reason = "reflected from the same cluster;";
3121 goto filtered;
3122 }
718e3744 3123
d62a17ae 3124 /* Apply incoming filter. */
3125 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3126 peer->stat_pfx_filter++;
d62a17ae 3127 reason = "filter;";
3128 goto filtered;
3129 }
718e3744 3130
a8b72dc6
DA
3131 /* RFC 8212 to prevent route leaks.
3132 * This specification intends to improve this situation by requiring the
3133 * explicit configuration of both BGP Import and Export Policies for any
3134 * External BGP (EBGP) session such as customers, peers, or
3135 * confederation boundaries for all enabled address families. Through
3136 * codification of the aforementioned requirement, operators will
3137 * benefit from consistent behavior across different BGP
3138 * implementations.
3139 */
3140 if (peer->bgp->ebgp_requires_policy == DEFAULT_EBGP_POLICY_ENABLED)
3141 if (!bgp_inbound_policy_exists(peer,
3142 &peer->filter[afi][safi])) {
3143 reason = "inbound policy missing";
3144 goto filtered;
3145 }
3146
d62a17ae 3147 bgp_attr_dup(&new_attr, attr);
3148
3149 /* Apply incoming route-map.
3150 * NB: new_attr may now contain newly allocated values from route-map
3151 * "set"
3152 * commands, so we need bgp_attr_flush in the error paths, until we
3153 * intern
3154 * the attr (which takes over the memory references) */
82b692c0
LK
3155 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL,
3156 label, num_labels) == RMAP_DENY) {
b4d46cc9 3157 peer->stat_pfx_filter++;
d62a17ae 3158 reason = "route-map;";
3159 bgp_attr_flush(&new_attr);
3160 goto filtered;
3161 }
718e3744 3162
05864da7 3163 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3164 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3165 /* remove from RIB previous entry */
3166 bgp_zebra_withdraw(p, pi, bgp, safi);
3167 }
3168
7f323236
DW
3169 if (peer->sort == BGP_PEER_EBGP) {
3170
a4d82a8a
PZ
3171 /* If we receive the graceful-shutdown community from an eBGP
3172 * peer we must lower local-preference */
3173 if (new_attr.community
3174 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3175 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3176 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3177
a4d82a8a
PZ
3178 /* If graceful-shutdown is configured then add the GSHUT
3179 * community to all paths received from eBGP peers */
3180 } else if (bgp_flag_check(peer->bgp,
3181 BGP_FLAG_GRACEFUL_SHUTDOWN)) {
7f323236
DW
3182 bgp_attr_add_gshut_community(&new_attr);
3183 }
3184 }
3185
d62a17ae 3186 /* next hop check. */
a4d82a8a
PZ
3187 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
3188 && bgp_update_martian_nexthop(bgp, afi, safi, &new_attr)) {
b4d46cc9 3189 peer->stat_pfx_nh_invalid++;
d62a17ae 3190 reason = "martian or self next-hop;";
3191 bgp_attr_flush(&new_attr);
3192 goto filtered;
3193 }
718e3744 3194
5c14a191 3195 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3196 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3197 reason = "self mac;";
3198 goto filtered;
3199 }
3200
d62a17ae 3201 attr_new = bgp_attr_intern(&new_attr);
3202
3203 /* If the update is implicit withdraw. */
40381db7
DS
3204 if (pi) {
3205 pi->uptime = bgp_clock();
3206 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3207
4a11bf2c
DL
3208 hook_call(bgp_process, bgp, afi, safi, rn, peer, true);
3209
d62a17ae 3210 /* Same attribute comes in. */
40381db7
DS
3211 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3212 && attrhash_cmp(pi->attr, attr_new)
d62a17ae 3213 && (!has_valid_label
40381db7 3214 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3215 num_labels * sizeof(mpls_label_t))
d62a17ae 3216 == 0)
3217 && (overlay_index_equal(
40381db7 3218 afi, pi, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3219 evpn == NULL ? NULL : &evpn->gw_ip))) {
3220 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3221 BGP_CONFIG_DAMPENING)
3222 && peer->sort == BGP_PEER_EBGP
40381db7 3223 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3224 if (bgp_debug_update(peer, p, NULL, 1)) {
3225 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3226 afi, safi, prd, p, label,
3227 num_labels, addpath_id ? 1 : 0,
3228 addpath_id, pfx_buf,
3229 sizeof(pfx_buf));
d62a17ae 3230 zlog_debug("%s rcvd %s", peer->host,
3231 pfx_buf);
3232 }
3233
40381db7 3234 if (bgp_damp_update(pi, rn, afi, safi)
d62a17ae 3235 != BGP_DAMP_SUPPRESSED) {
40381db7 3236 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3237 safi);
3238 bgp_process(bgp, rn, afi, safi);
3239 }
3240 } else /* Duplicate - odd */
3241 {
3242 if (bgp_debug_update(peer, p, NULL, 1)) {
3243 if (!peer->rcvd_attr_printed) {
3244 zlog_debug(
3245 "%s rcvd UPDATE w/ attr: %s",
3246 peer->host,
3247 peer->rcvd_attr_str);
3248 peer->rcvd_attr_printed = 1;
3249 }
3250
3251 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3252 afi, safi, prd, p, label,
3253 num_labels, addpath_id ? 1 : 0,
3254 addpath_id, pfx_buf,
3255 sizeof(pfx_buf));
d62a17ae 3256 zlog_debug(
3257 "%s rcvd %s...duplicate ignored",
3258 peer->host, pfx_buf);
3259 }
3260
3261 /* graceful restart STALE flag unset. */
40381db7 3262 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3263 bgp_path_info_unset_flag(
40381db7 3264 rn, pi, BGP_PATH_STALE);
d62a17ae 3265 bgp_process(bgp, rn, afi, safi);
3266 }
3267 }
3268
3269 bgp_unlock_node(rn);
3270 bgp_attr_unintern(&attr_new);
3271
3272 return 0;
3273 }
718e3744 3274
d62a17ae 3275 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3276 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3277 if (bgp_debug_update(peer, p, NULL, 1)) {
3278 bgp_debug_rdpfxpath2str(
a4d82a8a 3279 afi, safi, prd, p, label, num_labels,
d62a17ae 3280 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3281 sizeof(pfx_buf));
3282 zlog_debug(
3283 "%s rcvd %s, flapped quicker than processing",
3284 peer->host, pfx_buf);
3285 }
3286
40381db7 3287 bgp_path_info_restore(rn, pi);
d62a17ae 3288 }
718e3744 3289
d62a17ae 3290 /* Received Logging. */
3291 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3292 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3293 num_labels, addpath_id ? 1 : 0,
3294 addpath_id, pfx_buf,
3295 sizeof(pfx_buf));
d62a17ae 3296 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3297 }
718e3744 3298
d62a17ae 3299 /* graceful restart STALE flag unset. */
40381db7
DS
3300 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
3301 bgp_path_info_unset_flag(rn, pi, BGP_PATH_STALE);
d62a17ae 3302
3303 /* The attribute is changed. */
40381db7 3304 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3305
3306 /* implicit withdraw, decrement aggregate and pcount here.
3307 * only if update is accepted, they'll increment below.
3308 */
40381db7 3309 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3310
3311 /* Update bgp route dampening information. */
3312 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3313 && peer->sort == BGP_PEER_EBGP) {
3314 /* This is implicit withdraw so we should update
3315 dampening
3316 information. */
40381db7
DS
3317 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
3318 bgp_damp_withdraw(pi, rn, afi, safi, 1);
d62a17ae 3319 }
65efcfce 3320#if ENABLE_BGP_VNC
d62a17ae 3321 if (safi == SAFI_MPLS_VPN) {
3322 struct bgp_node *prn = NULL;
3323 struct bgp_table *table = NULL;
3324
3325 prn = bgp_node_get(bgp->rib[afi][safi],
3326 (struct prefix *)prd);
67009e22
DS
3327 if (bgp_node_has_bgp_path_info_data(prn)) {
3328 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3329
3330 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3331 bgp, prd, table, p, pi);
d62a17ae 3332 }
3333 bgp_unlock_node(prn);
3334 }
3335 if ((afi == AFI_IP || afi == AFI_IP6)
3336 && (safi == SAFI_UNICAST)) {
40381db7 3337 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3338 /*
3339 * Implicit withdraw case.
3340 */
3341 ++vnc_implicit_withdraw;
40381db7
DS
3342 vnc_import_bgp_del_route(bgp, p, pi);
3343 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3344 }
3345 }
65efcfce 3346#endif
128ea8ab 3347
d62a17ae 3348 /* Special handling for EVPN update of an existing route. If the
3349 * extended community attribute has changed, we need to
3350 * un-import
3351 * the route using its existing extended community. It will be
3352 * subsequently processed for import with the new extended
3353 * community.
3354 */
3355 if (safi == SAFI_EVPN && !same_attr) {
40381db7 3356 if ((pi->attr->flag
d62a17ae 3357 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3358 && (attr_new->flag
3359 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3360 int cmp;
3361
40381db7 3362 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3363 attr_new->ecommunity);
3364 if (!cmp) {
3365 if (bgp_debug_update(peer, p, NULL, 1))
3366 zlog_debug(
3367 "Change in EXT-COMM, existing %s new %s",
3368 ecommunity_str(
40381db7 3369 pi->attr->ecommunity),
d62a17ae 3370 ecommunity_str(
3371 attr_new->ecommunity));
3372 bgp_evpn_unimport_route(bgp, afi, safi,
40381db7 3373 p, pi);
d62a17ae 3374 }
3375 }
3376 }
718e3744 3377
d62a17ae 3378 /* Update to new attribute. */
40381db7
DS
3379 bgp_attr_unintern(&pi->attr);
3380 pi->attr = attr_new;
d62a17ae 3381
3382 /* Update MPLS label */
3383 if (has_valid_label) {
40381db7 3384 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3385 if (extra->label != label) {
3386 memcpy(&extra->label, label,
dbd587da 3387 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3388 extra->num_labels = num_labels;
3389 }
b57ba6d2
MK
3390 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3391 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3392 }
718e3744 3393
65efcfce 3394#if ENABLE_BGP_VNC
d62a17ae 3395 if ((afi == AFI_IP || afi == AFI_IP6)
3396 && (safi == SAFI_UNICAST)) {
3397 if (vnc_implicit_withdraw) {
3398 /*
3399 * Add back the route with its new attributes
3400 * (e.g., nexthop).
3401 * The route is still selected, until the route
3402 * selection
3403 * queued by bgp_process actually runs. We have
3404 * to make this
3405 * update to the VNC side immediately to avoid
3406 * racing against
3407 * configuration changes (e.g., route-map
3408 * changes) which
3409 * trigger re-importation of the entire RIB.
3410 */
40381db7
DS
3411 vnc_import_bgp_add_route(bgp, p, pi);
3412 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 3413 }
3414 }
65efcfce 3415#endif
d62a17ae 3416 /* Update Overlay Index */
3417 if (afi == AFI_L2VPN) {
3418 overlay_index_update(
40381db7 3419 pi->attr, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3420 evpn == NULL ? NULL : &evpn->gw_ip);
3421 }
65efcfce 3422
d62a17ae 3423 /* Update bgp route dampening information. */
3424 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3425 && peer->sort == BGP_PEER_EBGP) {
3426 /* Now we do normal update dampening. */
40381db7 3427 ret = bgp_damp_update(pi, rn, afi, safi);
d62a17ae 3428 if (ret == BGP_DAMP_SUPPRESSED) {
3429 bgp_unlock_node(rn);
3430 return 0;
3431 }
3432 }
128ea8ab 3433
d62a17ae 3434 /* Nexthop reachability check - for unicast and
3435 * labeled-unicast.. */
3436 if ((afi == AFI_IP || afi == AFI_IP6)
3437 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
3438 if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1
3439 && !CHECK_FLAG(peer->flags,
3440 PEER_FLAG_DISABLE_CONNECTED_CHECK)
3441 && !bgp_flag_check(
3442 bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
3443 connected = 1;
3444 else
3445 connected = 0;
3446
960035b2
PZ
3447 struct bgp *bgp_nexthop = bgp;
3448
40381db7
DS
3449 if (pi->extra && pi->extra->bgp_orig)
3450 bgp_nexthop = pi->extra->bgp_orig;
960035b2 3451
40381db7
DS
3452 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, afi, pi,
3453 NULL, connected)
a4d82a8a 3454 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
40381db7 3455 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 3456 else {
3457 if (BGP_DEBUG(nht, NHT)) {
3458 char buf1[INET6_ADDRSTRLEN];
3459 inet_ntop(AF_INET,
3460 (const void *)&attr_new
3461 ->nexthop,
3462 buf1, INET6_ADDRSTRLEN);
3463 zlog_debug("%s(%s): NH unresolved",
3464 __FUNCTION__, buf1);
3465 }
40381db7 3466 bgp_path_info_unset_flag(rn, pi,
18ee8310 3467 BGP_PATH_VALID);
d62a17ae 3468 }
3469 } else
40381db7 3470 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 3471
3472#if ENABLE_BGP_VNC
3473 if (safi == SAFI_MPLS_VPN) {
3474 struct bgp_node *prn = NULL;
3475 struct bgp_table *table = NULL;
3476
3477 prn = bgp_node_get(bgp->rib[afi][safi],
3478 (struct prefix *)prd);
67009e22
DS
3479 if (bgp_node_has_bgp_path_info_data(prn)) {
3480 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3481
3482 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 3483 bgp, prd, table, p, pi);
d62a17ae 3484 }
3485 bgp_unlock_node(prn);
3486 }
3487#endif
718e3744 3488
d62a17ae 3489 /* If this is an EVPN route and some attribute has changed,
3490 * process
3491 * route for import. If the extended community has changed, we
3492 * would
3493 * have done the un-import earlier and the import would result
3494 * in the
3495 * route getting injected into appropriate L2 VNIs. If it is
3496 * just
3497 * some other attribute change, the import will result in
3498 * updating
3499 * the attributes for the route in the VNI(s).
3500 */
3501 if (safi == SAFI_EVPN && !same_attr)
40381db7 3502 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 3503
3504 /* Process change. */
40381db7 3505 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 3506
3507 bgp_process(bgp, rn, afi, safi);
3508 bgp_unlock_node(rn);
558d1fec 3509
ddb5b488
PZ
3510 if (SAFI_UNICAST == safi
3511 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3512 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3513
40381db7 3514 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3515 }
3516 if ((SAFI_MPLS_VPN == safi)
3517 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3518
40381db7 3519 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
3520 }
3521
28070ee3 3522#if ENABLE_BGP_VNC
d62a17ae 3523 if (SAFI_MPLS_VPN == safi) {
3524 mpls_label_t label_decoded = decode_label(label);
28070ee3 3525
d62a17ae 3526 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3527 type, sub_type, &label_decoded);
3528 }
3529 if (SAFI_ENCAP == safi) {
3530 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3531 type, sub_type, NULL);
3532 }
28070ee3
PZ
3533#endif
3534
d62a17ae 3535 return 0;
3536 } // End of implicit withdraw
718e3744 3537
d62a17ae 3538 /* Received Logging. */
3539 if (bgp_debug_update(peer, p, NULL, 1)) {
3540 if (!peer->rcvd_attr_printed) {
3541 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3542 peer->rcvd_attr_str);
3543 peer->rcvd_attr_printed = 1;
3544 }
718e3744 3545
a4d82a8a 3546 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3547 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3548 sizeof(pfx_buf));
3549 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3550 }
718e3744 3551
d62a17ae 3552 /* Make new BGP info. */
3553 new = info_make(type, sub_type, 0, peer, attr_new, rn);
718e3744 3554
d62a17ae 3555 /* Update MPLS label */
3556 if (has_valid_label) {
18ee8310 3557 extra = bgp_path_info_extra_get(new);
8ba71050 3558 if (extra->label != label) {
dbd587da
QY
3559 memcpy(&extra->label, label,
3560 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3561 extra->num_labels = num_labels;
3562 }
b57ba6d2
MK
3563 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3564 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3565 }
718e3744 3566
d62a17ae 3567 /* Update Overlay Index */
3568 if (afi == AFI_L2VPN) {
3569 overlay_index_update(new->attr,
3570 evpn == NULL ? NULL : &evpn->eth_s_id,
3571 evpn == NULL ? NULL : &evpn->gw_ip);
3572 }
3573 /* Nexthop reachability check. */
3574 if ((afi == AFI_IP || afi == AFI_IP6)
3575 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
3576 if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1
3577 && !CHECK_FLAG(peer->flags,
3578 PEER_FLAG_DISABLE_CONNECTED_CHECK)
3579 && !bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
3580 connected = 1;
3581 else
3582 connected = 0;
3583
960035b2 3584 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, connected)
a4d82a8a 3585 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
18ee8310 3586 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
d62a17ae 3587 else {
3588 if (BGP_DEBUG(nht, NHT)) {
3589 char buf1[INET6_ADDRSTRLEN];
3590 inet_ntop(AF_INET,
3591 (const void *)&attr_new->nexthop,
3592 buf1, INET6_ADDRSTRLEN);
3593 zlog_debug("%s(%s): NH unresolved",
3594 __FUNCTION__, buf1);
3595 }
18ee8310 3596 bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID);
d62a17ae 3597 }
3598 } else
18ee8310 3599 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
a82478b9 3600
d62a17ae 3601 /* Addpath ID */
3602 new->addpath_rx_id = addpath_id;
3603
3604 /* Increment prefix */
3605 bgp_aggregate_increment(bgp, p, new, afi, safi);
3606
3607 /* Register new BGP information. */
18ee8310 3608 bgp_path_info_add(rn, new);
d62a17ae 3609
3610 /* route_node_get lock */
3611 bgp_unlock_node(rn);
558d1fec 3612
65efcfce 3613#if ENABLE_BGP_VNC
d62a17ae 3614 if (safi == SAFI_MPLS_VPN) {
3615 struct bgp_node *prn = NULL;
3616 struct bgp_table *table = NULL;
3617
3618 prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
67009e22
DS
3619 if (bgp_node_has_bgp_path_info_data(prn)) {
3620 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3621
3622 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3623 bgp, prd, table, p, new);
3624 }
3625 bgp_unlock_node(prn);
3626 }
65efcfce
LB
3627#endif
3628
d62a17ae 3629 /* If maximum prefix count is configured and current prefix
3630 count exeed it. */
3631 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3632 return -1;
718e3744 3633
d62a17ae 3634 /* If this is an EVPN route, process for import. */
3635 if (safi == SAFI_EVPN)
3636 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 3637
4a11bf2c
DL
3638 hook_call(bgp_process, bgp, afi, safi, rn, peer, false);
3639
d62a17ae 3640 /* Process change. */
3641 bgp_process(bgp, rn, afi, safi);
718e3744 3642
ddb5b488
PZ
3643 if (SAFI_UNICAST == safi
3644 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3645 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3646 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
3647 }
3648 if ((SAFI_MPLS_VPN == safi)
3649 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3650
3651 vpn_leak_to_vrf_update(bgp, new);
3652 }
28070ee3 3653#if ENABLE_BGP_VNC
d62a17ae 3654 if (SAFI_MPLS_VPN == safi) {
3655 mpls_label_t label_decoded = decode_label(label);
28070ee3 3656
d62a17ae 3657 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3658 sub_type, &label_decoded);
3659 }
3660 if (SAFI_ENCAP == safi) {
3661 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3662 sub_type, NULL);
3663 }
28070ee3
PZ
3664#endif
3665
d62a17ae 3666 return 0;
718e3744 3667
d62a17ae 3668/* This BGP update is filtered. Log the reason then update BGP
3669 entry. */
3670filtered:
4a11bf2c
DL
3671 hook_call(bgp_process, bgp, afi, safi, rn, peer, true);
3672
d62a17ae 3673 if (bgp_debug_update(peer, p, NULL, 1)) {
3674 if (!peer->rcvd_attr_printed) {
3675 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3676 peer->rcvd_attr_str);
3677 peer->rcvd_attr_printed = 1;
3678 }
718e3744 3679
a4d82a8a 3680 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3681 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3682 sizeof(pfx_buf));
3683 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3684 peer->host, pfx_buf, reason);
3685 }
128ea8ab 3686
40381db7 3687 if (pi) {
d62a17ae 3688 /* If this is an EVPN route, un-import it as it is now filtered.
3689 */
3690 if (safi == SAFI_EVPN)
40381db7 3691 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 3692
ddb5b488
PZ
3693 if (SAFI_UNICAST == safi
3694 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3695 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3696
40381db7 3697 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3698 }
3699 if ((SAFI_MPLS_VPN == safi)
3700 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3701
40381db7 3702 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
3703 }
3704
40381db7 3705 bgp_rib_remove(rn, pi, peer, afi, safi);
d62a17ae 3706 }
3707
3708 bgp_unlock_node(rn);
558d1fec 3709
97736e32 3710#if ENABLE_BGP_VNC
d62a17ae 3711 /*
3712 * Filtered update is treated as an implicit withdrawal (see
3713 * bgp_rib_remove()
3714 * a few lines above)
3715 */
3716 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
3717 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
3718 0);
3719 }
97736e32
PZ
3720#endif
3721
d62a17ae 3722 return 0;
718e3744 3723}
3724
d7c0a89a 3725int bgp_withdraw(struct peer *peer, struct prefix *p, uint32_t addpath_id,
d62a17ae 3726 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3727 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3728 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 3729{
d62a17ae 3730 struct bgp *bgp;
3731 char pfx_buf[BGP_PRD_PATH_STRLEN];
3732 struct bgp_node *rn;
40381db7 3733 struct bgp_path_info *pi;
718e3744 3734
28070ee3 3735#if ENABLE_BGP_VNC
d62a17ae 3736 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
3737 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
3738 0);
3739 }
28070ee3
PZ
3740#endif
3741
d62a17ae 3742 bgp = peer->bgp;
3743
3744 /* Lookup node. */
3745 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
3746
3747 /* If peer is soft reconfiguration enabled. Record input packet for
3748 * further calculation.
3749 *
3750 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3751 * routes that are filtered. This tanks out Quagga RS pretty badly due
3752 * to
3753 * the iteration over all RS clients.
3754 * Since we need to remove the entry from adj_in anyway, do that first
3755 * and
3756 * if there was no entry, we don't need to do anything more.
3757 */
3758 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3759 && peer != bgp->peer_self)
3760 if (!bgp_adj_in_unset(rn, peer, addpath_id)) {
b4d46cc9
DL
3761 peer->stat_pfx_dup_withdraw++;
3762
d62a17ae 3763 if (bgp_debug_update(peer, p, NULL, 1)) {
3764 bgp_debug_rdpfxpath2str(
a4d82a8a 3765 afi, safi, prd, p, label, num_labels,
d62a17ae 3766 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3767 sizeof(pfx_buf));
3768 zlog_debug(
3769 "%s withdrawing route %s not in adj-in",
3770 peer->host, pfx_buf);
3771 }
3772 bgp_unlock_node(rn);
3773 return 0;
3774 }
cd808e74 3775
d62a17ae 3776 /* Lookup withdrawn route. */
6f94b685 3777 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
3778 if (pi->peer == peer && pi->type == type
3779 && pi->sub_type == sub_type
3780 && pi->addpath_rx_id == addpath_id)
d62a17ae 3781 break;
3782
3783 /* Logging. */
3784 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 3785 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3786 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3787 sizeof(pfx_buf));
3788 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
3789 pfx_buf);
3790 }
718e3744 3791
d62a17ae 3792 /* Withdraw specified route from routing table. */
40381db7
DS
3793 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
3794 bgp_rib_withdraw(rn, pi, peer, afi, safi, prd);
ddb5b488
PZ
3795 if (SAFI_UNICAST == safi
3796 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3797 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 3798 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3799 }
3800 if ((SAFI_MPLS_VPN == safi)
3801 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3802
40381db7 3803 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
3804 }
3805 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 3806 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3807 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3808 sizeof(pfx_buf));
3809 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
3810 }
718e3744 3811
d62a17ae 3812 /* Unlock bgp_node_get() lock. */
3813 bgp_unlock_node(rn);
3814
3815 return 0;
718e3744 3816}
6b0655a2 3817
d62a17ae 3818void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
3819 int withdraw)
718e3744 3820{
d62a17ae 3821 struct update_subgroup *subgrp;
3822 subgrp = peer_subgroup(peer, afi, safi);
3823 subgroup_default_originate(subgrp, withdraw);
3f9c7369 3824}
6182d65b 3825
718e3744 3826
3f9c7369
DS
3827/*
3828 * bgp_stop_announce_route_timer
3829 */
d62a17ae 3830void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 3831{
d62a17ae 3832 if (!paf->t_announce_route)
3833 return;
3834
3835 THREAD_TIMER_OFF(paf->t_announce_route);
718e3744 3836}
6b0655a2 3837
3f9c7369
DS
3838/*
3839 * bgp_announce_route_timer_expired
3840 *
3841 * Callback that is invoked when the route announcement timer for a
3842 * peer_af expires.
3843 */
d62a17ae 3844static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 3845{
d62a17ae 3846 struct peer_af *paf;
3847 struct peer *peer;
558d1fec 3848
d62a17ae 3849 paf = THREAD_ARG(t);
3850 peer = paf->peer;
718e3744 3851
d62a17ae 3852 if (peer->status != Established)
3853 return 0;
3f9c7369 3854
d62a17ae 3855 if (!peer->afc_nego[paf->afi][paf->safi])
3856 return 0;
3f9c7369 3857
d62a17ae 3858 peer_af_announce_route(paf, 1);
3859 return 0;
718e3744 3860}
3861
3f9c7369
DS
3862/*
3863 * bgp_announce_route
3864 *
3865 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3866 */
d62a17ae 3867void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
3868{
3869 struct peer_af *paf;
3870 struct update_subgroup *subgrp;
3871
3872 paf = peer_af_find(peer, afi, safi);
3873 if (!paf)
3874 return;
3875 subgrp = PAF_SUBGRP(paf);
3876
3877 /*
3878 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3879 * or a refresh has already been triggered.
3880 */
3881 if (!subgrp || paf->t_announce_route)
3882 return;
3883
3884 /*
3885 * Start a timer to stagger/delay the announce. This serves
3886 * two purposes - announcement can potentially be combined for
3887 * multiple peers and the announcement doesn't happen in the
3888 * vty context.
3889 */
3890 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
3891 (subgrp->peer_count == 1)
3892 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3893 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
3894 &paf->t_announce_route);
3f9c7369
DS
3895}
3896
3897/*
3898 * Announce routes from all AF tables to a peer.
3899 *
3900 * This should ONLY be called when there is a need to refresh the
3901 * routes to the peer based on a policy change for this peer alone
3902 * or a route refresh request received from the peer.
3903 * The operation will result in splitting the peer from its existing
3904 * subgroups and putting it in new subgroups.
3905 */
d62a17ae 3906void bgp_announce_route_all(struct peer *peer)
718e3744 3907{
d62a17ae 3908 afi_t afi;
3909 safi_t safi;
3910
05c7a1cc
QY
3911 FOREACH_AFI_SAFI (afi, safi)
3912 bgp_announce_route(peer, afi, safi);
718e3744 3913}
6b0655a2 3914
d62a17ae 3915static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
3916 struct bgp_table *table,
3917 struct prefix_rd *prd)
718e3744 3918{
d62a17ae 3919 int ret;
3920 struct bgp_node *rn;
3921 struct bgp_adj_in *ain;
718e3744 3922
d62a17ae 3923 if (!table)
3924 table = peer->bgp->rib[afi][safi];
718e3744 3925
d62a17ae 3926 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
3927 for (ain = rn->adj_in; ain; ain = ain->next) {
ea47320b
DL
3928 if (ain->peer != peer)
3929 continue;
8692c506 3930
d7d15889 3931 struct bgp_path_info *pi;
d7c0a89a 3932 uint32_t num_labels = 0;
b57ba6d2 3933 mpls_label_t *label_pnt = NULL;
8cb687c2 3934 struct bgp_route_evpn evpn;
b57ba6d2 3935
d7d15889
DS
3936 for (pi = bgp_node_get_bgp_path_info(rn); pi;
3937 pi = pi->next)
3938 if (pi->peer == peer)
3939 break;
3940
40381db7
DS
3941 if (pi && pi->extra)
3942 num_labels = pi->extra->num_labels;
b57ba6d2 3943 if (num_labels)
40381db7 3944 label_pnt = &pi->extra->label[0];
8cb687c2
DS
3945 if (pi)
3946 memcpy(&evpn, &pi->attr->evpn_overlay,
3947 sizeof(evpn));
3948 else
3949 memset(&evpn, 0, sizeof(evpn));
8692c506 3950
ea47320b
DL
3951 ret = bgp_update(peer, &rn->p, ain->addpath_rx_id,
3952 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
a4d82a8a 3953 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 3954 num_labels, 1, &evpn);
ea47320b
DL
3955
3956 if (ret < 0) {
3957 bgp_unlock_node(rn);
3958 return;
d62a17ae 3959 }
3960 }
718e3744 3961}
3962
d62a17ae 3963void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 3964{
d62a17ae 3965 struct bgp_node *rn;
3966 struct bgp_table *table;
718e3744 3967
d62a17ae 3968 if (peer->status != Established)
3969 return;
718e3744 3970
d62a17ae 3971 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
3972 && (safi != SAFI_EVPN))
3973 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
3974 else
3975 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
67009e22
DS
3976 rn = bgp_route_next(rn)) {
3977 table = bgp_node_get_bgp_table_info(rn);
3978 if (table != NULL) {
d62a17ae 3979 struct prefix_rd prd;
67009e22 3980
d62a17ae 3981 prd.family = AF_UNSPEC;
3982 prd.prefixlen = 64;
3983 memcpy(&prd.val, rn->p.u.val, 8);
8692c506 3984
d62a17ae 3985 bgp_soft_reconfig_table(peer, afi, safi, table,
3986 &prd);
3987 }
67009e22 3988 }
718e3744 3989}
6b0655a2 3990
228da428 3991
d62a17ae 3992struct bgp_clear_node_queue {
3993 struct bgp_node *rn;
228da428
CC
3994};
3995
d62a17ae 3996static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 3997{
d62a17ae 3998 struct bgp_clear_node_queue *cnq = data;
3999 struct bgp_node *rn = cnq->rn;
4000 struct peer *peer = wq->spec.data;
40381db7 4001 struct bgp_path_info *pi;
3103e8d2 4002 struct bgp *bgp;
d62a17ae 4003 afi_t afi = bgp_node_table(rn)->afi;
4004 safi_t safi = bgp_node_table(rn)->safi;
4005
4006 assert(rn && peer);
3103e8d2 4007 bgp = peer->bgp;
d62a17ae 4008
4009 /* It is possible that we have multiple paths for a prefix from a peer
4010 * if that peer is using AddPath.
4011 */
6f94b685 4012 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 4013 if (pi->peer != peer)
ea47320b
DL
4014 continue;
4015
4016 /* graceful restart STALE flag set. */
4017 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4018 && peer->nsf[afi][safi]
40381db7
DS
4019 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4020 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
4021 bgp_path_info_set_flag(rn, pi, BGP_PATH_STALE);
ea47320b
DL
4022 else {
4023 /* If this is an EVPN route, process for
4024 * un-import. */
4025 if (safi == SAFI_EVPN)
40381db7
DS
4026 bgp_evpn_unimport_route(bgp, afi, safi, &rn->p,
4027 pi);
3103e8d2
DS
4028 /* Handle withdraw for VRF route-leaking and L3VPN */
4029 if (SAFI_UNICAST == safi
4030 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4031 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4032 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4033 bgp, pi);
960035b2 4034 }
3103e8d2 4035 if (SAFI_MPLS_VPN == safi &&
960035b2 4036 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4037 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4038 }
3103e8d2 4039
40381db7 4040 bgp_rib_remove(rn, pi, peer, afi, safi);
d62a17ae 4041 }
ea47320b 4042 }
d62a17ae 4043 return WQ_SUCCESS;
200df115 4044}
4045
d62a17ae 4046static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4047{
d62a17ae 4048 struct bgp_clear_node_queue *cnq = data;
4049 struct bgp_node *rn = cnq->rn;
4050 struct bgp_table *table = bgp_node_table(rn);
228da428 4051
d62a17ae 4052 bgp_unlock_node(rn);
4053 bgp_table_unlock(table);
4054 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4055}
4056
d62a17ae 4057static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4058{
d62a17ae 4059 struct peer *peer = wq->spec.data;
64e580a7 4060
d62a17ae 4061 /* Tickle FSM to start moving again */
4062 BGP_EVENT_ADD(peer, Clearing_Completed);
4063
4064 peer_unlock(peer); /* bgp_clear_route */
200df115 4065}
718e3744 4066
d62a17ae 4067static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4068{
d62a17ae 4069 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4070
4071 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4072#undef CLEAR_QUEUE_NAME_LEN
4073
0ce1ca80 4074 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4075 peer->clear_node_queue->spec.hold = 10;
4076 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4077 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4078 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4079 peer->clear_node_queue->spec.max_retries = 0;
4080
4081 /* we only 'lock' this peer reference when the queue is actually active
4082 */
4083 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4084}
4085
d62a17ae 4086static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4087 struct bgp_table *table)
65ca75e0 4088{
d62a17ae 4089 struct bgp_node *rn;
4090 int force = bm->process_main_queue ? 0 : 1;
6cf159b9 4091
d62a17ae 4092 if (!table)
4093 table = peer->bgp->rib[afi][safi];
dc83d712 4094
d62a17ae 4095 /* If still no table => afi/safi isn't configured at all or smth. */
4096 if (!table)
4097 return;
dc83d712 4098
d62a17ae 4099 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
40381db7 4100 struct bgp_path_info *pi, *next;
d62a17ae 4101 struct bgp_adj_in *ain;
4102 struct bgp_adj_in *ain_next;
4103
4104 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4105 * queued for every clearing peer, regardless of whether it is
4106 * relevant to the peer at hand.
4107 *
4108 * Overview: There are 3 different indices which need to be
4109 * scrubbed, potentially, when a peer is removed:
4110 *
4111 * 1 peer's routes visible via the RIB (ie accepted routes)
4112 * 2 peer's routes visible by the (optional) peer's adj-in index
4113 * 3 other routes visible by the peer's adj-out index
4114 *
4115 * 3 there is no hurry in scrubbing, once the struct peer is
4116 * removed from bgp->peer, we could just GC such deleted peer's
4117 * adj-outs at our leisure.
4118 *
4119 * 1 and 2 must be 'scrubbed' in some way, at least made
4120 * invisible via RIB index before peer session is allowed to be
4121 * brought back up. So one needs to know when such a 'search' is
4122 * complete.
4123 *
4124 * Ideally:
4125 *
4126 * - there'd be a single global queue or a single RIB walker
4127 * - rather than tracking which route_nodes still need to be
4128 * examined on a peer basis, we'd track which peers still
4129 * aren't cleared
4130 *
4131 * Given that our per-peer prefix-counts now should be reliable,
4132 * this may actually be achievable. It doesn't seem to be a huge
4133 * problem at this time,
4134 *
4135 * It is possible that we have multiple paths for a prefix from
4136 * a peer
4137 * if that peer is using AddPath.
4138 */
4139 ain = rn->adj_in;
4140 while (ain) {
4141 ain_next = ain->next;
4142
4143 if (ain->peer == peer) {
4144 bgp_adj_in_remove(rn, ain);
4145 bgp_unlock_node(rn);
4146 }
4147
4148 ain = ain_next;
4149 }
4150
6f94b685 4151 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
40381db7
DS
4152 next = pi->next;
4153 if (pi->peer != peer)
d62a17ae 4154 continue;
4155
4156 if (force)
40381db7 4157 bgp_path_info_reap(rn, pi);
d62a17ae 4158 else {
4159 struct bgp_clear_node_queue *cnq;
4160
4161 /* both unlocked in bgp_clear_node_queue_del */
4162 bgp_table_lock(bgp_node_table(rn));
4163 bgp_lock_node(rn);
4164 cnq = XCALLOC(
4165 MTYPE_BGP_CLEAR_NODE_QUEUE,
4166 sizeof(struct bgp_clear_node_queue));
4167 cnq->rn = rn;
4168 work_queue_add(peer->clear_node_queue, cnq);
4169 break;
4170 }
4171 }
4172 }
4173 return;
4174}
4175
4176void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4177{
4178 struct bgp_node *rn;
4179 struct bgp_table *table;
4180
4181 if (peer->clear_node_queue == NULL)
4182 bgp_clear_node_queue_init(peer);
4183
4184 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4185 * Idle until it receives a Clearing_Completed event. This protects
4186 * against peers which flap faster than we can we clear, which could
4187 * lead to:
4188 *
4189 * a) race with routes from the new session being installed before
4190 * clear_route_node visits the node (to delete the route of that
4191 * peer)
4192 * b) resource exhaustion, clear_route_node likely leads to an entry
4193 * on the process_main queue. Fast-flapping could cause that queue
4194 * to grow and grow.
4195 */
4196
4197 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4198 * the unlock will happen upon work-queue completion; other wise, the
4199 * unlock happens at the end of this function.
4200 */
4201 if (!peer->clear_node_queue->thread)
4202 peer_lock(peer);
4203
4204 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4205 bgp_clear_route_table(peer, afi, safi, NULL);
4206 else
4207 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
67009e22
DS
4208 rn = bgp_route_next(rn)) {
4209 table = bgp_node_get_bgp_table_info(rn);
4210 if (!table)
4211 continue;
4212
4213 bgp_clear_route_table(peer, afi, safi, table);
4214 }
d62a17ae 4215
4216 /* unlock if no nodes got added to the clear-node-queue. */
4217 if (!peer->clear_node_queue->thread)
4218 peer_unlock(peer);
718e3744 4219}
d62a17ae 4220
4221void bgp_clear_route_all(struct peer *peer)
718e3744 4222{
d62a17ae 4223 afi_t afi;
4224 safi_t safi;
718e3744 4225
05c7a1cc
QY
4226 FOREACH_AFI_SAFI (afi, safi)
4227 bgp_clear_route(peer, afi, safi);
65efcfce
LB
4228
4229#if ENABLE_BGP_VNC
d62a17ae 4230 rfapiProcessPeerDown(peer);
65efcfce 4231#endif
718e3744 4232}
4233
d62a17ae 4234void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4235{
d62a17ae 4236 struct bgp_table *table;
4237 struct bgp_node *rn;
4238 struct bgp_adj_in *ain;
4239 struct bgp_adj_in *ain_next;
718e3744 4240
d62a17ae 4241 table = peer->bgp->rib[afi][safi];
718e3744 4242
d62a17ae 4243 /* It is possible that we have multiple paths for a prefix from a peer
4244 * if that peer is using AddPath.
4245 */
4246 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
4247 ain = rn->adj_in;
43143c8f 4248
d62a17ae 4249 while (ain) {
4250 ain_next = ain->next;
43143c8f 4251
d62a17ae 4252 if (ain->peer == peer) {
4253 bgp_adj_in_remove(rn, ain);
4254 bgp_unlock_node(rn);
4255 }
43143c8f 4256
d62a17ae 4257 ain = ain_next;
4258 }
4259 }
718e3744 4260}
93406d87 4261
d62a17ae 4262void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4263{
4264 struct bgp_node *rn;
40381db7 4265 struct bgp_path_info *pi;
d62a17ae 4266 struct bgp_table *table;
4267
4268 if (safi == SAFI_MPLS_VPN) {
4269 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4270 rn = bgp_route_next(rn)) {
4271 struct bgp_node *rm;
d62a17ae 4272
4273 /* look for neighbor in tables */
67009e22
DS
4274 table = bgp_node_get_bgp_table_info(rn);
4275 if (!table)
ea47320b
DL
4276 continue;
4277
4278 for (rm = bgp_table_top(table); rm;
4279 rm = bgp_route_next(rm))
6f94b685
DS
4280 for (pi = bgp_node_get_bgp_path_info(rm); pi;
4281 pi = pi->next) {
40381db7 4282 if (pi->peer != peer)
ea47320b 4283 continue;
40381db7 4284 if (!CHECK_FLAG(pi->flags,
1defdda8 4285 BGP_PATH_STALE))
ea47320b
DL
4286 break;
4287
40381db7 4288 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4289 break;
4290 }
d62a17ae 4291 }
4292 } else {
4293 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4294 rn = bgp_route_next(rn))
6f94b685
DS
4295 for (pi = bgp_node_get_bgp_path_info(rn); pi;
4296 pi = pi->next) {
40381db7 4297 if (pi->peer != peer)
ea47320b 4298 continue;
40381db7 4299 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4300 break;
40381db7 4301 bgp_rib_remove(rn, pi, peer, afi, safi);
ea47320b
DL
4302 break;
4303 }
d62a17ae 4304 }
93406d87 4305}
6b0655a2 4306
9dac9fc8
DA
4307int bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
4308{
4309 if (peer->sort == BGP_PEER_EBGP
4310 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
4311 || FILTER_LIST_OUT_NAME(filter)
4312 || DISTRIBUTE_OUT_NAME(filter)))
4313 return 1;
4314 return 0;
4315}
4316
4317int bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
4318{
4319 if (peer->sort == BGP_PEER_EBGP
4320 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
4321 || FILTER_LIST_IN_NAME(filter)
4322 || DISTRIBUTE_IN_NAME(filter)))
4323 return 1;
4324 return 0;
4325}
4326
568e10ca 4327static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
4328 safi_t safi)
bb86c601 4329{
d62a17ae 4330 struct bgp_node *rn;
40381db7 4331 struct bgp_path_info *pi;
4b7e6066 4332 struct bgp_path_info *next;
bb86c601 4333
d62a17ae 4334 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
6f94b685 4335 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
40381db7 4336 next = pi->next;
1b7bb747
CS
4337
4338 /* Unimport EVPN routes from VRFs */
4339 if (safi == SAFI_EVPN)
4340 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
4341 SAFI_EVPN,
4342 &rn->p, pi);
4343
40381db7
DS
4344 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
4345 && pi->type == ZEBRA_ROUTE_BGP
4346 && (pi->sub_type == BGP_ROUTE_NORMAL
4347 || pi->sub_type == BGP_ROUTE_AGGREGATE
4348 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 4349
d62a17ae 4350 if (bgp_fibupd_safi(safi))
40381db7
DS
4351 bgp_zebra_withdraw(&rn->p, pi, bgp,
4352 safi);
4353 bgp_path_info_reap(rn, pi);
d62a17ae 4354 }
4355 }
bb86c601
LB
4356}
4357
718e3744 4358/* Delete all kernel routes. */
d62a17ae 4359void bgp_cleanup_routes(struct bgp *bgp)
4360{
4361 afi_t afi;
4362 struct bgp_node *rn;
67009e22 4363 struct bgp_table *table;
d62a17ae 4364
4365 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
4366 if (afi == AFI_L2VPN)
4367 continue;
568e10ca 4368 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
4369 SAFI_UNICAST);
d62a17ae 4370 /*
4371 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4372 */
4373 if (afi != AFI_L2VPN) {
4374 safi_t safi;
4375 safi = SAFI_MPLS_VPN;
4376 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4377 rn = bgp_route_next(rn)) {
67009e22
DS
4378 table = bgp_node_get_bgp_table_info(rn);
4379 if (table != NULL) {
4380 bgp_cleanup_table(bgp, table, safi);
4381 bgp_table_finish(&table);
4382 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4383 bgp_unlock_node(rn);
4384 }
4385 }
4386 safi = SAFI_ENCAP;
4387 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4388 rn = bgp_route_next(rn)) {
67009e22
DS
4389 table = bgp_node_get_bgp_table_info(rn);
4390 if (table != NULL) {
4391 bgp_cleanup_table(bgp, table, safi);
4392 bgp_table_finish(&table);
4393 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4394 bgp_unlock_node(rn);
4395 }
4396 }
4397 }
4398 }
4399 for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn;
4400 rn = bgp_route_next(rn)) {
67009e22
DS
4401 table = bgp_node_get_bgp_table_info(rn);
4402 if (table != NULL) {
4403 bgp_cleanup_table(bgp, table, SAFI_EVPN);
4404 bgp_table_finish(&table);
4405 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4406 bgp_unlock_node(rn);
4407 }
bb86c601 4408 }
718e3744 4409}
4410
d62a17ae 4411void bgp_reset(void)
718e3744 4412{
d62a17ae 4413 vty_reset();
4414 bgp_zclient_reset();
4415 access_list_reset();
4416 prefix_list_reset();
718e3744 4417}
6b0655a2 4418
d62a17ae 4419static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 4420{
d62a17ae 4421 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
4422 && CHECK_FLAG(peer->af_cap[afi][safi],
4423 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
4424}
4425
718e3744 4426/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4427 value. */
d62a17ae 4428int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
4429 struct bgp_nlri *packet)
4430{
d7c0a89a
QY
4431 uint8_t *pnt;
4432 uint8_t *lim;
d62a17ae 4433 struct prefix p;
4434 int psize;
4435 int ret;
4436 afi_t afi;
4437 safi_t safi;
4438 int addpath_encoded;
d7c0a89a 4439 uint32_t addpath_id;
d62a17ae 4440
d62a17ae 4441 pnt = packet->nlri;
4442 lim = pnt + packet->length;
4443 afi = packet->afi;
4444 safi = packet->safi;
4445 addpath_id = 0;
4446 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
4447
4448 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4449 syntactic validity. If the field is syntactically incorrect,
4450 then the Error Subcode is set to Invalid Network Field. */
4451 for (; pnt < lim; pnt += psize) {
4452 /* Clear prefix structure. */
4453 memset(&p, 0, sizeof(struct prefix));
4454
4455 if (addpath_encoded) {
4456
4457 /* When packet overflow occurs return immediately. */
4458 if (pnt + BGP_ADDPATH_ID_LEN > lim)
513386b5 4459 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4460
4461 addpath_id = ntohl(*((uint32_t *)pnt));
4462 pnt += BGP_ADDPATH_ID_LEN;
4463 }
718e3744 4464
d62a17ae 4465 /* Fetch prefix length. */
4466 p.prefixlen = *pnt++;
4467 /* afi/safi validity already verified by caller,
4468 * bgp_update_receive */
4469 p.family = afi2family(afi);
4470
4471 /* Prefix length check. */
4472 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 4473 flog_err(
e50f7cfd 4474 EC_BGP_UPDATE_RCV,
14454c9f 4475 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 4476 peer->host, p.prefixlen, packet->afi);
513386b5 4477 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 4478 }
6b0655a2 4479
d62a17ae 4480 /* Packet size overflow check. */
4481 psize = PSIZE(p.prefixlen);
4482
4483 /* When packet overflow occur return immediately. */
4484 if (pnt + psize > lim) {
af4c2728 4485 flog_err(
e50f7cfd 4486 EC_BGP_UPDATE_RCV,
d62a17ae 4487 "%s [Error] Update packet error (prefix length %d overflows packet)",
4488 peer->host, p.prefixlen);
513386b5 4489 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4490 }
4491
4492 /* Defensive coding, double-check the psize fits in a struct
4493 * prefix */
4494 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 4495 flog_err(
e50f7cfd 4496 EC_BGP_UPDATE_RCV,
d62a17ae 4497 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4498 peer->host, p.prefixlen, sizeof(p.u));
513386b5 4499 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4500 }
4501
4502 /* Fetch prefix from NLRI packet. */
a85297a7 4503 memcpy(p.u.val, pnt, psize);
d62a17ae 4504
4505 /* Check address. */
4506 if (afi == AFI_IP && safi == SAFI_UNICAST) {
4507 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
4508 /* From RFC4271 Section 6.3:
4509 *
4510 * If a prefix in the NLRI field is semantically
4511 * incorrect
4512 * (e.g., an unexpected multicast IP address),
4513 * an error SHOULD
4514 * be logged locally, and the prefix SHOULD be
4515 * ignored.
a4d82a8a 4516 */
af4c2728 4517 flog_err(
e50f7cfd 4518 EC_BGP_UPDATE_RCV,
d62a17ae 4519 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4520 peer->host, inet_ntoa(p.u.prefix4));
4521 continue;
4522 }
4523 }
4524
4525 /* Check address. */
4526 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
4527 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4528 char buf[BUFSIZ];
4529
af4c2728 4530 flog_err(
e50f7cfd 4531 EC_BGP_UPDATE_RCV,
d62a17ae 4532 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4533 peer->host,
4534 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4535 BUFSIZ));
4536
4537 continue;
4538 }
4539 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
4540 char buf[BUFSIZ];
4541
af4c2728 4542 flog_err(
e50f7cfd 4543 EC_BGP_UPDATE_RCV,
d62a17ae 4544 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4545 peer->host,
4546 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4547 BUFSIZ));
4548
4549 continue;
4550 }
4551 }
4552
4553 /* Normal process. */
4554 if (attr)
4555 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
4556 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 4557 NULL, NULL, 0, 0, NULL);
d62a17ae 4558 else
4559 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
4560 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
4561 BGP_ROUTE_NORMAL, NULL, NULL, 0,
4562 NULL);
d62a17ae 4563
513386b5
DA
4564 /* Do not send BGP notification twice when maximum-prefix count
4565 * overflow. */
4566 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4567 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
4568
4569 /* Address family configuration mismatch. */
d62a17ae 4570 if (ret < 0)
513386b5 4571 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 4572 }
4573
4574 /* Packet length consistency check. */
4575 if (pnt != lim) {
af4c2728 4576 flog_err(
e50f7cfd 4577 EC_BGP_UPDATE_RCV,
d62a17ae 4578 "%s [Error] Update packet error (prefix length mismatch with total length)",
4579 peer->host);
513386b5 4580 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4581 }
6b0655a2 4582
513386b5 4583 return BGP_NLRI_PARSE_OK;
718e3744 4584}
4585
d62a17ae 4586static struct bgp_static *bgp_static_new(void)
718e3744 4587{
d62a17ae 4588 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 4589}
4590
d62a17ae 4591static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 4592{
0a22ddfb 4593 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 4594 route_map_counter_decrement(bgp_static->rmap.map);
4595
0a22ddfb 4596 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 4597 XFREE(MTYPE_BGP_STATIC, bgp_static);
4598}
4599
4600void bgp_static_update(struct bgp *bgp, struct prefix *p,
4601 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
4602{
4603 struct bgp_node *rn;
40381db7 4604 struct bgp_path_info *pi;
4b7e6066 4605 struct bgp_path_info *new;
40381db7 4606 struct bgp_path_info rmap_path;
d62a17ae 4607 struct attr attr;
4608 struct attr *attr_new;
b68885f9 4609 route_map_result_t ret;
65efcfce 4610#if ENABLE_BGP_VNC
d62a17ae 4611 int vnc_implicit_withdraw = 0;
65efcfce 4612#endif
fee0f4c6 4613
d62a17ae 4614 assert(bgp_static);
4615 if (!bgp_static)
4616 return;
dd8103a9 4617
d62a17ae 4618 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4619
d62a17ae 4620 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 4621
d62a17ae 4622 attr.nexthop = bgp_static->igpnexthop;
4623 attr.med = bgp_static->igpmetric;
4624 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 4625
d62a17ae 4626 if (bgp_static->atomic)
4627 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 4628
d62a17ae 4629 /* Store label index, if required. */
4630 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
4631 attr.label_index = bgp_static->label_index;
4632 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
4633 }
718e3744 4634
d62a17ae 4635 /* Apply route-map. */
4636 if (bgp_static->rmap.name) {
4637 struct attr attr_tmp = attr;
80ced710 4638
40381db7
DS
4639 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
4640 rmap_path.peer = bgp->peer_self;
4641 rmap_path.attr = &attr_tmp;
fee0f4c6 4642
d62a17ae 4643 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 4644
40381db7
DS
4645 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
4646 &rmap_path);
fee0f4c6 4647
d62a17ae 4648 bgp->peer_self->rmap_type = 0;
718e3744 4649
d62a17ae 4650 if (ret == RMAP_DENYMATCH) {
4651 /* Free uninterned attribute. */
4652 bgp_attr_flush(&attr_tmp);
718e3744 4653
d62a17ae 4654 /* Unintern original. */
4655 aspath_unintern(&attr.aspath);
4656 bgp_static_withdraw(bgp, p, afi, safi);
4657 return;
4658 }
7f323236
DW
4659
4660 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
4661 bgp_attr_add_gshut_community(&attr_tmp);
4662
d62a17ae 4663 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
4664 } else {
4665
4666 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
4667 bgp_attr_add_gshut_community(&attr);
4668
d62a17ae 4669 attr_new = bgp_attr_intern(&attr);
7f323236 4670 }
718e3744 4671
6f94b685 4672 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4673 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4674 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4675 break;
4676
40381db7
DS
4677 if (pi) {
4678 if (attrhash_cmp(pi->attr, attr_new)
4679 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
d62a17ae 4680 && !bgp_flag_check(bgp, BGP_FLAG_FORCE_STATIC_PROCESS)) {
4681 bgp_unlock_node(rn);
4682 bgp_attr_unintern(&attr_new);
4683 aspath_unintern(&attr.aspath);
4684 return;
4685 } else {
4686 /* The attribute is changed. */
40381db7 4687 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4688
4689 /* Rewrite BGP route information. */
40381db7
DS
4690 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
4691 bgp_path_info_restore(rn, pi);
d62a17ae 4692 else
40381db7 4693 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
65efcfce 4694#if ENABLE_BGP_VNC
d62a17ae 4695 if ((afi == AFI_IP || afi == AFI_IP6)
4696 && (safi == SAFI_UNICAST)) {
40381db7 4697 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4698 /*
4699 * Implicit withdraw case.
40381db7 4700 * We have to do this before pi is
d62a17ae 4701 * changed
4702 */
4703 ++vnc_implicit_withdraw;
40381db7 4704 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 4705 vnc_import_bgp_exterior_del_route(
40381db7 4706 bgp, p, pi);
d62a17ae 4707 }
4708 }
65efcfce 4709#endif
40381db7
DS
4710 bgp_attr_unintern(&pi->attr);
4711 pi->attr = attr_new;
4712 pi->uptime = bgp_clock();
65efcfce 4713#if ENABLE_BGP_VNC
d62a17ae 4714 if ((afi == AFI_IP || afi == AFI_IP6)
4715 && (safi == SAFI_UNICAST)) {
4716 if (vnc_implicit_withdraw) {
40381db7 4717 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 4718 vnc_import_bgp_exterior_add_route(
40381db7 4719 bgp, p, pi);
d62a17ae 4720 }
4721 }
65efcfce 4722#endif
718e3744 4723
d62a17ae 4724 /* Nexthop reachability check. */
4725 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
4726 && (safi == SAFI_UNICAST
4727 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
4728
4729 struct bgp *bgp_nexthop = bgp;
4730
40381db7
DS
4731 if (pi->extra && pi->extra->bgp_orig)
4732 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
4733
4734 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
40381db7
DS
4735 afi, pi, NULL, 0))
4736 bgp_path_info_set_flag(rn, pi,
18ee8310 4737 BGP_PATH_VALID);
d62a17ae 4738 else {
4739 if (BGP_DEBUG(nht, NHT)) {
4740 char buf1[INET6_ADDRSTRLEN];
4741 inet_ntop(p->family,
4742 &p->u.prefix, buf1,
4743 INET6_ADDRSTRLEN);
4744 zlog_debug(
4745 "%s(%s): Route not in table, not advertising",
4746 __FUNCTION__, buf1);
4747 }
18ee8310 4748 bgp_path_info_unset_flag(
40381db7 4749 rn, pi, BGP_PATH_VALID);
d62a17ae 4750 }
4751 } else {
4752 /* Delete the NHT structure if any, if we're
4753 * toggling between
4754 * enabling/disabling import check. We
4755 * deregister the route
4756 * from NHT to avoid overloading NHT and the
4757 * process interaction
4758 */
40381db7
DS
4759 bgp_unlink_nexthop(pi);
4760 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 4761 }
4762 /* Process change. */
40381db7 4763 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4764 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
4765
4766 if (SAFI_UNICAST == safi
4767 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4768 || bgp->inst_type
4769 == BGP_INSTANCE_TYPE_DEFAULT)) {
4770 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 4771 pi);
ddb5b488
PZ
4772 }
4773
d62a17ae 4774 bgp_unlock_node(rn);
4775 aspath_unintern(&attr.aspath);
4776 return;
4777 }
718e3744 4778 }
718e3744 4779
d62a17ae 4780 /* Make new BGP info. */
4781 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
4782 attr_new, rn);
4783 /* Nexthop reachability check. */
4784 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
4785 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 4786 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
18ee8310 4787 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
d62a17ae 4788 else {
4789 if (BGP_DEBUG(nht, NHT)) {
4790 char buf1[INET6_ADDRSTRLEN];
4791 inet_ntop(p->family, &p->u.prefix, buf1,
4792 INET6_ADDRSTRLEN);
4793 zlog_debug(
4794 "%s(%s): Route not in table, not advertising",
4795 __FUNCTION__, buf1);
4796 }
18ee8310 4797 bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID);
d62a17ae 4798 }
4799 } else {
4800 /* Delete the NHT structure if any, if we're toggling between
4801 * enabling/disabling import check. We deregister the route
4802 * from NHT to avoid overloading NHT and the process interaction
4803 */
4804 bgp_unlink_nexthop(new);
4805
18ee8310 4806 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
fc9a856f 4807 }
078430f6 4808
d62a17ae 4809 /* Aggregate address increment. */
4810 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 4811
d62a17ae 4812 /* Register new BGP information. */
18ee8310 4813 bgp_path_info_add(rn, new);
718e3744 4814
d62a17ae 4815 /* route_node_get lock */
4816 bgp_unlock_node(rn);
4817
4818 /* Process change. */
4819 bgp_process(bgp, rn, afi, safi);
4820
ddb5b488
PZ
4821 if (SAFI_UNICAST == safi
4822 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4823 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4824 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4825 }
4826
d62a17ae 4827 /* Unintern original. */
4828 aspath_unintern(&attr.aspath);
718e3744 4829}
4830
d62a17ae 4831void bgp_static_withdraw(struct bgp *bgp, struct prefix *p, afi_t afi,
4832 safi_t safi)
718e3744 4833{
d62a17ae 4834 struct bgp_node *rn;
40381db7 4835 struct bgp_path_info *pi;
718e3744 4836
d62a17ae 4837 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4838
d62a17ae 4839 /* Check selected route and self inserted route. */
6f94b685 4840 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4841 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4842 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4843 break;
4844
4845 /* Withdraw static BGP route from routing table. */
40381db7 4846 if (pi) {
ddb5b488
PZ
4847 if (SAFI_UNICAST == safi
4848 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4849 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4850 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 4851 }
40381db7
DS
4852 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
4853 bgp_unlink_nexthop(pi);
4854 bgp_path_info_delete(rn, pi);
d62a17ae 4855 bgp_process(bgp, rn, afi, safi);
4856 }
718e3744 4857
d62a17ae 4858 /* Unlock bgp_node_lookup. */
4859 bgp_unlock_node(rn);
718e3744 4860}
4861
137446f9
LB
4862/*
4863 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4864 */
d62a17ae 4865static void bgp_static_withdraw_safi(struct bgp *bgp, struct prefix *p,
4866 afi_t afi, safi_t safi,
4867 struct prefix_rd *prd)
718e3744 4868{
d62a17ae 4869 struct bgp_node *rn;
40381db7 4870 struct bgp_path_info *pi;
718e3744 4871
d62a17ae 4872 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 4873
d62a17ae 4874 /* Check selected route and self inserted route. */
6f94b685 4875 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4876 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4877 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4878 break;
718e3744 4879
d62a17ae 4880 /* Withdraw static BGP route from routing table. */
40381db7 4881 if (pi) {
65efcfce 4882#if ENABLE_BGP_VNC
d62a17ae 4883 rfapiProcessWithdraw(
40381db7 4884 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 4885 1); /* Kill, since it is an administrative change */
65efcfce 4886#endif
ddb5b488
PZ
4887 if (SAFI_MPLS_VPN == safi
4888 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4889 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 4890 }
40381db7
DS
4891 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
4892 bgp_path_info_delete(rn, pi);
d62a17ae 4893 bgp_process(bgp, rn, afi, safi);
4894 }
718e3744 4895
d62a17ae 4896 /* Unlock bgp_node_lookup. */
4897 bgp_unlock_node(rn);
718e3744 4898}
4899
d62a17ae 4900static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p,
4901 struct bgp_static *bgp_static, afi_t afi,
4902 safi_t safi)
137446f9 4903{
d62a17ae 4904 struct bgp_node *rn;
4b7e6066 4905 struct bgp_path_info *new;
d62a17ae 4906 struct attr *attr_new;
4907 struct attr attr = {0};
40381db7 4908 struct bgp_path_info *pi;
65efcfce 4909#if ENABLE_BGP_VNC
d62a17ae 4910 mpls_label_t label = 0;
65efcfce 4911#endif
d7c0a89a 4912 uint32_t num_labels = 0;
d62a17ae 4913 union gw_addr add;
137446f9 4914
d62a17ae 4915 assert(bgp_static);
137446f9 4916
b57ba6d2
MK
4917 if (bgp_static->label != MPLS_INVALID_LABEL)
4918 num_labels = 1;
d62a17ae 4919 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
4920 &bgp_static->prd);
137446f9 4921
d62a17ae 4922 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 4923
d62a17ae 4924 attr.nexthop = bgp_static->igpnexthop;
4925 attr.med = bgp_static->igpmetric;
4926 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 4927
d62a17ae 4928 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
4929 || (safi == SAFI_ENCAP)) {
4930 if (afi == AFI_IP) {
4931 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
4932 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
4933 }
4934 }
4935 if (afi == AFI_L2VPN) {
4936 if (bgp_static->gatewayIp.family == AF_INET)
4937 add.ipv4.s_addr =
4938 bgp_static->gatewayIp.u.prefix4.s_addr;
4939 else if (bgp_static->gatewayIp.family == AF_INET6)
4940 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
4941 sizeof(struct in6_addr));
4942 overlay_index_update(&attr, bgp_static->eth_s_id, &add);
4943 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
4944 struct bgp_encap_type_vxlan bet;
4945 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 4946 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 4947 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
4948 }
4949 if (bgp_static->router_mac) {
4950 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
4951 }
4952 }
4953 /* Apply route-map. */
4954 if (bgp_static->rmap.name) {
4955 struct attr attr_tmp = attr;
40381db7 4956 struct bgp_path_info rmap_path;
b68885f9 4957 route_map_result_t ret;
137446f9 4958
40381db7
DS
4959 rmap_path.peer = bgp->peer_self;
4960 rmap_path.attr = &attr_tmp;
137446f9 4961
d62a17ae 4962 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 4963
40381db7
DS
4964 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
4965 &rmap_path);
137446f9 4966
d62a17ae 4967 bgp->peer_self->rmap_type = 0;
137446f9 4968
d62a17ae 4969 if (ret == RMAP_DENYMATCH) {
4970 /* Free uninterned attribute. */
4971 bgp_attr_flush(&attr_tmp);
137446f9 4972
d62a17ae 4973 /* Unintern original. */
4974 aspath_unintern(&attr.aspath);
4975 bgp_static_withdraw_safi(bgp, p, afi, safi,
4976 &bgp_static->prd);
4977 return;
4978 }
137446f9 4979
d62a17ae 4980 attr_new = bgp_attr_intern(&attr_tmp);
4981 } else {
4982 attr_new = bgp_attr_intern(&attr);
4983 }
137446f9 4984
6f94b685 4985 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4986 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4987 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4988 break;
4989
40381db7 4990 if (pi) {
d62a17ae 4991 memset(&add, 0, sizeof(union gw_addr));
40381db7
DS
4992 if (attrhash_cmp(pi->attr, attr_new)
4993 && overlay_index_equal(afi, pi, bgp_static->eth_s_id, &add)
4994 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4995 bgp_unlock_node(rn);
4996 bgp_attr_unintern(&attr_new);
4997 aspath_unintern(&attr.aspath);
4998 return;
4999 } else {
5000 /* The attribute is changed. */
40381db7 5001 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5002
5003 /* Rewrite BGP route information. */
40381db7
DS
5004 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
5005 bgp_path_info_restore(rn, pi);
d62a17ae 5006 else
40381db7
DS
5007 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5008 bgp_attr_unintern(&pi->attr);
5009 pi->attr = attr_new;
5010 pi->uptime = bgp_clock();
65efcfce 5011#if ENABLE_BGP_VNC
40381db7
DS
5012 if (pi->extra)
5013 label = decode_label(&pi->extra->label[0]);
65efcfce 5014#endif
137446f9 5015
d62a17ae 5016 /* Process change. */
40381db7 5017 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 5018 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
5019
5020 if (SAFI_MPLS_VPN == safi
5021 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5022 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5023 }
65efcfce 5024#if ENABLE_BGP_VNC
40381db7
DS
5025 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5026 pi->attr, afi, safi, pi->type,
5027 pi->sub_type, &label);
65efcfce 5028#endif
d62a17ae 5029 bgp_unlock_node(rn);
5030 aspath_unintern(&attr.aspath);
5031 return;
5032 }
5033 }
137446f9
LB
5034
5035
d62a17ae 5036 /* Make new BGP info. */
5037 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
5038 attr_new, rn);
1defdda8 5039 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5040 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5041 if (num_labels) {
5042 new->extra->label[0] = bgp_static->label;
5043 new->extra->num_labels = num_labels;
5044 }
65efcfce 5045#if ENABLE_BGP_VNC
d62a17ae 5046 label = decode_label(&bgp_static->label);
65efcfce 5047#endif
137446f9 5048
d62a17ae 5049 /* Aggregate address increment. */
5050 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5051
d62a17ae 5052 /* Register new BGP information. */
18ee8310 5053 bgp_path_info_add(rn, new);
d62a17ae 5054 /* route_node_get lock */
5055 bgp_unlock_node(rn);
137446f9 5056
d62a17ae 5057 /* Process change. */
5058 bgp_process(bgp, rn, afi, safi);
137446f9 5059
ddb5b488
PZ
5060 if (SAFI_MPLS_VPN == safi
5061 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5062 vpn_leak_to_vrf_update(bgp, new);
5063 }
65efcfce 5064#if ENABLE_BGP_VNC
d62a17ae 5065 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5066 safi, new->type, new->sub_type, &label);
65efcfce
LB
5067#endif
5068
d62a17ae 5069 /* Unintern original. */
5070 aspath_unintern(&attr.aspath);
137446f9
LB
5071}
5072
718e3744 5073/* Configure static BGP network. When user don't run zebra, static
5074 route should be installed as valid. */
e2a86ad9
DS
5075static int bgp_static_set(struct vty *vty, const char *negate,
5076 const char *ip_str, afi_t afi, safi_t safi,
d7c0a89a 5077 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 5078{
5079 VTY_DECLVAR_CONTEXT(bgp, bgp);
5080 int ret;
5081 struct prefix p;
5082 struct bgp_static *bgp_static;
5083 struct bgp_node *rn;
d7c0a89a 5084 uint8_t need_update = 0;
d62a17ae 5085
5086 /* Convert IP prefix string to struct prefix. */
5087 ret = str2prefix(ip_str, &p);
5088 if (!ret) {
5089 vty_out(vty, "%% Malformed prefix\n");
5090 return CMD_WARNING_CONFIG_FAILED;
5091 }
5092 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5093 vty_out(vty, "%% Malformed prefix (link-local address)\n");
5094 return CMD_WARNING_CONFIG_FAILED;
5095 }
718e3744 5096
d62a17ae 5097 apply_mask(&p);
718e3744 5098
e2a86ad9 5099 if (negate) {
718e3744 5100
e2a86ad9
DS
5101 /* Set BGP static route configuration. */
5102 rn = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5103
e2a86ad9 5104 if (!rn) {
a4d82a8a 5105 vty_out(vty, "%% Can't find static route specified\n");
d62a17ae 5106 return CMD_WARNING_CONFIG_FAILED;
5107 }
5108
5a8ba9fc 5109 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 5110
e2a86ad9
DS
5111 if ((label_index != BGP_INVALID_LABEL_INDEX)
5112 && (label_index != bgp_static->label_index)) {
5113 vty_out(vty,
5114 "%% label-index doesn't match static route\n");
5115 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5116 }
d62a17ae 5117
e2a86ad9
DS
5118 if ((rmap && bgp_static->rmap.name)
5119 && strcmp(rmap, bgp_static->rmap.name)) {
5120 vty_out(vty,
5121 "%% route-map name doesn't match static route\n");
5122 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5123 }
718e3744 5124
e2a86ad9
DS
5125 /* Update BGP RIB. */
5126 if (!bgp_static->backdoor)
5127 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5128
e2a86ad9
DS
5129 /* Clear configuration. */
5130 bgp_static_free(bgp_static);
5a8ba9fc 5131 bgp_node_set_bgp_static_info(rn, NULL);
e2a86ad9
DS
5132 bgp_unlock_node(rn);
5133 bgp_unlock_node(rn);
5134 } else {
718e3744 5135
e2a86ad9
DS
5136 /* Set BGP static route configuration. */
5137 rn = bgp_node_get(bgp->route[afi][safi], &p);
718e3744 5138
5a8ba9fc 5139 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 5140 if (bgp_static) {
e2a86ad9 5141 /* Configuration change. */
e2a86ad9
DS
5142 /* Label index cannot be changed. */
5143 if (bgp_static->label_index != label_index) {
5144 vty_out(vty, "%% cannot change label-index\n");
5145 return CMD_WARNING_CONFIG_FAILED;
5146 }
d62a17ae 5147
e2a86ad9 5148 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5149 if (bgp_static->valid
5150 && bgp_static->backdoor != backdoor)
e2a86ad9 5151 need_update = 1;
718e3744 5152
e2a86ad9 5153 bgp_static->backdoor = backdoor;
718e3744 5154
e2a86ad9 5155 if (rmap) {
0a22ddfb
QY
5156 XFREE(MTYPE_ROUTE_MAP_NAME,
5157 bgp_static->rmap.name);
b4897fa5 5158 route_map_counter_decrement(
5159 bgp_static->rmap.map);
e2a86ad9
DS
5160 bgp_static->rmap.name =
5161 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5162 bgp_static->rmap.map =
5163 route_map_lookup_by_name(rmap);
b4897fa5 5164 route_map_counter_increment(
5165 bgp_static->rmap.map);
e2a86ad9 5166 } else {
0a22ddfb
QY
5167 XFREE(MTYPE_ROUTE_MAP_NAME,
5168 bgp_static->rmap.name);
b4897fa5 5169 route_map_counter_decrement(
5170 bgp_static->rmap.map);
e2a86ad9
DS
5171 bgp_static->rmap.name = NULL;
5172 bgp_static->rmap.map = NULL;
5173 bgp_static->valid = 0;
5174 }
5175 bgp_unlock_node(rn);
5176 } else {
5177 /* New configuration. */
5178 bgp_static = bgp_static_new();
5179 bgp_static->backdoor = backdoor;
5180 bgp_static->valid = 0;
5181 bgp_static->igpmetric = 0;
5182 bgp_static->igpnexthop.s_addr = 0;
5183 bgp_static->label_index = label_index;
718e3744 5184
e2a86ad9 5185 if (rmap) {
0a22ddfb
QY
5186 XFREE(MTYPE_ROUTE_MAP_NAME,
5187 bgp_static->rmap.name);
b4897fa5 5188 route_map_counter_decrement(
5189 bgp_static->rmap.map);
e2a86ad9
DS
5190 bgp_static->rmap.name =
5191 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5192 bgp_static->rmap.map =
5193 route_map_lookup_by_name(rmap);
b4897fa5 5194 route_map_counter_increment(
5195 bgp_static->rmap.map);
e2a86ad9 5196 }
5a8ba9fc 5197 bgp_node_set_bgp_static_info(rn, bgp_static);
e2a86ad9 5198 }
d62a17ae 5199
e2a86ad9
DS
5200 bgp_static->valid = 1;
5201 if (need_update)
5202 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5203
e2a86ad9
DS
5204 if (!bgp_static->backdoor)
5205 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5206 }
d62a17ae 5207
5208 return CMD_SUCCESS;
5209}
5210
5211void bgp_static_add(struct bgp *bgp)
5212{
5213 afi_t afi;
5214 safi_t safi;
5215 struct bgp_node *rn;
5216 struct bgp_node *rm;
5217 struct bgp_table *table;
5218 struct bgp_static *bgp_static;
5219
05c7a1cc
QY
5220 FOREACH_AFI_SAFI (afi, safi)
5221 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5222 rn = bgp_route_next(rn)) {
67009e22 5223 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5224 continue;
ea47320b 5225
05c7a1cc
QY
5226 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5227 || (safi == SAFI_EVPN)) {
67009e22 5228 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5229
5230 for (rm = bgp_table_top(table); rm;
5231 rm = bgp_route_next(rm)) {
a78beeb5 5232 bgp_static =
5a8ba9fc
DS
5233 bgp_node_get_bgp_static_info(
5234 rm);
05c7a1cc
QY
5235 bgp_static_update_safi(bgp, &rm->p,
5236 bgp_static, afi,
5237 safi);
d62a17ae 5238 }
05c7a1cc 5239 } else {
5a8ba9fc
DS
5240 bgp_static_update(
5241 bgp, &rn->p,
5242 bgp_node_get_bgp_static_info(rn), afi,
5243 safi);
ea47320b 5244 }
05c7a1cc 5245 }
6aeb9e78
DS
5246}
5247
718e3744 5248/* Called from bgp_delete(). Delete all static routes from the BGP
5249 instance. */
d62a17ae 5250void bgp_static_delete(struct bgp *bgp)
5251{
5252 afi_t afi;
5253 safi_t safi;
5254 struct bgp_node *rn;
5255 struct bgp_node *rm;
5256 struct bgp_table *table;
5257 struct bgp_static *bgp_static;
5258
05c7a1cc
QY
5259 FOREACH_AFI_SAFI (afi, safi)
5260 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5261 rn = bgp_route_next(rn)) {
67009e22 5262 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5263 continue;
ea47320b 5264
05c7a1cc
QY
5265 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5266 || (safi == SAFI_EVPN)) {
67009e22 5267 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5268
5269 for (rm = bgp_table_top(table); rm;
5270 rm = bgp_route_next(rm)) {
a78beeb5 5271 bgp_static =
5a8ba9fc
DS
5272 bgp_node_get_bgp_static_info(
5273 rm);
c7d14ba6
PG
5274 if (!bgp_static)
5275 continue;
5276
05c7a1cc
QY
5277 bgp_static_withdraw_safi(
5278 bgp, &rm->p, AFI_IP, safi,
5279 (struct prefix_rd *)&rn->p);
ea47320b 5280 bgp_static_free(bgp_static);
5a8ba9fc 5281 bgp_node_set_bgp_static_info(rn, NULL);
ea47320b 5282 bgp_unlock_node(rn);
d62a17ae 5283 }
05c7a1cc 5284 } else {
5a8ba9fc 5285 bgp_static = bgp_node_get_bgp_static_info(rn);
05c7a1cc
QY
5286 bgp_static_withdraw(bgp, &rn->p, afi, safi);
5287 bgp_static_free(bgp_static);
5a8ba9fc 5288 bgp_node_set_bgp_static_info(rn, NULL);
05c7a1cc 5289 bgp_unlock_node(rn);
ea47320b 5290 }
05c7a1cc 5291 }
d62a17ae 5292}
5293
5294void bgp_static_redo_import_check(struct bgp *bgp)
5295{
5296 afi_t afi;
5297 safi_t safi;
5298 struct bgp_node *rn;
5299 struct bgp_node *rm;
5300 struct bgp_table *table;
5301 struct bgp_static *bgp_static;
5302
5303 /* Use this flag to force reprocessing of the route */
5304 bgp_flag_set(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc
QY
5305 FOREACH_AFI_SAFI (afi, safi) {
5306 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5307 rn = bgp_route_next(rn)) {
67009e22 5308 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5309 continue;
ea47320b 5310
05c7a1cc
QY
5311 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5312 || (safi == SAFI_EVPN)) {
67009e22 5313 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5314
5315 for (rm = bgp_table_top(table); rm;
5316 rm = bgp_route_next(rm)) {
a78beeb5 5317 bgp_static =
5a8ba9fc
DS
5318 bgp_node_get_bgp_static_info(
5319 rm);
05c7a1cc
QY
5320 bgp_static_update_safi(bgp, &rm->p,
5321 bgp_static, afi,
5322 safi);
d62a17ae 5323 }
05c7a1cc 5324 } else {
5a8ba9fc 5325 bgp_static = bgp_node_get_bgp_static_info(rn);
05c7a1cc
QY
5326 bgp_static_update(bgp, &rn->p, bgp_static, afi,
5327 safi);
ea47320b 5328 }
05c7a1cc
QY
5329 }
5330 }
d62a17ae 5331 bgp_flag_unset(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
5332}
5333
5334static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
5335 safi_t safi)
5336{
5337 struct bgp_table *table;
5338 struct bgp_node *rn;
40381db7 5339 struct bgp_path_info *pi;
d62a17ae 5340
dfb6fd1d
NT
5341 /* Do not install the aggregate route if BGP is in the
5342 * process of termination.
5343 */
5344 if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS) ||
5345 (bgp->peer_self == NULL))
5346 return;
5347
d62a17ae 5348 table = bgp->rib[afi][safi];
5349 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685 5350 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7
DS
5351 if (pi->peer == bgp->peer_self
5352 && ((pi->type == ZEBRA_ROUTE_BGP
5353 && pi->sub_type == BGP_ROUTE_STATIC)
5354 || (pi->type != ZEBRA_ROUTE_BGP
5355 && pi->sub_type
d62a17ae 5356 == BGP_ROUTE_REDISTRIBUTE))) {
40381db7 5357 bgp_aggregate_decrement(bgp, &rn->p, pi, afi,
d62a17ae 5358 safi);
40381db7
DS
5359 bgp_unlink_nexthop(pi);
5360 bgp_path_info_delete(rn, pi);
d62a17ae 5361 bgp_process(bgp, rn, afi, safi);
5362 }
5363 }
5364 }
ad4cbda1 5365}
5366
5367/*
5368 * Purge all networks and redistributed routes from routing table.
5369 * Invoked upon the instance going down.
5370 */
d62a17ae 5371void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 5372{
d62a17ae 5373 afi_t afi;
5374 safi_t safi;
ad4cbda1 5375
05c7a1cc
QY
5376 FOREACH_AFI_SAFI (afi, safi)
5377 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 5378}
5379
137446f9
LB
5380/*
5381 * gpz 110624
5382 * Currently this is used to set static routes for VPN and ENCAP.
5383 * I think it can probably be factored with bgp_static_set.
5384 */
d62a17ae 5385int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
5386 const char *ip_str, const char *rd_str,
5387 const char *label_str, const char *rmap_str,
5388 int evpn_type, const char *esi, const char *gwip,
5389 const char *ethtag, const char *routermac)
5390{
5391 VTY_DECLVAR_CONTEXT(bgp, bgp);
5392 int ret;
5393 struct prefix p;
5394 struct prefix_rd prd;
5395 struct bgp_node *prn;
5396 struct bgp_node *rn;
5397 struct bgp_table *table;
5398 struct bgp_static *bgp_static;
5399 mpls_label_t label = MPLS_INVALID_LABEL;
5400 struct prefix gw_ip;
5401
5402 /* validate ip prefix */
5403 ret = str2prefix(ip_str, &p);
5404 if (!ret) {
5405 vty_out(vty, "%% Malformed prefix\n");
5406 return CMD_WARNING_CONFIG_FAILED;
5407 }
5408 apply_mask(&p);
5409 if ((afi == AFI_L2VPN)
5410 && (bgp_build_evpn_prefix(evpn_type,
5411 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5412 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5413 return CMD_WARNING_CONFIG_FAILED;
5414 }
718e3744 5415
d62a17ae 5416 ret = str2prefix_rd(rd_str, &prd);
5417 if (!ret) {
5418 vty_out(vty, "%% Malformed rd\n");
5419 return CMD_WARNING_CONFIG_FAILED;
5420 }
718e3744 5421
d62a17ae 5422 if (label_str) {
5423 unsigned long label_val;
5424 label_val = strtoul(label_str, NULL, 10);
5425 encode_label(label_val, &label);
5426 }
9bedbb1e 5427
d62a17ae 5428 if (safi == SAFI_EVPN) {
5429 if (esi && str2esi(esi, NULL) == 0) {
5430 vty_out(vty, "%% Malformed ESI\n");
5431 return CMD_WARNING_CONFIG_FAILED;
5432 }
5433 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
5434 vty_out(vty, "%% Malformed Router MAC\n");
5435 return CMD_WARNING_CONFIG_FAILED;
5436 }
5437 if (gwip) {
5438 memset(&gw_ip, 0, sizeof(struct prefix));
5439 ret = str2prefix(gwip, &gw_ip);
5440 if (!ret) {
5441 vty_out(vty, "%% Malformed GatewayIp\n");
5442 return CMD_WARNING_CONFIG_FAILED;
5443 }
5444 if ((gw_ip.family == AF_INET
3714a385 5445 && is_evpn_prefix_ipaddr_v6(
d62a17ae 5446 (struct prefix_evpn *)&p))
5447 || (gw_ip.family == AF_INET6
3714a385 5448 && is_evpn_prefix_ipaddr_v4(
d62a17ae 5449 (struct prefix_evpn *)&p))) {
5450 vty_out(vty,
5451 "%% GatewayIp family differs with IP prefix\n");
5452 return CMD_WARNING_CONFIG_FAILED;
5453 }
5454 }
5455 }
5456 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
67009e22
DS
5457 if (!bgp_node_has_bgp_path_info_data(prn))
5458 bgp_node_set_bgp_table_info(prn,
5459 bgp_table_init(bgp, afi, safi));
67009e22 5460 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 5461
5462 rn = bgp_node_get(table, &p);
5463
67009e22 5464 if (bgp_node_has_bgp_path_info_data(rn)) {
d62a17ae 5465 vty_out(vty, "%% Same network configuration exists\n");
5466 bgp_unlock_node(rn);
5467 } else {
5468 /* New configuration. */
5469 bgp_static = bgp_static_new();
5470 bgp_static->backdoor = 0;
5471 bgp_static->valid = 0;
5472 bgp_static->igpmetric = 0;
5473 bgp_static->igpnexthop.s_addr = 0;
5474 bgp_static->label = label;
5475 bgp_static->prd = prd;
5476
5477 if (rmap_str) {
0a22ddfb 5478 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5479 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 5480 bgp_static->rmap.name =
5481 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
5482 bgp_static->rmap.map =
5483 route_map_lookup_by_name(rmap_str);
b4897fa5 5484 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 5485 }
718e3744 5486
d62a17ae 5487 if (safi == SAFI_EVPN) {
5488 if (esi) {
5489 bgp_static->eth_s_id =
5490 XCALLOC(MTYPE_ATTR,
5491 sizeof(struct eth_segment_id));
5492 str2esi(esi, bgp_static->eth_s_id);
5493 }
5494 if (routermac) {
5495 bgp_static->router_mac =
28328ea9 5496 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
5497 (void)prefix_str2mac(routermac,
5498 bgp_static->router_mac);
d62a17ae 5499 }
5500 if (gwip)
5501 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
5502 }
5a8ba9fc 5503 bgp_node_set_bgp_static_info(rn, bgp_static);
718e3744 5504
d62a17ae 5505 bgp_static->valid = 1;
5506 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
5507 }
718e3744 5508
d62a17ae 5509 return CMD_SUCCESS;
718e3744 5510}
5511
5512/* Configure static BGP network. */
d62a17ae 5513int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
5514 const char *ip_str, const char *rd_str,
5515 const char *label_str, int evpn_type, const char *esi,
5516 const char *gwip, const char *ethtag)
5517{
5518 VTY_DECLVAR_CONTEXT(bgp, bgp);
5519 int ret;
5520 struct prefix p;
5521 struct prefix_rd prd;
5522 struct bgp_node *prn;
5523 struct bgp_node *rn;
5524 struct bgp_table *table;
5525 struct bgp_static *bgp_static;
5526 mpls_label_t label = MPLS_INVALID_LABEL;
5527
5528 /* Convert IP prefix string to struct prefix. */
5529 ret = str2prefix(ip_str, &p);
5530 if (!ret) {
5531 vty_out(vty, "%% Malformed prefix\n");
5532 return CMD_WARNING_CONFIG_FAILED;
5533 }
5534 apply_mask(&p);
5535 if ((afi == AFI_L2VPN)
5536 && (bgp_build_evpn_prefix(evpn_type,
5537 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5538 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5539 return CMD_WARNING_CONFIG_FAILED;
5540 }
5541 ret = str2prefix_rd(rd_str, &prd);
5542 if (!ret) {
5543 vty_out(vty, "%% Malformed rd\n");
5544 return CMD_WARNING_CONFIG_FAILED;
5545 }
718e3744 5546
d62a17ae 5547 if (label_str) {
5548 unsigned long label_val;
5549 label_val = strtoul(label_str, NULL, 10);
5550 encode_label(label_val, &label);
5551 }
718e3744 5552
d62a17ae 5553 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
67009e22
DS
5554 if (!bgp_node_has_bgp_path_info_data(prn))
5555 bgp_node_set_bgp_table_info(prn,
5556 bgp_table_init(bgp, afi, safi));
d62a17ae 5557 else
5558 bgp_unlock_node(prn);
67009e22 5559 table = bgp_node_get_bgp_table_info(prn);
718e3744 5560
d62a17ae 5561 rn = bgp_node_lookup(table, &p);
6b0655a2 5562
d62a17ae 5563 if (rn) {
5564 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 5565
5a8ba9fc 5566 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 5567 bgp_static_free(bgp_static);
5a8ba9fc 5568 bgp_node_set_bgp_static_info(rn, NULL);
d62a17ae 5569 bgp_unlock_node(rn);
5570 bgp_unlock_node(rn);
5571 } else
5572 vty_out(vty, "%% Can't find the route\n");
5573
5574 return CMD_SUCCESS;
5575}
5576
5577static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
5578 const char *rmap_name)
5579{
5580 VTY_DECLVAR_CONTEXT(bgp, bgp);
5581 struct bgp_rmap *rmap;
5582
5583 rmap = &bgp->table_map[afi][safi];
5584 if (rmap_name) {
0a22ddfb 5585 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5586 route_map_counter_decrement(rmap->map);
d62a17ae 5587 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
5588 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 5589 route_map_counter_increment(rmap->map);
d62a17ae 5590 } else {
0a22ddfb 5591 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5592 route_map_counter_decrement(rmap->map);
d62a17ae 5593 rmap->name = NULL;
5594 rmap->map = NULL;
5595 }
73ac8160 5596
d62a17ae 5597 if (bgp_fibupd_safi(safi))
5598 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5599
d62a17ae 5600 return CMD_SUCCESS;
73ac8160
DS
5601}
5602
d62a17ae 5603static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
5604 const char *rmap_name)
73ac8160 5605{
d62a17ae 5606 VTY_DECLVAR_CONTEXT(bgp, bgp);
5607 struct bgp_rmap *rmap;
73ac8160 5608
d62a17ae 5609 rmap = &bgp->table_map[afi][safi];
0a22ddfb 5610 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5611 route_map_counter_decrement(rmap->map);
d62a17ae 5612 rmap->name = NULL;
5613 rmap->map = NULL;
73ac8160 5614
d62a17ae 5615 if (bgp_fibupd_safi(safi))
5616 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5617
d62a17ae 5618 return CMD_SUCCESS;
73ac8160
DS
5619}
5620
2b791107 5621void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 5622 safi_t safi)
73ac8160 5623{
d62a17ae 5624 if (bgp->table_map[afi][safi].name) {
d62a17ae 5625 vty_out(vty, " table-map %s\n",
5626 bgp->table_map[afi][safi].name);
5627 }
73ac8160
DS
5628}
5629
73ac8160
DS
5630DEFUN (bgp_table_map,
5631 bgp_table_map_cmd,
5632 "table-map WORD",
5633 "BGP table to RIB route download filter\n"
5634 "Name of the route map\n")
5635{
d62a17ae 5636 int idx_word = 1;
5637 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5638 argv[idx_word]->arg);
73ac8160
DS
5639}
5640DEFUN (no_bgp_table_map,
5641 no_bgp_table_map_cmd,
5642 "no table-map WORD",
3a2d747c 5643 NO_STR
73ac8160
DS
5644 "BGP table to RIB route download filter\n"
5645 "Name of the route map\n")
5646{
d62a17ae 5647 int idx_word = 2;
5648 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5649 argv[idx_word]->arg);
73ac8160
DS
5650}
5651
e2a86ad9
DS
5652DEFPY(bgp_network,
5653 bgp_network_cmd,
5654 "[no] network \
5655 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5656 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5657 backdoor$backdoor}]",
5658 NO_STR
5659 "Specify a network to announce via BGP\n"
5660 "IPv4 prefix\n"
5661 "Network number\n"
5662 "Network mask\n"
5663 "Network mask\n"
5664 "Route-map to modify the attributes\n"
5665 "Name of the route map\n"
5666 "Label index to associate with the prefix\n"
5667 "Label index value\n"
5668 "Specify a BGP backdoor route\n")
5669{
5670 char addr_prefix_str[BUFSIZ];
5671
5672 if (address_str) {
5673 int ret;
718e3744 5674
e2a86ad9
DS
5675 ret = netmask_str2prefix_str(address_str, netmask_str,
5676 addr_prefix_str);
5677 if (!ret) {
5678 vty_out(vty, "%% Inconsistent address and mask\n");
5679 return CMD_WARNING_CONFIG_FAILED;
5680 }
d62a17ae 5681 }
718e3744 5682
a4d82a8a
PZ
5683 return bgp_static_set(
5684 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
5685 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
5686 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 5687}
5688
e2a86ad9
DS
5689DEFPY(ipv6_bgp_network,
5690 ipv6_bgp_network_cmd,
5691 "[no] network X:X::X:X/M$prefix \
5692 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5693 NO_STR
5694 "Specify a network to announce via BGP\n"
5695 "IPv6 prefix\n"
5696 "Route-map to modify the attributes\n"
5697 "Name of the route map\n"
5698 "Label index to associate with the prefix\n"
5699 "Label index value\n")
718e3744 5700{
a4d82a8a
PZ
5701 return bgp_static_set(
5702 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
5703 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
5704}
5705
d62a17ae 5706static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 5707{
d62a17ae 5708 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 5709}
5710
d62a17ae 5711static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 5712{
20894f50
DA
5713 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
5714 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 5715 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
5716}
718e3744 5717
40381db7 5718static int bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
29f7d023 5719 struct aspath *aspath,
3da2cc32 5720 struct community *comm,
dd18c5a9
DS
5721 struct ecommunity *ecomm,
5722 struct lcommunity *lcomm)
eaaf8adb
DS
5723{
5724 static struct aspath *ae = NULL;
5725
5726 if (!ae)
5727 ae = aspath_empty();
5728
40381db7 5729 if (!pi)
eaaf8adb
DS
5730 return 0;
5731
40381db7 5732 if (origin != pi->attr->origin)
eaaf8adb
DS
5733 return 0;
5734
40381db7 5735 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
29f7d023
DS
5736 return 0;
5737
40381db7 5738 if (!community_cmp(pi->attr->community, comm))
eaaf8adb
DS
5739 return 0;
5740
3da2cc32 5741 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
eaaf8adb
DS
5742 return 0;
5743
dd18c5a9
DS
5744 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
5745 return 0;
5746
40381db7 5747 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
7ce8a8e0
DS
5748 return 0;
5749
eaaf8adb
DS
5750 return 1;
5751}
5752
c701010e
DS
5753static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi,
5754 struct prefix *p, uint8_t origin,
5755 struct aspath *aspath,
5756 struct community *community,
3da2cc32 5757 struct ecommunity *ecommunity,
dd18c5a9 5758 struct lcommunity *lcommunity,
c701010e
DS
5759 uint8_t atomic_aggregate,
5760 struct bgp_aggregate *aggregate)
5761{
5762 struct bgp_node *rn;
5763 struct bgp_table *table;
6f94b685 5764 struct bgp_path_info *pi, *orig, *new;
20894f50 5765 struct attr *attr;
c701010e
DS
5766
5767 table = bgp->rib[afi][safi];
5768
5769 rn = bgp_node_get(table, p);
eaaf8adb 5770
6f94b685 5771 for (orig = pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
5772 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5773 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
5774 break;
5775
c701010e 5776 if (aggregate->count > 0) {
eaaf8adb
DS
5777 /*
5778 * If the aggregate information has not changed
5779 * no need to re-install it again.
5780 */
6f94b685 5781 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 5782 ecommunity, lcommunity)) {
eaaf8adb
DS
5783 bgp_unlock_node(rn);
5784
5785 if (aspath)
5786 aspath_free(aspath);
5787 if (community)
3c1f53de 5788 community_free(&community);
3da2cc32
DS
5789 if (ecommunity)
5790 ecommunity_free(&ecommunity);
dd18c5a9
DS
5791 if (lcommunity)
5792 lcommunity_free(&lcommunity);
eaaf8adb
DS
5793
5794 return;
5795 }
5796
5797 /*
5798 * Mark the old as unusable
5799 */
40381db7
DS
5800 if (pi)
5801 bgp_path_info_delete(rn, pi);
eaaf8adb 5802
20894f50
DA
5803 attr = bgp_attr_aggregate_intern(
5804 bgp, origin, aspath, community, ecommunity, lcommunity,
5805 aggregate, atomic_aggregate, p);
5806
5807 if (!attr) {
5808 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
5809 return;
5810 }
5811
3da2cc32 5812 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
20894f50
DA
5813 bgp->peer_self, attr, rn);
5814
1defdda8 5815 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 5816
18ee8310 5817 bgp_path_info_add(rn, new);
c701010e
DS
5818 bgp_process(bgp, rn, afi, safi);
5819 } else {
6f94b685 5820 for (pi = orig; pi; pi = pi->next)
40381db7
DS
5821 if (pi->peer == bgp->peer_self
5822 && pi->type == ZEBRA_ROUTE_BGP
5823 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
5824 break;
5825
5826 /* Withdraw static BGP route from routing table. */
40381db7
DS
5827 if (pi) {
5828 bgp_path_info_delete(rn, pi);
c701010e
DS
5829 bgp_process(bgp, rn, afi, safi);
5830 }
5831 }
5832
5833 bgp_unlock_node(rn);
5834}
5835
b5d58c32 5836/* Update an aggregate as routes are added/removed from the BGP table */
20894f50 5837void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
fc968841 5838 afi_t afi, safi_t safi,
d62a17ae 5839 struct bgp_aggregate *aggregate)
5840{
5841 struct bgp_table *table;
5842 struct bgp_node *top;
5843 struct bgp_node *rn;
d7c0a89a 5844 uint8_t origin;
d62a17ae 5845 struct aspath *aspath = NULL;
d62a17ae 5846 struct community *community = NULL;
3da2cc32 5847 struct ecommunity *ecommunity = NULL;
dd18c5a9 5848 struct lcommunity *lcommunity = NULL;
40381db7 5849 struct bgp_path_info *pi;
d62a17ae 5850 unsigned long match = 0;
d7c0a89a 5851 uint8_t atomic_aggregate = 0;
d62a17ae 5852
9f822fa2
S
5853 /* If the bgp instance is being deleted or self peer is deleted
5854 * then do not create aggregate route
5855 */
5856 if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS) ||
5857 (bgp->peer_self == NULL))
5858 return;
5859
d62a17ae 5860 /* ORIGIN attribute: If at least one route among routes that are
5861 aggregated has ORIGIN with the value INCOMPLETE, then the
5862 aggregated route must have the ORIGIN attribute with the value
5863 INCOMPLETE. Otherwise, if at least one route among routes that
5864 are aggregated has ORIGIN with the value EGP, then the aggregated
5865 route must have the origin attribute with the value EGP. In all
5866 other case the value of the ORIGIN attribute of the aggregated
5867 route is INTERNAL. */
5868 origin = BGP_ORIGIN_IGP;
718e3744 5869
d62a17ae 5870 table = bgp->rib[afi][safi];
718e3744 5871
d62a17ae 5872 top = bgp_node_get(table, p);
5873 for (rn = bgp_node_get(table, p); rn;
c2ff8b3e
DS
5874 rn = bgp_route_next_until(rn, top)) {
5875 if (rn->p.prefixlen <= p->prefixlen)
5876 continue;
d62a17ae 5877
c2ff8b3e 5878 match = 0;
d62a17ae 5879
6f94b685 5880 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 5881 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 5882 continue;
718e3744 5883
40381db7 5884 if (pi->attr->flag
c2ff8b3e
DS
5885 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
5886 atomic_aggregate = 1;
d62a17ae 5887
40381db7 5888 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 5889 continue;
d62a17ae 5890
f273fef1
DS
5891 /*
5892 * summary-only aggregate route suppress
5893 * aggregated route announcements.
5894 */
c2ff8b3e 5895 if (aggregate->summary_only) {
40381db7
DS
5896 (bgp_path_info_extra_get(pi))->suppress++;
5897 bgp_path_info_set_flag(rn, pi,
18ee8310 5898 BGP_PATH_ATTR_CHANGED);
c2ff8b3e 5899 match++;
d62a17ae 5900 }
c2ff8b3e
DS
5901
5902 aggregate->count++;
5903
f273fef1
DS
5904 /*
5905 * If at least one route among routes that are
5906 * aggregated has ORIGIN with the value INCOMPLETE,
5907 * then the aggregated route MUST have the ORIGIN
5908 * attribute with the value INCOMPLETE. Otherwise, if
5909 * at least one route among routes that are aggregated
5910 * has ORIGIN with the value EGP, then the aggregated
5911 * route MUST have the ORIGIN attribute with the value
5912 * EGP.
5913 */
fc968841
NT
5914 switch (pi->attr->origin) {
5915 case BGP_ORIGIN_INCOMPLETE:
5916 aggregate->incomplete_origin_count++;
5917 break;
5918 case BGP_ORIGIN_EGP:
5919 aggregate->egp_origin_count++;
5920 break;
5921 default:
5922 /*Do nothing.
5923 */
5924 break;
5925 }
c2ff8b3e
DS
5926
5927 if (!aggregate->as_set)
5928 continue;
5929
f273fef1
DS
5930 /*
5931 * as-set aggregate route generate origin, as path,
5932 * and community aggregation.
5933 */
fc968841
NT
5934 /* Compute aggregate route's as-path.
5935 */
ef51a7d8 5936 bgp_compute_aggregate_aspath_hash(aggregate,
5937 pi->attr->aspath);
c2ff8b3e 5938
fc968841
NT
5939 /* Compute aggregate route's community.
5940 */
5941 if (pi->attr->community)
21fec674 5942 bgp_compute_aggregate_community_hash(
fc968841
NT
5943 aggregate,
5944 pi->attr->community);
dd18c5a9 5945
fc968841
NT
5946 /* Compute aggregate route's extended community.
5947 */
5948 if (pi->attr->ecommunity)
4edd83f9 5949 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
5950 aggregate,
5951 pi->attr->ecommunity);
5952
5953 /* Compute aggregate route's large community.
5954 */
5955 if (pi->attr->lcommunity)
f1eb1f05 5956 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
5957 aggregate,
5958 pi->attr->lcommunity);
d62a17ae 5959 }
c2ff8b3e
DS
5960 if (match)
5961 bgp_process(bgp, rn, afi, safi);
5962 }
21fec674 5963 if (aggregate->as_set) {
ef51a7d8 5964 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 5965 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 5966 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 5967 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 5968 }
5969
f1eb1f05 5970
d62a17ae 5971 bgp_unlock_node(top);
718e3744 5972
718e3744 5973
fc968841
NT
5974 if (aggregate->incomplete_origin_count > 0)
5975 origin = BGP_ORIGIN_INCOMPLETE;
5976 else if (aggregate->egp_origin_count > 0)
5977 origin = BGP_ORIGIN_EGP;
d62a17ae 5978
fc968841
NT
5979 if (aggregate->as_set) {
5980 if (aggregate->aspath)
5981 /* Retrieve aggregate route's as-path.
5982 */
5983 aspath = aspath_dup(aggregate->aspath);
d62a17ae 5984
fc968841
NT
5985 if (aggregate->community)
5986 /* Retrieve aggregate route's community.
5987 */
5988 community = community_dup(aggregate->community);
3da2cc32 5989
fc968841
NT
5990 if (aggregate->ecommunity)
5991 /* Retrieve aggregate route's ecommunity.
5992 */
5993 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 5994
fc968841
NT
5995 if (aggregate->lcommunity)
5996 /* Retrieve aggregate route's lcommunity.
5997 */
5998 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 5999 }
718e3744 6000
c701010e 6001 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
6002 ecommunity, lcommunity, atomic_aggregate,
6003 aggregate);
718e3744 6004}
6005
20894f50 6006void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
3b7db173
DS
6007 safi_t safi, struct bgp_aggregate *aggregate)
6008{
6009 struct bgp_table *table;
6010 struct bgp_node *top;
6011 struct bgp_node *rn;
40381db7 6012 struct bgp_path_info *pi;
3b7db173
DS
6013 unsigned long match;
6014
6015 table = bgp->rib[afi][safi];
6016
6017 /* If routes exists below this node, generate aggregate routes. */
6018 top = bgp_node_get(table, p);
6019 for (rn = bgp_node_get(table, p); rn;
6020 rn = bgp_route_next_until(rn, top)) {
6021 if (rn->p.prefixlen <= p->prefixlen)
6022 continue;
6023 match = 0;
6024
6f94b685 6025 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 6026 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
6027 continue;
6028
40381db7 6029 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
6030 continue;
6031
40381db7
DS
6032 if (aggregate->summary_only && pi->extra) {
6033 pi->extra->suppress--;
3b7db173 6034
40381db7 6035 if (pi->extra->suppress == 0) {
18ee8310 6036 bgp_path_info_set_flag(
40381db7 6037 rn, pi, BGP_PATH_ATTR_CHANGED);
3b7db173
DS
6038 match++;
6039 }
6040 }
6041 aggregate->count--;
fc968841
NT
6042
6043 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6044 aggregate->incomplete_origin_count--;
6045 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6046 aggregate->egp_origin_count--;
6047
6048 if (aggregate->as_set) {
6049 /* Remove as-path from aggregate.
6050 */
ef51a7d8 6051 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
6052 aggregate,
6053 pi->attr->aspath);
6054
6055 if (pi->attr->community)
6056 /* Remove community from aggregate.
6057 */
21fec674 6058 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
6059 aggregate,
6060 pi->attr->community);
6061
6062 if (pi->attr->ecommunity)
6063 /* Remove ecommunity from aggregate.
6064 */
4edd83f9 6065 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
6066 aggregate,
6067 pi->attr->ecommunity);
6068
6069 if (pi->attr->lcommunity)
6070 /* Remove lcommunity from aggregate.
6071 */
f1eb1f05 6072 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
6073 aggregate,
6074 pi->attr->lcommunity);
6075 }
6076
3b7db173
DS
6077 }
6078
6079 /* If this node was suppressed, process the change. */
6080 if (match)
6081 bgp_process(bgp, rn, afi, safi);
6082 }
f1eb1f05 6083 if (aggregate->as_set) {
ef51a7d8 6084 aspath_free(aggregate->aspath);
6085 aggregate->aspath = NULL;
21fec674 6086 if (aggregate->community)
6087 community_free(&aggregate->community);
4edd83f9 6088 if (aggregate->ecommunity)
6089 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 6090 if (aggregate->lcommunity)
6091 lcommunity_free(&aggregate->lcommunity);
6092 }
6093
3b7db173
DS
6094 bgp_unlock_node(top);
6095}
718e3744 6096
fc968841
NT
6097static void bgp_add_route_to_aggregate(struct bgp *bgp, struct prefix *aggr_p,
6098 struct bgp_path_info *pinew, afi_t afi,
6099 safi_t safi,
6100 struct bgp_aggregate *aggregate)
6101{
6102 uint8_t origin;
6103 struct aspath *aspath = NULL;
6104 uint8_t atomic_aggregate = 0;
6105 struct community *community = NULL;
6106 struct ecommunity *ecommunity = NULL;
6107 struct lcommunity *lcommunity = NULL;
6108
6109 /* ORIGIN attribute: If at least one route among routes that are
6110 * aggregated has ORIGIN with the value INCOMPLETE, then the
6111 * aggregated route must have the ORIGIN attribute with the value
6112 * INCOMPLETE. Otherwise, if at least one route among routes that
6113 * are aggregated has ORIGIN with the value EGP, then the aggregated
6114 * route must have the origin attribute with the value EGP. In all
6115 * other case the value of the ORIGIN attribute of the aggregated
6116 * route is INTERNAL.
6117 */
6118 origin = BGP_ORIGIN_IGP;
6119
6120 aggregate->count++;
6121
6122 if (aggregate->summary_only)
6123 (bgp_path_info_extra_get(pinew))->suppress++;
6124
6125 switch (pinew->attr->origin) {
6126 case BGP_ORIGIN_INCOMPLETE:
6127 aggregate->incomplete_origin_count++;
6128 break;
6129 case BGP_ORIGIN_EGP:
6130 aggregate->egp_origin_count++;
6131 break;
6132 default:
6133 /* Do nothing.
6134 */
6135 break;
6136 }
6137
6138 if (aggregate->incomplete_origin_count > 0)
6139 origin = BGP_ORIGIN_INCOMPLETE;
6140 else if (aggregate->egp_origin_count > 0)
6141 origin = BGP_ORIGIN_EGP;
6142
6143 if (aggregate->as_set) {
6144 /* Compute aggregate route's as-path.
6145 */
6146 bgp_compute_aggregate_aspath(aggregate,
6147 pinew->attr->aspath);
6148
6149 /* Compute aggregate route's community.
6150 */
6151 if (pinew->attr->community)
6152 bgp_compute_aggregate_community(
6153 aggregate,
6154 pinew->attr->community);
6155
6156 /* Compute aggregate route's extended community.
6157 */
6158 if (pinew->attr->ecommunity)
6159 bgp_compute_aggregate_ecommunity(
6160 aggregate,
6161 pinew->attr->ecommunity);
6162
6163 /* Compute aggregate route's large community.
6164 */
6165 if (pinew->attr->lcommunity)
6166 bgp_compute_aggregate_lcommunity(
6167 aggregate,
6168 pinew->attr->lcommunity);
6169
6170 /* Retrieve aggregate route's as-path.
6171 */
6172 if (aggregate->aspath)
6173 aspath = aspath_dup(aggregate->aspath);
6174
6175 /* Retrieve aggregate route's community.
6176 */
6177 if (aggregate->community)
6178 community = community_dup(aggregate->community);
6179
6180 /* Retrieve aggregate route's ecommunity.
6181 */
6182 if (aggregate->ecommunity)
6183 ecommunity = ecommunity_dup(aggregate->ecommunity);
6184
6185 /* Retrieve aggregate route's lcommunity.
6186 */
6187 if (aggregate->lcommunity)
6188 lcommunity = lcommunity_dup(aggregate->lcommunity);
6189 }
6190
6191 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6192 aspath, community, ecommunity,
6193 lcommunity, atomic_aggregate, aggregate);
6194}
6195
6196static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
6197 safi_t safi,
6198 struct bgp_path_info *pi,
6199 struct bgp_aggregate *aggregate,
6200 struct prefix *aggr_p)
6201{
6202 uint8_t origin;
6203 struct aspath *aspath = NULL;
6204 uint8_t atomic_aggregate = 0;
6205 struct community *community = NULL;
6206 struct ecommunity *ecommunity = NULL;
6207 struct lcommunity *lcommunity = NULL;
6208 unsigned long match = 0;
6209
6210 if (BGP_PATH_HOLDDOWN(pi))
6211 return;
6212
6213 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6214 return;
6215
6216 if (aggregate->summary_only
6217 && pi->extra
6218 && pi->extra->suppress > 0) {
6219 pi->extra->suppress--;
6220
6221 if (pi->extra->suppress == 0) {
6222 bgp_path_info_set_flag(pi->net, pi,
6223 BGP_PATH_ATTR_CHANGED);
6224 match++;
6225 }
6226 }
6227
6228 if (aggregate->count > 0)
6229 aggregate->count--;
6230
6231 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6232 aggregate->incomplete_origin_count--;
6233 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6234 aggregate->egp_origin_count--;
6235
6236 if (aggregate->as_set) {
6237 /* Remove as-path from aggregate.
6238 */
6239 bgp_remove_aspath_from_aggregate(aggregate,
6240 pi->attr->aspath);
6241
6242 if (pi->attr->community)
6243 /* Remove community from aggregate.
6244 */
6245 bgp_remove_community_from_aggregate(
6246 aggregate,
6247 pi->attr->community);
6248
6249 if (pi->attr->ecommunity)
6250 /* Remove ecommunity from aggregate.
6251 */
6252 bgp_remove_ecommunity_from_aggregate(
6253 aggregate,
6254 pi->attr->ecommunity);
6255
6256 if (pi->attr->lcommunity)
6257 /* Remove lcommunity from aggregate.
6258 */
6259 bgp_remove_lcommunity_from_aggregate(
6260 aggregate,
6261 pi->attr->lcommunity);
6262 }
6263
6264 /* If this node was suppressed, process the change. */
6265 if (match)
6266 bgp_process(bgp, pi->net, afi, safi);
6267
6268 origin = BGP_ORIGIN_IGP;
6269 if (aggregate->incomplete_origin_count > 0)
6270 origin = BGP_ORIGIN_INCOMPLETE;
6271 else if (aggregate->egp_origin_count > 0)
6272 origin = BGP_ORIGIN_EGP;
6273
6274 if (aggregate->as_set) {
6275 /* Retrieve aggregate route's as-path.
6276 */
6277 if (aggregate->aspath)
6278 aspath = aspath_dup(aggregate->aspath);
6279
6280 /* Retrieve aggregate route's community.
6281 */
6282 if (aggregate->community)
6283 community = community_dup(aggregate->community);
6284
6285 /* Retrieve aggregate route's ecommunity.
6286 */
6287 if (aggregate->ecommunity)
6288 ecommunity = ecommunity_dup(aggregate->ecommunity);
6289
6290 /* Retrieve aggregate route's lcommunity.
6291 */
6292 if (aggregate->lcommunity)
6293 lcommunity = lcommunity_dup(aggregate->lcommunity);
6294 }
6295
6296 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6297 aspath, community, ecommunity,
6298 lcommunity, atomic_aggregate, aggregate);
6299}
6300
d62a17ae 6301void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p,
40381db7 6302 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 6303{
d62a17ae 6304 struct bgp_node *child;
6305 struct bgp_node *rn;
6306 struct bgp_aggregate *aggregate;
6307 struct bgp_table *table;
718e3744 6308
d62a17ae 6309 table = bgp->aggregate[afi][safi];
f018db83 6310
d62a17ae 6311 /* No aggregates configured. */
6312 if (bgp_table_top_nolock(table) == NULL)
6313 return;
f018db83 6314
d62a17ae 6315 if (p->prefixlen == 0)
6316 return;
718e3744 6317
40381db7 6318 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 6319 return;
718e3744 6320
d62a17ae 6321 child = bgp_node_get(table, p);
718e3744 6322
d62a17ae 6323 /* Aggregate address configuration check. */
b1e62edd 6324 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
b613a918 6325 aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 6326 if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
fc968841
NT
6327 bgp_add_route_to_aggregate(bgp, &rn->p, pi, afi,
6328 safi, aggregate);
d62a17ae 6329 }
b1e62edd 6330 }
d62a17ae 6331 bgp_unlock_node(child);
718e3744 6332}
6333
d62a17ae 6334void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p,
4b7e6066 6335 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 6336{
d62a17ae 6337 struct bgp_node *child;
6338 struct bgp_node *rn;
6339 struct bgp_aggregate *aggregate;
6340 struct bgp_table *table;
718e3744 6341
d62a17ae 6342 table = bgp->aggregate[afi][safi];
718e3744 6343
d62a17ae 6344 /* No aggregates configured. */
6345 if (bgp_table_top_nolock(table) == NULL)
6346 return;
718e3744 6347
d62a17ae 6348 if (p->prefixlen == 0)
6349 return;
718e3744 6350
d62a17ae 6351 child = bgp_node_get(table, p);
718e3744 6352
d62a17ae 6353 /* Aggregate address configuration check. */
b1e62edd 6354 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
b613a918 6355 aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 6356 if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
fc968841
NT
6357 bgp_remove_route_from_aggregate(bgp, afi, safi,
6358 del, aggregate, &rn->p);
d62a17ae 6359 }
b1e62edd 6360 }
d62a17ae 6361 bgp_unlock_node(child);
6362}
718e3744 6363
718e3744 6364/* Aggregate route attribute. */
6365#define AGGREGATE_SUMMARY_ONLY 1
6366#define AGGREGATE_AS_SET 1
6367
d62a17ae 6368static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
6369 afi_t afi, safi_t safi)
718e3744 6370{
d62a17ae 6371 VTY_DECLVAR_CONTEXT(bgp, bgp);
6372 int ret;
6373 struct prefix p;
6374 struct bgp_node *rn;
6375 struct bgp_aggregate *aggregate;
718e3744 6376
d62a17ae 6377 /* Convert string to prefix structure. */
6378 ret = str2prefix(prefix_str, &p);
6379 if (!ret) {
6380 vty_out(vty, "Malformed prefix\n");
6381 return CMD_WARNING_CONFIG_FAILED;
6382 }
6383 apply_mask(&p);
6384
6385 /* Old configuration check. */
6386 rn = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
6387 if (!rn) {
6388 vty_out(vty,
6389 "%% There is no aggregate-address configuration.\n");
6390 return CMD_WARNING_CONFIG_FAILED;
6391 }
f6269b4f 6392
b613a918 6393 aggregate = bgp_node_get_bgp_aggregate_info(rn);
09990cdd 6394 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
dd18c5a9
DS
6395 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
6396 NULL, NULL, 0, aggregate);
d62a17ae 6397
6398 /* Unlock aggregate address configuration. */
b613a918 6399 bgp_node_set_bgp_aggregate_info(rn, NULL);
fc968841
NT
6400
6401 if (aggregate->community)
6402 community_free(&aggregate->community);
6403
6404 if (aggregate->community_hash) {
6405 /* Delete all communities in the hash.
6406 */
6407 hash_clean(aggregate->community_hash,
6408 bgp_aggr_community_remove);
6409 /* Free up the community_hash.
6410 */
6411 hash_free(aggregate->community_hash);
6412 }
6413
6414 if (aggregate->ecommunity)
6415 ecommunity_free(&aggregate->ecommunity);
6416
6417 if (aggregate->ecommunity_hash) {
6418 /* Delete all ecommunities in the hash.
6419 */
6420 hash_clean(aggregate->ecommunity_hash,
6421 bgp_aggr_ecommunity_remove);
6422 /* Free up the ecommunity_hash.
6423 */
6424 hash_free(aggregate->ecommunity_hash);
6425 }
6426
6427 if (aggregate->lcommunity)
6428 lcommunity_free(&aggregate->lcommunity);
6429
6430 if (aggregate->lcommunity_hash) {
6431 /* Delete all lcommunities in the hash.
6432 */
6433 hash_clean(aggregate->lcommunity_hash,
6434 bgp_aggr_lcommunity_remove);
6435 /* Free up the lcommunity_hash.
6436 */
6437 hash_free(aggregate->lcommunity_hash);
6438 }
6439
6440 if (aggregate->aspath)
6441 aspath_free(aggregate->aspath);
6442
6443 if (aggregate->aspath_hash) {
6444 /* Delete all as-paths in the hash.
6445 */
6446 hash_clean(aggregate->aspath_hash,
6447 bgp_aggr_aspath_remove);
6448 /* Free up the aspath_hash.
6449 */
6450 hash_free(aggregate->aspath_hash);
6451 }
6452
d62a17ae 6453 bgp_aggregate_free(aggregate);
6454 bgp_unlock_node(rn);
6455 bgp_unlock_node(rn);
6456
6457 return CMD_SUCCESS;
6458}
6459
6460static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
20894f50
DA
6461 safi_t safi, const char *rmap, uint8_t summary_only,
6462 uint8_t as_set)
d62a17ae 6463{
6464 VTY_DECLVAR_CONTEXT(bgp, bgp);
6465 int ret;
6466 struct prefix p;
6467 struct bgp_node *rn;
6468 struct bgp_aggregate *aggregate;
6469
6470 /* Convert string to prefix structure. */
6471 ret = str2prefix(prefix_str, &p);
6472 if (!ret) {
6473 vty_out(vty, "Malformed prefix\n");
6474 return CMD_WARNING_CONFIG_FAILED;
6475 }
6476 apply_mask(&p);
6477
3624ac81
DS
6478 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
6479 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
6480 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6481 prefix_str);
6482 return CMD_WARNING_CONFIG_FAILED;
6483 }
6484
d62a17ae 6485 /* Old configuration check. */
6486 rn = bgp_node_get(bgp->aggregate[afi][safi], &p);
20894f50 6487 aggregate = bgp_node_get_bgp_aggregate_info(rn);
d62a17ae 6488
20894f50 6489 if (aggregate) {
d62a17ae 6490 vty_out(vty, "There is already same aggregate network.\n");
6491 /* try to remove the old entry */
6492 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
6493 if (ret) {
6494 vty_out(vty, "Error deleting aggregate.\n");
6495 bgp_unlock_node(rn);
6496 return CMD_WARNING_CONFIG_FAILED;
6497 }
6498 }
718e3744 6499
d62a17ae 6500 /* Make aggregate address structure. */
6501 aggregate = bgp_aggregate_new();
6502 aggregate->summary_only = summary_only;
6503 aggregate->as_set = as_set;
6504 aggregate->safi = safi;
20894f50
DA
6505
6506 if (rmap) {
6507 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6508 route_map_counter_decrement(aggregate->rmap.map);
6509 aggregate->rmap.name =
6510 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6511 aggregate->rmap.map = route_map_lookup_by_name(rmap);
6512 route_map_counter_increment(aggregate->rmap.map);
6513 }
b613a918 6514 bgp_node_set_bgp_aggregate_info(rn, aggregate);
718e3744 6515
d62a17ae 6516 /* Aggregate address insert into BGP routing table. */
fc968841 6517 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 6518
d62a17ae 6519 return CMD_SUCCESS;
718e3744 6520}
6521
6522DEFUN (aggregate_address,
6523 aggregate_address_cmd,
20894f50 6524 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6525 "Configure BGP aggregate entries\n"
6526 "Aggregate prefix\n"
6527 "Generate AS set path information\n"
a636c635
DW
6528 "Filter more specific routes from updates\n"
6529 "Filter more specific routes from updates\n"
20894f50
DA
6530 "Generate AS set path information\n"
6531 "Apply route map to aggregate network\n"
6532 "Name of route map\n")
718e3744 6533{
d62a17ae 6534 int idx = 0;
6535 argv_find(argv, argc, "A.B.C.D/M", &idx);
6536 char *prefix = argv[idx]->arg;
20894f50 6537 char *rmap = NULL;
d62a17ae 6538 int as_set =
6539 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
6540 idx = 0;
6541 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6542 ? AGGREGATE_SUMMARY_ONLY
6543 : 0;
e3e6107d 6544
20894f50
DA
6545 idx = 0;
6546 argv_find(argv, argc, "WORD", &idx);
6547 if (idx)
6548 rmap = argv[idx]->arg;
6549
d62a17ae 6550 return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty),
20894f50 6551 rmap, summary_only, as_set);
718e3744 6552}
6553
e3e6107d
QY
6554DEFUN (aggregate_address_mask,
6555 aggregate_address_mask_cmd,
20894f50 6556 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6557 "Configure BGP aggregate entries\n"
6558 "Aggregate address\n"
6559 "Aggregate mask\n"
6560 "Generate AS set path information\n"
a636c635
DW
6561 "Filter more specific routes from updates\n"
6562 "Filter more specific routes from updates\n"
20894f50
DA
6563 "Generate AS set path information\n"
6564 "Apply route map to aggregate network\n"
6565 "Name of route map\n")
718e3744 6566{
d62a17ae 6567 int idx = 0;
6568 argv_find(argv, argc, "A.B.C.D", &idx);
6569 char *prefix = argv[idx]->arg;
6570 char *mask = argv[idx + 1]->arg;
cf40d052 6571 bool rmap_found;
20894f50 6572 char *rmap = NULL;
d62a17ae 6573 int as_set =
6574 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
6575 idx = 0;
6576 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6577 ? AGGREGATE_SUMMARY_ONLY
6578 : 0;
6579
cf40d052
DS
6580 rmap_found = argv_find(argv, argc, "WORD", &idx);
6581 if (rmap_found)
20894f50
DA
6582 rmap = argv[idx]->arg;
6583
d62a17ae 6584 char prefix_str[BUFSIZ];
6585 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
6586
6587 if (!ret) {
6588 vty_out(vty, "%% Inconsistent address and mask\n");
6589 return CMD_WARNING_CONFIG_FAILED;
6590 }
718e3744 6591
d62a17ae 6592 return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
20894f50 6593 rmap, summary_only, as_set);
718e3744 6594}
6595
718e3744 6596DEFUN (no_aggregate_address,
6597 no_aggregate_address_cmd,
b84da0db 6598 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6599 NO_STR
6600 "Configure BGP aggregate entries\n"
a636c635
DW
6601 "Aggregate prefix\n"
6602 "Generate AS set path information\n"
e3e6107d
QY
6603 "Filter more specific routes from updates\n"
6604 "Filter more specific routes from updates\n"
b84da0db
DA
6605 "Generate AS set path information\n"
6606 "Apply route map to aggregate network\n"
6607 "Name of route map\n")
718e3744 6608{
d62a17ae 6609 int idx = 0;
6610 argv_find(argv, argc, "A.B.C.D/M", &idx);
6611 char *prefix = argv[idx]->arg;
6612 return bgp_aggregate_unset(vty, prefix, AFI_IP, bgp_node_safi(vty));
718e3744 6613}
6614
718e3744 6615DEFUN (no_aggregate_address_mask,
6616 no_aggregate_address_mask_cmd,
b84da0db 6617 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6618 NO_STR
6619 "Configure BGP aggregate entries\n"
6620 "Aggregate address\n"
a636c635
DW
6621 "Aggregate mask\n"
6622 "Generate AS set path information\n"
e3e6107d
QY
6623 "Filter more specific routes from updates\n"
6624 "Filter more specific routes from updates\n"
b84da0db
DA
6625 "Generate AS set path information\n"
6626 "Apply route map to aggregate network\n"
6627 "Name of route map\n")
718e3744 6628{
d62a17ae 6629 int idx = 0;
6630 argv_find(argv, argc, "A.B.C.D", &idx);
6631 char *prefix = argv[idx]->arg;
6632 char *mask = argv[idx + 1]->arg;
718e3744 6633
d62a17ae 6634 char prefix_str[BUFSIZ];
6635 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
718e3744 6636
d62a17ae 6637 if (!ret) {
6638 vty_out(vty, "%% Inconsistent address and mask\n");
6639 return CMD_WARNING_CONFIG_FAILED;
6640 }
718e3744 6641
d62a17ae 6642 return bgp_aggregate_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
718e3744 6643}
6644
718e3744 6645DEFUN (ipv6_aggregate_address,
6646 ipv6_aggregate_address_cmd,
20894f50 6647 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6648 "Configure BGP aggregate entries\n"
6649 "Aggregate prefix\n"
5101fece 6650 "Generate AS set path information\n"
6651 "Filter more specific routes from updates\n"
6652 "Filter more specific routes from updates\n"
20894f50
DA
6653 "Generate AS set path information\n"
6654 "Apply route map to aggregate network\n"
6655 "Name of route map\n")
718e3744 6656{
d62a17ae 6657 int idx = 0;
6658 argv_find(argv, argc, "X:X::X:X/M", &idx);
6659 char *prefix = argv[idx]->arg;
20894f50 6660 char *rmap = NULL;
273fae13 6661 bool rmap_found;
5101fece 6662 int as_set =
6663 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
6664
6665 idx = 0;
d62a17ae 6666 int sum_only = argv_find(argv, argc, "summary-only", &idx)
6667 ? AGGREGATE_SUMMARY_ONLY
6668 : 0;
20894f50 6669
273fae13
DA
6670 rmap_found = argv_find(argv, argc, "WORD", &idx);
6671 if (rmap_found)
20894f50
DA
6672 rmap = argv[idx]->arg;
6673
6674 return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, rmap,
6675 sum_only, as_set);
718e3744 6676}
6677
6678DEFUN (no_ipv6_aggregate_address,
6679 no_ipv6_aggregate_address_cmd,
b84da0db 6680 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6681 NO_STR
6682 "Configure BGP aggregate entries\n"
16cedbb0 6683 "Aggregate prefix\n"
5101fece 6684 "Generate AS set path information\n"
6685 "Filter more specific routes from updates\n"
6686 "Filter more specific routes from updates\n"
b84da0db
DA
6687 "Generate AS set path information\n"
6688 "Apply route map to aggregate network\n"
6689 "Name of route map\n")
718e3744 6690{
d62a17ae 6691 int idx = 0;
6692 argv_find(argv, argc, "X:X::X:X/M", &idx);
6693 char *prefix = argv[idx]->arg;
6694 return bgp_aggregate_unset(vty, prefix, AFI_IP6, SAFI_UNICAST);
718e3744 6695}
6696
718e3744 6697/* Redistribute route treatment. */
d62a17ae 6698void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
6699 const union g_addr *nexthop, ifindex_t ifindex,
6700 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
6701 uint8_t type, unsigned short instance,
6702 route_tag_t tag)
d62a17ae 6703{
4b7e6066 6704 struct bgp_path_info *new;
40381db7
DS
6705 struct bgp_path_info *bpi;
6706 struct bgp_path_info rmap_path;
d62a17ae 6707 struct bgp_node *bn;
6708 struct attr attr;
6709 struct attr *new_attr;
6710 afi_t afi;
b68885f9 6711 route_map_result_t ret;
d62a17ae 6712 struct bgp_redist *red;
6713
6714 /* Make default attribute. */
6715 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
6716 /*
6717 * This must not be NULL to satisfy Coverity SA
6718 */
6719 assert(attr.aspath);
9de1f7ff 6720
a4d82a8a 6721 switch (nhtype) {
9de1f7ff
DS
6722 case NEXTHOP_TYPE_IFINDEX:
6723 break;
6724 case NEXTHOP_TYPE_IPV4:
6725 case NEXTHOP_TYPE_IPV4_IFINDEX:
6726 attr.nexthop = nexthop->ipv4;
6727 break;
6728 case NEXTHOP_TYPE_IPV6:
6729 case NEXTHOP_TYPE_IPV6_IFINDEX:
6730 attr.mp_nexthop_global = nexthop->ipv6;
6731 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
6732 break;
6733 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
6734 switch (p->family) {
6735 case AF_INET:
9de1f7ff 6736 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
6737 break;
6738 case AF_INET6:
9de1f7ff
DS
6739 memset(&attr.mp_nexthop_global, 0,
6740 sizeof(attr.mp_nexthop_global));
74489921 6741 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 6742 break;
74489921 6743 }
9de1f7ff 6744 break;
d62a17ae 6745 }
74489921 6746 attr.nh_ifindex = ifindex;
f04a80a5 6747
d62a17ae 6748 attr.med = metric;
6749 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
6750 attr.tag = tag;
718e3744 6751
d62a17ae 6752 afi = family2afi(p->family);
6aeb9e78 6753
d62a17ae 6754 red = bgp_redist_lookup(bgp, afi, type, instance);
6755 if (red) {
6756 struct attr attr_new;
718e3744 6757
d62a17ae 6758 /* Copy attribute for modification. */
6759 bgp_attr_dup(&attr_new, &attr);
718e3744 6760
d62a17ae 6761 if (red->redist_metric_flag)
6762 attr_new.med = red->redist_metric;
718e3744 6763
d62a17ae 6764 /* Apply route-map. */
6765 if (red->rmap.name) {
40381db7
DS
6766 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
6767 rmap_path.peer = bgp->peer_self;
6768 rmap_path.attr = &attr_new;
718e3744 6769
d62a17ae 6770 SET_FLAG(bgp->peer_self->rmap_type,
6771 PEER_RMAP_TYPE_REDISTRIBUTE);
6772
6773 ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
40381db7 6774 &rmap_path);
d62a17ae 6775
6776 bgp->peer_self->rmap_type = 0;
6777
6778 if (ret == RMAP_DENYMATCH) {
6779 /* Free uninterned attribute. */
6780 bgp_attr_flush(&attr_new);
6781
6782 /* Unintern original. */
6783 aspath_unintern(&attr.aspath);
6784 bgp_redistribute_delete(bgp, p, type, instance);
6785 return;
6786 }
6787 }
6788
7f323236
DW
6789 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
6790 bgp_attr_add_gshut_community(&attr_new);
6791
d62a17ae 6792 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
6793 SAFI_UNICAST, p, NULL);
6794
6795 new_attr = bgp_attr_intern(&attr_new);
6796
6f94b685
DS
6797 for (bpi = bgp_node_get_bgp_path_info(bn); bpi;
6798 bpi = bpi->next)
40381db7
DS
6799 if (bpi->peer == bgp->peer_self
6800 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 6801 break;
6802
40381db7 6803 if (bpi) {
d62a17ae 6804 /* Ensure the (source route) type is updated. */
40381db7
DS
6805 bpi->type = type;
6806 if (attrhash_cmp(bpi->attr, new_attr)
6807 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 6808 bgp_attr_unintern(&new_attr);
6809 aspath_unintern(&attr.aspath);
6810 bgp_unlock_node(bn);
6811 return;
6812 } else {
6813 /* The attribute is changed. */
40381db7 6814 bgp_path_info_set_flag(bn, bpi,
18ee8310 6815 BGP_PATH_ATTR_CHANGED);
d62a17ae 6816
6817 /* Rewrite BGP route information. */
40381db7
DS
6818 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
6819 bgp_path_info_restore(bn, bpi);
d62a17ae 6820 else
40381db7
DS
6821 bgp_aggregate_decrement(
6822 bgp, p, bpi, afi, SAFI_UNICAST);
6823 bgp_attr_unintern(&bpi->attr);
6824 bpi->attr = new_attr;
6825 bpi->uptime = bgp_clock();
d62a17ae 6826
6827 /* Process change. */
40381db7 6828 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 6829 SAFI_UNICAST);
6830 bgp_process(bgp, bn, afi, SAFI_UNICAST);
6831 bgp_unlock_node(bn);
6832 aspath_unintern(&attr.aspath);
ddb5b488
PZ
6833
6834 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6835 || (bgp->inst_type
6836 == BGP_INSTANCE_TYPE_DEFAULT)) {
6837
6838 vpn_leak_from_vrf_update(
40381db7 6839 bgp_get_default(), bgp, bpi);
ddb5b488 6840 }
d62a17ae 6841 return;
6842 }
6843 }
6844
6845 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
6846 bgp->peer_self, new_attr, bn);
1defdda8 6847 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 6848
6849 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 6850 bgp_path_info_add(bn, new);
d62a17ae 6851 bgp_unlock_node(bn);
6852 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
6853
6854 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6855 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6856
6857 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6858 }
d62a17ae 6859 }
6860
6861 /* Unintern original. */
6862 aspath_unintern(&attr.aspath);
718e3744 6863}
6864
d7c0a89a
QY
6865void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
6866 unsigned short instance)
718e3744 6867{
d62a17ae 6868 afi_t afi;
6869 struct bgp_node *rn;
40381db7 6870 struct bgp_path_info *pi;
d62a17ae 6871 struct bgp_redist *red;
718e3744 6872
d62a17ae 6873 afi = family2afi(p->family);
718e3744 6874
d62a17ae 6875 red = bgp_redist_lookup(bgp, afi, type, instance);
6876 if (red) {
6877 rn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
6878 SAFI_UNICAST, p, NULL);
6879
6f94b685 6880 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7 6881 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 6882 break;
6883
40381db7 6884 if (pi) {
ddb5b488
PZ
6885 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6886 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6887
6888 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 6889 bgp, pi);
ddb5b488 6890 }
40381db7
DS
6891 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
6892 bgp_path_info_delete(rn, pi);
d62a17ae 6893 bgp_process(bgp, rn, afi, SAFI_UNICAST);
6894 }
6895 bgp_unlock_node(rn);
6896 }
6897}
6898
6899/* Withdraw specified route type's route. */
6900void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 6901 unsigned short instance)
d62a17ae 6902{
6903 struct bgp_node *rn;
40381db7 6904 struct bgp_path_info *pi;
d62a17ae 6905 struct bgp_table *table;
6906
6907 table = bgp->rib[afi][SAFI_UNICAST];
6908
6909 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685 6910 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
6911 if (pi->peer == bgp->peer_self && pi->type == type
6912 && pi->instance == instance)
d62a17ae 6913 break;
6914
40381db7 6915 if (pi) {
ddb5b488
PZ
6916 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6917 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6918
6919 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 6920 bgp, pi);
ddb5b488 6921 }
40381db7 6922 bgp_aggregate_decrement(bgp, &rn->p, pi, afi,
d62a17ae 6923 SAFI_UNICAST);
40381db7 6924 bgp_path_info_delete(rn, pi);
d62a17ae 6925 bgp_process(bgp, rn, afi, SAFI_UNICAST);
6926 }
718e3744 6927 }
718e3744 6928}
6b0655a2 6929
718e3744 6930/* Static function to display route. */
9c92b5f7
MK
6931static void route_vty_out_route(struct prefix *p, struct vty *vty,
6932 json_object *json)
718e3744 6933{
be054588 6934 int len = 0;
d62a17ae 6935 char buf[BUFSIZ];
50e05855 6936 char buf2[BUFSIZ];
718e3744 6937
d62a17ae 6938 if (p->family == AF_INET) {
c6462ff4 6939 if (!json) {
89e5e9f0
PM
6940 len = vty_out(
6941 vty, "%s/%d",
6942 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
6943 p->prefixlen);
c6462ff4
MK
6944 } else {
6945 json_object_string_add(json, "prefix",
6946 inet_ntop(p->family,
6947 &p->u.prefix, buf,
6948 BUFSIZ));
6949 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 6950 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 6951 json_object_string_add(json, "network", buf2);
c6462ff4 6952 }
d62a17ae 6953 } else if (p->family == AF_ETHERNET) {
b03b8898
DS
6954 prefix2str(p, buf, PREFIX_STRLEN);
6955 len = vty_out(vty, "%s", buf);
6956 } else if (p->family == AF_EVPN) {
57f7feb6 6957 if (!json)
60466a63
QY
6958 len = vty_out(
6959 vty, "%s",
6960 bgp_evpn_route2str((struct prefix_evpn *)p, buf,
6961 BUFSIZ));
57f7feb6 6962 else
60466a63 6963 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
6964 } else if (p->family == AF_FLOWSPEC) {
6965 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
6966 json ?
6967 NLRI_STRING_FORMAT_JSON_SIMPLE :
6968 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 6969 } else {
c6462ff4 6970 if (!json)
60466a63
QY
6971 len = vty_out(
6972 vty, "%s/%d",
6973 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
6974 p->prefixlen);
50e05855
AD
6975 else {
6976 json_object_string_add(json, "prefix",
6977 inet_ntop(p->family,
6978 &p->u.prefix, buf,
6979 BUFSIZ));
6980 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
6981 prefix2str(p, buf2, PREFIX_STRLEN);
6982 json_object_string_add(json, "network", buf2);
6983 }
9c92b5f7 6984 }
d62a17ae 6985
9c92b5f7
MK
6986 if (!json) {
6987 len = 17 - len;
6988 if (len < 1)
6989 vty_out(vty, "\n%*s", 20, " ");
6990 else
6991 vty_out(vty, "%*s", len, " ");
6992 }
718e3744 6993}
6994
d62a17ae 6995enum bgp_display_type {
6996 normal_list,
718e3744 6997};
6998
18ee8310 6999/* Print the short form route status for a bgp_path_info */
4b7e6066 7000static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 7001 struct bgp_path_info *path,
d62a17ae 7002 json_object *json_path)
718e3744 7003{
d62a17ae 7004 if (json_path) {
b05a1c8b 7005
d62a17ae 7006 /* Route status display. */
9b6d8fcf 7007 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7008 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 7009
9b6d8fcf 7010 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7011 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 7012
9b6d8fcf 7013 if (path->extra && path->extra->suppress)
d62a17ae 7014 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 7015
9b6d8fcf
DS
7016 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7017 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7018 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 7019
d62a17ae 7020 /* Selected */
9b6d8fcf 7021 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7022 json_object_boolean_true_add(json_path, "history");
b05a1c8b 7023
9b6d8fcf 7024 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7025 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 7026
9b6d8fcf 7027 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7028 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b 7029
9b6d8fcf 7030 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7031 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 7032
d62a17ae 7033 /* Internal route. */
9b6d8fcf
DS
7034 if ((path->peer->as)
7035 && (path->peer->as == path->peer->local_as))
d62a17ae 7036 json_object_string_add(json_path, "pathFrom",
7037 "internal");
7038 else
7039 json_object_string_add(json_path, "pathFrom",
7040 "external");
b05a1c8b 7041
d62a17ae 7042 return;
7043 }
b05a1c8b 7044
d62a17ae 7045 /* Route status display. */
9b6d8fcf 7046 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7047 vty_out(vty, "R");
9b6d8fcf 7048 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7049 vty_out(vty, "S");
9b6d8fcf 7050 else if (path->extra && path->extra->suppress)
d62a17ae 7051 vty_out(vty, "s");
9b6d8fcf
DS
7052 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7053 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7054 vty_out(vty, "*");
7055 else
7056 vty_out(vty, " ");
7057
7058 /* Selected */
9b6d8fcf 7059 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7060 vty_out(vty, "h");
9b6d8fcf 7061 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7062 vty_out(vty, "d");
9b6d8fcf 7063 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7064 vty_out(vty, ">");
9b6d8fcf 7065 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7066 vty_out(vty, "=");
7067 else
7068 vty_out(vty, " ");
718e3744 7069
d62a17ae 7070 /* Internal route. */
9b6d8fcf
DS
7071 if (path->peer && (path->peer->as)
7072 && (path->peer->as == path->peer->local_as))
d62a17ae 7073 vty_out(vty, "i");
7074 else
7075 vty_out(vty, " ");
b40d939b 7076}
7077
25b5da8d
DA
7078static char *bgp_nexthop_fqdn(struct peer *peer)
7079{
7080 if (peer->hostname && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
7081 return peer->hostname;
7082 return NULL;
7083}
7084
b40d939b 7085/* called from terminal list command */
4b7e6066 7086void route_vty_out(struct vty *vty, struct prefix *p,
9b6d8fcf 7087 struct bgp_path_info *path, int display, safi_t safi,
4b7e6066 7088 json_object *json_paths)
d62a17ae 7089{
7090 struct attr *attr;
7091 json_object *json_path = NULL;
7092 json_object *json_nexthops = NULL;
7093 json_object *json_nexthop_global = NULL;
7094 json_object *json_nexthop_ll = NULL;
6f214dd3 7095 json_object *json_ext_community = NULL;
9df8b37c 7096 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 7097 bool nexthop_self =
9b6d8fcf 7098 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 7099 bool nexthop_othervrf = false;
43089216 7100 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 7101 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
25b5da8d 7102 char *nexthop_fqdn = bgp_nexthop_fqdn(path->peer);
d62a17ae 7103
7104 if (json_paths)
7105 json_path = json_object_new_object();
7106
7107 /* short status lead text */
9b6d8fcf 7108 route_vty_short_status_out(vty, path, json_path);
d62a17ae 7109
7110 if (!json_paths) {
7111 /* print prefix and mask */
7112 if (!display)
9c92b5f7 7113 route_vty_out_route(p, vty, json_path);
d62a17ae 7114 else
7115 vty_out(vty, "%*s", 17, " ");
9c92b5f7 7116 } else {
b682f6de 7117 route_vty_out_route(p, vty, json_path);
d62a17ae 7118 }
47fc97cc 7119
d62a17ae 7120 /* Print attribute */
9b6d8fcf 7121 attr = path->attr;
445c2480 7122
9df8b37c
PZ
7123 /*
7124 * If vrf id of nexthop is different from that of prefix,
7125 * set up printable string to append
7126 */
9b6d8fcf 7127 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
7128 const char *self = "";
7129
7130 if (nexthop_self)
7131 self = "<";
7132
7133 nexthop_othervrf = true;
9b6d8fcf 7134 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 7135
9b6d8fcf 7136 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
7137 snprintf(vrf_id_str, sizeof(vrf_id_str),
7138 "@%s%s", VRFID_NONE_STR, self);
7139 else
7140 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 7141 path->extra->bgp_orig->vrf_id, self);
9df8b37c 7142
9b6d8fcf
DS
7143 if (path->extra->bgp_orig->inst_type
7144 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 7145
9b6d8fcf 7146 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
7147 } else {
7148 const char *self = "";
7149
7150 if (nexthop_self)
7151 self = "<";
7152
7153 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
7154 }
7155
445c2480
DS
7156 /*
7157 * For ENCAP and EVPN routes, nexthop address family is not
7158 * neccessarily the same as the prefix address family.
7159 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7160 * EVPN routes are also exchanged with a MP nexthop. Currently,
7161 * this
7162 * is only IPv4, the value will be present in either
7163 * attr->nexthop or
7164 * attr->mp_nexthop_global_in
7165 */
7166 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
7167 char buf[BUFSIZ];
7168 char nexthop[128];
7169 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
7170
7171 switch (af) {
7172 case AF_INET:
7173 sprintf(nexthop, "%s",
a4d82a8a
PZ
7174 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
7175 BUFSIZ));
445c2480
DS
7176 break;
7177 case AF_INET6:
7178 sprintf(nexthop, "%s",
a4d82a8a
PZ
7179 inet_ntop(af, &attr->mp_nexthop_global, buf,
7180 BUFSIZ));
445c2480
DS
7181 break;
7182 default:
7183 sprintf(nexthop, "?");
7184 break;
d62a17ae 7185 }
d62a17ae 7186
445c2480
DS
7187 if (json_paths) {
7188 json_nexthop_global = json_object_new_object();
7189
25b5da8d
DA
7190 json_object_string_add(
7191 json_nexthop_global, "afi",
7192 nexthop_fqdn ? "fqdn"
7193 : (af == AF_INET) ? "ip" : "ipv6");
7194 json_object_string_add(
7195 json_nexthop_global,
7196 nexthop_fqdn ? "fqdn"
7197 : (af == AF_INET) ? "ip" : "ipv6",
7198 nexthop_fqdn ? nexthop_fqdn : nexthop);
445c2480
DS
7199 json_object_boolean_true_add(json_nexthop_global,
7200 "used");
7201 } else
25b5da8d
DA
7202 vty_out(vty, "%s%s",
7203 nexthop_fqdn ? nexthop_fqdn : nexthop,
7204 vrf_id_str);
445c2480
DS
7205 } else if (safi == SAFI_EVPN) {
7206 if (json_paths) {
7207 json_nexthop_global = json_object_new_object();
7208
25b5da8d
DA
7209 json_object_string_add(
7210 json_nexthop_global,
7211 nexthop_fqdn ? "fqdn" : "ip",
7212 nexthop_fqdn ? nexthop_fqdn
7213 : inet_ntoa(attr->nexthop));
a4d82a8a
PZ
7214 json_object_string_add(json_nexthop_global, "afi",
7215 "ipv4");
445c2480
DS
7216 json_object_boolean_true_add(json_nexthop_global,
7217 "used");
7218 } else
25b5da8d
DA
7219 vty_out(vty, "%-16s%s",
7220 nexthop_fqdn ?: inet_ntoa(attr->nexthop),
9df8b37c 7221 vrf_id_str);
d33fc23b 7222 } else if (safi == SAFI_FLOWSPEC) {
026b914a
PG
7223 if (attr->nexthop.s_addr != 0) {
7224 if (json_paths) {
7225 json_nexthop_global = json_object_new_object();
7226 json_object_string_add(
25b5da8d
DA
7227 json_nexthop_global,
7228 nexthop_fqdn ? "fqdn" : "ip",
7229 nexthop_fqdn
7230 ? nexthop_fqdn
7231 : inet_ntoa(attr->nexthop));
026b914a
PG
7232 json_object_string_add(json_nexthop_global,
7233 "afi", "ipv4");
50e05855
AD
7234 json_object_boolean_true_add(
7235 json_nexthop_global,
026b914a
PG
7236 "used");
7237 } else {
25b5da8d
DA
7238 vty_out(vty, "%-16s",
7239 nexthop_fqdn
7240 ? nexthop_fqdn
7241 : inet_ntoa(attr->nexthop));
026b914a
PG
7242 }
7243 }
d33fc23b 7244 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
7245 if (json_paths) {
7246 json_nexthop_global = json_object_new_object();
d62a17ae 7247
22df2d8a
DS
7248 json_object_string_add(json_nexthop_global,
7249 nexthop_fqdn ? "fqdn" : "ip",
7250 nexthop_fqdn
7251 ? nexthop_fqdn
7252 : inet_ntoa(attr->nexthop));
445c2480 7253
a4d82a8a
PZ
7254 json_object_string_add(json_nexthop_global, "afi",
7255 "ipv4");
445c2480
DS
7256 json_object_boolean_true_add(json_nexthop_global,
7257 "used");
7258 } else {
9df8b37c
PZ
7259 char buf[BUFSIZ];
7260
d87ff2dd 7261 snprintf(buf, sizeof(buf), "%s%s",
25b5da8d
DA
7262 nexthop_fqdn ? nexthop_fqdn
7263 : inet_ntoa(attr->nexthop),
7264 vrf_id_str);
9df8b37c 7265 vty_out(vty, "%-16s", buf);
d62a17ae 7266 }
445c2480 7267 }
b05a1c8b 7268
445c2480 7269 /* IPv6 Next Hop */
a4d82a8a 7270 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
7271 int len;
7272 char buf[BUFSIZ];
d62a17ae 7273
445c2480
DS
7274 if (json_paths) {
7275 json_nexthop_global = json_object_new_object();
a4d82a8a 7276 json_object_string_add(
25b5da8d
DA
7277 json_nexthop_global,
7278 nexthop_fqdn ? "fqdn" : "ip",
7279 nexthop_fqdn
7280 ? nexthop_fqdn
7281 : inet_ntop(AF_INET6,
7282 &attr->mp_nexthop_global,
7283 buf, BUFSIZ));
a4d82a8a
PZ
7284 json_object_string_add(json_nexthop_global, "afi",
7285 "ipv6");
7286 json_object_string_add(json_nexthop_global, "scope",
7287 "global");
445c2480
DS
7288
7289 /* We display both LL & GL if both have been
7290 * received */
0606039c
DA
7291 if ((attr->mp_nexthop_len
7292 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 7293 || (path->peer->conf_if)) {
a4d82a8a 7294 json_nexthop_ll = json_object_new_object();
d62a17ae 7295 json_object_string_add(
25b5da8d
DA
7296 json_nexthop_ll,
7297 nexthop_fqdn ? "fqdn" : "ip",
7298 nexthop_fqdn
7299 ? nexthop_fqdn
7300 : inet_ntop(
7301 AF_INET6,
7302 &attr->mp_nexthop_local,
7303 buf, BUFSIZ));
a4d82a8a
PZ
7304 json_object_string_add(json_nexthop_ll, "afi",
7305 "ipv6");
7306 json_object_string_add(json_nexthop_ll, "scope",
445c2480 7307 "link-local");
d62a17ae 7308
a4d82a8a
PZ
7309 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
7310 &attr->mp_nexthop_local)
445c2480
DS
7311 != 0)
7312 && !attr->mp_nexthop_prefer_global)
d62a17ae 7313 json_object_boolean_true_add(
a4d82a8a 7314 json_nexthop_ll, "used");
445c2480
DS
7315 else
7316 json_object_boolean_true_add(
a4d82a8a 7317 json_nexthop_global, "used");
445c2480
DS
7318 } else
7319 json_object_boolean_true_add(
7320 json_nexthop_global, "used");
7321 } else {
7322 /* Display LL if LL/Global both in table unless
7323 * prefer-global is set */
0606039c
DA
7324 if (((attr->mp_nexthop_len
7325 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 7326 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
7327 || (path->peer->conf_if)) {
7328 if (path->peer->conf_if) {
a4d82a8a 7329 len = vty_out(vty, "%s",
9b6d8fcf 7330 path->peer->conf_if);
445c2480
DS
7331 len = 16 - len; /* len of IPv6
7332 addr + max
7333 len of def
7334 ifname */
7335
7336 if (len < 1)
a4d82a8a 7337 vty_out(vty, "\n%*s", 36, " ");
445c2480 7338 else
a4d82a8a 7339 vty_out(vty, "%*s", len, " ");
d62a17ae 7340 } else {
7341 len = vty_out(
9df8b37c 7342 vty, "%s%s",
25b5da8d
DA
7343 nexthop_fqdn
7344 ? nexthop_fqdn
7345 : inet_ntop(
7346 AF_INET6,
7347 &attr->mp_nexthop_local,
7348 buf, BUFSIZ),
9df8b37c 7349 vrf_id_str);
d62a17ae 7350 len = 16 - len;
7351
7352 if (len < 1)
a4d82a8a 7353 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 7354 else
a4d82a8a 7355 vty_out(vty, "%*s", len, " ");
d62a17ae 7356 }
445c2480 7357 } else {
a4d82a8a 7358 len = vty_out(
9df8b37c 7359 vty, "%s%s",
25b5da8d
DA
7360 nexthop_fqdn
7361 ? nexthop_fqdn
7362 : inet_ntop(
7363 AF_INET6,
7364 &attr->mp_nexthop_global,
7365 buf, BUFSIZ),
7366 vrf_id_str);
445c2480
DS
7367 len = 16 - len;
7368
7369 if (len < 1)
7370 vty_out(vty, "\n%*s", 36, " ");
7371 else
7372 vty_out(vty, "%*s", len, " ");
d62a17ae 7373 }
7374 }
445c2480 7375 }
718e3744 7376
445c2480
DS
7377 /* MED/Metric */
7378 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
50e05855
AD
7379 if (json_paths) {
7380
7381 /*
7382 * Adding "metric" field to match with corresponding
7383 * CLI. "med" will be deprecated in future.
7384 */
a4d82a8a 7385 json_object_int_add(json_path, "med", attr->med);
50e05855
AD
7386 json_object_int_add(json_path, "metric", attr->med);
7387 } else
445c2480
DS
7388 vty_out(vty, "%10u", attr->med);
7389 else if (!json_paths)
7390 vty_out(vty, " ");
d62a17ae 7391
445c2480
DS
7392 /* Local Pref */
7393 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855
AD
7394 if (json_paths) {
7395
7396 /*
7397 * Adding "locPrf" field to match with corresponding
7398 * CLI. "localPref" will be deprecated in future.
7399 */
445c2480
DS
7400 json_object_int_add(json_path, "localpref",
7401 attr->local_pref);
50e05855
AD
7402 json_object_int_add(json_path, "locPrf",
7403 attr->local_pref);
7404 } else
445c2480
DS
7405 vty_out(vty, "%7u", attr->local_pref);
7406 else if (!json_paths)
7407 vty_out(vty, " ");
d62a17ae 7408
445c2480
DS
7409 if (json_paths)
7410 json_object_int_add(json_path, "weight", attr->weight);
7411 else
7412 vty_out(vty, "%7u ", attr->weight);
47fc97cc 7413
445c2480
DS
7414 if (json_paths) {
7415 char buf[BUFSIZ];
a4d82a8a
PZ
7416 json_object_string_add(
7417 json_path, "peerId",
9b6d8fcf 7418 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 7419 }
b05a1c8b 7420
445c2480
DS
7421 /* Print aspath */
7422 if (attr->aspath) {
50e05855
AD
7423 if (json_paths) {
7424
7425 /*
7426 * Adding "path" field to match with corresponding
7427 * CLI. "aspath" will be deprecated in future.
7428 */
445c2480
DS
7429 json_object_string_add(json_path, "aspath",
7430 attr->aspath->str);
50e05855
AD
7431 json_object_string_add(json_path, "path",
7432 attr->aspath->str);
7433 } else
445c2480 7434 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 7435 }
f1aa5d8a 7436
445c2480
DS
7437 /* Print origin */
7438 if (json_paths)
a4d82a8a
PZ
7439 json_object_string_add(json_path, "origin",
7440 bgp_origin_long_str[attr->origin]);
445c2480
DS
7441 else
7442 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7443
9df8b37c 7444 if (json_paths) {
6f214dd3
CS
7445 if (safi == SAFI_EVPN &&
7446 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7447 json_ext_community = json_object_new_object();
7448 json_object_string_add(json_ext_community,
7449 "string",
7450 attr->ecommunity->str);
7451 json_object_object_add(json_path,
7452 "extendedCommunity",
7453 json_ext_community);
7454 }
7455
9df8b37c
PZ
7456 if (nexthop_self)
7457 json_object_boolean_true_add(json_path,
7458 "announceNexthopSelf");
7459 if (nexthop_othervrf) {
7460 json_object_string_add(json_path, "nhVrfName",
7461 nexthop_vrfname);
7462
7463 json_object_int_add(json_path, "nhVrfId",
7464 ((nexthop_vrfid == VRF_UNKNOWN)
7465 ? -1
7466 : (int)nexthop_vrfid));
7467 }
7468 }
7469
d62a17ae 7470 if (json_paths) {
7471 if (json_nexthop_global || json_nexthop_ll) {
7472 json_nexthops = json_object_new_array();
f1aa5d8a 7473
d62a17ae 7474 if (json_nexthop_global)
7475 json_object_array_add(json_nexthops,
7476 json_nexthop_global);
f1aa5d8a 7477
d62a17ae 7478 if (json_nexthop_ll)
7479 json_object_array_add(json_nexthops,
7480 json_nexthop_ll);
f1aa5d8a 7481
d62a17ae 7482 json_object_object_add(json_path, "nexthops",
7483 json_nexthops);
7484 }
7485
7486 json_object_array_add(json_paths, json_path);
7487 } else {
7488 vty_out(vty, "\n");
6f214dd3
CS
7489
7490 if (safi == SAFI_EVPN &&
7491 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7492 vty_out(vty, "%*s", 20, " ");
7493 vty_out(vty, "%s\n", attr->ecommunity->str);
7494 }
7495
65efcfce 7496#if ENABLE_BGP_VNC
d62a17ae 7497 /* prints an additional line, indented, with VNC info, if
7498 * present */
7499 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 7500 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 7501#endif
d62a17ae 7502 }
7503}
718e3744 7504
7505/* called from terminal list command */
d62a17ae 7506void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr,
9f049418 7507 safi_t safi, bool use_json, json_object *json_ar)
d62a17ae 7508{
7509 json_object *json_status = NULL;
7510 json_object *json_net = NULL;
7511 char buff[BUFSIZ];
dc387b0f 7512
d62a17ae 7513 /* Route status display. */
7514 if (use_json) {
7515 json_status = json_object_new_object();
7516 json_net = json_object_new_object();
7517 } else {
7518 vty_out(vty, "*");
7519 vty_out(vty, ">");
7520 vty_out(vty, " ");
7521 }
718e3744 7522
d62a17ae 7523 /* print prefix and mask */
50e05855 7524 if (use_json) {
dc387b0f
LK
7525 if (safi == SAFI_EVPN)
7526 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
7527 else if (p->family == AF_INET || p->family == AF_INET6) {
7528 json_object_string_add(
7529 json_net, "addrPrefix",
7530 inet_ntop(p->family, &p->u.prefix, buff,
7531 BUFSIZ));
7532 json_object_int_add(json_net, "prefixLen",
7533 p->prefixlen);
7534 prefix2str(p, buff, PREFIX_STRLEN);
7535 json_object_string_add(json_net, "network", buff);
7536 }
50e05855 7537 } else
9c92b5f7 7538 route_vty_out_route(p, vty, NULL);
d62a17ae 7539
7540 /* Print attribute */
7541 if (attr) {
7542 if (use_json) {
7543 if (p->family == AF_INET
7544 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 7545 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 7546 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 7547 json_object_string_add(
7548 json_net, "nextHop",
7549 inet_ntoa(
7550 attr->mp_nexthop_global_in));
7551 else
7552 json_object_string_add(
7553 json_net, "nextHop",
7554 inet_ntoa(attr->nexthop));
7555 } else if (p->family == AF_INET6
7556 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
7557 char buf[BUFSIZ];
7558
7559 json_object_string_add(
aa0a10fc 7560 json_net, "nextHopGlobal",
d62a17ae 7561 inet_ntop(AF_INET6,
7562 &attr->mp_nexthop_global, buf,
7563 BUFSIZ));
dc387b0f
LK
7564 } else if (p->family == AF_EVPN &&
7565 !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
7566 json_object_string_add(json_net,
7567 "nextHop", inet_ntoa(
7568 attr->mp_nexthop_global_in));
d62a17ae 7569
7570 if (attr->flag
7571 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
7572 json_object_int_add(json_net, "metric",
7573 attr->med);
7574
50e05855
AD
7575 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
7576
7577 /*
7578 * Adding "locPrf" field to match with
7579 * corresponding CLI. "localPref" will be
7580 * deprecated in future.
7581 */
d62a17ae 7582 json_object_int_add(json_net, "localPref",
7583 attr->local_pref);
50e05855
AD
7584 json_object_int_add(json_net, "locPrf",
7585 attr->local_pref);
7586 }
d62a17ae 7587
7588 json_object_int_add(json_net, "weight", attr->weight);
7589
7590 /* Print aspath */
50e05855
AD
7591 if (attr->aspath) {
7592
7593 /*
7594 * Adding "path" field to match with
7595 * corresponding CLI. "localPref" will be
7596 * deprecated in future.
7597 */
d62a17ae 7598 json_object_string_add(json_net, "asPath",
7599 attr->aspath->str);
50e05855
AD
7600 json_object_string_add(json_net, "path",
7601 attr->aspath->str);
7602 }
d62a17ae 7603
7604 /* Print origin */
7605 json_object_string_add(json_net, "bgpOriginCode",
7606 bgp_origin_str[attr->origin]);
7607 } else {
7608 if (p->family == AF_INET
7609 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7610 || safi == SAFI_EVPN
7611 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7612 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7613 || safi == SAFI_EVPN)
7614 vty_out(vty, "%-16s",
7615 inet_ntoa(
7616 attr->mp_nexthop_global_in));
7617 else
7618 vty_out(vty, "%-16s",
7619 inet_ntoa(attr->nexthop));
7620 } else if (p->family == AF_INET6
7621 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
7622 int len;
7623 char buf[BUFSIZ];
7624
7625 len = vty_out(
7626 vty, "%s",
7627 inet_ntop(AF_INET6,
7628 &attr->mp_nexthop_global, buf,
7629 BUFSIZ));
7630 len = 16 - len;
7631 if (len < 1)
7632 vty_out(vty, "\n%*s", 36, " ");
7633 else
7634 vty_out(vty, "%*s", len, " ");
7635 }
7636 if (attr->flag
7637 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
7638 vty_out(vty, "%10u", attr->med);
7639 else
7640 vty_out(vty, " ");
718e3744 7641
d62a17ae 7642 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
7643 vty_out(vty, "%7u", attr->local_pref);
7644 else
7645 vty_out(vty, " ");
7646
7647 vty_out(vty, "%7u ", attr->weight);
7648
7649 /* Print aspath */
7650 if (attr->aspath)
7651 aspath_print_vty(vty, "%s", attr->aspath, " ");
7652
7653 /* Print origin */
7654 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7655 }
7656 }
7657 if (use_json) {
7658 json_object_boolean_true_add(json_status, "*");
7659 json_object_boolean_true_add(json_status, ">");
7660 json_object_object_add(json_net, "appliedStatusSymbols",
7661 json_status);
1608ff77 7662
dc387b0f
LK
7663 prefix2str(p, buff, PREFIX_STRLEN);
7664 json_object_object_add(json_ar, buff, json_net);
d62a17ae 7665 } else
7666 vty_out(vty, "\n");
7667}
7668
7669void route_vty_out_tag(struct vty *vty, struct prefix *p,
9b6d8fcf 7670 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 7671 json_object *json)
7672{
7673 json_object *json_out = NULL;
7674 struct attr *attr;
7675 mpls_label_t label = MPLS_INVALID_LABEL;
7676
9b6d8fcf 7677 if (!path->extra)
d62a17ae 7678 return;
7679
7680 if (json)
7681 json_out = json_object_new_object();
7682
7683 /* short status lead text */
9b6d8fcf 7684 route_vty_short_status_out(vty, path, json_out);
d62a17ae 7685
7686 /* print prefix and mask */
7687 if (json == NULL) {
7688 if (!display)
9c92b5f7 7689 route_vty_out_route(p, vty, NULL);
d62a17ae 7690 else
7691 vty_out(vty, "%*s", 17, " ");
7692 }
7693
7694 /* Print attribute */
9b6d8fcf 7695 attr = path->attr;
05864da7
DS
7696 if (((p->family == AF_INET)
7697 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
7698 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
7699 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7700 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7701 || safi == SAFI_EVPN) {
7702 if (json)
7703 json_object_string_add(
7704 json_out, "mpNexthopGlobalIn",
7705 inet_ntoa(attr->mp_nexthop_global_in));
7706 else
7707 vty_out(vty, "%-16s",
7708 inet_ntoa(attr->mp_nexthop_global_in));
7709 } else {
7710 if (json)
7711 json_object_string_add(
7712 json_out, "nexthop",
7713 inet_ntoa(attr->nexthop));
7714 else
7715 vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
7716 }
7717 } else if (((p->family == AF_INET6)
7718 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
7719 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
7720 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7721 char buf_a[512];
7722
7723 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
7724 if (json)
7725 json_object_string_add(
7726 json_out, "mpNexthopGlobalIn",
7727 inet_ntop(AF_INET6,
7728 &attr->mp_nexthop_global,
7729 buf_a, sizeof(buf_a)));
7730 else
7731 vty_out(vty, "%s",
7732 inet_ntop(AF_INET6,
7733 &attr->mp_nexthop_global,
7734 buf_a, sizeof(buf_a)));
7735 } else if (attr->mp_nexthop_len
7736 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
7737 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
7738 &attr->mp_nexthop_global,
7739 &attr->mp_nexthop_local);
7740 if (json)
7741 json_object_string_add(json_out,
7742 "mpNexthopGlobalLocal",
7743 buf_a);
7744 else
7745 vty_out(vty, "%s", buf_a);
d62a17ae 7746 }
7747 }
7748
9b6d8fcf 7749 label = decode_label(&path->extra->label[0]);
d62a17ae 7750
7751 if (bgp_is_valid_label(&label)) {
7752 if (json) {
7753 json_object_int_add(json_out, "notag", label);
7754 json_object_array_add(json, json_out);
7755 } else {
7756 vty_out(vty, "notag/%d", label);
7757 vty_out(vty, "\n");
7758 }
7759 }
7760}
718e3744 7761
d62a17ae 7762void route_vty_out_overlay(struct vty *vty, struct prefix *p,
9b6d8fcf 7763 struct bgp_path_info *path, int display,
d62a17ae 7764 json_object *json_paths)
718e3744 7765{
d62a17ae 7766 struct attr *attr;
14f51eba 7767 char buf[BUFSIZ] = {0};
d62a17ae 7768 json_object *json_path = NULL;
14f51eba
LK
7769 json_object *json_nexthop = NULL;
7770 json_object *json_overlay = NULL;
856ca177 7771
9b6d8fcf 7772 if (!path->extra)
d62a17ae 7773 return;
718e3744 7774
14f51eba
LK
7775 if (json_paths) {
7776 json_path = json_object_new_object();
7777 json_overlay = json_object_new_object();
7778 json_nexthop = json_object_new_object();
7779 }
7780
d62a17ae 7781 /* short status lead text */
9b6d8fcf 7782 route_vty_short_status_out(vty, path, json_path);
856ca177 7783
d62a17ae 7784 /* print prefix and mask */
7785 if (!display)
14f51eba 7786 route_vty_out_route(p, vty, json_path);
d62a17ae 7787 else
7788 vty_out(vty, "%*s", 17, " ");
7789
7790 /* Print attribute */
9b6d8fcf 7791 attr = path->attr;
05864da7
DS
7792 char buf1[BUFSIZ];
7793 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 7794
05864da7
DS
7795 switch (af) {
7796 case AF_INET:
7797 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
7798 if (!json_path) {
7799 vty_out(vty, "%-16s", buf);
7800 } else {
7801 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 7802
05864da7 7803 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 7804
05864da7
DS
7805 json_object_object_add(json_path, "nexthop",
7806 json_nexthop);
7807 }
7808 break;
7809 case AF_INET6:
7810 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
7811 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
7812 if (!json_path) {
7813 vty_out(vty, "%s(%s)", buf, buf1);
7814 } else {
7815 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 7816
05864da7
DS
7817 json_object_string_add(json_nexthop, "ipv6LinkLocal",
7818 buf1);
14f51eba 7819
05864da7 7820 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 7821
05864da7
DS
7822 json_object_object_add(json_path, "nexthop",
7823 json_nexthop);
7824 }
7825 break;
7826 default:
7827 if (!json_path) {
7828 vty_out(vty, "?");
7829 } else {
7830 json_object_string_add(json_nexthop, "Error",
7831 "Unsupported address-family");
d62a17ae 7832 }
05864da7 7833 }
988258b4 7834
05864da7 7835 char *str = esi2str(&(attr->evpn_overlay.eth_s_id));
988258b4 7836
05864da7
DS
7837 if (!json_path)
7838 vty_out(vty, "%s", str);
7839 else
7840 json_object_string_add(json_overlay, "esi", str);
25b5da8d 7841
05864da7 7842 XFREE(MTYPE_TMP, str);
988258b4 7843
05864da7
DS
7844 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
7845 inet_ntop(AF_INET, &(attr->evpn_overlay.gw_ip.ipv4), buf,
7846 BUFSIZ);
7847 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
7848 inet_ntop(AF_INET6, &(attr->evpn_overlay.gw_ip.ipv6), buf,
7849 BUFSIZ);
7850 }
14f51eba 7851
05864da7
DS
7852 if (!json_path)
7853 vty_out(vty, "/%s", buf);
7854 else
7855 json_object_string_add(json_overlay, "gw", buf);
7856
7857 if (attr->ecommunity) {
7858 char *mac = NULL;
7859 struct ecommunity_val *routermac = ecommunity_lookup(
7860 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
7861 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
7862
7863 if (routermac)
7864 mac = ecom_mac2str((char *)routermac->val);
7865 if (mac) {
7866 if (!json_path) {
7867 vty_out(vty, "/%s", (char *)mac);
7868 } else {
7869 json_object_string_add(json_overlay, "rmac",
7870 mac);
988258b4 7871 }
05864da7 7872 XFREE(MTYPE_TMP, mac);
988258b4 7873 }
05864da7 7874 }
718e3744 7875
05864da7
DS
7876 if (!json_path) {
7877 vty_out(vty, "\n");
7878 } else {
7879 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 7880
05864da7 7881 json_object_array_add(json_paths, json_path);
14f51eba 7882 }
d62a17ae 7883}
718e3744 7884
d62a17ae 7885/* dampening route */
7886static void damp_route_vty_out(struct vty *vty, struct prefix *p,
a935f597 7887 struct bgp_path_info *path, int display, afi_t afi,
4b7e6066 7888 safi_t safi, bool use_json, json_object *json)
d62a17ae 7889{
7890 struct attr *attr;
7891 int len;
7892 char timebuf[BGP_UPTIME_LEN];
7893
7894 /* short status lead text */
9b6d8fcf 7895 route_vty_short_status_out(vty, path, json);
d62a17ae 7896
7897 /* print prefix and mask */
7898 if (!use_json) {
7899 if (!display)
9c92b5f7 7900 route_vty_out_route(p, vty, NULL);
d62a17ae 7901 else
7902 vty_out(vty, "%*s", 17, " ");
7903 }
7904
9b6d8fcf 7905 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 7906 len = 17 - len;
7907 if (len < 1) {
7908 if (!use_json)
7909 vty_out(vty, "\n%*s", 34, " ");
7910 } else {
7911 if (use_json)
7912 json_object_int_add(json, "peerHost", len);
7913 else
7914 vty_out(vty, "%*s", len, " ");
7915 }
7916
7917 if (use_json)
a935f597
DA
7918 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
7919 safi, use_json, json);
d62a17ae 7920 else
9b6d8fcf
DS
7921 vty_out(vty, "%s ",
7922 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
7923 BGP_UPTIME_LEN, afi, safi,
7924 use_json, json));
d62a17ae 7925
7926 /* Print attribute */
9b6d8fcf 7927 attr = path->attr;
d62a17ae 7928
05864da7
DS
7929 /* Print aspath */
7930 if (attr->aspath) {
d62a17ae 7931 if (use_json)
05864da7
DS
7932 json_object_string_add(json, "asPath",
7933 attr->aspath->str);
d62a17ae 7934 else
05864da7 7935 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 7936 }
05864da7
DS
7937
7938 /* Print origin */
7939 if (use_json)
7940 json_object_string_add(json, "origin",
7941 bgp_origin_str[attr->origin]);
7942 else
7943 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7944
d62a17ae 7945 if (!use_json)
7946 vty_out(vty, "\n");
7947}
718e3744 7948
d62a17ae 7949/* flap route */
7950static void flap_route_vty_out(struct vty *vty, struct prefix *p,
a935f597 7951 struct bgp_path_info *path, int display, afi_t afi,
4b7e6066 7952 safi_t safi, bool use_json, json_object *json)
784d3a42 7953{
d62a17ae 7954 struct attr *attr;
7955 struct bgp_damp_info *bdi;
7956 char timebuf[BGP_UPTIME_LEN];
7957 int len;
784d3a42 7958
9b6d8fcf 7959 if (!path->extra)
d62a17ae 7960 return;
784d3a42 7961
9b6d8fcf 7962 bdi = path->extra->damp_info;
784d3a42 7963
d62a17ae 7964 /* short status lead text */
9b6d8fcf 7965 route_vty_short_status_out(vty, path, json);
784d3a42 7966
d62a17ae 7967 /* print prefix and mask */
7968 if (!use_json) {
7969 if (!display)
9c92b5f7 7970 route_vty_out_route(p, vty, NULL);
d62a17ae 7971 else
7972 vty_out(vty, "%*s", 17, " ");
7973 }
784d3a42 7974
9b6d8fcf 7975 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 7976 len = 16 - len;
7977 if (len < 1) {
7978 if (!use_json)
7979 vty_out(vty, "\n%*s", 33, " ");
7980 } else {
7981 if (use_json)
7982 json_object_int_add(json, "peerHost", len);
7983 else
7984 vty_out(vty, "%*s", len, " ");
7985 }
784d3a42 7986
d62a17ae 7987 len = vty_out(vty, "%d", bdi->flap);
7988 len = 5 - len;
7989 if (len < 1) {
7990 if (!use_json)
7991 vty_out(vty, " ");
7992 } else {
7993 if (use_json)
7994 json_object_int_add(json, "bdiFlap", len);
7995 else
7996 vty_out(vty, "%*s", len, " ");
7997 }
7998
7999 if (use_json)
8000 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
8001 json);
8002 else
996c9314
LB
8003 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
8004 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 8005
9b6d8fcf
DS
8006 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
8007 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 8008 if (use_json)
9b6d8fcf 8009 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8010 BGP_UPTIME_LEN, afi, safi,
8011 use_json, json);
d62a17ae 8012 else
8013 vty_out(vty, "%s ",
9b6d8fcf 8014 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8015 BGP_UPTIME_LEN, afi,
8016 safi, use_json, json));
d62a17ae 8017 } else {
8018 if (!use_json)
8019 vty_out(vty, "%*s ", 8, " ");
8020 }
8021
8022 /* Print attribute */
9b6d8fcf 8023 attr = path->attr;
d62a17ae 8024
05864da7
DS
8025 /* Print aspath */
8026 if (attr->aspath) {
d62a17ae 8027 if (use_json)
05864da7
DS
8028 json_object_string_add(json, "asPath",
8029 attr->aspath->str);
d62a17ae 8030 else
05864da7 8031 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8032 }
05864da7
DS
8033
8034 /* Print origin */
8035 if (use_json)
8036 json_object_string_add(json, "origin",
8037 bgp_origin_str[attr->origin]);
8038 else
8039 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8040
d62a17ae 8041 if (!use_json)
8042 vty_out(vty, "\n");
8043}
8044
8045static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
8046 int *first, const char *header,
8047 json_object *json_adv_to)
8048{
8049 char buf1[INET6_ADDRSTRLEN];
8050 json_object *json_peer = NULL;
8051
8052 if (json_adv_to) {
8053 /* 'advertised-to' is a dictionary of peers we have advertised
8054 * this
8055 * prefix too. The key is the peer's IP or swpX, the value is
8056 * the
8057 * hostname if we know it and "" if not.
8058 */
8059 json_peer = json_object_new_object();
8060
8061 if (peer->hostname)
8062 json_object_string_add(json_peer, "hostname",
8063 peer->hostname);
8064
8065 if (peer->conf_if)
8066 json_object_object_add(json_adv_to, peer->conf_if,
8067 json_peer);
8068 else
8069 json_object_object_add(
8070 json_adv_to,
8071 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
8072 json_peer);
8073 } else {
8074 if (*first) {
8075 vty_out(vty, "%s", header);
8076 *first = 0;
8077 }
8078
8079 if (peer->hostname
8080 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
8081 if (peer->conf_if)
8082 vty_out(vty, " %s(%s)", peer->hostname,
8083 peer->conf_if);
8084 else
8085 vty_out(vty, " %s(%s)", peer->hostname,
8086 sockunion2str(&peer->su, buf1,
8087 SU_ADDRSTRLEN));
8088 } else {
8089 if (peer->conf_if)
8090 vty_out(vty, " %s", peer->conf_if);
8091 else
8092 vty_out(vty, " %s",
8093 sockunion2str(&peer->su, buf1,
8094 SU_ADDRSTRLEN));
8095 }
8096 }
784d3a42
PG
8097}
8098
dcc68b5e
MS
8099static void route_vty_out_tx_ids(struct vty *vty,
8100 struct bgp_addpath_info_data *d)
8101{
8102 int i;
8103
8104 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
8105 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
8106 d->addpath_tx_id[i],
8107 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
8108 }
8109}
8110
0dc8ee70
DS
8111static const char *bgp_path_selection_reason2str(
8112 enum bgp_path_selection_reason reason)
8113{
8114 switch (reason) {
8115 case bgp_path_selection_none:
8116 return "Nothing to Select";
8117 break;
8118 case bgp_path_selection_first:
8119 return "First path received";
8120 break;
8121 case bgp_path_selection_evpn_sticky_mac:
8122 return "EVPN Sticky Mac";
8123 break;
8124 case bgp_path_selection_evpn_seq:
8125 return "EVPN sequence number";
8126 break;
8127 case bgp_path_selection_evpn_lower_ip:
8128 return "EVPN lower IP";
8129 break;
8130 case bgp_path_selection_weight:
8131 return "Weight";
8132 break;
8133 case bgp_path_selection_local_pref:
8134 return "Local Pref";
8135 break;
8136 case bgp_path_selection_local_route:
8137 return "Local Route";
8138 break;
8139 case bgp_path_selection_confed_as_path:
8140 return "Confederation based AS Path";
8141 break;
8142 case bgp_path_selection_as_path:
8143 return "AS Path";
8144 break;
8145 case bgp_path_selection_origin:
8146 return "Origin";
8147 break;
8148 case bgp_path_selection_med:
8149 return "MED";
8150 break;
8151 case bgp_path_selection_peer:
8152 return "Peer Type";
8153 break;
8154 case bgp_path_selection_confed:
8155 return "Confed Peer Type";
8156 break;
8157 case bgp_path_selection_igp_metric:
8158 return "IGP Metric";
8159 break;
8160 case bgp_path_selection_older:
8161 return "Older Path";
8162 break;
8163 case bgp_path_selection_router_id:
8164 return "Router ID";
8165 break;
8166 case bgp_path_selection_cluster_length:
8167 return "Cluser length";
8168 break;
8169 case bgp_path_selection_stale:
8170 return "Path Staleness";
8171 break;
8172 case bgp_path_selection_local_configured:
8173 return "Locally configured route";
8174 break;
8175 case bgp_path_selection_neighbor_ip:
8176 return "Neighbor IP";
8177 break;
8178 case bgp_path_selection_default:
8179 return "Nothing left to compare";
8180 break;
8181 }
a74879b2 8182 return "Invalid (internal error)";
0dc8ee70
DS
8183}
8184
f08b5ca0
DS
8185void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
8186 struct bgp_node *bn, struct bgp_path_info *path,
8187 afi_t afi, safi_t safi, json_object *json_paths)
d62a17ae 8188{
8189 char buf[INET6_ADDRSTRLEN];
8190 char buf1[BUFSIZ];
d62a17ae 8191 char buf2[EVPN_ROUTE_STRLEN];
d62a17ae 8192 struct attr *attr;
8193 int sockunion_vty_out(struct vty *, union sockunion *);
8194 time_t tbuf;
8195 json_object *json_bestpath = NULL;
8196 json_object *json_cluster_list = NULL;
8197 json_object *json_cluster_list_list = NULL;
8198 json_object *json_ext_community = NULL;
8199 json_object *json_last_update = NULL;
7fd077aa 8200 json_object *json_pmsi = NULL;
d62a17ae 8201 json_object *json_nexthop_global = NULL;
8202 json_object *json_nexthop_ll = NULL;
8203 json_object *json_nexthops = NULL;
8204 json_object *json_path = NULL;
8205 json_object *json_peer = NULL;
8206 json_object *json_string = NULL;
8207 json_object *json_adv_to = NULL;
8208 int first = 0;
8209 struct listnode *node, *nnode;
8210 struct peer *peer;
8211 int addpath_capable;
8212 int has_adj;
8213 unsigned int first_as;
1defdda8 8214 bool nexthop_self =
9b6d8fcf 8215 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 8216 int i;
25b5da8d 8217 char *nexthop_fqdn = bgp_nexthop_fqdn(path->peer);
d62a17ae 8218
8219 if (json_paths) {
8220 json_path = json_object_new_object();
8221 json_peer = json_object_new_object();
8222 json_nexthop_global = json_object_new_object();
8223 }
8224
44c69747 8225 if (path->extra) {
b57ba6d2 8226 char tag_buf[30];
d62a17ae 8227
d7325ee7 8228 buf2[0] = '\0';
d62a17ae 8229 tag_buf[0] = '\0';
9b6d8fcf
DS
8230 if (path->extra && path->extra->num_labels) {
8231 bgp_evpn_label2str(path->extra->label,
8232 path->extra->num_labels, tag_buf,
a4d82a8a 8233 sizeof(tag_buf));
d62a17ae 8234 }
d7325ee7 8235 if (safi == SAFI_EVPN) {
44c69747
LK
8236 if (!json_paths) {
8237 bgp_evpn_route2str((struct prefix_evpn *)&bn->p,
8238 buf2, sizeof(buf2));
8239 vty_out(vty, " Route %s", buf2);
8240 if (tag_buf[0] != '\0')
8241 vty_out(vty, " VNI %s", tag_buf);
8242 vty_out(vty, "\n");
8243 } else {
8244 if (tag_buf[0])
8245 json_object_string_add(json_path, "VNI",
8246 tag_buf);
8247 }
d7325ee7
DD
8248 }
8249
44c69747 8250 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 8251 struct bgp_path_info *parent_ri;
d62a17ae 8252 struct bgp_node *rn, *prn;
8253
9b6d8fcf 8254 parent_ri = (struct bgp_path_info *)path->extra->parent;
d62a17ae 8255 rn = parent_ri->net;
8256 if (rn && rn->prn) {
8257 prn = rn->prn;
d7325ee7
DD
8258 prefix_rd2str((struct prefix_rd *)&prn->p,
8259 buf1, sizeof(buf1));
8260 if (is_pi_family_evpn(parent_ri)) {
8261 bgp_evpn_route2str((struct prefix_evpn *)&rn->p,
8262 buf2, sizeof(buf2));
8263 vty_out(vty, " Imported from %s:%s, VNI %s\n", buf1, buf2, tag_buf);
8264 } else
8265 vty_out(vty, " Imported from %s:%s\n", buf1, buf2);
d62a17ae 8266 }
8267 }
8268 }
d62a17ae 8269
9b6d8fcf 8270 attr = path->attr;
d62a17ae 8271
05864da7
DS
8272 /* Line1 display AS-path, Aggregator */
8273 if (attr->aspath) {
8274 if (json_paths) {
8275 if (!attr->aspath->json)
8276 aspath_str_update(attr->aspath, true);
8277 json_object_lock(attr->aspath->json);
8278 json_object_object_add(json_path, "aspath",
8279 attr->aspath->json);
8280 } else {
8281 if (attr->aspath->segments)
8282 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 8283 else
05864da7 8284 vty_out(vty, " Local");
d62a17ae 8285 }
05864da7 8286 }
d62a17ae 8287
05864da7
DS
8288 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
8289 if (json_paths)
8290 json_object_boolean_true_add(json_path, "removed");
8291 else
8292 vty_out(vty, ", (removed)");
8293 }
d62a17ae 8294
05864da7
DS
8295 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
8296 if (json_paths)
8297 json_object_boolean_true_add(json_path, "stale");
8298 else
8299 vty_out(vty, ", (stale)");
8300 }
d62a17ae 8301
05864da7
DS
8302 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
8303 if (json_paths) {
8304 json_object_int_add(json_path, "aggregatorAs",
8305 attr->aggregator_as);
8306 json_object_string_add(
8307 json_path, "aggregatorId",
8308 inet_ntoa(attr->aggregator_addr));
8309 } else {
8310 vty_out(vty, ", (aggregated by %u %s)",
8311 attr->aggregator_as,
8312 inet_ntoa(attr->aggregator_addr));
d62a17ae 8313 }
05864da7 8314 }
d62a17ae 8315
05864da7
DS
8316 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
8317 PEER_FLAG_REFLECTOR_CLIENT)) {
8318 if (json_paths)
8319 json_object_boolean_true_add(json_path,
8320 "rxedFromRrClient");
8321 else
8322 vty_out(vty, ", (Received from a RR-client)");
8323 }
d62a17ae 8324
05864da7
DS
8325 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
8326 PEER_FLAG_RSERVER_CLIENT)) {
8327 if (json_paths)
8328 json_object_boolean_true_add(json_path,
8329 "rxedFromRsClient");
8330 else
8331 vty_out(vty, ", (Received from a RS-client)");
8332 }
d62a17ae 8333
05864da7
DS
8334 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
8335 if (json_paths)
8336 json_object_boolean_true_add(json_path,
8337 "dampeningHistoryEntry");
8338 else
8339 vty_out(vty, ", (history entry)");
8340 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
8341 if (json_paths)
8342 json_object_boolean_true_add(json_path,
8343 "dampeningSuppressed");
8344 else
8345 vty_out(vty, ", (suppressed due to dampening)");
8346 }
d62a17ae 8347
05864da7
DS
8348 if (!json_paths)
8349 vty_out(vty, "\n");
d62a17ae 8350
05864da7
DS
8351 /* Line2 display Next-hop, Neighbor, Router-id */
8352 /* Display the nexthop */
8353 if ((bn->p.family == AF_INET || bn->p.family == AF_ETHERNET
8354 || bn->p.family == AF_EVPN)
8355 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
8356 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8357 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8358 || safi == SAFI_EVPN) {
d62a17ae 8359 if (json_paths)
d62a17ae 8360 json_object_string_add(
25b5da8d
DA
8361 json_nexthop_global,
8362 nexthop_fqdn ? "fqdn" : "ip",
8363 nexthop_fqdn
8364 ? nexthop_fqdn
05864da7
DS
8365 : inet_ntoa(
8366 attr->mp_nexthop_global_in));
8367 else
d62a17ae 8368 vty_out(vty, " %s",
25b5da8d
DA
8369 nexthop_fqdn
8370 ? nexthop_fqdn
05864da7
DS
8371 : inet_ntoa(
8372 attr->mp_nexthop_global_in));
d62a17ae 8373 } else {
d62a17ae 8374 if (json_paths)
05864da7
DS
8375 json_object_string_add(
8376 json_nexthop_global,
8377 nexthop_fqdn ? "fqdn" : "ip",
8378 nexthop_fqdn
8379 ? nexthop_fqdn
8380 : inet_ntoa(attr->nexthop));
d62a17ae 8381 else
05864da7
DS
8382 vty_out(vty, " %s",
8383 nexthop_fqdn
8384 ? nexthop_fqdn
8385 : inet_ntoa(attr->nexthop));
d62a17ae 8386 }
8387
05864da7
DS
8388 if (json_paths)
8389 json_object_string_add(json_nexthop_global, "afi",
8390 "ipv4");
8391 } else {
8392 if (json_paths) {
8393 json_object_string_add(
8394 json_nexthop_global,
8395 nexthop_fqdn ? "fqdn" : "ip",
8396 nexthop_fqdn
8397 ? nexthop_fqdn
8398 : inet_ntop(AF_INET6,
8399 &attr->mp_nexthop_global,
8400 buf, INET6_ADDRSTRLEN));
8401 json_object_string_add(json_nexthop_global, "afi",
8402 "ipv6");
8403 json_object_string_add(json_nexthop_global, "scope",
8404 "global");
8405 } else {
8406 vty_out(vty, " %s",
8407 nexthop_fqdn
8408 ? nexthop_fqdn
8409 : inet_ntop(AF_INET6,
8410 &attr->mp_nexthop_global,
8411 buf, INET6_ADDRSTRLEN));
d62a17ae 8412 }
05864da7 8413 }
d62a17ae 8414
05864da7
DS
8415 /* Display the IGP cost or 'inaccessible' */
8416 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
8417 if (json_paths)
8418 json_object_boolean_false_add(json_nexthop_global,
8419 "accessible");
8420 else
8421 vty_out(vty, " (inaccessible)");
8422 } else {
8423 if (path->extra && path->extra->igpmetric) {
d62a17ae 8424 if (json_paths)
05864da7
DS
8425 json_object_int_add(json_nexthop_global,
8426 "metric",
8427 path->extra->igpmetric);
d62a17ae 8428 else
05864da7
DS
8429 vty_out(vty, " (metric %u)",
8430 path->extra->igpmetric);
d62a17ae 8431 }
8432
05864da7 8433 /* IGP cost is 0, display this only for json */
d62a17ae 8434 else {
d62a17ae 8435 if (json_paths)
05864da7
DS
8436 json_object_int_add(json_nexthop_global,
8437 "metric", 0);
d62a17ae 8438 }
d62a17ae 8439
05864da7
DS
8440 if (json_paths)
8441 json_object_boolean_true_add(json_nexthop_global,
8442 "accessible");
8443 }
d62a17ae 8444
05864da7
DS
8445 /* Display peer "from" output */
8446 /* This path was originated locally */
8447 if (path->peer == bgp->peer_self) {
d62a17ae 8448
05864da7
DS
8449 if (safi == SAFI_EVPN
8450 || (bn->p.family == AF_INET
8451 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 8452 if (json_paths)
05864da7
DS
8453 json_object_string_add(json_peer, "peerId",
8454 "0.0.0.0");
d62a17ae 8455 else
05864da7
DS
8456 vty_out(vty, " from 0.0.0.0 ");
8457 } else {
d62a17ae 8458 if (json_paths)
05864da7
DS
8459 json_object_string_add(json_peer, "peerId",
8460 "::");
d62a17ae 8461 else
05864da7 8462 vty_out(vty, " from :: ");
d62a17ae 8463 }
d62a17ae 8464
05864da7
DS
8465 if (json_paths)
8466 json_object_string_add(json_peer, "routerId",
8467 inet_ntoa(bgp->router_id));
8468 else
8469 vty_out(vty, "(%s)", inet_ntoa(bgp->router_id));
8470 }
d62a17ae 8471
05864da7
DS
8472 /* We RXed this path from one of our peers */
8473 else {
8474
8475 if (json_paths) {
8476 json_object_string_add(json_peer, "peerId",
8477 sockunion2str(&path->peer->su,
8478 buf,
8479 SU_ADDRSTRLEN));
8480 json_object_string_add(json_peer, "routerId",
8481 inet_ntop(AF_INET,
8482 &path->peer->remote_id,
8483 buf1, sizeof(buf1)));
8484
8485 if (path->peer->hostname)
8486 json_object_string_add(json_peer, "hostname",
8487 path->peer->hostname);
8488
8489 if (path->peer->domainname)
8490 json_object_string_add(json_peer, "domainname",
8491 path->peer->domainname);
8492
8493 if (path->peer->conf_if)
8494 json_object_string_add(json_peer, "interface",
8495 path->peer->conf_if);
8496 } else {
8497 if (path->peer->conf_if) {
8498 if (path->peer->hostname
8499 && bgp_flag_check(path->peer->bgp,
8500 BGP_FLAG_SHOW_HOSTNAME))
8501 vty_out(vty, " from %s(%s)",
8502 path->peer->hostname,
8503 path->peer->conf_if);
d62a17ae 8504 else
05864da7 8505 vty_out(vty, " from %s",
9b6d8fcf 8506 path->peer->conf_if);
d62a17ae 8507 } else {
05864da7
DS
8508 if (path->peer->hostname
8509 && bgp_flag_check(path->peer->bgp,
8510 BGP_FLAG_SHOW_HOSTNAME))
8511 vty_out(vty, " from %s(%s)",
8512 path->peer->hostname,
8513 path->peer->host);
d62a17ae 8514 else
05864da7
DS
8515 vty_out(vty, " from %s",
8516 sockunion2str(&path->peer->su,
8517 buf,
8518 SU_ADDRSTRLEN));
d62a17ae 8519 }
d62a17ae 8520
05864da7
DS
8521 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
8522 vty_out(vty, " (%s)",
8523 inet_ntoa(attr->originator_id));
8524 else
8525 vty_out(vty, " (%s)",
8526 inet_ntop(AF_INET,
8527 &path->peer->remote_id, buf1,
8528 sizeof(buf1)));
d62a17ae 8529 }
05864da7 8530 }
9df8b37c 8531
05864da7
DS
8532 /*
8533 * Note when vrfid of nexthop is different from that of prefix
8534 */
8535 if (path->extra && path->extra->bgp_orig) {
8536 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8537
05864da7
DS
8538 if (json_paths) {
8539 const char *vn;
9df8b37c 8540
05864da7
DS
8541 if (path->extra->bgp_orig->inst_type
8542 == BGP_INSTANCE_TYPE_DEFAULT)
8543 vn = VRF_DEFAULT_NAME;
8544 else
8545 vn = path->extra->bgp_orig->name;
9df8b37c 8546
05864da7 8547 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 8548
05864da7
DS
8549 if (nexthop_vrfid == VRF_UNKNOWN) {
8550 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 8551 } else {
05864da7
DS
8552 json_object_int_add(json_path, "nhVrfId",
8553 (int)nexthop_vrfid);
9df8b37c 8554 }
05864da7
DS
8555 } else {
8556 if (nexthop_vrfid == VRF_UNKNOWN)
8557 vty_out(vty, " vrf ?");
d62a17ae 8558 else
05864da7 8559 vty_out(vty, " vrf %u", nexthop_vrfid);
9df8b37c 8560 }
05864da7 8561 }
9df8b37c 8562
05864da7
DS
8563 if (nexthop_self) {
8564 if (json_paths) {
8565 json_object_boolean_true_add(json_path,
8566 "announceNexthopSelf");
8567 } else {
8568 vty_out(vty, " announce-nh-self");
9df8b37c 8569 }
05864da7 8570 }
9df8b37c 8571
05864da7
DS
8572 if (!json_paths)
8573 vty_out(vty, "\n");
d62a17ae 8574
05864da7
DS
8575 /* display the link-local nexthop */
8576 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
8577 if (json_paths) {
8578 json_nexthop_ll = json_object_new_object();
8579 json_object_string_add(
8580 json_nexthop_ll, nexthop_fqdn ? "fqdn" : "ip",
8581 nexthop_fqdn
8582 ? nexthop_fqdn
8583 : inet_ntop(AF_INET6,
8584 &attr->mp_nexthop_local,
8585 buf, INET6_ADDRSTRLEN));
8586 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
8587 json_object_string_add(json_nexthop_ll, "scope",
8588 "link-local");
d62a17ae 8589
05864da7
DS
8590 json_object_boolean_true_add(json_nexthop_ll,
8591 "accessible");
d62a17ae 8592
05864da7 8593 if (!attr->mp_nexthop_prefer_global)
d62a17ae 8594 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
8595 "used");
8596 else
8597 json_object_boolean_true_add(
8598 json_nexthop_global, "used");
8599 } else {
8600 vty_out(vty, " (%s) %s\n",
8601 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
8602 buf, INET6_ADDRSTRLEN),
8603 attr->mp_nexthop_prefer_global
8604 ? "(prefer-global)"
8605 : "(used)");
d62a17ae 8606 }
05864da7
DS
8607 }
8608 /* If we do not have a link-local nexthop then we must flag the
8609 global as "used" */
8610 else {
8611 if (json_paths)
8612 json_object_boolean_true_add(json_nexthop_global,
8613 "used");
8614 }
d62a17ae 8615
05864da7
DS
8616 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8617 * Int/Ext/Local, Atomic, best */
8618 if (json_paths)
8619 json_object_string_add(json_path, "origin",
8620 bgp_origin_long_str[attr->origin]);
8621 else
8622 vty_out(vty, " Origin %s",
8623 bgp_origin_long_str[attr->origin]);
9df8b37c 8624
05864da7
DS
8625 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
8626 if (json_paths) {
8627 /*
8628 * Adding "metric" field to match with
8629 * corresponding CLI. "med" will be
8630 * deprecated in future.
8631 */
8632 json_object_int_add(json_path, "med", attr->med);
8633 json_object_int_add(json_path, "metric", attr->med);
8634 } else
8635 vty_out(vty, ", metric %u", attr->med);
8636 }
9df8b37c 8637
05864da7
DS
8638 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
8639 if (json_paths)
8640 json_object_int_add(json_path, "localpref",
8641 attr->local_pref);
8642 else
8643 vty_out(vty, ", localpref %u", attr->local_pref);
8644 }
9df8b37c 8645
05864da7
DS
8646 if (attr->weight != 0) {
8647 if (json_paths)
8648 json_object_int_add(json_path, "weight", attr->weight);
8649 else
8650 vty_out(vty, ", weight %u", attr->weight);
8651 }
9df8b37c 8652
05864da7
DS
8653 if (attr->tag != 0) {
8654 if (json_paths)
8655 json_object_int_add(json_path, "tag", attr->tag);
8656 else
8657 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
8658 }
9df8b37c 8659
05864da7
DS
8660 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
8661 if (json_paths)
8662 json_object_boolean_false_add(json_path, "valid");
8663 else
8664 vty_out(vty, ", invalid");
8665 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
8666 if (json_paths)
8667 json_object_boolean_true_add(json_path, "valid");
8668 else
8669 vty_out(vty, ", valid");
8670 }
9df8b37c 8671
05864da7
DS
8672 if (path->peer != bgp->peer_self) {
8673 if (path->peer->as == path->peer->local_as) {
8674 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
8675 if (json_paths)
8676 json_object_string_add(
8677 json_peer, "type",
8678 "confed-internal");
d62a17ae 8679 else
05864da7 8680 vty_out(vty, ", confed-internal");
d62a17ae 8681 } else {
05864da7
DS
8682 if (json_paths)
8683 json_object_string_add(
8684 json_peer, "type", "internal");
8685 else
8686 vty_out(vty, ", internal");
9df8b37c 8687 }
05864da7
DS
8688 } else {
8689 if (bgp_confederation_peers_check(bgp,
8690 path->peer->as)) {
8691 if (json_paths)
8692 json_object_string_add(
8693 json_peer, "type",
8694 "confed-external");
d62a17ae 8695 else
05864da7 8696 vty_out(vty, ", confed-external");
d62a17ae 8697 } else {
05864da7
DS
8698 if (json_paths)
8699 json_object_string_add(
8700 json_peer, "type", "external");
8701 else
8702 vty_out(vty, ", external");
d62a17ae 8703 }
8704 }
05864da7
DS
8705 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
8706 if (json_paths) {
8707 json_object_boolean_true_add(json_path, "aggregated");
8708 json_object_boolean_true_add(json_path, "local");
8709 } else {
8710 vty_out(vty, ", aggregated, local");
8711 }
8712 } else if (path->type != ZEBRA_ROUTE_BGP) {
8713 if (json_paths)
8714 json_object_boolean_true_add(json_path, "sourced");
8715 else
8716 vty_out(vty, ", sourced");
8717 } else {
8718 if (json_paths) {
8719 json_object_boolean_true_add(json_path, "sourced");
8720 json_object_boolean_true_add(json_path, "local");
8721 } else {
8722 vty_out(vty, ", sourced, local");
d62a17ae 8723 }
05864da7 8724 }
718e3744 8725
05864da7 8726 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 8727 if (json_paths)
05864da7
DS
8728 json_object_boolean_true_add(json_path,
8729 "atomicAggregate");
d62a17ae 8730 else
05864da7
DS
8731 vty_out(vty, ", atomic-aggregate");
8732 }
d62a17ae 8733
05864da7
DS
8734 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
8735 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
8736 && bgp_path_info_mpath_count(path))) {
8737 if (json_paths)
8738 json_object_boolean_true_add(json_path, "multipath");
8739 else
8740 vty_out(vty, ", multipath");
8741 }
50e05855 8742
05864da7
DS
8743 // Mark the bestpath(s)
8744 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
8745 first_as = aspath_get_first_as(attr->aspath);
718e3744 8746
05864da7
DS
8747 if (json_paths) {
8748 if (!json_bestpath)
8749 json_bestpath = json_object_new_object();
8750 json_object_int_add(json_bestpath, "bestpathFromAs",
8751 first_as);
8752 } else {
8753 if (first_as)
8754 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 8755 else
05864da7 8756 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 8757 }
05864da7 8758 }
718e3744 8759
05864da7
DS
8760 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
8761 if (json_paths) {
8762 if (!json_bestpath)
8763 json_bestpath = json_object_new_object();
8764 json_object_boolean_true_add(json_bestpath, "overall");
8765 json_object_string_add(
8766 json_bestpath, "selectionReason",
8767 bgp_path_selection_reason2str(bn->reason));
8768 } else {
8769 vty_out(vty, ", best");
8770 vty_out(vty, " (%s)",
8771 bgp_path_selection_reason2str(bn->reason));
d62a17ae 8772 }
05864da7 8773 }
718e3744 8774
05864da7
DS
8775 if (json_bestpath)
8776 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 8777
05864da7
DS
8778 if (!json_paths)
8779 vty_out(vty, "\n");
8780
8781 /* Line 4 display Community */
8782 if (attr->community) {
8783 if (json_paths) {
8784 if (!attr->community->json)
8785 community_str(attr->community, true);
8786 json_object_lock(attr->community->json);
8787 json_object_object_add(json_path, "community",
8788 attr->community->json);
8789 } else {
8790 vty_out(vty, " Community: %s\n",
8791 attr->community->str);
d62a17ae 8792 }
05864da7 8793 }
718e3744 8794
05864da7
DS
8795 /* Line 5 display Extended-community */
8796 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8797 if (json_paths) {
8798 json_ext_community = json_object_new_object();
8799 json_object_string_add(json_ext_community, "string",
8800 attr->ecommunity->str);
8801 json_object_object_add(json_path, "extendedCommunity",
8802 json_ext_community);
d62a17ae 8803 } else {
05864da7
DS
8804 vty_out(vty, " Extended Community: %s\n",
8805 attr->ecommunity->str);
d62a17ae 8806 }
05864da7 8807 }
718e3744 8808
05864da7
DS
8809 /* Line 6 display Large community */
8810 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
8811 if (json_paths) {
8812 if (!attr->lcommunity->json)
8813 lcommunity_str(attr->lcommunity, true);
8814 json_object_lock(attr->lcommunity->json);
8815 json_object_object_add(json_path, "largeCommunity",
8816 attr->lcommunity->json);
8817 } else {
8818 vty_out(vty, " Large Community: %s\n",
8819 attr->lcommunity->str);
d62a17ae 8820 }
05864da7 8821 }
718e3744 8822
05864da7
DS
8823 /* Line 7 display Originator, Cluster-id */
8824 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
8825 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
8826 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 8827 if (json_paths)
05864da7
DS
8828 json_object_string_add(
8829 json_path, "originatorId",
8830 inet_ntoa(attr->originator_id));
d62a17ae 8831 else
05864da7
DS
8832 vty_out(vty, " Originator: %s",
8833 inet_ntoa(attr->originator_id));
d62a17ae 8834 }
856ca177 8835
05864da7
DS
8836 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
8837 int i;
d62a17ae 8838
8839 if (json_paths) {
05864da7
DS
8840 json_cluster_list = json_object_new_object();
8841 json_cluster_list_list =
8842 json_object_new_array();
8843
8844 for (i = 0; i < attr->cluster->length / 4;
8845 i++) {
8846 json_string = json_object_new_string(
8847 inet_ntoa(attr->cluster
8848 ->list[i]));
8849 json_object_array_add(
8850 json_cluster_list_list,
8851 json_string);
8852 }
718e3744 8853
05864da7
DS
8854 /*
8855 * struct cluster_list does not have
8856 * "str" variable like aspath and community
8857 * do. Add this someday if someone asks
8858 * for it.
8859 * json_object_string_add(json_cluster_list,
8860 * "string", attr->cluster->str);
8861 */
8862 json_object_object_add(json_cluster_list,
8863 "list",
8864 json_cluster_list_list);
8865 json_object_object_add(json_path, "clusterList",
8866 json_cluster_list);
0dc8ee70 8867 } else {
05864da7
DS
8868 vty_out(vty, ", Cluster list: ");
8869
8870 for (i = 0; i < attr->cluster->length / 4;
8871 i++) {
8872 vty_out(vty, "%s ",
8873 inet_ntoa(attr->cluster
8874 ->list[i]));
8875 }
0dc8ee70 8876 }
d62a17ae 8877 }
718e3744 8878
d62a17ae 8879 if (!json_paths)
8880 vty_out(vty, "\n");
05864da7 8881 }
d62a17ae 8882
05864da7 8883 if (path->extra && path->extra->damp_info)
a935f597 8884 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 8885
05864da7
DS
8886 /* Remote Label */
8887 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
8888 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
8889 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 8890
05864da7
DS
8891 if (json_paths)
8892 json_object_int_add(json_path, "remoteLabel", label);
8893 else
8894 vty_out(vty, " Remote label: %d\n", label);
8895 }
d62a17ae 8896
05864da7
DS
8897 /* Label Index */
8898 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
8899 if (json_paths)
8900 json_object_int_add(json_path, "labelIndex",
8901 attr->label_index);
8902 else
8903 vty_out(vty, " Label Index: %d\n",
8904 attr->label_index);
8905 }
d62a17ae 8906
05864da7
DS
8907 /* Line 8 display Addpath IDs */
8908 if (path->addpath_rx_id
8909 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
8910 if (json_paths) {
8911 json_object_int_add(json_path, "addpathRxId",
8912 path->addpath_rx_id);
d62a17ae 8913
05864da7
DS
8914 /* Keep backwards compatibility with the old API
8915 * by putting TX All's ID in the old field
8916 */
8917 json_object_int_add(
8918 json_path, "addpathTxId",
8919 path->tx_addpath
8920 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 8921
05864da7
DS
8922 /* ... but create a specific field for each
8923 * strategy
8924 */
8925 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
8926 json_object_int_add(
8927 json_path,
8928 bgp_addpath_names(i)->id_json_name,
8929 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 8930 }
05864da7
DS
8931 } else {
8932 vty_out(vty, " AddPath ID: RX %u, ",
8933 path->addpath_rx_id);
d62a17ae 8934
05864da7 8935 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 8936 }
05864da7 8937 }
520d5d76 8938
05864da7
DS
8939 /* If we used addpath to TX a non-bestpath we need to display
8940 * "Advertised to" on a path-by-path basis
8941 */
8942 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
8943 first = 1;
dcc68b5e 8944
05864da7
DS
8945 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
8946 addpath_capable =
8947 bgp_addpath_encode_tx(peer, afi, safi);
8948 has_adj = bgp_adj_out_lookup(
8949 peer, path->net,
8950 bgp_addpath_id_for_peer(peer, afi, safi,
8951 &path->tx_addpath));
8952
8953 if ((addpath_capable && has_adj)
8954 || (!addpath_capable && has_adj
8955 && CHECK_FLAG(path->flags,
8956 BGP_PATH_SELECTED))) {
8957 if (json_path && !json_adv_to)
8958 json_adv_to = json_object_new_object();
dcc68b5e 8959
05864da7
DS
8960 route_vty_out_advertised_to(
8961 vty, peer, &first,
8962 " Advertised to:", json_adv_to);
d62a17ae 8963 }
8964 }
718e3744 8965
05864da7
DS
8966 if (json_path) {
8967 if (json_adv_to) {
8968 json_object_object_add(
8969 json_path, "advertisedTo", json_adv_to);
d62a17ae 8970 }
05864da7
DS
8971 } else {
8972 if (!first) {
8973 vty_out(vty, "\n");
d62a17ae 8974 }
8975 }
05864da7 8976 }
b05a1c8b 8977
05864da7
DS
8978 /* Line 9 display Uptime */
8979 tbuf = time(NULL) - (bgp_clock() - path->uptime);
8980 if (json_paths) {
8981 json_last_update = json_object_new_object();
8982 json_object_int_add(json_last_update, "epoch", tbuf);
8983 json_object_string_add(json_last_update, "string",
8984 ctime(&tbuf));
8985 json_object_object_add(json_path, "lastUpdate",
8986 json_last_update);
8987 } else
8988 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 8989
05864da7
DS
8990 /* Line 10 display PMSI tunnel attribute, if present */
8991 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
8992 const char *str =
8993 lookup_msg(bgp_pmsi_tnltype_str, attr->pmsi_tnl_type,
8994 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 8995
05864da7
DS
8996 if (json_paths) {
8997 json_pmsi = json_object_new_object();
8998 json_object_string_add(json_pmsi, "tunnelType", str);
8999 json_object_int_add(json_pmsi, "label",
9000 label2vni(&attr->label));
9001 json_object_object_add(json_path, "pmsi", json_pmsi);
9002 } else
9003 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
9004 str, label2vni(&attr->label));
d62a17ae 9005 }
f1aa5d8a 9006
d62a17ae 9007 /* We've constructed the json object for this path, add it to the json
9008 * array of paths
9009 */
9010 if (json_paths) {
9011 if (json_nexthop_global || json_nexthop_ll) {
9012 json_nexthops = json_object_new_array();
f1aa5d8a 9013
d62a17ae 9014 if (json_nexthop_global)
9015 json_object_array_add(json_nexthops,
9016 json_nexthop_global);
f1aa5d8a 9017
d62a17ae 9018 if (json_nexthop_ll)
9019 json_object_array_add(json_nexthops,
9020 json_nexthop_ll);
f1aa5d8a 9021
d62a17ae 9022 json_object_object_add(json_path, "nexthops",
9023 json_nexthops);
9024 }
9025
9026 json_object_object_add(json_path, "peer", json_peer);
9027 json_object_array_add(json_paths, json_path);
05864da7 9028 }
b366b518
BB
9029}
9030
96ade3ed 9031#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
9032#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9033#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 9034
d62a17ae 9035static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
9036 const char *prefix_list_str, afi_t afi,
9037 safi_t safi, enum bgp_show_type type);
9038static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
9039 const char *filter, afi_t afi, safi_t safi,
9040 enum bgp_show_type type);
9041static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
9042 const char *rmap_str, afi_t afi, safi_t safi,
9043 enum bgp_show_type type);
9044static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
9045 const char *com, int exact, afi_t afi,
9046 safi_t safi);
9047static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
9048 const char *prefix, afi_t afi, safi_t safi,
9049 enum bgp_show_type type);
a4d82a8a
PZ
9050static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
9051 afi_t afi, safi_t safi, enum bgp_show_type type);
7f323236
DW
9052static int bgp_show_community(struct vty *vty, struct bgp *bgp,
9053 const char *comstr, int exact, afi_t afi,
9f049418 9054 safi_t safi, bool use_json);
d62a17ae 9055
1ae44dfc
LB
9056
9057static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 9058 struct bgp_table *table, enum bgp_show_type type,
9f049418 9059 void *output_arg, bool use_json, char *rd,
a4d82a8a
PZ
9060 int is_last, unsigned long *output_cum,
9061 unsigned long *total_cum,
9386b588 9062 unsigned long *json_header_depth)
d62a17ae 9063{
40381db7 9064 struct bgp_path_info *pi;
d62a17ae 9065 struct bgp_node *rn;
9066 int header = 1;
9067 int display;
1ae44dfc
LB
9068 unsigned long output_count = 0;
9069 unsigned long total_count = 0;
d62a17ae 9070 struct prefix *p;
d62a17ae 9071 char buf2[BUFSIZ];
9072 json_object *json_paths = NULL;
9073 int first = 1;
9074
1ae44dfc
LB
9075 if (output_cum && *output_cum != 0)
9076 header = 0;
9077
9386b588 9078 if (use_json && !*json_header_depth) {
d62a17ae 9079 vty_out(vty,
66f80d74 9080 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
01eced22
AD
9081 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9082 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 9083 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b
DS
9084 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
9085 ? VRF_DEFAULT_NAME
9086 : bgp->name,
01eced22
AD
9087 table->version, inet_ntoa(bgp->router_id),
9088 bgp->default_local_pref, bgp->as);
9386b588
PZ
9089 *json_header_depth = 2;
9090 if (rd) {
445c2480 9091 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
9092 ++*json_header_depth;
9093 }
d62a17ae 9094 }
718e3744 9095
445c2480
DS
9096 if (use_json && rd) {
9097 vty_out(vty, " \"%s\" : { ", rd);
9098 }
9099
d62a17ae 9100 /* Start processing of routes. */
98ce9a06 9101 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685
DS
9102 pi = bgp_node_get_bgp_path_info(rn);
9103 if (pi == NULL)
98ce9a06 9104 continue;
d62a17ae 9105
98ce9a06 9106 display = 0;
98ce9a06
DS
9107 if (use_json)
9108 json_paths = json_object_new_array();
9109 else
9110 json_paths = NULL;
d62a17ae 9111
6f94b685 9112 for (; pi; pi = pi->next) {
98ce9a06
DS
9113 total_count++;
9114 if (type == bgp_show_type_flap_statistics
9115 || type == bgp_show_type_flap_neighbor
9116 || type == bgp_show_type_dampend_paths
9117 || type == bgp_show_type_damp_neighbor) {
40381db7 9118 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
9119 continue;
9120 }
9121 if (type == bgp_show_type_regexp) {
9122 regex_t *regex = output_arg;
d62a17ae 9123
40381db7 9124 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
9125 == REG_NOMATCH)
9126 continue;
9127 }
9128 if (type == bgp_show_type_prefix_list) {
9129 struct prefix_list *plist = output_arg;
d62a17ae 9130
98ce9a06
DS
9131 if (prefix_list_apply(plist, &rn->p)
9132 != PREFIX_PERMIT)
9133 continue;
9134 }
9135 if (type == bgp_show_type_filter_list) {
9136 struct as_list *as_list = output_arg;
d62a17ae 9137
40381db7 9138 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
9139 != AS_FILTER_PERMIT)
9140 continue;
9141 }
9142 if (type == bgp_show_type_route_map) {
9143 struct route_map *rmap = output_arg;
9b6d8fcf 9144 struct bgp_path_info path;
98ce9a06 9145 struct attr dummy_attr;
b68885f9 9146 route_map_result_t ret;
d62a17ae 9147
40381db7 9148 bgp_attr_dup(&dummy_attr, pi->attr);
d62a17ae 9149
40381db7 9150 path.peer = pi->peer;
9b6d8fcf 9151 path.attr = &dummy_attr;
d62a17ae 9152
a4d82a8a 9153 ret = route_map_apply(rmap, &rn->p, RMAP_BGP,
9b6d8fcf 9154 &path);
98ce9a06
DS
9155 if (ret == RMAP_DENYMATCH)
9156 continue;
9157 }
9158 if (type == bgp_show_type_neighbor
9159 || type == bgp_show_type_flap_neighbor
9160 || type == bgp_show_type_damp_neighbor) {
9161 union sockunion *su = output_arg;
9162
40381db7
DS
9163 if (pi->peer == NULL
9164 || pi->peer->su_remote == NULL
9165 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
9166 continue;
9167 }
9168 if (type == bgp_show_type_cidr_only) {
d7c0a89a 9169 uint32_t destination;
d62a17ae 9170
98ce9a06
DS
9171 destination = ntohl(rn->p.u.prefix4.s_addr);
9172 if (IN_CLASSC(destination)
9173 && rn->p.prefixlen == 24)
9174 continue;
9175 if (IN_CLASSB(destination)
9176 && rn->p.prefixlen == 16)
9177 continue;
9178 if (IN_CLASSA(destination)
9179 && rn->p.prefixlen == 8)
9180 continue;
9181 }
9182 if (type == bgp_show_type_prefix_longer) {
f7813c7c 9183 p = output_arg;
98ce9a06
DS
9184 if (!prefix_match(p, &rn->p))
9185 continue;
9186 }
9187 if (type == bgp_show_type_community_all) {
40381db7 9188 if (!pi->attr->community)
98ce9a06
DS
9189 continue;
9190 }
9191 if (type == bgp_show_type_community) {
9192 struct community *com = output_arg;
d62a17ae 9193
40381db7
DS
9194 if (!pi->attr->community
9195 || !community_match(pi->attr->community,
98ce9a06
DS
9196 com))
9197 continue;
9198 }
9199 if (type == bgp_show_type_community_exact) {
9200 struct community *com = output_arg;
d62a17ae 9201
40381db7
DS
9202 if (!pi->attr->community
9203 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
9204 continue;
9205 }
9206 if (type == bgp_show_type_community_list) {
9207 struct community_list *list = output_arg;
d62a17ae 9208
40381db7 9209 if (!community_list_match(pi->attr->community,
a4d82a8a 9210 list))
98ce9a06
DS
9211 continue;
9212 }
a4d82a8a 9213 if (type == bgp_show_type_community_list_exact) {
98ce9a06 9214 struct community_list *list = output_arg;
d62a17ae 9215
98ce9a06 9216 if (!community_list_exact_match(
40381db7 9217 pi->attr->community, list))
98ce9a06
DS
9218 continue;
9219 }
9220 if (type == bgp_show_type_lcommunity) {
9221 struct lcommunity *lcom = output_arg;
d62a17ae 9222
40381db7
DS
9223 if (!pi->attr->lcommunity
9224 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
9225 lcom))
9226 continue;
9227 }
36a206db 9228
9229 if (type == bgp_show_type_lcommunity_exact) {
9230 struct lcommunity *lcom = output_arg;
9231
9232 if (!pi->attr->lcommunity
9233 || !lcommunity_cmp(pi->attr->lcommunity,
9234 lcom))
9235 continue;
9236 }
98ce9a06
DS
9237 if (type == bgp_show_type_lcommunity_list) {
9238 struct community_list *list = output_arg;
d62a17ae 9239
40381db7 9240 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 9241 list))
98ce9a06
DS
9242 continue;
9243 }
36a206db 9244 if (type
9245 == bgp_show_type_lcommunity_list_exact) {
9246 struct community_list *list = output_arg;
9247
9248 if (!lcommunity_list_exact_match(
9249 pi->attr->lcommunity, list))
9250 continue;
9251 }
98ce9a06 9252 if (type == bgp_show_type_lcommunity_all) {
40381db7 9253 if (!pi->attr->lcommunity)
98ce9a06
DS
9254 continue;
9255 }
9256 if (type == bgp_show_type_dampend_paths
9257 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
9258 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
9259 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
9260 continue;
9261 }
9262
9263 if (!use_json && header) {
996c9314 9264 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 9265 ", local router ID is %s, vrf id ",
98ce9a06
DS
9266 table->version,
9267 inet_ntoa(bgp->router_id));
9df8b37c
PZ
9268 if (bgp->vrf_id == VRF_UNKNOWN)
9269 vty_out(vty, "%s", VRFID_NONE_STR);
9270 else
9271 vty_out(vty, "%u", bgp->vrf_id);
9272 vty_out(vty, "\n");
01eced22
AD
9273 vty_out(vty, "Default local pref %u, ",
9274 bgp->default_local_pref);
9275 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 9276 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 9277 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 9278 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 9279 if (type == bgp_show_type_dampend_paths
9280 || type == bgp_show_type_damp_neighbor)
98ce9a06 9281 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
9282 else if (type == bgp_show_type_flap_statistics
9283 || type == bgp_show_type_flap_neighbor)
98ce9a06 9284 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 9285 else
98ce9a06
DS
9286 vty_out(vty, BGP_SHOW_HEADER);
9287 header = 0;
d62a17ae 9288 }
98ce9a06
DS
9289 if (rd != NULL && !display && !output_count) {
9290 if (!use_json)
9291 vty_out(vty,
9292 "Route Distinguisher: %s\n",
9293 rd);
d62a17ae 9294 }
98ce9a06
DS
9295 if (type == bgp_show_type_dampend_paths
9296 || type == bgp_show_type_damp_neighbor)
a935f597 9297 damp_route_vty_out(vty, &rn->p, pi, display, AFI_IP,
a4d82a8a 9298 safi, use_json, json_paths);
98ce9a06
DS
9299 else if (type == bgp_show_type_flap_statistics
9300 || type == bgp_show_type_flap_neighbor)
a935f597 9301 flap_route_vty_out(vty, &rn->p, pi, display, AFI_IP,
a4d82a8a 9302 safi, use_json, json_paths);
98ce9a06 9303 else
40381db7 9304 route_vty_out(vty, &rn->p, pi, display, safi,
a4d82a8a 9305 json_paths);
98ce9a06 9306 display++;
d62a17ae 9307 }
9308
98ce9a06
DS
9309 if (display) {
9310 output_count++;
9311 if (!use_json)
9312 continue;
9313
9314 p = &rn->p;
625d2931
PG
9315 /* encode prefix */
9316 if (p->family == AF_FLOWSPEC) {
9317 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
9318
9319 bgp_fs_nlri_get_string((unsigned char *)
9320 p->u.prefix_flowspec.ptr,
9321 p->u.prefix_flowspec
9322 .prefixlen,
9323 retstr,
9324 NLRI_STRING_FORMAT_MIN,
9325 NULL);
9326 if (first)
9327 vty_out(vty, "\"%s/%d\": ",
9328 retstr,
9329 p->u.prefix_flowspec.prefixlen);
9330 else
9331 vty_out(vty, ",\"%s/%d\": ",
9332 retstr,
9333 p->u.prefix_flowspec.prefixlen);
9334 } else {
9335 prefix2str(p, buf2, sizeof(buf2));
9336 if (first)
9337 vty_out(vty, "\"%s\": ", buf2);
9338 else
9339 vty_out(vty, ",\"%s\": ", buf2);
9340 }
98ce9a06 9341 vty_out(vty, "%s",
23b2a7ef 9342 json_object_to_json_string(json_paths));
98ce9a06 9343 json_object_free(json_paths);
449feb8e 9344 json_paths = NULL;
98ce9a06
DS
9345 first = 0;
9346 }
9347 }
9348
1ae44dfc
LB
9349 if (output_cum) {
9350 output_count += *output_cum;
9351 *output_cum = output_count;
9352 }
9353 if (total_cum) {
9354 total_count += *total_cum;
9355 *total_cum = total_count;
9356 }
d62a17ae 9357 if (use_json) {
9386b588 9358 if (rd) {
a4d82a8a 9359 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
9360 }
9361 if (is_last) {
a4d82a8a
PZ
9362 unsigned long i;
9363 for (i = 0; i < *json_header_depth; ++i)
9364 vty_out(vty, " } ");
faf6559a 9365 vty_out(vty, "\n");
9386b588 9366 }
d62a17ae 9367 } else {
1ae44dfc
LB
9368 if (is_last) {
9369 /* No route is displayed */
9370 if (output_count == 0) {
9371 if (type == bgp_show_type_normal)
9372 vty_out(vty,
9373 "No BGP prefixes displayed, %ld exist\n",
9374 total_count);
9375 } else
d62a17ae 9376 vty_out(vty,
1ae44dfc
LB
9377 "\nDisplayed %ld routes and %ld total paths\n",
9378 output_count, total_count);
9379 }
d62a17ae 9380 }
718e3744 9381
d62a17ae 9382 return CMD_SUCCESS;
718e3744 9383}
9384
1ae44dfc
LB
9385int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
9386 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 9387 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc
LB
9388{
9389 struct bgp_node *rn, *next;
9390 unsigned long output_cum = 0;
9391 unsigned long total_cum = 0;
9386b588 9392 unsigned long json_header_depth = 0;
67009e22 9393 struct bgp_table *itable;
0136788c
LB
9394 bool show_msg;
9395
9396 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc
LB
9397
9398 for (rn = bgp_table_top(table); rn; rn = next) {
9399 next = bgp_route_next(rn);
9400 if (prd_match && memcmp(rn->p.u.val, prd_match->val, 8) != 0)
9401 continue;
67009e22
DS
9402
9403 itable = bgp_node_get_bgp_table_info(rn);
9404 if (itable != NULL) {
1ae44dfc 9405 struct prefix_rd prd;
06b9f471 9406 char rd[RD_ADDRSTRLEN];
1ae44dfc
LB
9407
9408 memcpy(&prd, &(rn->p), sizeof(struct prefix_rd));
06b9f471 9409 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22
DS
9410 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
9411 use_json, rd, next == NULL, &output_cum,
9412 &total_cum, &json_header_depth);
0136788c
LB
9413 if (next == NULL)
9414 show_msg = false;
1ae44dfc
LB
9415 }
9416 }
0136788c
LB
9417 if (show_msg) {
9418 if (output_cum == 0)
9419 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
9420 total_cum);
9421 else
9422 vty_out(vty,
9423 "\nDisplayed %ld routes and %ld total paths\n",
9424 output_cum, total_cum);
9425 }
1ae44dfc
LB
9426 return CMD_SUCCESS;
9427}
d62a17ae 9428static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
9f049418 9429 enum bgp_show_type type, void *output_arg, bool use_json)
fee0f4c6 9430{
d62a17ae 9431 struct bgp_table *table;
9386b588 9432 unsigned long json_header_depth = 0;
fee0f4c6 9433
d62a17ae 9434 if (bgp == NULL) {
9435 bgp = bgp_get_default();
9436 }
fee0f4c6 9437
d62a17ae 9438 if (bgp == NULL) {
9439 if (!use_json)
9440 vty_out(vty, "No BGP process is configured\n");
16307668
RW
9441 else
9442 vty_out(vty, "{}\n");
d62a17ae 9443 return CMD_WARNING;
9444 }
4dd6177e 9445
1ae44dfc 9446 table = bgp->rib[afi][safi];
d62a17ae 9447 /* use MPLS and ENCAP specific shows until they are merged */
9448 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
9449 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
9450 output_arg, use_json);
d62a17ae 9451 }
dba3c1d3
PG
9452
9453 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
9454 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
9455 output_arg, use_json,
9456 1, NULL, NULL);
9457 }
d62a17ae 9458 /* labeled-unicast routes live in the unicast table */
9459 else if (safi == SAFI_LABELED_UNICAST)
9460 safi = SAFI_UNICAST;
fee0f4c6 9461
1ae44dfc 9462 return bgp_show_table(vty, bgp, safi, table, type, output_arg, use_json,
9386b588 9463 NULL, 1, NULL, NULL, &json_header_depth);
fee0f4c6 9464}
9465
d62a17ae 9466static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
9f049418 9467 safi_t safi, bool use_json)
f186de26 9468{
d62a17ae 9469 struct listnode *node, *nnode;
9470 struct bgp *bgp;
9471 int is_first = 1;
9f049418 9472 bool route_output = false;
f186de26 9473
d62a17ae 9474 if (use_json)
9475 vty_out(vty, "{\n");
9f689658 9476
d62a17ae 9477 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 9478 route_output = true;
d62a17ae 9479 if (use_json) {
9480 if (!is_first)
9481 vty_out(vty, ",\n");
9482 else
9483 is_first = 0;
9484
9485 vty_out(vty, "\"%s\":",
9486 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 9487 ? VRF_DEFAULT_NAME
d62a17ae 9488 : bgp->name);
9489 } else {
9490 vty_out(vty, "\nInstance %s:\n",
9491 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 9492 ? VRF_DEFAULT_NAME
d62a17ae 9493 : bgp->name);
9494 }
9495 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
9496 use_json);
9497 }
9f689658 9498
d62a17ae 9499 if (use_json)
9500 vty_out(vty, "}\n");
9f049418
DS
9501 else if (!route_output)
9502 vty_out(vty, "%% BGP instance not found\n");
f186de26 9503}
9504
718e3744 9505/* Header of detailed BGP route information */
d62a17ae 9506void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9507 struct bgp_node *rn, struct prefix_rd *prd,
9508 afi_t afi, safi_t safi, json_object *json)
9509{
40381db7 9510 struct bgp_path_info *pi;
d62a17ae 9511 struct prefix *p;
9512 struct peer *peer;
9513 struct listnode *node, *nnode;
06b9f471 9514 char buf1[RD_ADDRSTRLEN];
d62a17ae 9515 char buf2[INET6_ADDRSTRLEN];
d62a17ae 9516 char buf3[EVPN_ROUTE_STRLEN];
0291c246 9517 char prefix_str[BUFSIZ];
d62a17ae 9518 int count = 0;
9519 int best = 0;
9520 int suppress = 0;
c5f1e1b2
C
9521 int accept_own = 0;
9522 int route_filter_translated_v4 = 0;
9523 int route_filter_v4 = 0;
9524 int route_filter_translated_v6 = 0;
9525 int route_filter_v6 = 0;
9526 int llgr_stale = 0;
9527 int no_llgr = 0;
9528 int accept_own_nexthop = 0;
9529 int blackhole = 0;
d62a17ae 9530 int no_export = 0;
9531 int no_advertise = 0;
9532 int local_as = 0;
c5f1e1b2 9533 int no_peer = 0;
d62a17ae 9534 int first = 1;
9535 int has_valid_label = 0;
9536 mpls_label_t label = 0;
9537 json_object *json_adv_to = NULL;
9bedbb1e 9538
d62a17ae 9539 p = &rn->p;
9540 has_valid_label = bgp_is_valid_label(&rn->local_label);
9541
9542 if (has_valid_label)
9543 label = label_pton(&rn->local_label);
9544
44c69747 9545 if (safi == SAFI_EVPN) {
d62a17ae 9546
44c69747 9547 if (!json) {
d62a17ae 9548 vty_out(vty, "BGP routing table entry for %s%s%s\n",
06b9f471 9549 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
44c69747 9550 : "", prd ? ":" : "",
d62a17ae 9551 bgp_evpn_route2str((struct prefix_evpn *)p,
44c69747
LK
9552 buf3, sizeof(buf3)));
9553 } else {
9554 json_object_string_add(json, "rd",
9555 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
9556 "");
9557 bgp_evpn_route2json((struct prefix_evpn *)p, json);
9558 }
9559 } else {
9560 if (!json) {
d62a17ae 9561 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
9562 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
44c69747
LK
9563 ? prefix_rd2str(prd, buf1,
9564 sizeof(buf1))
9565 : ""),
d62a17ae 9566 safi == SAFI_MPLS_VPN ? ":" : "",
9567 inet_ntop(p->family, &p->u.prefix, buf2,
44c69747 9568 INET6_ADDRSTRLEN),
d62a17ae 9569 p->prefixlen);
cd1964ff 9570
44c69747
LK
9571 } else
9572 json_object_string_add(json, "prefix",
9573 prefix2str(p, prefix_str, sizeof(prefix_str)));
9574 }
9575
9576 if (has_valid_label) {
9577 if (json)
9578 json_object_int_add(json, "localLabel", label);
9579 else
d62a17ae 9580 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
9581 }
9582
9583 if (!json)
d62a17ae 9584 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 9585 vty_out(vty, "not allocated\n");
718e3744 9586
6f94b685 9587 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
d62a17ae 9588 count++;
40381db7 9589 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 9590 best = count;
40381db7 9591 if (pi->extra && pi->extra->suppress)
d62a17ae 9592 suppress = 1;
cee9c031 9593
40381db7 9594 if (pi->attr->community == NULL)
cee9c031
QY
9595 continue;
9596
9597 no_advertise += community_include(
40381db7
DS
9598 pi->attr->community, COMMUNITY_NO_ADVERTISE);
9599 no_export += community_include(pi->attr->community,
cee9c031 9600 COMMUNITY_NO_EXPORT);
40381db7 9601 local_as += community_include(pi->attr->community,
cee9c031 9602 COMMUNITY_LOCAL_AS);
40381db7 9603 accept_own += community_include(pi->attr->community,
cee9c031
QY
9604 COMMUNITY_ACCEPT_OWN);
9605 route_filter_translated_v4 += community_include(
40381db7 9606 pi->attr->community,
cee9c031
QY
9607 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
9608 route_filter_translated_v6 += community_include(
40381db7 9609 pi->attr->community,
cee9c031
QY
9610 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
9611 route_filter_v4 += community_include(
40381db7 9612 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 9613 route_filter_v6 += community_include(
40381db7
DS
9614 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
9615 llgr_stale += community_include(pi->attr->community,
cee9c031 9616 COMMUNITY_LLGR_STALE);
40381db7 9617 no_llgr += community_include(pi->attr->community,
cee9c031
QY
9618 COMMUNITY_NO_LLGR);
9619 accept_own_nexthop +=
40381db7 9620 community_include(pi->attr->community,
cee9c031 9621 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 9622 blackhole += community_include(pi->attr->community,
cee9c031 9623 COMMUNITY_BLACKHOLE);
40381db7 9624 no_peer += community_include(pi->attr->community,
cee9c031 9625 COMMUNITY_NO_PEER);
d62a17ae 9626 }
718e3744 9627 }
718e3744 9628
d62a17ae 9629 if (!json) {
9630 vty_out(vty, "Paths: (%d available", count);
9631 if (best) {
9632 vty_out(vty, ", best #%d", best);
b84060bb
PG
9633 if (safi == SAFI_UNICAST) {
9634 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
9635 vty_out(vty, ", table %s",
9636 VRF_DEFAULT_NAME);
9637 else
9638 vty_out(vty, ", vrf %s",
9639 bgp->name);
9640 }
d62a17ae 9641 } else
9642 vty_out(vty, ", no best path");
9643
c5f1e1b2
C
9644 if (accept_own)
9645 vty_out(vty,
9646 ", accept own local route exported and imported in different VRF");
9647 else if (route_filter_translated_v4)
9648 vty_out(vty,
9649 ", mark translated RTs for VPNv4 route filtering");
9650 else if (route_filter_v4)
9651 vty_out(vty,
9652 ", attach RT as-is for VPNv4 route filtering");
9653 else if (route_filter_translated_v6)
9654 vty_out(vty,
9655 ", mark translated RTs for VPNv6 route filtering");
9656 else if (route_filter_v6)
9657 vty_out(vty,
9658 ", attach RT as-is for VPNv6 route filtering");
9659 else if (llgr_stale)
9660 vty_out(vty,
9661 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9662 else if (no_llgr)
9663 vty_out(vty,
9664 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9665 else if (accept_own_nexthop)
9666 vty_out(vty,
9667 ", accept local nexthop");
9668 else if (blackhole)
9669 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 9670 else if (no_export)
9671 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
9672 else if (no_advertise)
9673 vty_out(vty, ", not advertised to any peer");
d62a17ae 9674 else if (local_as)
9675 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
9676 else if (no_peer)
9677 vty_out(vty,
9678 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 9679
9680 if (suppress)
9681 vty_out(vty,
9682 ", Advertisements suppressed by an aggregate.");
9683 vty_out(vty, ")\n");
9684 }
718e3744 9685
d62a17ae 9686 /* If we are not using addpath then we can display Advertised to and
9687 * that will
9688 * show what peers we advertised the bestpath to. If we are using
9689 * addpath
9690 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 9691 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 9692 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9693 if (bgp_adj_out_lookup(peer, rn, 0)) {
9694 if (json && !json_adv_to)
9695 json_adv_to = json_object_new_object();
9696
9697 route_vty_out_advertised_to(
9698 vty, peer, &first,
9699 " Advertised to non peer-group peers:\n ",
9700 json_adv_to);
9701 }
9702 }
9703
9704 if (json) {
9705 if (json_adv_to) {
9706 json_object_object_add(json, "advertisedTo",
9707 json_adv_to);
9708 }
9709 } else {
9710 if (first)
9711 vty_out(vty, " Not advertised to any peer");
9712 vty_out(vty, "\n");
9713 }
9714 }
718e3744 9715}
9716
44c69747
LK
9717static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9718 struct bgp_node *bgp_node, struct vty *vty,
9719 struct bgp *bgp, afi_t afi,
9720 safi_t safi, json_object *json,
9721 enum bgp_path_type pathtype, int *display)
9722{
9723 struct bgp_path_info *pi;
9724 int header = 1;
9725 char rdbuf[RD_ADDRSTRLEN];
9726 json_object *json_header = NULL;
9727 json_object *json_paths = NULL;
9728
9729 for (pi = bgp_node_get_bgp_path_info(bgp_node); pi;
9730 pi = pi->next) {
9731
9732 if (json && !json_paths) {
9733 /* Instantiate json_paths only if path is valid */
9734 json_paths = json_object_new_array();
9735 if (pfx_rd) {
9736 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
9737 json_header = json_object_new_object();
9738 } else
9739 json_header = json;
9740 }
9741
9742 if (header) {
9743 route_vty_out_detail_header(
9744 vty, bgp, bgp_node, pfx_rd,
9745 AFI_IP, safi, json_header);
9746 header = 0;
9747 }
9748 (*display)++;
9749
9750 if (pathtype == BGP_PATH_SHOW_ALL
9751 || (pathtype == BGP_PATH_SHOW_BESTPATH
9752 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
9753 || (pathtype == BGP_PATH_SHOW_MULTIPATH
9754 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
9755 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
9756 route_vty_out_detail(vty, bgp, bgp_node,
9757 pi, AFI_IP, safi,
9758 json_paths);
9759 }
9760
9761 if (json && json_paths) {
9762 json_object_object_add(json_header, "paths", json_paths);
9763
9764 if (pfx_rd)
9765 json_object_object_add(json, rdbuf, json_header);
9766 }
9767}
9768
718e3744 9769/* Display specified route of BGP table. */
d62a17ae 9770static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
9771 struct bgp_table *rib, const char *ip_str,
9772 afi_t afi, safi_t safi,
9773 struct prefix_rd *prd, int prefix_check,
9f049418 9774 enum bgp_path_type pathtype, bool use_json)
d62a17ae 9775{
9776 int ret;
d62a17ae 9777 int display = 0;
9778 struct prefix match;
9779 struct bgp_node *rn;
9780 struct bgp_node *rm;
d62a17ae 9781 struct bgp_table *table;
9782 json_object *json = NULL;
9783 json_object *json_paths = NULL;
9784
9785 /* Check IP address argument. */
9786 ret = str2prefix(ip_str, &match);
9787 if (!ret) {
9788 vty_out(vty, "address is malformed\n");
9789 return CMD_WARNING;
9790 }
718e3744 9791
d62a17ae 9792 match.family = afi2family(afi);
b05a1c8b 9793
44c69747 9794 if (use_json)
d62a17ae 9795 json = json_object_new_object();
718e3744 9796
44c69747 9797 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
d62a17ae 9798 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
9799 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
9800 continue;
67009e22
DS
9801 table = bgp_node_get_bgp_table_info(rn);
9802 if (!table)
ea47320b 9803 continue;
d62a17ae 9804
ea47320b
DL
9805 if ((rm = bgp_node_match(table, &match)) == NULL)
9806 continue;
d62a17ae 9807
ea47320b
DL
9808 if (prefix_check
9809 && rm->p.prefixlen != match.prefixlen) {
9810 bgp_unlock_node(rm);
9811 continue;
9812 }
d62a17ae 9813
44c69747
LK
9814 bgp_show_path_info((struct prefix_rd *)&rn->p, rm,
9815 vty, bgp, afi, safi, json,
9816 pathtype, &display);
9817
9818 bgp_unlock_node(rm);
9819 }
9820 } else if (safi == SAFI_EVPN) {
9821 struct bgp_node *longest_pfx;
9822 bool is_exact_pfxlen_match = FALSE;
9823
9824 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
9825 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
9826 continue;
9827 table = bgp_node_get_bgp_table_info(rn);
9828 if (!table)
9829 continue;
9830
9831 longest_pfx = NULL;
9832 is_exact_pfxlen_match = FALSE;
9833 /*
9834 * Search through all the prefixes for a match. The
9835 * pfx's are enumerated in ascending order of pfxlens.
9836 * So, the last pfx match is the longest match. Set
9837 * is_exact_pfxlen_match when we get exact pfxlen match
9838 */
9839 for (rm = bgp_table_top(table); rm;
9840 rm = bgp_route_next(rm)) {
9841 /*
9842 * Get prefixlen of the ip-prefix within type5
9843 * evpn route
9844 */
9845 if (evpn_type5_prefix_match(&rm->p,
9846 &match) && rm->info) {
9847 longest_pfx = rm;
9848 int type5_pfxlen =
9849 bgp_evpn_get_type5_prefixlen(&rm->p);
9850 if (type5_pfxlen == match.prefixlen) {
9851 is_exact_pfxlen_match = TRUE;
9852 bgp_unlock_node(rm);
9853 break;
9854 }
d62a17ae 9855 }
9856 }
ea47320b 9857
44c69747
LK
9858 if (!longest_pfx)
9859 continue;
9860
9861 if (prefix_check && !is_exact_pfxlen_match)
9862 continue;
9863
9864 rm = longest_pfx;
9865 bgp_lock_node(rm);
9866
9867 bgp_show_path_info((struct prefix_rd *)&rn->p, rm,
9868 vty, bgp, afi, safi, json,
9869 pathtype, &display);
9870
ea47320b 9871 bgp_unlock_node(rm);
d62a17ae 9872 }
98a9dbc7 9873 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
9874 if (use_json)
9875 json_paths = json_object_new_array();
9876
63a0b7a9
PG
9877 display = bgp_flowspec_display_match_per_ip(afi, rib,
9878 &match, prefix_check,
9879 vty,
9880 use_json,
9881 json_paths);
44c69747
LK
9882 if (use_json && display)
9883 json_object_object_add(json, "paths", json_paths);
d62a17ae 9884 } else {
d62a17ae 9885 if ((rn = bgp_node_match(rib, &match)) != NULL) {
9886 if (!prefix_check
9887 || rn->p.prefixlen == match.prefixlen) {
44c69747
LK
9888 bgp_show_path_info(NULL, rn, vty, bgp, afi,
9889 safi, json,
9890 pathtype, &display);
d62a17ae 9891 }
9892
9893 bgp_unlock_node(rn);
9894 }
9895 }
e5eee9af 9896
d62a17ae 9897 if (use_json) {
996c9314 9898 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
9899 json, JSON_C_TO_STRING_PRETTY |
9900 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 9901 json_object_free(json);
9902 } else {
9903 if (!display) {
9904 vty_out(vty, "%% Network not in table\n");
9905 return CMD_WARNING;
9906 }
9907 }
b05a1c8b 9908
d62a17ae 9909 return CMD_SUCCESS;
718e3744 9910}
9911
fee0f4c6 9912/* Display specified route of Main RIB */
d62a17ae 9913static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
9914 afi_t afi, safi_t safi, struct prefix_rd *prd,
9915 int prefix_check, enum bgp_path_type pathtype,
9f049418 9916 bool use_json)
d62a17ae 9917{
9b86009a 9918 if (!bgp) {
d62a17ae 9919 bgp = bgp_get_default();
9b86009a
RW
9920 if (!bgp) {
9921 if (!use_json)
9922 vty_out(vty, "No BGP process is configured\n");
16307668
RW
9923 else
9924 vty_out(vty, "{}\n");
9b86009a
RW
9925 return CMD_WARNING;
9926 }
9927 }
d62a17ae 9928
9929 /* labeled-unicast routes live in the unicast table */
9930 if (safi == SAFI_LABELED_UNICAST)
9931 safi = SAFI_UNICAST;
9932
9933 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
9934 afi, safi, prd, prefix_check, pathtype,
9935 use_json);
9936}
9937
9938static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 9939 struct cmd_token **argv, bool exact, afi_t afi,
9940 safi_t safi, bool uj)
d62a17ae 9941{
9942 struct lcommunity *lcom;
9943 struct buffer *b;
9944 int i;
9945 char *str;
9946 int first = 0;
9947
9948 b = buffer_new(1024);
9949 for (i = 0; i < argc; i++) {
9950 if (first)
9951 buffer_putc(b, ' ');
9952 else {
9953 if (strmatch(argv[i]->text, "AA:BB:CC")) {
9954 first = 1;
9955 buffer_putstr(b, argv[i]->arg);
9956 }
9957 }
9958 }
9959 buffer_putc(b, '\0');
57d187bc 9960
d62a17ae 9961 str = buffer_getstr(b);
9962 buffer_free(b);
57d187bc 9963
d62a17ae 9964 lcom = lcommunity_str2com(str);
9965 XFREE(MTYPE_TMP, str);
9966 if (!lcom) {
9967 vty_out(vty, "%% Large-community malformed\n");
9968 return CMD_WARNING;
9969 }
57d187bc 9970
36a206db 9971 return bgp_show(vty, bgp, afi, safi,
9972 (exact ? bgp_show_type_lcommunity_exact
9973 : bgp_show_type_lcommunity),
9974 lcom, uj);
57d187bc
JS
9975}
9976
d62a17ae 9977static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 9978 const char *lcom, bool exact, afi_t afi,
9979 safi_t safi, bool uj)
57d187bc 9980{
d62a17ae 9981 struct community_list *list;
57d187bc 9982
e237b0d2 9983 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 9984 LARGE_COMMUNITY_LIST_MASTER);
9985 if (list == NULL) {
9986 vty_out(vty, "%% %s is not a valid large-community-list name\n",
9987 lcom);
9988 return CMD_WARNING;
9989 }
57d187bc 9990
36a206db 9991 return bgp_show(vty, bgp, afi, safi,
9992 (exact ? bgp_show_type_lcommunity_list_exact
9993 : bgp_show_type_lcommunity_list),
d62a17ae 9994 list, uj);
fee0f4c6 9995}
9996
52951b63
DS
9997DEFUN (show_ip_bgp_large_community_list,
9998 show_ip_bgp_large_community_list_cmd,
36a206db 9999 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community-list <(1-500)|WORD> [exact-match] [json]",
52951b63
DS
10000 SHOW_STR
10001 IP_STR
10002 BGP_STR
10003 BGP_INSTANCE_HELP_STR
9bedbb1e 10004 BGP_AFI_HELP_STR
4dd6177e 10005 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10006 "Display routes matching the large-community-list\n"
10007 "large-community-list number\n"
10008 "large-community-list name\n"
36a206db 10009 "Exact match of the large-communities\n"
52951b63
DS
10010 JSON_STR)
10011{
d62a17ae 10012 char *vrf = NULL;
10013 afi_t afi = AFI_IP6;
10014 safi_t safi = SAFI_UNICAST;
10015 int idx = 0;
36a206db 10016 bool exact_match = 0;
d62a17ae 10017
10018 if (argv_find(argv, argc, "ip", &idx))
10019 afi = AFI_IP;
10020 if (argv_find(argv, argc, "view", &idx)
10021 || argv_find(argv, argc, "vrf", &idx))
10022 vrf = argv[++idx]->arg;
10023 if (argv_find(argv, argc, "ipv4", &idx)
10024 || argv_find(argv, argc, "ipv6", &idx)) {
10025 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
10026 if (argv_find(argv, argc, "unicast", &idx)
10027 || argv_find(argv, argc, "multicast", &idx))
10028 safi = bgp_vty_safi_from_str(argv[idx]->text);
10029 }
10030
9f049418 10031 bool uj = use_json(argc, argv);
d62a17ae 10032
10033 struct bgp *bgp = bgp_lookup_by_name(vrf);
10034 if (bgp == NULL) {
10035 vty_out(vty, "Can't find BGP instance %s\n", vrf);
10036 return CMD_WARNING;
10037 }
10038
10039 argv_find(argv, argc, "large-community-list", &idx);
36a206db 10040
10041 const char *clist_number_or_name = argv[++idx]->arg;
10042
10043 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10044 exact_match = 1;
10045
10046 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
10047 exact_match, afi, safi, uj);
52951b63
DS
10048}
10049DEFUN (show_ip_bgp_large_community,
10050 show_ip_bgp_large_community_cmd,
36a206db 10051 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community [<AA:BB:CC> [exact-match]] [json]",
52951b63
DS
10052 SHOW_STR
10053 IP_STR
10054 BGP_STR
10055 BGP_INSTANCE_HELP_STR
9bedbb1e 10056 BGP_AFI_HELP_STR
4dd6177e 10057 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10058 "Display routes matching the large-communities\n"
10059 "List of large-community numbers\n"
36a206db 10060 "Exact match of the large-communities\n"
52951b63
DS
10061 JSON_STR)
10062{
d62a17ae 10063 char *vrf = NULL;
10064 afi_t afi = AFI_IP6;
10065 safi_t safi = SAFI_UNICAST;
10066 int idx = 0;
36a206db 10067 bool exact_match = 0;
d62a17ae 10068
10069 if (argv_find(argv, argc, "ip", &idx))
10070 afi = AFI_IP;
10071 if (argv_find(argv, argc, "view", &idx)
10072 || argv_find(argv, argc, "vrf", &idx))
10073 vrf = argv[++idx]->arg;
10074 if (argv_find(argv, argc, "ipv4", &idx)
10075 || argv_find(argv, argc, "ipv6", &idx)) {
10076 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
10077 if (argv_find(argv, argc, "unicast", &idx)
10078 || argv_find(argv, argc, "multicast", &idx))
10079 safi = bgp_vty_safi_from_str(argv[idx]->text);
10080 }
10081
9f049418 10082 bool uj = use_json(argc, argv);
d62a17ae 10083
10084 struct bgp *bgp = bgp_lookup_by_name(vrf);
10085 if (bgp == NULL) {
10086 vty_out(vty, "Can't find BGP instance %s\n", vrf);
10087 return CMD_WARNING;
10088 }
10089
36a206db 10090 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
10091 if (argv_find(argv, argc, "exact-match", &idx))
10092 exact_match = 1;
10093 return bgp_show_lcommunity(vty, bgp, argc, argv,
10094 exact_match, afi, safi, uj);
10095 } else
d62a17ae 10096 return bgp_show(vty, bgp, afi, safi,
10097 bgp_show_type_lcommunity_all, NULL, uj);
52951b63
DS
10098}
10099
d62a17ae 10100static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
10101 safi_t safi);
e01ca200 10102
7b2ff250
DW
10103
10104/* BGP route print out function without JSON */
af462945
DS
10105DEFUN (show_ip_bgp,
10106 show_ip_bgp_cmd,
4dd6177e 10107 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
7b2ff250
DW
10108 <dampening <parameters>\
10109 |route-map WORD\
10110 |prefix-list WORD\
10111 |filter-list WORD\
10112 |statistics\
7b2ff250
DW
10113 |community-list <(1-500)|WORD> [exact-match]\
10114 |A.B.C.D/M longer-prefixes\
10115 |X:X::X:X/M longer-prefixes\
10116 >",
718e3744 10117 SHOW_STR
10118 IP_STR
10119 BGP_STR
a636c635 10120 BGP_INSTANCE_HELP_STR
4f280b15 10121 BGP_AFI_HELP_STR
4dd6177e 10122 BGP_SAFI_WITH_LABEL_HELP_STR
a636c635 10123 "Display detailed information about dampening\n"
af462945 10124 "Display detail of configured dampening parameters\n"
a636c635
DW
10125 "Display routes matching the route-map\n"
10126 "A route-map to match on\n"
10127 "Display routes conforming to the prefix-list\n"
8c3deaae 10128 "Prefix-list name\n"
a636c635
DW
10129 "Display routes conforming to the filter-list\n"
10130 "Regular expression access list name\n"
e01ca200 10131 "BGP RIB advertisement statistics\n"
a636c635
DW
10132 "Display routes matching the community-list\n"
10133 "community-list number\n"
10134 "community-list name\n"
10135 "Exact match of the communities\n"
0c7b1b01 10136 "IPv4 prefix\n"
8c3deaae 10137 "Display route and more specific routes\n"
0c7b1b01 10138 "IPv6 prefix\n"
7b2ff250 10139 "Display route and more specific routes\n")
718e3744 10140{
d62a17ae 10141 afi_t afi = AFI_IP6;
10142 safi_t safi = SAFI_UNICAST;
10143 int exact_match = 0;
d62a17ae 10144 struct bgp *bgp = NULL;
10145 int idx = 0;
10146
10147 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10148 &bgp, false);
d62a17ae 10149 if (!idx)
10150 return CMD_WARNING;
10151
d62a17ae 10152 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 10153 if (argv_find(argv, argc, "parameters", &idx))
d62a17ae 10154 return bgp_show_dampening_parameters(vty, afi, safi);
10155 }
c016b6c7 10156
d62a17ae 10157 if (argv_find(argv, argc, "prefix-list", &idx))
10158 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
10159 safi, bgp_show_type_prefix_list);
10160
10161 if (argv_find(argv, argc, "filter-list", &idx))
10162 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
10163 safi, bgp_show_type_filter_list);
10164
10165 if (argv_find(argv, argc, "statistics", &idx))
10166 return bgp_table_stats(vty, bgp, afi, safi);
10167
10168 if (argv_find(argv, argc, "route-map", &idx))
10169 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
10170 safi, bgp_show_type_route_map);
10171
d62a17ae 10172 if (argv_find(argv, argc, "community-list", &idx)) {
10173 const char *clist_number_or_name = argv[++idx]->arg;
10174 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10175 exact_match = 1;
10176 return bgp_show_community_list(vty, bgp, clist_number_or_name,
10177 exact_match, afi, safi);
10178 }
10179 /* prefix-longer */
10180 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10181 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10182 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
10183 safi,
10184 bgp_show_type_prefix_longer);
10185
7b2ff250
DW
10186 return CMD_WARNING;
10187}
10188
10189/* BGP route print out function with JSON */
10190DEFUN (show_ip_bgp_json,
10191 show_ip_bgp_json_cmd,
10192 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
cf4898bc
QY
10193 [cidr-only\
10194 |dampening <flap-statistics|dampened-paths>\
10195 |community [AA:NN|local-AS|no-advertise|no-export\
10196 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10197 |accept-own|accept-own-nexthop|route-filter-v6\
10198 |route-filter-v4|route-filter-translated-v6\
10199 |route-filter-translated-v4] [exact-match]\
10200 ] [json]",
7b2ff250
DW
10201 SHOW_STR
10202 IP_STR
10203 BGP_STR
10204 BGP_INSTANCE_HELP_STR
10205 BGP_AFI_HELP_STR
10206 BGP_SAFI_WITH_LABEL_HELP_STR
10207 "Display only routes with non-natural netmasks\n"
10208 "Display detailed information about dampening\n"
10209 "Display flap statistics of routes\n"
10210 "Display paths suppressed due to dampening\n"
10211 "Display routes matching the communities\n"
d0086e8e
AD
10212 COMMUNITY_AANN_STR
10213 "Do not send outside local AS (well-known community)\n"
10214 "Do not advertise to any peer (well-known community)\n"
10215 "Do not export to next AS (well-known community)\n"
10216 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
10217 "Do not export to any peer (well-known community)\n"
10218 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10219 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10220 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10221 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10222 "Should accept VPN route with local nexthop (well-known community)\n"
10223 "RT VPNv6 route filtering (well-known community)\n"
10224 "RT VPNv4 route filtering (well-known community)\n"
10225 "RT translated VPNv6 route filtering (well-known community)\n"
10226 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 10227 "Exact match of the communities\n"
7b2ff250
DW
10228 JSON_STR)
10229{
10230 afi_t afi = AFI_IP6;
10231 safi_t safi = SAFI_UNICAST;
10232 enum bgp_show_type sh_type = bgp_show_type_normal;
10233 struct bgp *bgp = NULL;
10234 int idx = 0;
d0086e8e 10235 int exact_match = 0;
9f049418
DS
10236 bool uj = use_json(argc, argv);
10237
10238 if (uj)
10239 argc--;
7b2ff250
DW
10240
10241 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10242 &bgp, uj);
7b2ff250
DW
10243 if (!idx)
10244 return CMD_WARNING;
10245
7b2ff250
DW
10246 if (argv_find(argv, argc, "cidr-only", &idx))
10247 return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
10248 NULL, uj);
10249
10250 if (argv_find(argv, argc, "dampening", &idx)) {
10251 if (argv_find(argv, argc, "dampened-paths", &idx))
10252 return bgp_show(vty, bgp, afi, safi,
10253 bgp_show_type_dampend_paths, NULL, uj);
10254 else if (argv_find(argv, argc, "flap-statistics", &idx))
10255 return bgp_show(vty, bgp, afi, safi,
10256 bgp_show_type_flap_statistics, NULL,
10257 uj);
10258 }
10259
10260 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 10261 char *maybecomm = NULL;
cf4898bc 10262 char *community = NULL;
d0086e8e 10263
79bc257a
RW
10264 if (idx + 1 < argc) {
10265 if (argv[idx + 1]->type == VARIABLE_TKN)
10266 maybecomm = argv[idx + 1]->arg;
10267 else
10268 maybecomm = argv[idx + 1]->text;
10269 }
10270
cf4898bc
QY
10271 if (maybecomm && !strmatch(maybecomm, "json")
10272 && !strmatch(maybecomm, "exact-match"))
10273 community = maybecomm;
d0086e8e 10274
cf4898bc
QY
10275 if (argv_find(argv, argc, "exact-match", &idx))
10276 exact_match = 1;
d0086e8e 10277
cf4898bc
QY
10278 if (community)
10279 return bgp_show_community(vty, bgp, community,
10280 exact_match, afi, safi, uj);
10281 else
d0086e8e 10282 return (bgp_show(vty, bgp, afi, safi,
cf4898bc
QY
10283 bgp_show_type_community_all, NULL,
10284 uj));
7b2ff250 10285 }
d0086e8e 10286
1ae44dfc 10287 return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj);
a636c635 10288}
47fc97cc 10289
718e3744 10290DEFUN (show_ip_bgp_route,
10291 show_ip_bgp_route_cmd,
4dd6177e 10292 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]"
ae19d7dd 10293 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
718e3744 10294 SHOW_STR
10295 IP_STR
10296 BGP_STR
a636c635 10297 BGP_INSTANCE_HELP_STR
4f280b15 10298 BGP_AFI_HELP_STR
4dd6177e 10299 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 10300 "Network in the BGP routing table to display\n"
0c7b1b01 10301 "IPv4 prefix\n"
8c3deaae 10302 "Network in the BGP routing table to display\n"
0c7b1b01 10303 "IPv6 prefix\n"
4092b06c 10304 "Display only the bestpath\n"
b05a1c8b 10305 "Display only multipaths\n"
9973d184 10306 JSON_STR)
4092b06c 10307{
d62a17ae 10308 int prefix_check = 0;
ae19d7dd 10309
d62a17ae 10310 afi_t afi = AFI_IP6;
10311 safi_t safi = SAFI_UNICAST;
10312 char *prefix = NULL;
10313 struct bgp *bgp = NULL;
10314 enum bgp_path_type path_type;
9f049418 10315 bool uj = use_json(argc, argv);
b05a1c8b 10316
d62a17ae 10317 int idx = 0;
ae19d7dd 10318
d62a17ae 10319 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10320 &bgp, uj);
d62a17ae 10321 if (!idx)
10322 return CMD_WARNING;
c41247f5 10323
d62a17ae 10324 if (!bgp) {
10325 vty_out(vty,
10326 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10327 return CMD_WARNING;
10328 }
a636c635 10329
d62a17ae 10330 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10331 if (argv_find(argv, argc, "A.B.C.D", &idx)
10332 || argv_find(argv, argc, "X:X::X:X", &idx))
10333 prefix_check = 0;
10334 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10335 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10336 prefix_check = 1;
10337
10338 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
10339 && afi != AFI_IP6) {
10340 vty_out(vty,
10341 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10342 return CMD_WARNING;
10343 }
10344 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
10345 && afi != AFI_IP) {
10346 vty_out(vty,
10347 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10348 return CMD_WARNING;
10349 }
10350
10351 prefix = argv[idx]->arg;
10352
10353 /* [<bestpath|multipath>] */
10354 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 10355 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 10356 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 10357 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 10358 else
360660c6 10359 path_type = BGP_PATH_SHOW_ALL;
a636c635 10360
d62a17ae 10361 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
10362 path_type, uj);
4092b06c
DS
10363}
10364
8c3deaae
QY
10365DEFUN (show_ip_bgp_regexp,
10366 show_ip_bgp_regexp_cmd,
4dd6177e 10367 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX...",
8c3deaae
QY
10368 SHOW_STR
10369 IP_STR
10370 BGP_STR
b00b230a 10371 BGP_INSTANCE_HELP_STR
4f280b15 10372 BGP_AFI_HELP_STR
4dd6177e 10373 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 10374 "Display routes matching the AS path regular expression\n"
a818ea74 10375 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n")
8c3deaae 10376{
d62a17ae 10377 afi_t afi = AFI_IP6;
10378 safi_t safi = SAFI_UNICAST;
10379 struct bgp *bgp = NULL;
8c3deaae 10380
d62a17ae 10381 int idx = 0;
10382 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10383 &bgp, false);
d62a17ae 10384 if (!idx)
10385 return CMD_WARNING;
8c3deaae 10386
d62a17ae 10387 // get index of regex
10388 argv_find(argv, argc, "regexp", &idx);
10389 idx++;
8c3deaae 10390
d62a17ae 10391 char *regstr = argv_concat(argv, argc, idx);
e889891d 10392 int rc = bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
d62a17ae 10393 bgp_show_type_regexp);
10394 XFREE(MTYPE_TMP, regstr);
10395 return rc;
8c3deaae
QY
10396}
10397
a636c635
DW
10398DEFUN (show_ip_bgp_instance_all,
10399 show_ip_bgp_instance_all_cmd,
4dd6177e 10400 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json]",
4092b06c 10401 SHOW_STR
a636c635 10402 IP_STR
4092b06c 10403 BGP_STR
a636c635 10404 BGP_INSTANCE_ALL_HELP_STR
4f280b15 10405 BGP_AFI_HELP_STR
4dd6177e 10406 BGP_SAFI_WITH_LABEL_HELP_STR
9973d184 10407 JSON_STR)
4092b06c 10408{
d62a17ae 10409 afi_t afi = AFI_IP;
10410 safi_t safi = SAFI_UNICAST;
10411 struct bgp *bgp = NULL;
d62a17ae 10412 int idx = 0;
9f049418 10413 bool uj = use_json(argc, argv);
ae19d7dd 10414
d62a17ae 10415 if (uj)
10416 argc--;
e3e29b32 10417
9f049418
DS
10418 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10419 &bgp, uj);
10420 if (!idx)
10421 return CMD_WARNING;
10422
d62a17ae 10423 bgp_show_all_instances_routes_vty(vty, afi, safi, uj);
10424 return CMD_SUCCESS;
e3e29b32
LB
10425}
10426
a4d82a8a
PZ
10427static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
10428 afi_t afi, safi_t safi, enum bgp_show_type type)
718e3744 10429{
d62a17ae 10430 regex_t *regex;
10431 int rc;
e3e29b32 10432
c3900853
DA
10433 if (!config_bgp_aspath_validate(regstr)) {
10434 vty_out(vty, "Invalid character in as-path access-list %s\n",
10435 regstr);
10436 return CMD_WARNING_CONFIG_FAILED;
10437 }
10438
d62a17ae 10439 regex = bgp_regcomp(regstr);
10440 if (!regex) {
10441 vty_out(vty, "Can't compile regexp %s\n", regstr);
10442 return CMD_WARNING;
10443 }
a636c635 10444
e889891d 10445 rc = bgp_show(vty, bgp, afi, safi, type, regex, 0);
d62a17ae 10446 bgp_regex_free(regex);
10447 return rc;
e3e29b32
LB
10448}
10449
d62a17ae 10450static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10451 const char *prefix_list_str, afi_t afi,
10452 safi_t safi, enum bgp_show_type type)
e3e29b32 10453{
d62a17ae 10454 struct prefix_list *plist;
718e3744 10455
d62a17ae 10456 plist = prefix_list_lookup(afi, prefix_list_str);
10457 if (plist == NULL) {
10458 vty_out(vty, "%% %s is not a valid prefix-list name\n",
10459 prefix_list_str);
10460 return CMD_WARNING;
10461 }
718e3744 10462
d62a17ae 10463 return bgp_show(vty, bgp, afi, safi, type, plist, 0);
4092b06c
DS
10464}
10465
d62a17ae 10466static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10467 const char *filter, afi_t afi, safi_t safi,
10468 enum bgp_show_type type)
4092b06c 10469{
d62a17ae 10470 struct as_list *as_list;
718e3744 10471
d62a17ae 10472 as_list = as_list_lookup(filter);
10473 if (as_list == NULL) {
10474 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
10475 filter);
10476 return CMD_WARNING;
10477 }
a636c635 10478
d62a17ae 10479 return bgp_show(vty, bgp, afi, safi, type, as_list, 0);
718e3744 10480}
10481
d62a17ae 10482static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10483 const char *rmap_str, afi_t afi, safi_t safi,
10484 enum bgp_show_type type)
718e3744 10485{
d62a17ae 10486 struct route_map *rmap;
bb46e94f 10487
d62a17ae 10488 rmap = route_map_lookup_by_name(rmap_str);
10489 if (!rmap) {
10490 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
10491 return CMD_WARNING;
10492 }
10493
10494 return bgp_show(vty, bgp, afi, safi, type, rmap, 0);
10495}
10496
7f323236
DW
10497static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10498 const char *comstr, int exact, afi_t afi,
9f049418 10499 safi_t safi, bool use_json)
d62a17ae 10500{
10501 struct community *com;
d62a17ae 10502 int ret = 0;
10503
7f323236 10504 com = community_str2com(comstr);
d62a17ae 10505 if (!com) {
7f323236 10506 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 10507 return CMD_WARNING;
10508 }
10509
10510 ret = bgp_show(vty, bgp, afi, safi,
10511 (exact ? bgp_show_type_community_exact
10512 : bgp_show_type_community),
d0086e8e 10513 com, use_json);
3c1f53de 10514 community_free(&com);
46c3ce83 10515
d62a17ae 10516 return ret;
718e3744 10517}
10518
d62a17ae 10519static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10520 const char *com, int exact, afi_t afi,
10521 safi_t safi)
50ef26d4 10522{
d62a17ae 10523 struct community_list *list;
50ef26d4 10524
e237b0d2 10525 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 10526 if (list == NULL) {
10527 vty_out(vty, "%% %s is not a valid community-list name\n", com);
10528 return CMD_WARNING;
10529 }
718e3744 10530
d62a17ae 10531 return bgp_show(vty, bgp, afi, safi,
10532 (exact ? bgp_show_type_community_list_exact
10533 : bgp_show_type_community_list),
10534 list, 0);
50ef26d4 10535}
10536
d62a17ae 10537static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10538 const char *prefix, afi_t afi, safi_t safi,
10539 enum bgp_show_type type)
718e3744 10540{
d62a17ae 10541 int ret;
10542 struct prefix *p;
47fc97cc 10543
d62a17ae 10544 p = prefix_new();
95cbbd2a 10545
d62a17ae 10546 ret = str2prefix(prefix, p);
10547 if (!ret) {
10548 vty_out(vty, "%% Malformed Prefix\n");
10549 return CMD_WARNING;
10550 }
47e9b292 10551
d62a17ae 10552 ret = bgp_show(vty, bgp, afi, safi, type, p, 0);
63265b5c 10553 prefix_free(&p);
d62a17ae 10554 return ret;
10555}
10556
d62a17ae 10557enum bgp_stats {
10558 BGP_STATS_MAXBITLEN = 0,
10559 BGP_STATS_RIB,
10560 BGP_STATS_PREFIXES,
10561 BGP_STATS_TOTPLEN,
10562 BGP_STATS_UNAGGREGATEABLE,
10563 BGP_STATS_MAX_AGGREGATEABLE,
10564 BGP_STATS_AGGREGATES,
10565 BGP_STATS_SPACE,
10566 BGP_STATS_ASPATH_COUNT,
10567 BGP_STATS_ASPATH_MAXHOPS,
10568 BGP_STATS_ASPATH_TOTHOPS,
10569 BGP_STATS_ASPATH_MAXSIZE,
10570 BGP_STATS_ASPATH_TOTSIZE,
10571 BGP_STATS_ASN_HIGHEST,
10572 BGP_STATS_MAX,
a636c635 10573};
2815e61f 10574
d62a17ae 10575static const char *table_stats_strs[] = {
9d303b37
DL
10576 [BGP_STATS_PREFIXES] = "Total Prefixes",
10577 [BGP_STATS_TOTPLEN] = "Average prefix length",
10578 [BGP_STATS_RIB] = "Total Advertisements",
10579 [BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes",
10580 [BGP_STATS_MAX_AGGREGATEABLE] =
10581 "Maximum aggregateable prefixes",
10582 [BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements",
10583 [BGP_STATS_SPACE] = "Address space advertised",
10584 [BGP_STATS_ASPATH_COUNT] = "Advertisements with paths",
10585 [BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)",
10586 [BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)",
10587 [BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)",
10588 [BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)",
10589 [BGP_STATS_ASN_HIGHEST] = "Highest public ASN",
10590 [BGP_STATS_MAX] = NULL,
a636c635 10591};
2815e61f 10592
d62a17ae 10593struct bgp_table_stats {
10594 struct bgp_table *table;
10595 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 10596 double total_space;
ff7924f6
PJ
10597};
10598
a636c635
DW
10599#if 0
10600#define TALLY_SIGFIG 100000
10601static unsigned long
10602ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 10603{
a636c635
DW
10604 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
10605 unsigned long res = (newtot * TALLY_SIGFIG) / count;
10606 unsigned long ret = newtot / count;
07d0c4ed 10607
a636c635
DW
10608 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
10609 return ret + 1;
10610 else
10611 return ret;
10612}
10613#endif
ff7924f6 10614
9c14ec72
RW
10615static void bgp_table_stats_rn(struct bgp_node *rn, struct bgp_node *top,
10616 struct bgp_table_stats *ts, unsigned int space)
2815e61f 10617{
9c14ec72
RW
10618 struct bgp_node *prn = bgp_node_parent_nolock(rn);
10619 struct bgp_path_info *pi;
d62a17ae 10620
9c14ec72
RW
10621 if (rn == top)
10622 return;
d62a17ae 10623
9c14ec72
RW
10624 if (!bgp_node_has_bgp_path_info_data(rn))
10625 return;
d62a17ae 10626
9c14ec72
RW
10627 ts->counts[BGP_STATS_PREFIXES]++;
10628 ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
ff7924f6 10629
a636c635
DW
10630#if 0
10631 ts->counts[BGP_STATS_AVGPLEN]
10632 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
10633 ts->counts[BGP_STATS_AVGPLEN],
10634 rn->p.prefixlen);
10635#endif
d62a17ae 10636
9c14ec72
RW
10637 /* check if the prefix is included by any other announcements */
10638 while (prn && !bgp_node_has_bgp_path_info_data(prn))
10639 prn = bgp_node_parent_nolock(prn);
d62a17ae 10640
9c14ec72
RW
10641 if (prn == NULL || prn == top) {
10642 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
10643 /* announced address space */
10644 if (space)
10645 ts->total_space += pow(2.0, space - rn->p.prefixlen);
10646 } else if (bgp_node_has_bgp_path_info_data(prn))
10647 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 10648
9c14ec72
RW
10649
10650 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
10651 ts->counts[BGP_STATS_RIB]++;
10652
05864da7
DS
10653 if (CHECK_FLAG(pi->attr->flag,
10654 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
10655 ts->counts[BGP_STATS_AGGREGATES]++;
10656
10657 /* as-path stats */
05864da7 10658 if (pi->attr->aspath) {
9c14ec72
RW
10659 unsigned int hops = aspath_count_hops(pi->attr->aspath);
10660 unsigned int size = aspath_size(pi->attr->aspath);
10661 as_t highest = aspath_highest(pi->attr->aspath);
10662
10663 ts->counts[BGP_STATS_ASPATH_COUNT]++;
10664
10665 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
10666 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
10667
10668 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
10669 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
10670
10671 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
10672 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 10673#if 0
07d0c4ed 10674 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
10675 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
10676 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
10677 hops);
10678 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
10679 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
10680 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
10681 size);
10682#endif
9c14ec72
RW
10683 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
10684 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
10685 }
10686 }
10687}
10688
10689static int bgp_table_stats_walker(struct thread *t)
10690{
10691 struct bgp_node *rn, *nrn;
10692 struct bgp_node *top;
10693 struct bgp_table_stats *ts = THREAD_ARG(t);
10694 unsigned int space = 0;
10695
10696 if (!(top = bgp_table_top(ts->table)))
10697 return 0;
10698
10699 switch (ts->table->afi) {
10700 case AFI_IP:
10701 space = IPV4_MAX_BITLEN;
10702 break;
10703 case AFI_IP6:
10704 space = IPV6_MAX_BITLEN;
10705 break;
10706 default:
10707 return 0;
10708 }
10709
10710 ts->counts[BGP_STATS_MAXBITLEN] = space;
10711
10712 for (rn = top; rn; rn = bgp_route_next(rn)) {
10713 if (ts->table->safi == SAFI_MPLS_VPN) {
10714 struct bgp_table *table;
10715
10716 table = bgp_node_get_bgp_table_info(rn);
10717 if (!table)
10718 continue;
10719
10720 top = bgp_table_top(table);
10721 for (nrn = bgp_table_top(table); nrn;
10722 nrn = bgp_route_next(nrn))
10723 bgp_table_stats_rn(nrn, top, ts, space);
10724 } else {
10725 bgp_table_stats_rn(rn, top, ts, space);
d62a17ae 10726 }
10727 }
9c14ec72 10728
d62a17ae 10729 return 0;
2815e61f 10730}
ff7924f6 10731
d62a17ae 10732static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
10733 safi_t safi)
2815e61f 10734{
d62a17ae 10735 struct bgp_table_stats ts;
10736 unsigned int i;
019386c2 10737
d62a17ae 10738 if (!bgp->rib[afi][safi]) {
10739 vty_out(vty, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10740 afi, safi);
10741 return CMD_WARNING;
10742 }
019386c2 10743
5cb5f4d0 10744 vty_out(vty, "BGP %s RIB statistics\n", get_afi_safi_str(afi, safi, false));
019386c2 10745
d62a17ae 10746 /* labeled-unicast routes live in the unicast table */
10747 if (safi == SAFI_LABELED_UNICAST)
10748 safi = SAFI_UNICAST;
019386c2 10749
d62a17ae 10750 memset(&ts, 0, sizeof(ts));
10751 ts.table = bgp->rib[afi][safi];
10752 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 10753
d62a17ae 10754 for (i = 0; i < BGP_STATS_MAX; i++) {
10755 if (!table_stats_strs[i])
10756 continue;
10757
10758 switch (i) {
a636c635
DW
10759#if 0
10760 case BGP_STATS_ASPATH_AVGHOPS:
10761 case BGP_STATS_ASPATH_AVGSIZE:
10762 case BGP_STATS_AVGPLEN:
10763 vty_out (vty, "%-30s: ", table_stats_strs[i]);
10764 vty_out (vty, "%12.2f",
10765 (float)ts.counts[i] / (float)TALLY_SIGFIG);
10766 break;
10767#endif
d62a17ae 10768 case BGP_STATS_ASPATH_TOTHOPS:
10769 case BGP_STATS_ASPATH_TOTSIZE:
10770 vty_out(vty, "%-30s: ", table_stats_strs[i]);
10771 vty_out(vty, "%12.2f",
10772 ts.counts[i]
10773 ? (float)ts.counts[i]
10774 / (float)ts.counts
10775 [BGP_STATS_ASPATH_COUNT]
10776 : 0);
10777 break;
10778 case BGP_STATS_TOTPLEN:
10779 vty_out(vty, "%-30s: ", table_stats_strs[i]);
10780 vty_out(vty, "%12.2f",
10781 ts.counts[i]
10782 ? (float)ts.counts[i]
10783 / (float)ts.counts
10784 [BGP_STATS_PREFIXES]
10785 : 0);
10786 break;
10787 case BGP_STATS_SPACE:
10788 vty_out(vty, "%-30s: ", table_stats_strs[i]);
8d0ab76d
DL
10789 vty_out(vty, "%12g\n", ts.total_space);
10790
10791 if (afi == AFI_IP6) {
10792 vty_out(vty, "%30s: ", "/32 equivalent ");
10793 vty_out(vty, "%12g\n",
a4d82a8a 10794 ts.total_space * pow(2.0, -128 + 32));
8d0ab76d
DL
10795 vty_out(vty, "%30s: ", "/48 equivalent ");
10796 vty_out(vty, "%12g\n",
a4d82a8a 10797 ts.total_space * pow(2.0, -128 + 48));
8d0ab76d
DL
10798 } else {
10799 vty_out(vty, "%30s: ", "% announced ");
10800 vty_out(vty, "%12.2f\n",
10801 ts.total_space * 100. * pow(2.0, -32));
10802 vty_out(vty, "%30s: ", "/8 equivalent ");
10803 vty_out(vty, "%12.2f\n",
a4d82a8a 10804 ts.total_space * pow(2.0, -32 + 8));
8d0ab76d
DL
10805 vty_out(vty, "%30s: ", "/24 equivalent ");
10806 vty_out(vty, "%12.2f\n",
a4d82a8a 10807 ts.total_space * pow(2.0, -32 + 24));
8d0ab76d 10808 }
d62a17ae 10809 break;
10810 default:
10811 vty_out(vty, "%-30s: ", table_stats_strs[i]);
10812 vty_out(vty, "%12llu", ts.counts[i]);
10813 }
ff7924f6 10814
d62a17ae 10815 vty_out(vty, "\n");
10816 }
10817 return CMD_SUCCESS;
10818}
10819
10820enum bgp_pcounts {
10821 PCOUNT_ADJ_IN = 0,
10822 PCOUNT_DAMPED,
10823 PCOUNT_REMOVED,
10824 PCOUNT_HISTORY,
10825 PCOUNT_STALE,
10826 PCOUNT_VALID,
10827 PCOUNT_ALL,
10828 PCOUNT_COUNTED,
10829 PCOUNT_PFCNT, /* the figure we display to users */
10830 PCOUNT_MAX,
a636c635 10831};
718e3744 10832
d62a17ae 10833static const char *pcount_strs[] = {
9d303b37
DL
10834 [PCOUNT_ADJ_IN] = "Adj-in",
10835 [PCOUNT_DAMPED] = "Damped",
10836 [PCOUNT_REMOVED] = "Removed",
10837 [PCOUNT_HISTORY] = "History",
10838 [PCOUNT_STALE] = "Stale",
10839 [PCOUNT_VALID] = "Valid",
10840 [PCOUNT_ALL] = "All RIB",
10841 [PCOUNT_COUNTED] = "PfxCt counted",
10842 [PCOUNT_PFCNT] = "Useable",
10843 [PCOUNT_MAX] = NULL,
a636c635 10844};
718e3744 10845
d62a17ae 10846struct peer_pcounts {
10847 unsigned int count[PCOUNT_MAX];
10848 const struct peer *peer;
10849 const struct bgp_table *table;
a636c635 10850};
47fc97cc 10851
d62a17ae 10852static int bgp_peer_count_walker(struct thread *t)
10853{
10854 struct bgp_node *rn;
10855 struct peer_pcounts *pc = THREAD_ARG(t);
10856 const struct peer *peer = pc->peer;
10857
10858 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn)) {
10859 struct bgp_adj_in *ain;
40381db7 10860 struct bgp_path_info *pi;
d62a17ae 10861
10862 for (ain = rn->adj_in; ain; ain = ain->next)
10863 if (ain->peer == peer)
10864 pc->count[PCOUNT_ADJ_IN]++;
10865
6f94b685
DS
10866 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
10867
40381db7 10868 if (pi->peer != peer)
d62a17ae 10869 continue;
10870
10871 pc->count[PCOUNT_ALL]++;
10872
40381db7 10873 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
d62a17ae 10874 pc->count[PCOUNT_DAMPED]++;
40381db7 10875 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
d62a17ae 10876 pc->count[PCOUNT_HISTORY]++;
40381db7 10877 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
d62a17ae 10878 pc->count[PCOUNT_REMOVED]++;
40381db7 10879 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 10880 pc->count[PCOUNT_STALE]++;
40381db7 10881 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
d62a17ae 10882 pc->count[PCOUNT_VALID]++;
40381db7 10883 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
d62a17ae 10884 pc->count[PCOUNT_PFCNT]++;
10885
40381db7 10886 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 10887 pc->count[PCOUNT_COUNTED]++;
40381db7 10888 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
1c50c1c0
QY
10889 flog_err(
10890 EC_LIB_DEVELOPMENT,
10891 "Attempting to count but flags say it is unusable");
d62a17ae 10892 } else {
40381db7 10893 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
1c50c1c0
QY
10894 flog_err(
10895 EC_LIB_DEVELOPMENT,
10896 "Not counted but flags say we should");
d62a17ae 10897 }
10898 }
10899 }
10900 return 0;
718e3744 10901}
10902
d62a17ae 10903static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 10904 safi_t safi, bool use_json)
856ca177 10905{
d62a17ae 10906 struct peer_pcounts pcounts = {.peer = peer};
10907 unsigned int i;
10908 json_object *json = NULL;
10909 json_object *json_loop = NULL;
856ca177 10910
d62a17ae 10911 if (use_json) {
10912 json = json_object_new_object();
10913 json_loop = json_object_new_object();
10914 }
718e3744 10915
d62a17ae 10916 if (!peer || !peer->bgp || !peer->afc[afi][safi]
10917 || !peer->bgp->rib[afi][safi]) {
10918 if (use_json) {
10919 json_object_string_add(
10920 json, "warning",
10921 "No such neighbor or address family");
10922 vty_out(vty, "%s\n", json_object_to_json_string(json));
10923 json_object_free(json);
10924 } else
10925 vty_out(vty, "%% No such neighbor or address family\n");
10926
10927 return CMD_WARNING;
10928 }
2a71e9ce 10929
d62a17ae 10930 memset(&pcounts, 0, sizeof(pcounts));
10931 pcounts.peer = peer;
10932 pcounts.table = peer->bgp->rib[afi][safi];
10933
10934 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
10935 * stats for the thread-walk (i.e. ensure this can't be blamed on
10936 * on just vty_read()).
10937 */
d62a17ae 10938 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
10939
10940 if (use_json) {
10941 json_object_string_add(json, "prefixCountsFor", peer->host);
10942 json_object_string_add(json, "multiProtocol",
5cb5f4d0 10943 get_afi_safi_str(afi, safi, true));
d62a17ae 10944 json_object_int_add(json, "pfxCounter",
10945 peer->pcount[afi][safi]);
10946
10947 for (i = 0; i < PCOUNT_MAX; i++)
10948 json_object_int_add(json_loop, pcount_strs[i],
10949 pcounts.count[i]);
10950
10951 json_object_object_add(json, "ribTableWalkCounters", json_loop);
10952
10953 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
10954 json_object_string_add(json, "pfxctDriftFor",
10955 peer->host);
10956 json_object_string_add(
10957 json, "recommended",
10958 "Please report this bug, with the above command output");
10959 }
996c9314
LB
10960 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10961 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 10962 json_object_free(json);
10963 } else {
10964
10965 if (peer->hostname
10966 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
10967 vty_out(vty, "Prefix counts for %s/%s, %s\n",
10968 peer->hostname, peer->host,
5cb5f4d0 10969 get_afi_safi_str(afi, safi, false));
d62a17ae 10970 } else {
10971 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 10972 get_afi_safi_str(afi, safi, false));
d62a17ae 10973 }
10974
a0a87037 10975 vty_out(vty, "PfxCt: %" PRIu32 "\n", peer->pcount[afi][safi]);
d62a17ae 10976 vty_out(vty, "\nCounts from RIB table walk:\n\n");
10977
10978 for (i = 0; i < PCOUNT_MAX; i++)
10979 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
10980 pcounts.count[i]);
10981
10982 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
10983 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
10984 vty_out(vty,
10985 "Please report this bug, with the above command output\n");
10986 }
10987 }
10988
10989 return CMD_SUCCESS;
718e3744 10990}
10991
a636c635
DW
10992DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
10993 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
c1a44e43 10994 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] "
30a6a167 10995 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
718e3744 10996 SHOW_STR
10997 IP_STR
10998 BGP_STR
8386ac43 10999 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
11000 BGP_AFI_HELP_STR
11001 BGP_SAFI_HELP_STR
0b16f239
DS
11002 "Detailed information on TCP and BGP neighbor connections\n"
11003 "Neighbor to display information about\n"
11004 "Neighbor to display information about\n"
91d37724 11005 "Neighbor on BGP configured interface\n"
a636c635 11006 "Display detailed prefix count information\n"
9973d184 11007 JSON_STR)
0b16f239 11008{
d62a17ae 11009 afi_t afi = AFI_IP6;
11010 safi_t safi = SAFI_UNICAST;
11011 struct peer *peer;
11012 int idx = 0;
11013 struct bgp *bgp = NULL;
9f049418
DS
11014 bool uj = use_json(argc, argv);
11015
11016 if (uj)
11017 argc--;
856ca177 11018
d62a17ae 11019 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11020 &bgp, uj);
d62a17ae 11021 if (!idx)
11022 return CMD_WARNING;
0b16f239 11023
d62a17ae 11024 argv_find(argv, argc, "neighbors", &idx);
11025 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
11026 if (!peer)
11027 return CMD_WARNING;
bb46e94f 11028
29c8d9da 11029 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 11030}
0b16f239 11031
d6902373
PG
11032#ifdef KEEP_OLD_VPN_COMMANDS
11033DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
11034 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
11035 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
11036 SHOW_STR
11037 IP_STR
11038 BGP_STR
d6902373 11039 BGP_VPNVX_HELP_STR
91d37724 11040 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
11041 "Detailed information on TCP and BGP neighbor connections\n"
11042 "Neighbor to display information about\n"
11043 "Neighbor to display information about\n"
91d37724 11044 "Neighbor on BGP configured interface\n"
a636c635 11045 "Display detailed prefix count information\n"
9973d184 11046 JSON_STR)
a636c635 11047{
d62a17ae 11048 int idx_peer = 6;
11049 struct peer *peer;
9f049418 11050 bool uj = use_json(argc, argv);
a636c635 11051
d62a17ae 11052 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
11053 if (!peer)
11054 return CMD_WARNING;
11055
11056 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
11057}
11058
d6902373
PG
11059DEFUN (show_ip_bgp_vpn_all_route_prefix,
11060 show_ip_bgp_vpn_all_route_prefix_cmd,
11061 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
11062 SHOW_STR
11063 IP_STR
11064 BGP_STR
d6902373 11065 BGP_VPNVX_HELP_STR
91d37724
QY
11066 "Display information about all VPNv4 NLRIs\n"
11067 "Network in the BGP routing table to display\n"
3a2d747c 11068 "Network in the BGP routing table to display\n"
9973d184 11069 JSON_STR)
91d37724 11070{
d62a17ae 11071 int idx = 0;
11072 char *network = NULL;
11073 struct bgp *bgp = bgp_get_default();
11074 if (!bgp) {
11075 vty_out(vty, "Can't find default instance\n");
11076 return CMD_WARNING;
11077 }
87e34b58 11078
d62a17ae 11079 if (argv_find(argv, argc, "A.B.C.D", &idx))
11080 network = argv[idx]->arg;
11081 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
11082 network = argv[idx]->arg;
11083 else {
11084 vty_out(vty, "Unable to figure out Network\n");
11085 return CMD_WARNING;
11086 }
87e34b58 11087
d62a17ae 11088 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 11089 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 11090}
d6902373 11091#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 11092
44c69747
LK
11093DEFUN (show_bgp_l2vpn_evpn_route_prefix,
11094 show_bgp_l2vpn_evpn_route_prefix_cmd,
11095 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 11096 SHOW_STR
4c63a661
PG
11097 BGP_STR
11098 L2VPN_HELP_STR
11099 EVPN_HELP_STR
44c69747
LK
11100 "Network in the BGP routing table to display\n"
11101 "Network in the BGP routing table to display\n"
4c63a661
PG
11102 "Network in the BGP routing table to display\n"
11103 "Network in the BGP routing table to display\n"
11104 JSON_STR)
11105{
d62a17ae 11106 int idx = 0;
11107 char *network = NULL;
44c69747 11108 int prefix_check = 0;
a636c635 11109
44c69747
LK
11110 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
11111 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 11112 network = argv[idx]->arg;
44c69747
LK
11113 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
11114 argv_find(argv, argc, "A.B.C.D/M", &idx)) {
d62a17ae 11115 network = argv[idx]->arg;
44c69747
LK
11116 prefix_check = 1;
11117 } else {
d62a17ae 11118 vty_out(vty, "Unable to figure out Network\n");
11119 return CMD_WARNING;
11120 }
44c69747
LK
11121 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
11122 prefix_check, BGP_PATH_SHOW_ALL,
11123 use_json(argc, argv));
d62a17ae 11124}
11125
11126static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 11127 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 11128 const char *rmap_name, bool use_json,
6392aaa6 11129 json_object *json)
d62a17ae 11130{
11131 struct bgp_table *table;
11132 struct bgp_adj_in *ain;
11133 struct bgp_adj_out *adj;
11134 unsigned long output_count;
11135 unsigned long filtered_count;
11136 struct bgp_node *rn;
11137 int header1 = 1;
11138 struct bgp *bgp;
11139 int header2 = 1;
11140 struct attr attr;
11141 int ret;
11142 struct update_subgroup *subgrp;
11143 json_object *json_scode = NULL;
11144 json_object *json_ocode = NULL;
11145 json_object *json_ar = NULL;
11146 struct peer_af *paf;
f99def61 11147 bool route_filtered;
d62a17ae 11148
11149 if (use_json) {
11150 json_scode = json_object_new_object();
11151 json_ocode = json_object_new_object();
11152 json_ar = json_object_new_object();
11153
11154 json_object_string_add(json_scode, "suppressed", "s");
11155 json_object_string_add(json_scode, "damped", "d");
11156 json_object_string_add(json_scode, "history", "h");
11157 json_object_string_add(json_scode, "valid", "*");
11158 json_object_string_add(json_scode, "best", ">");
11159 json_object_string_add(json_scode, "multipath", "=");
11160 json_object_string_add(json_scode, "internal", "i");
11161 json_object_string_add(json_scode, "ribFailure", "r");
11162 json_object_string_add(json_scode, "stale", "S");
11163 json_object_string_add(json_scode, "removed", "R");
11164
11165 json_object_string_add(json_ocode, "igp", "i");
11166 json_object_string_add(json_ocode, "egp", "e");
11167 json_object_string_add(json_ocode, "incomplete", "?");
11168 }
a636c635 11169
d62a17ae 11170 bgp = peer->bgp;
a636c635 11171
d62a17ae 11172 if (!bgp) {
11173 if (use_json) {
11174 json_object_string_add(json, "alert", "no BGP");
11175 vty_out(vty, "%s\n", json_object_to_json_string(json));
11176 json_object_free(json);
11177 } else
11178 vty_out(vty, "%% No bgp\n");
11179 return;
11180 }
a636c635 11181
c512a642
EDP
11182 /* labeled-unicast routes live in the unicast table */
11183 if (safi == SAFI_LABELED_UNICAST)
11184 table = bgp->rib[afi][SAFI_UNICAST];
11185 else
11186 table = bgp->rib[afi][safi];
d62a17ae 11187
11188 output_count = filtered_count = 0;
11189 subgrp = peer_subgroup(peer, afi, safi);
11190
6392aaa6 11191 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 11192 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
11193 if (use_json) {
11194 json_object_int_add(json, "bgpTableVersion",
11195 table->version);
11196 json_object_string_add(json, "bgpLocalRouterId",
11197 inet_ntoa(bgp->router_id));
01eced22
AD
11198 json_object_int_add(json, "defaultLocPrf",
11199 bgp->default_local_pref);
11200 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 11201 json_object_object_add(json, "bgpStatusCodes",
11202 json_scode);
11203 json_object_object_add(json, "bgpOriginCodes",
11204 json_ocode);
07d0c4ed
DA
11205 json_object_string_add(
11206 json, "bgpOriginatingDefaultNetwork",
11207 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 11208 } else {
996c9314 11209 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 11210 ", local router ID is %s, vrf id ",
d62a17ae 11211 table->version, inet_ntoa(bgp->router_id));
9df8b37c
PZ
11212 if (bgp->vrf_id == VRF_UNKNOWN)
11213 vty_out(vty, "%s", VRFID_NONE_STR);
11214 else
11215 vty_out(vty, "%u", bgp->vrf_id);
11216 vty_out(vty, "\n");
01eced22
AD
11217 vty_out(vty, "Default local pref %u, ",
11218 bgp->default_local_pref);
11219 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 11220 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11221 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 11222 vty_out(vty, BGP_SHOW_OCODE_HEADER);
11223
07d0c4ed
DA
11224 vty_out(vty, "Originating default network %s\n\n",
11225 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 11226 }
11227 header1 = 0;
11228 }
a636c635 11229
d62a17ae 11230 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6392aaa6
PM
11231 if (type == bgp_show_adj_route_received
11232 || type == bgp_show_adj_route_filtered) {
d62a17ae 11233 for (ain = rn->adj_in; ain; ain = ain->next) {
05864da7 11234 if (ain->peer != peer)
ea47320b 11235 continue;
6392aaa6 11236
ea47320b
DL
11237 if (header1) {
11238 if (use_json) {
11239 json_object_int_add(
60466a63 11240 json, "bgpTableVersion",
ea47320b
DL
11241 0);
11242 json_object_string_add(
11243 json,
11244 "bgpLocalRouterId",
11245 inet_ntoa(
11246 bgp->router_id));
01eced22
AD
11247 json_object_int_add(json,
11248 "defaultLocPrf",
11249 bgp->default_local_pref);
11250 json_object_int_add(json,
11251 "localAS", bgp->as);
ea47320b 11252 json_object_object_add(
60466a63 11253 json, "bgpStatusCodes",
ea47320b
DL
11254 json_scode);
11255 json_object_object_add(
60466a63 11256 json, "bgpOriginCodes",
ea47320b
DL
11257 json_ocode);
11258 } else {
11259 vty_out(vty,
9df8b37c 11260 "BGP table version is 0, local router ID is %s, vrf id ",
ea47320b 11261 inet_ntoa(
9df8b37c
PZ
11262 bgp->router_id));
11263 if (bgp->vrf_id == VRF_UNKNOWN)
11264 vty_out(vty, "%s",
11265 VRFID_NONE_STR);
11266 else
11267 vty_out(vty, "%u",
11268 bgp->vrf_id);
11269 vty_out(vty, "\n");
01eced22
AD
11270 vty_out(vty,
11271 "Default local pref %u, ",
11272 bgp->default_local_pref);
11273 vty_out(vty, "local AS %u\n",
11274 bgp->as);
ea47320b
DL
11275 vty_out(vty,
11276 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
11277 vty_out(vty,
11278 BGP_SHOW_NCODE_HEADER);
ea47320b
DL
11279 vty_out(vty,
11280 BGP_SHOW_OCODE_HEADER);
d62a17ae 11281 }
ea47320b
DL
11282 header1 = 0;
11283 }
11284 if (header2) {
11285 if (!use_json)
11286 vty_out(vty, BGP_SHOW_HEADER);
11287 header2 = 0;
11288 }
6392aaa6
PM
11289
11290 bgp_attr_dup(&attr, ain->attr);
f99def61
AD
11291 route_filtered = false;
11292
11293 /* Filter prefix using distribute list,
11294 * filter list or prefix list
11295 */
11296 if ((bgp_input_filter(peer, &rn->p, &attr, afi,
11297 safi)) == FILTER_DENY)
11298 route_filtered = true;
11299
11300 /* Filter prefix using route-map */
6392aaa6 11301 ret = bgp_input_modifier(peer, &rn->p, &attr,
82b692c0 11302 afi, safi, rmap_name, NULL, 0);
6392aaa6 11303
13c8e163
AD
11304 if (type == bgp_show_adj_route_filtered &&
11305 !route_filtered && ret != RMAP_DENY) {
b755861b 11306 bgp_attr_undup(&attr, ain->attr);
6392aaa6 11307 continue;
d62a17ae 11308 }
6392aaa6 11309
13c8e163
AD
11310 if (type == bgp_show_adj_route_received &&
11311 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
11312 filtered_count++;
11313
11314 route_vty_out_tmp(vty, &rn->p, &attr, safi,
11315 use_json, json_ar);
b755861b 11316 bgp_attr_undup(&attr, ain->attr);
6392aaa6 11317 output_count++;
d62a17ae 11318 }
6392aaa6 11319 } else if (type == bgp_show_adj_route_advertised) {
a79c04e7 11320 RB_FOREACH (adj, bgp_adj_out_rb, &rn->adj_out)
924c3f6a 11321 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 11322 if (paf->peer != peer || !adj->attr)
924c3f6a 11323 continue;
d62a17ae 11324
924c3f6a
DS
11325 if (header1) {
11326 if (use_json) {
11327 json_object_int_add(
11328 json,
11329 "bgpTableVersion",
11330 table->version);
11331 json_object_string_add(
11332 json,
11333 "bgpLocalRouterId",
11334 inet_ntoa(
11335 bgp->router_id));
01eced22
AD
11336 json_object_int_add(
11337 json, "defaultLocPrf",
11338 bgp->default_local_pref
11339 );
11340 json_object_int_add(
11341 json, "localAS",
11342 bgp->as);
924c3f6a
DS
11343 json_object_object_add(
11344 json,
11345 "bgpStatusCodes",
11346 json_scode);
11347 json_object_object_add(
11348 json,
11349 "bgpOriginCodes",
11350 json_ocode);
11351 } else {
11352 vty_out(vty,
11353 "BGP table version is %" PRIu64
9df8b37c 11354 ", local router ID is %s, vrf id ",
924c3f6a
DS
11355 table->version,
11356 inet_ntoa(
11357 bgp->router_id));
9df8b37c
PZ
11358 if (bgp->vrf_id ==
11359 VRF_UNKNOWN)
11360 vty_out(vty,
11361 "%s",
11362 VRFID_NONE_STR);
11363 else
11364 vty_out(vty,
11365 "%u",
11366 bgp->vrf_id);
11367 vty_out(vty, "\n");
01eced22
AD
11368 vty_out(vty,
11369 "Default local pref %u, ",
11370 bgp->default_local_pref
11371 );
11372 vty_out(vty,
11373 "local AS %u\n",
11374 bgp->as);
924c3f6a
DS
11375 vty_out(vty,
11376 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
11377 vty_out(vty,
11378 BGP_SHOW_NCODE_HEADER);
924c3f6a
DS
11379 vty_out(vty,
11380 BGP_SHOW_OCODE_HEADER);
a2addae8 11381 }
924c3f6a
DS
11382 header1 = 0;
11383 }
924c3f6a
DS
11384 if (header2) {
11385 if (!use_json)
11386 vty_out(vty,
11387 BGP_SHOW_HEADER);
11388 header2 = 0;
11389 }
d62a17ae 11390
b755861b
PM
11391 bgp_attr_dup(&attr, adj->attr);
11392 ret = bgp_output_modifier(
11393 peer, &rn->p, &attr, afi, safi,
11394 rmap_name);
f46d8e1e 11395
b755861b
PM
11396 if (ret != RMAP_DENY) {
11397 route_vty_out_tmp(vty, &rn->p,
11398 &attr, safi,
11399 use_json,
11400 json_ar);
11401 output_count++;
11402 } else {
11403 filtered_count++;
a2addae8 11404 }
b755861b
PM
11405
11406 bgp_attr_undup(&attr, adj->attr);
924c3f6a 11407 }
d62a17ae 11408 }
11409 }
d62a17ae 11410
d62a17ae 11411 if (use_json) {
6392aaa6
PM
11412 json_object_object_add(json, "advertisedRoutes", json_ar);
11413 json_object_int_add(json, "totalPrefixCounter", output_count);
11414 json_object_int_add(json, "filteredPrefixCounter",
11415 filtered_count);
11416
996c9314
LB
11417 vty_out(vty, "%s\n", json_object_to_json_string_ext(
11418 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 11419 json_object_free(json);
6392aaa6
PM
11420 } else if (output_count > 0) {
11421 if (filtered_count > 0)
11422 vty_out(vty,
11423 "\nTotal number of prefixes %ld (%ld filtered)\n",
11424 output_count, filtered_count);
11425 else
11426 vty_out(vty, "\nTotal number of prefixes %ld\n",
11427 output_count);
d62a17ae 11428 }
a636c635 11429}
2a71e9ce 11430
d62a17ae 11431static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 11432 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 11433 const char *rmap_name, bool use_json)
0b16f239 11434{
d62a17ae 11435 json_object *json = NULL;
0b16f239 11436
d62a17ae 11437 if (use_json)
11438 json = json_object_new_object();
0b16f239 11439
d62a17ae 11440 if (!peer || !peer->afc[afi][safi]) {
11441 if (use_json) {
11442 json_object_string_add(
11443 json, "warning",
11444 "No such neighbor or address family");
11445 vty_out(vty, "%s\n", json_object_to_json_string(json));
11446 json_object_free(json);
11447 } else
11448 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 11449
d62a17ae 11450 return CMD_WARNING;
11451 }
11452
6392aaa6
PM
11453 if ((type == bgp_show_adj_route_received
11454 || type == bgp_show_adj_route_filtered)
d62a17ae 11455 && !CHECK_FLAG(peer->af_flags[afi][safi],
11456 PEER_FLAG_SOFT_RECONFIG)) {
11457 if (use_json) {
11458 json_object_string_add(
11459 json, "warning",
11460 "Inbound soft reconfiguration not enabled");
11461 vty_out(vty, "%s\n", json_object_to_json_string(json));
11462 json_object_free(json);
11463 } else
11464 vty_out(vty,
11465 "%% Inbound soft reconfiguration not enabled\n");
11466
11467 return CMD_WARNING;
11468 }
0b16f239 11469
6392aaa6 11470 show_adj_route(vty, peer, afi, safi, type, rmap_name, use_json, json);
0b16f239 11471
d62a17ae 11472 return CMD_SUCCESS;
a636c635 11473}
50ef26d4 11474
a636c635
DW
11475DEFUN (show_ip_bgp_instance_neighbor_advertised_route,
11476 show_ip_bgp_instance_neighbor_advertised_route_cmd,
4dd6177e 11477 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
6392aaa6 11478 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
718e3744 11479 SHOW_STR
11480 IP_STR
11481 BGP_STR
a636c635 11482 BGP_INSTANCE_HELP_STR
7395a2c9 11483 BGP_AFI_HELP_STR
4dd6177e 11484 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 11485 "Detailed information on TCP and BGP neighbor connections\n"
11486 "Neighbor to display information about\n"
11487 "Neighbor to display information about\n"
91d37724 11488 "Neighbor on BGP configured interface\n"
a636c635 11489 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
11490 "Display the received routes from neighbor\n"
11491 "Display the filtered routes received from neighbor\n"
a636c635
DW
11492 "Route-map to modify the attributes\n"
11493 "Name of the route map\n"
9973d184 11494 JSON_STR)
718e3744 11495{
d62a17ae 11496 afi_t afi = AFI_IP6;
11497 safi_t safi = SAFI_UNICAST;
11498 char *rmap_name = NULL;
11499 char *peerstr = NULL;
d62a17ae 11500 struct bgp *bgp = NULL;
11501 struct peer *peer;
6392aaa6 11502 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 11503 int idx = 0;
9f049418 11504 bool uj = use_json(argc, argv);
6392aaa6 11505
d62a17ae 11506 if (uj)
11507 argc--;
30a6a167 11508
9f049418
DS
11509 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11510 &bgp, uj);
11511 if (!idx)
11512 return CMD_WARNING;
11513
d62a17ae 11514 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11515 argv_find(argv, argc, "neighbors", &idx);
11516 peerstr = argv[++idx]->arg;
8c3deaae 11517
d62a17ae 11518 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
11519 if (!peer)
11520 return CMD_WARNING;
856ca177 11521
d62a17ae 11522 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
11523 type = bgp_show_adj_route_advertised;
11524 else if (argv_find(argv, argc, "received-routes", &idx))
11525 type = bgp_show_adj_route_received;
11526 else if (argv_find(argv, argc, "filtered-routes", &idx))
11527 type = bgp_show_adj_route_filtered;
11528
d62a17ae 11529 if (argv_find(argv, argc, "route-map", &idx))
11530 rmap_name = argv[++idx]->arg;
95cbbd2a 11531
6392aaa6 11532 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj);
95cbbd2a
ML
11533}
11534
718e3744 11535DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
11536 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 11537 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 11538 SHOW_STR
11539 IP_STR
11540 BGP_STR
8c3deaae
QY
11541 "Address Family\n"
11542 "Address Family\n"
718e3744 11543 "Address Family modifier\n"
11544 "Detailed information on TCP and BGP neighbor connections\n"
11545 "Neighbor to display information about\n"
11546 "Neighbor to display information about\n"
91d37724 11547 "Neighbor on BGP configured interface\n"
718e3744 11548 "Display information received from a BGP neighbor\n"
856ca177 11549 "Display the prefixlist filter\n"
9973d184 11550 JSON_STR)
718e3744 11551{
d62a17ae 11552 afi_t afi = AFI_IP6;
11553 safi_t safi = SAFI_UNICAST;
11554 char *peerstr = NULL;
11555
11556 char name[BUFSIZ];
11557 union sockunion su;
11558 struct peer *peer;
11559 int count, ret;
11560
11561 int idx = 0;
11562
11563 /* show [ip] bgp */
11564 if (argv_find(argv, argc, "ip", &idx))
11565 afi = AFI_IP;
11566 /* [<ipv4|ipv6> [unicast]] */
11567 if (argv_find(argv, argc, "ipv4", &idx))
11568 afi = AFI_IP;
11569 if (argv_find(argv, argc, "ipv6", &idx))
11570 afi = AFI_IP6;
11571 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11572 argv_find(argv, argc, "neighbors", &idx);
11573 peerstr = argv[++idx]->arg;
11574
9f049418 11575 bool uj = use_json(argc, argv);
d62a17ae 11576
11577 ret = str2sockunion(peerstr, &su);
11578 if (ret < 0) {
11579 peer = peer_lookup_by_conf_if(NULL, peerstr);
11580 if (!peer) {
11581 if (uj)
11582 vty_out(vty, "{}\n");
11583 else
11584 vty_out(vty,
11585 "%% Malformed address or name: %s\n",
11586 peerstr);
11587 return CMD_WARNING;
11588 }
11589 } else {
11590 peer = peer_lookup(NULL, &su);
11591 if (!peer) {
11592 if (uj)
11593 vty_out(vty, "{}\n");
11594 else
11595 vty_out(vty, "No peer\n");
11596 return CMD_WARNING;
11597 }
11598 }
718e3744 11599
d62a17ae 11600 sprintf(name, "%s.%d.%d", peer->host, afi, safi);
11601 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
11602 if (count) {
11603 if (!uj)
11604 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 11605 get_afi_safi_str(afi, safi, false));
d62a17ae 11606 prefix_bgp_show_prefix_list(vty, afi, name, uj);
11607 } else {
11608 if (uj)
11609 vty_out(vty, "{}\n");
11610 else
11611 vty_out(vty, "No functional output\n");
11612 }
718e3744 11613
d62a17ae 11614 return CMD_SUCCESS;
11615}
11616
11617static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
11618 afi_t afi, safi_t safi,
9f049418 11619 enum bgp_show_type type, bool use_json)
d62a17ae 11620{
8a893163
DW
11621 /* labeled-unicast routes live in the unicast table */
11622 if (safi == SAFI_LABELED_UNICAST)
11623 safi = SAFI_UNICAST;
11624
d62a17ae 11625 if (!peer || !peer->afc[afi][safi]) {
11626 if (use_json) {
11627 json_object *json_no = NULL;
11628 json_no = json_object_new_object();
11629 json_object_string_add(
11630 json_no, "warning",
11631 "No such neighbor or address family");
11632 vty_out(vty, "%s\n",
11633 json_object_to_json_string(json_no));
11634 json_object_free(json_no);
11635 } else
11636 vty_out(vty, "%% No such neighbor or address family\n");
11637 return CMD_WARNING;
11638 }
47fc97cc 11639
d62a17ae 11640 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json);
718e3744 11641}
11642
dba3c1d3
PG
11643DEFUN (show_ip_bgp_flowspec_routes_detailed,
11644 show_ip_bgp_flowspec_routes_detailed_cmd,
11645 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
11646 SHOW_STR
11647 IP_STR
11648 BGP_STR
11649 BGP_INSTANCE_HELP_STR
11650 BGP_AFI_HELP_STR
11651 "SAFI Flowspec\n"
11652 "Detailed information on flowspec entries\n"
11653 JSON_STR)
11654{
11655 afi_t afi = AFI_IP;
11656 safi_t safi = SAFI_UNICAST;
11657 struct bgp *bgp = NULL;
11658 int idx = 0;
9f049418
DS
11659 bool uj = use_json(argc, argv);
11660
11661 if (uj)
11662 argc--;
dba3c1d3
PG
11663
11664 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11665 &bgp, uj);
dba3c1d3
PG
11666 if (!idx)
11667 return CMD_WARNING;
11668
9f049418 11669 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL, uj);
dba3c1d3
PG
11670}
11671
718e3744 11672DEFUN (show_ip_bgp_neighbor_routes,
11673 show_ip_bgp_neighbor_routes_cmd,
4dd6177e 11674 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
30a6a167 11675 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
50ef26d4 11676 SHOW_STR
11677 IP_STR
11678 BGP_STR
8386ac43 11679 BGP_INSTANCE_HELP_STR
4f280b15 11680 BGP_AFI_HELP_STR
4dd6177e 11681 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 11682 "Detailed information on TCP and BGP neighbor connections\n"
11683 "Neighbor to display information about\n"
11684 "Neighbor to display information about\n"
91d37724 11685 "Neighbor on BGP configured interface\n"
2525cf39 11686 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
11687 "Display the dampened routes received from neighbor\n"
11688 "Display routes learned from neighbor\n"
9973d184 11689 JSON_STR)
718e3744 11690{
d62a17ae 11691 char *peerstr = NULL;
11692 struct bgp *bgp = NULL;
11693 afi_t afi = AFI_IP6;
11694 safi_t safi = SAFI_UNICAST;
11695 struct peer *peer;
11696 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 11697 int idx = 0;
9f049418
DS
11698 bool uj = use_json(argc, argv);
11699
11700 if (uj)
11701 argc--;
bb46e94f 11702
d62a17ae 11703 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11704 &bgp, uj);
d62a17ae 11705 if (!idx)
11706 return CMD_WARNING;
c493f2d8 11707
d62a17ae 11708 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11709 argv_find(argv, argc, "neighbors", &idx);
11710 peerstr = argv[++idx]->arg;
8c3deaae 11711
d62a17ae 11712 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 11713 if (!peer)
d62a17ae 11714 return CMD_WARNING;
bb46e94f 11715
d62a17ae 11716 if (argv_find(argv, argc, "flap-statistics", &idx))
11717 sh_type = bgp_show_type_flap_neighbor;
11718 else if (argv_find(argv, argc, "dampened-routes", &idx))
11719 sh_type = bgp_show_type_damp_neighbor;
11720 else if (argv_find(argv, argc, "routes", &idx))
11721 sh_type = bgp_show_type_neighbor;
2525cf39 11722
d62a17ae 11723 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 11724}
6b0655a2 11725
734b349e 11726struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 11727
d62a17ae 11728struct bgp_distance {
11729 /* Distance value for the IP source prefix. */
d7c0a89a 11730 uint8_t distance;
718e3744 11731
d62a17ae 11732 /* Name of the access-list to be matched. */
11733 char *access_list;
718e3744 11734};
11735
4f280b15
LB
11736DEFUN (show_bgp_afi_vpn_rd_route,
11737 show_bgp_afi_vpn_rd_route_cmd,
d114b977 11738 "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
11739 SHOW_STR
11740 BGP_STR
11741 BGP_AFI_HELP_STR
11742 "Address Family modifier\n"
11743 "Display information for a route distinguisher\n"
11744 "Route Distinguisher\n"
7395a2c9
DS
11745 "Network in the BGP routing table to display\n"
11746 "Network in the BGP routing table to display\n"
11747 JSON_STR)
4f280b15 11748{
d62a17ae 11749 int ret;
11750 struct prefix_rd prd;
11751 afi_t afi = AFI_MAX;
11752 int idx = 0;
4f280b15 11753
ff6566f3
DS
11754 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
11755 vty_out(vty, "%% Malformed Address Family\n");
11756 return CMD_WARNING;
11757 }
11758
d62a17ae 11759 ret = str2prefix_rd(argv[5]->arg, &prd);
11760 if (!ret) {
11761 vty_out(vty, "%% Malformed Route Distinguisher\n");
11762 return CMD_WARNING;
11763 }
ff6566f3 11764
d62a17ae 11765 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 11766 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
11767}
11768
d62a17ae 11769static struct bgp_distance *bgp_distance_new(void)
718e3744 11770{
d62a17ae 11771 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 11772}
11773
d62a17ae 11774static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 11775{
d62a17ae 11776 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 11777}
11778
d62a17ae 11779static int bgp_distance_set(struct vty *vty, const char *distance_str,
11780 const char *ip_str, const char *access_list_str)
718e3744 11781{
d62a17ae 11782 int ret;
11783 afi_t afi;
11784 safi_t safi;
11785 struct prefix p;
d7c0a89a 11786 uint8_t distance;
d62a17ae 11787 struct bgp_node *rn;
11788 struct bgp_distance *bdistance;
718e3744 11789
d62a17ae 11790 afi = bgp_node_afi(vty);
11791 safi = bgp_node_safi(vty);
734b349e 11792
d62a17ae 11793 ret = str2prefix(ip_str, &p);
11794 if (ret == 0) {
11795 vty_out(vty, "Malformed prefix\n");
11796 return CMD_WARNING_CONFIG_FAILED;
11797 }
718e3744 11798
d62a17ae 11799 distance = atoi(distance_str);
718e3744 11800
d62a17ae 11801 /* Get BGP distance node. */
11802 rn = bgp_node_get(bgp_distance_table[afi][safi], (struct prefix *)&p);
5b00b40e 11803 bdistance = bgp_node_get_bgp_distance_info(rn);
ca2e160d 11804 if (bdistance)
d62a17ae 11805 bgp_unlock_node(rn);
ca2e160d 11806 else {
d62a17ae 11807 bdistance = bgp_distance_new();
5b00b40e 11808 bgp_node_set_bgp_distance_info(rn, bdistance);
d62a17ae 11809 }
718e3744 11810
d62a17ae 11811 /* Set distance value. */
11812 bdistance->distance = distance;
718e3744 11813
d62a17ae 11814 /* Reset access-list configuration. */
11815 if (bdistance->access_list) {
11816 XFREE(MTYPE_AS_LIST, bdistance->access_list);
11817 bdistance->access_list = NULL;
11818 }
11819 if (access_list_str)
11820 bdistance->access_list =
11821 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 11822
d62a17ae 11823 return CMD_SUCCESS;
718e3744 11824}
11825
d62a17ae 11826static int bgp_distance_unset(struct vty *vty, const char *distance_str,
11827 const char *ip_str, const char *access_list_str)
718e3744 11828{
d62a17ae 11829 int ret;
11830 afi_t afi;
11831 safi_t safi;
11832 struct prefix p;
11833 int distance;
11834 struct bgp_node *rn;
11835 struct bgp_distance *bdistance;
718e3744 11836
d62a17ae 11837 afi = bgp_node_afi(vty);
11838 safi = bgp_node_safi(vty);
734b349e 11839
d62a17ae 11840 ret = str2prefix(ip_str, &p);
11841 if (ret == 0) {
11842 vty_out(vty, "Malformed prefix\n");
11843 return CMD_WARNING_CONFIG_FAILED;
11844 }
718e3744 11845
d62a17ae 11846 rn = bgp_node_lookup(bgp_distance_table[afi][safi],
11847 (struct prefix *)&p);
11848 if (!rn) {
11849 vty_out(vty, "Can't find specified prefix\n");
11850 return CMD_WARNING_CONFIG_FAILED;
11851 }
718e3744 11852
5b00b40e 11853 bdistance = bgp_node_get_bgp_distance_info(rn);
d62a17ae 11854 distance = atoi(distance_str);
1f9a9fff 11855
d62a17ae 11856 if (bdistance->distance != distance) {
11857 vty_out(vty, "Distance does not match configured\n");
11858 return CMD_WARNING_CONFIG_FAILED;
11859 }
718e3744 11860
0a22ddfb 11861 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 11862 bgp_distance_free(bdistance);
718e3744 11863
6f94b685 11864 bgp_node_set_bgp_path_info(rn, NULL);
d62a17ae 11865 bgp_unlock_node(rn);
11866 bgp_unlock_node(rn);
718e3744 11867
d62a17ae 11868 return CMD_SUCCESS;
718e3744 11869}
11870
718e3744 11871/* Apply BGP information to distance method. */
40381db7 11872uint8_t bgp_distance_apply(struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 11873 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 11874{
11875 struct bgp_node *rn;
11876 struct prefix q;
11877 struct peer *peer;
11878 struct bgp_distance *bdistance;
11879 struct access_list *alist;
11880 struct bgp_static *bgp_static;
11881
11882 if (!bgp)
11883 return 0;
11884
40381db7 11885 peer = pinfo->peer;
d62a17ae 11886
7b7d48e5
DS
11887 if (pinfo->attr->distance)
11888 return pinfo->attr->distance;
11889
d62a17ae 11890 /* Check source address. */
11891 sockunion2hostprefix(&peer->su, &q);
11892 rn = bgp_node_match(bgp_distance_table[afi][safi], &q);
11893 if (rn) {
5b00b40e 11894 bdistance = bgp_node_get_bgp_distance_info(rn);
d62a17ae 11895 bgp_unlock_node(rn);
11896
11897 if (bdistance->access_list) {
11898 alist = access_list_lookup(afi, bdistance->access_list);
11899 if (alist
11900 && access_list_apply(alist, p) == FILTER_PERMIT)
11901 return bdistance->distance;
11902 } else
11903 return bdistance->distance;
718e3744 11904 }
718e3744 11905
d62a17ae 11906 /* Backdoor check. */
11907 rn = bgp_node_lookup(bgp->route[afi][safi], p);
11908 if (rn) {
5a8ba9fc 11909 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 11910 bgp_unlock_node(rn);
718e3744 11911
d62a17ae 11912 if (bgp_static->backdoor) {
11913 if (bgp->distance_local[afi][safi])
11914 return bgp->distance_local[afi][safi];
11915 else
11916 return ZEBRA_IBGP_DISTANCE_DEFAULT;
11917 }
718e3744 11918 }
718e3744 11919
d62a17ae 11920 if (peer->sort == BGP_PEER_EBGP) {
11921 if (bgp->distance_ebgp[afi][safi])
11922 return bgp->distance_ebgp[afi][safi];
11923 return ZEBRA_EBGP_DISTANCE_DEFAULT;
11924 } else {
11925 if (bgp->distance_ibgp[afi][safi])
11926 return bgp->distance_ibgp[afi][safi];
11927 return ZEBRA_IBGP_DISTANCE_DEFAULT;
11928 }
718e3744 11929}
11930
11931DEFUN (bgp_distance,
11932 bgp_distance_cmd,
6147e2c6 11933 "distance bgp (1-255) (1-255) (1-255)",
718e3744 11934 "Define an administrative distance\n"
11935 "BGP distance\n"
11936 "Distance for routes external to the AS\n"
11937 "Distance for routes internal to the AS\n"
11938 "Distance for local routes\n")
11939{
d62a17ae 11940 VTY_DECLVAR_CONTEXT(bgp, bgp);
11941 int idx_number = 2;
11942 int idx_number_2 = 3;
11943 int idx_number_3 = 4;
11944 afi_t afi;
11945 safi_t safi;
718e3744 11946
d62a17ae 11947 afi = bgp_node_afi(vty);
11948 safi = bgp_node_safi(vty);
718e3744 11949
d62a17ae 11950 bgp->distance_ebgp[afi][safi] = atoi(argv[idx_number]->arg);
11951 bgp->distance_ibgp[afi][safi] = atoi(argv[idx_number_2]->arg);
11952 bgp->distance_local[afi][safi] = atoi(argv[idx_number_3]->arg);
11953 return CMD_SUCCESS;
718e3744 11954}
11955
11956DEFUN (no_bgp_distance,
11957 no_bgp_distance_cmd,
a636c635 11958 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 11959 NO_STR
11960 "Define an administrative distance\n"
11961 "BGP distance\n"
11962 "Distance for routes external to the AS\n"
11963 "Distance for routes internal to the AS\n"
11964 "Distance for local routes\n")
11965{
d62a17ae 11966 VTY_DECLVAR_CONTEXT(bgp, bgp);
11967 afi_t afi;
11968 safi_t safi;
718e3744 11969
d62a17ae 11970 afi = bgp_node_afi(vty);
11971 safi = bgp_node_safi(vty);
718e3744 11972
d62a17ae 11973 bgp->distance_ebgp[afi][safi] = 0;
11974 bgp->distance_ibgp[afi][safi] = 0;
11975 bgp->distance_local[afi][safi] = 0;
11976 return CMD_SUCCESS;
718e3744 11977}
11978
718e3744 11979
11980DEFUN (bgp_distance_source,
11981 bgp_distance_source_cmd,
6147e2c6 11982 "distance (1-255) A.B.C.D/M",
718e3744 11983 "Define an administrative distance\n"
11984 "Administrative distance\n"
11985 "IP source prefix\n")
11986{
d62a17ae 11987 int idx_number = 1;
11988 int idx_ipv4_prefixlen = 2;
11989 bgp_distance_set(vty, argv[idx_number]->arg,
11990 argv[idx_ipv4_prefixlen]->arg, NULL);
11991 return CMD_SUCCESS;
718e3744 11992}
11993
11994DEFUN (no_bgp_distance_source,
11995 no_bgp_distance_source_cmd,
6147e2c6 11996 "no distance (1-255) A.B.C.D/M",
718e3744 11997 NO_STR
11998 "Define an administrative distance\n"
11999 "Administrative distance\n"
12000 "IP source prefix\n")
12001{
d62a17ae 12002 int idx_number = 2;
12003 int idx_ipv4_prefixlen = 3;
12004 bgp_distance_unset(vty, argv[idx_number]->arg,
12005 argv[idx_ipv4_prefixlen]->arg, NULL);
12006 return CMD_SUCCESS;
718e3744 12007}
12008
12009DEFUN (bgp_distance_source_access_list,
12010 bgp_distance_source_access_list_cmd,
6147e2c6 12011 "distance (1-255) A.B.C.D/M WORD",
718e3744 12012 "Define an administrative distance\n"
12013 "Administrative distance\n"
12014 "IP source prefix\n"
12015 "Access list name\n")
12016{
d62a17ae 12017 int idx_number = 1;
12018 int idx_ipv4_prefixlen = 2;
12019 int idx_word = 3;
12020 bgp_distance_set(vty, argv[idx_number]->arg,
12021 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12022 return CMD_SUCCESS;
718e3744 12023}
12024
12025DEFUN (no_bgp_distance_source_access_list,
12026 no_bgp_distance_source_access_list_cmd,
6147e2c6 12027 "no distance (1-255) A.B.C.D/M WORD",
718e3744 12028 NO_STR
12029 "Define an administrative distance\n"
12030 "Administrative distance\n"
12031 "IP source prefix\n"
12032 "Access list name\n")
12033{
d62a17ae 12034 int idx_number = 2;
12035 int idx_ipv4_prefixlen = 3;
12036 int idx_word = 4;
12037 bgp_distance_unset(vty, argv[idx_number]->arg,
12038 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12039 return CMD_SUCCESS;
718e3744 12040}
6b0655a2 12041
734b349e
MZ
12042DEFUN (ipv6_bgp_distance_source,
12043 ipv6_bgp_distance_source_cmd,
39e92c06 12044 "distance (1-255) X:X::X:X/M",
734b349e
MZ
12045 "Define an administrative distance\n"
12046 "Administrative distance\n"
12047 "IP source prefix\n")
12048{
d62a17ae 12049 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
12050 return CMD_SUCCESS;
734b349e
MZ
12051}
12052
12053DEFUN (no_ipv6_bgp_distance_source,
12054 no_ipv6_bgp_distance_source_cmd,
39e92c06 12055 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
12056 NO_STR
12057 "Define an administrative distance\n"
12058 "Administrative distance\n"
12059 "IP source prefix\n")
12060{
d62a17ae 12061 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
12062 return CMD_SUCCESS;
734b349e
MZ
12063}
12064
12065DEFUN (ipv6_bgp_distance_source_access_list,
12066 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12067 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12068 "Define an administrative distance\n"
12069 "Administrative distance\n"
12070 "IP source prefix\n"
12071 "Access list name\n")
12072{
d62a17ae 12073 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
12074 return CMD_SUCCESS;
734b349e
MZ
12075}
12076
12077DEFUN (no_ipv6_bgp_distance_source_access_list,
12078 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12079 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12080 NO_STR
12081 "Define an administrative distance\n"
12082 "Administrative distance\n"
12083 "IP source prefix\n"
12084 "Access list name\n")
12085{
d62a17ae 12086 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
12087 return CMD_SUCCESS;
734b349e
MZ
12088}
12089
718e3744 12090DEFUN (bgp_damp_set,
12091 bgp_damp_set_cmd,
31500417 12092 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 12093 "BGP Specific commands\n"
12094 "Enable route-flap dampening\n"
12095 "Half-life time for the penalty\n"
12096 "Value to start reusing a route\n"
12097 "Value to start suppressing a route\n"
12098 "Maximum duration to suppress a stable route\n")
12099{
d62a17ae 12100 VTY_DECLVAR_CONTEXT(bgp, bgp);
12101 int idx_half_life = 2;
12102 int idx_reuse = 3;
12103 int idx_suppress = 4;
12104 int idx_max_suppress = 5;
12105 int half = DEFAULT_HALF_LIFE * 60;
12106 int reuse = DEFAULT_REUSE;
12107 int suppress = DEFAULT_SUPPRESS;
12108 int max = 4 * half;
12109
12110 if (argc == 6) {
12111 half = atoi(argv[idx_half_life]->arg) * 60;
12112 reuse = atoi(argv[idx_reuse]->arg);
12113 suppress = atoi(argv[idx_suppress]->arg);
12114 max = atoi(argv[idx_max_suppress]->arg) * 60;
12115 } else if (argc == 3) {
12116 half = atoi(argv[idx_half_life]->arg) * 60;
12117 max = 4 * half;
12118 }
718e3744 12119
d62a17ae 12120 if (suppress < reuse) {
12121 vty_out(vty,
12122 "Suppress value cannot be less than reuse value \n");
12123 return 0;
12124 }
7ebe9748 12125
d62a17ae 12126 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
12127 reuse, suppress, max);
718e3744 12128}
12129
718e3744 12130DEFUN (bgp_damp_unset,
12131 bgp_damp_unset_cmd,
d04c479d 12132 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 12133 NO_STR
12134 "BGP Specific commands\n"
16cedbb0
QY
12135 "Enable route-flap dampening\n"
12136 "Half-life time for the penalty\n"
12137 "Value to start reusing a route\n"
12138 "Value to start suppressing a route\n"
12139 "Maximum duration to suppress a stable route\n")
718e3744 12140{
d62a17ae 12141 VTY_DECLVAR_CONTEXT(bgp, bgp);
12142 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 12143}
12144
718e3744 12145/* Display specified route of BGP table. */
d62a17ae 12146static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
12147 const char *ip_str, afi_t afi, safi_t safi,
12148 struct prefix_rd *prd, int prefix_check)
12149{
12150 int ret;
12151 struct prefix match;
12152 struct bgp_node *rn;
12153 struct bgp_node *rm;
40381db7
DS
12154 struct bgp_path_info *pi;
12155 struct bgp_path_info *pi_temp;
d62a17ae 12156 struct bgp *bgp;
12157 struct bgp_table *table;
12158
12159 /* BGP structure lookup. */
12160 if (view_name) {
12161 bgp = bgp_lookup_by_name(view_name);
12162 if (bgp == NULL) {
12163 vty_out(vty, "%% Can't find BGP instance %s\n",
12164 view_name);
12165 return CMD_WARNING;
12166 }
12167 } else {
12168 bgp = bgp_get_default();
12169 if (bgp == NULL) {
12170 vty_out(vty, "%% No BGP process is configured\n");
12171 return CMD_WARNING;
12172 }
718e3744 12173 }
718e3744 12174
d62a17ae 12175 /* Check IP address argument. */
12176 ret = str2prefix(ip_str, &match);
12177 if (!ret) {
12178 vty_out(vty, "%% address is malformed\n");
12179 return CMD_WARNING;
12180 }
718e3744 12181
d62a17ae 12182 match.family = afi2family(afi);
12183
12184 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
12185 || (safi == SAFI_EVPN)) {
12186 for (rn = bgp_table_top(bgp->rib[AFI_IP][safi]); rn;
12187 rn = bgp_route_next(rn)) {
12188 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
12189 continue;
67009e22
DS
12190 table = bgp_node_get_bgp_table_info(rn);
12191 if (!table)
ea47320b
DL
12192 continue;
12193 if ((rm = bgp_node_match(table, &match)) == NULL)
12194 continue;
d62a17ae 12195
ea47320b
DL
12196 if (!prefix_check
12197 || rm->p.prefixlen == match.prefixlen) {
6f94b685 12198 pi = bgp_node_get_bgp_path_info(rm);
40381db7
DS
12199 while (pi) {
12200 if (pi->extra && pi->extra->damp_info) {
12201 pi_temp = pi->next;
ea47320b 12202 bgp_damp_info_free(
40381db7 12203 pi->extra->damp_info,
a935f597 12204 1, afi, safi);
40381db7 12205 pi = pi_temp;
ea47320b 12206 } else
40381db7 12207 pi = pi->next;
d62a17ae 12208 }
ea47320b
DL
12209 }
12210
12211 bgp_unlock_node(rm);
d62a17ae 12212 }
12213 } else {
12214 if ((rn = bgp_node_match(bgp->rib[afi][safi], &match))
12215 != NULL) {
12216 if (!prefix_check
12217 || rn->p.prefixlen == match.prefixlen) {
6f94b685 12218 pi = bgp_node_get_bgp_path_info(rn);
40381db7
DS
12219 while (pi) {
12220 if (pi->extra && pi->extra->damp_info) {
12221 pi_temp = pi->next;
d62a17ae 12222 bgp_damp_info_free(
40381db7 12223 pi->extra->damp_info,
a935f597 12224 1, afi, safi);
40381db7 12225 pi = pi_temp;
d62a17ae 12226 } else
40381db7 12227 pi = pi->next;
d62a17ae 12228 }
12229 }
12230
12231 bgp_unlock_node(rn);
12232 }
12233 }
718e3744 12234
d62a17ae 12235 return CMD_SUCCESS;
718e3744 12236}
12237
12238DEFUN (clear_ip_bgp_dampening,
12239 clear_ip_bgp_dampening_cmd,
12240 "clear ip bgp dampening",
12241 CLEAR_STR
12242 IP_STR
12243 BGP_STR
12244 "Clear route flap dampening information\n")
12245{
a935f597 12246 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 12247 return CMD_SUCCESS;
718e3744 12248}
12249
12250DEFUN (clear_ip_bgp_dampening_prefix,
12251 clear_ip_bgp_dampening_prefix_cmd,
12252 "clear ip bgp dampening A.B.C.D/M",
12253 CLEAR_STR
12254 IP_STR
12255 BGP_STR
12256 "Clear route flap dampening information\n"
0c7b1b01 12257 "IPv4 prefix\n")
718e3744 12258{
d62a17ae 12259 int idx_ipv4_prefixlen = 4;
12260 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
12261 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 12262}
12263
12264DEFUN (clear_ip_bgp_dampening_address,
12265 clear_ip_bgp_dampening_address_cmd,
12266 "clear ip bgp dampening A.B.C.D",
12267 CLEAR_STR
12268 IP_STR
12269 BGP_STR
12270 "Clear route flap dampening information\n"
12271 "Network to clear damping information\n")
12272{
d62a17ae 12273 int idx_ipv4 = 4;
12274 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
12275 SAFI_UNICAST, NULL, 0);
718e3744 12276}
12277
12278DEFUN (clear_ip_bgp_dampening_address_mask,
12279 clear_ip_bgp_dampening_address_mask_cmd,
12280 "clear ip bgp dampening A.B.C.D A.B.C.D",
12281 CLEAR_STR
12282 IP_STR
12283 BGP_STR
12284 "Clear route flap dampening information\n"
12285 "Network to clear damping information\n"
12286 "Network mask\n")
12287{
d62a17ae 12288 int idx_ipv4 = 4;
12289 int idx_ipv4_2 = 5;
12290 int ret;
12291 char prefix_str[BUFSIZ];
718e3744 12292
d62a17ae 12293 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
12294 prefix_str);
12295 if (!ret) {
12296 vty_out(vty, "%% Inconsistent address and mask\n");
12297 return CMD_WARNING;
12298 }
718e3744 12299
d62a17ae 12300 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
12301 NULL, 0);
718e3744 12302}
6b0655a2 12303
e3b78da8 12304static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
12305{
12306 struct vty *vty = arg;
e3b78da8 12307 struct peer *peer = bucket->data;
825d9834
DS
12308 char buf[SU_ADDRSTRLEN];
12309
12310 vty_out(vty, "\tPeer: %s %s\n", peer->host,
12311 sockunion2str(&peer->su, buf, sizeof(buf)));
12312}
12313
12314DEFUN (show_bgp_peerhash,
12315 show_bgp_peerhash_cmd,
12316 "show bgp peerhash",
12317 SHOW_STR
12318 BGP_STR
12319 "Display information about the BGP peerhash\n")
12320{
12321 struct list *instances = bm->bgp;
12322 struct listnode *node;
12323 struct bgp *bgp;
12324
12325 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
12326 vty_out(vty, "BGP: %s\n", bgp->name);
12327 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
12328 vty);
12329 }
12330
12331 return CMD_SUCCESS;
12332}
12333
587ff0fd 12334/* also used for encap safi */
2b791107
DL
12335static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
12336 afi_t afi, safi_t safi)
d62a17ae 12337{
12338 struct bgp_node *prn;
12339 struct bgp_node *rn;
12340 struct bgp_table *table;
12341 struct prefix *p;
12342 struct prefix_rd *prd;
12343 struct bgp_static *bgp_static;
12344 mpls_label_t label;
12345 char buf[SU_ADDRSTRLEN];
12346 char rdbuf[RD_ADDRSTRLEN];
12347
12348 /* Network configuration. */
12349 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b 12350 prn = bgp_route_next(prn)) {
67009e22
DS
12351 table = bgp_node_get_bgp_table_info(prn);
12352 if (!table)
ea47320b 12353 continue;
d62a17ae 12354
60466a63 12355 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5a8ba9fc 12356 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12357 if (bgp_static == NULL)
ea47320b 12358 continue;
d62a17ae 12359
ea47320b
DL
12360 p = &rn->p;
12361 prd = (struct prefix_rd *)&prn->p;
d62a17ae 12362
ea47320b 12363 /* "network" configuration display. */
06b9f471 12364 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
12365 label = decode_label(&bgp_static->label);
12366
12367 vty_out(vty, " network %s/%d rd %s",
12368 inet_ntop(p->family, &p->u.prefix, buf,
12369 SU_ADDRSTRLEN),
12370 p->prefixlen, rdbuf);
12371 if (safi == SAFI_MPLS_VPN)
12372 vty_out(vty, " label %u", label);
12373
12374 if (bgp_static->rmap.name)
12375 vty_out(vty, " route-map %s",
12376 bgp_static->rmap.name);
e2a86ad9
DS
12377
12378 if (bgp_static->backdoor)
12379 vty_out(vty, " backdoor");
12380
ea47320b
DL
12381 vty_out(vty, "\n");
12382 }
12383 }
d62a17ae 12384}
12385
2b791107
DL
12386static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
12387 afi_t afi, safi_t safi)
d62a17ae 12388{
12389 struct bgp_node *prn;
12390 struct bgp_node *rn;
12391 struct bgp_table *table;
12392 struct prefix *p;
12393 struct prefix_rd *prd;
12394 struct bgp_static *bgp_static;
ff44f570 12395 char buf[PREFIX_STRLEN * 2];
d62a17ae 12396 char buf2[SU_ADDRSTRLEN];
12397 char rdbuf[RD_ADDRSTRLEN];
12398
12399 /* Network configuration. */
12400 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b 12401 prn = bgp_route_next(prn)) {
67009e22
DS
12402 table = bgp_node_get_bgp_table_info(prn);
12403 if (!table)
ea47320b 12404 continue;
d62a17ae 12405
60466a63 12406 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5a8ba9fc 12407 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12408 if (bgp_static == NULL)
ea47320b 12409 continue;
d62a17ae 12410
ea47320b
DL
12411 char *macrouter = NULL;
12412 char *esi = NULL;
d62a17ae 12413
ea47320b
DL
12414 if (bgp_static->router_mac)
12415 macrouter = prefix_mac2str(
12416 bgp_static->router_mac, NULL, 0);
12417 if (bgp_static->eth_s_id)
12418 esi = esi2str(bgp_static->eth_s_id);
12419 p = &rn->p;
12420 prd = (struct prefix_rd *)&prn->p;
d62a17ae 12421
ea47320b 12422 /* "network" configuration display. */
06b9f471 12423 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
12424 if (p->u.prefix_evpn.route_type == 5) {
12425 char local_buf[PREFIX_STRLEN];
3714a385 12426 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
12427 struct prefix_evpn *)p)
12428 ? AF_INET
12429 : AF_INET6;
3714a385 12430 inet_ntop(family,
12431 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a
PZ
12432 local_buf, PREFIX_STRLEN);
12433 sprintf(buf, "%s/%u", local_buf,
3714a385 12434 p->u.prefix_evpn.prefix_addr.ip_prefix_length);
197cb530
PG
12435 } else {
12436 prefix2str(p, buf, sizeof(buf));
12437 }
ea47320b 12438
a4d82a8a
PZ
12439 if (bgp_static->gatewayIp.family == AF_INET
12440 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
12441 inet_ntop(bgp_static->gatewayIp.family,
12442 &bgp_static->gatewayIp.u.prefix, buf2,
12443 sizeof(buf2));
ea47320b 12444 vty_out(vty,
7bcc8dac 12445 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 12446 buf, rdbuf,
12447 p->u.prefix_evpn.prefix_addr.eth_tag,
60466a63 12448 decode_label(&bgp_static->label), esi, buf2,
ea47320b
DL
12449 macrouter);
12450
0a22ddfb
QY
12451 XFREE(MTYPE_TMP, macrouter);
12452 XFREE(MTYPE_TMP, esi);
ea47320b
DL
12453 }
12454 }
3da6fcd5
PG
12455}
12456
718e3744 12457/* Configuration of static route announcement and aggregate
12458 information. */
2b791107
DL
12459void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
12460 safi_t safi)
d62a17ae 12461{
12462 struct bgp_node *rn;
12463 struct prefix *p;
12464 struct bgp_static *bgp_static;
12465 struct bgp_aggregate *bgp_aggregate;
12466 char buf[SU_ADDRSTRLEN];
12467
2b791107
DL
12468 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
12469 bgp_config_write_network_vpn(vty, bgp, afi, safi);
12470 return;
12471 }
d62a17ae 12472
2b791107
DL
12473 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
12474 bgp_config_write_network_evpn(vty, bgp, afi, safi);
12475 return;
12476 }
d62a17ae 12477
12478 /* Network configuration. */
12479 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
ea47320b 12480 rn = bgp_route_next(rn)) {
5a8ba9fc 12481 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12482 if (bgp_static == NULL)
ea47320b 12483 continue;
d62a17ae 12484
ea47320b 12485 p = &rn->p;
d62a17ae 12486
d8a9922d
DS
12487 vty_out(vty, " network %s/%d",
12488 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
12489 p->prefixlen);
d62a17ae 12490
ea47320b
DL
12491 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
12492 vty_out(vty, " label-index %u",
12493 bgp_static->label_index);
d62a17ae 12494
ea47320b
DL
12495 if (bgp_static->rmap.name)
12496 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
12497
12498 if (bgp_static->backdoor)
12499 vty_out(vty, " backdoor");
718e3744 12500
ea47320b
DL
12501 vty_out(vty, "\n");
12502 }
12503
d62a17ae 12504 /* Aggregate-address configuration. */
12505 for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn;
ea47320b 12506 rn = bgp_route_next(rn)) {
b613a918 12507 bgp_aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 12508 if (bgp_aggregate == NULL)
ea47320b 12509 continue;
d62a17ae 12510
ea47320b 12511 p = &rn->p;
d62a17ae 12512
d8a9922d
DS
12513 vty_out(vty, " aggregate-address %s/%d",
12514 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
12515 p->prefixlen);
d62a17ae 12516
ea47320b
DL
12517 if (bgp_aggregate->as_set)
12518 vty_out(vty, " as-set");
d62a17ae 12519
ea47320b
DL
12520 if (bgp_aggregate->summary_only)
12521 vty_out(vty, " summary-only");
718e3744 12522
20894f50
DA
12523 if (bgp_aggregate->rmap.name)
12524 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
12525
ea47320b
DL
12526 vty_out(vty, "\n");
12527 }
d62a17ae 12528}
734b349e 12529
2b791107 12530void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 12531 safi_t safi)
d62a17ae 12532{
12533 struct bgp_node *rn;
12534 struct bgp_distance *bdistance;
12535
12536 /* Distance configuration. */
12537 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
12538 && bgp->distance_local[afi][safi]
12539 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
12540 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
12541 || bgp->distance_local[afi][safi]
12542 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 12543 vty_out(vty, " distance bgp %d %d %d\n",
12544 bgp->distance_ebgp[afi][safi],
12545 bgp->distance_ibgp[afi][safi],
12546 bgp->distance_local[afi][safi]);
12547 }
734b349e 12548
d62a17ae 12549 for (rn = bgp_table_top(bgp_distance_table[afi][safi]); rn;
ca2e160d 12550 rn = bgp_route_next(rn)) {
5b00b40e 12551 bdistance = bgp_node_get_bgp_distance_info(rn);
ca2e160d 12552 if (bdistance != NULL) {
d62a17ae 12553 char buf[PREFIX_STRLEN];
12554
d62a17ae 12555 vty_out(vty, " distance %d %s %s\n",
12556 bdistance->distance,
12557 prefix2str(&rn->p, buf, sizeof(buf)),
12558 bdistance->access_list ? bdistance->access_list
12559 : "");
12560 }
ca2e160d 12561 }
718e3744 12562}
12563
12564/* Allocate routing table structure and install commands. */
d62a17ae 12565void bgp_route_init(void)
12566{
12567 afi_t afi;
12568 safi_t safi;
12569
12570 /* Init BGP distance table. */
05c7a1cc 12571 FOREACH_AFI_SAFI (afi, safi)
960035b2 12572 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 12573
12574 /* IPv4 BGP commands. */
12575 install_element(BGP_NODE, &bgp_table_map_cmd);
12576 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 12577 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 12578
12579 install_element(BGP_NODE, &aggregate_address_cmd);
12580 install_element(BGP_NODE, &aggregate_address_mask_cmd);
12581 install_element(BGP_NODE, &no_aggregate_address_cmd);
12582 install_element(BGP_NODE, &no_aggregate_address_mask_cmd);
12583
12584 /* IPv4 unicast configuration. */
12585 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
12586 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 12587 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 12588
12589 install_element(BGP_IPV4_NODE, &aggregate_address_cmd);
12590 install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd);
12591 install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd);
12592 install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
12593
12594 /* IPv4 multicast configuration. */
12595 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
12596 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 12597 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
d62a17ae 12598 install_element(BGP_IPV4M_NODE, &aggregate_address_cmd);
12599 install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
12600 install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd);
12601 install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
12602
12603 /* IPv4 labeled-unicast configuration. */
12604 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
12605 install_element(VIEW_NODE, &show_ip_bgp_cmd);
7b2ff250 12606 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 12607 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
12608 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
12609
12610 install_element(VIEW_NODE,
12611 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
12612 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
12613 install_element(VIEW_NODE,
12614 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 12615#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 12616 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 12617#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 12618 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
12619 install_element(VIEW_NODE,
44c69747 12620 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 12621
d62a17ae 12622 /* BGP dampening clear commands */
12623 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
12624 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 12625
d62a17ae 12626 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
12627 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
12628
12629 /* prefix count */
12630 install_element(ENABLE_NODE,
12631 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 12632#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 12633 install_element(ENABLE_NODE,
12634 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 12635#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 12636
d62a17ae 12637 /* New config IPv6 BGP commands. */
12638 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
12639 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 12640 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 12641
12642 install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
12643 install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
12644
12645 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 12646
d62a17ae 12647 install_element(BGP_NODE, &bgp_distance_cmd);
12648 install_element(BGP_NODE, &no_bgp_distance_cmd);
12649 install_element(BGP_NODE, &bgp_distance_source_cmd);
12650 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
12651 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
12652 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
12653 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
12654 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
12655 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
12656 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
12657 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
12658 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
12659 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
12660 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
12661 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
12662 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
12663 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
12664 install_element(BGP_IPV4M_NODE,
12665 &no_bgp_distance_source_access_list_cmd);
12666 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
12667 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
12668 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
12669 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
12670 install_element(BGP_IPV6_NODE,
12671 &ipv6_bgp_distance_source_access_list_cmd);
12672 install_element(BGP_IPV6_NODE,
12673 &no_ipv6_bgp_distance_source_access_list_cmd);
12674 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
12675 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
12676 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
12677 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
12678 install_element(BGP_IPV6M_NODE,
12679 &ipv6_bgp_distance_source_access_list_cmd);
12680 install_element(BGP_IPV6M_NODE,
12681 &no_ipv6_bgp_distance_source_access_list_cmd);
12682
12683 install_element(BGP_NODE, &bgp_damp_set_cmd);
12684 install_element(BGP_NODE, &bgp_damp_unset_cmd);
12685 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
12686 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
12687
12688 /* IPv4 Multicast Mode */
12689 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
12690 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
12691
12692 /* Large Communities */
12693 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
12694 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
12695
12696 /* show bgp ipv4 flowspec detailed */
12697 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
12698
825d9834 12699 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 12700}
12701
12702void bgp_route_finish(void)
12703{
12704 afi_t afi;
12705 safi_t safi;
12706
05c7a1cc
QY
12707 FOREACH_AFI_SAFI (afi, safi) {
12708 bgp_table_unlock(bgp_distance_table[afi][safi]);
12709 bgp_distance_table[afi][safi] = NULL;
12710 }
228da428 12711}