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