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