]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #5241 from sworleys/SA-NHG
[mirror_frr.git] / bgpd / bgp_route.c
CommitLineData
718e3744 1/* BGP routing information
896014f4
DL
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
718e3744 21
22#include <zebra.h>
8d0ab76d 23#include <math.h>
718e3744 24
2618a52e 25#include "printfrr.h"
718e3744 26#include "prefix.h"
27#include "linklist.h"
28#include "memory.h"
29#include "command.h"
30#include "stream.h"
31#include "filter.h"
718e3744 32#include "log.h"
33#include "routemap.h"
34#include "buffer.h"
35#include "sockunion.h"
36#include "plist.h"
37#include "thread.h"
200df115 38#include "workqueue.h"
3f9c7369 39#include "queue.h"
6e919709 40#include "memory.h"
4dcadbef 41#include "lib/json.h"
d8d084d9 42#include "lib_errors.h"
718e3744 43
44#include "bgpd/bgpd.h"
45#include "bgpd/bgp_table.h"
46#include "bgpd/bgp_route.h"
47#include "bgpd/bgp_attr.h"
48#include "bgpd/bgp_debug.h"
14454c9f 49#include "bgpd/bgp_errors.h"
718e3744 50#include "bgpd/bgp_aspath.h"
51#include "bgpd/bgp_regex.h"
52#include "bgpd/bgp_community.h"
53#include "bgpd/bgp_ecommunity.h"
57d187bc 54#include "bgpd/bgp_lcommunity.h"
718e3744 55#include "bgpd/bgp_clist.h"
56#include "bgpd/bgp_packet.h"
57#include "bgpd/bgp_filter.h"
58#include "bgpd/bgp_fsm.h"
59#include "bgpd/bgp_mplsvpn.h"
60#include "bgpd/bgp_nexthop.h"
61#include "bgpd/bgp_damp.h"
62#include "bgpd/bgp_advertise.h"
63#include "bgpd/bgp_zebra.h"
0a486e5f 64#include "bgpd/bgp_vty.h"
96450faf 65#include "bgpd/bgp_mpath.h"
fc9a856f 66#include "bgpd/bgp_nht.h"
3f9c7369 67#include "bgpd/bgp_updgrp.h"
cd1964ff 68#include "bgpd/bgp_label.h"
dcc68b5e 69#include "bgpd/bgp_addpath.h"
4e802e66 70#include "bgpd/bgp_mac.h"
718e3744 71
65efcfce 72#if ENABLE_BGP_VNC
f8b6f499
LB
73#include "bgpd/rfapi/rfapi_backend.h"
74#include "bgpd/rfapi/vnc_import_bgp.h"
75#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 76#endif
aee875b5
PG
77#include "bgpd/bgp_encap_types.h"
78#include "bgpd/bgp_encap_tlv.h"
684a7227 79#include "bgpd/bgp_evpn.h"
3da6fcd5 80#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 81#include "bgpd/bgp_flowspec.h"
98a9dbc7 82#include "bgpd/bgp_flowspec_util.h"
45918cfb 83#include "bgpd/bgp_pbr.h"
65efcfce 84
e2a86ad9
DS
85#ifndef VTYSH_EXTRACT_PL
86#include "bgpd/bgp_route_clippy.c"
87#endif
aee875b5 88
718e3744 89/* Extern from bgp_dump.c */
dde72586
SH
90extern const char *bgp_origin_str[];
91extern const char *bgp_origin_long_str[];
6b0655a2 92
b7d08f5a 93/* PMSI strings. */
94#define PMSI_TNLTYPE_STR_NO_INFO "No info"
95#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
96static const struct message bgp_pmsi_tnltype_str[] = {
97 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
98 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
99 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
100 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
101 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
102 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
103 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
104 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 105 {0}
106};
b7d08f5a 107
9df8b37c
PZ
108#define VRFID_NONE_STR "-"
109
4a11bf2c
DL
110DEFINE_HOOK(bgp_process,
111 (struct bgp *bgp, afi_t afi, safi_t safi,
112 struct bgp_node *bn, struct peer *peer, bool withdraw),
113 (bgp, afi, safi, bn, peer, withdraw))
114
115
d62a17ae 116struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
117 safi_t safi, struct prefix *p,
118 struct prefix_rd *prd)
119{
120 struct bgp_node *rn;
121 struct bgp_node *prn = NULL;
122
123 assert(table);
124 if (!table)
125 return NULL;
126
127 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
128 || (safi == SAFI_EVPN)) {
129 prn = bgp_node_get(table, (struct prefix *)prd);
130
67009e22
DS
131 if (!bgp_node_has_bgp_path_info_data(prn))
132 bgp_node_set_bgp_table_info(
133 prn, bgp_table_init(table->bgp, afi, safi));
d62a17ae 134 else
135 bgp_unlock_node(prn);
67009e22 136 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 137 }
718e3744 138
d62a17ae 139 rn = bgp_node_get(table, p);
718e3744 140
d62a17ae 141 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
142 || (safi == SAFI_EVPN))
143 rn->prn = prn;
718e3744 144
d62a17ae 145 return rn;
718e3744 146}
6b0655a2 147
d62a17ae 148struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
149 safi_t safi, struct prefix *p,
150 struct prefix_rd *prd)
128ea8ab 151{
d62a17ae 152 struct bgp_node *rn;
153 struct bgp_node *prn = NULL;
128ea8ab 154
d62a17ae 155 if (!table)
156 return NULL;
128ea8ab 157
d62a17ae 158 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
159 || (safi == SAFI_EVPN)) {
160 prn = bgp_node_lookup(table, (struct prefix *)prd);
161 if (!prn)
162 return NULL;
128ea8ab 163
6f94b685 164 if (!bgp_node_has_bgp_path_info_data(prn)) {
d62a17ae 165 bgp_unlock_node(prn);
166 return NULL;
167 }
128ea8ab 168
67009e22 169 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 170 }
128ea8ab 171
d62a17ae 172 rn = bgp_node_lookup(table, p);
128ea8ab 173
d62a17ae 174 return rn;
128ea8ab 175}
176
18ee8310
DS
177/* Allocate bgp_path_info_extra */
178static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 179{
4b7e6066
DS
180 struct bgp_path_info_extra *new;
181 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
182 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
183 new->label[0] = MPLS_INVALID_LABEL;
184 new->num_labels = 0;
3e3708cb
PG
185 new->bgp_fs_pbr = NULL;
186 new->bgp_fs_iprule = NULL;
d62a17ae 187 return new;
fb982c25
PJ
188}
189
a2e219fe 190void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 191{
4b7e6066 192 struct bgp_path_info_extra *e;
d62a17ae 193
c93a3b77
DS
194 if (!extra || !*extra)
195 return;
d62a17ae 196
c93a3b77
DS
197 e = *extra;
198 if (e->damp_info)
a935f597
DA
199 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
200 e->damp_info->safi);
d62a17ae 201
c93a3b77
DS
202 e->damp_info = NULL;
203 if (e->parent) {
40381db7 204 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 205
40381db7 206 if (bpi->net) {
0e70e6c8
DL
207 /* FIXME: since multiple e may have the same e->parent
208 * and e->parent->net is holding a refcount for each
209 * of them, we need to do some fudging here.
210 *
40381db7
DS
211 * WARNING: if bpi->net->lock drops to 0, bpi may be
212 * freed as well (because bpi->net was holding the
213 * last reference to bpi) => write after free!
0e70e6c8
DL
214 */
215 unsigned refcount;
216
40381db7
DS
217 bpi = bgp_path_info_lock(bpi);
218 refcount = bpi->net->lock - 1;
219 bgp_unlock_node((struct bgp_node *)bpi->net);
0e70e6c8 220 if (!refcount)
40381db7
DS
221 bpi->net = NULL;
222 bgp_path_info_unlock(bpi);
0e70e6c8 223 }
18ee8310 224 bgp_path_info_unlock(e->parent);
c93a3b77 225 e->parent = NULL;
d62a17ae 226 }
c93a3b77
DS
227
228 if (e->bgp_orig)
229 bgp_unlock(e->bgp_orig);
c26edcda 230
ce3c0614
PG
231 if ((*extra)->bgp_fs_iprule)
232 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 233 if ((*extra)->bgp_fs_pbr)
6a154c88 234 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77
DS
235 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
236
237 *extra = NULL;
fb982c25
PJ
238}
239
18ee8310
DS
240/* Get bgp_path_info extra information for the given bgp_path_info, lazy
241 * allocated if required.
fb982c25 242 */
40381db7 243struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 244{
40381db7
DS
245 if (!pi->extra)
246 pi->extra = bgp_path_info_extra_new();
247 return pi->extra;
fb982c25
PJ
248}
249
718e3744 250/* Free bgp route information. */
9b6d8fcf 251static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 252{
05864da7 253 bgp_attr_unintern(&path->attr);
fb018d25 254
9b6d8fcf
DS
255 bgp_unlink_nexthop(path);
256 bgp_path_info_extra_free(&path->extra);
257 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
258 if (path->net)
259 bgp_addpath_free_info_data(&path->tx_addpath,
260 &path->net->tx_addpath);
718e3744 261
9b6d8fcf 262 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 263
9b6d8fcf 264 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 265}
266
9b6d8fcf 267struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 268{
9b6d8fcf
DS
269 path->lock++;
270 return path;
200df115 271}
272
9b6d8fcf 273struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 274{
9b6d8fcf
DS
275 assert(path && path->lock > 0);
276 path->lock--;
d62a17ae 277
9b6d8fcf 278 if (path->lock == 0) {
200df115 279#if 0
280 zlog_debug ("%s: unlocked and freeing", __func__);
281 zlog_backtrace (LOG_DEBUG);
282#endif
9b6d8fcf 283 bgp_path_info_free(path);
d62a17ae 284 return NULL;
285 }
200df115 286
287#if 0
9b6d8fcf 288 if (path->lock == 1)
200df115 289 {
290 zlog_debug ("%s: unlocked to 1", __func__);
291 zlog_backtrace (LOG_DEBUG);
292 }
293#endif
d62a17ae 294
9b6d8fcf 295 return path;
200df115 296}
297
40381db7 298void bgp_path_info_add(struct bgp_node *rn, struct bgp_path_info *pi)
718e3744 299{
4b7e6066 300 struct bgp_path_info *top;
718e3744 301
6f94b685 302 top = bgp_node_get_bgp_path_info(rn);
d62a17ae 303
6f94b685 304 pi->next = top;
40381db7 305 pi->prev = NULL;
d62a17ae 306 if (top)
40381db7 307 top->prev = pi;
6f94b685 308 bgp_node_set_bgp_path_info(rn, pi);
d62a17ae 309
40381db7 310 bgp_path_info_lock(pi);
d62a17ae 311 bgp_lock_node(rn);
40381db7 312 peer_lock(pi->peer); /* bgp_path_info peer reference */
718e3744 313}
314
d62a17ae 315/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 316 completion callback *only* */
40381db7 317void bgp_path_info_reap(struct bgp_node *rn, struct bgp_path_info *pi)
718e3744 318{
40381db7
DS
319 if (pi->next)
320 pi->next->prev = pi->prev;
321 if (pi->prev)
322 pi->prev->next = pi->next;
d62a17ae 323 else
6f94b685 324 bgp_node_set_bgp_path_info(rn, pi->next);
d62a17ae 325
40381db7
DS
326 bgp_path_info_mpath_dequeue(pi);
327 bgp_path_info_unlock(pi);
d62a17ae 328 bgp_unlock_node(rn);
718e3744 329}
330
40381db7 331void bgp_path_info_delete(struct bgp_node *rn, struct bgp_path_info *pi)
b40d939b 332{
40381db7 333 bgp_path_info_set_flag(rn, pi, BGP_PATH_REMOVED);
d62a17ae 334 /* set of previous already took care of pcount */
40381db7 335 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 336}
337
18ee8310 338/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
339 called when a route is deleted and then quickly re-added before the
340 deletion has been processed */
40381db7 341void bgp_path_info_restore(struct bgp_node *rn, struct bgp_path_info *pi)
8d45210e 342{
40381db7 343 bgp_path_info_unset_flag(rn, pi, BGP_PATH_REMOVED);
d62a17ae 344 /* unset of previous already took care of pcount */
40381db7 345 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
346}
347
d62a17ae 348/* Adjust pcount as required */
40381db7 349static void bgp_pcount_adjust(struct bgp_node *rn, struct bgp_path_info *pi)
1a392d46 350{
d62a17ae 351 struct bgp_table *table;
67174041 352
d62a17ae 353 assert(rn && bgp_node_table(rn));
40381db7 354 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 355
d62a17ae 356 table = bgp_node_table(rn);
67174041 357
40381db7 358 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 359 return;
360
40381db7
DS
361 if (!BGP_PATH_COUNTABLE(pi)
362 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 363
40381db7 364 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 365
366 /* slight hack, but more robust against errors. */
40381db7
DS
367 if (pi->peer->pcount[table->afi][table->safi])
368 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 369 else
450971aa 370 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 371 "Asked to decrement 0 prefix count for peer");
40381db7
DS
372 } else if (BGP_PATH_COUNTABLE(pi)
373 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
374 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
375 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 376 }
1a392d46
PJ
377}
378
40381db7
DS
379static int bgp_label_index_differs(struct bgp_path_info *pi1,
380 struct bgp_path_info *pi2)
28d58fd7 381{
40381db7 382 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 383}
1a392d46 384
18ee8310 385/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
386 * This is here primarily to keep prefix-count in check.
387 */
40381db7 388void bgp_path_info_set_flag(struct bgp_node *rn, struct bgp_path_info *pi,
18ee8310 389 uint32_t flag)
1a392d46 390{
40381db7 391 SET_FLAG(pi->flags, flag);
d62a17ae 392
393 /* early bath if we know it's not a flag that changes countability state
394 */
395 if (!CHECK_FLAG(flag,
1defdda8 396 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 397 return;
398
40381db7 399 bgp_pcount_adjust(rn, pi);
1a392d46
PJ
400}
401
40381db7 402void bgp_path_info_unset_flag(struct bgp_node *rn, struct bgp_path_info *pi,
18ee8310 403 uint32_t flag)
1a392d46 404{
40381db7 405 UNSET_FLAG(pi->flags, flag);
d62a17ae 406
407 /* early bath if we know it's not a flag that changes countability state
408 */
409 if (!CHECK_FLAG(flag,
1defdda8 410 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 411 return;
412
40381db7 413 bgp_pcount_adjust(rn, pi);
1a392d46
PJ
414}
415
718e3744 416/* Get MED value. If MED value is missing and "bgp bestpath
417 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 418static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 419{
420 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
421 return attr->med;
422 else {
423 if (bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST))
424 return BGP_MED_MAX;
425 else
426 return 0;
427 }
718e3744 428}
429
40381db7 430void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf)
2ec1e66f 431{
40381db7
DS
432 if (pi->addpath_rx_id)
433 sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
434 pi->addpath_rx_id);
d62a17ae 435 else
40381db7 436 sprintf(buf, "path %s", pi->peer->host);
d62a17ae 437}
9fbdd100 438
d62a17ae 439/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
440 */
18ee8310
DS
441static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
442 struct bgp_path_info *exist, int *paths_eq,
443 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
444 char *pfx_buf, afi_t afi, safi_t safi,
445 enum bgp_path_selection_reason *reason)
d62a17ae 446{
447 struct attr *newattr, *existattr;
448 bgp_peer_sort_t new_sort;
449 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
450 uint32_t new_pref;
451 uint32_t exist_pref;
452 uint32_t new_med;
453 uint32_t exist_med;
454 uint32_t new_weight;
455 uint32_t exist_weight;
d62a17ae 456 uint32_t newm, existm;
457 struct in_addr new_id;
458 struct in_addr exist_id;
459 int new_cluster;
460 int exist_cluster;
461 int internal_as_route;
462 int confed_as_route;
04d14c8b 463 int ret = 0;
d62a17ae 464 char new_buf[PATH_ADDPATH_STR_BUFFER];
465 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
466 uint32_t new_mm_seq;
467 uint32_t exist_mm_seq;
6d8c603a 468 int nh_cmp;
d62a17ae 469
470 *paths_eq = 0;
471
472 /* 0. Null check. */
473 if (new == NULL) {
fdf81fa0 474 *reason = bgp_path_selection_none;
d62a17ae 475 if (debug)
476 zlog_debug("%s: new is NULL", pfx_buf);
477 return 0;
478 }
2ec1e66f 479
d62a17ae 480 if (debug)
18ee8310 481 bgp_path_info_path_with_addpath_rx_str(new, new_buf);
718e3744 482
d62a17ae 483 if (exist == NULL) {
fdf81fa0 484 *reason = bgp_path_selection_first;
d62a17ae 485 if (debug)
486 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
487 new_buf);
488 return 1;
489 }
2ec1e66f 490
d62a17ae 491 if (debug) {
18ee8310 492 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
d62a17ae 493 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
494 pfx_buf, new_buf, new->flags, exist_buf,
495 exist->flags);
496 }
8ff56318 497
d62a17ae 498 newattr = new->attr;
499 existattr = exist->attr;
500
501 /* For EVPN routes, we cannot just go by local vs remote, we have to
502 * look at the MAC mobility sequence number, if present.
503 */
504 if (safi == SAFI_EVPN) {
505 /* This is an error condition described in RFC 7432 Section
506 * 15.2. The RFC
507 * states that in this scenario "the PE MUST alert the operator"
508 * but it
509 * does not state what other action to take. In order to provide
510 * some
511 * consistency in this scenario we are going to prefer the path
512 * with the
513 * sticky flag.
514 */
515 if (newattr->sticky != existattr->sticky) {
516 if (!debug) {
517 prefix2str(&new->net->p, pfx_buf,
518 sizeof(*pfx_buf)
519 * PREFIX2STR_BUFFER);
18ee8310
DS
520 bgp_path_info_path_with_addpath_rx_str(new,
521 new_buf);
522 bgp_path_info_path_with_addpath_rx_str(
523 exist, exist_buf);
d62a17ae 524 }
525
526 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 527 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
528 if (debug)
529 zlog_debug(
530 "%s: %s wins over %s due to sticky MAC flag",
531 pfx_buf, new_buf, exist_buf);
d62a17ae 532 return 1;
533 }
534
535 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 536 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
537 if (debug)
538 zlog_debug(
539 "%s: %s loses to %s due to sticky MAC flag",
540 pfx_buf, new_buf, exist_buf);
d62a17ae 541 return 0;
542 }
543 }
128ea8ab 544
d62a17ae 545 new_mm_seq = mac_mobility_seqnum(newattr);
546 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 547
d62a17ae 548 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 549 *reason = bgp_path_selection_evpn_seq;
d62a17ae 550 if (debug)
551 zlog_debug(
552 "%s: %s wins over %s due to MM seq %u > %u",
553 pfx_buf, new_buf, exist_buf, new_mm_seq,
554 exist_mm_seq);
555 return 1;
556 }
8ff56318 557
d62a17ae 558 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 559 *reason = bgp_path_selection_evpn_seq;
d62a17ae 560 if (debug)
561 zlog_debug(
562 "%s: %s loses to %s due to MM seq %u < %u",
563 pfx_buf, new_buf, exist_buf, new_mm_seq,
564 exist_mm_seq);
565 return 0;
566 }
6d8c603a
AK
567
568 /*
569 * if sequence numbers are the same path with the lowest IP
570 * wins
571 */
572 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
573 if (nh_cmp < 0) {
fdf81fa0 574 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
575 if (debug)
576 zlog_debug(
577 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
578 pfx_buf, new_buf, exist_buf, new_mm_seq,
579 inet_ntoa(new->attr->nexthop));
580 return 1;
581 }
582 if (nh_cmp > 0) {
fdf81fa0 583 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
584 if (debug)
585 zlog_debug(
586 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
587 pfx_buf, new_buf, exist_buf, new_mm_seq,
588 inet_ntoa(new->attr->nexthop));
589 return 0;
590 }
d62a17ae 591 }
9fbdd100 592
d62a17ae 593 /* 1. Weight check. */
d62a17ae 594 new_weight = newattr->weight;
595 exist_weight = existattr->weight;
8ff56318 596
d62a17ae 597 if (new_weight > exist_weight) {
fdf81fa0 598 *reason = bgp_path_selection_weight;
d62a17ae 599 if (debug)
600 zlog_debug("%s: %s wins over %s due to weight %d > %d",
601 pfx_buf, new_buf, exist_buf, new_weight,
602 exist_weight);
603 return 1;
604 }
718e3744 605
d62a17ae 606 if (new_weight < exist_weight) {
fdf81fa0 607 *reason = bgp_path_selection_weight;
d62a17ae 608 if (debug)
609 zlog_debug("%s: %s loses to %s due to weight %d < %d",
610 pfx_buf, new_buf, exist_buf, new_weight,
611 exist_weight);
612 return 0;
613 }
9fbdd100 614
d62a17ae 615 /* 2. Local preference check. */
616 new_pref = exist_pref = bgp->default_local_pref;
617
618 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
619 new_pref = newattr->local_pref;
620 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
621 exist_pref = existattr->local_pref;
622
623 if (new_pref > exist_pref) {
fdf81fa0 624 *reason = bgp_path_selection_local_pref;
d62a17ae 625 if (debug)
626 zlog_debug(
627 "%s: %s wins over %s due to localpref %d > %d",
628 pfx_buf, new_buf, exist_buf, new_pref,
629 exist_pref);
630 return 1;
631 }
718e3744 632
d62a17ae 633 if (new_pref < exist_pref) {
fdf81fa0 634 *reason = bgp_path_selection_local_pref;
d62a17ae 635 if (debug)
636 zlog_debug(
637 "%s: %s loses to %s due to localpref %d < %d",
638 pfx_buf, new_buf, exist_buf, new_pref,
639 exist_pref);
640 return 0;
641 }
9fbdd100 642
d62a17ae 643 /* 3. Local route check. We prefer:
644 * - BGP_ROUTE_STATIC
645 * - BGP_ROUTE_AGGREGATE
646 * - BGP_ROUTE_REDISTRIBUTE
647 */
90f4f482 648 if (!(new->sub_type == BGP_ROUTE_NORMAL ||
649 new->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 650 *reason = bgp_path_selection_local_route;
d62a17ae 651 if (debug)
652 zlog_debug(
653 "%s: %s wins over %s due to preferred BGP_ROUTE type",
654 pfx_buf, new_buf, exist_buf);
655 return 1;
656 }
718e3744 657
90f4f482 658 if (!(exist->sub_type == BGP_ROUTE_NORMAL ||
88493076 659 exist->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 660 *reason = bgp_path_selection_local_route;
d62a17ae 661 if (debug)
662 zlog_debug(
663 "%s: %s loses to %s due to preferred BGP_ROUTE type",
664 pfx_buf, new_buf, exist_buf);
665 return 0;
6811845b 666 }
718e3744 667
d62a17ae 668 /* 4. AS path length check. */
669 if (!bgp_flag_check(bgp, BGP_FLAG_ASPATH_IGNORE)) {
670 int exist_hops = aspath_count_hops(existattr->aspath);
671 int exist_confeds = aspath_count_confeds(existattr->aspath);
672
673 if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_CONFED)) {
674 int aspath_hops;
675
676 aspath_hops = aspath_count_hops(newattr->aspath);
677 aspath_hops += aspath_count_confeds(newattr->aspath);
678
679 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 680 *reason = bgp_path_selection_confed_as_path;
d62a17ae 681 if (debug)
682 zlog_debug(
683 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
684 pfx_buf, new_buf, exist_buf,
685 aspath_hops,
686 (exist_hops + exist_confeds));
687 return 1;
688 }
689
690 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 691 *reason = bgp_path_selection_confed_as_path;
d62a17ae 692 if (debug)
693 zlog_debug(
694 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
695 pfx_buf, new_buf, exist_buf,
696 aspath_hops,
697 (exist_hops + exist_confeds));
698 return 0;
699 }
700 } else {
701 int newhops = aspath_count_hops(newattr->aspath);
702
703 if (newhops < exist_hops) {
fdf81fa0 704 *reason = bgp_path_selection_as_path;
d62a17ae 705 if (debug)
706 zlog_debug(
707 "%s: %s wins over %s due to aspath hopcount %d < %d",
708 pfx_buf, new_buf, exist_buf,
709 newhops, exist_hops);
710 return 1;
711 }
712
713 if (newhops > exist_hops) {
fdf81fa0 714 *reason = bgp_path_selection_as_path;
d62a17ae 715 if (debug)
716 zlog_debug(
717 "%s: %s loses to %s due to aspath hopcount %d > %d",
718 pfx_buf, new_buf, exist_buf,
719 newhops, exist_hops);
720 return 0;
721 }
722 }
723 }
9fbdd100 724
d62a17ae 725 /* 5. Origin check. */
726 if (newattr->origin < existattr->origin) {
fdf81fa0 727 *reason = bgp_path_selection_origin;
d62a17ae 728 if (debug)
729 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
730 pfx_buf, new_buf, exist_buf,
731 bgp_origin_long_str[newattr->origin],
732 bgp_origin_long_str[existattr->origin]);
733 return 1;
734 }
718e3744 735
d62a17ae 736 if (newattr->origin > existattr->origin) {
fdf81fa0 737 *reason = bgp_path_selection_origin;
d62a17ae 738 if (debug)
739 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
740 pfx_buf, new_buf, exist_buf,
741 bgp_origin_long_str[newattr->origin],
742 bgp_origin_long_str[existattr->origin]);
743 return 0;
744 }
718e3744 745
d62a17ae 746 /* 6. MED check. */
747 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
748 && aspath_count_hops(existattr->aspath) == 0);
749 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
750 && aspath_count_confeds(existattr->aspath) > 0
751 && aspath_count_hops(newattr->aspath) == 0
752 && aspath_count_hops(existattr->aspath) == 0);
753
754 if (bgp_flag_check(bgp, BGP_FLAG_ALWAYS_COMPARE_MED)
755 || (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED) && confed_as_route)
756 || aspath_cmp_left(newattr->aspath, existattr->aspath)
757 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
758 || internal_as_route) {
759 new_med = bgp_med_value(new->attr, bgp);
760 exist_med = bgp_med_value(exist->attr, bgp);
761
762 if (new_med < exist_med) {
fdf81fa0 763 *reason = bgp_path_selection_med;
d62a17ae 764 if (debug)
765 zlog_debug(
766 "%s: %s wins over %s due to MED %d < %d",
767 pfx_buf, new_buf, exist_buf, new_med,
768 exist_med);
769 return 1;
770 }
8ff56318 771
d62a17ae 772 if (new_med > exist_med) {
fdf81fa0 773 *reason = bgp_path_selection_med;
d62a17ae 774 if (debug)
775 zlog_debug(
776 "%s: %s loses to %s due to MED %d > %d",
777 pfx_buf, new_buf, exist_buf, new_med,
778 exist_med);
779 return 0;
780 }
781 }
9fbdd100 782
d62a17ae 783 /* 7. Peer type check. */
784 new_sort = new->peer->sort;
785 exist_sort = exist->peer->sort;
786
787 if (new_sort == BGP_PEER_EBGP
788 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 789 *reason = bgp_path_selection_peer;
d62a17ae 790 if (debug)
791 zlog_debug(
792 "%s: %s wins over %s due to eBGP peer > iBGP peer",
793 pfx_buf, new_buf, exist_buf);
794 return 1;
795 }
718e3744 796
d62a17ae 797 if (exist_sort == BGP_PEER_EBGP
798 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 799 *reason = bgp_path_selection_peer;
d62a17ae 800 if (debug)
801 zlog_debug(
802 "%s: %s loses to %s due to iBGP peer < eBGP peer",
803 pfx_buf, new_buf, exist_buf);
804 return 0;
805 }
8ff56318 806
d62a17ae 807 /* 8. IGP metric check. */
808 newm = existm = 0;
8ff56318 809
d62a17ae 810 if (new->extra)
811 newm = new->extra->igpmetric;
812 if (exist->extra)
813 existm = exist->extra->igpmetric;
9fbdd100 814
d62a17ae 815 if (newm < existm) {
816 if (debug)
817 zlog_debug(
818 "%s: %s wins over %s due to IGP metric %d < %d",
819 pfx_buf, new_buf, exist_buf, newm, existm);
820 ret = 1;
821 }
718e3744 822
d62a17ae 823 if (newm > existm) {
824 if (debug)
825 zlog_debug(
826 "%s: %s loses to %s due to IGP metric %d > %d",
827 pfx_buf, new_buf, exist_buf, newm, existm);
828 ret = 0;
5e242b0d 829 }
5e242b0d 830
d62a17ae 831 /* 9. Same IGP metric. Compare the cluster list length as
832 representative of IGP hops metric. Rewrite the metric value
833 pair (newm, existm) with the cluster list length. Prefer the
834 path with smaller cluster list length. */
835 if (newm == existm) {
836 if (peer_sort(new->peer) == BGP_PEER_IBGP
837 && peer_sort(exist->peer) == BGP_PEER_IBGP
838 && (mpath_cfg == NULL
839 || CHECK_FLAG(
840 mpath_cfg->ibgp_flags,
841 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
842 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
843 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
844
845 if (newm < existm) {
846 if (debug)
847 zlog_debug(
848 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
849 pfx_buf, new_buf, exist_buf,
850 newm, existm);
851 ret = 1;
852 }
853
854 if (newm > existm) {
855 if (debug)
856 zlog_debug(
857 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
858 pfx_buf, new_buf, exist_buf,
859 newm, existm);
860 ret = 0;
861 }
862 }
863 }
31a4638f 864
d62a17ae 865 /* 10. confed-external vs. confed-internal */
866 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
867 if (new_sort == BGP_PEER_CONFED
868 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 869 *reason = bgp_path_selection_confed;
d62a17ae 870 if (debug)
871 zlog_debug(
872 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
873 pfx_buf, new_buf, exist_buf);
874 return 1;
875 }
718e3744 876
d62a17ae 877 if (exist_sort == BGP_PEER_CONFED
878 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 879 *reason = bgp_path_selection_confed;
d62a17ae 880 if (debug)
881 zlog_debug(
882 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
883 pfx_buf, new_buf, exist_buf);
884 return 0;
885 }
886 }
718e3744 887
d62a17ae 888 /* 11. Maximum path check. */
889 if (newm == existm) {
890 /* If one path has a label but the other does not, do not treat
891 * them as equals for multipath
892 */
a4d82a8a 893 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 894 != (exist->extra
b57ba6d2 895 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 896 if (debug)
897 zlog_debug(
898 "%s: %s and %s cannot be multipath, one has a label while the other does not",
899 pfx_buf, new_buf, exist_buf);
900 } else if (bgp_flag_check(bgp,
901 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
902
903 /*
904 * For the two paths, all comparison steps till IGP
905 * metric
906 * have succeeded - including AS_PATH hop count. Since
907 * 'bgp
908 * bestpath as-path multipath-relax' knob is on, we
909 * don't need
910 * an exact match of AS_PATH. Thus, mark the paths are
911 * equal.
912 * That will trigger both these paths to get into the
913 * multipath
914 * array.
915 */
916 *paths_eq = 1;
917
918 if (debug)
919 zlog_debug(
920 "%s: %s and %s are equal via multipath-relax",
921 pfx_buf, new_buf, exist_buf);
922 } else if (new->peer->sort == BGP_PEER_IBGP) {
923 if (aspath_cmp(new->attr->aspath,
924 exist->attr->aspath)) {
925 *paths_eq = 1;
926
927 if (debug)
928 zlog_debug(
929 "%s: %s and %s are equal via matching aspaths",
930 pfx_buf, new_buf, exist_buf);
931 }
932 } else if (new->peer->as == exist->peer->as) {
933 *paths_eq = 1;
934
935 if (debug)
936 zlog_debug(
937 "%s: %s and %s are equal via same remote-as",
938 pfx_buf, new_buf, exist_buf);
939 }
940 } else {
941 /*
942 * TODO: If unequal cost ibgp multipath is enabled we can
943 * mark the paths as equal here instead of returning
944 */
945 if (debug) {
946 if (ret == 1)
947 zlog_debug(
948 "%s: %s wins over %s after IGP metric comparison",
949 pfx_buf, new_buf, exist_buf);
950 else
951 zlog_debug(
952 "%s: %s loses to %s after IGP metric comparison",
953 pfx_buf, new_buf, exist_buf);
954 }
fdf81fa0 955 *reason = bgp_path_selection_igp_metric;
d62a17ae 956 return ret;
957 }
718e3744 958
d62a17ae 959 /* 12. If both paths are external, prefer the path that was received
960 first (the oldest one). This step minimizes route-flap, since a
961 newer path won't displace an older one, even if it was the
962 preferred route based on the additional decision criteria below. */
963 if (!bgp_flag_check(bgp, BGP_FLAG_COMPARE_ROUTER_ID)
964 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 965 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 966 *reason = bgp_path_selection_older;
d62a17ae 967 if (debug)
968 zlog_debug(
969 "%s: %s wins over %s due to oldest external",
970 pfx_buf, new_buf, exist_buf);
971 return 1;
972 }
9fbdd100 973
1defdda8 974 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 975 *reason = bgp_path_selection_older;
d62a17ae 976 if (debug)
977 zlog_debug(
978 "%s: %s loses to %s due to oldest external",
979 pfx_buf, new_buf, exist_buf);
980 return 0;
981 }
982 }
718e3744 983
d62a17ae 984 /* 13. Router-ID comparision. */
985 /* If one of the paths is "stale", the corresponding peer router-id will
986 * be 0 and would always win over the other path. If originator id is
987 * used for the comparision, it will decide which path is better.
988 */
989 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
990 new_id.s_addr = newattr->originator_id.s_addr;
991 else
992 new_id.s_addr = new->peer->remote_id.s_addr;
993 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
994 exist_id.s_addr = existattr->originator_id.s_addr;
995 else
996 exist_id.s_addr = exist->peer->remote_id.s_addr;
997
998 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 999 *reason = bgp_path_selection_router_id;
d62a17ae 1000 if (debug)
1001 zlog_debug(
1002 "%s: %s wins over %s due to Router-ID comparison",
1003 pfx_buf, new_buf, exist_buf);
1004 return 1;
1005 }
718e3744 1006
d62a17ae 1007 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1008 *reason = bgp_path_selection_router_id;
d62a17ae 1009 if (debug)
1010 zlog_debug(
1011 "%s: %s loses to %s due to Router-ID comparison",
1012 pfx_buf, new_buf, exist_buf);
1013 return 0;
1014 }
9fbdd100 1015
d62a17ae 1016 /* 14. Cluster length comparision. */
1017 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1018 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1019
1020 if (new_cluster < exist_cluster) {
fdf81fa0 1021 *reason = bgp_path_selection_cluster_length;
d62a17ae 1022 if (debug)
1023 zlog_debug(
1024 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1025 pfx_buf, new_buf, exist_buf, new_cluster,
1026 exist_cluster);
1027 return 1;
1028 }
718e3744 1029
d62a17ae 1030 if (new_cluster > exist_cluster) {
fdf81fa0 1031 *reason = bgp_path_selection_cluster_length;
d62a17ae 1032 if (debug)
1033 zlog_debug(
1034 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1035 pfx_buf, new_buf, exist_buf, new_cluster,
1036 exist_cluster);
1037 return 0;
1038 }
9fbdd100 1039
d62a17ae 1040 /* 15. Neighbor address comparision. */
1041 /* Do this only if neither path is "stale" as stale paths do not have
1042 * valid peer information (as the connection may or may not be up).
1043 */
1defdda8 1044 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1045 *reason = bgp_path_selection_stale;
d62a17ae 1046 if (debug)
1047 zlog_debug(
1048 "%s: %s wins over %s due to latter path being STALE",
1049 pfx_buf, new_buf, exist_buf);
1050 return 1;
1051 }
0de5153c 1052
1defdda8 1053 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1054 *reason = bgp_path_selection_stale;
d62a17ae 1055 if (debug)
1056 zlog_debug(
1057 "%s: %s loses to %s due to former path being STALE",
1058 pfx_buf, new_buf, exist_buf);
1059 return 0;
1060 }
718e3744 1061
d62a17ae 1062 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1063 if (new->peer->su_remote == NULL) {
1064 *reason = bgp_path_selection_local_configured;
d62a17ae 1065 return 0;
fdf81fa0
DS
1066 }
1067 if (exist->peer->su_remote == NULL) {
1068 *reason = bgp_path_selection_local_configured;
d62a17ae 1069 return 1;
fdf81fa0 1070 }
9fbdd100 1071
d62a17ae 1072 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1073
1074 if (ret == 1) {
fdf81fa0 1075 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1076 if (debug)
1077 zlog_debug(
1078 "%s: %s loses to %s due to Neighor IP comparison",
1079 pfx_buf, new_buf, exist_buf);
1080 return 0;
1081 }
1082
1083 if (ret == -1) {
fdf81fa0 1084 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1085 if (debug)
1086 zlog_debug(
1087 "%s: %s wins over %s due to Neighor IP comparison",
1088 pfx_buf, new_buf, exist_buf);
1089 return 1;
1090 }
9fbdd100 1091
fdf81fa0 1092 *reason = bgp_path_selection_default;
d62a17ae 1093 if (debug)
1094 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1095 pfx_buf, new_buf, exist_buf);
718e3744 1096
d62a17ae 1097 return 1;
718e3744 1098}
1099
65efcfce
LB
1100/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1101 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1102 * multipath is enabled
65efcfce 1103 * This version is compatible with */
18ee8310
DS
1104int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1105 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1106 afi_t afi, safi_t safi,
1107 enum bgp_path_selection_reason *reason)
d62a17ae 1108{
1109 int paths_eq;
1110 int ret;
18ee8310 1111 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1112 afi, safi, reason);
d62a17ae 1113
1114 if (paths_eq)
1115 ret = 0;
1116 else {
1117 if (ret == 1)
1118 ret = -1;
1119 else
1120 ret = 1;
1121 }
1122 return ret;
65efcfce
LB
1123}
1124
d62a17ae 1125static enum filter_type bgp_input_filter(struct peer *peer, struct prefix *p,
1126 struct attr *attr, afi_t afi,
1127 safi_t safi)
718e3744 1128{
d62a17ae 1129 struct bgp_filter *filter;
718e3744 1130
d62a17ae 1131 filter = &peer->filter[afi][safi];
718e3744 1132
d62a17ae 1133#define FILTER_EXIST_WARN(F, f, filter) \
1134 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1135 zlog_debug("%s: Could not find configured input %s-list %s!", \
1136 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1137
1138 if (DISTRIBUTE_IN_NAME(filter)) {
1139 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1140
1141 if (access_list_apply(DISTRIBUTE_IN(filter), p) == FILTER_DENY)
1142 return FILTER_DENY;
1143 }
1144
1145 if (PREFIX_LIST_IN_NAME(filter)) {
1146 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1147
1148 if (prefix_list_apply(PREFIX_LIST_IN(filter), p) == PREFIX_DENY)
1149 return FILTER_DENY;
1150 }
1151
1152 if (FILTER_LIST_IN_NAME(filter)) {
1153 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1154
1155 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
1156 == AS_FILTER_DENY)
1157 return FILTER_DENY;
1158 }
1159
1160 return FILTER_PERMIT;
650f76c2 1161#undef FILTER_EXIST_WARN
718e3744 1162}
1163
d62a17ae 1164static enum filter_type bgp_output_filter(struct peer *peer, struct prefix *p,
1165 struct attr *attr, afi_t afi,
1166 safi_t safi)
718e3744 1167{
d62a17ae 1168 struct bgp_filter *filter;
1169
1170 filter = &peer->filter[afi][safi];
1171
1172#define FILTER_EXIST_WARN(F, f, filter) \
1173 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1174 zlog_debug("%s: Could not find configured output %s-list %s!", \
1175 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1176
d62a17ae 1177 if (DISTRIBUTE_OUT_NAME(filter)) {
1178 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1179
d62a17ae 1180 if (access_list_apply(DISTRIBUTE_OUT(filter), p) == FILTER_DENY)
1181 return FILTER_DENY;
1182 }
1183
1184 if (PREFIX_LIST_OUT_NAME(filter)) {
1185 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1186
d62a17ae 1187 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
1188 == PREFIX_DENY)
1189 return FILTER_DENY;
1190 }
718e3744 1191
d62a17ae 1192 if (FILTER_LIST_OUT_NAME(filter)) {
1193 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1194
d62a17ae 1195 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
1196 == AS_FILTER_DENY)
1197 return FILTER_DENY;
1198 }
718e3744 1199
d62a17ae 1200 return FILTER_PERMIT;
650f76c2 1201#undef FILTER_EXIST_WARN
718e3744 1202}
1203
1204/* If community attribute includes no_export then return 1. */
d62a17ae 1205static int bgp_community_filter(struct peer *peer, struct attr *attr)
1206{
1207 if (attr->community) {
1208 /* NO_ADVERTISE check. */
1209 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
1210 return 1;
1211
1212 /* NO_EXPORT check. */
1213 if (peer->sort == BGP_PEER_EBGP
1214 && community_include(attr->community, COMMUNITY_NO_EXPORT))
1215 return 1;
1216
1217 /* NO_EXPORT_SUBCONFED check. */
1218 if (peer->sort == BGP_PEER_EBGP
1219 || peer->sort == BGP_PEER_CONFED)
1220 if (community_include(attr->community,
1221 COMMUNITY_NO_EXPORT_SUBCONFED))
1222 return 1;
1223 }
1224 return 0;
718e3744 1225}
1226
1227/* Route reflection loop check. */
d62a17ae 1228static int bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1229{
d62a17ae 1230 struct in_addr cluster_id;
718e3744 1231
d62a17ae 1232 if (attr->cluster) {
1233 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1234 cluster_id = peer->bgp->cluster_id;
1235 else
1236 cluster_id = peer->bgp->router_id;
1237
1238 if (cluster_loop_check(attr->cluster, cluster_id))
1239 return 1;
1240 }
1241 return 0;
718e3744 1242}
6b0655a2 1243
d62a17ae 1244static int bgp_input_modifier(struct peer *peer, struct prefix *p,
1245 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1246 const char *rmap_name, mpls_label_t *label,
196c6b09 1247 uint32_t num_labels, struct bgp_node *rn)
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 1281 rmap_path.extra = &extra;
196c6b09
LK
1282 rmap_path.net = rn;
1283
82b692c0
LK
1284 extra.num_labels = num_labels;
1285 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1286 memcpy(extra.label, label,
1287 num_labels * sizeof(mpls_label_t));
718e3744 1288
d62a17ae 1289 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1290
d62a17ae 1291 /* Apply BGP route map to the attribute. */
40381db7 1292 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
0b16f239 1293
d62a17ae 1294 peer->rmap_type = 0;
0b16f239 1295
1f2263be 1296 if (ret == RMAP_DENYMATCH)
d62a17ae 1297 return RMAP_DENY;
0b16f239 1298 }
d62a17ae 1299 return RMAP_PERMIT;
0b16f239
DS
1300}
1301
d62a17ae 1302static int bgp_output_modifier(struct peer *peer, struct prefix *p,
1303 struct attr *attr, afi_t afi, safi_t safi,
1304 const char *rmap_name)
0b16f239 1305{
40381db7 1306 struct bgp_path_info rmap_path;
d62a17ae 1307 route_map_result_t ret;
1308 struct route_map *rmap = NULL;
d7c0a89a 1309 uint8_t rmap_type;
0b16f239 1310
b787157a
DS
1311 /*
1312 * So if we get to this point and have no rmap_name
1313 * we want to just show the output as it currently
1314 * exists.
1315 */
1316 if (!rmap_name)
1317 return RMAP_PERMIT;
0b16f239 1318
d62a17ae 1319 /* Apply default weight value. */
1320 if (peer->weight[afi][safi])
1321 attr->weight = peer->weight[afi][safi];
0b16f239 1322
b787157a 1323 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1324
b787157a
DS
1325 /*
1326 * If we have a route map name and we do not find
1327 * the routemap that means we have an implicit
1328 * deny.
1329 */
1330 if (rmap == NULL)
1331 return RMAP_DENY;
0b16f239 1332
40381db7 1333 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1334 /* Route map apply. */
b787157a 1335 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1336 rmap_path.peer = peer;
1337 rmap_path.attr = attr;
0b16f239 1338
0f672529 1339 rmap_type = peer->rmap_type;
b787157a 1340 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1341
b787157a 1342 /* Apply BGP route map to the attribute. */
40381db7 1343 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
ac41b2a2 1344
0f672529 1345 peer->rmap_type = rmap_type;
b787157a
DS
1346
1347 if (ret == RMAP_DENYMATCH)
1348 /*
1349 * caller has multiple error paths with bgp_attr_flush()
1350 */
1351 return RMAP_DENY;
ac41b2a2 1352
d62a17ae 1353 return RMAP_PERMIT;
718e3744 1354}
6b0655a2 1355
5000f21c 1356/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1357static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1358 struct peer *peer, struct attr *attr)
1359{
1360 if (peer->sort == BGP_PEER_EBGP
1361 && (peer_af_flag_check(peer, afi, safi,
1362 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1363 || peer_af_flag_check(peer, afi, safi,
1364 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1365 || peer_af_flag_check(peer, afi, safi,
1366 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1367 || peer_af_flag_check(peer, afi, safi,
1368 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1369 // Take action on the entire aspath
1370 if (peer_af_flag_check(peer, afi, safi,
1371 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1372 || peer_af_flag_check(peer, afi, safi,
1373 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1374 if (peer_af_flag_check(
1375 peer, afi, safi,
1376 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1377 attr->aspath = aspath_replace_private_asns(
bf26b80e 1378 attr->aspath, bgp->as, peer->as);
d62a17ae 1379
1380 // The entire aspath consists of private ASNs so create
1381 // an empty aspath
1382 else if (aspath_private_as_check(attr->aspath))
1383 attr->aspath = aspath_empty_get();
1384
1385 // There are some public and some private ASNs, remove
1386 // the private ASNs
1387 else
1388 attr->aspath = aspath_remove_private_asns(
bf26b80e 1389 attr->aspath, peer->as);
d62a17ae 1390 }
1391
1392 // 'all' was not specified so the entire aspath must be private
1393 // ASNs
1394 // for us to do anything
1395 else if (aspath_private_as_check(attr->aspath)) {
1396 if (peer_af_flag_check(
1397 peer, afi, safi,
1398 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1399 attr->aspath = aspath_replace_private_asns(
bf26b80e 1400 attr->aspath, bgp->as, peer->as);
d62a17ae 1401 else
1402 attr->aspath = aspath_empty_get();
1403 }
1404 }
5000f21c
DS
1405}
1406
c7122e14 1407/* If this is an EBGP peer with as-override */
d62a17ae 1408static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1409 struct peer *peer, struct attr *attr)
1410{
1411 if (peer->sort == BGP_PEER_EBGP
1412 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1413 if (aspath_single_asn_check(attr->aspath, peer->as))
1414 attr->aspath = aspath_replace_specific_asn(
1415 attr->aspath, peer->as, bgp->as);
1416 }
1417}
1418
7f323236
DW
1419void bgp_attr_add_gshut_community(struct attr *attr)
1420{
1421 struct community *old;
1422 struct community *new;
1423 struct community *merge;
1424 struct community *gshut;
1425
1426 old = attr->community;
1427 gshut = community_str2com("graceful-shutdown");
1428
990f4f91 1429 assert(gshut);
1430
7f323236
DW
1431 if (old) {
1432 merge = community_merge(community_dup(old), gshut);
1433
a4d82a8a 1434 if (old->refcnt == 0)
3c1f53de 1435 community_free(&old);
7f323236
DW
1436
1437 new = community_uniq_sort(merge);
3c1f53de 1438 community_free(&merge);
7f323236
DW
1439 } else {
1440 new = community_dup(gshut);
1441 }
1442
3c1f53de 1443 community_free(&gshut);
7f323236
DW
1444 attr->community = new;
1445 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1446
1447 /* When we add the graceful-shutdown community we must also
1448 * lower the local-preference */
1449 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1450 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1451}
1452
1453
d7c0a89a 1454static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1455{
960035b2 1456 if (family == AF_INET) {
d62a17ae 1457 attr->nexthop.s_addr = 0;
960035b2
PZ
1458 attr->mp_nexthop_global_in.s_addr = 0;
1459 }
d62a17ae 1460 if (family == AF_INET6)
1461 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1462 if (family == AF_EVPN)
1463 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1464}
1465
40381db7 1466int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
d62a17ae 1467 struct update_subgroup *subgrp, struct prefix *p,
1468 struct attr *attr)
1469{
1470 struct bgp_filter *filter;
1471 struct peer *from;
1472 struct peer *peer;
1473 struct peer *onlypeer;
1474 struct bgp *bgp;
40381db7 1475 struct attr *piattr;
d62a17ae 1476 char buf[PREFIX_STRLEN];
b68885f9 1477 route_map_result_t ret;
d62a17ae 1478 int transparent;
1479 int reflect;
1480 afi_t afi;
1481 safi_t safi;
1482 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
1483
1484 if (DISABLE_BGP_ANNOUNCE)
1485 return 0;
1486
1487 afi = SUBGRP_AFI(subgrp);
1488 safi = SUBGRP_SAFI(subgrp);
1489 peer = SUBGRP_PEER(subgrp);
1490 onlypeer = NULL;
1491 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1492 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1493
40381db7 1494 from = pi->peer;
d62a17ae 1495 filter = &peer->filter[afi][safi];
1496 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1497 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1498 : pi->attr;
3f9c7369 1499
65efcfce 1500#if ENABLE_BGP_VNC
d62a17ae 1501 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1502 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1503 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1504
1505 /*
1506 * direct and direct_ext type routes originate internally even
1507 * though they can have peer pointers that reference other
1508 * systems
1509 */
1510 prefix2str(p, buf, PREFIX_STRLEN);
1511 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1512 __func__, buf);
1513 samepeer_safe = 1;
1514 }
65efcfce
LB
1515#endif
1516
ddb5b488
PZ
1517 if (((afi == AFI_IP) || (afi == AFI_IP6))
1518 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1519 && (pi->type == ZEBRA_ROUTE_BGP)
1520 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1521
1522 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1523
1524 samepeer_safe = 1;
1525 }
1526
d62a17ae 1527 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1528 * pi is valid */
1529 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1530 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1531 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 1532 return 0;
1533 }
adbac85e 1534
d62a17ae 1535 /* If this is not the bestpath then check to see if there is an enabled
1536 * addpath
1537 * feature that requires us to advertise it */
40381db7 1538 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1539 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
d62a17ae 1540 return 0;
1541 }
1542 }
06370dac 1543
d62a17ae 1544 /* Aggregate-address suppress check. */
40381db7 1545 if (pi->extra && pi->extra->suppress)
d62a17ae 1546 if (!UNSUPPRESS_MAP_NAME(filter)) {
1547 return 0;
1548 }
3f9c7369 1549
13b7e7f0
DS
1550 /*
1551 * If we are doing VRF 2 VRF leaking via the import
1552 * statement, we want to prevent the route going
1553 * off box as that the RT and RD created are localy
1554 * significant and globaly useless.
1555 */
40381db7
DS
1556 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1557 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
13b7e7f0
DS
1558 return 0;
1559
d62a17ae 1560 /* If it's labeled safi, make sure the route has a valid label. */
1561 if (safi == SAFI_LABELED_UNICAST) {
40381db7 1562 mpls_label_t label = bgp_adv_label(rn, pi, peer, afi, safi);
d62a17ae 1563 if (!bgp_is_valid_label(&label)) {
1564 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1565 zlog_debug("u%" PRIu64 ":s%" PRIu64
1566 " %s/%d is filtered - no label (%p)",
1567 subgrp->update_group->id, subgrp->id,
1568 inet_ntop(p->family, &p->u.prefix,
1569 buf, SU_ADDRSTRLEN),
1570 p->prefixlen, &label);
1571 return 0;
1572 }
1573 }
cd1964ff 1574
d62a17ae 1575 /* Do not send back route to sender. */
1576 if (onlypeer && from == onlypeer) {
1577 return 0;
1578 }
3f9c7369 1579
d62a17ae 1580 /* Do not send the default route in the BGP table if the neighbor is
1581 * configured for default-originate */
1582 if (CHECK_FLAG(peer->af_flags[afi][safi],
1583 PEER_FLAG_DEFAULT_ORIGINATE)) {
1584 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
1585 return 0;
1586 else if (p->family == AF_INET6 && p->prefixlen == 0)
1587 return 0;
1588 }
4125bb67 1589
d62a17ae 1590 /* Transparency check. */
1591 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1592 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1593 transparent = 1;
1594 else
1595 transparent = 0;
1596
1597 /* If community is not disabled check the no-export and local. */
40381db7 1598 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1599 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1600 zlog_debug(
1601 "subgrpannouncecheck: community filter check fail");
1602 return 0;
1603 }
3f9c7369 1604
d62a17ae 1605 /* If the attribute has originator-id and it is same as remote
1606 peer's id. */
40381db7
DS
1607 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1608 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1609 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1610 zlog_debug(
1611 "%s [Update:SEND] %s originator-id is same as "
1612 "remote router-id",
1613 onlypeer->host,
1614 prefix2str(p, buf, sizeof(buf)));
1615 return 0;
1616 }
3f9c7369 1617
d62a17ae 1618 /* ORF prefix-list filter check */
1619 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1620 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1621 || CHECK_FLAG(peer->af_cap[afi][safi],
1622 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1623 if (peer->orf_plist[afi][safi]) {
1624 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1625 == PREFIX_DENY) {
1626 if (bgp_debug_update(NULL, p,
1627 subgrp->update_group, 0))
1628 zlog_debug(
1629 "%s [Update:SEND] %s is filtered via ORF",
1630 peer->host,
1631 prefix2str(p, buf,
1632 sizeof(buf)));
1633 return 0;
1634 }
1635 }
1636
1637 /* Output filter check. */
40381db7 1638 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1639 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1640 zlog_debug("%s [Update:SEND] %s is filtered",
1641 peer->host, prefix2str(p, buf, sizeof(buf)));
1642 return 0;
1643 }
3f9c7369 1644
d62a17ae 1645 /* AS path loop check. */
2b31007c
RZ
1646 if (onlypeer && onlypeer->as_path_loop_detection
1647 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1648 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1649 zlog_debug(
1650 "%s [Update:SEND] suppress announcement to peer AS %u "
1651 "that is part of AS path.",
1652 onlypeer->host, onlypeer->as);
1653 return 0;
1654 }
3f9c7369 1655
d62a17ae 1656 /* If we're a CONFED we need to loop check the CONFED ID too */
1657 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1658 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1659 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1660 zlog_debug(
1661 "%s [Update:SEND] suppress announcement to peer AS %u"
1662 " is AS path.",
1663 peer->host, bgp->confed_id);
1664 return 0;
1665 }
3f9c7369 1666 }
3f9c7369 1667
d62a17ae 1668 /* Route-Reflect check. */
1669 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1670 reflect = 1;
1671 else
1672 reflect = 0;
1673
1674 /* IBGP reflection check. */
1675 if (reflect && !samepeer_safe) {
1676 /* A route from a Client peer. */
1677 if (CHECK_FLAG(from->af_flags[afi][safi],
1678 PEER_FLAG_REFLECTOR_CLIENT)) {
1679 /* Reflect to all the Non-Client peers and also to the
1680 Client peers other than the originator. Originator
1681 check
1682 is already done. So there is noting to do. */
1683 /* no bgp client-to-client reflection check. */
1684 if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
1685 if (CHECK_FLAG(peer->af_flags[afi][safi],
1686 PEER_FLAG_REFLECTOR_CLIENT))
1687 return 0;
1688 } else {
1689 /* A route from a Non-client peer. Reflect to all other
1690 clients. */
1691 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1692 PEER_FLAG_REFLECTOR_CLIENT))
1693 return 0;
1694 }
1695 }
3f9c7369 1696
d62a17ae 1697 /* For modify attribute, copy it to temporary structure. */
40381db7 1698 bgp_attr_dup(attr, piattr);
d62a17ae 1699
1700 /* If local-preference is not set. */
1701 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1702 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1703 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1704 attr->local_pref = bgp->default_local_pref;
3f9c7369 1705 }
3f9c7369 1706
d62a17ae 1707 /* If originator-id is not set and the route is to be reflected,
1708 set the originator id */
1709 if (reflect
1710 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1711 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1712 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1713 }
3f9c7369 1714
d62a17ae 1715 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1716 */
1717 if (peer->sort == BGP_PEER_EBGP
1718 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1719 if (from != bgp->peer_self && !transparent
1720 && !CHECK_FLAG(peer->af_flags[afi][safi],
1721 PEER_FLAG_MED_UNCHANGED))
1722 attr->flag &=
1723 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1724 }
3f9c7369 1725
d62a17ae 1726 /* Since the nexthop attribute can vary per peer, it is not explicitly
1727 * set
1728 * in announce check, only certain flags and length (or number of
1729 * nexthops
1730 * -- for IPv6/MP_REACH) are set here in order to guide the update
1731 * formation
1732 * code in setting the nexthop(s) on a per peer basis in
1733 * reformat_peer().
1734 * Typically, the source nexthop in the attribute is preserved but in
1735 * the
1736 * scenarios where we know it will always be overwritten, we reset the
1737 * nexthop to "0" in an attempt to achieve better Update packing. An
1738 * example of this is when a prefix from each of 2 IBGP peers needs to
1739 * be
1740 * announced to an EBGP peer (and they have the same attributes barring
1741 * their nexthop).
1742 */
1743 if (reflect)
1744 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1745
1746#define NEXTHOP_IS_V6 \
1747 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1748 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1749 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1750 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1751
1752 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1753 * if
1754 * the peer (group) is configured to receive link-local nexthop
1755 * unchanged
c728d027
DA
1756 * and it is available in the prefix OR we're not reflecting the route,
1757 * link-local nexthop address is valid and
d62a17ae 1758 * the peer (group) to whom we're going to announce is on a shared
1759 * network
1760 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
1761 * By checking if nexthop LL address is valid we are sure that
1762 * we do not announce LL address as `::`.
d62a17ae 1763 */
1764 if (NEXTHOP_IS_V6) {
1765 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
1766 if ((CHECK_FLAG(peer->af_flags[afi][safi],
1767 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
1768 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
1769 || (!reflect
1770 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
1771 && peer->shared_network
d62a17ae 1772 && (from == bgp->peer_self
1773 || peer->sort == BGP_PEER_EBGP))) {
1774 attr->mp_nexthop_len =
1775 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
1776 }
3f9c7369 1777
d62a17ae 1778 /* Clear off link-local nexthop in source, whenever it is not
1779 * needed to
1780 * ensure more prefixes share the same attribute for
1781 * announcement.
1782 */
1783 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
1784 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
1785 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
1786 }
3f9c7369 1787
d62a17ae 1788 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
1789 bgp_peer_as_override(bgp, afi, safi, peer, attr);
1790
1791 /* Route map & unsuppress-map apply. */
40381db7 1792 if (ROUTE_MAP_OUT_NAME(filter) || (pi->extra && pi->extra->suppress)) {
b8694ef4
DS
1793 struct bgp_path_info rmap_path = {0};
1794 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
1795 struct attr dummy_attr = {0};
d62a17ae 1796
40381db7
DS
1797 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
1798 rmap_path.peer = peer;
1799 rmap_path.attr = attr;
196c6b09 1800 rmap_path.net = rn;
d37ba549 1801
40381db7
DS
1802 if (pi->extra) {
1803 memcpy(&dummy_rmap_path_extra, pi->extra,
4b7e6066 1804 sizeof(struct bgp_path_info_extra));
40381db7 1805 rmap_path.extra = &dummy_rmap_path_extra;
16f7ce2b
MK
1806 }
1807
d62a17ae 1808 /* don't confuse inbound and outbound setting */
1809 RESET_FLAG(attr->rmap_change_flags);
1810
1811 /*
1812 * The route reflector is not allowed to modify the attributes
1813 * of the reflected IBGP routes unless explicitly allowed.
1814 */
1815 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1816 && !bgp_flag_check(bgp,
1817 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
1818 bgp_attr_dup(&dummy_attr, attr);
40381db7 1819 rmap_path.attr = &dummy_attr;
d62a17ae 1820 }
3f9c7369 1821
d62a17ae 1822 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 1823
40381db7 1824 if (pi->extra && pi->extra->suppress)
d62a17ae 1825 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
40381db7 1826 RMAP_BGP, &rmap_path);
d62a17ae 1827 else
1828 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
40381db7 1829 RMAP_BGP, &rmap_path);
d62a17ae 1830
1831 peer->rmap_type = 0;
1832
1833 if (ret == RMAP_DENYMATCH) {
778048bf
AD
1834 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1835 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1836 peer->host, prefix2str(p, buf, sizeof(buf)));
1837
d62a17ae 1838 bgp_attr_flush(attr);
1839 return 0;
1840 }
3f9c7369 1841 }
3f9c7369 1842
9dac9fc8
DA
1843 /* RFC 8212 to prevent route leaks.
1844 * This specification intends to improve this situation by requiring the
1845 * explicit configuration of both BGP Import and Export Policies for any
1846 * External BGP (EBGP) session such as customers, peers, or
1847 * confederation boundaries for all enabled address families. Through
1848 * codification of the aforementioned requirement, operators will
1849 * benefit from consistent behavior across different BGP
1850 * implementations.
1851 */
1852 if (peer->bgp->ebgp_requires_policy
1853 == DEFAULT_EBGP_POLICY_ENABLED)
1854 if (!bgp_outbound_policy_exists(peer, filter))
1855 return 0;
1856
7f323236 1857 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
a4d82a8a
PZ
1858 if (peer->sort == BGP_PEER_IBGP
1859 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
1860 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1861 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1862 } else {
1863 bgp_attr_add_gshut_community(attr);
1864 }
1865 }
1866
d62a17ae 1867 /* After route-map has been applied, we check to see if the nexthop to
1868 * be carried in the attribute (that is used for the announcement) can
1869 * be cleared off or not. We do this in all cases where we would be
1870 * setting the nexthop to "ourselves". For IPv6, we only need to
1871 * consider
1872 * the global nexthop here; the link-local nexthop would have been
1873 * cleared
1874 * already, and if not, it is required by the update formation code.
1875 * Also see earlier comments in this function.
1876 */
1877 /*
1878 * If route-map has performed some operation on the nexthop or the peer
1879 * configuration says to pass it unchanged, we cannot reset the nexthop
1880 * here, so only attempt to do it if these aren't true. Note that the
1881 * route-map handler itself might have cleared the nexthop, if for
1882 * example,
1883 * it is configured as 'peer-address'.
1884 */
1885 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 1886 piattr->rmap_change_flags)
d62a17ae 1887 && !transparent
1888 && !CHECK_FLAG(peer->af_flags[afi][safi],
1889 PEER_FLAG_NEXTHOP_UNCHANGED)) {
1890 /* We can reset the nexthop, if setting (or forcing) it to
1891 * 'self' */
1892 if (CHECK_FLAG(peer->af_flags[afi][safi],
1893 PEER_FLAG_NEXTHOP_SELF)
1894 || CHECK_FLAG(peer->af_flags[afi][safi],
1895 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
1896 if (!reflect
1897 || CHECK_FLAG(peer->af_flags[afi][safi],
1898 PEER_FLAG_FORCE_NEXTHOP_SELF))
1899 subgroup_announce_reset_nhop(
1900 (peer_cap_enhe(peer, afi, safi)
1901 ? AF_INET6
1902 : p->family),
1903 attr);
1904 } else if (peer->sort == BGP_PEER_EBGP) {
1905 /* Can also reset the nexthop if announcing to EBGP, but
1906 * only if
1907 * no peer in the subgroup is on a shared subnet.
1908 * Note: 3rd party nexthop currently implemented for
1909 * IPv4 only.
1910 */
737af885
BS
1911 if ((p->family == AF_INET) &&
1912 (!bgp_subgrp_multiaccess_check_v4(
1913 piattr->nexthop,
1914 subgrp)))
d62a17ae 1915 subgroup_announce_reset_nhop(
1916 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
1917 ? AF_INET6
1918 : p->family),
737af885
BS
1919 attr);
1920
1921 if ((p->family == AF_INET6) &&
1922 (!bgp_subgrp_multiaccess_check_v6(
1923 piattr->mp_nexthop_global,
1924 subgrp)))
1925 subgroup_announce_reset_nhop(
1926 (peer_cap_enhe(peer, afi, safi)
1927 ? AF_INET6
1928 : p->family),
1929 attr);
1930
1931
1932
40381db7 1933 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
1934 /*
1935 * This flag is used for leaked vpn-vrf routes
1936 */
1937 int family = p->family;
1938
1939 if (peer_cap_enhe(peer, afi, safi))
1940 family = AF_INET6;
1941
1942 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1943 zlog_debug(
1defdda8 1944 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
1945 __func__, family2str(family));
1946 subgroup_announce_reset_nhop(family, attr);
d62a17ae 1947 }
63696f1d 1948 }
960035b2 1949
63696f1d 1950 /* If IPv6/MP and nexthop does not have any override and happens
1951 * to
1952 * be a link-local address, reset it so that we don't pass along
1953 * the
1954 * source's link-local IPv6 address to recipients who may not be
1955 * on
1956 * the same interface.
1957 */
1958 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
1959 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global))
1960 subgroup_announce_reset_nhop(AF_INET6, attr);
d62a17ae 1961 }
3f9c7369 1962
d62a17ae 1963 return 1;
3f9c7369
DS
1964}
1965
d62a17ae 1966void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
1967 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
1968 struct bgp_path_info_pair *result, afi_t afi,
1969 safi_t safi)
1970{
1971 struct bgp_path_info *new_select;
1972 struct bgp_path_info *old_select;
40381db7
DS
1973 struct bgp_path_info *pi;
1974 struct bgp_path_info *pi1;
1975 struct bgp_path_info *pi2;
1976 struct bgp_path_info *nextpi = NULL;
d62a17ae 1977 int paths_eq, do_mpath, debug;
1978 struct list mp_list;
1979 char pfx_buf[PREFIX2STR_BUFFER];
1980 char path_buf[PATH_ADDPATH_STR_BUFFER];
1981
1982 bgp_mp_list_init(&mp_list);
1983 do_mpath =
1984 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
1985
1986 debug = bgp_debug_bestpath(&rn->p);
1987
1988 if (debug)
1989 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
1990
1991 /* bgp deterministic-med */
1992 new_select = NULL;
1993 if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)) {
1994
1defdda8 1995 /* Clear BGP_PATH_DMED_SELECTED for all paths */
6f94b685
DS
1996 for (pi1 = bgp_node_get_bgp_path_info(rn); pi1;
1997 pi1 = pi1->next)
40381db7 1998 bgp_path_info_unset_flag(rn, pi1,
18ee8310 1999 BGP_PATH_DMED_SELECTED);
d62a17ae 2000
6f94b685
DS
2001 for (pi1 = bgp_node_get_bgp_path_info(rn); pi1;
2002 pi1 = pi1->next) {
40381db7 2003 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2004 continue;
40381db7 2005 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2006 continue;
ea8b2282 2007 if (pi1->peer != bgp->peer_self)
40381db7 2008 if (pi1->peer->status != Established)
d62a17ae 2009 continue;
2010
40381db7
DS
2011 new_select = pi1;
2012 if (pi1->next) {
2013 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2014 if (CHECK_FLAG(pi2->flags,
1defdda8 2015 BGP_PATH_DMED_CHECK))
d62a17ae 2016 continue;
40381db7 2017 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2018 continue;
ea8b2282 2019 if (pi2->peer != bgp->peer_self
d62a17ae 2020 && !CHECK_FLAG(
ea8b2282
DS
2021 pi2->peer->sflags,
2022 PEER_STATUS_NSF_WAIT))
40381db7 2023 if (pi2->peer->status
d62a17ae 2024 != Established)
2025 continue;
2026
121e245d
DS
2027 if (!aspath_cmp_left(pi1->attr->aspath,
2028 pi2->attr->aspath)
2029 && !aspath_cmp_left_confed(
40381db7 2030 pi1->attr->aspath,
121e245d
DS
2031 pi2->attr->aspath))
2032 continue;
d62a17ae 2033
121e245d
DS
2034 if (bgp_path_info_cmp(
2035 bgp, pi2, new_select,
2036 &paths_eq, mpath_cfg, debug,
fdf81fa0
DS
2037 pfx_buf, afi, safi,
2038 &rn->reason)) {
121e245d
DS
2039 bgp_path_info_unset_flag(
2040 rn, new_select,
2041 BGP_PATH_DMED_SELECTED);
2042 new_select = pi2;
d62a17ae 2043 }
121e245d
DS
2044
2045 bgp_path_info_set_flag(
2046 rn, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2047 }
2048 }
18ee8310
DS
2049 bgp_path_info_set_flag(rn, new_select,
2050 BGP_PATH_DMED_CHECK);
2051 bgp_path_info_set_flag(rn, new_select,
2052 BGP_PATH_DMED_SELECTED);
d62a17ae 2053
2054 if (debug) {
18ee8310
DS
2055 bgp_path_info_path_with_addpath_rx_str(
2056 new_select, path_buf);
c66faab1 2057 zlog_debug("%s: %s is the bestpath from AS %u",
d62a17ae 2058 pfx_buf, path_buf,
2059 aspath_get_first_as(
2060 new_select->attr->aspath));
2061 }
2062 }
2063 }
96450faf 2064
d62a17ae 2065 /* Check old selected route and new selected route. */
2066 old_select = NULL;
2067 new_select = NULL;
6f94b685
DS
2068 for (pi = bgp_node_get_bgp_path_info(rn);
2069 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
40381db7
DS
2070 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2071 old_select = pi;
d62a17ae 2072
40381db7 2073 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2074 /* reap REMOVED routes, if needs be
2075 * selected route must stay for a while longer though
2076 */
40381db7
DS
2077 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2078 && (pi != old_select))
2079 bgp_path_info_reap(rn, pi);
d62a17ae 2080
ddb5b488 2081 if (debug)
40381db7
DS
2082 zlog_debug("%s: pi %p in holddown", __func__,
2083 pi);
ddb5b488 2084
d62a17ae 2085 continue;
2086 }
96450faf 2087
40381db7
DS
2088 if (pi->peer && pi->peer != bgp->peer_self
2089 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2090 if (pi->peer->status != Established) {
ddb5b488
PZ
2091
2092 if (debug)
2093 zlog_debug(
40381db7
DS
2094 "%s: pi %p non self peer %s not estab state",
2095 __func__, pi, pi->peer->host);
ddb5b488 2096
d62a17ae 2097 continue;
ddb5b488 2098 }
9fbdd100 2099
d62a17ae 2100 if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)
40381db7
DS
2101 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
2102 bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2103 if (debug)
40381db7 2104 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2105 continue;
2106 }
9fbdd100 2107
40381db7 2108 bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK);
06370dac 2109
40381db7 2110 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
fdf81fa0 2111 debug, pfx_buf, afi, safi, &rn->reason)) {
40381db7 2112 new_select = pi;
d62a17ae 2113 }
2114 }
718e3744 2115
d62a17ae 2116 /* Now that we know which path is the bestpath see if any of the other
2117 * paths
2118 * qualify as multipaths
2119 */
2120 if (debug) {
2121 if (new_select)
18ee8310
DS
2122 bgp_path_info_path_with_addpath_rx_str(new_select,
2123 path_buf);
d62a17ae 2124 else
2125 sprintf(path_buf, "NONE");
2126 zlog_debug(
2127 "%s: After path selection, newbest is %s oldbest was %s",
2128 pfx_buf, path_buf,
2129 old_select ? old_select->peer->host : "NONE");
96450faf 2130 }
9fbdd100 2131
d62a17ae 2132 if (do_mpath && new_select) {
6f94b685
DS
2133 for (pi = bgp_node_get_bgp_path_info(rn);
2134 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2135
2136 if (debug)
18ee8310 2137 bgp_path_info_path_with_addpath_rx_str(
40381db7 2138 pi, path_buf);
d62a17ae 2139
40381db7 2140 if (pi == new_select) {
d62a17ae 2141 if (debug)
2142 zlog_debug(
2143 "%s: %s is the bestpath, add to the multipath list",
2144 pfx_buf, path_buf);
40381db7 2145 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2146 continue;
2147 }
2148
40381db7 2149 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2150 continue;
2151
40381db7
DS
2152 if (pi->peer && pi->peer != bgp->peer_self
2153 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2154 PEER_STATUS_NSF_WAIT))
40381db7 2155 if (pi->peer->status != Established)
d62a17ae 2156 continue;
2157
40381db7 2158 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2159 if (debug)
2160 zlog_debug(
2161 "%s: %s has the same nexthop as the bestpath, skip it",
2162 pfx_buf, path_buf);
2163 continue;
2164 }
2165
40381db7 2166 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0
DS
2167 mpath_cfg, debug, pfx_buf, afi, safi,
2168 &rn->reason);
d62a17ae 2169
2170 if (paths_eq) {
2171 if (debug)
2172 zlog_debug(
2173 "%s: %s is equivalent to the bestpath, add to the multipath list",
2174 pfx_buf, path_buf);
40381db7 2175 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2176 }
2177 }
2178 }
fee0f4c6 2179
18ee8310
DS
2180 bgp_path_info_mpath_update(rn, new_select, old_select, &mp_list,
2181 mpath_cfg);
2182 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2183 bgp_mp_list_clear(&mp_list);
96450faf 2184
dcc68b5e
MS
2185 bgp_addpath_update_ids(bgp, rn, afi, safi);
2186
d62a17ae 2187 result->old = old_select;
2188 result->new = new_select;
96450faf 2189
d62a17ae 2190 return;
fee0f4c6 2191}
2192
3f9c7369
DS
2193/*
2194 * A new route/change in bestpath of an existing route. Evaluate the path
2195 * for advertisement to the subgroup.
2196 */
d62a17ae 2197int subgroup_process_announce_selected(struct update_subgroup *subgrp,
4b7e6066 2198 struct bgp_path_info *selected,
d62a17ae 2199 struct bgp_node *rn,
d7c0a89a 2200 uint32_t addpath_tx_id)
d62a17ae 2201{
2202 struct prefix *p;
2203 struct peer *onlypeer;
2204 struct attr attr;
2205 afi_t afi;
2206 safi_t safi;
adbac85e 2207
d62a17ae 2208 p = &rn->p;
2209 afi = SUBGRP_AFI(subgrp);
2210 safi = SUBGRP_SAFI(subgrp);
2211 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2212 : NULL);
2213
e0207895
PZ
2214 if (BGP_DEBUG(update, UPDATE_OUT)) {
2215 char buf_prefix[PREFIX_STRLEN];
2216 prefix2str(p, buf_prefix, sizeof(buf_prefix));
ddb5b488
PZ
2217 zlog_debug("%s: p=%s, selected=%p", __func__, buf_prefix,
2218 selected);
e0207895
PZ
2219 }
2220
d62a17ae 2221 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2222 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2223 PEER_STATUS_ORF_WAIT_REFRESH))
d62a17ae 2224 return 0;
2225
2226 memset(&attr, 0, sizeof(struct attr));
2227 /* It's initialized in bgp_announce_check() */
2228
2229 /* Announcement to the subgroup. If the route is filtered withdraw it.
2230 */
2231 if (selected) {
2232 if (subgroup_announce_check(rn, selected, subgrp, p, &attr))
2233 bgp_adj_out_set_subgroup(rn, subgrp, &attr, selected);
2234 else
2235 bgp_adj_out_unset_subgroup(rn, subgrp, 1,
dcc68b5e 2236 addpath_tx_id);
d62a17ae 2237 }
2238
2239 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2240 else {
2241 bgp_adj_out_unset_subgroup(rn, subgrp, 1, addpath_tx_id);
2242 }
558d1fec 2243
d62a17ae 2244 return 0;
200df115 2245}
fee0f4c6 2246
3064bf43 2247/*
e1072051 2248 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2249 * This is called at the end of route processing.
3064bf43 2250 */
d62a17ae 2251void bgp_zebra_clear_route_change_flags(struct bgp_node *rn)
3064bf43 2252{
40381db7 2253 struct bgp_path_info *pi;
3064bf43 2254
6f94b685 2255 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 2256 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2257 continue;
40381db7
DS
2258 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2259 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2260 }
3064bf43 2261}
2262
2263/*
2264 * Has the route changed from the RIB's perspective? This is invoked only
2265 * if the route selection returns the same best route as earlier - to
2266 * determine if we need to update zebra or not.
2267 */
4b7e6066
DS
2268int bgp_zebra_has_route_changed(struct bgp_node *rn,
2269 struct bgp_path_info *selected)
d62a17ae 2270{
4b7e6066 2271 struct bgp_path_info *mpinfo;
d62a17ae 2272
2bb9eff4
DS
2273 /* If this is multipath, check all selected paths for any nexthop
2274 * change or attribute change. Some attribute changes (e.g., community)
2275 * aren't of relevance to the RIB, but we'll update zebra to ensure
2276 * we handle the case of BGP nexthop change. This is the behavior
2277 * when the best path has an attribute change anyway.
d62a17ae 2278 */
1defdda8
DS
2279 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
2280 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG))
d62a17ae 2281 return 1;
2282
2bb9eff4
DS
2283 /*
2284 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2285 */
18ee8310
DS
2286 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2287 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2288 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2289 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
d62a17ae 2290 return 1;
2291 }
3064bf43 2292
d62a17ae 2293 /* Nothing has changed from the RIB's perspective. */
2294 return 0;
3064bf43 2295}
2296
d62a17ae 2297struct bgp_process_queue {
2298 struct bgp *bgp;
a4d82a8a 2299 STAILQ_HEAD(, bgp_node) pqueue;
aac24838
JB
2300#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2301 unsigned int flags;
2302 unsigned int queued;
200df115 2303};
2304
3103e8d2
DS
2305/*
2306 * old_select = The old best path
2307 * new_select = the new best path
2308 *
2309 * if (!old_select && new_select)
2310 * We are sending new information on.
2311 *
2312 * if (old_select && new_select) {
2313 * if (new_select != old_select)
2314 * We have a new best path send a change
2315 * else
2316 * We've received a update with new attributes that needs
2317 * to be passed on.
2318 * }
2319 *
2320 * if (old_select && !new_select)
2321 * We have no eligible route that we can announce or the rn
2322 * is being removed.
2323 */
aac24838
JB
2324static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
2325 afi_t afi, safi_t safi)
d62a17ae 2326{
4b7e6066
DS
2327 struct bgp_path_info *new_select;
2328 struct bgp_path_info *old_select;
2329 struct bgp_path_info_pair old_and_new;
ddb5b488
PZ
2330 char pfx_buf[PREFIX2STR_BUFFER];
2331 int debug = 0;
d62a17ae 2332
f4c713ae
LB
2333 if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS)) {
2334 if (rn)
2335 debug = bgp_debug_bestpath(&rn->p);
2336 if (debug) {
2337 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2338 zlog_debug(
2339 "%s: bgp delete in progress, ignoring event, p=%s",
2340 __func__, pfx_buf);
2341 }
2342 return;
2343 }
d62a17ae 2344 /* Is it end of initial update? (after startup) */
2345 if (!rn) {
2346 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2347 sizeof(bgp->update_delay_zebra_resume_time));
2348
2349 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2350 FOREACH_AFI_SAFI (afi, safi) {
2351 if (bgp_fibupd_safi(safi))
2352 bgp_zebra_announce_table(bgp, afi, safi);
2353 }
d62a17ae 2354 bgp->main_peers_update_hold = 0;
2355
2356 bgp_start_routeadv(bgp);
aac24838 2357 return;
d62a17ae 2358 }
cb1faec9 2359
b575a12c
A
2360 struct prefix *p = &rn->p;
2361
ddb5b488
PZ
2362 debug = bgp_debug_bestpath(&rn->p);
2363 if (debug) {
2364 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2365 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__, pfx_buf,
2366 afi2str(afi), safi2str(safi));
2367 }
2368
d62a17ae 2369 /* Best path selection. */
2370 bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new,
2371 afi, safi);
2372 old_select = old_and_new.old;
2373 new_select = old_and_new.new;
2374
2375 /* Do we need to allocate or free labels?
2376 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2377 * necessary to do this upon changes to best path. Exceptions:
2378 * - label index has changed -> recalculate resulting label
2379 * - path_info sub_type changed -> switch to/from implicit-null
2380 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2381 */
318cac96 2382 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2383 if (new_select) {
2384 if (!old_select
2385 || bgp_label_index_differs(new_select, old_select)
57592a53
AD
2386 || new_select->sub_type != old_select->sub_type
2387 || !bgp_is_valid_label(&rn->local_label)) {
2388 /* Enforced penultimate hop popping:
2389 * implicit-null for local routes, aggregate
2390 * and redistributed routes
2391 */
d62a17ae 2392 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2393 || new_select->sub_type
2394 == BGP_ROUTE_AGGREGATE
2395 || new_select->sub_type
2396 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2397 if (CHECK_FLAG(
2398 rn->flags,
2399 BGP_NODE_REGISTERED_FOR_LABEL))
2400 bgp_unregister_for_label(rn);
70e98a7f 2401 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
d62a17ae 2402 &rn->local_label);
2403 bgp_set_valid_label(&rn->local_label);
2404 } else
2405 bgp_register_for_label(rn, new_select);
2406 }
a4d82a8a
PZ
2407 } else if (CHECK_FLAG(rn->flags,
2408 BGP_NODE_REGISTERED_FOR_LABEL)) {
d62a17ae 2409 bgp_unregister_for_label(rn);
318cac96
DW
2410 }
2411 } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
2412 bgp_unregister_for_label(rn);
d62a17ae 2413 }
cd1964ff 2414
ddb5b488
PZ
2415 if (debug) {
2416 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2417 zlog_debug(
2418 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2419 __func__, pfx_buf, afi2str(afi), safi2str(safi),
2420 old_select, new_select);
2421 }
2422
d62a17ae 2423 /* If best route remains the same and this is not due to user-initiated
2424 * clear, see exactly what needs to be done.
2425 */
d62a17ae 2426 if (old_select && old_select == new_select
2427 && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
1defdda8 2428 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2429 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 2430 if (bgp_zebra_has_route_changed(rn, old_select)) {
65efcfce 2431#if ENABLE_BGP_VNC
d62a17ae 2432 vnc_import_bgp_add_route(bgp, p, old_select);
2433 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2434#endif
bb744275 2435 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2436 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2437
2438 if (new_select->type == ZEBRA_ROUTE_BGP
2439 && (new_select->sub_type == BGP_ROUTE_NORMAL
2440 || new_select->sub_type
2441 == BGP_ROUTE_IMPORTED))
2442
2443 bgp_zebra_announce(rn, p, old_select,
2444 bgp, afi, safi);
2445 }
d62a17ae 2446 }
1defdda8 2447 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
d62a17ae 2448 bgp_zebra_clear_route_change_flags(rn);
2449
2450 /* If there is a change of interest to peers, reannounce the
2451 * route. */
1defdda8 2452 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
d62a17ae 2453 || CHECK_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED)) {
2454 group_announce_route(bgp, afi, safi, rn, new_select);
2455
2456 /* unicast routes must also be annouced to
2457 * labeled-unicast update-groups */
2458 if (safi == SAFI_UNICAST)
2459 group_announce_route(bgp, afi,
2460 SAFI_LABELED_UNICAST, rn,
2461 new_select);
2462
1defdda8 2463 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2464 UNSET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED);
2465 }
fee0f4c6 2466
d62a17ae 2467 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2468 return;
d62a17ae 2469 }
8ad7271d 2470
d62a17ae 2471 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2472 */
2473 UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR);
2474
2475 /* bestpath has changed; bump version */
2476 if (old_select || new_select) {
2477 bgp_bump_version(rn);
2478
2479 if (!bgp->t_rmap_def_originate_eval) {
2480 bgp_lock(bgp);
2481 thread_add_timer(
2482 bm->master,
2483 update_group_refresh_default_originate_route_map,
2484 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2485 &bgp->t_rmap_def_originate_eval);
2486 }
2487 }
3f9c7369 2488
d62a17ae 2489 if (old_select)
18ee8310 2490 bgp_path_info_unset_flag(rn, old_select, BGP_PATH_SELECTED);
d62a17ae 2491 if (new_select) {
ddb5b488
PZ
2492 if (debug)
2493 zlog_debug("%s: setting SELECTED flag", __func__);
18ee8310
DS
2494 bgp_path_info_set_flag(rn, new_select, BGP_PATH_SELECTED);
2495 bgp_path_info_unset_flag(rn, new_select, BGP_PATH_ATTR_CHANGED);
1defdda8 2496 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
d62a17ae 2497 }
338b3424 2498
65efcfce 2499#if ENABLE_BGP_VNC
d62a17ae 2500 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2501 if (old_select != new_select) {
2502 if (old_select) {
2503 vnc_import_bgp_exterior_del_route(bgp, p,
2504 old_select);
2505 vnc_import_bgp_del_route(bgp, p, old_select);
2506 }
2507 if (new_select) {
2508 vnc_import_bgp_exterior_add_route(bgp, p,
2509 new_select);
2510 vnc_import_bgp_add_route(bgp, p, new_select);
2511 }
2512 }
2513 }
65efcfce
LB
2514#endif
2515
d62a17ae 2516 group_announce_route(bgp, afi, safi, rn, new_select);
2517
2518 /* unicast routes must also be annouced to labeled-unicast update-groups
2519 */
2520 if (safi == SAFI_UNICAST)
2521 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, rn,
2522 new_select);
2523
2524 /* FIB update. */
2525 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2526 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2527 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2528 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2529 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2530 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2531
2532 /* if this is an evpn imported type-5 prefix,
2533 * we need to withdraw the route first to clear
2534 * the nh neigh and the RMAC entry.
2535 */
2536 if (old_select &&
2537 is_route_parent_evpn(old_select))
2538 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2539
d62a17ae 2540 bgp_zebra_announce(rn, p, new_select, bgp, afi, safi);
2b659f33 2541 } else {
d62a17ae 2542 /* Withdraw the route from the kernel. */
2543 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2544 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2545 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2546 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2547
568e10ca 2548 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2549 }
718e3744 2550 }
3064bf43 2551
5424b7ba
MK
2552 /* advertise/withdraw type-5 routes */
2553 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
f106e3a7 2554 if (advertise_type5_routes(bgp, afi) &&
2555 new_select &&
2556 is_route_injectable_into_evpn(new_select)) {
7e4ed18e
MK
2557
2558 /* apply the route-map */
2559 if (bgp->adv_cmd_rmap[afi][safi].map) {
b68885f9 2560 route_map_result_t ret;
7e4ed18e 2561
3518f352
DS
2562 ret = route_map_apply(
2563 bgp->adv_cmd_rmap[afi][safi].map,
2564 &rn->p, RMAP_BGP, new_select);
b68885f9 2565 if (ret == RMAP_PERMITMATCH)
3518f352
DS
2566 bgp_evpn_advertise_type5_route(
2567 bgp, &rn->p, new_select->attr,
2568 afi, safi);
c27ee4c4 2569 else
2570 bgp_evpn_withdraw_type5_route(
2571 bgp, &rn->p, afi, safi);
7e4ed18e
MK
2572 } else {
2573 bgp_evpn_advertise_type5_route(bgp,
2574 &rn->p,
2575 new_select->attr,
2576 afi, safi);
2577
2578 }
f106e3a7 2579 } else if (advertise_type5_routes(bgp, afi) &&
2580 old_select &&
2581 is_route_injectable_into_evpn(old_select))
31310b25 2582 bgp_evpn_withdraw_type5_route(bgp, &rn->p, afi, safi);
5424b7ba
MK
2583 }
2584
d62a17ae 2585 /* Clear any route change flags. */
2586 bgp_zebra_clear_route_change_flags(rn);
3064bf43 2587
18ee8310 2588 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2589 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
18ee8310 2590 bgp_path_info_reap(rn, old_select);
d62a17ae 2591
2592 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2593 return;
718e3744 2594}
2595
aac24838 2596static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 2597{
aac24838
JB
2598 struct bgp_process_queue *pqnode = data;
2599 struct bgp *bgp = pqnode->bgp;
d62a17ae 2600 struct bgp_table *table;
ac021f40 2601 struct bgp_node *rn;
aac24838
JB
2602
2603 /* eoiu marker */
2604 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
2605 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
2606 /* should always have dedicated wq call */
2607 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
2608 return WQ_SUCCESS;
2609 }
2610
ac021f40
LB
2611 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
2612 rn = STAILQ_FIRST(&pqnode->pqueue);
2613 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
b3e1dd3c 2614 STAILQ_NEXT(rn, pq) = NULL; /* complete unlink */
aac24838 2615 table = bgp_node_table(rn);
ac021f40 2616 /* note, new RNs may be added as part of processing */
aac24838 2617 bgp_process_main_one(bgp, rn, table->afi, table->safi);
cb1faec9 2618
aac24838 2619 bgp_unlock_node(rn);
d62a17ae 2620 bgp_table_unlock(table);
2621 }
aac24838
JB
2622
2623 return WQ_SUCCESS;
2624}
2625
2626static void bgp_processq_del(struct work_queue *wq, void *data)
2627{
2628 struct bgp_process_queue *pqnode = data;
2629
2630 bgp_unlock(pqnode->bgp);
2631
2632 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 2633}
2634
d62a17ae 2635void bgp_process_queue_init(void)
200df115 2636{
0ce1ca80 2637 if (!bm->process_main_queue)
d62a17ae 2638 bm->process_main_queue =
2639 work_queue_new(bm->master, "process_main_queue");
2640
aac24838 2641 bm->process_main_queue->spec.workfunc = &bgp_process_wq;
d62a17ae 2642 bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
2643 bm->process_main_queue->spec.max_retries = 0;
2644 bm->process_main_queue->spec.hold = 50;
2645 /* Use a higher yield value of 50ms for main queue processing */
2646 bm->process_main_queue->spec.yield = 50 * 1000L;
200df115 2647}
2648
cfe8d15a 2649static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
2650{
2651 struct bgp_process_queue *pqnode;
2652
a4d82a8a
PZ
2653 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
2654 sizeof(struct bgp_process_queue));
aac24838
JB
2655
2656 /* unlocked in bgp_processq_del */
2657 pqnode->bgp = bgp_lock(bgp);
2658 STAILQ_INIT(&pqnode->pqueue);
2659
aac24838
JB
2660 return pqnode;
2661}
2662
d62a17ae 2663void bgp_process(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)
fee0f4c6 2664{
aac24838
JB
2665#define ARBITRARY_PROCESS_QLEN 10000
2666 struct work_queue *wq = bm->process_main_queue;
d62a17ae 2667 struct bgp_process_queue *pqnode;
cfe8d15a 2668 int pqnode_reuse = 0;
495f0b13 2669
d62a17ae 2670 /* already scheduled for processing? */
2671 if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED))
2672 return;
2e02b9b2 2673
aac24838 2674 if (wq == NULL)
d62a17ae 2675 return;
2676
aac24838 2677 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
2678 limit only if is from the same BGP view and it's not an EOIU marker
2679 */
aac24838
JB
2680 if (work_queue_item_count(wq)) {
2681 struct work_queue_item *item = work_queue_last_item(wq);
2682 pqnode = item->data;
228da428 2683
a4d82a8a
PZ
2684 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
2685 || pqnode->bgp != bgp
2686 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
2687 pqnode = bgp_processq_alloc(bgp);
2688 else
2689 pqnode_reuse = 1;
aac24838 2690 } else
cfe8d15a 2691 pqnode = bgp_processq_alloc(bgp);
aac24838 2692 /* all unlocked in bgp_process_wq */
d62a17ae 2693 bgp_table_lock(bgp_node_table(rn));
aac24838 2694
d62a17ae 2695 SET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838
JB
2696 bgp_lock_node(rn);
2697
60466a63
QY
2698 /* can't be enqueued twice */
2699 assert(STAILQ_NEXT(rn, pq) == NULL);
aac24838
JB
2700 STAILQ_INSERT_TAIL(&pqnode->pqueue, rn, pq);
2701 pqnode->queued++;
2702
cfe8d15a
LB
2703 if (!pqnode_reuse)
2704 work_queue_add(wq, pqnode);
2705
d62a17ae 2706 return;
fee0f4c6 2707}
0a486e5f 2708
d62a17ae 2709void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 2710{
d62a17ae 2711 struct bgp_process_queue *pqnode;
cb1faec9 2712
d62a17ae 2713 if (bm->process_main_queue == NULL)
2714 return;
2e02b9b2 2715
cfe8d15a 2716 pqnode = bgp_processq_alloc(bgp);
cb1faec9 2717
aac24838 2718 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
cfe8d15a 2719 work_queue_add(bm->process_main_queue, pqnode);
cb1faec9
DS
2720}
2721
d62a17ae 2722static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 2723{
d62a17ae 2724 struct peer *peer;
0a486e5f 2725
d62a17ae 2726 peer = THREAD_ARG(thread);
2727 peer->t_pmax_restart = NULL;
0a486e5f 2728
d62a17ae 2729 if (bgp_debug_neighbor_events(peer))
2730 zlog_debug(
2731 "%s Maximum-prefix restart timer expired, restore peering",
2732 peer->host);
0a486e5f 2733
a9bafa95
DS
2734 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
2735 zlog_debug("%s: %s peer_clear failed",
2736 __PRETTY_FUNCTION__, peer->host);
0a486e5f 2737
d62a17ae 2738 return 0;
0a486e5f 2739}
2740
d62a17ae 2741int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
2742 int always)
718e3744 2743{
d62a17ae 2744 iana_afi_t pkt_afi;
5c525538 2745 iana_safi_t pkt_safi;
9cabb64b 2746
d62a17ae 2747 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
2748 return 0;
e0701b79 2749
d62a17ae 2750 if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) {
2751 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2752 PEER_STATUS_PREFIX_LIMIT)
2753 && !always)
2754 return 0;
e0701b79 2755
d62a17ae 2756 zlog_info(
a0a87037
DA
2757 "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32
2758 " exceed, limit %" PRIu32,
5cb5f4d0 2759 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 2760 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2761 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
2762
2763 if (CHECK_FLAG(peer->af_flags[afi][safi],
2764 PEER_FLAG_MAX_PREFIX_WARNING))
2765 return 0;
2766
2767 /* Convert AFI, SAFI to values for packet. */
2768 pkt_afi = afi_int2iana(afi);
2769 pkt_safi = safi_int2iana(safi);
2770 {
d7c0a89a 2771 uint8_t ndata[7];
d62a17ae 2772
2773 ndata[0] = (pkt_afi >> 8);
2774 ndata[1] = pkt_afi;
2775 ndata[2] = pkt_safi;
2776 ndata[3] = (peer->pmax[afi][safi] >> 24);
2777 ndata[4] = (peer->pmax[afi][safi] >> 16);
2778 ndata[5] = (peer->pmax[afi][safi] >> 8);
2779 ndata[6] = (peer->pmax[afi][safi]);
2780
2781 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2782 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
2783 BGP_NOTIFY_CEASE_MAX_PREFIX,
2784 ndata, 7);
2785 }
2786
2787 /* Dynamic peers will just close their connection. */
2788 if (peer_dynamic_neighbor(peer))
2789 return 1;
2790
2791 /* restart timer start */
2792 if (peer->pmax_restart[afi][safi]) {
2793 peer->v_pmax_restart =
2794 peer->pmax_restart[afi][safi] * 60;
2795
2796 if (bgp_debug_neighbor_events(peer))
2797 zlog_debug(
2798 "%s Maximum-prefix restart timer started for %d secs",
2799 peer->host, peer->v_pmax_restart);
2800
2801 BGP_TIMER_ON(peer->t_pmax_restart,
2802 bgp_maximum_prefix_restart_timer,
2803 peer->v_pmax_restart);
2804 }
2805
2806 return 1;
2807 } else
2808 UNSET_FLAG(peer->af_sflags[afi][safi],
2809 PEER_STATUS_PREFIX_LIMIT);
2810
2811 if (peer->pcount[afi][safi]
2812 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
2813 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2814 PEER_STATUS_PREFIX_THRESHOLD)
2815 && !always)
2816 return 0;
2817
2818 zlog_info(
a0a87037
DA
2819 "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32
2820 ", max %" PRIu32,
5cb5f4d0 2821 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 2822 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2823 SET_FLAG(peer->af_sflags[afi][safi],
2824 PEER_STATUS_PREFIX_THRESHOLD);
2825 } else
2826 UNSET_FLAG(peer->af_sflags[afi][safi],
2827 PEER_STATUS_PREFIX_THRESHOLD);
2828 return 0;
718e3744 2829}
2830
b40d939b 2831/* Unconditionally remove the route from the RIB, without taking
2832 * damping into consideration (eg, because the session went down)
2833 */
40381db7 2834void bgp_rib_remove(struct bgp_node *rn, struct bgp_path_info *pi,
4b7e6066 2835 struct peer *peer, afi_t afi, safi_t safi)
718e3744 2836{
40381db7 2837 bgp_aggregate_decrement(peer->bgp, &rn->p, pi, afi, safi);
d62a17ae 2838
40381db7
DS
2839 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
2840 bgp_path_info_delete(rn, pi); /* keep historical info */
d62a17ae 2841
4a11bf2c
DL
2842 hook_call(bgp_process, peer->bgp, afi, safi, rn, peer, true);
2843
d62a17ae 2844 bgp_process(peer->bgp, rn, afi, safi);
2845}
2846
40381db7 2847static void bgp_rib_withdraw(struct bgp_node *rn, struct bgp_path_info *pi,
d62a17ae 2848 struct peer *peer, afi_t afi, safi_t safi,
2849 struct prefix_rd *prd)
2850{
d62a17ae 2851 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 2852 * the bgp_path_info in the RIB for historical reference.
d62a17ae 2853 */
2854 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
2855 && peer->sort == BGP_PEER_EBGP)
40381db7 2856 if ((bgp_damp_withdraw(pi, rn, afi, safi, 0))
d62a17ae 2857 == BGP_DAMP_SUPPRESSED) {
40381db7 2858 bgp_aggregate_decrement(peer->bgp, &rn->p, pi, afi,
d62a17ae 2859 safi);
2860 return;
2861 }
2862
65efcfce 2863#if ENABLE_BGP_VNC
d62a17ae 2864 if (safi == SAFI_MPLS_VPN) {
2865 struct bgp_node *prn = NULL;
2866 struct bgp_table *table = NULL;
2867
2868 prn = bgp_node_get(peer->bgp->rib[afi][safi],
2869 (struct prefix *)prd);
67009e22
DS
2870 if (bgp_node_has_bgp_path_info_data(prn)) {
2871 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 2872
2873 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 2874 peer->bgp, prd, table, &rn->p, pi);
d62a17ae 2875 }
2876 bgp_unlock_node(prn);
2877 }
2878 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 2879 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 2880
40381db7 2881 vnc_import_bgp_del_route(peer->bgp, &rn->p, pi);
d62a17ae 2882 vnc_import_bgp_exterior_del_route(peer->bgp, &rn->p,
40381db7 2883 pi);
d62a17ae 2884 }
65efcfce 2885 }
d62a17ae 2886#endif
128ea8ab 2887
d62a17ae 2888 /* If this is an EVPN route, process for un-import. */
2889 if (safi == SAFI_EVPN)
40381db7 2890 bgp_evpn_unimport_route(peer->bgp, afi, safi, &rn->p, pi);
128ea8ab 2891
40381db7 2892 bgp_rib_remove(rn, pi, peer, afi, safi);
718e3744 2893}
2894
4b7e6066
DS
2895struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
2896 struct peer *peer, struct attr *attr,
2897 struct bgp_node *rn)
fb018d25 2898{
4b7e6066 2899 struct bgp_path_info *new;
fb018d25 2900
d62a17ae 2901 /* Make new BGP info. */
4b7e6066 2902 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 2903 new->type = type;
2904 new->instance = instance;
2905 new->sub_type = sub_type;
2906 new->peer = peer;
2907 new->attr = attr;
2908 new->uptime = bgp_clock();
2909 new->net = rn;
d62a17ae 2910 return new;
fb018d25
DS
2911}
2912
d62a17ae 2913static void overlay_index_update(struct attr *attr,
2914 struct eth_segment_id *eth_s_id,
2915 union gw_addr *gw_ip)
684a7227 2916{
d62a17ae 2917 if (!attr)
2918 return;
684a7227 2919
d62a17ae 2920 if (eth_s_id == NULL) {
2921 memset(&(attr->evpn_overlay.eth_s_id), 0,
2922 sizeof(struct eth_segment_id));
2923 } else {
2924 memcpy(&(attr->evpn_overlay.eth_s_id), eth_s_id,
2925 sizeof(struct eth_segment_id));
2926 }
2927 if (gw_ip == NULL) {
2928 memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr));
2929 } else {
2930 memcpy(&(attr->evpn_overlay.gw_ip), gw_ip,
2931 sizeof(union gw_addr));
2932 }
684a7227
PG
2933}
2934
40381db7 2935static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 2936 struct eth_segment_id *eth_s_id,
2937 union gw_addr *gw_ip)
2938{
40381db7
DS
2939 struct eth_segment_id *path_eth_s_id, *path_eth_s_id_remote;
2940 union gw_addr *path_gw_ip, *path_gw_ip_remote;
11ebf4ed
DS
2941 union {
2942 struct eth_segment_id esi;
2943 union gw_addr ip;
2944 } temp;
d62a17ae 2945
2946 if (afi != AFI_L2VPN)
2947 return true;
11ebf4ed 2948
05864da7
DS
2949 path_eth_s_id = &(path->attr->evpn_overlay.eth_s_id);
2950 path_gw_ip = &(path->attr->evpn_overlay.gw_ip);
11ebf4ed
DS
2951
2952 if (gw_ip == NULL) {
2953 memset(&temp, 0, sizeof(temp));
40381db7 2954 path_gw_ip_remote = &temp.ip;
11ebf4ed 2955 } else
40381db7 2956 path_gw_ip_remote = gw_ip;
11ebf4ed
DS
2957
2958 if (eth_s_id == NULL) {
2959 memset(&temp, 0, sizeof(temp));
40381db7 2960 path_eth_s_id_remote = &temp.esi;
11ebf4ed 2961 } else
40381db7 2962 path_eth_s_id_remote = eth_s_id;
11ebf4ed 2963
40381db7 2964 if (!memcmp(path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr)))
d62a17ae 2965 return false;
11ebf4ed 2966
40381db7 2967 return !memcmp(path_eth_s_id, path_eth_s_id_remote,
d62a17ae 2968 sizeof(struct eth_segment_id));
684a7227
PG
2969}
2970
c265ee22 2971/* Check if received nexthop is valid or not. */
d62a17ae 2972static int bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
2973 struct attr *attr)
2974{
2975 int ret = 0;
2976
2977 /* Only validated for unicast and multicast currently. */
2978 /* Also valid for EVPN where the nexthop is an IP address. */
2979 if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN)
2980 return 0;
2981
2982 /* If NEXT_HOP is present, validate it. */
2983 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
2984 if (attr->nexthop.s_addr == 0
2985 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
2986 || bgp_nexthop_self(bgp, attr->nexthop))
2987 return 1;
2988 }
c265ee22 2989
d62a17ae 2990 /* If MP_NEXTHOP is present, validate it. */
2991 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2992 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2993 * it is not an IPv6 link-local address.
2994 */
2995 if (attr->mp_nexthop_len) {
2996 switch (attr->mp_nexthop_len) {
2997 case BGP_ATTR_NHLEN_IPV4:
2998 case BGP_ATTR_NHLEN_VPNV4:
2999 ret = (attr->mp_nexthop_global_in.s_addr == 0
3000 || IPV4_CLASS_DE(ntohl(
3001 attr->mp_nexthop_global_in.s_addr))
3002 || bgp_nexthop_self(bgp,
3003 attr->mp_nexthop_global_in));
3004 break;
3005
3006 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
3007 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3008 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
3009 ret = (IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global)
3010 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3011 || IN6_IS_ADDR_MULTICAST(
5e76ce50 3012 &attr->mp_nexthop_global));
d62a17ae 3013 break;
3014
3015 default:
3016 ret = 1;
3017 break;
3018 }
3019 }
c265ee22 3020
d62a17ae 3021 return ret;
3022}
3023
d7c0a89a 3024int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
d62a17ae 3025 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3026 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3027 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3028 struct bgp_route_evpn *evpn)
d62a17ae 3029{
3030 int ret;
3031 int aspath_loop_count = 0;
3032 struct bgp_node *rn;
3033 struct bgp *bgp;
3034 struct attr new_attr;
3035 struct attr *attr_new;
40381db7 3036 struct bgp_path_info *pi;
4b7e6066
DS
3037 struct bgp_path_info *new;
3038 struct bgp_path_info_extra *extra;
d62a17ae 3039 const char *reason;
3040 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3041 int connected = 0;
3042 int do_loop_check = 1;
3043 int has_valid_label = 0;
7c312383 3044 afi_t nh_afi;
65efcfce 3045#if ENABLE_BGP_VNC
d62a17ae 3046 int vnc_implicit_withdraw = 0;
65efcfce 3047#endif
d62a17ae 3048 int same_attr = 0;
718e3744 3049
d62a17ae 3050 memset(&new_attr, 0, sizeof(struct attr));
3051 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3052 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3053
d62a17ae 3054 bgp = peer->bgp;
3055 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3056 /* TODO: Check to see if we can get rid of "is_valid_label" */
3057 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3058 has_valid_label = (num_labels > 0) ? 1 : 0;
3059 else
3060 has_valid_label = bgp_is_valid_label(label);
718e3744 3061
d62a17ae 3062 /* When peer's soft reconfiguration enabled. Record input packet in
3063 Adj-RIBs-In. */
3064 if (!soft_reconfig
3065 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3066 && peer != bgp->peer_self)
3067 bgp_adj_in_set(rn, peer, attr, addpath_id);
3068
3069 /* Check previously received route. */
6f94b685 3070 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
3071 if (pi->peer == peer && pi->type == type
3072 && pi->sub_type == sub_type
3073 && pi->addpath_rx_id == addpath_id)
d62a17ae 3074 break;
3075
3076 /* AS path local-as loop check. */
3077 if (peer->change_local_as) {
c4368918
DW
3078 if (peer->allowas_in[afi][safi])
3079 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3080 else if (!CHECK_FLAG(peer->flags,
3081 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3082 aspath_loop_count = 1;
3083
3084 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3085 > aspath_loop_count) {
b4d46cc9 3086 peer->stat_pfx_aspath_loop++;
d62a17ae 3087 reason = "as-path contains our own AS;";
3088 goto filtered;
3089 }
718e3744 3090 }
718e3744 3091
d62a17ae 3092 /* If the peer is configured for "allowas-in origin" and the last ASN in
3093 * the
3094 * as-path is our ASN then we do not need to call aspath_loop_check
3095 */
3096 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3097 if (aspath_get_last_as(attr->aspath) == bgp->as)
3098 do_loop_check = 0;
3099
3100 /* AS path loop check. */
3101 if (do_loop_check) {
3102 if (aspath_loop_check(attr->aspath, bgp->as)
3103 > peer->allowas_in[afi][safi]
3104 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3105 && aspath_loop_check(attr->aspath, bgp->confed_id)
3106 > peer->allowas_in[afi][safi])) {
b4d46cc9 3107 peer->stat_pfx_aspath_loop++;
d62a17ae 3108 reason = "as-path contains our own AS;";
3109 goto filtered;
3110 }
3111 }
aac9ef6c 3112
d62a17ae 3113 /* Route reflector originator ID check. */
3114 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3115 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3116 peer->stat_pfx_originator_loop++;
d62a17ae 3117 reason = "originator is us;";
3118 goto filtered;
3119 }
718e3744 3120
d62a17ae 3121 /* Route reflector cluster ID check. */
3122 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3123 peer->stat_pfx_cluster_loop++;
d62a17ae 3124 reason = "reflected from the same cluster;";
3125 goto filtered;
3126 }
718e3744 3127
d62a17ae 3128 /* Apply incoming filter. */
3129 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3130 peer->stat_pfx_filter++;
d62a17ae 3131 reason = "filter;";
3132 goto filtered;
3133 }
718e3744 3134
a8b72dc6
DA
3135 /* RFC 8212 to prevent route leaks.
3136 * This specification intends to improve this situation by requiring the
3137 * explicit configuration of both BGP Import and Export Policies for any
3138 * External BGP (EBGP) session such as customers, peers, or
3139 * confederation boundaries for all enabled address families. Through
3140 * codification of the aforementioned requirement, operators will
3141 * benefit from consistent behavior across different BGP
3142 * implementations.
3143 */
3144 if (peer->bgp->ebgp_requires_policy == DEFAULT_EBGP_POLICY_ENABLED)
3145 if (!bgp_inbound_policy_exists(peer,
3146 &peer->filter[afi][safi])) {
3147 reason = "inbound policy missing";
3148 goto filtered;
3149 }
3150
d62a17ae 3151 bgp_attr_dup(&new_attr, attr);
3152
3153 /* Apply incoming route-map.
3154 * NB: new_attr may now contain newly allocated values from route-map
3155 * "set"
3156 * commands, so we need bgp_attr_flush in the error paths, until we
3157 * intern
3158 * the attr (which takes over the memory references) */
82b692c0 3159 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL,
196c6b09 3160 label, num_labels, rn) == RMAP_DENY) {
b4d46cc9 3161 peer->stat_pfx_filter++;
d62a17ae 3162 reason = "route-map;";
3163 bgp_attr_flush(&new_attr);
3164 goto filtered;
3165 }
718e3744 3166
05864da7 3167 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3168 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3169 /* remove from RIB previous entry */
3170 bgp_zebra_withdraw(p, pi, bgp, safi);
3171 }
3172
7f323236
DW
3173 if (peer->sort == BGP_PEER_EBGP) {
3174
a4d82a8a
PZ
3175 /* If we receive the graceful-shutdown community from an eBGP
3176 * peer we must lower local-preference */
3177 if (new_attr.community
3178 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3179 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3180 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3181
a4d82a8a
PZ
3182 /* If graceful-shutdown is configured then add the GSHUT
3183 * community to all paths received from eBGP peers */
3184 } else if (bgp_flag_check(peer->bgp,
3185 BGP_FLAG_GRACEFUL_SHUTDOWN)) {
7f323236
DW
3186 bgp_attr_add_gshut_community(&new_attr);
3187 }
3188 }
3189
d62a17ae 3190 /* next hop check. */
a4d82a8a
PZ
3191 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
3192 && bgp_update_martian_nexthop(bgp, afi, safi, &new_attr)) {
b4d46cc9 3193 peer->stat_pfx_nh_invalid++;
d62a17ae 3194 reason = "martian or self next-hop;";
3195 bgp_attr_flush(&new_attr);
3196 goto filtered;
3197 }
718e3744 3198
5c14a191 3199 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3200 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3201 reason = "self mac;";
3202 goto filtered;
3203 }
3204
d62a17ae 3205 attr_new = bgp_attr_intern(&new_attr);
3206
3207 /* If the update is implicit withdraw. */
40381db7
DS
3208 if (pi) {
3209 pi->uptime = bgp_clock();
3210 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3211
4a11bf2c
DL
3212 hook_call(bgp_process, bgp, afi, safi, rn, peer, true);
3213
d62a17ae 3214 /* Same attribute comes in. */
40381db7
DS
3215 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3216 && attrhash_cmp(pi->attr, attr_new)
d62a17ae 3217 && (!has_valid_label
40381db7 3218 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3219 num_labels * sizeof(mpls_label_t))
d62a17ae 3220 == 0)
3221 && (overlay_index_equal(
40381db7 3222 afi, pi, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3223 evpn == NULL ? NULL : &evpn->gw_ip))) {
3224 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3225 BGP_CONFIG_DAMPENING)
3226 && peer->sort == BGP_PEER_EBGP
40381db7 3227 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3228 if (bgp_debug_update(peer, p, NULL, 1)) {
3229 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3230 afi, safi, prd, p, label,
3231 num_labels, addpath_id ? 1 : 0,
3232 addpath_id, pfx_buf,
3233 sizeof(pfx_buf));
d62a17ae 3234 zlog_debug("%s rcvd %s", peer->host,
3235 pfx_buf);
3236 }
3237
40381db7 3238 if (bgp_damp_update(pi, rn, afi, safi)
d62a17ae 3239 != BGP_DAMP_SUPPRESSED) {
40381db7 3240 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3241 safi);
3242 bgp_process(bgp, rn, afi, safi);
3243 }
3244 } else /* Duplicate - odd */
3245 {
3246 if (bgp_debug_update(peer, p, NULL, 1)) {
3247 if (!peer->rcvd_attr_printed) {
3248 zlog_debug(
3249 "%s rcvd UPDATE w/ attr: %s",
3250 peer->host,
3251 peer->rcvd_attr_str);
3252 peer->rcvd_attr_printed = 1;
3253 }
3254
3255 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3256 afi, safi, prd, p, label,
3257 num_labels, addpath_id ? 1 : 0,
3258 addpath_id, pfx_buf,
3259 sizeof(pfx_buf));
d62a17ae 3260 zlog_debug(
3261 "%s rcvd %s...duplicate ignored",
3262 peer->host, pfx_buf);
3263 }
3264
3265 /* graceful restart STALE flag unset. */
40381db7 3266 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3267 bgp_path_info_unset_flag(
40381db7 3268 rn, pi, BGP_PATH_STALE);
d62a17ae 3269 bgp_process(bgp, rn, afi, safi);
3270 }
3271 }
3272
3273 bgp_unlock_node(rn);
3274 bgp_attr_unintern(&attr_new);
3275
3276 return 0;
3277 }
718e3744 3278
d62a17ae 3279 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3280 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3281 if (bgp_debug_update(peer, p, NULL, 1)) {
3282 bgp_debug_rdpfxpath2str(
a4d82a8a 3283 afi, safi, prd, p, label, num_labels,
d62a17ae 3284 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3285 sizeof(pfx_buf));
3286 zlog_debug(
3287 "%s rcvd %s, flapped quicker than processing",
3288 peer->host, pfx_buf);
3289 }
3290
40381db7 3291 bgp_path_info_restore(rn, pi);
d62a17ae 3292 }
718e3744 3293
d62a17ae 3294 /* Received Logging. */
3295 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3296 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3297 num_labels, addpath_id ? 1 : 0,
3298 addpath_id, pfx_buf,
3299 sizeof(pfx_buf));
d62a17ae 3300 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3301 }
718e3744 3302
d62a17ae 3303 /* graceful restart STALE flag unset. */
40381db7
DS
3304 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
3305 bgp_path_info_unset_flag(rn, pi, BGP_PATH_STALE);
d62a17ae 3306
3307 /* The attribute is changed. */
40381db7 3308 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3309
3310 /* implicit withdraw, decrement aggregate and pcount here.
3311 * only if update is accepted, they'll increment below.
3312 */
40381db7 3313 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3314
3315 /* Update bgp route dampening information. */
3316 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3317 && peer->sort == BGP_PEER_EBGP) {
3318 /* This is implicit withdraw so we should update
3319 dampening
3320 information. */
40381db7
DS
3321 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
3322 bgp_damp_withdraw(pi, rn, afi, safi, 1);
d62a17ae 3323 }
65efcfce 3324#if ENABLE_BGP_VNC
d62a17ae 3325 if (safi == SAFI_MPLS_VPN) {
3326 struct bgp_node *prn = NULL;
3327 struct bgp_table *table = NULL;
3328
3329 prn = bgp_node_get(bgp->rib[afi][safi],
3330 (struct prefix *)prd);
67009e22
DS
3331 if (bgp_node_has_bgp_path_info_data(prn)) {
3332 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3333
3334 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3335 bgp, prd, table, p, pi);
d62a17ae 3336 }
3337 bgp_unlock_node(prn);
3338 }
3339 if ((afi == AFI_IP || afi == AFI_IP6)
3340 && (safi == SAFI_UNICAST)) {
40381db7 3341 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3342 /*
3343 * Implicit withdraw case.
3344 */
3345 ++vnc_implicit_withdraw;
40381db7
DS
3346 vnc_import_bgp_del_route(bgp, p, pi);
3347 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3348 }
3349 }
65efcfce 3350#endif
128ea8ab 3351
d62a17ae 3352 /* Special handling for EVPN update of an existing route. If the
3353 * extended community attribute has changed, we need to
3354 * un-import
3355 * the route using its existing extended community. It will be
3356 * subsequently processed for import with the new extended
3357 * community.
3358 */
3359 if (safi == SAFI_EVPN && !same_attr) {
40381db7 3360 if ((pi->attr->flag
d62a17ae 3361 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3362 && (attr_new->flag
3363 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3364 int cmp;
3365
40381db7 3366 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3367 attr_new->ecommunity);
3368 if (!cmp) {
3369 if (bgp_debug_update(peer, p, NULL, 1))
3370 zlog_debug(
3371 "Change in EXT-COMM, existing %s new %s",
3372 ecommunity_str(
40381db7 3373 pi->attr->ecommunity),
d62a17ae 3374 ecommunity_str(
3375 attr_new->ecommunity));
3376 bgp_evpn_unimport_route(bgp, afi, safi,
40381db7 3377 p, pi);
d62a17ae 3378 }
3379 }
3380 }
718e3744 3381
d62a17ae 3382 /* Update to new attribute. */
40381db7
DS
3383 bgp_attr_unintern(&pi->attr);
3384 pi->attr = attr_new;
d62a17ae 3385
3386 /* Update MPLS label */
3387 if (has_valid_label) {
40381db7 3388 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3389 if (extra->label != label) {
3390 memcpy(&extra->label, label,
dbd587da 3391 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3392 extra->num_labels = num_labels;
3393 }
b57ba6d2
MK
3394 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3395 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3396 }
718e3744 3397
65efcfce 3398#if ENABLE_BGP_VNC
d62a17ae 3399 if ((afi == AFI_IP || afi == AFI_IP6)
3400 && (safi == SAFI_UNICAST)) {
3401 if (vnc_implicit_withdraw) {
3402 /*
3403 * Add back the route with its new attributes
3404 * (e.g., nexthop).
3405 * The route is still selected, until the route
3406 * selection
3407 * queued by bgp_process actually runs. We have
3408 * to make this
3409 * update to the VNC side immediately to avoid
3410 * racing against
3411 * configuration changes (e.g., route-map
3412 * changes) which
3413 * trigger re-importation of the entire RIB.
3414 */
40381db7
DS
3415 vnc_import_bgp_add_route(bgp, p, pi);
3416 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 3417 }
3418 }
65efcfce 3419#endif
d62a17ae 3420 /* Update Overlay Index */
3421 if (afi == AFI_L2VPN) {
3422 overlay_index_update(
40381db7 3423 pi->attr, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3424 evpn == NULL ? NULL : &evpn->gw_ip);
3425 }
65efcfce 3426
d62a17ae 3427 /* Update bgp route dampening information. */
3428 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3429 && peer->sort == BGP_PEER_EBGP) {
3430 /* Now we do normal update dampening. */
40381db7 3431 ret = bgp_damp_update(pi, rn, afi, safi);
d62a17ae 3432 if (ret == BGP_DAMP_SUPPRESSED) {
3433 bgp_unlock_node(rn);
3434 return 0;
3435 }
3436 }
128ea8ab 3437
d62a17ae 3438 /* Nexthop reachability check - for unicast and
3439 * labeled-unicast.. */
7c312383
AD
3440 if (((afi == AFI_IP || afi == AFI_IP6)
3441 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3442 || (safi == SAFI_EVPN &&
3443 bgp_evpn_is_prefix_nht_supported(p))) {
d62a17ae 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
7c312383
AD
3458 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
3459
3460 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
3461 pi, NULL, connected)
a4d82a8a 3462 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
40381db7 3463 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 3464 else {
3465 if (BGP_DEBUG(nht, NHT)) {
3466 char buf1[INET6_ADDRSTRLEN];
3467 inet_ntop(AF_INET,
3468 (const void *)&attr_new
3469 ->nexthop,
3470 buf1, INET6_ADDRSTRLEN);
3471 zlog_debug("%s(%s): NH unresolved",
3472 __FUNCTION__, buf1);
3473 }
40381db7 3474 bgp_path_info_unset_flag(rn, pi,
18ee8310 3475 BGP_PATH_VALID);
d62a17ae 3476 }
3477 } else
40381db7 3478 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 3479
3480#if ENABLE_BGP_VNC
3481 if (safi == SAFI_MPLS_VPN) {
3482 struct bgp_node *prn = NULL;
3483 struct bgp_table *table = NULL;
3484
3485 prn = bgp_node_get(bgp->rib[afi][safi],
3486 (struct prefix *)prd);
67009e22
DS
3487 if (bgp_node_has_bgp_path_info_data(prn)) {
3488 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3489
3490 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 3491 bgp, prd, table, p, pi);
d62a17ae 3492 }
3493 bgp_unlock_node(prn);
3494 }
3495#endif
718e3744 3496
d62a17ae 3497 /* If this is an EVPN route and some attribute has changed,
3498 * process
3499 * route for import. If the extended community has changed, we
3500 * would
3501 * have done the un-import earlier and the import would result
3502 * in the
3503 * route getting injected into appropriate L2 VNIs. If it is
3504 * just
3505 * some other attribute change, the import will result in
3506 * updating
3507 * the attributes for the route in the VNI(s).
3508 */
7c312383
AD
3509 if (safi == SAFI_EVPN && !same_attr &&
3510 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 3511 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 3512
3513 /* Process change. */
40381db7 3514 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 3515
3516 bgp_process(bgp, rn, afi, safi);
3517 bgp_unlock_node(rn);
558d1fec 3518
ddb5b488
PZ
3519 if (SAFI_UNICAST == safi
3520 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3521 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3522
40381db7 3523 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3524 }
3525 if ((SAFI_MPLS_VPN == safi)
3526 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3527
40381db7 3528 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
3529 }
3530
28070ee3 3531#if ENABLE_BGP_VNC
d62a17ae 3532 if (SAFI_MPLS_VPN == safi) {
3533 mpls_label_t label_decoded = decode_label(label);
28070ee3 3534
d62a17ae 3535 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3536 type, sub_type, &label_decoded);
3537 }
3538 if (SAFI_ENCAP == safi) {
3539 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3540 type, sub_type, NULL);
3541 }
28070ee3
PZ
3542#endif
3543
d62a17ae 3544 return 0;
3545 } // End of implicit withdraw
718e3744 3546
d62a17ae 3547 /* Received Logging. */
3548 if (bgp_debug_update(peer, p, NULL, 1)) {
3549 if (!peer->rcvd_attr_printed) {
3550 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3551 peer->rcvd_attr_str);
3552 peer->rcvd_attr_printed = 1;
3553 }
718e3744 3554
a4d82a8a 3555 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3556 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3557 sizeof(pfx_buf));
3558 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3559 }
718e3744 3560
d62a17ae 3561 /* Make new BGP info. */
3562 new = info_make(type, sub_type, 0, peer, attr_new, rn);
718e3744 3563
d62a17ae 3564 /* Update MPLS label */
3565 if (has_valid_label) {
18ee8310 3566 extra = bgp_path_info_extra_get(new);
8ba71050 3567 if (extra->label != label) {
dbd587da
QY
3568 memcpy(&extra->label, label,
3569 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3570 extra->num_labels = num_labels;
3571 }
b57ba6d2
MK
3572 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3573 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3574 }
718e3744 3575
d62a17ae 3576 /* Update Overlay Index */
3577 if (afi == AFI_L2VPN) {
3578 overlay_index_update(new->attr,
3579 evpn == NULL ? NULL : &evpn->eth_s_id,
3580 evpn == NULL ? NULL : &evpn->gw_ip);
3581 }
3582 /* Nexthop reachability check. */
7c312383
AD
3583 if (((afi == AFI_IP || afi == AFI_IP6)
3584 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3585 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
d62a17ae 3586 if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1
3587 && !CHECK_FLAG(peer->flags,
3588 PEER_FLAG_DISABLE_CONNECTED_CHECK)
3589 && !bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
3590 connected = 1;
3591 else
3592 connected = 0;
3593
7c312383
AD
3594 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
3595
3596 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, new, NULL,
3597 connected)
a4d82a8a 3598 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
18ee8310 3599 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
d62a17ae 3600 else {
3601 if (BGP_DEBUG(nht, NHT)) {
3602 char buf1[INET6_ADDRSTRLEN];
3603 inet_ntop(AF_INET,
3604 (const void *)&attr_new->nexthop,
3605 buf1, INET6_ADDRSTRLEN);
3606 zlog_debug("%s(%s): NH unresolved",
3607 __FUNCTION__, buf1);
3608 }
18ee8310 3609 bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID);
d62a17ae 3610 }
3611 } else
18ee8310 3612 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
a82478b9 3613
d62a17ae 3614 /* Addpath ID */
3615 new->addpath_rx_id = addpath_id;
3616
3617 /* Increment prefix */
3618 bgp_aggregate_increment(bgp, p, new, afi, safi);
3619
3620 /* Register new BGP information. */
18ee8310 3621 bgp_path_info_add(rn, new);
d62a17ae 3622
3623 /* route_node_get lock */
3624 bgp_unlock_node(rn);
558d1fec 3625
65efcfce 3626#if ENABLE_BGP_VNC
d62a17ae 3627 if (safi == SAFI_MPLS_VPN) {
3628 struct bgp_node *prn = NULL;
3629 struct bgp_table *table = NULL;
3630
3631 prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
67009e22
DS
3632 if (bgp_node_has_bgp_path_info_data(prn)) {
3633 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3634
3635 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3636 bgp, prd, table, p, new);
3637 }
3638 bgp_unlock_node(prn);
3639 }
65efcfce
LB
3640#endif
3641
d62a17ae 3642 /* If maximum prefix count is configured and current prefix
3643 count exeed it. */
3644 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3645 return -1;
718e3744 3646
d62a17ae 3647 /* If this is an EVPN route, process for import. */
7c312383 3648 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 3649 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 3650
4a11bf2c
DL
3651 hook_call(bgp_process, bgp, afi, safi, rn, peer, false);
3652
d62a17ae 3653 /* Process change. */
3654 bgp_process(bgp, rn, afi, safi);
718e3744 3655
ddb5b488
PZ
3656 if (SAFI_UNICAST == safi
3657 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3658 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3659 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
3660 }
3661 if ((SAFI_MPLS_VPN == safi)
3662 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3663
3664 vpn_leak_to_vrf_update(bgp, new);
3665 }
28070ee3 3666#if ENABLE_BGP_VNC
d62a17ae 3667 if (SAFI_MPLS_VPN == safi) {
3668 mpls_label_t label_decoded = decode_label(label);
28070ee3 3669
d62a17ae 3670 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3671 sub_type, &label_decoded);
3672 }
3673 if (SAFI_ENCAP == safi) {
3674 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3675 sub_type, NULL);
3676 }
28070ee3
PZ
3677#endif
3678
d62a17ae 3679 return 0;
718e3744 3680
d62a17ae 3681/* This BGP update is filtered. Log the reason then update BGP
3682 entry. */
3683filtered:
4a11bf2c
DL
3684 hook_call(bgp_process, bgp, afi, safi, rn, peer, true);
3685
d62a17ae 3686 if (bgp_debug_update(peer, p, NULL, 1)) {
3687 if (!peer->rcvd_attr_printed) {
3688 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3689 peer->rcvd_attr_str);
3690 peer->rcvd_attr_printed = 1;
3691 }
718e3744 3692
a4d82a8a 3693 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3694 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3695 sizeof(pfx_buf));
3696 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3697 peer->host, pfx_buf, reason);
3698 }
128ea8ab 3699
40381db7 3700 if (pi) {
d62a17ae 3701 /* If this is an EVPN route, un-import it as it is now filtered.
3702 */
3703 if (safi == SAFI_EVPN)
40381db7 3704 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 3705
ddb5b488
PZ
3706 if (SAFI_UNICAST == safi
3707 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3708 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3709
40381db7 3710 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3711 }
3712 if ((SAFI_MPLS_VPN == safi)
3713 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3714
40381db7 3715 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
3716 }
3717
40381db7 3718 bgp_rib_remove(rn, pi, peer, afi, safi);
d62a17ae 3719 }
3720
3721 bgp_unlock_node(rn);
558d1fec 3722
97736e32 3723#if ENABLE_BGP_VNC
d62a17ae 3724 /*
3725 * Filtered update is treated as an implicit withdrawal (see
3726 * bgp_rib_remove()
3727 * a few lines above)
3728 */
3729 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
3730 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
3731 0);
3732 }
97736e32
PZ
3733#endif
3734
d62a17ae 3735 return 0;
718e3744 3736}
3737
d7c0a89a 3738int bgp_withdraw(struct peer *peer, struct prefix *p, uint32_t addpath_id,
d62a17ae 3739 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3740 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3741 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 3742{
d62a17ae 3743 struct bgp *bgp;
3744 char pfx_buf[BGP_PRD_PATH_STRLEN];
3745 struct bgp_node *rn;
40381db7 3746 struct bgp_path_info *pi;
718e3744 3747
28070ee3 3748#if ENABLE_BGP_VNC
d62a17ae 3749 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
3750 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
3751 0);
3752 }
28070ee3
PZ
3753#endif
3754
d62a17ae 3755 bgp = peer->bgp;
3756
3757 /* Lookup node. */
3758 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
3759
3760 /* If peer is soft reconfiguration enabled. Record input packet for
3761 * further calculation.
3762 *
3763 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3764 * routes that are filtered. This tanks out Quagga RS pretty badly due
3765 * to
3766 * the iteration over all RS clients.
3767 * Since we need to remove the entry from adj_in anyway, do that first
3768 * and
3769 * if there was no entry, we don't need to do anything more.
3770 */
3771 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3772 && peer != bgp->peer_self)
3773 if (!bgp_adj_in_unset(rn, peer, addpath_id)) {
b4d46cc9
DL
3774 peer->stat_pfx_dup_withdraw++;
3775
d62a17ae 3776 if (bgp_debug_update(peer, p, NULL, 1)) {
3777 bgp_debug_rdpfxpath2str(
a4d82a8a 3778 afi, safi, prd, p, label, num_labels,
d62a17ae 3779 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3780 sizeof(pfx_buf));
3781 zlog_debug(
3782 "%s withdrawing route %s not in adj-in",
3783 peer->host, pfx_buf);
3784 }
3785 bgp_unlock_node(rn);
3786 return 0;
3787 }
cd808e74 3788
d62a17ae 3789 /* Lookup withdrawn route. */
6f94b685 3790 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
3791 if (pi->peer == peer && pi->type == type
3792 && pi->sub_type == sub_type
3793 && pi->addpath_rx_id == addpath_id)
d62a17ae 3794 break;
3795
3796 /* Logging. */
3797 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 3798 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3799 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3800 sizeof(pfx_buf));
3801 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
3802 pfx_buf);
3803 }
718e3744 3804
d62a17ae 3805 /* Withdraw specified route from routing table. */
40381db7
DS
3806 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
3807 bgp_rib_withdraw(rn, pi, peer, afi, safi, prd);
ddb5b488
PZ
3808 if (SAFI_UNICAST == safi
3809 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3810 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 3811 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3812 }
3813 if ((SAFI_MPLS_VPN == safi)
3814 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3815
40381db7 3816 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
3817 }
3818 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 3819 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3820 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3821 sizeof(pfx_buf));
3822 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
3823 }
718e3744 3824
d62a17ae 3825 /* Unlock bgp_node_get() lock. */
3826 bgp_unlock_node(rn);
3827
3828 return 0;
718e3744 3829}
6b0655a2 3830
d62a17ae 3831void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
3832 int withdraw)
718e3744 3833{
d62a17ae 3834 struct update_subgroup *subgrp;
3835 subgrp = peer_subgroup(peer, afi, safi);
3836 subgroup_default_originate(subgrp, withdraw);
3f9c7369 3837}
6182d65b 3838
718e3744 3839
3f9c7369
DS
3840/*
3841 * bgp_stop_announce_route_timer
3842 */
d62a17ae 3843void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 3844{
d62a17ae 3845 if (!paf->t_announce_route)
3846 return;
3847
3848 THREAD_TIMER_OFF(paf->t_announce_route);
718e3744 3849}
6b0655a2 3850
3f9c7369
DS
3851/*
3852 * bgp_announce_route_timer_expired
3853 *
3854 * Callback that is invoked when the route announcement timer for a
3855 * peer_af expires.
3856 */
d62a17ae 3857static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 3858{
d62a17ae 3859 struct peer_af *paf;
3860 struct peer *peer;
558d1fec 3861
d62a17ae 3862 paf = THREAD_ARG(t);
3863 peer = paf->peer;
718e3744 3864
d62a17ae 3865 if (peer->status != Established)
3866 return 0;
3f9c7369 3867
d62a17ae 3868 if (!peer->afc_nego[paf->afi][paf->safi])
3869 return 0;
3f9c7369 3870
d62a17ae 3871 peer_af_announce_route(paf, 1);
3872 return 0;
718e3744 3873}
3874
3f9c7369
DS
3875/*
3876 * bgp_announce_route
3877 *
3878 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3879 */
d62a17ae 3880void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
3881{
3882 struct peer_af *paf;
3883 struct update_subgroup *subgrp;
3884
3885 paf = peer_af_find(peer, afi, safi);
3886 if (!paf)
3887 return;
3888 subgrp = PAF_SUBGRP(paf);
3889
3890 /*
3891 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3892 * or a refresh has already been triggered.
3893 */
3894 if (!subgrp || paf->t_announce_route)
3895 return;
3896
3897 /*
3898 * Start a timer to stagger/delay the announce. This serves
3899 * two purposes - announcement can potentially be combined for
3900 * multiple peers and the announcement doesn't happen in the
3901 * vty context.
3902 */
3903 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
3904 (subgrp->peer_count == 1)
3905 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3906 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
3907 &paf->t_announce_route);
3f9c7369
DS
3908}
3909
3910/*
3911 * Announce routes from all AF tables to a peer.
3912 *
3913 * This should ONLY be called when there is a need to refresh the
3914 * routes to the peer based on a policy change for this peer alone
3915 * or a route refresh request received from the peer.
3916 * The operation will result in splitting the peer from its existing
3917 * subgroups and putting it in new subgroups.
3918 */
d62a17ae 3919void bgp_announce_route_all(struct peer *peer)
718e3744 3920{
d62a17ae 3921 afi_t afi;
3922 safi_t safi;
3923
05c7a1cc
QY
3924 FOREACH_AFI_SAFI (afi, safi)
3925 bgp_announce_route(peer, afi, safi);
718e3744 3926}
6b0655a2 3927
d62a17ae 3928static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
3929 struct bgp_table *table,
3930 struct prefix_rd *prd)
718e3744 3931{
d62a17ae 3932 int ret;
3933 struct bgp_node *rn;
3934 struct bgp_adj_in *ain;
718e3744 3935
d62a17ae 3936 if (!table)
3937 table = peer->bgp->rib[afi][safi];
718e3744 3938
d62a17ae 3939 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
3940 for (ain = rn->adj_in; ain; ain = ain->next) {
ea47320b
DL
3941 if (ain->peer != peer)
3942 continue;
8692c506 3943
d7d15889 3944 struct bgp_path_info *pi;
d7c0a89a 3945 uint32_t num_labels = 0;
b57ba6d2 3946 mpls_label_t *label_pnt = NULL;
8cb687c2 3947 struct bgp_route_evpn evpn;
b57ba6d2 3948
d7d15889
DS
3949 for (pi = bgp_node_get_bgp_path_info(rn); pi;
3950 pi = pi->next)
3951 if (pi->peer == peer)
3952 break;
3953
40381db7
DS
3954 if (pi && pi->extra)
3955 num_labels = pi->extra->num_labels;
b57ba6d2 3956 if (num_labels)
40381db7 3957 label_pnt = &pi->extra->label[0];
8cb687c2
DS
3958 if (pi)
3959 memcpy(&evpn, &pi->attr->evpn_overlay,
3960 sizeof(evpn));
3961 else
3962 memset(&evpn, 0, sizeof(evpn));
8692c506 3963
ea47320b
DL
3964 ret = bgp_update(peer, &rn->p, ain->addpath_rx_id,
3965 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
a4d82a8a 3966 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 3967 num_labels, 1, &evpn);
ea47320b
DL
3968
3969 if (ret < 0) {
3970 bgp_unlock_node(rn);
3971 return;
d62a17ae 3972 }
3973 }
718e3744 3974}
3975
d62a17ae 3976void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 3977{
d62a17ae 3978 struct bgp_node *rn;
3979 struct bgp_table *table;
718e3744 3980
d62a17ae 3981 if (peer->status != Established)
3982 return;
718e3744 3983
d62a17ae 3984 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
3985 && (safi != SAFI_EVPN))
3986 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
3987 else
3988 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
67009e22
DS
3989 rn = bgp_route_next(rn)) {
3990 table = bgp_node_get_bgp_table_info(rn);
3991 if (table != NULL) {
d62a17ae 3992 struct prefix_rd prd;
67009e22 3993
d62a17ae 3994 prd.family = AF_UNSPEC;
3995 prd.prefixlen = 64;
3996 memcpy(&prd.val, rn->p.u.val, 8);
8692c506 3997
d62a17ae 3998 bgp_soft_reconfig_table(peer, afi, safi, table,
3999 &prd);
4000 }
67009e22 4001 }
718e3744 4002}
6b0655a2 4003
228da428 4004
d62a17ae 4005struct bgp_clear_node_queue {
4006 struct bgp_node *rn;
228da428
CC
4007};
4008
d62a17ae 4009static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4010{
d62a17ae 4011 struct bgp_clear_node_queue *cnq = data;
4012 struct bgp_node *rn = cnq->rn;
4013 struct peer *peer = wq->spec.data;
40381db7 4014 struct bgp_path_info *pi;
3103e8d2 4015 struct bgp *bgp;
d62a17ae 4016 afi_t afi = bgp_node_table(rn)->afi;
4017 safi_t safi = bgp_node_table(rn)->safi;
4018
4019 assert(rn && peer);
3103e8d2 4020 bgp = peer->bgp;
d62a17ae 4021
4022 /* It is possible that we have multiple paths for a prefix from a peer
4023 * if that peer is using AddPath.
4024 */
6f94b685 4025 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 4026 if (pi->peer != peer)
ea47320b
DL
4027 continue;
4028
4029 /* graceful restart STALE flag set. */
4030 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4031 && peer->nsf[afi][safi]
40381db7
DS
4032 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4033 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
4034 bgp_path_info_set_flag(rn, pi, BGP_PATH_STALE);
ea47320b
DL
4035 else {
4036 /* If this is an EVPN route, process for
4037 * un-import. */
4038 if (safi == SAFI_EVPN)
40381db7
DS
4039 bgp_evpn_unimport_route(bgp, afi, safi, &rn->p,
4040 pi);
3103e8d2
DS
4041 /* Handle withdraw for VRF route-leaking and L3VPN */
4042 if (SAFI_UNICAST == safi
4043 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4044 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4045 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4046 bgp, pi);
960035b2 4047 }
3103e8d2 4048 if (SAFI_MPLS_VPN == safi &&
960035b2 4049 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4050 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4051 }
3103e8d2 4052
40381db7 4053 bgp_rib_remove(rn, pi, peer, afi, safi);
d62a17ae 4054 }
ea47320b 4055 }
d62a17ae 4056 return WQ_SUCCESS;
200df115 4057}
4058
d62a17ae 4059static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4060{
d62a17ae 4061 struct bgp_clear_node_queue *cnq = data;
4062 struct bgp_node *rn = cnq->rn;
4063 struct bgp_table *table = bgp_node_table(rn);
228da428 4064
d62a17ae 4065 bgp_unlock_node(rn);
4066 bgp_table_unlock(table);
4067 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4068}
4069
d62a17ae 4070static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4071{
d62a17ae 4072 struct peer *peer = wq->spec.data;
64e580a7 4073
d62a17ae 4074 /* Tickle FSM to start moving again */
4075 BGP_EVENT_ADD(peer, Clearing_Completed);
4076
4077 peer_unlock(peer); /* bgp_clear_route */
200df115 4078}
718e3744 4079
d62a17ae 4080static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4081{
d62a17ae 4082 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4083
4084 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4085#undef CLEAR_QUEUE_NAME_LEN
4086
0ce1ca80 4087 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4088 peer->clear_node_queue->spec.hold = 10;
4089 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4090 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4091 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4092 peer->clear_node_queue->spec.max_retries = 0;
4093
4094 /* we only 'lock' this peer reference when the queue is actually active
4095 */
4096 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4097}
4098
d62a17ae 4099static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4100 struct bgp_table *table)
65ca75e0 4101{
d62a17ae 4102 struct bgp_node *rn;
4103 int force = bm->process_main_queue ? 0 : 1;
6cf159b9 4104
d62a17ae 4105 if (!table)
4106 table = peer->bgp->rib[afi][safi];
dc83d712 4107
d62a17ae 4108 /* If still no table => afi/safi isn't configured at all or smth. */
4109 if (!table)
4110 return;
dc83d712 4111
d62a17ae 4112 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
40381db7 4113 struct bgp_path_info *pi, *next;
d62a17ae 4114 struct bgp_adj_in *ain;
4115 struct bgp_adj_in *ain_next;
4116
4117 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4118 * queued for every clearing peer, regardless of whether it is
4119 * relevant to the peer at hand.
4120 *
4121 * Overview: There are 3 different indices which need to be
4122 * scrubbed, potentially, when a peer is removed:
4123 *
4124 * 1 peer's routes visible via the RIB (ie accepted routes)
4125 * 2 peer's routes visible by the (optional) peer's adj-in index
4126 * 3 other routes visible by the peer's adj-out index
4127 *
4128 * 3 there is no hurry in scrubbing, once the struct peer is
4129 * removed from bgp->peer, we could just GC such deleted peer's
4130 * adj-outs at our leisure.
4131 *
4132 * 1 and 2 must be 'scrubbed' in some way, at least made
4133 * invisible via RIB index before peer session is allowed to be
4134 * brought back up. So one needs to know when such a 'search' is
4135 * complete.
4136 *
4137 * Ideally:
4138 *
4139 * - there'd be a single global queue or a single RIB walker
4140 * - rather than tracking which route_nodes still need to be
4141 * examined on a peer basis, we'd track which peers still
4142 * aren't cleared
4143 *
4144 * Given that our per-peer prefix-counts now should be reliable,
4145 * this may actually be achievable. It doesn't seem to be a huge
4146 * problem at this time,
4147 *
4148 * It is possible that we have multiple paths for a prefix from
4149 * a peer
4150 * if that peer is using AddPath.
4151 */
4152 ain = rn->adj_in;
4153 while (ain) {
4154 ain_next = ain->next;
4155
4156 if (ain->peer == peer) {
4157 bgp_adj_in_remove(rn, ain);
4158 bgp_unlock_node(rn);
4159 }
4160
4161 ain = ain_next;
4162 }
4163
6f94b685 4164 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
40381db7
DS
4165 next = pi->next;
4166 if (pi->peer != peer)
d62a17ae 4167 continue;
4168
4169 if (force)
40381db7 4170 bgp_path_info_reap(rn, pi);
d62a17ae 4171 else {
4172 struct bgp_clear_node_queue *cnq;
4173
4174 /* both unlocked in bgp_clear_node_queue_del */
4175 bgp_table_lock(bgp_node_table(rn));
4176 bgp_lock_node(rn);
4177 cnq = XCALLOC(
4178 MTYPE_BGP_CLEAR_NODE_QUEUE,
4179 sizeof(struct bgp_clear_node_queue));
4180 cnq->rn = rn;
4181 work_queue_add(peer->clear_node_queue, cnq);
4182 break;
4183 }
4184 }
4185 }
4186 return;
4187}
4188
4189void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4190{
4191 struct bgp_node *rn;
4192 struct bgp_table *table;
4193
4194 if (peer->clear_node_queue == NULL)
4195 bgp_clear_node_queue_init(peer);
4196
4197 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4198 * Idle until it receives a Clearing_Completed event. This protects
4199 * against peers which flap faster than we can we clear, which could
4200 * lead to:
4201 *
4202 * a) race with routes from the new session being installed before
4203 * clear_route_node visits the node (to delete the route of that
4204 * peer)
4205 * b) resource exhaustion, clear_route_node likely leads to an entry
4206 * on the process_main queue. Fast-flapping could cause that queue
4207 * to grow and grow.
4208 */
4209
4210 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4211 * the unlock will happen upon work-queue completion; other wise, the
4212 * unlock happens at the end of this function.
4213 */
4214 if (!peer->clear_node_queue->thread)
4215 peer_lock(peer);
4216
4217 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4218 bgp_clear_route_table(peer, afi, safi, NULL);
4219 else
4220 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
67009e22
DS
4221 rn = bgp_route_next(rn)) {
4222 table = bgp_node_get_bgp_table_info(rn);
4223 if (!table)
4224 continue;
4225
4226 bgp_clear_route_table(peer, afi, safi, table);
4227 }
d62a17ae 4228
4229 /* unlock if no nodes got added to the clear-node-queue. */
4230 if (!peer->clear_node_queue->thread)
4231 peer_unlock(peer);
718e3744 4232}
d62a17ae 4233
4234void bgp_clear_route_all(struct peer *peer)
718e3744 4235{
d62a17ae 4236 afi_t afi;
4237 safi_t safi;
718e3744 4238
05c7a1cc
QY
4239 FOREACH_AFI_SAFI (afi, safi)
4240 bgp_clear_route(peer, afi, safi);
65efcfce
LB
4241
4242#if ENABLE_BGP_VNC
d62a17ae 4243 rfapiProcessPeerDown(peer);
65efcfce 4244#endif
718e3744 4245}
4246
d62a17ae 4247void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4248{
d62a17ae 4249 struct bgp_table *table;
4250 struct bgp_node *rn;
4251 struct bgp_adj_in *ain;
4252 struct bgp_adj_in *ain_next;
718e3744 4253
d62a17ae 4254 table = peer->bgp->rib[afi][safi];
718e3744 4255
d62a17ae 4256 /* It is possible that we have multiple paths for a prefix from a peer
4257 * if that peer is using AddPath.
4258 */
4259 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
4260 ain = rn->adj_in;
43143c8f 4261
d62a17ae 4262 while (ain) {
4263 ain_next = ain->next;
43143c8f 4264
d62a17ae 4265 if (ain->peer == peer) {
4266 bgp_adj_in_remove(rn, ain);
4267 bgp_unlock_node(rn);
4268 }
43143c8f 4269
d62a17ae 4270 ain = ain_next;
4271 }
4272 }
718e3744 4273}
93406d87 4274
d62a17ae 4275void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4276{
4277 struct bgp_node *rn;
40381db7 4278 struct bgp_path_info *pi;
d62a17ae 4279 struct bgp_table *table;
4280
4281 if (safi == SAFI_MPLS_VPN) {
4282 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4283 rn = bgp_route_next(rn)) {
4284 struct bgp_node *rm;
d62a17ae 4285
4286 /* look for neighbor in tables */
67009e22
DS
4287 table = bgp_node_get_bgp_table_info(rn);
4288 if (!table)
ea47320b
DL
4289 continue;
4290
4291 for (rm = bgp_table_top(table); rm;
4292 rm = bgp_route_next(rm))
6f94b685
DS
4293 for (pi = bgp_node_get_bgp_path_info(rm); pi;
4294 pi = pi->next) {
40381db7 4295 if (pi->peer != peer)
ea47320b 4296 continue;
40381db7 4297 if (!CHECK_FLAG(pi->flags,
1defdda8 4298 BGP_PATH_STALE))
ea47320b
DL
4299 break;
4300
40381db7 4301 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4302 break;
4303 }
d62a17ae 4304 }
4305 } else {
4306 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4307 rn = bgp_route_next(rn))
6f94b685
DS
4308 for (pi = bgp_node_get_bgp_path_info(rn); pi;
4309 pi = pi->next) {
40381db7 4310 if (pi->peer != peer)
ea47320b 4311 continue;
40381db7 4312 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4313 break;
40381db7 4314 bgp_rib_remove(rn, pi, peer, afi, safi);
ea47320b
DL
4315 break;
4316 }
d62a17ae 4317 }
93406d87 4318}
6b0655a2 4319
9dac9fc8
DA
4320int bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
4321{
4322 if (peer->sort == BGP_PEER_EBGP
4323 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
4324 || FILTER_LIST_OUT_NAME(filter)
4325 || DISTRIBUTE_OUT_NAME(filter)))
4326 return 1;
4327 return 0;
4328}
4329
4330int bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
4331{
4332 if (peer->sort == BGP_PEER_EBGP
4333 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
4334 || FILTER_LIST_IN_NAME(filter)
4335 || DISTRIBUTE_IN_NAME(filter)))
4336 return 1;
4337 return 0;
4338}
4339
568e10ca 4340static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
4341 safi_t safi)
bb86c601 4342{
d62a17ae 4343 struct bgp_node *rn;
40381db7 4344 struct bgp_path_info *pi;
4b7e6066 4345 struct bgp_path_info *next;
bb86c601 4346
d62a17ae 4347 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
6f94b685 4348 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
40381db7 4349 next = pi->next;
1b7bb747
CS
4350
4351 /* Unimport EVPN routes from VRFs */
4352 if (safi == SAFI_EVPN)
4353 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
4354 SAFI_EVPN,
4355 &rn->p, pi);
4356
40381db7
DS
4357 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
4358 && pi->type == ZEBRA_ROUTE_BGP
4359 && (pi->sub_type == BGP_ROUTE_NORMAL
4360 || pi->sub_type == BGP_ROUTE_AGGREGATE
4361 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 4362
d62a17ae 4363 if (bgp_fibupd_safi(safi))
40381db7
DS
4364 bgp_zebra_withdraw(&rn->p, pi, bgp,
4365 safi);
4366 bgp_path_info_reap(rn, pi);
d62a17ae 4367 }
4368 }
bb86c601
LB
4369}
4370
718e3744 4371/* Delete all kernel routes. */
d62a17ae 4372void bgp_cleanup_routes(struct bgp *bgp)
4373{
4374 afi_t afi;
4375 struct bgp_node *rn;
67009e22 4376 struct bgp_table *table;
d62a17ae 4377
4378 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
4379 if (afi == AFI_L2VPN)
4380 continue;
568e10ca 4381 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
4382 SAFI_UNICAST);
d62a17ae 4383 /*
4384 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4385 */
4386 if (afi != AFI_L2VPN) {
4387 safi_t safi;
4388 safi = SAFI_MPLS_VPN;
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 safi = SAFI_ENCAP;
4400 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4401 rn = bgp_route_next(rn)) {
67009e22
DS
4402 table = bgp_node_get_bgp_table_info(rn);
4403 if (table != NULL) {
4404 bgp_cleanup_table(bgp, table, safi);
4405 bgp_table_finish(&table);
4406 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4407 bgp_unlock_node(rn);
4408 }
4409 }
4410 }
4411 }
4412 for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn;
4413 rn = bgp_route_next(rn)) {
67009e22
DS
4414 table = bgp_node_get_bgp_table_info(rn);
4415 if (table != NULL) {
4416 bgp_cleanup_table(bgp, table, SAFI_EVPN);
4417 bgp_table_finish(&table);
4418 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4419 bgp_unlock_node(rn);
4420 }
bb86c601 4421 }
718e3744 4422}
4423
d62a17ae 4424void bgp_reset(void)
718e3744 4425{
d62a17ae 4426 vty_reset();
4427 bgp_zclient_reset();
4428 access_list_reset();
4429 prefix_list_reset();
718e3744 4430}
6b0655a2 4431
d62a17ae 4432static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 4433{
d62a17ae 4434 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
4435 && CHECK_FLAG(peer->af_cap[afi][safi],
4436 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
4437}
4438
718e3744 4439/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4440 value. */
d62a17ae 4441int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
4442 struct bgp_nlri *packet)
4443{
d7c0a89a
QY
4444 uint8_t *pnt;
4445 uint8_t *lim;
d62a17ae 4446 struct prefix p;
4447 int psize;
4448 int ret;
4449 afi_t afi;
4450 safi_t safi;
4451 int addpath_encoded;
d7c0a89a 4452 uint32_t addpath_id;
d62a17ae 4453
d62a17ae 4454 pnt = packet->nlri;
4455 lim = pnt + packet->length;
4456 afi = packet->afi;
4457 safi = packet->safi;
4458 addpath_id = 0;
4459 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
4460
4461 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4462 syntactic validity. If the field is syntactically incorrect,
4463 then the Error Subcode is set to Invalid Network Field. */
4464 for (; pnt < lim; pnt += psize) {
4465 /* Clear prefix structure. */
4466 memset(&p, 0, sizeof(struct prefix));
4467
4468 if (addpath_encoded) {
4469
4470 /* When packet overflow occurs return immediately. */
4471 if (pnt + BGP_ADDPATH_ID_LEN > lim)
513386b5 4472 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4473
4474 addpath_id = ntohl(*((uint32_t *)pnt));
4475 pnt += BGP_ADDPATH_ID_LEN;
4476 }
718e3744 4477
d62a17ae 4478 /* Fetch prefix length. */
4479 p.prefixlen = *pnt++;
4480 /* afi/safi validity already verified by caller,
4481 * bgp_update_receive */
4482 p.family = afi2family(afi);
4483
4484 /* Prefix length check. */
4485 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 4486 flog_err(
e50f7cfd 4487 EC_BGP_UPDATE_RCV,
14454c9f 4488 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 4489 peer->host, p.prefixlen, packet->afi);
513386b5 4490 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 4491 }
6b0655a2 4492
d62a17ae 4493 /* Packet size overflow check. */
4494 psize = PSIZE(p.prefixlen);
4495
4496 /* When packet overflow occur return immediately. */
4497 if (pnt + psize > lim) {
af4c2728 4498 flog_err(
e50f7cfd 4499 EC_BGP_UPDATE_RCV,
d62a17ae 4500 "%s [Error] Update packet error (prefix length %d overflows packet)",
4501 peer->host, p.prefixlen);
513386b5 4502 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4503 }
4504
4505 /* Defensive coding, double-check the psize fits in a struct
4506 * prefix */
4507 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 4508 flog_err(
e50f7cfd 4509 EC_BGP_UPDATE_RCV,
d62a17ae 4510 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4511 peer->host, p.prefixlen, sizeof(p.u));
513386b5 4512 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4513 }
4514
4515 /* Fetch prefix from NLRI packet. */
a85297a7 4516 memcpy(p.u.val, pnt, psize);
d62a17ae 4517
4518 /* Check address. */
4519 if (afi == AFI_IP && safi == SAFI_UNICAST) {
4520 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
4521 /* From RFC4271 Section 6.3:
4522 *
4523 * If a prefix in the NLRI field is semantically
4524 * incorrect
4525 * (e.g., an unexpected multicast IP address),
4526 * an error SHOULD
4527 * be logged locally, and the prefix SHOULD be
4528 * ignored.
a4d82a8a 4529 */
af4c2728 4530 flog_err(
e50f7cfd 4531 EC_BGP_UPDATE_RCV,
d62a17ae 4532 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4533 peer->host, inet_ntoa(p.u.prefix4));
4534 continue;
4535 }
4536 }
4537
4538 /* Check address. */
4539 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
4540 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4541 char buf[BUFSIZ];
4542
af4c2728 4543 flog_err(
e50f7cfd 4544 EC_BGP_UPDATE_RCV,
d62a17ae 4545 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4546 peer->host,
4547 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4548 BUFSIZ));
4549
4550 continue;
4551 }
4552 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
4553 char buf[BUFSIZ];
4554
af4c2728 4555 flog_err(
e50f7cfd 4556 EC_BGP_UPDATE_RCV,
d62a17ae 4557 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4558 peer->host,
4559 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4560 BUFSIZ));
4561
4562 continue;
4563 }
4564 }
4565
4566 /* Normal process. */
4567 if (attr)
4568 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
4569 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 4570 NULL, NULL, 0, 0, NULL);
d62a17ae 4571 else
4572 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
4573 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
4574 BGP_ROUTE_NORMAL, NULL, NULL, 0,
4575 NULL);
d62a17ae 4576
513386b5
DA
4577 /* Do not send BGP notification twice when maximum-prefix count
4578 * overflow. */
4579 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4580 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
4581
4582 /* Address family configuration mismatch. */
d62a17ae 4583 if (ret < 0)
513386b5 4584 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 4585 }
4586
4587 /* Packet length consistency check. */
4588 if (pnt != lim) {
af4c2728 4589 flog_err(
e50f7cfd 4590 EC_BGP_UPDATE_RCV,
d62a17ae 4591 "%s [Error] Update packet error (prefix length mismatch with total length)",
4592 peer->host);
513386b5 4593 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4594 }
6b0655a2 4595
513386b5 4596 return BGP_NLRI_PARSE_OK;
718e3744 4597}
4598
d62a17ae 4599static struct bgp_static *bgp_static_new(void)
718e3744 4600{
d62a17ae 4601 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 4602}
4603
d62a17ae 4604static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 4605{
0a22ddfb 4606 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 4607 route_map_counter_decrement(bgp_static->rmap.map);
4608
0a22ddfb 4609 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 4610 XFREE(MTYPE_BGP_STATIC, bgp_static);
4611}
4612
4613void bgp_static_update(struct bgp *bgp, struct prefix *p,
4614 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
4615{
4616 struct bgp_node *rn;
40381db7 4617 struct bgp_path_info *pi;
4b7e6066 4618 struct bgp_path_info *new;
40381db7 4619 struct bgp_path_info rmap_path;
d62a17ae 4620 struct attr attr;
4621 struct attr *attr_new;
b68885f9 4622 route_map_result_t ret;
65efcfce 4623#if ENABLE_BGP_VNC
d62a17ae 4624 int vnc_implicit_withdraw = 0;
65efcfce 4625#endif
fee0f4c6 4626
d62a17ae 4627 assert(bgp_static);
4628 if (!bgp_static)
4629 return;
dd8103a9 4630
d62a17ae 4631 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4632
d62a17ae 4633 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 4634
d62a17ae 4635 attr.nexthop = bgp_static->igpnexthop;
4636 attr.med = bgp_static->igpmetric;
4637 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 4638
d62a17ae 4639 if (bgp_static->atomic)
4640 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 4641
d62a17ae 4642 /* Store label index, if required. */
4643 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
4644 attr.label_index = bgp_static->label_index;
4645 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
4646 }
718e3744 4647
d62a17ae 4648 /* Apply route-map. */
4649 if (bgp_static->rmap.name) {
4650 struct attr attr_tmp = attr;
80ced710 4651
40381db7
DS
4652 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
4653 rmap_path.peer = bgp->peer_self;
4654 rmap_path.attr = &attr_tmp;
fee0f4c6 4655
d62a17ae 4656 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 4657
40381db7
DS
4658 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
4659 &rmap_path);
fee0f4c6 4660
d62a17ae 4661 bgp->peer_self->rmap_type = 0;
718e3744 4662
d62a17ae 4663 if (ret == RMAP_DENYMATCH) {
4664 /* Free uninterned attribute. */
4665 bgp_attr_flush(&attr_tmp);
718e3744 4666
d62a17ae 4667 /* Unintern original. */
4668 aspath_unintern(&attr.aspath);
4669 bgp_static_withdraw(bgp, p, afi, safi);
4670 return;
4671 }
7f323236
DW
4672
4673 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
4674 bgp_attr_add_gshut_community(&attr_tmp);
4675
d62a17ae 4676 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
4677 } else {
4678
4679 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
4680 bgp_attr_add_gshut_community(&attr);
4681
d62a17ae 4682 attr_new = bgp_attr_intern(&attr);
7f323236 4683 }
718e3744 4684
6f94b685 4685 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4686 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4687 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4688 break;
4689
40381db7
DS
4690 if (pi) {
4691 if (attrhash_cmp(pi->attr, attr_new)
4692 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
d62a17ae 4693 && !bgp_flag_check(bgp, BGP_FLAG_FORCE_STATIC_PROCESS)) {
4694 bgp_unlock_node(rn);
4695 bgp_attr_unintern(&attr_new);
4696 aspath_unintern(&attr.aspath);
4697 return;
4698 } else {
4699 /* The attribute is changed. */
40381db7 4700 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4701
4702 /* Rewrite BGP route information. */
40381db7
DS
4703 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
4704 bgp_path_info_restore(rn, pi);
d62a17ae 4705 else
40381db7 4706 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
65efcfce 4707#if ENABLE_BGP_VNC
d62a17ae 4708 if ((afi == AFI_IP || afi == AFI_IP6)
4709 && (safi == SAFI_UNICAST)) {
40381db7 4710 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4711 /*
4712 * Implicit withdraw case.
40381db7 4713 * We have to do this before pi is
d62a17ae 4714 * changed
4715 */
4716 ++vnc_implicit_withdraw;
40381db7 4717 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 4718 vnc_import_bgp_exterior_del_route(
40381db7 4719 bgp, p, pi);
d62a17ae 4720 }
4721 }
65efcfce 4722#endif
40381db7
DS
4723 bgp_attr_unintern(&pi->attr);
4724 pi->attr = attr_new;
4725 pi->uptime = bgp_clock();
65efcfce 4726#if ENABLE_BGP_VNC
d62a17ae 4727 if ((afi == AFI_IP || afi == AFI_IP6)
4728 && (safi == SAFI_UNICAST)) {
4729 if (vnc_implicit_withdraw) {
40381db7 4730 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 4731 vnc_import_bgp_exterior_add_route(
40381db7 4732 bgp, p, pi);
d62a17ae 4733 }
4734 }
65efcfce 4735#endif
718e3744 4736
d62a17ae 4737 /* Nexthop reachability check. */
4738 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
4739 && (safi == SAFI_UNICAST
4740 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
4741
4742 struct bgp *bgp_nexthop = bgp;
4743
40381db7
DS
4744 if (pi->extra && pi->extra->bgp_orig)
4745 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
4746
4747 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
40381db7
DS
4748 afi, pi, NULL, 0))
4749 bgp_path_info_set_flag(rn, pi,
18ee8310 4750 BGP_PATH_VALID);
d62a17ae 4751 else {
4752 if (BGP_DEBUG(nht, NHT)) {
4753 char buf1[INET6_ADDRSTRLEN];
4754 inet_ntop(p->family,
4755 &p->u.prefix, buf1,
4756 INET6_ADDRSTRLEN);
4757 zlog_debug(
4758 "%s(%s): Route not in table, not advertising",
4759 __FUNCTION__, buf1);
4760 }
18ee8310 4761 bgp_path_info_unset_flag(
40381db7 4762 rn, pi, BGP_PATH_VALID);
d62a17ae 4763 }
4764 } else {
4765 /* Delete the NHT structure if any, if we're
4766 * toggling between
4767 * enabling/disabling import check. We
4768 * deregister the route
4769 * from NHT to avoid overloading NHT and the
4770 * process interaction
4771 */
40381db7
DS
4772 bgp_unlink_nexthop(pi);
4773 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 4774 }
4775 /* Process change. */
40381db7 4776 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4777 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
4778
4779 if (SAFI_UNICAST == safi
4780 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4781 || bgp->inst_type
4782 == BGP_INSTANCE_TYPE_DEFAULT)) {
4783 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 4784 pi);
ddb5b488
PZ
4785 }
4786
d62a17ae 4787 bgp_unlock_node(rn);
4788 aspath_unintern(&attr.aspath);
4789 return;
4790 }
718e3744 4791 }
718e3744 4792
d62a17ae 4793 /* Make new BGP info. */
4794 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
4795 attr_new, rn);
4796 /* Nexthop reachability check. */
4797 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
4798 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 4799 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
18ee8310 4800 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
d62a17ae 4801 else {
4802 if (BGP_DEBUG(nht, NHT)) {
4803 char buf1[INET6_ADDRSTRLEN];
4804 inet_ntop(p->family, &p->u.prefix, buf1,
4805 INET6_ADDRSTRLEN);
4806 zlog_debug(
4807 "%s(%s): Route not in table, not advertising",
4808 __FUNCTION__, buf1);
4809 }
18ee8310 4810 bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID);
d62a17ae 4811 }
4812 } else {
4813 /* Delete the NHT structure if any, if we're toggling between
4814 * enabling/disabling import check. We deregister the route
4815 * from NHT to avoid overloading NHT and the process interaction
4816 */
4817 bgp_unlink_nexthop(new);
4818
18ee8310 4819 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
fc9a856f 4820 }
078430f6 4821
d62a17ae 4822 /* Aggregate address increment. */
4823 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 4824
d62a17ae 4825 /* Register new BGP information. */
18ee8310 4826 bgp_path_info_add(rn, new);
718e3744 4827
d62a17ae 4828 /* route_node_get lock */
4829 bgp_unlock_node(rn);
4830
4831 /* Process change. */
4832 bgp_process(bgp, rn, afi, safi);
4833
ddb5b488
PZ
4834 if (SAFI_UNICAST == safi
4835 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4836 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4837 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4838 }
4839
d62a17ae 4840 /* Unintern original. */
4841 aspath_unintern(&attr.aspath);
718e3744 4842}
4843
d62a17ae 4844void bgp_static_withdraw(struct bgp *bgp, struct prefix *p, afi_t afi,
4845 safi_t safi)
718e3744 4846{
d62a17ae 4847 struct bgp_node *rn;
40381db7 4848 struct bgp_path_info *pi;
718e3744 4849
d62a17ae 4850 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4851
d62a17ae 4852 /* Check selected route and self inserted route. */
6f94b685 4853 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4854 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4855 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4856 break;
4857
4858 /* Withdraw static BGP route from routing table. */
40381db7 4859 if (pi) {
ddb5b488
PZ
4860 if (SAFI_UNICAST == safi
4861 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4862 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4863 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 4864 }
40381db7
DS
4865 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
4866 bgp_unlink_nexthop(pi);
4867 bgp_path_info_delete(rn, pi);
d62a17ae 4868 bgp_process(bgp, rn, afi, safi);
4869 }
718e3744 4870
d62a17ae 4871 /* Unlock bgp_node_lookup. */
4872 bgp_unlock_node(rn);
718e3744 4873}
4874
137446f9
LB
4875/*
4876 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4877 */
d62a17ae 4878static void bgp_static_withdraw_safi(struct bgp *bgp, struct prefix *p,
4879 afi_t afi, safi_t safi,
4880 struct prefix_rd *prd)
718e3744 4881{
d62a17ae 4882 struct bgp_node *rn;
40381db7 4883 struct bgp_path_info *pi;
718e3744 4884
d62a17ae 4885 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 4886
d62a17ae 4887 /* Check selected route and self inserted route. */
6f94b685 4888 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4889 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4890 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4891 break;
718e3744 4892
d62a17ae 4893 /* Withdraw static BGP route from routing table. */
40381db7 4894 if (pi) {
65efcfce 4895#if ENABLE_BGP_VNC
d62a17ae 4896 rfapiProcessWithdraw(
40381db7 4897 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 4898 1); /* Kill, since it is an administrative change */
65efcfce 4899#endif
ddb5b488
PZ
4900 if (SAFI_MPLS_VPN == safi
4901 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4902 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 4903 }
40381db7
DS
4904 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
4905 bgp_path_info_delete(rn, pi);
d62a17ae 4906 bgp_process(bgp, rn, afi, safi);
4907 }
718e3744 4908
d62a17ae 4909 /* Unlock bgp_node_lookup. */
4910 bgp_unlock_node(rn);
718e3744 4911}
4912
d62a17ae 4913static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p,
4914 struct bgp_static *bgp_static, afi_t afi,
4915 safi_t safi)
137446f9 4916{
d62a17ae 4917 struct bgp_node *rn;
4b7e6066 4918 struct bgp_path_info *new;
d62a17ae 4919 struct attr *attr_new;
4920 struct attr attr = {0};
40381db7 4921 struct bgp_path_info *pi;
65efcfce 4922#if ENABLE_BGP_VNC
d62a17ae 4923 mpls_label_t label = 0;
65efcfce 4924#endif
d7c0a89a 4925 uint32_t num_labels = 0;
d62a17ae 4926 union gw_addr add;
137446f9 4927
d62a17ae 4928 assert(bgp_static);
137446f9 4929
b57ba6d2
MK
4930 if (bgp_static->label != MPLS_INVALID_LABEL)
4931 num_labels = 1;
d62a17ae 4932 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
4933 &bgp_static->prd);
137446f9 4934
d62a17ae 4935 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 4936
d62a17ae 4937 attr.nexthop = bgp_static->igpnexthop;
4938 attr.med = bgp_static->igpmetric;
4939 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 4940
d62a17ae 4941 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
4942 || (safi == SAFI_ENCAP)) {
4943 if (afi == AFI_IP) {
4944 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
4945 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
4946 }
4947 }
4948 if (afi == AFI_L2VPN) {
4949 if (bgp_static->gatewayIp.family == AF_INET)
4950 add.ipv4.s_addr =
4951 bgp_static->gatewayIp.u.prefix4.s_addr;
4952 else if (bgp_static->gatewayIp.family == AF_INET6)
4953 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
4954 sizeof(struct in6_addr));
4955 overlay_index_update(&attr, bgp_static->eth_s_id, &add);
4956 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
4957 struct bgp_encap_type_vxlan bet;
4958 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 4959 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 4960 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
4961 }
4962 if (bgp_static->router_mac) {
4963 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
4964 }
4965 }
4966 /* Apply route-map. */
4967 if (bgp_static->rmap.name) {
4968 struct attr attr_tmp = attr;
40381db7 4969 struct bgp_path_info rmap_path;
b68885f9 4970 route_map_result_t ret;
137446f9 4971
40381db7
DS
4972 rmap_path.peer = bgp->peer_self;
4973 rmap_path.attr = &attr_tmp;
137446f9 4974
d62a17ae 4975 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 4976
40381db7
DS
4977 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
4978 &rmap_path);
137446f9 4979
d62a17ae 4980 bgp->peer_self->rmap_type = 0;
137446f9 4981
d62a17ae 4982 if (ret == RMAP_DENYMATCH) {
4983 /* Free uninterned attribute. */
4984 bgp_attr_flush(&attr_tmp);
137446f9 4985
d62a17ae 4986 /* Unintern original. */
4987 aspath_unintern(&attr.aspath);
4988 bgp_static_withdraw_safi(bgp, p, afi, safi,
4989 &bgp_static->prd);
4990 return;
4991 }
137446f9 4992
d62a17ae 4993 attr_new = bgp_attr_intern(&attr_tmp);
4994 } else {
4995 attr_new = bgp_attr_intern(&attr);
4996 }
137446f9 4997
6f94b685 4998 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4999 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5000 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5001 break;
5002
40381db7 5003 if (pi) {
d62a17ae 5004 memset(&add, 0, sizeof(union gw_addr));
40381db7
DS
5005 if (attrhash_cmp(pi->attr, attr_new)
5006 && overlay_index_equal(afi, pi, bgp_static->eth_s_id, &add)
5007 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 5008 bgp_unlock_node(rn);
5009 bgp_attr_unintern(&attr_new);
5010 aspath_unintern(&attr.aspath);
5011 return;
5012 } else {
5013 /* The attribute is changed. */
40381db7 5014 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5015
5016 /* Rewrite BGP route information. */
40381db7
DS
5017 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
5018 bgp_path_info_restore(rn, pi);
d62a17ae 5019 else
40381db7
DS
5020 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5021 bgp_attr_unintern(&pi->attr);
5022 pi->attr = attr_new;
5023 pi->uptime = bgp_clock();
65efcfce 5024#if ENABLE_BGP_VNC
40381db7
DS
5025 if (pi->extra)
5026 label = decode_label(&pi->extra->label[0]);
65efcfce 5027#endif
137446f9 5028
d62a17ae 5029 /* Process change. */
40381db7 5030 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 5031 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
5032
5033 if (SAFI_MPLS_VPN == safi
5034 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5035 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5036 }
65efcfce 5037#if ENABLE_BGP_VNC
40381db7
DS
5038 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5039 pi->attr, afi, safi, pi->type,
5040 pi->sub_type, &label);
65efcfce 5041#endif
d62a17ae 5042 bgp_unlock_node(rn);
5043 aspath_unintern(&attr.aspath);
5044 return;
5045 }
5046 }
137446f9
LB
5047
5048
d62a17ae 5049 /* Make new BGP info. */
5050 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
5051 attr_new, rn);
1defdda8 5052 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5053 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5054 if (num_labels) {
5055 new->extra->label[0] = bgp_static->label;
5056 new->extra->num_labels = num_labels;
5057 }
65efcfce 5058#if ENABLE_BGP_VNC
d62a17ae 5059 label = decode_label(&bgp_static->label);
65efcfce 5060#endif
137446f9 5061
d62a17ae 5062 /* Aggregate address increment. */
5063 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5064
d62a17ae 5065 /* Register new BGP information. */
18ee8310 5066 bgp_path_info_add(rn, new);
d62a17ae 5067 /* route_node_get lock */
5068 bgp_unlock_node(rn);
137446f9 5069
d62a17ae 5070 /* Process change. */
5071 bgp_process(bgp, rn, afi, safi);
137446f9 5072
ddb5b488
PZ
5073 if (SAFI_MPLS_VPN == safi
5074 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5075 vpn_leak_to_vrf_update(bgp, new);
5076 }
65efcfce 5077#if ENABLE_BGP_VNC
d62a17ae 5078 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5079 safi, new->type, new->sub_type, &label);
65efcfce
LB
5080#endif
5081
d62a17ae 5082 /* Unintern original. */
5083 aspath_unintern(&attr.aspath);
137446f9
LB
5084}
5085
718e3744 5086/* Configure static BGP network. When user don't run zebra, static
5087 route should be installed as valid. */
e2a86ad9
DS
5088static int bgp_static_set(struct vty *vty, const char *negate,
5089 const char *ip_str, afi_t afi, safi_t safi,
d7c0a89a 5090 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 5091{
5092 VTY_DECLVAR_CONTEXT(bgp, bgp);
5093 int ret;
5094 struct prefix p;
5095 struct bgp_static *bgp_static;
5096 struct bgp_node *rn;
d7c0a89a 5097 uint8_t need_update = 0;
d62a17ae 5098
5099 /* Convert IP prefix string to struct prefix. */
5100 ret = str2prefix(ip_str, &p);
5101 if (!ret) {
5102 vty_out(vty, "%% Malformed prefix\n");
5103 return CMD_WARNING_CONFIG_FAILED;
5104 }
5105 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5106 vty_out(vty, "%% Malformed prefix (link-local address)\n");
5107 return CMD_WARNING_CONFIG_FAILED;
5108 }
718e3744 5109
d62a17ae 5110 apply_mask(&p);
718e3744 5111
e2a86ad9 5112 if (negate) {
718e3744 5113
e2a86ad9
DS
5114 /* Set BGP static route configuration. */
5115 rn = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5116
e2a86ad9 5117 if (!rn) {
a4d82a8a 5118 vty_out(vty, "%% Can't find static route specified\n");
d62a17ae 5119 return CMD_WARNING_CONFIG_FAILED;
5120 }
5121
5a8ba9fc 5122 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 5123
e2a86ad9
DS
5124 if ((label_index != BGP_INVALID_LABEL_INDEX)
5125 && (label_index != bgp_static->label_index)) {
5126 vty_out(vty,
5127 "%% label-index doesn't match static route\n");
5128 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5129 }
d62a17ae 5130
e2a86ad9
DS
5131 if ((rmap && bgp_static->rmap.name)
5132 && strcmp(rmap, bgp_static->rmap.name)) {
5133 vty_out(vty,
5134 "%% route-map name doesn't match static route\n");
5135 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5136 }
718e3744 5137
e2a86ad9
DS
5138 /* Update BGP RIB. */
5139 if (!bgp_static->backdoor)
5140 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5141
e2a86ad9
DS
5142 /* Clear configuration. */
5143 bgp_static_free(bgp_static);
5a8ba9fc 5144 bgp_node_set_bgp_static_info(rn, NULL);
e2a86ad9
DS
5145 bgp_unlock_node(rn);
5146 bgp_unlock_node(rn);
5147 } else {
718e3744 5148
e2a86ad9
DS
5149 /* Set BGP static route configuration. */
5150 rn = bgp_node_get(bgp->route[afi][safi], &p);
718e3744 5151
5a8ba9fc 5152 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 5153 if (bgp_static) {
e2a86ad9 5154 /* Configuration change. */
e2a86ad9
DS
5155 /* Label index cannot be changed. */
5156 if (bgp_static->label_index != label_index) {
5157 vty_out(vty, "%% cannot change label-index\n");
5158 return CMD_WARNING_CONFIG_FAILED;
5159 }
d62a17ae 5160
e2a86ad9 5161 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5162 if (bgp_static->valid
5163 && bgp_static->backdoor != backdoor)
e2a86ad9 5164 need_update = 1;
718e3744 5165
e2a86ad9 5166 bgp_static->backdoor = backdoor;
718e3744 5167
e2a86ad9 5168 if (rmap) {
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 =
5174 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5175 bgp_static->rmap.map =
5176 route_map_lookup_by_name(rmap);
b4897fa5 5177 route_map_counter_increment(
5178 bgp_static->rmap.map);
e2a86ad9 5179 } else {
0a22ddfb
QY
5180 XFREE(MTYPE_ROUTE_MAP_NAME,
5181 bgp_static->rmap.name);
b4897fa5 5182 route_map_counter_decrement(
5183 bgp_static->rmap.map);
e2a86ad9
DS
5184 bgp_static->rmap.name = NULL;
5185 bgp_static->rmap.map = NULL;
5186 bgp_static->valid = 0;
5187 }
5188 bgp_unlock_node(rn);
5189 } else {
5190 /* New configuration. */
5191 bgp_static = bgp_static_new();
5192 bgp_static->backdoor = backdoor;
5193 bgp_static->valid = 0;
5194 bgp_static->igpmetric = 0;
5195 bgp_static->igpnexthop.s_addr = 0;
5196 bgp_static->label_index = label_index;
718e3744 5197
e2a86ad9 5198 if (rmap) {
0a22ddfb
QY
5199 XFREE(MTYPE_ROUTE_MAP_NAME,
5200 bgp_static->rmap.name);
b4897fa5 5201 route_map_counter_decrement(
5202 bgp_static->rmap.map);
e2a86ad9
DS
5203 bgp_static->rmap.name =
5204 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5205 bgp_static->rmap.map =
5206 route_map_lookup_by_name(rmap);
b4897fa5 5207 route_map_counter_increment(
5208 bgp_static->rmap.map);
e2a86ad9 5209 }
5a8ba9fc 5210 bgp_node_set_bgp_static_info(rn, bgp_static);
e2a86ad9 5211 }
d62a17ae 5212
e2a86ad9
DS
5213 bgp_static->valid = 1;
5214 if (need_update)
5215 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5216
e2a86ad9
DS
5217 if (!bgp_static->backdoor)
5218 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5219 }
d62a17ae 5220
5221 return CMD_SUCCESS;
5222}
5223
5224void bgp_static_add(struct bgp *bgp)
5225{
5226 afi_t afi;
5227 safi_t safi;
5228 struct bgp_node *rn;
5229 struct bgp_node *rm;
5230 struct bgp_table *table;
5231 struct bgp_static *bgp_static;
5232
05c7a1cc
QY
5233 FOREACH_AFI_SAFI (afi, safi)
5234 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5235 rn = bgp_route_next(rn)) {
67009e22 5236 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5237 continue;
ea47320b 5238
05c7a1cc
QY
5239 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5240 || (safi == SAFI_EVPN)) {
67009e22 5241 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5242
5243 for (rm = bgp_table_top(table); rm;
5244 rm = bgp_route_next(rm)) {
a78beeb5 5245 bgp_static =
5a8ba9fc
DS
5246 bgp_node_get_bgp_static_info(
5247 rm);
05c7a1cc
QY
5248 bgp_static_update_safi(bgp, &rm->p,
5249 bgp_static, afi,
5250 safi);
d62a17ae 5251 }
05c7a1cc 5252 } else {
5a8ba9fc
DS
5253 bgp_static_update(
5254 bgp, &rn->p,
5255 bgp_node_get_bgp_static_info(rn), afi,
5256 safi);
ea47320b 5257 }
05c7a1cc 5258 }
6aeb9e78
DS
5259}
5260
718e3744 5261/* Called from bgp_delete(). Delete all static routes from the BGP
5262 instance. */
d62a17ae 5263void bgp_static_delete(struct bgp *bgp)
5264{
5265 afi_t afi;
5266 safi_t safi;
5267 struct bgp_node *rn;
5268 struct bgp_node *rm;
5269 struct bgp_table *table;
5270 struct bgp_static *bgp_static;
5271
05c7a1cc
QY
5272 FOREACH_AFI_SAFI (afi, safi)
5273 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5274 rn = bgp_route_next(rn)) {
67009e22 5275 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5276 continue;
ea47320b 5277
05c7a1cc
QY
5278 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5279 || (safi == SAFI_EVPN)) {
67009e22 5280 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5281
5282 for (rm = bgp_table_top(table); rm;
5283 rm = bgp_route_next(rm)) {
a78beeb5 5284 bgp_static =
5a8ba9fc
DS
5285 bgp_node_get_bgp_static_info(
5286 rm);
c7d14ba6
PG
5287 if (!bgp_static)
5288 continue;
5289
05c7a1cc
QY
5290 bgp_static_withdraw_safi(
5291 bgp, &rm->p, AFI_IP, safi,
5292 (struct prefix_rd *)&rn->p);
ea47320b 5293 bgp_static_free(bgp_static);
5a8ba9fc 5294 bgp_node_set_bgp_static_info(rn, NULL);
ea47320b 5295 bgp_unlock_node(rn);
d62a17ae 5296 }
05c7a1cc 5297 } else {
5a8ba9fc 5298 bgp_static = bgp_node_get_bgp_static_info(rn);
05c7a1cc
QY
5299 bgp_static_withdraw(bgp, &rn->p, afi, safi);
5300 bgp_static_free(bgp_static);
5a8ba9fc 5301 bgp_node_set_bgp_static_info(rn, NULL);
05c7a1cc 5302 bgp_unlock_node(rn);
ea47320b 5303 }
05c7a1cc 5304 }
d62a17ae 5305}
5306
5307void bgp_static_redo_import_check(struct bgp *bgp)
5308{
5309 afi_t afi;
5310 safi_t safi;
5311 struct bgp_node *rn;
5312 struct bgp_node *rm;
5313 struct bgp_table *table;
5314 struct bgp_static *bgp_static;
5315
5316 /* Use this flag to force reprocessing of the route */
5317 bgp_flag_set(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc
QY
5318 FOREACH_AFI_SAFI (afi, safi) {
5319 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5320 rn = bgp_route_next(rn)) {
67009e22 5321 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5322 continue;
ea47320b 5323
05c7a1cc
QY
5324 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5325 || (safi == SAFI_EVPN)) {
67009e22 5326 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5327
5328 for (rm = bgp_table_top(table); rm;
5329 rm = bgp_route_next(rm)) {
a78beeb5 5330 bgp_static =
5a8ba9fc
DS
5331 bgp_node_get_bgp_static_info(
5332 rm);
05c7a1cc
QY
5333 bgp_static_update_safi(bgp, &rm->p,
5334 bgp_static, afi,
5335 safi);
d62a17ae 5336 }
05c7a1cc 5337 } else {
5a8ba9fc 5338 bgp_static = bgp_node_get_bgp_static_info(rn);
05c7a1cc
QY
5339 bgp_static_update(bgp, &rn->p, bgp_static, afi,
5340 safi);
ea47320b 5341 }
05c7a1cc
QY
5342 }
5343 }
d62a17ae 5344 bgp_flag_unset(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
5345}
5346
5347static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
5348 safi_t safi)
5349{
5350 struct bgp_table *table;
5351 struct bgp_node *rn;
40381db7 5352 struct bgp_path_info *pi;
d62a17ae 5353
dfb6fd1d
NT
5354 /* Do not install the aggregate route if BGP is in the
5355 * process of termination.
5356 */
5357 if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS) ||
5358 (bgp->peer_self == NULL))
5359 return;
5360
d62a17ae 5361 table = bgp->rib[afi][safi];
5362 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685 5363 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7
DS
5364 if (pi->peer == bgp->peer_self
5365 && ((pi->type == ZEBRA_ROUTE_BGP
5366 && pi->sub_type == BGP_ROUTE_STATIC)
5367 || (pi->type != ZEBRA_ROUTE_BGP
5368 && pi->sub_type
d62a17ae 5369 == BGP_ROUTE_REDISTRIBUTE))) {
40381db7 5370 bgp_aggregate_decrement(bgp, &rn->p, pi, afi,
d62a17ae 5371 safi);
40381db7
DS
5372 bgp_unlink_nexthop(pi);
5373 bgp_path_info_delete(rn, pi);
d62a17ae 5374 bgp_process(bgp, rn, afi, safi);
5375 }
5376 }
5377 }
ad4cbda1 5378}
5379
5380/*
5381 * Purge all networks and redistributed routes from routing table.
5382 * Invoked upon the instance going down.
5383 */
d62a17ae 5384void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 5385{
d62a17ae 5386 afi_t afi;
5387 safi_t safi;
ad4cbda1 5388
05c7a1cc
QY
5389 FOREACH_AFI_SAFI (afi, safi)
5390 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 5391}
5392
137446f9
LB
5393/*
5394 * gpz 110624
5395 * Currently this is used to set static routes for VPN and ENCAP.
5396 * I think it can probably be factored with bgp_static_set.
5397 */
d62a17ae 5398int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
5399 const char *ip_str, const char *rd_str,
5400 const char *label_str, const char *rmap_str,
5401 int evpn_type, const char *esi, const char *gwip,
5402 const char *ethtag, const char *routermac)
5403{
5404 VTY_DECLVAR_CONTEXT(bgp, bgp);
5405 int ret;
5406 struct prefix p;
5407 struct prefix_rd prd;
5408 struct bgp_node *prn;
5409 struct bgp_node *rn;
5410 struct bgp_table *table;
5411 struct bgp_static *bgp_static;
5412 mpls_label_t label = MPLS_INVALID_LABEL;
5413 struct prefix gw_ip;
5414
5415 /* validate ip prefix */
5416 ret = str2prefix(ip_str, &p);
5417 if (!ret) {
5418 vty_out(vty, "%% Malformed prefix\n");
5419 return CMD_WARNING_CONFIG_FAILED;
5420 }
5421 apply_mask(&p);
5422 if ((afi == AFI_L2VPN)
5423 && (bgp_build_evpn_prefix(evpn_type,
5424 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5425 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5426 return CMD_WARNING_CONFIG_FAILED;
5427 }
718e3744 5428
d62a17ae 5429 ret = str2prefix_rd(rd_str, &prd);
5430 if (!ret) {
5431 vty_out(vty, "%% Malformed rd\n");
5432 return CMD_WARNING_CONFIG_FAILED;
5433 }
718e3744 5434
d62a17ae 5435 if (label_str) {
5436 unsigned long label_val;
5437 label_val = strtoul(label_str, NULL, 10);
5438 encode_label(label_val, &label);
5439 }
9bedbb1e 5440
d62a17ae 5441 if (safi == SAFI_EVPN) {
5442 if (esi && str2esi(esi, NULL) == 0) {
5443 vty_out(vty, "%% Malformed ESI\n");
5444 return CMD_WARNING_CONFIG_FAILED;
5445 }
5446 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
5447 vty_out(vty, "%% Malformed Router MAC\n");
5448 return CMD_WARNING_CONFIG_FAILED;
5449 }
5450 if (gwip) {
5451 memset(&gw_ip, 0, sizeof(struct prefix));
5452 ret = str2prefix(gwip, &gw_ip);
5453 if (!ret) {
5454 vty_out(vty, "%% Malformed GatewayIp\n");
5455 return CMD_WARNING_CONFIG_FAILED;
5456 }
5457 if ((gw_ip.family == AF_INET
3714a385 5458 && is_evpn_prefix_ipaddr_v6(
d62a17ae 5459 (struct prefix_evpn *)&p))
5460 || (gw_ip.family == AF_INET6
3714a385 5461 && is_evpn_prefix_ipaddr_v4(
d62a17ae 5462 (struct prefix_evpn *)&p))) {
5463 vty_out(vty,
5464 "%% GatewayIp family differs with IP prefix\n");
5465 return CMD_WARNING_CONFIG_FAILED;
5466 }
5467 }
5468 }
5469 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
67009e22
DS
5470 if (!bgp_node_has_bgp_path_info_data(prn))
5471 bgp_node_set_bgp_table_info(prn,
5472 bgp_table_init(bgp, afi, safi));
67009e22 5473 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 5474
5475 rn = bgp_node_get(table, &p);
5476
67009e22 5477 if (bgp_node_has_bgp_path_info_data(rn)) {
d62a17ae 5478 vty_out(vty, "%% Same network configuration exists\n");
5479 bgp_unlock_node(rn);
5480 } else {
5481 /* New configuration. */
5482 bgp_static = bgp_static_new();
5483 bgp_static->backdoor = 0;
5484 bgp_static->valid = 0;
5485 bgp_static->igpmetric = 0;
5486 bgp_static->igpnexthop.s_addr = 0;
5487 bgp_static->label = label;
5488 bgp_static->prd = prd;
5489
5490 if (rmap_str) {
0a22ddfb 5491 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5492 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 5493 bgp_static->rmap.name =
5494 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
5495 bgp_static->rmap.map =
5496 route_map_lookup_by_name(rmap_str);
b4897fa5 5497 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 5498 }
718e3744 5499
d62a17ae 5500 if (safi == SAFI_EVPN) {
5501 if (esi) {
5502 bgp_static->eth_s_id =
5503 XCALLOC(MTYPE_ATTR,
5504 sizeof(struct eth_segment_id));
5505 str2esi(esi, bgp_static->eth_s_id);
5506 }
5507 if (routermac) {
5508 bgp_static->router_mac =
28328ea9 5509 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
5510 (void)prefix_str2mac(routermac,
5511 bgp_static->router_mac);
d62a17ae 5512 }
5513 if (gwip)
5514 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
5515 }
5a8ba9fc 5516 bgp_node_set_bgp_static_info(rn, bgp_static);
718e3744 5517
d62a17ae 5518 bgp_static->valid = 1;
5519 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
5520 }
718e3744 5521
d62a17ae 5522 return CMD_SUCCESS;
718e3744 5523}
5524
5525/* Configure static BGP network. */
d62a17ae 5526int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
5527 const char *ip_str, const char *rd_str,
5528 const char *label_str, int evpn_type, const char *esi,
5529 const char *gwip, const char *ethtag)
5530{
5531 VTY_DECLVAR_CONTEXT(bgp, bgp);
5532 int ret;
5533 struct prefix p;
5534 struct prefix_rd prd;
5535 struct bgp_node *prn;
5536 struct bgp_node *rn;
5537 struct bgp_table *table;
5538 struct bgp_static *bgp_static;
5539 mpls_label_t label = MPLS_INVALID_LABEL;
5540
5541 /* Convert IP prefix string to struct prefix. */
5542 ret = str2prefix(ip_str, &p);
5543 if (!ret) {
5544 vty_out(vty, "%% Malformed prefix\n");
5545 return CMD_WARNING_CONFIG_FAILED;
5546 }
5547 apply_mask(&p);
5548 if ((afi == AFI_L2VPN)
5549 && (bgp_build_evpn_prefix(evpn_type,
5550 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5551 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5552 return CMD_WARNING_CONFIG_FAILED;
5553 }
5554 ret = str2prefix_rd(rd_str, &prd);
5555 if (!ret) {
5556 vty_out(vty, "%% Malformed rd\n");
5557 return CMD_WARNING_CONFIG_FAILED;
5558 }
718e3744 5559
d62a17ae 5560 if (label_str) {
5561 unsigned long label_val;
5562 label_val = strtoul(label_str, NULL, 10);
5563 encode_label(label_val, &label);
5564 }
718e3744 5565
d62a17ae 5566 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
67009e22
DS
5567 if (!bgp_node_has_bgp_path_info_data(prn))
5568 bgp_node_set_bgp_table_info(prn,
5569 bgp_table_init(bgp, afi, safi));
d62a17ae 5570 else
5571 bgp_unlock_node(prn);
67009e22 5572 table = bgp_node_get_bgp_table_info(prn);
718e3744 5573
d62a17ae 5574 rn = bgp_node_lookup(table, &p);
6b0655a2 5575
d62a17ae 5576 if (rn) {
5577 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 5578
5a8ba9fc 5579 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 5580 bgp_static_free(bgp_static);
5a8ba9fc 5581 bgp_node_set_bgp_static_info(rn, NULL);
d62a17ae 5582 bgp_unlock_node(rn);
5583 bgp_unlock_node(rn);
5584 } else
5585 vty_out(vty, "%% Can't find the route\n");
5586
5587 return CMD_SUCCESS;
5588}
5589
5590static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
5591 const char *rmap_name)
5592{
5593 VTY_DECLVAR_CONTEXT(bgp, bgp);
5594 struct bgp_rmap *rmap;
5595
5596 rmap = &bgp->table_map[afi][safi];
5597 if (rmap_name) {
0a22ddfb 5598 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5599 route_map_counter_decrement(rmap->map);
d62a17ae 5600 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
5601 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 5602 route_map_counter_increment(rmap->map);
d62a17ae 5603 } else {
0a22ddfb 5604 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5605 route_map_counter_decrement(rmap->map);
d62a17ae 5606 rmap->name = NULL;
5607 rmap->map = NULL;
5608 }
73ac8160 5609
d62a17ae 5610 if (bgp_fibupd_safi(safi))
5611 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5612
d62a17ae 5613 return CMD_SUCCESS;
73ac8160
DS
5614}
5615
d62a17ae 5616static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
5617 const char *rmap_name)
73ac8160 5618{
d62a17ae 5619 VTY_DECLVAR_CONTEXT(bgp, bgp);
5620 struct bgp_rmap *rmap;
73ac8160 5621
d62a17ae 5622 rmap = &bgp->table_map[afi][safi];
0a22ddfb 5623 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5624 route_map_counter_decrement(rmap->map);
d62a17ae 5625 rmap->name = NULL;
5626 rmap->map = NULL;
73ac8160 5627
d62a17ae 5628 if (bgp_fibupd_safi(safi))
5629 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5630
d62a17ae 5631 return CMD_SUCCESS;
73ac8160
DS
5632}
5633
2b791107 5634void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 5635 safi_t safi)
73ac8160 5636{
d62a17ae 5637 if (bgp->table_map[afi][safi].name) {
d62a17ae 5638 vty_out(vty, " table-map %s\n",
5639 bgp->table_map[afi][safi].name);
5640 }
73ac8160
DS
5641}
5642
73ac8160
DS
5643DEFUN (bgp_table_map,
5644 bgp_table_map_cmd,
5645 "table-map WORD",
5646 "BGP table to RIB route download filter\n"
5647 "Name of the route map\n")
5648{
d62a17ae 5649 int idx_word = 1;
5650 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5651 argv[idx_word]->arg);
73ac8160
DS
5652}
5653DEFUN (no_bgp_table_map,
5654 no_bgp_table_map_cmd,
5655 "no table-map WORD",
3a2d747c 5656 NO_STR
73ac8160
DS
5657 "BGP table to RIB route download filter\n"
5658 "Name of the route map\n")
5659{
d62a17ae 5660 int idx_word = 2;
5661 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5662 argv[idx_word]->arg);
73ac8160
DS
5663}
5664
e2a86ad9
DS
5665DEFPY(bgp_network,
5666 bgp_network_cmd,
5667 "[no] network \
5668 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5669 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5670 backdoor$backdoor}]",
5671 NO_STR
5672 "Specify a network to announce via BGP\n"
5673 "IPv4 prefix\n"
5674 "Network number\n"
5675 "Network mask\n"
5676 "Network mask\n"
5677 "Route-map to modify the attributes\n"
5678 "Name of the route map\n"
5679 "Label index to associate with the prefix\n"
5680 "Label index value\n"
5681 "Specify a BGP backdoor route\n")
5682{
5683 char addr_prefix_str[BUFSIZ];
5684
5685 if (address_str) {
5686 int ret;
718e3744 5687
e2a86ad9
DS
5688 ret = netmask_str2prefix_str(address_str, netmask_str,
5689 addr_prefix_str);
5690 if (!ret) {
5691 vty_out(vty, "%% Inconsistent address and mask\n");
5692 return CMD_WARNING_CONFIG_FAILED;
5693 }
d62a17ae 5694 }
718e3744 5695
a4d82a8a
PZ
5696 return bgp_static_set(
5697 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
5698 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
5699 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 5700}
5701
e2a86ad9
DS
5702DEFPY(ipv6_bgp_network,
5703 ipv6_bgp_network_cmd,
5704 "[no] network X:X::X:X/M$prefix \
5705 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5706 NO_STR
5707 "Specify a network to announce via BGP\n"
5708 "IPv6 prefix\n"
5709 "Route-map to modify the attributes\n"
5710 "Name of the route map\n"
5711 "Label index to associate with the prefix\n"
5712 "Label index value\n")
718e3744 5713{
a4d82a8a
PZ
5714 return bgp_static_set(
5715 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
5716 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
5717}
5718
d62a17ae 5719static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 5720{
d62a17ae 5721 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 5722}
5723
d62a17ae 5724static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 5725{
20894f50
DA
5726 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
5727 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 5728 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
5729}
718e3744 5730
40381db7 5731static int bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
29f7d023 5732 struct aspath *aspath,
3da2cc32 5733 struct community *comm,
dd18c5a9
DS
5734 struct ecommunity *ecomm,
5735 struct lcommunity *lcomm)
eaaf8adb
DS
5736{
5737 static struct aspath *ae = NULL;
5738
5739 if (!ae)
5740 ae = aspath_empty();
5741
40381db7 5742 if (!pi)
eaaf8adb
DS
5743 return 0;
5744
40381db7 5745 if (origin != pi->attr->origin)
eaaf8adb
DS
5746 return 0;
5747
40381db7 5748 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
29f7d023
DS
5749 return 0;
5750
40381db7 5751 if (!community_cmp(pi->attr->community, comm))
eaaf8adb
DS
5752 return 0;
5753
3da2cc32 5754 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
eaaf8adb
DS
5755 return 0;
5756
dd18c5a9
DS
5757 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
5758 return 0;
5759
40381db7 5760 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
7ce8a8e0
DS
5761 return 0;
5762
eaaf8adb
DS
5763 return 1;
5764}
5765
c701010e
DS
5766static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi,
5767 struct prefix *p, uint8_t origin,
5768 struct aspath *aspath,
5769 struct community *community,
3da2cc32 5770 struct ecommunity *ecommunity,
dd18c5a9 5771 struct lcommunity *lcommunity,
c701010e
DS
5772 uint8_t atomic_aggregate,
5773 struct bgp_aggregate *aggregate)
5774{
5775 struct bgp_node *rn;
5776 struct bgp_table *table;
6f94b685 5777 struct bgp_path_info *pi, *orig, *new;
20894f50 5778 struct attr *attr;
c701010e
DS
5779
5780 table = bgp->rib[afi][safi];
5781
5782 rn = bgp_node_get(table, p);
eaaf8adb 5783
6f94b685 5784 for (orig = pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
5785 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5786 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
5787 break;
5788
c701010e 5789 if (aggregate->count > 0) {
eaaf8adb
DS
5790 /*
5791 * If the aggregate information has not changed
5792 * no need to re-install it again.
5793 */
6f94b685 5794 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 5795 ecommunity, lcommunity)) {
eaaf8adb
DS
5796 bgp_unlock_node(rn);
5797
5798 if (aspath)
5799 aspath_free(aspath);
5800 if (community)
3c1f53de 5801 community_free(&community);
3da2cc32
DS
5802 if (ecommunity)
5803 ecommunity_free(&ecommunity);
dd18c5a9
DS
5804 if (lcommunity)
5805 lcommunity_free(&lcommunity);
eaaf8adb
DS
5806
5807 return;
5808 }
5809
5810 /*
5811 * Mark the old as unusable
5812 */
40381db7
DS
5813 if (pi)
5814 bgp_path_info_delete(rn, pi);
eaaf8adb 5815
20894f50
DA
5816 attr = bgp_attr_aggregate_intern(
5817 bgp, origin, aspath, community, ecommunity, lcommunity,
5818 aggregate, atomic_aggregate, p);
5819
5820 if (!attr) {
5821 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
5822 return;
5823 }
5824
3da2cc32 5825 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
20894f50
DA
5826 bgp->peer_self, attr, rn);
5827
1defdda8 5828 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 5829
18ee8310 5830 bgp_path_info_add(rn, new);
c701010e
DS
5831 bgp_process(bgp, rn, afi, safi);
5832 } else {
6f94b685 5833 for (pi = orig; pi; pi = pi->next)
40381db7
DS
5834 if (pi->peer == bgp->peer_self
5835 && pi->type == ZEBRA_ROUTE_BGP
5836 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
5837 break;
5838
5839 /* Withdraw static BGP route from routing table. */
40381db7
DS
5840 if (pi) {
5841 bgp_path_info_delete(rn, pi);
c701010e
DS
5842 bgp_process(bgp, rn, afi, safi);
5843 }
5844 }
5845
5846 bgp_unlock_node(rn);
5847}
5848
b5d58c32 5849/* Update an aggregate as routes are added/removed from the BGP table */
20894f50 5850void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
fc968841 5851 afi_t afi, safi_t safi,
d62a17ae 5852 struct bgp_aggregate *aggregate)
5853{
5854 struct bgp_table *table;
5855 struct bgp_node *top;
5856 struct bgp_node *rn;
d7c0a89a 5857 uint8_t origin;
d62a17ae 5858 struct aspath *aspath = NULL;
d62a17ae 5859 struct community *community = NULL;
3da2cc32 5860 struct ecommunity *ecommunity = NULL;
dd18c5a9 5861 struct lcommunity *lcommunity = NULL;
40381db7 5862 struct bgp_path_info *pi;
d62a17ae 5863 unsigned long match = 0;
d7c0a89a 5864 uint8_t atomic_aggregate = 0;
d62a17ae 5865
9f822fa2
S
5866 /* If the bgp instance is being deleted or self peer is deleted
5867 * then do not create aggregate route
5868 */
5869 if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS) ||
5870 (bgp->peer_self == NULL))
5871 return;
5872
d62a17ae 5873 /* ORIGIN attribute: If at least one route among routes that are
5874 aggregated has ORIGIN with the value INCOMPLETE, then the
5875 aggregated route must have the ORIGIN attribute with the value
5876 INCOMPLETE. Otherwise, if at least one route among routes that
5877 are aggregated has ORIGIN with the value EGP, then the aggregated
5878 route must have the origin attribute with the value EGP. In all
5879 other case the value of the ORIGIN attribute of the aggregated
5880 route is INTERNAL. */
5881 origin = BGP_ORIGIN_IGP;
718e3744 5882
d62a17ae 5883 table = bgp->rib[afi][safi];
718e3744 5884
d62a17ae 5885 top = bgp_node_get(table, p);
5886 for (rn = bgp_node_get(table, p); rn;
c2ff8b3e
DS
5887 rn = bgp_route_next_until(rn, top)) {
5888 if (rn->p.prefixlen <= p->prefixlen)
5889 continue;
d62a17ae 5890
c2ff8b3e 5891 match = 0;
d62a17ae 5892
6f94b685 5893 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 5894 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 5895 continue;
718e3744 5896
40381db7 5897 if (pi->attr->flag
c2ff8b3e
DS
5898 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
5899 atomic_aggregate = 1;
d62a17ae 5900
40381db7 5901 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 5902 continue;
d62a17ae 5903
f273fef1
DS
5904 /*
5905 * summary-only aggregate route suppress
5906 * aggregated route announcements.
5907 */
c2ff8b3e 5908 if (aggregate->summary_only) {
40381db7
DS
5909 (bgp_path_info_extra_get(pi))->suppress++;
5910 bgp_path_info_set_flag(rn, pi,
18ee8310 5911 BGP_PATH_ATTR_CHANGED);
c2ff8b3e 5912 match++;
d62a17ae 5913 }
c2ff8b3e
DS
5914
5915 aggregate->count++;
5916
f273fef1
DS
5917 /*
5918 * If at least one route among routes that are
5919 * aggregated has ORIGIN with the value INCOMPLETE,
5920 * then the aggregated route MUST have the ORIGIN
5921 * attribute with the value INCOMPLETE. Otherwise, if
5922 * at least one route among routes that are aggregated
5923 * has ORIGIN with the value EGP, then the aggregated
5924 * route MUST have the ORIGIN attribute with the value
5925 * EGP.
5926 */
fc968841
NT
5927 switch (pi->attr->origin) {
5928 case BGP_ORIGIN_INCOMPLETE:
5929 aggregate->incomplete_origin_count++;
5930 break;
5931 case BGP_ORIGIN_EGP:
5932 aggregate->egp_origin_count++;
5933 break;
5934 default:
5935 /*Do nothing.
5936 */
5937 break;
5938 }
c2ff8b3e
DS
5939
5940 if (!aggregate->as_set)
5941 continue;
5942
f273fef1
DS
5943 /*
5944 * as-set aggregate route generate origin, as path,
5945 * and community aggregation.
5946 */
fc968841
NT
5947 /* Compute aggregate route's as-path.
5948 */
ef51a7d8 5949 bgp_compute_aggregate_aspath_hash(aggregate,
5950 pi->attr->aspath);
c2ff8b3e 5951
fc968841
NT
5952 /* Compute aggregate route's community.
5953 */
5954 if (pi->attr->community)
21fec674 5955 bgp_compute_aggregate_community_hash(
fc968841
NT
5956 aggregate,
5957 pi->attr->community);
dd18c5a9 5958
fc968841
NT
5959 /* Compute aggregate route's extended community.
5960 */
5961 if (pi->attr->ecommunity)
4edd83f9 5962 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
5963 aggregate,
5964 pi->attr->ecommunity);
5965
5966 /* Compute aggregate route's large community.
5967 */
5968 if (pi->attr->lcommunity)
f1eb1f05 5969 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
5970 aggregate,
5971 pi->attr->lcommunity);
d62a17ae 5972 }
c2ff8b3e
DS
5973 if (match)
5974 bgp_process(bgp, rn, afi, safi);
5975 }
21fec674 5976 if (aggregate->as_set) {
ef51a7d8 5977 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 5978 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 5979 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 5980 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 5981 }
5982
f1eb1f05 5983
d62a17ae 5984 bgp_unlock_node(top);
718e3744 5985
718e3744 5986
fc968841
NT
5987 if (aggregate->incomplete_origin_count > 0)
5988 origin = BGP_ORIGIN_INCOMPLETE;
5989 else if (aggregate->egp_origin_count > 0)
5990 origin = BGP_ORIGIN_EGP;
d62a17ae 5991
fc968841
NT
5992 if (aggregate->as_set) {
5993 if (aggregate->aspath)
5994 /* Retrieve aggregate route's as-path.
5995 */
5996 aspath = aspath_dup(aggregate->aspath);
d62a17ae 5997
fc968841
NT
5998 if (aggregate->community)
5999 /* Retrieve aggregate route's community.
6000 */
6001 community = community_dup(aggregate->community);
3da2cc32 6002
fc968841
NT
6003 if (aggregate->ecommunity)
6004 /* Retrieve aggregate route's ecommunity.
6005 */
6006 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 6007
fc968841
NT
6008 if (aggregate->lcommunity)
6009 /* Retrieve aggregate route's lcommunity.
6010 */
6011 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 6012 }
718e3744 6013
c701010e 6014 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
6015 ecommunity, lcommunity, atomic_aggregate,
6016 aggregate);
718e3744 6017}
6018
20894f50 6019void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
3b7db173
DS
6020 safi_t safi, struct bgp_aggregate *aggregate)
6021{
6022 struct bgp_table *table;
6023 struct bgp_node *top;
6024 struct bgp_node *rn;
40381db7 6025 struct bgp_path_info *pi;
3b7db173
DS
6026 unsigned long match;
6027
6028 table = bgp->rib[afi][safi];
6029
6030 /* If routes exists below this node, generate aggregate routes. */
6031 top = bgp_node_get(table, p);
6032 for (rn = bgp_node_get(table, p); rn;
6033 rn = bgp_route_next_until(rn, top)) {
6034 if (rn->p.prefixlen <= p->prefixlen)
6035 continue;
6036 match = 0;
6037
6f94b685 6038 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 6039 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
6040 continue;
6041
40381db7 6042 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
6043 continue;
6044
40381db7
DS
6045 if (aggregate->summary_only && pi->extra) {
6046 pi->extra->suppress--;
3b7db173 6047
40381db7 6048 if (pi->extra->suppress == 0) {
18ee8310 6049 bgp_path_info_set_flag(
40381db7 6050 rn, pi, BGP_PATH_ATTR_CHANGED);
3b7db173
DS
6051 match++;
6052 }
6053 }
6054 aggregate->count--;
fc968841
NT
6055
6056 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6057 aggregate->incomplete_origin_count--;
6058 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6059 aggregate->egp_origin_count--;
6060
6061 if (aggregate->as_set) {
6062 /* Remove as-path from aggregate.
6063 */
ef51a7d8 6064 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
6065 aggregate,
6066 pi->attr->aspath);
6067
6068 if (pi->attr->community)
6069 /* Remove community from aggregate.
6070 */
21fec674 6071 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
6072 aggregate,
6073 pi->attr->community);
6074
6075 if (pi->attr->ecommunity)
6076 /* Remove ecommunity from aggregate.
6077 */
4edd83f9 6078 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
6079 aggregate,
6080 pi->attr->ecommunity);
6081
6082 if (pi->attr->lcommunity)
6083 /* Remove lcommunity from aggregate.
6084 */
f1eb1f05 6085 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
6086 aggregate,
6087 pi->attr->lcommunity);
6088 }
6089
3b7db173
DS
6090 }
6091
6092 /* If this node was suppressed, process the change. */
6093 if (match)
6094 bgp_process(bgp, rn, afi, safi);
6095 }
f1eb1f05 6096 if (aggregate->as_set) {
ef51a7d8 6097 aspath_free(aggregate->aspath);
6098 aggregate->aspath = NULL;
21fec674 6099 if (aggregate->community)
6100 community_free(&aggregate->community);
4edd83f9 6101 if (aggregate->ecommunity)
6102 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 6103 if (aggregate->lcommunity)
6104 lcommunity_free(&aggregate->lcommunity);
6105 }
6106
3b7db173
DS
6107 bgp_unlock_node(top);
6108}
718e3744 6109
fc968841
NT
6110static void bgp_add_route_to_aggregate(struct bgp *bgp, struct prefix *aggr_p,
6111 struct bgp_path_info *pinew, afi_t afi,
6112 safi_t safi,
6113 struct bgp_aggregate *aggregate)
6114{
6115 uint8_t origin;
6116 struct aspath *aspath = NULL;
6117 uint8_t atomic_aggregate = 0;
6118 struct community *community = NULL;
6119 struct ecommunity *ecommunity = NULL;
6120 struct lcommunity *lcommunity = NULL;
6121
6122 /* ORIGIN attribute: If at least one route among routes that are
6123 * aggregated has ORIGIN with the value INCOMPLETE, then the
6124 * aggregated route must have the ORIGIN attribute with the value
6125 * INCOMPLETE. Otherwise, if at least one route among routes that
6126 * are aggregated has ORIGIN with the value EGP, then the aggregated
6127 * route must have the origin attribute with the value EGP. In all
6128 * other case the value of the ORIGIN attribute of the aggregated
6129 * route is INTERNAL.
6130 */
6131 origin = BGP_ORIGIN_IGP;
6132
6133 aggregate->count++;
6134
6135 if (aggregate->summary_only)
6136 (bgp_path_info_extra_get(pinew))->suppress++;
6137
6138 switch (pinew->attr->origin) {
6139 case BGP_ORIGIN_INCOMPLETE:
6140 aggregate->incomplete_origin_count++;
6141 break;
6142 case BGP_ORIGIN_EGP:
6143 aggregate->egp_origin_count++;
6144 break;
6145 default:
6146 /* Do nothing.
6147 */
6148 break;
6149 }
6150
6151 if (aggregate->incomplete_origin_count > 0)
6152 origin = BGP_ORIGIN_INCOMPLETE;
6153 else if (aggregate->egp_origin_count > 0)
6154 origin = BGP_ORIGIN_EGP;
6155
6156 if (aggregate->as_set) {
6157 /* Compute aggregate route's as-path.
6158 */
6159 bgp_compute_aggregate_aspath(aggregate,
6160 pinew->attr->aspath);
6161
6162 /* Compute aggregate route's community.
6163 */
6164 if (pinew->attr->community)
6165 bgp_compute_aggregate_community(
6166 aggregate,
6167 pinew->attr->community);
6168
6169 /* Compute aggregate route's extended community.
6170 */
6171 if (pinew->attr->ecommunity)
6172 bgp_compute_aggregate_ecommunity(
6173 aggregate,
6174 pinew->attr->ecommunity);
6175
6176 /* Compute aggregate route's large community.
6177 */
6178 if (pinew->attr->lcommunity)
6179 bgp_compute_aggregate_lcommunity(
6180 aggregate,
6181 pinew->attr->lcommunity);
6182
6183 /* Retrieve aggregate route's as-path.
6184 */
6185 if (aggregate->aspath)
6186 aspath = aspath_dup(aggregate->aspath);
6187
6188 /* Retrieve aggregate route's community.
6189 */
6190 if (aggregate->community)
6191 community = community_dup(aggregate->community);
6192
6193 /* Retrieve aggregate route's ecommunity.
6194 */
6195 if (aggregate->ecommunity)
6196 ecommunity = ecommunity_dup(aggregate->ecommunity);
6197
6198 /* Retrieve aggregate route's lcommunity.
6199 */
6200 if (aggregate->lcommunity)
6201 lcommunity = lcommunity_dup(aggregate->lcommunity);
6202 }
6203
6204 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6205 aspath, community, ecommunity,
6206 lcommunity, atomic_aggregate, aggregate);
6207}
6208
6209static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
6210 safi_t safi,
6211 struct bgp_path_info *pi,
6212 struct bgp_aggregate *aggregate,
6213 struct prefix *aggr_p)
6214{
6215 uint8_t origin;
6216 struct aspath *aspath = NULL;
6217 uint8_t atomic_aggregate = 0;
6218 struct community *community = NULL;
6219 struct ecommunity *ecommunity = NULL;
6220 struct lcommunity *lcommunity = NULL;
6221 unsigned long match = 0;
6222
6223 if (BGP_PATH_HOLDDOWN(pi))
6224 return;
6225
6226 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6227 return;
6228
6229 if (aggregate->summary_only
6230 && pi->extra
6231 && pi->extra->suppress > 0) {
6232 pi->extra->suppress--;
6233
6234 if (pi->extra->suppress == 0) {
6235 bgp_path_info_set_flag(pi->net, pi,
6236 BGP_PATH_ATTR_CHANGED);
6237 match++;
6238 }
6239 }
6240
6241 if (aggregate->count > 0)
6242 aggregate->count--;
6243
6244 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6245 aggregate->incomplete_origin_count--;
6246 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6247 aggregate->egp_origin_count--;
6248
6249 if (aggregate->as_set) {
6250 /* Remove as-path from aggregate.
6251 */
6252 bgp_remove_aspath_from_aggregate(aggregate,
6253 pi->attr->aspath);
6254
6255 if (pi->attr->community)
6256 /* Remove community from aggregate.
6257 */
6258 bgp_remove_community_from_aggregate(
6259 aggregate,
6260 pi->attr->community);
6261
6262 if (pi->attr->ecommunity)
6263 /* Remove ecommunity from aggregate.
6264 */
6265 bgp_remove_ecommunity_from_aggregate(
6266 aggregate,
6267 pi->attr->ecommunity);
6268
6269 if (pi->attr->lcommunity)
6270 /* Remove lcommunity from aggregate.
6271 */
6272 bgp_remove_lcommunity_from_aggregate(
6273 aggregate,
6274 pi->attr->lcommunity);
6275 }
6276
6277 /* If this node was suppressed, process the change. */
6278 if (match)
6279 bgp_process(bgp, pi->net, afi, safi);
6280
6281 origin = BGP_ORIGIN_IGP;
6282 if (aggregate->incomplete_origin_count > 0)
6283 origin = BGP_ORIGIN_INCOMPLETE;
6284 else if (aggregate->egp_origin_count > 0)
6285 origin = BGP_ORIGIN_EGP;
6286
6287 if (aggregate->as_set) {
6288 /* Retrieve aggregate route's as-path.
6289 */
6290 if (aggregate->aspath)
6291 aspath = aspath_dup(aggregate->aspath);
6292
6293 /* Retrieve aggregate route's community.
6294 */
6295 if (aggregate->community)
6296 community = community_dup(aggregate->community);
6297
6298 /* Retrieve aggregate route's ecommunity.
6299 */
6300 if (aggregate->ecommunity)
6301 ecommunity = ecommunity_dup(aggregate->ecommunity);
6302
6303 /* Retrieve aggregate route's lcommunity.
6304 */
6305 if (aggregate->lcommunity)
6306 lcommunity = lcommunity_dup(aggregate->lcommunity);
6307 }
6308
6309 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6310 aspath, community, ecommunity,
6311 lcommunity, atomic_aggregate, aggregate);
6312}
6313
d62a17ae 6314void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p,
40381db7 6315 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 6316{
d62a17ae 6317 struct bgp_node *child;
6318 struct bgp_node *rn;
6319 struct bgp_aggregate *aggregate;
6320 struct bgp_table *table;
718e3744 6321
d62a17ae 6322 table = bgp->aggregate[afi][safi];
f018db83 6323
d62a17ae 6324 /* No aggregates configured. */
6325 if (bgp_table_top_nolock(table) == NULL)
6326 return;
f018db83 6327
d62a17ae 6328 if (p->prefixlen == 0)
6329 return;
718e3744 6330
40381db7 6331 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 6332 return;
718e3744 6333
d62a17ae 6334 child = bgp_node_get(table, p);
718e3744 6335
d62a17ae 6336 /* Aggregate address configuration check. */
b1e62edd 6337 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
b613a918 6338 aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 6339 if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
fc968841
NT
6340 bgp_add_route_to_aggregate(bgp, &rn->p, pi, afi,
6341 safi, aggregate);
d62a17ae 6342 }
b1e62edd 6343 }
d62a17ae 6344 bgp_unlock_node(child);
718e3744 6345}
6346
d62a17ae 6347void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p,
4b7e6066 6348 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 6349{
d62a17ae 6350 struct bgp_node *child;
6351 struct bgp_node *rn;
6352 struct bgp_aggregate *aggregate;
6353 struct bgp_table *table;
718e3744 6354
d62a17ae 6355 table = bgp->aggregate[afi][safi];
718e3744 6356
d62a17ae 6357 /* No aggregates configured. */
6358 if (bgp_table_top_nolock(table) == NULL)
6359 return;
718e3744 6360
d62a17ae 6361 if (p->prefixlen == 0)
6362 return;
718e3744 6363
d62a17ae 6364 child = bgp_node_get(table, p);
718e3744 6365
d62a17ae 6366 /* Aggregate address configuration check. */
b1e62edd 6367 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
b613a918 6368 aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 6369 if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
fc968841
NT
6370 bgp_remove_route_from_aggregate(bgp, afi, safi,
6371 del, aggregate, &rn->p);
d62a17ae 6372 }
b1e62edd 6373 }
d62a17ae 6374 bgp_unlock_node(child);
6375}
718e3744 6376
718e3744 6377/* Aggregate route attribute. */
6378#define AGGREGATE_SUMMARY_ONLY 1
6379#define AGGREGATE_AS_SET 1
6380
d62a17ae 6381static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
6382 afi_t afi, safi_t safi)
718e3744 6383{
d62a17ae 6384 VTY_DECLVAR_CONTEXT(bgp, bgp);
6385 int ret;
6386 struct prefix p;
6387 struct bgp_node *rn;
6388 struct bgp_aggregate *aggregate;
718e3744 6389
d62a17ae 6390 /* Convert string to prefix structure. */
6391 ret = str2prefix(prefix_str, &p);
6392 if (!ret) {
6393 vty_out(vty, "Malformed prefix\n");
6394 return CMD_WARNING_CONFIG_FAILED;
6395 }
6396 apply_mask(&p);
6397
6398 /* Old configuration check. */
6399 rn = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
6400 if (!rn) {
6401 vty_out(vty,
6402 "%% There is no aggregate-address configuration.\n");
6403 return CMD_WARNING_CONFIG_FAILED;
6404 }
f6269b4f 6405
b613a918 6406 aggregate = bgp_node_get_bgp_aggregate_info(rn);
09990cdd 6407 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
dd18c5a9
DS
6408 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
6409 NULL, NULL, 0, aggregate);
d62a17ae 6410
6411 /* Unlock aggregate address configuration. */
b613a918 6412 bgp_node_set_bgp_aggregate_info(rn, NULL);
fc968841
NT
6413
6414 if (aggregate->community)
6415 community_free(&aggregate->community);
6416
6417 if (aggregate->community_hash) {
6418 /* Delete all communities in the hash.
6419 */
6420 hash_clean(aggregate->community_hash,
6421 bgp_aggr_community_remove);
6422 /* Free up the community_hash.
6423 */
6424 hash_free(aggregate->community_hash);
6425 }
6426
6427 if (aggregate->ecommunity)
6428 ecommunity_free(&aggregate->ecommunity);
6429
6430 if (aggregate->ecommunity_hash) {
6431 /* Delete all ecommunities in the hash.
6432 */
6433 hash_clean(aggregate->ecommunity_hash,
6434 bgp_aggr_ecommunity_remove);
6435 /* Free up the ecommunity_hash.
6436 */
6437 hash_free(aggregate->ecommunity_hash);
6438 }
6439
6440 if (aggregate->lcommunity)
6441 lcommunity_free(&aggregate->lcommunity);
6442
6443 if (aggregate->lcommunity_hash) {
6444 /* Delete all lcommunities in the hash.
6445 */
6446 hash_clean(aggregate->lcommunity_hash,
6447 bgp_aggr_lcommunity_remove);
6448 /* Free up the lcommunity_hash.
6449 */
6450 hash_free(aggregate->lcommunity_hash);
6451 }
6452
6453 if (aggregate->aspath)
6454 aspath_free(aggregate->aspath);
6455
6456 if (aggregate->aspath_hash) {
6457 /* Delete all as-paths in the hash.
6458 */
6459 hash_clean(aggregate->aspath_hash,
6460 bgp_aggr_aspath_remove);
6461 /* Free up the aspath_hash.
6462 */
6463 hash_free(aggregate->aspath_hash);
6464 }
6465
d62a17ae 6466 bgp_aggregate_free(aggregate);
6467 bgp_unlock_node(rn);
6468 bgp_unlock_node(rn);
6469
6470 return CMD_SUCCESS;
6471}
6472
6473static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
20894f50
DA
6474 safi_t safi, const char *rmap, uint8_t summary_only,
6475 uint8_t as_set)
d62a17ae 6476{
6477 VTY_DECLVAR_CONTEXT(bgp, bgp);
6478 int ret;
6479 struct prefix p;
6480 struct bgp_node *rn;
6481 struct bgp_aggregate *aggregate;
6482
6483 /* Convert string to prefix structure. */
6484 ret = str2prefix(prefix_str, &p);
6485 if (!ret) {
6486 vty_out(vty, "Malformed prefix\n");
6487 return CMD_WARNING_CONFIG_FAILED;
6488 }
6489 apply_mask(&p);
6490
3624ac81
DS
6491 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
6492 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
6493 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6494 prefix_str);
6495 return CMD_WARNING_CONFIG_FAILED;
6496 }
6497
d62a17ae 6498 /* Old configuration check. */
6499 rn = bgp_node_get(bgp->aggregate[afi][safi], &p);
20894f50 6500 aggregate = bgp_node_get_bgp_aggregate_info(rn);
d62a17ae 6501
20894f50 6502 if (aggregate) {
d62a17ae 6503 vty_out(vty, "There is already same aggregate network.\n");
6504 /* try to remove the old entry */
6505 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
6506 if (ret) {
6507 vty_out(vty, "Error deleting aggregate.\n");
6508 bgp_unlock_node(rn);
6509 return CMD_WARNING_CONFIG_FAILED;
6510 }
6511 }
718e3744 6512
d62a17ae 6513 /* Make aggregate address structure. */
6514 aggregate = bgp_aggregate_new();
6515 aggregate->summary_only = summary_only;
6516 aggregate->as_set = as_set;
6517 aggregate->safi = safi;
20894f50
DA
6518
6519 if (rmap) {
6520 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6521 route_map_counter_decrement(aggregate->rmap.map);
6522 aggregate->rmap.name =
6523 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6524 aggregate->rmap.map = route_map_lookup_by_name(rmap);
6525 route_map_counter_increment(aggregate->rmap.map);
6526 }
b613a918 6527 bgp_node_set_bgp_aggregate_info(rn, aggregate);
718e3744 6528
d62a17ae 6529 /* Aggregate address insert into BGP routing table. */
fc968841 6530 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 6531
d62a17ae 6532 return CMD_SUCCESS;
718e3744 6533}
6534
6535DEFUN (aggregate_address,
6536 aggregate_address_cmd,
20894f50 6537 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6538 "Configure BGP aggregate entries\n"
6539 "Aggregate prefix\n"
6540 "Generate AS set path information\n"
a636c635
DW
6541 "Filter more specific routes from updates\n"
6542 "Filter more specific routes from updates\n"
20894f50
DA
6543 "Generate AS set path information\n"
6544 "Apply route map to aggregate network\n"
6545 "Name of route map\n")
718e3744 6546{
d62a17ae 6547 int idx = 0;
6548 argv_find(argv, argc, "A.B.C.D/M", &idx);
6549 char *prefix = argv[idx]->arg;
20894f50 6550 char *rmap = NULL;
d62a17ae 6551 int as_set =
6552 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
6553 idx = 0;
6554 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6555 ? AGGREGATE_SUMMARY_ONLY
6556 : 0;
e3e6107d 6557
20894f50
DA
6558 idx = 0;
6559 argv_find(argv, argc, "WORD", &idx);
6560 if (idx)
6561 rmap = argv[idx]->arg;
6562
d62a17ae 6563 return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty),
20894f50 6564 rmap, summary_only, as_set);
718e3744 6565}
6566
e3e6107d
QY
6567DEFUN (aggregate_address_mask,
6568 aggregate_address_mask_cmd,
20894f50 6569 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6570 "Configure BGP aggregate entries\n"
6571 "Aggregate address\n"
6572 "Aggregate mask\n"
6573 "Generate AS set path information\n"
a636c635
DW
6574 "Filter more specific routes from updates\n"
6575 "Filter more specific routes from updates\n"
20894f50
DA
6576 "Generate AS set path information\n"
6577 "Apply route map to aggregate network\n"
6578 "Name of route map\n")
718e3744 6579{
d62a17ae 6580 int idx = 0;
6581 argv_find(argv, argc, "A.B.C.D", &idx);
6582 char *prefix = argv[idx]->arg;
6583 char *mask = argv[idx + 1]->arg;
cf40d052 6584 bool rmap_found;
20894f50 6585 char *rmap = NULL;
d62a17ae 6586 int as_set =
6587 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
6588 idx = 0;
6589 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6590 ? AGGREGATE_SUMMARY_ONLY
6591 : 0;
6592
cf40d052
DS
6593 rmap_found = argv_find(argv, argc, "WORD", &idx);
6594 if (rmap_found)
20894f50
DA
6595 rmap = argv[idx]->arg;
6596
d62a17ae 6597 char prefix_str[BUFSIZ];
6598 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
6599
6600 if (!ret) {
6601 vty_out(vty, "%% Inconsistent address and mask\n");
6602 return CMD_WARNING_CONFIG_FAILED;
6603 }
718e3744 6604
d62a17ae 6605 return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
20894f50 6606 rmap, summary_only, as_set);
718e3744 6607}
6608
718e3744 6609DEFUN (no_aggregate_address,
6610 no_aggregate_address_cmd,
b84da0db 6611 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6612 NO_STR
6613 "Configure BGP aggregate entries\n"
a636c635
DW
6614 "Aggregate prefix\n"
6615 "Generate AS set path information\n"
e3e6107d
QY
6616 "Filter more specific routes from updates\n"
6617 "Filter more specific routes from updates\n"
b84da0db
DA
6618 "Generate AS set path information\n"
6619 "Apply route map to aggregate network\n"
6620 "Name of route map\n")
718e3744 6621{
d62a17ae 6622 int idx = 0;
6623 argv_find(argv, argc, "A.B.C.D/M", &idx);
6624 char *prefix = argv[idx]->arg;
6625 return bgp_aggregate_unset(vty, prefix, AFI_IP, bgp_node_safi(vty));
718e3744 6626}
6627
718e3744 6628DEFUN (no_aggregate_address_mask,
6629 no_aggregate_address_mask_cmd,
b84da0db 6630 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6631 NO_STR
6632 "Configure BGP aggregate entries\n"
6633 "Aggregate address\n"
a636c635
DW
6634 "Aggregate mask\n"
6635 "Generate AS set path information\n"
e3e6107d
QY
6636 "Filter more specific routes from updates\n"
6637 "Filter more specific routes from updates\n"
b84da0db
DA
6638 "Generate AS set path information\n"
6639 "Apply route map to aggregate network\n"
6640 "Name of route map\n")
718e3744 6641{
d62a17ae 6642 int idx = 0;
6643 argv_find(argv, argc, "A.B.C.D", &idx);
6644 char *prefix = argv[idx]->arg;
6645 char *mask = argv[idx + 1]->arg;
718e3744 6646
d62a17ae 6647 char prefix_str[BUFSIZ];
6648 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
718e3744 6649
d62a17ae 6650 if (!ret) {
6651 vty_out(vty, "%% Inconsistent address and mask\n");
6652 return CMD_WARNING_CONFIG_FAILED;
6653 }
718e3744 6654
d62a17ae 6655 return bgp_aggregate_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
718e3744 6656}
6657
718e3744 6658DEFUN (ipv6_aggregate_address,
6659 ipv6_aggregate_address_cmd,
20894f50 6660 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6661 "Configure BGP aggregate entries\n"
6662 "Aggregate prefix\n"
5101fece 6663 "Generate AS set path information\n"
6664 "Filter more specific routes from updates\n"
6665 "Filter more specific routes from updates\n"
20894f50
DA
6666 "Generate AS set path information\n"
6667 "Apply route map to aggregate network\n"
6668 "Name of route map\n")
718e3744 6669{
d62a17ae 6670 int idx = 0;
6671 argv_find(argv, argc, "X:X::X:X/M", &idx);
6672 char *prefix = argv[idx]->arg;
20894f50 6673 char *rmap = NULL;
273fae13 6674 bool rmap_found;
5101fece 6675 int as_set =
6676 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
6677
6678 idx = 0;
d62a17ae 6679 int sum_only = argv_find(argv, argc, "summary-only", &idx)
6680 ? AGGREGATE_SUMMARY_ONLY
6681 : 0;
20894f50 6682
273fae13
DA
6683 rmap_found = argv_find(argv, argc, "WORD", &idx);
6684 if (rmap_found)
20894f50
DA
6685 rmap = argv[idx]->arg;
6686
6687 return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, rmap,
6688 sum_only, as_set);
718e3744 6689}
6690
6691DEFUN (no_ipv6_aggregate_address,
6692 no_ipv6_aggregate_address_cmd,
b84da0db 6693 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6694 NO_STR
6695 "Configure BGP aggregate entries\n"
16cedbb0 6696 "Aggregate prefix\n"
5101fece 6697 "Generate AS set path information\n"
6698 "Filter more specific routes from updates\n"
6699 "Filter more specific routes from updates\n"
b84da0db
DA
6700 "Generate AS set path information\n"
6701 "Apply route map to aggregate network\n"
6702 "Name of route map\n")
718e3744 6703{
d62a17ae 6704 int idx = 0;
6705 argv_find(argv, argc, "X:X::X:X/M", &idx);
6706 char *prefix = argv[idx]->arg;
6707 return bgp_aggregate_unset(vty, prefix, AFI_IP6, SAFI_UNICAST);
718e3744 6708}
6709
718e3744 6710/* Redistribute route treatment. */
d62a17ae 6711void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
6712 const union g_addr *nexthop, ifindex_t ifindex,
6713 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
6714 uint8_t type, unsigned short instance,
6715 route_tag_t tag)
d62a17ae 6716{
4b7e6066 6717 struct bgp_path_info *new;
40381db7
DS
6718 struct bgp_path_info *bpi;
6719 struct bgp_path_info rmap_path;
d62a17ae 6720 struct bgp_node *bn;
6721 struct attr attr;
6722 struct attr *new_attr;
6723 afi_t afi;
b68885f9 6724 route_map_result_t ret;
d62a17ae 6725 struct bgp_redist *red;
6726
6727 /* Make default attribute. */
6728 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
6729 /*
6730 * This must not be NULL to satisfy Coverity SA
6731 */
6732 assert(attr.aspath);
9de1f7ff 6733
a4d82a8a 6734 switch (nhtype) {
9de1f7ff
DS
6735 case NEXTHOP_TYPE_IFINDEX:
6736 break;
6737 case NEXTHOP_TYPE_IPV4:
6738 case NEXTHOP_TYPE_IPV4_IFINDEX:
6739 attr.nexthop = nexthop->ipv4;
6740 break;
6741 case NEXTHOP_TYPE_IPV6:
6742 case NEXTHOP_TYPE_IPV6_IFINDEX:
6743 attr.mp_nexthop_global = nexthop->ipv6;
6744 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
6745 break;
6746 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
6747 switch (p->family) {
6748 case AF_INET:
9de1f7ff 6749 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
6750 break;
6751 case AF_INET6:
9de1f7ff
DS
6752 memset(&attr.mp_nexthop_global, 0,
6753 sizeof(attr.mp_nexthop_global));
74489921 6754 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 6755 break;
74489921 6756 }
9de1f7ff 6757 break;
d62a17ae 6758 }
74489921 6759 attr.nh_ifindex = ifindex;
f04a80a5 6760
d62a17ae 6761 attr.med = metric;
6762 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
6763 attr.tag = tag;
718e3744 6764
d62a17ae 6765 afi = family2afi(p->family);
6aeb9e78 6766
d62a17ae 6767 red = bgp_redist_lookup(bgp, afi, type, instance);
6768 if (red) {
6769 struct attr attr_new;
718e3744 6770
d62a17ae 6771 /* Copy attribute for modification. */
6772 bgp_attr_dup(&attr_new, &attr);
718e3744 6773
d62a17ae 6774 if (red->redist_metric_flag)
6775 attr_new.med = red->redist_metric;
718e3744 6776
d62a17ae 6777 /* Apply route-map. */
6778 if (red->rmap.name) {
40381db7
DS
6779 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
6780 rmap_path.peer = bgp->peer_self;
6781 rmap_path.attr = &attr_new;
718e3744 6782
d62a17ae 6783 SET_FLAG(bgp->peer_self->rmap_type,
6784 PEER_RMAP_TYPE_REDISTRIBUTE);
6785
6786 ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
40381db7 6787 &rmap_path);
d62a17ae 6788
6789 bgp->peer_self->rmap_type = 0;
6790
6791 if (ret == RMAP_DENYMATCH) {
6792 /* Free uninterned attribute. */
6793 bgp_attr_flush(&attr_new);
6794
6795 /* Unintern original. */
6796 aspath_unintern(&attr.aspath);
6797 bgp_redistribute_delete(bgp, p, type, instance);
6798 return;
6799 }
6800 }
6801
7f323236
DW
6802 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
6803 bgp_attr_add_gshut_community(&attr_new);
6804
d62a17ae 6805 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
6806 SAFI_UNICAST, p, NULL);
6807
6808 new_attr = bgp_attr_intern(&attr_new);
6809
6f94b685
DS
6810 for (bpi = bgp_node_get_bgp_path_info(bn); bpi;
6811 bpi = bpi->next)
40381db7
DS
6812 if (bpi->peer == bgp->peer_self
6813 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 6814 break;
6815
40381db7 6816 if (bpi) {
d62a17ae 6817 /* Ensure the (source route) type is updated. */
40381db7
DS
6818 bpi->type = type;
6819 if (attrhash_cmp(bpi->attr, new_attr)
6820 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 6821 bgp_attr_unintern(&new_attr);
6822 aspath_unintern(&attr.aspath);
6823 bgp_unlock_node(bn);
6824 return;
6825 } else {
6826 /* The attribute is changed. */
40381db7 6827 bgp_path_info_set_flag(bn, bpi,
18ee8310 6828 BGP_PATH_ATTR_CHANGED);
d62a17ae 6829
6830 /* Rewrite BGP route information. */
40381db7
DS
6831 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
6832 bgp_path_info_restore(bn, bpi);
d62a17ae 6833 else
40381db7
DS
6834 bgp_aggregate_decrement(
6835 bgp, p, bpi, afi, SAFI_UNICAST);
6836 bgp_attr_unintern(&bpi->attr);
6837 bpi->attr = new_attr;
6838 bpi->uptime = bgp_clock();
d62a17ae 6839
6840 /* Process change. */
40381db7 6841 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 6842 SAFI_UNICAST);
6843 bgp_process(bgp, bn, afi, SAFI_UNICAST);
6844 bgp_unlock_node(bn);
6845 aspath_unintern(&attr.aspath);
ddb5b488
PZ
6846
6847 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6848 || (bgp->inst_type
6849 == BGP_INSTANCE_TYPE_DEFAULT)) {
6850
6851 vpn_leak_from_vrf_update(
40381db7 6852 bgp_get_default(), bgp, bpi);
ddb5b488 6853 }
d62a17ae 6854 return;
6855 }
6856 }
6857
6858 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
6859 bgp->peer_self, new_attr, bn);
1defdda8 6860 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 6861
6862 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 6863 bgp_path_info_add(bn, new);
d62a17ae 6864 bgp_unlock_node(bn);
6865 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
6866
6867 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6868 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6869
6870 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6871 }
d62a17ae 6872 }
6873
6874 /* Unintern original. */
6875 aspath_unintern(&attr.aspath);
718e3744 6876}
6877
d7c0a89a
QY
6878void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
6879 unsigned short instance)
718e3744 6880{
d62a17ae 6881 afi_t afi;
6882 struct bgp_node *rn;
40381db7 6883 struct bgp_path_info *pi;
d62a17ae 6884 struct bgp_redist *red;
718e3744 6885
d62a17ae 6886 afi = family2afi(p->family);
718e3744 6887
d62a17ae 6888 red = bgp_redist_lookup(bgp, afi, type, instance);
6889 if (red) {
6890 rn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
6891 SAFI_UNICAST, p, NULL);
6892
6f94b685 6893 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7 6894 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 6895 break;
6896
40381db7 6897 if (pi) {
ddb5b488
PZ
6898 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6899 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6900
6901 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 6902 bgp, pi);
ddb5b488 6903 }
40381db7
DS
6904 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
6905 bgp_path_info_delete(rn, pi);
d62a17ae 6906 bgp_process(bgp, rn, afi, SAFI_UNICAST);
6907 }
6908 bgp_unlock_node(rn);
6909 }
6910}
6911
6912/* Withdraw specified route type's route. */
6913void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 6914 unsigned short instance)
d62a17ae 6915{
6916 struct bgp_node *rn;
40381db7 6917 struct bgp_path_info *pi;
d62a17ae 6918 struct bgp_table *table;
6919
6920 table = bgp->rib[afi][SAFI_UNICAST];
6921
6922 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685 6923 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
6924 if (pi->peer == bgp->peer_self && pi->type == type
6925 && pi->instance == instance)
d62a17ae 6926 break;
6927
40381db7 6928 if (pi) {
ddb5b488
PZ
6929 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6930 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6931
6932 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 6933 bgp, pi);
ddb5b488 6934 }
40381db7 6935 bgp_aggregate_decrement(bgp, &rn->p, pi, afi,
d62a17ae 6936 SAFI_UNICAST);
40381db7 6937 bgp_path_info_delete(rn, pi);
d62a17ae 6938 bgp_process(bgp, rn, afi, SAFI_UNICAST);
6939 }
718e3744 6940 }
718e3744 6941}
6b0655a2 6942
718e3744 6943/* Static function to display route. */
9c92b5f7
MK
6944static void route_vty_out_route(struct prefix *p, struct vty *vty,
6945 json_object *json)
718e3744 6946{
be054588 6947 int len = 0;
d62a17ae 6948 char buf[BUFSIZ];
50e05855 6949 char buf2[BUFSIZ];
718e3744 6950
d62a17ae 6951 if (p->family == AF_INET) {
c6462ff4 6952 if (!json) {
89e5e9f0
PM
6953 len = vty_out(
6954 vty, "%s/%d",
6955 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
6956 p->prefixlen);
c6462ff4
MK
6957 } else {
6958 json_object_string_add(json, "prefix",
6959 inet_ntop(p->family,
6960 &p->u.prefix, buf,
6961 BUFSIZ));
6962 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 6963 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 6964 json_object_string_add(json, "network", buf2);
c6462ff4 6965 }
d62a17ae 6966 } else if (p->family == AF_ETHERNET) {
b03b8898
DS
6967 prefix2str(p, buf, PREFIX_STRLEN);
6968 len = vty_out(vty, "%s", buf);
6969 } else if (p->family == AF_EVPN) {
57f7feb6 6970 if (!json)
60466a63
QY
6971 len = vty_out(
6972 vty, "%s",
6973 bgp_evpn_route2str((struct prefix_evpn *)p, buf,
6974 BUFSIZ));
57f7feb6 6975 else
60466a63 6976 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
6977 } else if (p->family == AF_FLOWSPEC) {
6978 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
6979 json ?
6980 NLRI_STRING_FORMAT_JSON_SIMPLE :
6981 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 6982 } else {
c6462ff4 6983 if (!json)
60466a63
QY
6984 len = vty_out(
6985 vty, "%s/%d",
6986 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
6987 p->prefixlen);
50e05855
AD
6988 else {
6989 json_object_string_add(json, "prefix",
6990 inet_ntop(p->family,
6991 &p->u.prefix, buf,
6992 BUFSIZ));
6993 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
6994 prefix2str(p, buf2, PREFIX_STRLEN);
6995 json_object_string_add(json, "network", buf2);
6996 }
9c92b5f7 6997 }
d62a17ae 6998
9c92b5f7
MK
6999 if (!json) {
7000 len = 17 - len;
7001 if (len < 1)
7002 vty_out(vty, "\n%*s", 20, " ");
7003 else
7004 vty_out(vty, "%*s", len, " ");
7005 }
718e3744 7006}
7007
d62a17ae 7008enum bgp_display_type {
7009 normal_list,
718e3744 7010};
7011
18ee8310 7012/* Print the short form route status for a bgp_path_info */
4b7e6066 7013static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 7014 struct bgp_path_info *path,
d62a17ae 7015 json_object *json_path)
718e3744 7016{
d62a17ae 7017 if (json_path) {
b05a1c8b 7018
d62a17ae 7019 /* Route status display. */
9b6d8fcf 7020 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7021 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 7022
9b6d8fcf 7023 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7024 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 7025
9b6d8fcf 7026 if (path->extra && path->extra->suppress)
d62a17ae 7027 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 7028
9b6d8fcf
DS
7029 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7030 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7031 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 7032
d62a17ae 7033 /* Selected */
9b6d8fcf 7034 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7035 json_object_boolean_true_add(json_path, "history");
b05a1c8b 7036
9b6d8fcf 7037 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7038 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 7039
9b6d8fcf 7040 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7041 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b 7042
9b6d8fcf 7043 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7044 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 7045
d62a17ae 7046 /* Internal route. */
9b6d8fcf
DS
7047 if ((path->peer->as)
7048 && (path->peer->as == path->peer->local_as))
d62a17ae 7049 json_object_string_add(json_path, "pathFrom",
7050 "internal");
7051 else
7052 json_object_string_add(json_path, "pathFrom",
7053 "external");
b05a1c8b 7054
d62a17ae 7055 return;
7056 }
b05a1c8b 7057
d62a17ae 7058 /* Route status display. */
9b6d8fcf 7059 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7060 vty_out(vty, "R");
9b6d8fcf 7061 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7062 vty_out(vty, "S");
9b6d8fcf 7063 else if (path->extra && path->extra->suppress)
d62a17ae 7064 vty_out(vty, "s");
9b6d8fcf
DS
7065 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7066 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7067 vty_out(vty, "*");
7068 else
7069 vty_out(vty, " ");
7070
7071 /* Selected */
9b6d8fcf 7072 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7073 vty_out(vty, "h");
9b6d8fcf 7074 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7075 vty_out(vty, "d");
9b6d8fcf 7076 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7077 vty_out(vty, ">");
9b6d8fcf 7078 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7079 vty_out(vty, "=");
7080 else
7081 vty_out(vty, " ");
718e3744 7082
d62a17ae 7083 /* Internal route. */
9b6d8fcf
DS
7084 if (path->peer && (path->peer->as)
7085 && (path->peer->as == path->peer->local_as))
d62a17ae 7086 vty_out(vty, "i");
7087 else
7088 vty_out(vty, " ");
b40d939b 7089}
7090
25b5da8d
DA
7091static char *bgp_nexthop_fqdn(struct peer *peer)
7092{
7093 if (peer->hostname && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
7094 return peer->hostname;
7095 return NULL;
7096}
7097
b40d939b 7098/* called from terminal list command */
4b7e6066 7099void route_vty_out(struct vty *vty, struct prefix *p,
9b6d8fcf 7100 struct bgp_path_info *path, int display, safi_t safi,
4b7e6066 7101 json_object *json_paths)
d62a17ae 7102{
7103 struct attr *attr;
7104 json_object *json_path = NULL;
7105 json_object *json_nexthops = NULL;
7106 json_object *json_nexthop_global = NULL;
7107 json_object *json_nexthop_ll = NULL;
6f214dd3 7108 json_object *json_ext_community = NULL;
9df8b37c 7109 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 7110 bool nexthop_self =
9b6d8fcf 7111 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 7112 bool nexthop_othervrf = false;
43089216 7113 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 7114 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
25b5da8d 7115 char *nexthop_fqdn = bgp_nexthop_fqdn(path->peer);
d62a17ae 7116
7117 if (json_paths)
7118 json_path = json_object_new_object();
7119
7120 /* short status lead text */
9b6d8fcf 7121 route_vty_short_status_out(vty, path, json_path);
d62a17ae 7122
7123 if (!json_paths) {
7124 /* print prefix and mask */
7125 if (!display)
9c92b5f7 7126 route_vty_out_route(p, vty, json_path);
d62a17ae 7127 else
7128 vty_out(vty, "%*s", 17, " ");
9c92b5f7 7129 } else {
b682f6de 7130 route_vty_out_route(p, vty, json_path);
d62a17ae 7131 }
47fc97cc 7132
d62a17ae 7133 /* Print attribute */
9b6d8fcf 7134 attr = path->attr;
445c2480 7135
9df8b37c
PZ
7136 /*
7137 * If vrf id of nexthop is different from that of prefix,
7138 * set up printable string to append
7139 */
9b6d8fcf 7140 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
7141 const char *self = "";
7142
7143 if (nexthop_self)
7144 self = "<";
7145
7146 nexthop_othervrf = true;
9b6d8fcf 7147 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 7148
9b6d8fcf 7149 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
7150 snprintf(vrf_id_str, sizeof(vrf_id_str),
7151 "@%s%s", VRFID_NONE_STR, self);
7152 else
7153 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 7154 path->extra->bgp_orig->vrf_id, self);
9df8b37c 7155
9b6d8fcf
DS
7156 if (path->extra->bgp_orig->inst_type
7157 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 7158
9b6d8fcf 7159 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
7160 } else {
7161 const char *self = "";
7162
7163 if (nexthop_self)
7164 self = "<";
7165
7166 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
7167 }
7168
445c2480
DS
7169 /*
7170 * For ENCAP and EVPN routes, nexthop address family is not
7171 * neccessarily the same as the prefix address family.
7172 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7173 * EVPN routes are also exchanged with a MP nexthop. Currently,
7174 * this
7175 * is only IPv4, the value will be present in either
7176 * attr->nexthop or
7177 * attr->mp_nexthop_global_in
7178 */
7179 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
7180 char buf[BUFSIZ];
7181 char nexthop[128];
7182 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
7183
7184 switch (af) {
7185 case AF_INET:
7186 sprintf(nexthop, "%s",
a4d82a8a
PZ
7187 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
7188 BUFSIZ));
445c2480
DS
7189 break;
7190 case AF_INET6:
7191 sprintf(nexthop, "%s",
a4d82a8a
PZ
7192 inet_ntop(af, &attr->mp_nexthop_global, buf,
7193 BUFSIZ));
445c2480
DS
7194 break;
7195 default:
7196 sprintf(nexthop, "?");
7197 break;
d62a17ae 7198 }
d62a17ae 7199
445c2480
DS
7200 if (json_paths) {
7201 json_nexthop_global = json_object_new_object();
7202
25b5da8d
DA
7203 json_object_string_add(
7204 json_nexthop_global, "afi",
7205 nexthop_fqdn ? "fqdn"
7206 : (af == AF_INET) ? "ip" : "ipv6");
7207 json_object_string_add(
7208 json_nexthop_global,
7209 nexthop_fqdn ? "fqdn"
7210 : (af == AF_INET) ? "ip" : "ipv6",
7211 nexthop_fqdn ? nexthop_fqdn : nexthop);
445c2480
DS
7212 json_object_boolean_true_add(json_nexthop_global,
7213 "used");
7214 } else
25b5da8d
DA
7215 vty_out(vty, "%s%s",
7216 nexthop_fqdn ? nexthop_fqdn : nexthop,
7217 vrf_id_str);
445c2480
DS
7218 } else if (safi == SAFI_EVPN) {
7219 if (json_paths) {
7220 json_nexthop_global = json_object_new_object();
7221
25b5da8d
DA
7222 json_object_string_add(
7223 json_nexthop_global,
7224 nexthop_fqdn ? "fqdn" : "ip",
7225 nexthop_fqdn ? nexthop_fqdn
7226 : inet_ntoa(attr->nexthop));
a4d82a8a
PZ
7227 json_object_string_add(json_nexthop_global, "afi",
7228 "ipv4");
445c2480
DS
7229 json_object_boolean_true_add(json_nexthop_global,
7230 "used");
7231 } else
25b5da8d
DA
7232 vty_out(vty, "%-16s%s",
7233 nexthop_fqdn ?: inet_ntoa(attr->nexthop),
9df8b37c 7234 vrf_id_str);
d33fc23b 7235 } else if (safi == SAFI_FLOWSPEC) {
026b914a
PG
7236 if (attr->nexthop.s_addr != 0) {
7237 if (json_paths) {
7238 json_nexthop_global = json_object_new_object();
7239 json_object_string_add(
25b5da8d
DA
7240 json_nexthop_global,
7241 nexthop_fqdn ? "fqdn" : "ip",
7242 nexthop_fqdn
7243 ? nexthop_fqdn
7244 : inet_ntoa(attr->nexthop));
026b914a
PG
7245 json_object_string_add(json_nexthop_global,
7246 "afi", "ipv4");
50e05855
AD
7247 json_object_boolean_true_add(
7248 json_nexthop_global,
026b914a
PG
7249 "used");
7250 } else {
25b5da8d
DA
7251 vty_out(vty, "%-16s",
7252 nexthop_fqdn
7253 ? nexthop_fqdn
7254 : inet_ntoa(attr->nexthop));
026b914a
PG
7255 }
7256 }
d33fc23b 7257 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
7258 if (json_paths) {
7259 json_nexthop_global = json_object_new_object();
d62a17ae 7260
22df2d8a
DS
7261 json_object_string_add(json_nexthop_global,
7262 nexthop_fqdn ? "fqdn" : "ip",
7263 nexthop_fqdn
7264 ? nexthop_fqdn
7265 : inet_ntoa(attr->nexthop));
445c2480 7266
a4d82a8a
PZ
7267 json_object_string_add(json_nexthop_global, "afi",
7268 "ipv4");
445c2480
DS
7269 json_object_boolean_true_add(json_nexthop_global,
7270 "used");
7271 } else {
9df8b37c
PZ
7272 char buf[BUFSIZ];
7273
d87ff2dd 7274 snprintf(buf, sizeof(buf), "%s%s",
25b5da8d
DA
7275 nexthop_fqdn ? nexthop_fqdn
7276 : inet_ntoa(attr->nexthop),
7277 vrf_id_str);
9df8b37c 7278 vty_out(vty, "%-16s", buf);
d62a17ae 7279 }
445c2480 7280 }
b05a1c8b 7281
445c2480 7282 /* IPv6 Next Hop */
a4d82a8a 7283 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
7284 int len;
7285 char buf[BUFSIZ];
d62a17ae 7286
445c2480
DS
7287 if (json_paths) {
7288 json_nexthop_global = json_object_new_object();
a4d82a8a 7289 json_object_string_add(
25b5da8d
DA
7290 json_nexthop_global,
7291 nexthop_fqdn ? "fqdn" : "ip",
7292 nexthop_fqdn
7293 ? nexthop_fqdn
7294 : inet_ntop(AF_INET6,
7295 &attr->mp_nexthop_global,
7296 buf, BUFSIZ));
a4d82a8a
PZ
7297 json_object_string_add(json_nexthop_global, "afi",
7298 "ipv6");
7299 json_object_string_add(json_nexthop_global, "scope",
7300 "global");
445c2480
DS
7301
7302 /* We display both LL & GL if both have been
7303 * received */
0606039c
DA
7304 if ((attr->mp_nexthop_len
7305 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 7306 || (path->peer->conf_if)) {
a4d82a8a 7307 json_nexthop_ll = json_object_new_object();
d62a17ae 7308 json_object_string_add(
25b5da8d
DA
7309 json_nexthop_ll,
7310 nexthop_fqdn ? "fqdn" : "ip",
7311 nexthop_fqdn
7312 ? nexthop_fqdn
7313 : inet_ntop(
7314 AF_INET6,
7315 &attr->mp_nexthop_local,
7316 buf, BUFSIZ));
a4d82a8a
PZ
7317 json_object_string_add(json_nexthop_ll, "afi",
7318 "ipv6");
7319 json_object_string_add(json_nexthop_ll, "scope",
445c2480 7320 "link-local");
d62a17ae 7321
a4d82a8a
PZ
7322 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
7323 &attr->mp_nexthop_local)
445c2480
DS
7324 != 0)
7325 && !attr->mp_nexthop_prefer_global)
d62a17ae 7326 json_object_boolean_true_add(
a4d82a8a 7327 json_nexthop_ll, "used");
445c2480
DS
7328 else
7329 json_object_boolean_true_add(
a4d82a8a 7330 json_nexthop_global, "used");
445c2480
DS
7331 } else
7332 json_object_boolean_true_add(
7333 json_nexthop_global, "used");
7334 } else {
7335 /* Display LL if LL/Global both in table unless
7336 * prefer-global is set */
0606039c
DA
7337 if (((attr->mp_nexthop_len
7338 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 7339 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
7340 || (path->peer->conf_if)) {
7341 if (path->peer->conf_if) {
a4d82a8a 7342 len = vty_out(vty, "%s",
9b6d8fcf 7343 path->peer->conf_if);
445c2480
DS
7344 len = 16 - len; /* len of IPv6
7345 addr + max
7346 len of def
7347 ifname */
7348
7349 if (len < 1)
a4d82a8a 7350 vty_out(vty, "\n%*s", 36, " ");
445c2480 7351 else
a4d82a8a 7352 vty_out(vty, "%*s", len, " ");
d62a17ae 7353 } else {
7354 len = vty_out(
9df8b37c 7355 vty, "%s%s",
25b5da8d
DA
7356 nexthop_fqdn
7357 ? nexthop_fqdn
7358 : inet_ntop(
7359 AF_INET6,
7360 &attr->mp_nexthop_local,
7361 buf, BUFSIZ),
9df8b37c 7362 vrf_id_str);
d62a17ae 7363 len = 16 - len;
7364
7365 if (len < 1)
a4d82a8a 7366 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 7367 else
a4d82a8a 7368 vty_out(vty, "%*s", len, " ");
d62a17ae 7369 }
445c2480 7370 } else {
a4d82a8a 7371 len = vty_out(
9df8b37c 7372 vty, "%s%s",
25b5da8d
DA
7373 nexthop_fqdn
7374 ? nexthop_fqdn
7375 : inet_ntop(
7376 AF_INET6,
7377 &attr->mp_nexthop_global,
7378 buf, BUFSIZ),
7379 vrf_id_str);
445c2480
DS
7380 len = 16 - len;
7381
7382 if (len < 1)
7383 vty_out(vty, "\n%*s", 36, " ");
7384 else
7385 vty_out(vty, "%*s", len, " ");
d62a17ae 7386 }
7387 }
445c2480 7388 }
718e3744 7389
445c2480
DS
7390 /* MED/Metric */
7391 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
50e05855
AD
7392 if (json_paths) {
7393
7394 /*
7395 * Adding "metric" field to match with corresponding
7396 * CLI. "med" will be deprecated in future.
7397 */
a4d82a8a 7398 json_object_int_add(json_path, "med", attr->med);
50e05855
AD
7399 json_object_int_add(json_path, "metric", attr->med);
7400 } else
445c2480
DS
7401 vty_out(vty, "%10u", attr->med);
7402 else if (!json_paths)
7403 vty_out(vty, " ");
d62a17ae 7404
445c2480
DS
7405 /* Local Pref */
7406 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855
AD
7407 if (json_paths) {
7408
7409 /*
7410 * Adding "locPrf" field to match with corresponding
7411 * CLI. "localPref" will be deprecated in future.
7412 */
445c2480
DS
7413 json_object_int_add(json_path, "localpref",
7414 attr->local_pref);
50e05855
AD
7415 json_object_int_add(json_path, "locPrf",
7416 attr->local_pref);
7417 } else
445c2480
DS
7418 vty_out(vty, "%7u", attr->local_pref);
7419 else if (!json_paths)
7420 vty_out(vty, " ");
d62a17ae 7421
445c2480
DS
7422 if (json_paths)
7423 json_object_int_add(json_path, "weight", attr->weight);
7424 else
7425 vty_out(vty, "%7u ", attr->weight);
47fc97cc 7426
445c2480
DS
7427 if (json_paths) {
7428 char buf[BUFSIZ];
a4d82a8a
PZ
7429 json_object_string_add(
7430 json_path, "peerId",
9b6d8fcf 7431 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 7432 }
b05a1c8b 7433
445c2480
DS
7434 /* Print aspath */
7435 if (attr->aspath) {
50e05855
AD
7436 if (json_paths) {
7437
7438 /*
7439 * Adding "path" field to match with corresponding
7440 * CLI. "aspath" will be deprecated in future.
7441 */
445c2480
DS
7442 json_object_string_add(json_path, "aspath",
7443 attr->aspath->str);
50e05855
AD
7444 json_object_string_add(json_path, "path",
7445 attr->aspath->str);
7446 } else
445c2480 7447 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 7448 }
f1aa5d8a 7449
445c2480
DS
7450 /* Print origin */
7451 if (json_paths)
a4d82a8a
PZ
7452 json_object_string_add(json_path, "origin",
7453 bgp_origin_long_str[attr->origin]);
445c2480
DS
7454 else
7455 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7456
9df8b37c 7457 if (json_paths) {
6f214dd3
CS
7458 if (safi == SAFI_EVPN &&
7459 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7460 json_ext_community = json_object_new_object();
7461 json_object_string_add(json_ext_community,
7462 "string",
7463 attr->ecommunity->str);
7464 json_object_object_add(json_path,
7465 "extendedCommunity",
7466 json_ext_community);
7467 }
7468
9df8b37c
PZ
7469 if (nexthop_self)
7470 json_object_boolean_true_add(json_path,
7471 "announceNexthopSelf");
7472 if (nexthop_othervrf) {
7473 json_object_string_add(json_path, "nhVrfName",
7474 nexthop_vrfname);
7475
7476 json_object_int_add(json_path, "nhVrfId",
7477 ((nexthop_vrfid == VRF_UNKNOWN)
7478 ? -1
7479 : (int)nexthop_vrfid));
7480 }
7481 }
7482
d62a17ae 7483 if (json_paths) {
7484 if (json_nexthop_global || json_nexthop_ll) {
7485 json_nexthops = json_object_new_array();
f1aa5d8a 7486
d62a17ae 7487 if (json_nexthop_global)
7488 json_object_array_add(json_nexthops,
7489 json_nexthop_global);
f1aa5d8a 7490
d62a17ae 7491 if (json_nexthop_ll)
7492 json_object_array_add(json_nexthops,
7493 json_nexthop_ll);
f1aa5d8a 7494
d62a17ae 7495 json_object_object_add(json_path, "nexthops",
7496 json_nexthops);
7497 }
7498
7499 json_object_array_add(json_paths, json_path);
7500 } else {
7501 vty_out(vty, "\n");
6f214dd3
CS
7502
7503 if (safi == SAFI_EVPN &&
7504 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7505 vty_out(vty, "%*s", 20, " ");
7506 vty_out(vty, "%s\n", attr->ecommunity->str);
7507 }
7508
65efcfce 7509#if ENABLE_BGP_VNC
d62a17ae 7510 /* prints an additional line, indented, with VNC info, if
7511 * present */
7512 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 7513 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 7514#endif
d62a17ae 7515 }
7516}
718e3744 7517
7518/* called from terminal list command */
d62a17ae 7519void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr,
9f049418 7520 safi_t safi, bool use_json, json_object *json_ar)
d62a17ae 7521{
7522 json_object *json_status = NULL;
7523 json_object *json_net = NULL;
7524 char buff[BUFSIZ];
dc387b0f 7525
d62a17ae 7526 /* Route status display. */
7527 if (use_json) {
7528 json_status = json_object_new_object();
7529 json_net = json_object_new_object();
7530 } else {
7531 vty_out(vty, "*");
7532 vty_out(vty, ">");
7533 vty_out(vty, " ");
7534 }
718e3744 7535
d62a17ae 7536 /* print prefix and mask */
50e05855 7537 if (use_json) {
dc387b0f
LK
7538 if (safi == SAFI_EVPN)
7539 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
7540 else if (p->family == AF_INET || p->family == AF_INET6) {
7541 json_object_string_add(
7542 json_net, "addrPrefix",
7543 inet_ntop(p->family, &p->u.prefix, buff,
7544 BUFSIZ));
7545 json_object_int_add(json_net, "prefixLen",
7546 p->prefixlen);
7547 prefix2str(p, buff, PREFIX_STRLEN);
7548 json_object_string_add(json_net, "network", buff);
7549 }
50e05855 7550 } else
9c92b5f7 7551 route_vty_out_route(p, vty, NULL);
d62a17ae 7552
7553 /* Print attribute */
7554 if (attr) {
7555 if (use_json) {
7556 if (p->family == AF_INET
7557 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 7558 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 7559 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 7560 json_object_string_add(
7561 json_net, "nextHop",
7562 inet_ntoa(
7563 attr->mp_nexthop_global_in));
7564 else
7565 json_object_string_add(
7566 json_net, "nextHop",
7567 inet_ntoa(attr->nexthop));
7568 } else if (p->family == AF_INET6
7569 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
7570 char buf[BUFSIZ];
7571
7572 json_object_string_add(
aa0a10fc 7573 json_net, "nextHopGlobal",
d62a17ae 7574 inet_ntop(AF_INET6,
7575 &attr->mp_nexthop_global, buf,
7576 BUFSIZ));
dc387b0f
LK
7577 } else if (p->family == AF_EVPN &&
7578 !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
7579 json_object_string_add(json_net,
7580 "nextHop", inet_ntoa(
7581 attr->mp_nexthop_global_in));
d62a17ae 7582
7583 if (attr->flag
7584 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
7585 json_object_int_add(json_net, "metric",
7586 attr->med);
7587
50e05855
AD
7588 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
7589
7590 /*
7591 * Adding "locPrf" field to match with
7592 * corresponding CLI. "localPref" will be
7593 * deprecated in future.
7594 */
d62a17ae 7595 json_object_int_add(json_net, "localPref",
7596 attr->local_pref);
50e05855
AD
7597 json_object_int_add(json_net, "locPrf",
7598 attr->local_pref);
7599 }
d62a17ae 7600
7601 json_object_int_add(json_net, "weight", attr->weight);
7602
7603 /* Print aspath */
50e05855
AD
7604 if (attr->aspath) {
7605
7606 /*
7607 * Adding "path" field to match with
7608 * corresponding CLI. "localPref" will be
7609 * deprecated in future.
7610 */
d62a17ae 7611 json_object_string_add(json_net, "asPath",
7612 attr->aspath->str);
50e05855
AD
7613 json_object_string_add(json_net, "path",
7614 attr->aspath->str);
7615 }
d62a17ae 7616
7617 /* Print origin */
7618 json_object_string_add(json_net, "bgpOriginCode",
7619 bgp_origin_str[attr->origin]);
7620 } else {
7621 if (p->family == AF_INET
7622 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7623 || safi == SAFI_EVPN
7624 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7625 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7626 || safi == SAFI_EVPN)
7627 vty_out(vty, "%-16s",
7628 inet_ntoa(
7629 attr->mp_nexthop_global_in));
7630 else
7631 vty_out(vty, "%-16s",
7632 inet_ntoa(attr->nexthop));
7633 } else if (p->family == AF_INET6
7634 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
7635 int len;
7636 char buf[BUFSIZ];
7637
7638 len = vty_out(
7639 vty, "%s",
7640 inet_ntop(AF_INET6,
7641 &attr->mp_nexthop_global, buf,
7642 BUFSIZ));
7643 len = 16 - len;
7644 if (len < 1)
7645 vty_out(vty, "\n%*s", 36, " ");
7646 else
7647 vty_out(vty, "%*s", len, " ");
7648 }
7649 if (attr->flag
7650 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
7651 vty_out(vty, "%10u", attr->med);
7652 else
7653 vty_out(vty, " ");
718e3744 7654
d62a17ae 7655 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
7656 vty_out(vty, "%7u", attr->local_pref);
7657 else
7658 vty_out(vty, " ");
7659
7660 vty_out(vty, "%7u ", attr->weight);
7661
7662 /* Print aspath */
7663 if (attr->aspath)
7664 aspath_print_vty(vty, "%s", attr->aspath, " ");
7665
7666 /* Print origin */
7667 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7668 }
7669 }
7670 if (use_json) {
7671 json_object_boolean_true_add(json_status, "*");
7672 json_object_boolean_true_add(json_status, ">");
7673 json_object_object_add(json_net, "appliedStatusSymbols",
7674 json_status);
1608ff77 7675
dc387b0f
LK
7676 prefix2str(p, buff, PREFIX_STRLEN);
7677 json_object_object_add(json_ar, buff, json_net);
d62a17ae 7678 } else
7679 vty_out(vty, "\n");
7680}
7681
7682void route_vty_out_tag(struct vty *vty, struct prefix *p,
9b6d8fcf 7683 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 7684 json_object *json)
7685{
7686 json_object *json_out = NULL;
7687 struct attr *attr;
7688 mpls_label_t label = MPLS_INVALID_LABEL;
7689
9b6d8fcf 7690 if (!path->extra)
d62a17ae 7691 return;
7692
7693 if (json)
7694 json_out = json_object_new_object();
7695
7696 /* short status lead text */
9b6d8fcf 7697 route_vty_short_status_out(vty, path, json_out);
d62a17ae 7698
7699 /* print prefix and mask */
7700 if (json == NULL) {
7701 if (!display)
9c92b5f7 7702 route_vty_out_route(p, vty, NULL);
d62a17ae 7703 else
7704 vty_out(vty, "%*s", 17, " ");
7705 }
7706
7707 /* Print attribute */
9b6d8fcf 7708 attr = path->attr;
05864da7
DS
7709 if (((p->family == AF_INET)
7710 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
7711 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
7712 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7713 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7714 || safi == SAFI_EVPN) {
7715 if (json)
7716 json_object_string_add(
7717 json_out, "mpNexthopGlobalIn",
7718 inet_ntoa(attr->mp_nexthop_global_in));
7719 else
7720 vty_out(vty, "%-16s",
7721 inet_ntoa(attr->mp_nexthop_global_in));
7722 } else {
7723 if (json)
7724 json_object_string_add(
7725 json_out, "nexthop",
7726 inet_ntoa(attr->nexthop));
7727 else
7728 vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
7729 }
7730 } else if (((p->family == AF_INET6)
7731 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
7732 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
7733 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7734 char buf_a[512];
7735
7736 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
7737 if (json)
7738 json_object_string_add(
7739 json_out, "mpNexthopGlobalIn",
7740 inet_ntop(AF_INET6,
7741 &attr->mp_nexthop_global,
7742 buf_a, sizeof(buf_a)));
7743 else
7744 vty_out(vty, "%s",
7745 inet_ntop(AF_INET6,
7746 &attr->mp_nexthop_global,
7747 buf_a, sizeof(buf_a)));
7748 } else if (attr->mp_nexthop_len
7749 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
7750 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
7751 &attr->mp_nexthop_global,
7752 &attr->mp_nexthop_local);
7753 if (json)
7754 json_object_string_add(json_out,
7755 "mpNexthopGlobalLocal",
7756 buf_a);
7757 else
7758 vty_out(vty, "%s", buf_a);
d62a17ae 7759 }
7760 }
7761
9b6d8fcf 7762 label = decode_label(&path->extra->label[0]);
d62a17ae 7763
7764 if (bgp_is_valid_label(&label)) {
7765 if (json) {
7766 json_object_int_add(json_out, "notag", label);
7767 json_object_array_add(json, json_out);
7768 } else {
7769 vty_out(vty, "notag/%d", label);
7770 vty_out(vty, "\n");
7771 }
7772 }
7773}
718e3744 7774
d62a17ae 7775void route_vty_out_overlay(struct vty *vty, struct prefix *p,
9b6d8fcf 7776 struct bgp_path_info *path, int display,
d62a17ae 7777 json_object *json_paths)
718e3744 7778{
d62a17ae 7779 struct attr *attr;
14f51eba 7780 char buf[BUFSIZ] = {0};
d62a17ae 7781 json_object *json_path = NULL;
14f51eba
LK
7782 json_object *json_nexthop = NULL;
7783 json_object *json_overlay = NULL;
856ca177 7784
9b6d8fcf 7785 if (!path->extra)
d62a17ae 7786 return;
718e3744 7787
14f51eba
LK
7788 if (json_paths) {
7789 json_path = json_object_new_object();
7790 json_overlay = json_object_new_object();
7791 json_nexthop = json_object_new_object();
7792 }
7793
d62a17ae 7794 /* short status lead text */
9b6d8fcf 7795 route_vty_short_status_out(vty, path, json_path);
856ca177 7796
d62a17ae 7797 /* print prefix and mask */
7798 if (!display)
14f51eba 7799 route_vty_out_route(p, vty, json_path);
d62a17ae 7800 else
7801 vty_out(vty, "%*s", 17, " ");
7802
7803 /* Print attribute */
9b6d8fcf 7804 attr = path->attr;
05864da7
DS
7805 char buf1[BUFSIZ];
7806 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 7807
05864da7
DS
7808 switch (af) {
7809 case AF_INET:
7810 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
7811 if (!json_path) {
7812 vty_out(vty, "%-16s", buf);
7813 } else {
7814 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 7815
05864da7 7816 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 7817
05864da7
DS
7818 json_object_object_add(json_path, "nexthop",
7819 json_nexthop);
7820 }
7821 break;
7822 case AF_INET6:
7823 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
7824 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
7825 if (!json_path) {
7826 vty_out(vty, "%s(%s)", buf, buf1);
7827 } else {
7828 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 7829
05864da7
DS
7830 json_object_string_add(json_nexthop, "ipv6LinkLocal",
7831 buf1);
14f51eba 7832
05864da7 7833 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 7834
05864da7
DS
7835 json_object_object_add(json_path, "nexthop",
7836 json_nexthop);
7837 }
7838 break;
7839 default:
7840 if (!json_path) {
7841 vty_out(vty, "?");
7842 } else {
7843 json_object_string_add(json_nexthop, "Error",
7844 "Unsupported address-family");
d62a17ae 7845 }
05864da7 7846 }
988258b4 7847
05864da7 7848 char *str = esi2str(&(attr->evpn_overlay.eth_s_id));
988258b4 7849
05864da7
DS
7850 if (!json_path)
7851 vty_out(vty, "%s", str);
7852 else
7853 json_object_string_add(json_overlay, "esi", str);
25b5da8d 7854
05864da7 7855 XFREE(MTYPE_TMP, str);
988258b4 7856
05864da7
DS
7857 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
7858 inet_ntop(AF_INET, &(attr->evpn_overlay.gw_ip.ipv4), buf,
7859 BUFSIZ);
7860 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
7861 inet_ntop(AF_INET6, &(attr->evpn_overlay.gw_ip.ipv6), buf,
7862 BUFSIZ);
7863 }
14f51eba 7864
05864da7
DS
7865 if (!json_path)
7866 vty_out(vty, "/%s", buf);
7867 else
7868 json_object_string_add(json_overlay, "gw", buf);
7869
7870 if (attr->ecommunity) {
7871 char *mac = NULL;
7872 struct ecommunity_val *routermac = ecommunity_lookup(
7873 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
7874 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
7875
7876 if (routermac)
7877 mac = ecom_mac2str((char *)routermac->val);
7878 if (mac) {
7879 if (!json_path) {
7880 vty_out(vty, "/%s", (char *)mac);
7881 } else {
7882 json_object_string_add(json_overlay, "rmac",
7883 mac);
988258b4 7884 }
05864da7 7885 XFREE(MTYPE_TMP, mac);
988258b4 7886 }
05864da7 7887 }
718e3744 7888
05864da7
DS
7889 if (!json_path) {
7890 vty_out(vty, "\n");
7891 } else {
7892 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 7893
05864da7 7894 json_object_array_add(json_paths, json_path);
14f51eba 7895 }
d62a17ae 7896}
718e3744 7897
d62a17ae 7898/* dampening route */
7899static void damp_route_vty_out(struct vty *vty, struct prefix *p,
a935f597 7900 struct bgp_path_info *path, int display, afi_t afi,
4b7e6066 7901 safi_t safi, bool use_json, json_object *json)
d62a17ae 7902{
7903 struct attr *attr;
7904 int len;
7905 char timebuf[BGP_UPTIME_LEN];
7906
7907 /* short status lead text */
9b6d8fcf 7908 route_vty_short_status_out(vty, path, json);
d62a17ae 7909
7910 /* print prefix and mask */
7911 if (!use_json) {
7912 if (!display)
9c92b5f7 7913 route_vty_out_route(p, vty, NULL);
d62a17ae 7914 else
7915 vty_out(vty, "%*s", 17, " ");
7916 }
7917
9b6d8fcf 7918 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 7919 len = 17 - len;
7920 if (len < 1) {
7921 if (!use_json)
7922 vty_out(vty, "\n%*s", 34, " ");
7923 } else {
7924 if (use_json)
7925 json_object_int_add(json, "peerHost", len);
7926 else
7927 vty_out(vty, "%*s", len, " ");
7928 }
7929
7930 if (use_json)
a935f597
DA
7931 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
7932 safi, use_json, json);
d62a17ae 7933 else
9b6d8fcf
DS
7934 vty_out(vty, "%s ",
7935 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
7936 BGP_UPTIME_LEN, afi, safi,
7937 use_json, json));
d62a17ae 7938
7939 /* Print attribute */
9b6d8fcf 7940 attr = path->attr;
d62a17ae 7941
05864da7
DS
7942 /* Print aspath */
7943 if (attr->aspath) {
d62a17ae 7944 if (use_json)
05864da7
DS
7945 json_object_string_add(json, "asPath",
7946 attr->aspath->str);
d62a17ae 7947 else
05864da7 7948 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 7949 }
05864da7
DS
7950
7951 /* Print origin */
7952 if (use_json)
7953 json_object_string_add(json, "origin",
7954 bgp_origin_str[attr->origin]);
7955 else
7956 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7957
d62a17ae 7958 if (!use_json)
7959 vty_out(vty, "\n");
7960}
718e3744 7961
d62a17ae 7962/* flap route */
7963static void flap_route_vty_out(struct vty *vty, struct prefix *p,
a935f597 7964 struct bgp_path_info *path, int display, afi_t afi,
4b7e6066 7965 safi_t safi, bool use_json, json_object *json)
784d3a42 7966{
d62a17ae 7967 struct attr *attr;
7968 struct bgp_damp_info *bdi;
7969 char timebuf[BGP_UPTIME_LEN];
7970 int len;
784d3a42 7971
9b6d8fcf 7972 if (!path->extra)
d62a17ae 7973 return;
784d3a42 7974
9b6d8fcf 7975 bdi = path->extra->damp_info;
784d3a42 7976
d62a17ae 7977 /* short status lead text */
9b6d8fcf 7978 route_vty_short_status_out(vty, path, json);
784d3a42 7979
d62a17ae 7980 /* print prefix and mask */
7981 if (!use_json) {
7982 if (!display)
9c92b5f7 7983 route_vty_out_route(p, vty, NULL);
d62a17ae 7984 else
7985 vty_out(vty, "%*s", 17, " ");
7986 }
784d3a42 7987
9b6d8fcf 7988 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 7989 len = 16 - len;
7990 if (len < 1) {
7991 if (!use_json)
7992 vty_out(vty, "\n%*s", 33, " ");
7993 } else {
7994 if (use_json)
7995 json_object_int_add(json, "peerHost", len);
7996 else
7997 vty_out(vty, "%*s", len, " ");
7998 }
784d3a42 7999
d62a17ae 8000 len = vty_out(vty, "%d", bdi->flap);
8001 len = 5 - len;
8002 if (len < 1) {
8003 if (!use_json)
8004 vty_out(vty, " ");
8005 } else {
8006 if (use_json)
8007 json_object_int_add(json, "bdiFlap", len);
8008 else
8009 vty_out(vty, "%*s", len, " ");
8010 }
8011
8012 if (use_json)
8013 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
8014 json);
8015 else
996c9314
LB
8016 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
8017 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 8018
9b6d8fcf
DS
8019 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
8020 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 8021 if (use_json)
9b6d8fcf 8022 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8023 BGP_UPTIME_LEN, afi, safi,
8024 use_json, json);
d62a17ae 8025 else
8026 vty_out(vty, "%s ",
9b6d8fcf 8027 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8028 BGP_UPTIME_LEN, afi,
8029 safi, use_json, json));
d62a17ae 8030 } else {
8031 if (!use_json)
8032 vty_out(vty, "%*s ", 8, " ");
8033 }
8034
8035 /* Print attribute */
9b6d8fcf 8036 attr = path->attr;
d62a17ae 8037
05864da7
DS
8038 /* Print aspath */
8039 if (attr->aspath) {
d62a17ae 8040 if (use_json)
05864da7
DS
8041 json_object_string_add(json, "asPath",
8042 attr->aspath->str);
d62a17ae 8043 else
05864da7 8044 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8045 }
05864da7
DS
8046
8047 /* Print origin */
8048 if (use_json)
8049 json_object_string_add(json, "origin",
8050 bgp_origin_str[attr->origin]);
8051 else
8052 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8053
d62a17ae 8054 if (!use_json)
8055 vty_out(vty, "\n");
8056}
8057
8058static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
8059 int *first, const char *header,
8060 json_object *json_adv_to)
8061{
8062 char buf1[INET6_ADDRSTRLEN];
8063 json_object *json_peer = NULL;
8064
8065 if (json_adv_to) {
8066 /* 'advertised-to' is a dictionary of peers we have advertised
8067 * this
8068 * prefix too. The key is the peer's IP or swpX, the value is
8069 * the
8070 * hostname if we know it and "" if not.
8071 */
8072 json_peer = json_object_new_object();
8073
8074 if (peer->hostname)
8075 json_object_string_add(json_peer, "hostname",
8076 peer->hostname);
8077
8078 if (peer->conf_if)
8079 json_object_object_add(json_adv_to, peer->conf_if,
8080 json_peer);
8081 else
8082 json_object_object_add(
8083 json_adv_to,
8084 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
8085 json_peer);
8086 } else {
8087 if (*first) {
8088 vty_out(vty, "%s", header);
8089 *first = 0;
8090 }
8091
8092 if (peer->hostname
8093 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
8094 if (peer->conf_if)
8095 vty_out(vty, " %s(%s)", peer->hostname,
8096 peer->conf_if);
8097 else
8098 vty_out(vty, " %s(%s)", peer->hostname,
8099 sockunion2str(&peer->su, buf1,
8100 SU_ADDRSTRLEN));
8101 } else {
8102 if (peer->conf_if)
8103 vty_out(vty, " %s", peer->conf_if);
8104 else
8105 vty_out(vty, " %s",
8106 sockunion2str(&peer->su, buf1,
8107 SU_ADDRSTRLEN));
8108 }
8109 }
784d3a42
PG
8110}
8111
dcc68b5e
MS
8112static void route_vty_out_tx_ids(struct vty *vty,
8113 struct bgp_addpath_info_data *d)
8114{
8115 int i;
8116
8117 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
8118 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
8119 d->addpath_tx_id[i],
8120 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
8121 }
8122}
8123
0dc8ee70
DS
8124static const char *bgp_path_selection_reason2str(
8125 enum bgp_path_selection_reason reason)
8126{
8127 switch (reason) {
8128 case bgp_path_selection_none:
8129 return "Nothing to Select";
8130 break;
8131 case bgp_path_selection_first:
8132 return "First path received";
8133 break;
8134 case bgp_path_selection_evpn_sticky_mac:
8135 return "EVPN Sticky Mac";
8136 break;
8137 case bgp_path_selection_evpn_seq:
8138 return "EVPN sequence number";
8139 break;
8140 case bgp_path_selection_evpn_lower_ip:
8141 return "EVPN lower IP";
8142 break;
8143 case bgp_path_selection_weight:
8144 return "Weight";
8145 break;
8146 case bgp_path_selection_local_pref:
8147 return "Local Pref";
8148 break;
8149 case bgp_path_selection_local_route:
8150 return "Local Route";
8151 break;
8152 case bgp_path_selection_confed_as_path:
8153 return "Confederation based AS Path";
8154 break;
8155 case bgp_path_selection_as_path:
8156 return "AS Path";
8157 break;
8158 case bgp_path_selection_origin:
8159 return "Origin";
8160 break;
8161 case bgp_path_selection_med:
8162 return "MED";
8163 break;
8164 case bgp_path_selection_peer:
8165 return "Peer Type";
8166 break;
8167 case bgp_path_selection_confed:
8168 return "Confed Peer Type";
8169 break;
8170 case bgp_path_selection_igp_metric:
8171 return "IGP Metric";
8172 break;
8173 case bgp_path_selection_older:
8174 return "Older Path";
8175 break;
8176 case bgp_path_selection_router_id:
8177 return "Router ID";
8178 break;
8179 case bgp_path_selection_cluster_length:
8180 return "Cluser length";
8181 break;
8182 case bgp_path_selection_stale:
8183 return "Path Staleness";
8184 break;
8185 case bgp_path_selection_local_configured:
8186 return "Locally configured route";
8187 break;
8188 case bgp_path_selection_neighbor_ip:
8189 return "Neighbor IP";
8190 break;
8191 case bgp_path_selection_default:
8192 return "Nothing left to compare";
8193 break;
8194 }
a74879b2 8195 return "Invalid (internal error)";
0dc8ee70
DS
8196}
8197
f08b5ca0
DS
8198void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
8199 struct bgp_node *bn, struct bgp_path_info *path,
8200 afi_t afi, safi_t safi, json_object *json_paths)
d62a17ae 8201{
8202 char buf[INET6_ADDRSTRLEN];
8203 char buf1[BUFSIZ];
d62a17ae 8204 char buf2[EVPN_ROUTE_STRLEN];
d62a17ae 8205 struct attr *attr;
8206 int sockunion_vty_out(struct vty *, union sockunion *);
8207 time_t tbuf;
8208 json_object *json_bestpath = NULL;
8209 json_object *json_cluster_list = NULL;
8210 json_object *json_cluster_list_list = NULL;
8211 json_object *json_ext_community = NULL;
8212 json_object *json_last_update = NULL;
7fd077aa 8213 json_object *json_pmsi = NULL;
d62a17ae 8214 json_object *json_nexthop_global = NULL;
8215 json_object *json_nexthop_ll = NULL;
8216 json_object *json_nexthops = NULL;
8217 json_object *json_path = NULL;
8218 json_object *json_peer = NULL;
8219 json_object *json_string = NULL;
8220 json_object *json_adv_to = NULL;
8221 int first = 0;
8222 struct listnode *node, *nnode;
8223 struct peer *peer;
8224 int addpath_capable;
8225 int has_adj;
8226 unsigned int first_as;
1defdda8 8227 bool nexthop_self =
9b6d8fcf 8228 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 8229 int i;
25b5da8d 8230 char *nexthop_fqdn = bgp_nexthop_fqdn(path->peer);
d62a17ae 8231
8232 if (json_paths) {
8233 json_path = json_object_new_object();
8234 json_peer = json_object_new_object();
8235 json_nexthop_global = json_object_new_object();
8236 }
8237
44c69747 8238 if (path->extra) {
b57ba6d2 8239 char tag_buf[30];
d62a17ae 8240
d7325ee7 8241 buf2[0] = '\0';
d62a17ae 8242 tag_buf[0] = '\0';
9b6d8fcf
DS
8243 if (path->extra && path->extra->num_labels) {
8244 bgp_evpn_label2str(path->extra->label,
8245 path->extra->num_labels, tag_buf,
a4d82a8a 8246 sizeof(tag_buf));
d62a17ae 8247 }
d7325ee7 8248 if (safi == SAFI_EVPN) {
44c69747
LK
8249 if (!json_paths) {
8250 bgp_evpn_route2str((struct prefix_evpn *)&bn->p,
8251 buf2, sizeof(buf2));
8252 vty_out(vty, " Route %s", buf2);
8253 if (tag_buf[0] != '\0')
8254 vty_out(vty, " VNI %s", tag_buf);
8255 vty_out(vty, "\n");
8256 } else {
8257 if (tag_buf[0])
8258 json_object_string_add(json_path, "VNI",
8259 tag_buf);
8260 }
d7325ee7
DD
8261 }
8262
44c69747 8263 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 8264 struct bgp_path_info *parent_ri;
d62a17ae 8265 struct bgp_node *rn, *prn;
8266
9b6d8fcf 8267 parent_ri = (struct bgp_path_info *)path->extra->parent;
d62a17ae 8268 rn = parent_ri->net;
8269 if (rn && rn->prn) {
8270 prn = rn->prn;
d7325ee7
DD
8271 prefix_rd2str((struct prefix_rd *)&prn->p,
8272 buf1, sizeof(buf1));
8273 if (is_pi_family_evpn(parent_ri)) {
8274 bgp_evpn_route2str((struct prefix_evpn *)&rn->p,
8275 buf2, sizeof(buf2));
8276 vty_out(vty, " Imported from %s:%s, VNI %s\n", buf1, buf2, tag_buf);
8277 } else
8278 vty_out(vty, " Imported from %s:%s\n", buf1, buf2);
d62a17ae 8279 }
8280 }
8281 }
d62a17ae 8282
9b6d8fcf 8283 attr = path->attr;
d62a17ae 8284
05864da7
DS
8285 /* Line1 display AS-path, Aggregator */
8286 if (attr->aspath) {
8287 if (json_paths) {
8288 if (!attr->aspath->json)
8289 aspath_str_update(attr->aspath, true);
8290 json_object_lock(attr->aspath->json);
8291 json_object_object_add(json_path, "aspath",
8292 attr->aspath->json);
8293 } else {
8294 if (attr->aspath->segments)
8295 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 8296 else
05864da7 8297 vty_out(vty, " Local");
d62a17ae 8298 }
05864da7 8299 }
d62a17ae 8300
05864da7
DS
8301 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
8302 if (json_paths)
8303 json_object_boolean_true_add(json_path, "removed");
8304 else
8305 vty_out(vty, ", (removed)");
8306 }
d62a17ae 8307
05864da7
DS
8308 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
8309 if (json_paths)
8310 json_object_boolean_true_add(json_path, "stale");
8311 else
8312 vty_out(vty, ", (stale)");
8313 }
d62a17ae 8314
05864da7
DS
8315 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
8316 if (json_paths) {
8317 json_object_int_add(json_path, "aggregatorAs",
8318 attr->aggregator_as);
8319 json_object_string_add(
8320 json_path, "aggregatorId",
8321 inet_ntoa(attr->aggregator_addr));
8322 } else {
8323 vty_out(vty, ", (aggregated by %u %s)",
8324 attr->aggregator_as,
8325 inet_ntoa(attr->aggregator_addr));
d62a17ae 8326 }
05864da7 8327 }
d62a17ae 8328
05864da7
DS
8329 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
8330 PEER_FLAG_REFLECTOR_CLIENT)) {
8331 if (json_paths)
8332 json_object_boolean_true_add(json_path,
8333 "rxedFromRrClient");
8334 else
8335 vty_out(vty, ", (Received from a RR-client)");
8336 }
d62a17ae 8337
05864da7
DS
8338 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
8339 PEER_FLAG_RSERVER_CLIENT)) {
8340 if (json_paths)
8341 json_object_boolean_true_add(json_path,
8342 "rxedFromRsClient");
8343 else
8344 vty_out(vty, ", (Received from a RS-client)");
8345 }
d62a17ae 8346
05864da7
DS
8347 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
8348 if (json_paths)
8349 json_object_boolean_true_add(json_path,
8350 "dampeningHistoryEntry");
8351 else
8352 vty_out(vty, ", (history entry)");
8353 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
8354 if (json_paths)
8355 json_object_boolean_true_add(json_path,
8356 "dampeningSuppressed");
8357 else
8358 vty_out(vty, ", (suppressed due to dampening)");
8359 }
d62a17ae 8360
05864da7
DS
8361 if (!json_paths)
8362 vty_out(vty, "\n");
d62a17ae 8363
05864da7
DS
8364 /* Line2 display Next-hop, Neighbor, Router-id */
8365 /* Display the nexthop */
8366 if ((bn->p.family == AF_INET || bn->p.family == AF_ETHERNET
8367 || bn->p.family == AF_EVPN)
8368 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
8369 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8370 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8371 || safi == SAFI_EVPN) {
d62a17ae 8372 if (json_paths)
d62a17ae 8373 json_object_string_add(
25b5da8d
DA
8374 json_nexthop_global,
8375 nexthop_fqdn ? "fqdn" : "ip",
8376 nexthop_fqdn
8377 ? nexthop_fqdn
05864da7
DS
8378 : inet_ntoa(
8379 attr->mp_nexthop_global_in));
8380 else
d62a17ae 8381 vty_out(vty, " %s",
25b5da8d
DA
8382 nexthop_fqdn
8383 ? nexthop_fqdn
05864da7
DS
8384 : inet_ntoa(
8385 attr->mp_nexthop_global_in));
d62a17ae 8386 } else {
d62a17ae 8387 if (json_paths)
05864da7
DS
8388 json_object_string_add(
8389 json_nexthop_global,
8390 nexthop_fqdn ? "fqdn" : "ip",
8391 nexthop_fqdn
8392 ? nexthop_fqdn
8393 : inet_ntoa(attr->nexthop));
d62a17ae 8394 else
05864da7
DS
8395 vty_out(vty, " %s",
8396 nexthop_fqdn
8397 ? nexthop_fqdn
8398 : inet_ntoa(attr->nexthop));
d62a17ae 8399 }
8400
05864da7
DS
8401 if (json_paths)
8402 json_object_string_add(json_nexthop_global, "afi",
8403 "ipv4");
8404 } else {
8405 if (json_paths) {
8406 json_object_string_add(
8407 json_nexthop_global,
8408 nexthop_fqdn ? "fqdn" : "ip",
8409 nexthop_fqdn
8410 ? nexthop_fqdn
8411 : inet_ntop(AF_INET6,
8412 &attr->mp_nexthop_global,
8413 buf, INET6_ADDRSTRLEN));
8414 json_object_string_add(json_nexthop_global, "afi",
8415 "ipv6");
8416 json_object_string_add(json_nexthop_global, "scope",
8417 "global");
8418 } else {
8419 vty_out(vty, " %s",
8420 nexthop_fqdn
8421 ? nexthop_fqdn
8422 : inet_ntop(AF_INET6,
8423 &attr->mp_nexthop_global,
8424 buf, INET6_ADDRSTRLEN));
d62a17ae 8425 }
05864da7 8426 }
d62a17ae 8427
05864da7
DS
8428 /* Display the IGP cost or 'inaccessible' */
8429 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
8430 if (json_paths)
8431 json_object_boolean_false_add(json_nexthop_global,
8432 "accessible");
8433 else
8434 vty_out(vty, " (inaccessible)");
8435 } else {
8436 if (path->extra && path->extra->igpmetric) {
d62a17ae 8437 if (json_paths)
05864da7
DS
8438 json_object_int_add(json_nexthop_global,
8439 "metric",
8440 path->extra->igpmetric);
d62a17ae 8441 else
05864da7
DS
8442 vty_out(vty, " (metric %u)",
8443 path->extra->igpmetric);
d62a17ae 8444 }
8445
05864da7 8446 /* IGP cost is 0, display this only for json */
d62a17ae 8447 else {
d62a17ae 8448 if (json_paths)
05864da7
DS
8449 json_object_int_add(json_nexthop_global,
8450 "metric", 0);
d62a17ae 8451 }
d62a17ae 8452
05864da7
DS
8453 if (json_paths)
8454 json_object_boolean_true_add(json_nexthop_global,
8455 "accessible");
8456 }
d62a17ae 8457
05864da7
DS
8458 /* Display peer "from" output */
8459 /* This path was originated locally */
8460 if (path->peer == bgp->peer_self) {
d62a17ae 8461
05864da7
DS
8462 if (safi == SAFI_EVPN
8463 || (bn->p.family == AF_INET
8464 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 8465 if (json_paths)
05864da7
DS
8466 json_object_string_add(json_peer, "peerId",
8467 "0.0.0.0");
d62a17ae 8468 else
05864da7
DS
8469 vty_out(vty, " from 0.0.0.0 ");
8470 } else {
d62a17ae 8471 if (json_paths)
05864da7
DS
8472 json_object_string_add(json_peer, "peerId",
8473 "::");
d62a17ae 8474 else
05864da7 8475 vty_out(vty, " from :: ");
d62a17ae 8476 }
d62a17ae 8477
05864da7
DS
8478 if (json_paths)
8479 json_object_string_add(json_peer, "routerId",
8480 inet_ntoa(bgp->router_id));
8481 else
8482 vty_out(vty, "(%s)", inet_ntoa(bgp->router_id));
8483 }
d62a17ae 8484
05864da7
DS
8485 /* We RXed this path from one of our peers */
8486 else {
8487
8488 if (json_paths) {
8489 json_object_string_add(json_peer, "peerId",
8490 sockunion2str(&path->peer->su,
8491 buf,
8492 SU_ADDRSTRLEN));
8493 json_object_string_add(json_peer, "routerId",
8494 inet_ntop(AF_INET,
8495 &path->peer->remote_id,
8496 buf1, sizeof(buf1)));
8497
8498 if (path->peer->hostname)
8499 json_object_string_add(json_peer, "hostname",
8500 path->peer->hostname);
8501
8502 if (path->peer->domainname)
8503 json_object_string_add(json_peer, "domainname",
8504 path->peer->domainname);
8505
8506 if (path->peer->conf_if)
8507 json_object_string_add(json_peer, "interface",
8508 path->peer->conf_if);
8509 } else {
8510 if (path->peer->conf_if) {
8511 if (path->peer->hostname
8512 && bgp_flag_check(path->peer->bgp,
8513 BGP_FLAG_SHOW_HOSTNAME))
8514 vty_out(vty, " from %s(%s)",
8515 path->peer->hostname,
8516 path->peer->conf_if);
d62a17ae 8517 else
05864da7 8518 vty_out(vty, " from %s",
9b6d8fcf 8519 path->peer->conf_if);
d62a17ae 8520 } else {
05864da7
DS
8521 if (path->peer->hostname
8522 && bgp_flag_check(path->peer->bgp,
8523 BGP_FLAG_SHOW_HOSTNAME))
8524 vty_out(vty, " from %s(%s)",
8525 path->peer->hostname,
8526 path->peer->host);
d62a17ae 8527 else
05864da7
DS
8528 vty_out(vty, " from %s",
8529 sockunion2str(&path->peer->su,
8530 buf,
8531 SU_ADDRSTRLEN));
d62a17ae 8532 }
d62a17ae 8533
05864da7
DS
8534 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
8535 vty_out(vty, " (%s)",
8536 inet_ntoa(attr->originator_id));
8537 else
8538 vty_out(vty, " (%s)",
8539 inet_ntop(AF_INET,
8540 &path->peer->remote_id, buf1,
8541 sizeof(buf1)));
d62a17ae 8542 }
05864da7 8543 }
9df8b37c 8544
05864da7
DS
8545 /*
8546 * Note when vrfid of nexthop is different from that of prefix
8547 */
8548 if (path->extra && path->extra->bgp_orig) {
8549 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8550
05864da7
DS
8551 if (json_paths) {
8552 const char *vn;
9df8b37c 8553
05864da7
DS
8554 if (path->extra->bgp_orig->inst_type
8555 == BGP_INSTANCE_TYPE_DEFAULT)
8556 vn = VRF_DEFAULT_NAME;
8557 else
8558 vn = path->extra->bgp_orig->name;
9df8b37c 8559
05864da7 8560 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 8561
05864da7
DS
8562 if (nexthop_vrfid == VRF_UNKNOWN) {
8563 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 8564 } else {
05864da7
DS
8565 json_object_int_add(json_path, "nhVrfId",
8566 (int)nexthop_vrfid);
9df8b37c 8567 }
05864da7
DS
8568 } else {
8569 if (nexthop_vrfid == VRF_UNKNOWN)
8570 vty_out(vty, " vrf ?");
d62a17ae 8571 else
05864da7 8572 vty_out(vty, " vrf %u", nexthop_vrfid);
9df8b37c 8573 }
05864da7 8574 }
9df8b37c 8575
05864da7
DS
8576 if (nexthop_self) {
8577 if (json_paths) {
8578 json_object_boolean_true_add(json_path,
8579 "announceNexthopSelf");
8580 } else {
8581 vty_out(vty, " announce-nh-self");
9df8b37c 8582 }
05864da7 8583 }
9df8b37c 8584
05864da7
DS
8585 if (!json_paths)
8586 vty_out(vty, "\n");
d62a17ae 8587
05864da7
DS
8588 /* display the link-local nexthop */
8589 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
8590 if (json_paths) {
8591 json_nexthop_ll = json_object_new_object();
8592 json_object_string_add(
8593 json_nexthop_ll, nexthop_fqdn ? "fqdn" : "ip",
8594 nexthop_fqdn
8595 ? nexthop_fqdn
8596 : inet_ntop(AF_INET6,
8597 &attr->mp_nexthop_local,
8598 buf, INET6_ADDRSTRLEN));
8599 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
8600 json_object_string_add(json_nexthop_ll, "scope",
8601 "link-local");
d62a17ae 8602
05864da7
DS
8603 json_object_boolean_true_add(json_nexthop_ll,
8604 "accessible");
d62a17ae 8605
05864da7 8606 if (!attr->mp_nexthop_prefer_global)
d62a17ae 8607 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
8608 "used");
8609 else
8610 json_object_boolean_true_add(
8611 json_nexthop_global, "used");
8612 } else {
8613 vty_out(vty, " (%s) %s\n",
8614 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
8615 buf, INET6_ADDRSTRLEN),
8616 attr->mp_nexthop_prefer_global
8617 ? "(prefer-global)"
8618 : "(used)");
d62a17ae 8619 }
05864da7
DS
8620 }
8621 /* If we do not have a link-local nexthop then we must flag the
8622 global as "used" */
8623 else {
8624 if (json_paths)
8625 json_object_boolean_true_add(json_nexthop_global,
8626 "used");
8627 }
d62a17ae 8628
05864da7
DS
8629 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8630 * Int/Ext/Local, Atomic, best */
8631 if (json_paths)
8632 json_object_string_add(json_path, "origin",
8633 bgp_origin_long_str[attr->origin]);
8634 else
8635 vty_out(vty, " Origin %s",
8636 bgp_origin_long_str[attr->origin]);
9df8b37c 8637
05864da7
DS
8638 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
8639 if (json_paths) {
8640 /*
8641 * Adding "metric" field to match with
8642 * corresponding CLI. "med" will be
8643 * deprecated in future.
8644 */
8645 json_object_int_add(json_path, "med", attr->med);
8646 json_object_int_add(json_path, "metric", attr->med);
8647 } else
8648 vty_out(vty, ", metric %u", attr->med);
8649 }
9df8b37c 8650
05864da7
DS
8651 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
8652 if (json_paths)
8653 json_object_int_add(json_path, "localpref",
8654 attr->local_pref);
8655 else
8656 vty_out(vty, ", localpref %u", attr->local_pref);
8657 }
9df8b37c 8658
05864da7
DS
8659 if (attr->weight != 0) {
8660 if (json_paths)
8661 json_object_int_add(json_path, "weight", attr->weight);
8662 else
8663 vty_out(vty, ", weight %u", attr->weight);
8664 }
9df8b37c 8665
05864da7
DS
8666 if (attr->tag != 0) {
8667 if (json_paths)
8668 json_object_int_add(json_path, "tag", attr->tag);
8669 else
8670 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
8671 }
9df8b37c 8672
05864da7
DS
8673 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
8674 if (json_paths)
8675 json_object_boolean_false_add(json_path, "valid");
8676 else
8677 vty_out(vty, ", invalid");
8678 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
8679 if (json_paths)
8680 json_object_boolean_true_add(json_path, "valid");
8681 else
8682 vty_out(vty, ", valid");
8683 }
9df8b37c 8684
05864da7
DS
8685 if (path->peer != bgp->peer_self) {
8686 if (path->peer->as == path->peer->local_as) {
8687 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
8688 if (json_paths)
8689 json_object_string_add(
8690 json_peer, "type",
8691 "confed-internal");
d62a17ae 8692 else
05864da7 8693 vty_out(vty, ", confed-internal");
d62a17ae 8694 } else {
05864da7
DS
8695 if (json_paths)
8696 json_object_string_add(
8697 json_peer, "type", "internal");
8698 else
8699 vty_out(vty, ", internal");
9df8b37c 8700 }
05864da7
DS
8701 } else {
8702 if (bgp_confederation_peers_check(bgp,
8703 path->peer->as)) {
8704 if (json_paths)
8705 json_object_string_add(
8706 json_peer, "type",
8707 "confed-external");
d62a17ae 8708 else
05864da7 8709 vty_out(vty, ", confed-external");
d62a17ae 8710 } else {
05864da7
DS
8711 if (json_paths)
8712 json_object_string_add(
8713 json_peer, "type", "external");
8714 else
8715 vty_out(vty, ", external");
d62a17ae 8716 }
8717 }
05864da7
DS
8718 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
8719 if (json_paths) {
8720 json_object_boolean_true_add(json_path, "aggregated");
8721 json_object_boolean_true_add(json_path, "local");
8722 } else {
8723 vty_out(vty, ", aggregated, local");
8724 }
8725 } else if (path->type != ZEBRA_ROUTE_BGP) {
8726 if (json_paths)
8727 json_object_boolean_true_add(json_path, "sourced");
8728 else
8729 vty_out(vty, ", sourced");
8730 } else {
8731 if (json_paths) {
8732 json_object_boolean_true_add(json_path, "sourced");
8733 json_object_boolean_true_add(json_path, "local");
8734 } else {
8735 vty_out(vty, ", sourced, local");
d62a17ae 8736 }
05864da7 8737 }
718e3744 8738
05864da7 8739 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 8740 if (json_paths)
05864da7
DS
8741 json_object_boolean_true_add(json_path,
8742 "atomicAggregate");
d62a17ae 8743 else
05864da7
DS
8744 vty_out(vty, ", atomic-aggregate");
8745 }
d62a17ae 8746
05864da7
DS
8747 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
8748 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
8749 && bgp_path_info_mpath_count(path))) {
8750 if (json_paths)
8751 json_object_boolean_true_add(json_path, "multipath");
8752 else
8753 vty_out(vty, ", multipath");
8754 }
50e05855 8755
05864da7
DS
8756 // Mark the bestpath(s)
8757 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
8758 first_as = aspath_get_first_as(attr->aspath);
718e3744 8759
05864da7
DS
8760 if (json_paths) {
8761 if (!json_bestpath)
8762 json_bestpath = json_object_new_object();
8763 json_object_int_add(json_bestpath, "bestpathFromAs",
8764 first_as);
8765 } else {
8766 if (first_as)
8767 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 8768 else
05864da7 8769 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 8770 }
05864da7 8771 }
718e3744 8772
05864da7
DS
8773 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
8774 if (json_paths) {
8775 if (!json_bestpath)
8776 json_bestpath = json_object_new_object();
8777 json_object_boolean_true_add(json_bestpath, "overall");
8778 json_object_string_add(
8779 json_bestpath, "selectionReason",
8780 bgp_path_selection_reason2str(bn->reason));
8781 } else {
8782 vty_out(vty, ", best");
8783 vty_out(vty, " (%s)",
8784 bgp_path_selection_reason2str(bn->reason));
d62a17ae 8785 }
05864da7 8786 }
718e3744 8787
05864da7
DS
8788 if (json_bestpath)
8789 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 8790
05864da7
DS
8791 if (!json_paths)
8792 vty_out(vty, "\n");
8793
8794 /* Line 4 display Community */
8795 if (attr->community) {
8796 if (json_paths) {
8797 if (!attr->community->json)
8798 community_str(attr->community, true);
8799 json_object_lock(attr->community->json);
8800 json_object_object_add(json_path, "community",
8801 attr->community->json);
8802 } else {
8803 vty_out(vty, " Community: %s\n",
8804 attr->community->str);
d62a17ae 8805 }
05864da7 8806 }
718e3744 8807
05864da7
DS
8808 /* Line 5 display Extended-community */
8809 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8810 if (json_paths) {
8811 json_ext_community = json_object_new_object();
8812 json_object_string_add(json_ext_community, "string",
8813 attr->ecommunity->str);
8814 json_object_object_add(json_path, "extendedCommunity",
8815 json_ext_community);
d62a17ae 8816 } else {
05864da7
DS
8817 vty_out(vty, " Extended Community: %s\n",
8818 attr->ecommunity->str);
d62a17ae 8819 }
05864da7 8820 }
718e3744 8821
05864da7
DS
8822 /* Line 6 display Large community */
8823 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
8824 if (json_paths) {
8825 if (!attr->lcommunity->json)
8826 lcommunity_str(attr->lcommunity, true);
8827 json_object_lock(attr->lcommunity->json);
8828 json_object_object_add(json_path, "largeCommunity",
8829 attr->lcommunity->json);
8830 } else {
8831 vty_out(vty, " Large Community: %s\n",
8832 attr->lcommunity->str);
d62a17ae 8833 }
05864da7 8834 }
718e3744 8835
05864da7
DS
8836 /* Line 7 display Originator, Cluster-id */
8837 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
8838 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
8839 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 8840 if (json_paths)
05864da7
DS
8841 json_object_string_add(
8842 json_path, "originatorId",
8843 inet_ntoa(attr->originator_id));
d62a17ae 8844 else
05864da7
DS
8845 vty_out(vty, " Originator: %s",
8846 inet_ntoa(attr->originator_id));
d62a17ae 8847 }
856ca177 8848
05864da7
DS
8849 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
8850 int i;
d62a17ae 8851
8852 if (json_paths) {
05864da7
DS
8853 json_cluster_list = json_object_new_object();
8854 json_cluster_list_list =
8855 json_object_new_array();
8856
8857 for (i = 0; i < attr->cluster->length / 4;
8858 i++) {
8859 json_string = json_object_new_string(
8860 inet_ntoa(attr->cluster
8861 ->list[i]));
8862 json_object_array_add(
8863 json_cluster_list_list,
8864 json_string);
8865 }
718e3744 8866
05864da7
DS
8867 /*
8868 * struct cluster_list does not have
8869 * "str" variable like aspath and community
8870 * do. Add this someday if someone asks
8871 * for it.
8872 * json_object_string_add(json_cluster_list,
8873 * "string", attr->cluster->str);
8874 */
8875 json_object_object_add(json_cluster_list,
8876 "list",
8877 json_cluster_list_list);
8878 json_object_object_add(json_path, "clusterList",
8879 json_cluster_list);
0dc8ee70 8880 } else {
05864da7
DS
8881 vty_out(vty, ", Cluster list: ");
8882
8883 for (i = 0; i < attr->cluster->length / 4;
8884 i++) {
8885 vty_out(vty, "%s ",
8886 inet_ntoa(attr->cluster
8887 ->list[i]));
8888 }
0dc8ee70 8889 }
d62a17ae 8890 }
718e3744 8891
d62a17ae 8892 if (!json_paths)
8893 vty_out(vty, "\n");
05864da7 8894 }
d62a17ae 8895
05864da7 8896 if (path->extra && path->extra->damp_info)
a935f597 8897 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 8898
05864da7
DS
8899 /* Remote Label */
8900 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
8901 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
8902 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 8903
05864da7
DS
8904 if (json_paths)
8905 json_object_int_add(json_path, "remoteLabel", label);
8906 else
8907 vty_out(vty, " Remote label: %d\n", label);
8908 }
d62a17ae 8909
05864da7
DS
8910 /* Label Index */
8911 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
8912 if (json_paths)
8913 json_object_int_add(json_path, "labelIndex",
8914 attr->label_index);
8915 else
8916 vty_out(vty, " Label Index: %d\n",
8917 attr->label_index);
8918 }
d62a17ae 8919
05864da7
DS
8920 /* Line 8 display Addpath IDs */
8921 if (path->addpath_rx_id
8922 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
8923 if (json_paths) {
8924 json_object_int_add(json_path, "addpathRxId",
8925 path->addpath_rx_id);
d62a17ae 8926
05864da7
DS
8927 /* Keep backwards compatibility with the old API
8928 * by putting TX All's ID in the old field
8929 */
8930 json_object_int_add(
8931 json_path, "addpathTxId",
8932 path->tx_addpath
8933 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 8934
05864da7
DS
8935 /* ... but create a specific field for each
8936 * strategy
8937 */
8938 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
8939 json_object_int_add(
8940 json_path,
8941 bgp_addpath_names(i)->id_json_name,
8942 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 8943 }
05864da7
DS
8944 } else {
8945 vty_out(vty, " AddPath ID: RX %u, ",
8946 path->addpath_rx_id);
d62a17ae 8947
05864da7 8948 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 8949 }
05864da7 8950 }
520d5d76 8951
05864da7
DS
8952 /* If we used addpath to TX a non-bestpath we need to display
8953 * "Advertised to" on a path-by-path basis
8954 */
8955 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
8956 first = 1;
dcc68b5e 8957
05864da7
DS
8958 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
8959 addpath_capable =
8960 bgp_addpath_encode_tx(peer, afi, safi);
8961 has_adj = bgp_adj_out_lookup(
8962 peer, path->net,
8963 bgp_addpath_id_for_peer(peer, afi, safi,
8964 &path->tx_addpath));
8965
8966 if ((addpath_capable && has_adj)
8967 || (!addpath_capable && has_adj
8968 && CHECK_FLAG(path->flags,
8969 BGP_PATH_SELECTED))) {
8970 if (json_path && !json_adv_to)
8971 json_adv_to = json_object_new_object();
dcc68b5e 8972
05864da7
DS
8973 route_vty_out_advertised_to(
8974 vty, peer, &first,
8975 " Advertised to:", json_adv_to);
d62a17ae 8976 }
8977 }
718e3744 8978
05864da7
DS
8979 if (json_path) {
8980 if (json_adv_to) {
8981 json_object_object_add(
8982 json_path, "advertisedTo", json_adv_to);
d62a17ae 8983 }
05864da7
DS
8984 } else {
8985 if (!first) {
8986 vty_out(vty, "\n");
d62a17ae 8987 }
8988 }
05864da7 8989 }
b05a1c8b 8990
05864da7
DS
8991 /* Line 9 display Uptime */
8992 tbuf = time(NULL) - (bgp_clock() - path->uptime);
8993 if (json_paths) {
8994 json_last_update = json_object_new_object();
8995 json_object_int_add(json_last_update, "epoch", tbuf);
8996 json_object_string_add(json_last_update, "string",
8997 ctime(&tbuf));
8998 json_object_object_add(json_path, "lastUpdate",
8999 json_last_update);
9000 } else
9001 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 9002
05864da7
DS
9003 /* Line 10 display PMSI tunnel attribute, if present */
9004 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
9005 const char *str =
9006 lookup_msg(bgp_pmsi_tnltype_str, attr->pmsi_tnl_type,
9007 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 9008
05864da7
DS
9009 if (json_paths) {
9010 json_pmsi = json_object_new_object();
9011 json_object_string_add(json_pmsi, "tunnelType", str);
9012 json_object_int_add(json_pmsi, "label",
9013 label2vni(&attr->label));
9014 json_object_object_add(json_path, "pmsi", json_pmsi);
9015 } else
9016 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
9017 str, label2vni(&attr->label));
d62a17ae 9018 }
f1aa5d8a 9019
d62a17ae 9020 /* We've constructed the json object for this path, add it to the json
9021 * array of paths
9022 */
9023 if (json_paths) {
9024 if (json_nexthop_global || json_nexthop_ll) {
9025 json_nexthops = json_object_new_array();
f1aa5d8a 9026
d62a17ae 9027 if (json_nexthop_global)
9028 json_object_array_add(json_nexthops,
9029 json_nexthop_global);
f1aa5d8a 9030
d62a17ae 9031 if (json_nexthop_ll)
9032 json_object_array_add(json_nexthops,
9033 json_nexthop_ll);
f1aa5d8a 9034
d62a17ae 9035 json_object_object_add(json_path, "nexthops",
9036 json_nexthops);
9037 }
9038
9039 json_object_object_add(json_path, "peer", json_peer);
9040 json_object_array_add(json_paths, json_path);
05864da7 9041 }
b366b518
BB
9042}
9043
96ade3ed 9044#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
9045#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9046#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 9047
d62a17ae 9048static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
9049 const char *prefix_list_str, afi_t afi,
9050 safi_t safi, enum bgp_show_type type);
9051static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
9052 const char *filter, afi_t afi, safi_t safi,
9053 enum bgp_show_type type);
9054static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
9055 const char *rmap_str, afi_t afi, safi_t safi,
9056 enum bgp_show_type type);
9057static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
9058 const char *com, int exact, afi_t afi,
9059 safi_t safi);
9060static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
9061 const char *prefix, afi_t afi, safi_t safi,
9062 enum bgp_show_type type);
a4d82a8a
PZ
9063static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
9064 afi_t afi, safi_t safi, enum bgp_show_type type);
7f323236
DW
9065static int bgp_show_community(struct vty *vty, struct bgp *bgp,
9066 const char *comstr, int exact, afi_t afi,
9f049418 9067 safi_t safi, bool use_json);
d62a17ae 9068
1ae44dfc
LB
9069
9070static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 9071 struct bgp_table *table, enum bgp_show_type type,
9f049418 9072 void *output_arg, bool use_json, char *rd,
a4d82a8a
PZ
9073 int is_last, unsigned long *output_cum,
9074 unsigned long *total_cum,
9386b588 9075 unsigned long *json_header_depth)
d62a17ae 9076{
40381db7 9077 struct bgp_path_info *pi;
d62a17ae 9078 struct bgp_node *rn;
9079 int header = 1;
9080 int display;
1ae44dfc
LB
9081 unsigned long output_count = 0;
9082 unsigned long total_count = 0;
d62a17ae 9083 struct prefix *p;
d62a17ae 9084 char buf2[BUFSIZ];
9085 json_object *json_paths = NULL;
9086 int first = 1;
9087
1ae44dfc
LB
9088 if (output_cum && *output_cum != 0)
9089 header = 0;
9090
9386b588 9091 if (use_json && !*json_header_depth) {
d62a17ae 9092 vty_out(vty,
66f80d74 9093 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
01eced22
AD
9094 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9095 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 9096 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b
DS
9097 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
9098 ? VRF_DEFAULT_NAME
9099 : bgp->name,
01eced22
AD
9100 table->version, inet_ntoa(bgp->router_id),
9101 bgp->default_local_pref, bgp->as);
9386b588
PZ
9102 *json_header_depth = 2;
9103 if (rd) {
445c2480 9104 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
9105 ++*json_header_depth;
9106 }
d62a17ae 9107 }
718e3744 9108
445c2480
DS
9109 if (use_json && rd) {
9110 vty_out(vty, " \"%s\" : { ", rd);
9111 }
9112
d62a17ae 9113 /* Start processing of routes. */
98ce9a06 9114 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685
DS
9115 pi = bgp_node_get_bgp_path_info(rn);
9116 if (pi == NULL)
98ce9a06 9117 continue;
d62a17ae 9118
98ce9a06 9119 display = 0;
98ce9a06
DS
9120 if (use_json)
9121 json_paths = json_object_new_array();
9122 else
9123 json_paths = NULL;
d62a17ae 9124
6f94b685 9125 for (; pi; pi = pi->next) {
98ce9a06
DS
9126 total_count++;
9127 if (type == bgp_show_type_flap_statistics
9128 || type == bgp_show_type_flap_neighbor
9129 || type == bgp_show_type_dampend_paths
9130 || type == bgp_show_type_damp_neighbor) {
40381db7 9131 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
9132 continue;
9133 }
9134 if (type == bgp_show_type_regexp) {
9135 regex_t *regex = output_arg;
d62a17ae 9136
40381db7 9137 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
9138 == REG_NOMATCH)
9139 continue;
9140 }
9141 if (type == bgp_show_type_prefix_list) {
9142 struct prefix_list *plist = output_arg;
d62a17ae 9143
98ce9a06
DS
9144 if (prefix_list_apply(plist, &rn->p)
9145 != PREFIX_PERMIT)
9146 continue;
9147 }
9148 if (type == bgp_show_type_filter_list) {
9149 struct as_list *as_list = output_arg;
d62a17ae 9150
40381db7 9151 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
9152 != AS_FILTER_PERMIT)
9153 continue;
9154 }
9155 if (type == bgp_show_type_route_map) {
9156 struct route_map *rmap = output_arg;
9b6d8fcf 9157 struct bgp_path_info path;
98ce9a06 9158 struct attr dummy_attr;
b68885f9 9159 route_map_result_t ret;
d62a17ae 9160
40381db7 9161 bgp_attr_dup(&dummy_attr, pi->attr);
d62a17ae 9162
40381db7 9163 path.peer = pi->peer;
9b6d8fcf 9164 path.attr = &dummy_attr;
d62a17ae 9165
a4d82a8a 9166 ret = route_map_apply(rmap, &rn->p, RMAP_BGP,
9b6d8fcf 9167 &path);
98ce9a06
DS
9168 if (ret == RMAP_DENYMATCH)
9169 continue;
9170 }
9171 if (type == bgp_show_type_neighbor
9172 || type == bgp_show_type_flap_neighbor
9173 || type == bgp_show_type_damp_neighbor) {
9174 union sockunion *su = output_arg;
9175
40381db7
DS
9176 if (pi->peer == NULL
9177 || pi->peer->su_remote == NULL
9178 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
9179 continue;
9180 }
9181 if (type == bgp_show_type_cidr_only) {
d7c0a89a 9182 uint32_t destination;
d62a17ae 9183
98ce9a06
DS
9184 destination = ntohl(rn->p.u.prefix4.s_addr);
9185 if (IN_CLASSC(destination)
9186 && rn->p.prefixlen == 24)
9187 continue;
9188 if (IN_CLASSB(destination)
9189 && rn->p.prefixlen == 16)
9190 continue;
9191 if (IN_CLASSA(destination)
9192 && rn->p.prefixlen == 8)
9193 continue;
9194 }
9195 if (type == bgp_show_type_prefix_longer) {
f7813c7c 9196 p = output_arg;
98ce9a06
DS
9197 if (!prefix_match(p, &rn->p))
9198 continue;
9199 }
9200 if (type == bgp_show_type_community_all) {
40381db7 9201 if (!pi->attr->community)
98ce9a06
DS
9202 continue;
9203 }
9204 if (type == bgp_show_type_community) {
9205 struct community *com = output_arg;
d62a17ae 9206
40381db7
DS
9207 if (!pi->attr->community
9208 || !community_match(pi->attr->community,
98ce9a06
DS
9209 com))
9210 continue;
9211 }
9212 if (type == bgp_show_type_community_exact) {
9213 struct community *com = output_arg;
d62a17ae 9214
40381db7
DS
9215 if (!pi->attr->community
9216 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
9217 continue;
9218 }
9219 if (type == bgp_show_type_community_list) {
9220 struct community_list *list = output_arg;
d62a17ae 9221
40381db7 9222 if (!community_list_match(pi->attr->community,
a4d82a8a 9223 list))
98ce9a06
DS
9224 continue;
9225 }
a4d82a8a 9226 if (type == bgp_show_type_community_list_exact) {
98ce9a06 9227 struct community_list *list = output_arg;
d62a17ae 9228
98ce9a06 9229 if (!community_list_exact_match(
40381db7 9230 pi->attr->community, list))
98ce9a06
DS
9231 continue;
9232 }
9233 if (type == bgp_show_type_lcommunity) {
9234 struct lcommunity *lcom = output_arg;
d62a17ae 9235
40381db7
DS
9236 if (!pi->attr->lcommunity
9237 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
9238 lcom))
9239 continue;
9240 }
36a206db 9241
9242 if (type == bgp_show_type_lcommunity_exact) {
9243 struct lcommunity *lcom = output_arg;
9244
9245 if (!pi->attr->lcommunity
9246 || !lcommunity_cmp(pi->attr->lcommunity,
9247 lcom))
9248 continue;
9249 }
98ce9a06
DS
9250 if (type == bgp_show_type_lcommunity_list) {
9251 struct community_list *list = output_arg;
d62a17ae 9252
40381db7 9253 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 9254 list))
98ce9a06
DS
9255 continue;
9256 }
36a206db 9257 if (type
9258 == bgp_show_type_lcommunity_list_exact) {
9259 struct community_list *list = output_arg;
9260
9261 if (!lcommunity_list_exact_match(
9262 pi->attr->lcommunity, list))
9263 continue;
9264 }
98ce9a06 9265 if (type == bgp_show_type_lcommunity_all) {
40381db7 9266 if (!pi->attr->lcommunity)
98ce9a06
DS
9267 continue;
9268 }
9269 if (type == bgp_show_type_dampend_paths
9270 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
9271 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
9272 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
9273 continue;
9274 }
9275
9276 if (!use_json && header) {
996c9314 9277 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 9278 ", local router ID is %s, vrf id ",
98ce9a06
DS
9279 table->version,
9280 inet_ntoa(bgp->router_id));
9df8b37c
PZ
9281 if (bgp->vrf_id == VRF_UNKNOWN)
9282 vty_out(vty, "%s", VRFID_NONE_STR);
9283 else
9284 vty_out(vty, "%u", bgp->vrf_id);
9285 vty_out(vty, "\n");
01eced22
AD
9286 vty_out(vty, "Default local pref %u, ",
9287 bgp->default_local_pref);
9288 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 9289 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 9290 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 9291 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 9292 if (type == bgp_show_type_dampend_paths
9293 || type == bgp_show_type_damp_neighbor)
98ce9a06 9294 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
9295 else if (type == bgp_show_type_flap_statistics
9296 || type == bgp_show_type_flap_neighbor)
98ce9a06 9297 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 9298 else
98ce9a06
DS
9299 vty_out(vty, BGP_SHOW_HEADER);
9300 header = 0;
d62a17ae 9301 }
98ce9a06
DS
9302 if (rd != NULL && !display && !output_count) {
9303 if (!use_json)
9304 vty_out(vty,
9305 "Route Distinguisher: %s\n",
9306 rd);
d62a17ae 9307 }
98ce9a06
DS
9308 if (type == bgp_show_type_dampend_paths
9309 || type == bgp_show_type_damp_neighbor)
a935f597 9310 damp_route_vty_out(vty, &rn->p, pi, display, AFI_IP,
a4d82a8a 9311 safi, use_json, json_paths);
98ce9a06
DS
9312 else if (type == bgp_show_type_flap_statistics
9313 || type == bgp_show_type_flap_neighbor)
a935f597 9314 flap_route_vty_out(vty, &rn->p, pi, display, AFI_IP,
a4d82a8a 9315 safi, use_json, json_paths);
98ce9a06 9316 else
40381db7 9317 route_vty_out(vty, &rn->p, pi, display, safi,
a4d82a8a 9318 json_paths);
98ce9a06 9319 display++;
d62a17ae 9320 }
9321
98ce9a06
DS
9322 if (display) {
9323 output_count++;
9324 if (!use_json)
9325 continue;
9326
9327 p = &rn->p;
625d2931
PG
9328 /* encode prefix */
9329 if (p->family == AF_FLOWSPEC) {
9330 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
9331
9332 bgp_fs_nlri_get_string((unsigned char *)
9333 p->u.prefix_flowspec.ptr,
9334 p->u.prefix_flowspec
9335 .prefixlen,
9336 retstr,
9337 NLRI_STRING_FORMAT_MIN,
9338 NULL);
9339 if (first)
9340 vty_out(vty, "\"%s/%d\": ",
9341 retstr,
9342 p->u.prefix_flowspec.prefixlen);
9343 else
9344 vty_out(vty, ",\"%s/%d\": ",
9345 retstr,
9346 p->u.prefix_flowspec.prefixlen);
9347 } else {
9348 prefix2str(p, buf2, sizeof(buf2));
9349 if (first)
9350 vty_out(vty, "\"%s\": ", buf2);
9351 else
9352 vty_out(vty, ",\"%s\": ", buf2);
9353 }
98ce9a06 9354 vty_out(vty, "%s",
23b2a7ef 9355 json_object_to_json_string(json_paths));
98ce9a06 9356 json_object_free(json_paths);
449feb8e 9357 json_paths = NULL;
98ce9a06
DS
9358 first = 0;
9359 }
9360 }
9361
1ae44dfc
LB
9362 if (output_cum) {
9363 output_count += *output_cum;
9364 *output_cum = output_count;
9365 }
9366 if (total_cum) {
9367 total_count += *total_cum;
9368 *total_cum = total_count;
9369 }
d62a17ae 9370 if (use_json) {
9386b588 9371 if (rd) {
a4d82a8a 9372 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
9373 }
9374 if (is_last) {
a4d82a8a
PZ
9375 unsigned long i;
9376 for (i = 0; i < *json_header_depth; ++i)
9377 vty_out(vty, " } ");
faf6559a 9378 vty_out(vty, "\n");
9386b588 9379 }
d62a17ae 9380 } else {
1ae44dfc
LB
9381 if (is_last) {
9382 /* No route is displayed */
9383 if (output_count == 0) {
9384 if (type == bgp_show_type_normal)
9385 vty_out(vty,
9386 "No BGP prefixes displayed, %ld exist\n",
9387 total_count);
9388 } else
d62a17ae 9389 vty_out(vty,
1ae44dfc
LB
9390 "\nDisplayed %ld routes and %ld total paths\n",
9391 output_count, total_count);
9392 }
d62a17ae 9393 }
718e3744 9394
d62a17ae 9395 return CMD_SUCCESS;
718e3744 9396}
9397
1ae44dfc
LB
9398int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
9399 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 9400 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc
LB
9401{
9402 struct bgp_node *rn, *next;
9403 unsigned long output_cum = 0;
9404 unsigned long total_cum = 0;
9386b588 9405 unsigned long json_header_depth = 0;
67009e22 9406 struct bgp_table *itable;
0136788c
LB
9407 bool show_msg;
9408
9409 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc
LB
9410
9411 for (rn = bgp_table_top(table); rn; rn = next) {
9412 next = bgp_route_next(rn);
9413 if (prd_match && memcmp(rn->p.u.val, prd_match->val, 8) != 0)
9414 continue;
67009e22
DS
9415
9416 itable = bgp_node_get_bgp_table_info(rn);
9417 if (itable != NULL) {
1ae44dfc 9418 struct prefix_rd prd;
06b9f471 9419 char rd[RD_ADDRSTRLEN];
1ae44dfc
LB
9420
9421 memcpy(&prd, &(rn->p), sizeof(struct prefix_rd));
06b9f471 9422 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22
DS
9423 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
9424 use_json, rd, next == NULL, &output_cum,
9425 &total_cum, &json_header_depth);
0136788c
LB
9426 if (next == NULL)
9427 show_msg = false;
1ae44dfc
LB
9428 }
9429 }
0136788c
LB
9430 if (show_msg) {
9431 if (output_cum == 0)
9432 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
9433 total_cum);
9434 else
9435 vty_out(vty,
9436 "\nDisplayed %ld routes and %ld total paths\n",
9437 output_cum, total_cum);
9438 }
1ae44dfc
LB
9439 return CMD_SUCCESS;
9440}
d62a17ae 9441static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
9f049418 9442 enum bgp_show_type type, void *output_arg, bool use_json)
fee0f4c6 9443{
d62a17ae 9444 struct bgp_table *table;
9386b588 9445 unsigned long json_header_depth = 0;
fee0f4c6 9446
d62a17ae 9447 if (bgp == NULL) {
9448 bgp = bgp_get_default();
9449 }
fee0f4c6 9450
d62a17ae 9451 if (bgp == NULL) {
9452 if (!use_json)
9453 vty_out(vty, "No BGP process is configured\n");
16307668
RW
9454 else
9455 vty_out(vty, "{}\n");
d62a17ae 9456 return CMD_WARNING;
9457 }
4dd6177e 9458
1ae44dfc 9459 table = bgp->rib[afi][safi];
d62a17ae 9460 /* use MPLS and ENCAP specific shows until they are merged */
9461 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
9462 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
9463 output_arg, use_json);
d62a17ae 9464 }
dba3c1d3
PG
9465
9466 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
9467 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
9468 output_arg, use_json,
9469 1, NULL, NULL);
9470 }
d62a17ae 9471 /* labeled-unicast routes live in the unicast table */
9472 else if (safi == SAFI_LABELED_UNICAST)
9473 safi = SAFI_UNICAST;
fee0f4c6 9474
1ae44dfc 9475 return bgp_show_table(vty, bgp, safi, table, type, output_arg, use_json,
9386b588 9476 NULL, 1, NULL, NULL, &json_header_depth);
fee0f4c6 9477}
9478
d62a17ae 9479static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
9f049418 9480 safi_t safi, bool use_json)
f186de26 9481{
d62a17ae 9482 struct listnode *node, *nnode;
9483 struct bgp *bgp;
9484 int is_first = 1;
9f049418 9485 bool route_output = false;
f186de26 9486
d62a17ae 9487 if (use_json)
9488 vty_out(vty, "{\n");
9f689658 9489
d62a17ae 9490 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 9491 route_output = true;
d62a17ae 9492 if (use_json) {
9493 if (!is_first)
9494 vty_out(vty, ",\n");
9495 else
9496 is_first = 0;
9497
9498 vty_out(vty, "\"%s\":",
9499 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 9500 ? VRF_DEFAULT_NAME
d62a17ae 9501 : bgp->name);
9502 } else {
9503 vty_out(vty, "\nInstance %s:\n",
9504 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 9505 ? VRF_DEFAULT_NAME
d62a17ae 9506 : bgp->name);
9507 }
9508 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
9509 use_json);
9510 }
9f689658 9511
d62a17ae 9512 if (use_json)
9513 vty_out(vty, "}\n");
9f049418
DS
9514 else if (!route_output)
9515 vty_out(vty, "%% BGP instance not found\n");
f186de26 9516}
9517
718e3744 9518/* Header of detailed BGP route information */
d62a17ae 9519void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9520 struct bgp_node *rn, struct prefix_rd *prd,
9521 afi_t afi, safi_t safi, json_object *json)
9522{
40381db7 9523 struct bgp_path_info *pi;
d62a17ae 9524 struct prefix *p;
9525 struct peer *peer;
9526 struct listnode *node, *nnode;
06b9f471 9527 char buf1[RD_ADDRSTRLEN];
d62a17ae 9528 char buf2[INET6_ADDRSTRLEN];
d62a17ae 9529 char buf3[EVPN_ROUTE_STRLEN];
0291c246 9530 char prefix_str[BUFSIZ];
d62a17ae 9531 int count = 0;
9532 int best = 0;
9533 int suppress = 0;
c5f1e1b2
C
9534 int accept_own = 0;
9535 int route_filter_translated_v4 = 0;
9536 int route_filter_v4 = 0;
9537 int route_filter_translated_v6 = 0;
9538 int route_filter_v6 = 0;
9539 int llgr_stale = 0;
9540 int no_llgr = 0;
9541 int accept_own_nexthop = 0;
9542 int blackhole = 0;
d62a17ae 9543 int no_export = 0;
9544 int no_advertise = 0;
9545 int local_as = 0;
c5f1e1b2 9546 int no_peer = 0;
d62a17ae 9547 int first = 1;
9548 int has_valid_label = 0;
9549 mpls_label_t label = 0;
9550 json_object *json_adv_to = NULL;
9bedbb1e 9551
d62a17ae 9552 p = &rn->p;
9553 has_valid_label = bgp_is_valid_label(&rn->local_label);
9554
9555 if (has_valid_label)
9556 label = label_pton(&rn->local_label);
9557
44c69747 9558 if (safi == SAFI_EVPN) {
d62a17ae 9559
44c69747 9560 if (!json) {
d62a17ae 9561 vty_out(vty, "BGP routing table entry for %s%s%s\n",
06b9f471 9562 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
44c69747 9563 : "", prd ? ":" : "",
d62a17ae 9564 bgp_evpn_route2str((struct prefix_evpn *)p,
44c69747
LK
9565 buf3, sizeof(buf3)));
9566 } else {
9567 json_object_string_add(json, "rd",
9568 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
9569 "");
9570 bgp_evpn_route2json((struct prefix_evpn *)p, json);
9571 }
9572 } else {
9573 if (!json) {
d62a17ae 9574 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
9575 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
44c69747
LK
9576 ? prefix_rd2str(prd, buf1,
9577 sizeof(buf1))
9578 : ""),
d62a17ae 9579 safi == SAFI_MPLS_VPN ? ":" : "",
9580 inet_ntop(p->family, &p->u.prefix, buf2,
44c69747 9581 INET6_ADDRSTRLEN),
d62a17ae 9582 p->prefixlen);
cd1964ff 9583
44c69747
LK
9584 } else
9585 json_object_string_add(json, "prefix",
9586 prefix2str(p, prefix_str, sizeof(prefix_str)));
9587 }
9588
9589 if (has_valid_label) {
9590 if (json)
9591 json_object_int_add(json, "localLabel", label);
9592 else
d62a17ae 9593 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
9594 }
9595
9596 if (!json)
d62a17ae 9597 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 9598 vty_out(vty, "not allocated\n");
718e3744 9599
6f94b685 9600 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
d62a17ae 9601 count++;
40381db7 9602 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 9603 best = count;
40381db7 9604 if (pi->extra && pi->extra->suppress)
d62a17ae 9605 suppress = 1;
cee9c031 9606
40381db7 9607 if (pi->attr->community == NULL)
cee9c031
QY
9608 continue;
9609
9610 no_advertise += community_include(
40381db7
DS
9611 pi->attr->community, COMMUNITY_NO_ADVERTISE);
9612 no_export += community_include(pi->attr->community,
cee9c031 9613 COMMUNITY_NO_EXPORT);
40381db7 9614 local_as += community_include(pi->attr->community,
cee9c031 9615 COMMUNITY_LOCAL_AS);
40381db7 9616 accept_own += community_include(pi->attr->community,
cee9c031
QY
9617 COMMUNITY_ACCEPT_OWN);
9618 route_filter_translated_v4 += community_include(
40381db7 9619 pi->attr->community,
cee9c031
QY
9620 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
9621 route_filter_translated_v6 += community_include(
40381db7 9622 pi->attr->community,
cee9c031
QY
9623 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
9624 route_filter_v4 += community_include(
40381db7 9625 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 9626 route_filter_v6 += community_include(
40381db7
DS
9627 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
9628 llgr_stale += community_include(pi->attr->community,
cee9c031 9629 COMMUNITY_LLGR_STALE);
40381db7 9630 no_llgr += community_include(pi->attr->community,
cee9c031
QY
9631 COMMUNITY_NO_LLGR);
9632 accept_own_nexthop +=
40381db7 9633 community_include(pi->attr->community,
cee9c031 9634 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 9635 blackhole += community_include(pi->attr->community,
cee9c031 9636 COMMUNITY_BLACKHOLE);
40381db7 9637 no_peer += community_include(pi->attr->community,
cee9c031 9638 COMMUNITY_NO_PEER);
d62a17ae 9639 }
718e3744 9640 }
718e3744 9641
d62a17ae 9642 if (!json) {
9643 vty_out(vty, "Paths: (%d available", count);
9644 if (best) {
9645 vty_out(vty, ", best #%d", best);
b84060bb
PG
9646 if (safi == SAFI_UNICAST) {
9647 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
9648 vty_out(vty, ", table %s",
9649 VRF_DEFAULT_NAME);
9650 else
9651 vty_out(vty, ", vrf %s",
9652 bgp->name);
9653 }
d62a17ae 9654 } else
9655 vty_out(vty, ", no best path");
9656
c5f1e1b2
C
9657 if (accept_own)
9658 vty_out(vty,
9659 ", accept own local route exported and imported in different VRF");
9660 else if (route_filter_translated_v4)
9661 vty_out(vty,
9662 ", mark translated RTs for VPNv4 route filtering");
9663 else if (route_filter_v4)
9664 vty_out(vty,
9665 ", attach RT as-is for VPNv4 route filtering");
9666 else if (route_filter_translated_v6)
9667 vty_out(vty,
9668 ", mark translated RTs for VPNv6 route filtering");
9669 else if (route_filter_v6)
9670 vty_out(vty,
9671 ", attach RT as-is for VPNv6 route filtering");
9672 else if (llgr_stale)
9673 vty_out(vty,
9674 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9675 else if (no_llgr)
9676 vty_out(vty,
9677 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9678 else if (accept_own_nexthop)
9679 vty_out(vty,
9680 ", accept local nexthop");
9681 else if (blackhole)
9682 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 9683 else if (no_export)
9684 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
9685 else if (no_advertise)
9686 vty_out(vty, ", not advertised to any peer");
d62a17ae 9687 else if (local_as)
9688 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
9689 else if (no_peer)
9690 vty_out(vty,
9691 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 9692
9693 if (suppress)
9694 vty_out(vty,
9695 ", Advertisements suppressed by an aggregate.");
9696 vty_out(vty, ")\n");
9697 }
718e3744 9698
d62a17ae 9699 /* If we are not using addpath then we can display Advertised to and
9700 * that will
9701 * show what peers we advertised the bestpath to. If we are using
9702 * addpath
9703 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 9704 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 9705 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9706 if (bgp_adj_out_lookup(peer, rn, 0)) {
9707 if (json && !json_adv_to)
9708 json_adv_to = json_object_new_object();
9709
9710 route_vty_out_advertised_to(
9711 vty, peer, &first,
9712 " Advertised to non peer-group peers:\n ",
9713 json_adv_to);
9714 }
9715 }
9716
9717 if (json) {
9718 if (json_adv_to) {
9719 json_object_object_add(json, "advertisedTo",
9720 json_adv_to);
9721 }
9722 } else {
9723 if (first)
9724 vty_out(vty, " Not advertised to any peer");
9725 vty_out(vty, "\n");
9726 }
9727 }
718e3744 9728}
9729
44c69747
LK
9730static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9731 struct bgp_node *bgp_node, struct vty *vty,
9732 struct bgp *bgp, afi_t afi,
9733 safi_t safi, json_object *json,
9734 enum bgp_path_type pathtype, int *display)
9735{
9736 struct bgp_path_info *pi;
9737 int header = 1;
9738 char rdbuf[RD_ADDRSTRLEN];
9739 json_object *json_header = NULL;
9740 json_object *json_paths = NULL;
9741
9742 for (pi = bgp_node_get_bgp_path_info(bgp_node); pi;
9743 pi = pi->next) {
9744
9745 if (json && !json_paths) {
9746 /* Instantiate json_paths only if path is valid */
9747 json_paths = json_object_new_array();
9748 if (pfx_rd) {
9749 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
9750 json_header = json_object_new_object();
9751 } else
9752 json_header = json;
9753 }
9754
9755 if (header) {
9756 route_vty_out_detail_header(
9757 vty, bgp, bgp_node, pfx_rd,
9758 AFI_IP, safi, json_header);
9759 header = 0;
9760 }
9761 (*display)++;
9762
9763 if (pathtype == BGP_PATH_SHOW_ALL
9764 || (pathtype == BGP_PATH_SHOW_BESTPATH
9765 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
9766 || (pathtype == BGP_PATH_SHOW_MULTIPATH
9767 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
9768 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
9769 route_vty_out_detail(vty, bgp, bgp_node,
9770 pi, AFI_IP, safi,
9771 json_paths);
9772 }
9773
9774 if (json && json_paths) {
9775 json_object_object_add(json_header, "paths", json_paths);
9776
9777 if (pfx_rd)
9778 json_object_object_add(json, rdbuf, json_header);
9779 }
9780}
9781
718e3744 9782/* Display specified route of BGP table. */
d62a17ae 9783static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
9784 struct bgp_table *rib, const char *ip_str,
9785 afi_t afi, safi_t safi,
9786 struct prefix_rd *prd, int prefix_check,
9f049418 9787 enum bgp_path_type pathtype, bool use_json)
d62a17ae 9788{
9789 int ret;
d62a17ae 9790 int display = 0;
9791 struct prefix match;
9792 struct bgp_node *rn;
9793 struct bgp_node *rm;
d62a17ae 9794 struct bgp_table *table;
9795 json_object *json = NULL;
9796 json_object *json_paths = NULL;
9797
9798 /* Check IP address argument. */
9799 ret = str2prefix(ip_str, &match);
9800 if (!ret) {
9801 vty_out(vty, "address is malformed\n");
9802 return CMD_WARNING;
9803 }
718e3744 9804
d62a17ae 9805 match.family = afi2family(afi);
b05a1c8b 9806
44c69747 9807 if (use_json)
d62a17ae 9808 json = json_object_new_object();
718e3744 9809
44c69747 9810 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
d62a17ae 9811 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
9812 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
9813 continue;
67009e22
DS
9814 table = bgp_node_get_bgp_table_info(rn);
9815 if (!table)
ea47320b 9816 continue;
d62a17ae 9817
ea47320b
DL
9818 if ((rm = bgp_node_match(table, &match)) == NULL)
9819 continue;
d62a17ae 9820
ea47320b
DL
9821 if (prefix_check
9822 && rm->p.prefixlen != match.prefixlen) {
9823 bgp_unlock_node(rm);
9824 continue;
9825 }
d62a17ae 9826
44c69747
LK
9827 bgp_show_path_info((struct prefix_rd *)&rn->p, rm,
9828 vty, bgp, afi, safi, json,
9829 pathtype, &display);
9830
9831 bgp_unlock_node(rm);
9832 }
9833 } else if (safi == SAFI_EVPN) {
9834 struct bgp_node *longest_pfx;
9835 bool is_exact_pfxlen_match = FALSE;
9836
9837 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
9838 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
9839 continue;
9840 table = bgp_node_get_bgp_table_info(rn);
9841 if (!table)
9842 continue;
9843
9844 longest_pfx = NULL;
9845 is_exact_pfxlen_match = FALSE;
9846 /*
9847 * Search through all the prefixes for a match. The
9848 * pfx's are enumerated in ascending order of pfxlens.
9849 * So, the last pfx match is the longest match. Set
9850 * is_exact_pfxlen_match when we get exact pfxlen match
9851 */
9852 for (rm = bgp_table_top(table); rm;
9853 rm = bgp_route_next(rm)) {
9854 /*
9855 * Get prefixlen of the ip-prefix within type5
9856 * evpn route
9857 */
9858 if (evpn_type5_prefix_match(&rm->p,
9859 &match) && rm->info) {
9860 longest_pfx = rm;
9861 int type5_pfxlen =
9862 bgp_evpn_get_type5_prefixlen(&rm->p);
9863 if (type5_pfxlen == match.prefixlen) {
9864 is_exact_pfxlen_match = TRUE;
9865 bgp_unlock_node(rm);
9866 break;
9867 }
d62a17ae 9868 }
9869 }
ea47320b 9870
44c69747
LK
9871 if (!longest_pfx)
9872 continue;
9873
9874 if (prefix_check && !is_exact_pfxlen_match)
9875 continue;
9876
9877 rm = longest_pfx;
9878 bgp_lock_node(rm);
9879
9880 bgp_show_path_info((struct prefix_rd *)&rn->p, rm,
9881 vty, bgp, afi, safi, json,
9882 pathtype, &display);
9883
ea47320b 9884 bgp_unlock_node(rm);
d62a17ae 9885 }
98a9dbc7 9886 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
9887 if (use_json)
9888 json_paths = json_object_new_array();
9889
63a0b7a9
PG
9890 display = bgp_flowspec_display_match_per_ip(afi, rib,
9891 &match, prefix_check,
9892 vty,
9893 use_json,
9894 json_paths);
44c69747
LK
9895 if (use_json && display)
9896 json_object_object_add(json, "paths", json_paths);
d62a17ae 9897 } else {
d62a17ae 9898 if ((rn = bgp_node_match(rib, &match)) != NULL) {
9899 if (!prefix_check
9900 || rn->p.prefixlen == match.prefixlen) {
44c69747
LK
9901 bgp_show_path_info(NULL, rn, vty, bgp, afi,
9902 safi, json,
9903 pathtype, &display);
d62a17ae 9904 }
9905
9906 bgp_unlock_node(rn);
9907 }
9908 }
e5eee9af 9909
d62a17ae 9910 if (use_json) {
996c9314 9911 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
9912 json, JSON_C_TO_STRING_PRETTY |
9913 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 9914 json_object_free(json);
9915 } else {
9916 if (!display) {
9917 vty_out(vty, "%% Network not in table\n");
9918 return CMD_WARNING;
9919 }
9920 }
b05a1c8b 9921
d62a17ae 9922 return CMD_SUCCESS;
718e3744 9923}
9924
fee0f4c6 9925/* Display specified route of Main RIB */
d62a17ae 9926static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
9927 afi_t afi, safi_t safi, struct prefix_rd *prd,
9928 int prefix_check, enum bgp_path_type pathtype,
9f049418 9929 bool use_json)
d62a17ae 9930{
9b86009a 9931 if (!bgp) {
d62a17ae 9932 bgp = bgp_get_default();
9b86009a
RW
9933 if (!bgp) {
9934 if (!use_json)
9935 vty_out(vty, "No BGP process is configured\n");
16307668
RW
9936 else
9937 vty_out(vty, "{}\n");
9b86009a
RW
9938 return CMD_WARNING;
9939 }
9940 }
d62a17ae 9941
9942 /* labeled-unicast routes live in the unicast table */
9943 if (safi == SAFI_LABELED_UNICAST)
9944 safi = SAFI_UNICAST;
9945
9946 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
9947 afi, safi, prd, prefix_check, pathtype,
9948 use_json);
9949}
9950
9951static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 9952 struct cmd_token **argv, bool exact, afi_t afi,
9953 safi_t safi, bool uj)
d62a17ae 9954{
9955 struct lcommunity *lcom;
9956 struct buffer *b;
9957 int i;
9958 char *str;
9959 int first = 0;
9960
9961 b = buffer_new(1024);
9962 for (i = 0; i < argc; i++) {
9963 if (first)
9964 buffer_putc(b, ' ');
9965 else {
9966 if (strmatch(argv[i]->text, "AA:BB:CC")) {
9967 first = 1;
9968 buffer_putstr(b, argv[i]->arg);
9969 }
9970 }
9971 }
9972 buffer_putc(b, '\0');
57d187bc 9973
d62a17ae 9974 str = buffer_getstr(b);
9975 buffer_free(b);
57d187bc 9976
d62a17ae 9977 lcom = lcommunity_str2com(str);
9978 XFREE(MTYPE_TMP, str);
9979 if (!lcom) {
9980 vty_out(vty, "%% Large-community malformed\n");
9981 return CMD_WARNING;
9982 }
57d187bc 9983
36a206db 9984 return bgp_show(vty, bgp, afi, safi,
9985 (exact ? bgp_show_type_lcommunity_exact
9986 : bgp_show_type_lcommunity),
9987 lcom, uj);
57d187bc
JS
9988}
9989
d62a17ae 9990static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 9991 const char *lcom, bool exact, afi_t afi,
9992 safi_t safi, bool uj)
57d187bc 9993{
d62a17ae 9994 struct community_list *list;
57d187bc 9995
e237b0d2 9996 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 9997 LARGE_COMMUNITY_LIST_MASTER);
9998 if (list == NULL) {
9999 vty_out(vty, "%% %s is not a valid large-community-list name\n",
10000 lcom);
10001 return CMD_WARNING;
10002 }
57d187bc 10003
36a206db 10004 return bgp_show(vty, bgp, afi, safi,
10005 (exact ? bgp_show_type_lcommunity_list_exact
10006 : bgp_show_type_lcommunity_list),
d62a17ae 10007 list, uj);
fee0f4c6 10008}
10009
52951b63
DS
10010DEFUN (show_ip_bgp_large_community_list,
10011 show_ip_bgp_large_community_list_cmd,
36a206db 10012 "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
10013 SHOW_STR
10014 IP_STR
10015 BGP_STR
10016 BGP_INSTANCE_HELP_STR
9bedbb1e 10017 BGP_AFI_HELP_STR
4dd6177e 10018 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10019 "Display routes matching the large-community-list\n"
10020 "large-community-list number\n"
10021 "large-community-list name\n"
36a206db 10022 "Exact match of the large-communities\n"
52951b63
DS
10023 JSON_STR)
10024{
d62a17ae 10025 char *vrf = NULL;
10026 afi_t afi = AFI_IP6;
10027 safi_t safi = SAFI_UNICAST;
10028 int idx = 0;
36a206db 10029 bool exact_match = 0;
d62a17ae 10030
10031 if (argv_find(argv, argc, "ip", &idx))
10032 afi = AFI_IP;
10033 if (argv_find(argv, argc, "view", &idx)
10034 || argv_find(argv, argc, "vrf", &idx))
10035 vrf = argv[++idx]->arg;
10036 if (argv_find(argv, argc, "ipv4", &idx)
10037 || argv_find(argv, argc, "ipv6", &idx)) {
10038 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
10039 if (argv_find(argv, argc, "unicast", &idx)
10040 || argv_find(argv, argc, "multicast", &idx))
10041 safi = bgp_vty_safi_from_str(argv[idx]->text);
10042 }
10043
9f049418 10044 bool uj = use_json(argc, argv);
d62a17ae 10045
10046 struct bgp *bgp = bgp_lookup_by_name(vrf);
10047 if (bgp == NULL) {
10048 vty_out(vty, "Can't find BGP instance %s\n", vrf);
10049 return CMD_WARNING;
10050 }
10051
10052 argv_find(argv, argc, "large-community-list", &idx);
36a206db 10053
10054 const char *clist_number_or_name = argv[++idx]->arg;
10055
10056 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10057 exact_match = 1;
10058
10059 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
10060 exact_match, afi, safi, uj);
52951b63
DS
10061}
10062DEFUN (show_ip_bgp_large_community,
10063 show_ip_bgp_large_community_cmd,
36a206db 10064 "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
10065 SHOW_STR
10066 IP_STR
10067 BGP_STR
10068 BGP_INSTANCE_HELP_STR
9bedbb1e 10069 BGP_AFI_HELP_STR
4dd6177e 10070 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10071 "Display routes matching the large-communities\n"
10072 "List of large-community numbers\n"
36a206db 10073 "Exact match of the large-communities\n"
52951b63
DS
10074 JSON_STR)
10075{
d62a17ae 10076 char *vrf = NULL;
10077 afi_t afi = AFI_IP6;
10078 safi_t safi = SAFI_UNICAST;
10079 int idx = 0;
36a206db 10080 bool exact_match = 0;
d62a17ae 10081
10082 if (argv_find(argv, argc, "ip", &idx))
10083 afi = AFI_IP;
10084 if (argv_find(argv, argc, "view", &idx)
10085 || argv_find(argv, argc, "vrf", &idx))
10086 vrf = argv[++idx]->arg;
10087 if (argv_find(argv, argc, "ipv4", &idx)
10088 || argv_find(argv, argc, "ipv6", &idx)) {
10089 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
10090 if (argv_find(argv, argc, "unicast", &idx)
10091 || argv_find(argv, argc, "multicast", &idx))
10092 safi = bgp_vty_safi_from_str(argv[idx]->text);
10093 }
10094
9f049418 10095 bool uj = use_json(argc, argv);
d62a17ae 10096
10097 struct bgp *bgp = bgp_lookup_by_name(vrf);
10098 if (bgp == NULL) {
10099 vty_out(vty, "Can't find BGP instance %s\n", vrf);
10100 return CMD_WARNING;
10101 }
10102
36a206db 10103 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
10104 if (argv_find(argv, argc, "exact-match", &idx))
10105 exact_match = 1;
10106 return bgp_show_lcommunity(vty, bgp, argc, argv,
10107 exact_match, afi, safi, uj);
10108 } else
d62a17ae 10109 return bgp_show(vty, bgp, afi, safi,
10110 bgp_show_type_lcommunity_all, NULL, uj);
52951b63
DS
10111}
10112
d62a17ae 10113static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
10114 safi_t safi);
e01ca200 10115
7b2ff250
DW
10116
10117/* BGP route print out function without JSON */
af462945
DS
10118DEFUN (show_ip_bgp,
10119 show_ip_bgp_cmd,
4dd6177e 10120 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
7b2ff250
DW
10121 <dampening <parameters>\
10122 |route-map WORD\
10123 |prefix-list WORD\
10124 |filter-list WORD\
10125 |statistics\
7b2ff250
DW
10126 |community-list <(1-500)|WORD> [exact-match]\
10127 |A.B.C.D/M longer-prefixes\
10128 |X:X::X:X/M longer-prefixes\
10129 >",
718e3744 10130 SHOW_STR
10131 IP_STR
10132 BGP_STR
a636c635 10133 BGP_INSTANCE_HELP_STR
4f280b15 10134 BGP_AFI_HELP_STR
4dd6177e 10135 BGP_SAFI_WITH_LABEL_HELP_STR
a636c635 10136 "Display detailed information about dampening\n"
af462945 10137 "Display detail of configured dampening parameters\n"
a636c635
DW
10138 "Display routes matching the route-map\n"
10139 "A route-map to match on\n"
10140 "Display routes conforming to the prefix-list\n"
8c3deaae 10141 "Prefix-list name\n"
a636c635
DW
10142 "Display routes conforming to the filter-list\n"
10143 "Regular expression access list name\n"
e01ca200 10144 "BGP RIB advertisement statistics\n"
a636c635
DW
10145 "Display routes matching the community-list\n"
10146 "community-list number\n"
10147 "community-list name\n"
10148 "Exact match of the communities\n"
0c7b1b01 10149 "IPv4 prefix\n"
8c3deaae 10150 "Display route and more specific routes\n"
0c7b1b01 10151 "IPv6 prefix\n"
7b2ff250 10152 "Display route and more specific routes\n")
718e3744 10153{
d62a17ae 10154 afi_t afi = AFI_IP6;
10155 safi_t safi = SAFI_UNICAST;
10156 int exact_match = 0;
d62a17ae 10157 struct bgp *bgp = NULL;
10158 int idx = 0;
10159
10160 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10161 &bgp, false);
d62a17ae 10162 if (!idx)
10163 return CMD_WARNING;
10164
d62a17ae 10165 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 10166 if (argv_find(argv, argc, "parameters", &idx))
d62a17ae 10167 return bgp_show_dampening_parameters(vty, afi, safi);
10168 }
c016b6c7 10169
d62a17ae 10170 if (argv_find(argv, argc, "prefix-list", &idx))
10171 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
10172 safi, bgp_show_type_prefix_list);
10173
10174 if (argv_find(argv, argc, "filter-list", &idx))
10175 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
10176 safi, bgp_show_type_filter_list);
10177
10178 if (argv_find(argv, argc, "statistics", &idx))
10179 return bgp_table_stats(vty, bgp, afi, safi);
10180
10181 if (argv_find(argv, argc, "route-map", &idx))
10182 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
10183 safi, bgp_show_type_route_map);
10184
d62a17ae 10185 if (argv_find(argv, argc, "community-list", &idx)) {
10186 const char *clist_number_or_name = argv[++idx]->arg;
10187 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10188 exact_match = 1;
10189 return bgp_show_community_list(vty, bgp, clist_number_or_name,
10190 exact_match, afi, safi);
10191 }
10192 /* prefix-longer */
10193 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10194 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10195 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
10196 safi,
10197 bgp_show_type_prefix_longer);
10198
7b2ff250
DW
10199 return CMD_WARNING;
10200}
10201
10202/* BGP route print out function with JSON */
10203DEFUN (show_ip_bgp_json,
10204 show_ip_bgp_json_cmd,
10205 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
cf4898bc
QY
10206 [cidr-only\
10207 |dampening <flap-statistics|dampened-paths>\
10208 |community [AA:NN|local-AS|no-advertise|no-export\
10209 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10210 |accept-own|accept-own-nexthop|route-filter-v6\
10211 |route-filter-v4|route-filter-translated-v6\
10212 |route-filter-translated-v4] [exact-match]\
10213 ] [json]",
7b2ff250
DW
10214 SHOW_STR
10215 IP_STR
10216 BGP_STR
10217 BGP_INSTANCE_HELP_STR
10218 BGP_AFI_HELP_STR
10219 BGP_SAFI_WITH_LABEL_HELP_STR
10220 "Display only routes with non-natural netmasks\n"
10221 "Display detailed information about dampening\n"
10222 "Display flap statistics of routes\n"
10223 "Display paths suppressed due to dampening\n"
10224 "Display routes matching the communities\n"
d0086e8e
AD
10225 COMMUNITY_AANN_STR
10226 "Do not send outside local AS (well-known community)\n"
10227 "Do not advertise to any peer (well-known community)\n"
10228 "Do not export to next AS (well-known community)\n"
10229 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
10230 "Do not export to any peer (well-known community)\n"
10231 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10232 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10233 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10234 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10235 "Should accept VPN route with local nexthop (well-known community)\n"
10236 "RT VPNv6 route filtering (well-known community)\n"
10237 "RT VPNv4 route filtering (well-known community)\n"
10238 "RT translated VPNv6 route filtering (well-known community)\n"
10239 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 10240 "Exact match of the communities\n"
7b2ff250
DW
10241 JSON_STR)
10242{
10243 afi_t afi = AFI_IP6;
10244 safi_t safi = SAFI_UNICAST;
10245 enum bgp_show_type sh_type = bgp_show_type_normal;
10246 struct bgp *bgp = NULL;
10247 int idx = 0;
d0086e8e 10248 int exact_match = 0;
9f049418
DS
10249 bool uj = use_json(argc, argv);
10250
10251 if (uj)
10252 argc--;
7b2ff250
DW
10253
10254 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10255 &bgp, uj);
7b2ff250
DW
10256 if (!idx)
10257 return CMD_WARNING;
10258
7b2ff250
DW
10259 if (argv_find(argv, argc, "cidr-only", &idx))
10260 return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
10261 NULL, uj);
10262
10263 if (argv_find(argv, argc, "dampening", &idx)) {
10264 if (argv_find(argv, argc, "dampened-paths", &idx))
10265 return bgp_show(vty, bgp, afi, safi,
10266 bgp_show_type_dampend_paths, NULL, uj);
10267 else if (argv_find(argv, argc, "flap-statistics", &idx))
10268 return bgp_show(vty, bgp, afi, safi,
10269 bgp_show_type_flap_statistics, NULL,
10270 uj);
10271 }
10272
10273 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 10274 char *maybecomm = NULL;
cf4898bc 10275 char *community = NULL;
d0086e8e 10276
79bc257a
RW
10277 if (idx + 1 < argc) {
10278 if (argv[idx + 1]->type == VARIABLE_TKN)
10279 maybecomm = argv[idx + 1]->arg;
10280 else
10281 maybecomm = argv[idx + 1]->text;
10282 }
10283
cf4898bc
QY
10284 if (maybecomm && !strmatch(maybecomm, "json")
10285 && !strmatch(maybecomm, "exact-match"))
10286 community = maybecomm;
d0086e8e 10287
cf4898bc
QY
10288 if (argv_find(argv, argc, "exact-match", &idx))
10289 exact_match = 1;
d0086e8e 10290
cf4898bc
QY
10291 if (community)
10292 return bgp_show_community(vty, bgp, community,
10293 exact_match, afi, safi, uj);
10294 else
d0086e8e 10295 return (bgp_show(vty, bgp, afi, safi,
cf4898bc
QY
10296 bgp_show_type_community_all, NULL,
10297 uj));
7b2ff250 10298 }
d0086e8e 10299
1ae44dfc 10300 return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj);
a636c635 10301}
47fc97cc 10302
718e3744 10303DEFUN (show_ip_bgp_route,
10304 show_ip_bgp_route_cmd,
4dd6177e 10305 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]"
ae19d7dd 10306 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
718e3744 10307 SHOW_STR
10308 IP_STR
10309 BGP_STR
a636c635 10310 BGP_INSTANCE_HELP_STR
4f280b15 10311 BGP_AFI_HELP_STR
4dd6177e 10312 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 10313 "Network in the BGP routing table to display\n"
0c7b1b01 10314 "IPv4 prefix\n"
8c3deaae 10315 "Network in the BGP routing table to display\n"
0c7b1b01 10316 "IPv6 prefix\n"
4092b06c 10317 "Display only the bestpath\n"
b05a1c8b 10318 "Display only multipaths\n"
9973d184 10319 JSON_STR)
4092b06c 10320{
d62a17ae 10321 int prefix_check = 0;
ae19d7dd 10322
d62a17ae 10323 afi_t afi = AFI_IP6;
10324 safi_t safi = SAFI_UNICAST;
10325 char *prefix = NULL;
10326 struct bgp *bgp = NULL;
10327 enum bgp_path_type path_type;
9f049418 10328 bool uj = use_json(argc, argv);
b05a1c8b 10329
d62a17ae 10330 int idx = 0;
ae19d7dd 10331
d62a17ae 10332 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10333 &bgp, uj);
d62a17ae 10334 if (!idx)
10335 return CMD_WARNING;
c41247f5 10336
d62a17ae 10337 if (!bgp) {
10338 vty_out(vty,
10339 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10340 return CMD_WARNING;
10341 }
a636c635 10342
d62a17ae 10343 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10344 if (argv_find(argv, argc, "A.B.C.D", &idx)
10345 || argv_find(argv, argc, "X:X::X:X", &idx))
10346 prefix_check = 0;
10347 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10348 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10349 prefix_check = 1;
10350
10351 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
10352 && afi != AFI_IP6) {
10353 vty_out(vty,
10354 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10355 return CMD_WARNING;
10356 }
10357 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
10358 && afi != AFI_IP) {
10359 vty_out(vty,
10360 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10361 return CMD_WARNING;
10362 }
10363
10364 prefix = argv[idx]->arg;
10365
10366 /* [<bestpath|multipath>] */
10367 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 10368 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 10369 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 10370 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 10371 else
360660c6 10372 path_type = BGP_PATH_SHOW_ALL;
a636c635 10373
d62a17ae 10374 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
10375 path_type, uj);
4092b06c
DS
10376}
10377
8c3deaae
QY
10378DEFUN (show_ip_bgp_regexp,
10379 show_ip_bgp_regexp_cmd,
4dd6177e 10380 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX...",
8c3deaae
QY
10381 SHOW_STR
10382 IP_STR
10383 BGP_STR
b00b230a 10384 BGP_INSTANCE_HELP_STR
4f280b15 10385 BGP_AFI_HELP_STR
4dd6177e 10386 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 10387 "Display routes matching the AS path regular expression\n"
a818ea74 10388 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n")
8c3deaae 10389{
d62a17ae 10390 afi_t afi = AFI_IP6;
10391 safi_t safi = SAFI_UNICAST;
10392 struct bgp *bgp = NULL;
8c3deaae 10393
d62a17ae 10394 int idx = 0;
10395 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10396 &bgp, false);
d62a17ae 10397 if (!idx)
10398 return CMD_WARNING;
8c3deaae 10399
d62a17ae 10400 // get index of regex
10401 argv_find(argv, argc, "regexp", &idx);
10402 idx++;
8c3deaae 10403
d62a17ae 10404 char *regstr = argv_concat(argv, argc, idx);
e889891d 10405 int rc = bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
d62a17ae 10406 bgp_show_type_regexp);
10407 XFREE(MTYPE_TMP, regstr);
10408 return rc;
8c3deaae
QY
10409}
10410
a636c635
DW
10411DEFUN (show_ip_bgp_instance_all,
10412 show_ip_bgp_instance_all_cmd,
4dd6177e 10413 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json]",
4092b06c 10414 SHOW_STR
a636c635 10415 IP_STR
4092b06c 10416 BGP_STR
a636c635 10417 BGP_INSTANCE_ALL_HELP_STR
4f280b15 10418 BGP_AFI_HELP_STR
4dd6177e 10419 BGP_SAFI_WITH_LABEL_HELP_STR
9973d184 10420 JSON_STR)
4092b06c 10421{
d62a17ae 10422 afi_t afi = AFI_IP;
10423 safi_t safi = SAFI_UNICAST;
10424 struct bgp *bgp = NULL;
d62a17ae 10425 int idx = 0;
9f049418 10426 bool uj = use_json(argc, argv);
ae19d7dd 10427
d62a17ae 10428 if (uj)
10429 argc--;
e3e29b32 10430
9f049418
DS
10431 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10432 &bgp, uj);
10433 if (!idx)
10434 return CMD_WARNING;
10435
d62a17ae 10436 bgp_show_all_instances_routes_vty(vty, afi, safi, uj);
10437 return CMD_SUCCESS;
e3e29b32
LB
10438}
10439
a4d82a8a
PZ
10440static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
10441 afi_t afi, safi_t safi, enum bgp_show_type type)
718e3744 10442{
d62a17ae 10443 regex_t *regex;
10444 int rc;
e3e29b32 10445
c3900853
DA
10446 if (!config_bgp_aspath_validate(regstr)) {
10447 vty_out(vty, "Invalid character in as-path access-list %s\n",
10448 regstr);
10449 return CMD_WARNING_CONFIG_FAILED;
10450 }
10451
d62a17ae 10452 regex = bgp_regcomp(regstr);
10453 if (!regex) {
10454 vty_out(vty, "Can't compile regexp %s\n", regstr);
10455 return CMD_WARNING;
10456 }
a636c635 10457
e889891d 10458 rc = bgp_show(vty, bgp, afi, safi, type, regex, 0);
d62a17ae 10459 bgp_regex_free(regex);
10460 return rc;
e3e29b32
LB
10461}
10462
d62a17ae 10463static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10464 const char *prefix_list_str, afi_t afi,
10465 safi_t safi, enum bgp_show_type type)
e3e29b32 10466{
d62a17ae 10467 struct prefix_list *plist;
718e3744 10468
d62a17ae 10469 plist = prefix_list_lookup(afi, prefix_list_str);
10470 if (plist == NULL) {
10471 vty_out(vty, "%% %s is not a valid prefix-list name\n",
10472 prefix_list_str);
10473 return CMD_WARNING;
10474 }
718e3744 10475
d62a17ae 10476 return bgp_show(vty, bgp, afi, safi, type, plist, 0);
4092b06c
DS
10477}
10478
d62a17ae 10479static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10480 const char *filter, afi_t afi, safi_t safi,
10481 enum bgp_show_type type)
4092b06c 10482{
d62a17ae 10483 struct as_list *as_list;
718e3744 10484
d62a17ae 10485 as_list = as_list_lookup(filter);
10486 if (as_list == NULL) {
10487 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
10488 filter);
10489 return CMD_WARNING;
10490 }
a636c635 10491
d62a17ae 10492 return bgp_show(vty, bgp, afi, safi, type, as_list, 0);
718e3744 10493}
10494
d62a17ae 10495static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10496 const char *rmap_str, afi_t afi, safi_t safi,
10497 enum bgp_show_type type)
718e3744 10498{
d62a17ae 10499 struct route_map *rmap;
bb46e94f 10500
d62a17ae 10501 rmap = route_map_lookup_by_name(rmap_str);
10502 if (!rmap) {
10503 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
10504 return CMD_WARNING;
10505 }
10506
10507 return bgp_show(vty, bgp, afi, safi, type, rmap, 0);
10508}
10509
7f323236
DW
10510static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10511 const char *comstr, int exact, afi_t afi,
9f049418 10512 safi_t safi, bool use_json)
d62a17ae 10513{
10514 struct community *com;
d62a17ae 10515 int ret = 0;
10516
7f323236 10517 com = community_str2com(comstr);
d62a17ae 10518 if (!com) {
7f323236 10519 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 10520 return CMD_WARNING;
10521 }
10522
10523 ret = bgp_show(vty, bgp, afi, safi,
10524 (exact ? bgp_show_type_community_exact
10525 : bgp_show_type_community),
d0086e8e 10526 com, use_json);
3c1f53de 10527 community_free(&com);
46c3ce83 10528
d62a17ae 10529 return ret;
718e3744 10530}
10531
d62a17ae 10532static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10533 const char *com, int exact, afi_t afi,
10534 safi_t safi)
50ef26d4 10535{
d62a17ae 10536 struct community_list *list;
50ef26d4 10537
e237b0d2 10538 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 10539 if (list == NULL) {
10540 vty_out(vty, "%% %s is not a valid community-list name\n", com);
10541 return CMD_WARNING;
10542 }
718e3744 10543
d62a17ae 10544 return bgp_show(vty, bgp, afi, safi,
10545 (exact ? bgp_show_type_community_list_exact
10546 : bgp_show_type_community_list),
10547 list, 0);
50ef26d4 10548}
10549
d62a17ae 10550static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10551 const char *prefix, afi_t afi, safi_t safi,
10552 enum bgp_show_type type)
718e3744 10553{
d62a17ae 10554 int ret;
10555 struct prefix *p;
47fc97cc 10556
d62a17ae 10557 p = prefix_new();
95cbbd2a 10558
d62a17ae 10559 ret = str2prefix(prefix, p);
10560 if (!ret) {
10561 vty_out(vty, "%% Malformed Prefix\n");
10562 return CMD_WARNING;
10563 }
47e9b292 10564
d62a17ae 10565 ret = bgp_show(vty, bgp, afi, safi, type, p, 0);
63265b5c 10566 prefix_free(&p);
d62a17ae 10567 return ret;
10568}
10569
d62a17ae 10570enum bgp_stats {
10571 BGP_STATS_MAXBITLEN = 0,
10572 BGP_STATS_RIB,
10573 BGP_STATS_PREFIXES,
10574 BGP_STATS_TOTPLEN,
10575 BGP_STATS_UNAGGREGATEABLE,
10576 BGP_STATS_MAX_AGGREGATEABLE,
10577 BGP_STATS_AGGREGATES,
10578 BGP_STATS_SPACE,
10579 BGP_STATS_ASPATH_COUNT,
10580 BGP_STATS_ASPATH_MAXHOPS,
10581 BGP_STATS_ASPATH_TOTHOPS,
10582 BGP_STATS_ASPATH_MAXSIZE,
10583 BGP_STATS_ASPATH_TOTSIZE,
10584 BGP_STATS_ASN_HIGHEST,
10585 BGP_STATS_MAX,
a636c635 10586};
2815e61f 10587
d62a17ae 10588static const char *table_stats_strs[] = {
9d303b37
DL
10589 [BGP_STATS_PREFIXES] = "Total Prefixes",
10590 [BGP_STATS_TOTPLEN] = "Average prefix length",
10591 [BGP_STATS_RIB] = "Total Advertisements",
10592 [BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes",
10593 [BGP_STATS_MAX_AGGREGATEABLE] =
10594 "Maximum aggregateable prefixes",
10595 [BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements",
10596 [BGP_STATS_SPACE] = "Address space advertised",
10597 [BGP_STATS_ASPATH_COUNT] = "Advertisements with paths",
10598 [BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)",
10599 [BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)",
10600 [BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)",
10601 [BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)",
10602 [BGP_STATS_ASN_HIGHEST] = "Highest public ASN",
10603 [BGP_STATS_MAX] = NULL,
a636c635 10604};
2815e61f 10605
d62a17ae 10606struct bgp_table_stats {
10607 struct bgp_table *table;
10608 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 10609 double total_space;
ff7924f6
PJ
10610};
10611
a636c635
DW
10612#if 0
10613#define TALLY_SIGFIG 100000
10614static unsigned long
10615ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 10616{
a636c635
DW
10617 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
10618 unsigned long res = (newtot * TALLY_SIGFIG) / count;
10619 unsigned long ret = newtot / count;
07d0c4ed 10620
a636c635
DW
10621 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
10622 return ret + 1;
10623 else
10624 return ret;
10625}
10626#endif
ff7924f6 10627
9c14ec72
RW
10628static void bgp_table_stats_rn(struct bgp_node *rn, struct bgp_node *top,
10629 struct bgp_table_stats *ts, unsigned int space)
2815e61f 10630{
9c14ec72
RW
10631 struct bgp_node *prn = bgp_node_parent_nolock(rn);
10632 struct bgp_path_info *pi;
d62a17ae 10633
9c14ec72
RW
10634 if (rn == top)
10635 return;
d62a17ae 10636
9c14ec72
RW
10637 if (!bgp_node_has_bgp_path_info_data(rn))
10638 return;
d62a17ae 10639
9c14ec72
RW
10640 ts->counts[BGP_STATS_PREFIXES]++;
10641 ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
ff7924f6 10642
a636c635
DW
10643#if 0
10644 ts->counts[BGP_STATS_AVGPLEN]
10645 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
10646 ts->counts[BGP_STATS_AVGPLEN],
10647 rn->p.prefixlen);
10648#endif
d62a17ae 10649
9c14ec72
RW
10650 /* check if the prefix is included by any other announcements */
10651 while (prn && !bgp_node_has_bgp_path_info_data(prn))
10652 prn = bgp_node_parent_nolock(prn);
d62a17ae 10653
9c14ec72
RW
10654 if (prn == NULL || prn == top) {
10655 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
10656 /* announced address space */
10657 if (space)
10658 ts->total_space += pow(2.0, space - rn->p.prefixlen);
10659 } else if (bgp_node_has_bgp_path_info_data(prn))
10660 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 10661
9c14ec72
RW
10662
10663 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
10664 ts->counts[BGP_STATS_RIB]++;
10665
05864da7
DS
10666 if (CHECK_FLAG(pi->attr->flag,
10667 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
10668 ts->counts[BGP_STATS_AGGREGATES]++;
10669
10670 /* as-path stats */
05864da7 10671 if (pi->attr->aspath) {
9c14ec72
RW
10672 unsigned int hops = aspath_count_hops(pi->attr->aspath);
10673 unsigned int size = aspath_size(pi->attr->aspath);
10674 as_t highest = aspath_highest(pi->attr->aspath);
10675
10676 ts->counts[BGP_STATS_ASPATH_COUNT]++;
10677
10678 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
10679 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
10680
10681 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
10682 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
10683
10684 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
10685 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 10686#if 0
07d0c4ed 10687 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
10688 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
10689 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
10690 hops);
10691 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
10692 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
10693 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
10694 size);
10695#endif
9c14ec72
RW
10696 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
10697 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
10698 }
10699 }
10700}
10701
10702static int bgp_table_stats_walker(struct thread *t)
10703{
10704 struct bgp_node *rn, *nrn;
10705 struct bgp_node *top;
10706 struct bgp_table_stats *ts = THREAD_ARG(t);
10707 unsigned int space = 0;
10708
10709 if (!(top = bgp_table_top(ts->table)))
10710 return 0;
10711
10712 switch (ts->table->afi) {
10713 case AFI_IP:
10714 space = IPV4_MAX_BITLEN;
10715 break;
10716 case AFI_IP6:
10717 space = IPV6_MAX_BITLEN;
10718 break;
10719 default:
10720 return 0;
10721 }
10722
10723 ts->counts[BGP_STATS_MAXBITLEN] = space;
10724
10725 for (rn = top; rn; rn = bgp_route_next(rn)) {
10726 if (ts->table->safi == SAFI_MPLS_VPN) {
10727 struct bgp_table *table;
10728
10729 table = bgp_node_get_bgp_table_info(rn);
10730 if (!table)
10731 continue;
10732
10733 top = bgp_table_top(table);
10734 for (nrn = bgp_table_top(table); nrn;
10735 nrn = bgp_route_next(nrn))
10736 bgp_table_stats_rn(nrn, top, ts, space);
10737 } else {
10738 bgp_table_stats_rn(rn, top, ts, space);
d62a17ae 10739 }
10740 }
9c14ec72 10741
d62a17ae 10742 return 0;
2815e61f 10743}
ff7924f6 10744
d62a17ae 10745static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
10746 safi_t safi)
2815e61f 10747{
d62a17ae 10748 struct bgp_table_stats ts;
10749 unsigned int i;
019386c2 10750
d62a17ae 10751 if (!bgp->rib[afi][safi]) {
10752 vty_out(vty, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10753 afi, safi);
10754 return CMD_WARNING;
10755 }
019386c2 10756
5cb5f4d0 10757 vty_out(vty, "BGP %s RIB statistics\n", get_afi_safi_str(afi, safi, false));
019386c2 10758
d62a17ae 10759 /* labeled-unicast routes live in the unicast table */
10760 if (safi == SAFI_LABELED_UNICAST)
10761 safi = SAFI_UNICAST;
019386c2 10762
d62a17ae 10763 memset(&ts, 0, sizeof(ts));
10764 ts.table = bgp->rib[afi][safi];
10765 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 10766
d62a17ae 10767 for (i = 0; i < BGP_STATS_MAX; i++) {
10768 if (!table_stats_strs[i])
10769 continue;
10770
10771 switch (i) {
a636c635
DW
10772#if 0
10773 case BGP_STATS_ASPATH_AVGHOPS:
10774 case BGP_STATS_ASPATH_AVGSIZE:
10775 case BGP_STATS_AVGPLEN:
10776 vty_out (vty, "%-30s: ", table_stats_strs[i]);
10777 vty_out (vty, "%12.2f",
10778 (float)ts.counts[i] / (float)TALLY_SIGFIG);
10779 break;
10780#endif
d62a17ae 10781 case BGP_STATS_ASPATH_TOTHOPS:
10782 case BGP_STATS_ASPATH_TOTSIZE:
10783 vty_out(vty, "%-30s: ", table_stats_strs[i]);
10784 vty_out(vty, "%12.2f",
10785 ts.counts[i]
10786 ? (float)ts.counts[i]
10787 / (float)ts.counts
10788 [BGP_STATS_ASPATH_COUNT]
10789 : 0);
10790 break;
10791 case BGP_STATS_TOTPLEN:
10792 vty_out(vty, "%-30s: ", table_stats_strs[i]);
10793 vty_out(vty, "%12.2f",
10794 ts.counts[i]
10795 ? (float)ts.counts[i]
10796 / (float)ts.counts
10797 [BGP_STATS_PREFIXES]
10798 : 0);
10799 break;
10800 case BGP_STATS_SPACE:
10801 vty_out(vty, "%-30s: ", table_stats_strs[i]);
8d0ab76d
DL
10802 vty_out(vty, "%12g\n", ts.total_space);
10803
10804 if (afi == AFI_IP6) {
10805 vty_out(vty, "%30s: ", "/32 equivalent ");
10806 vty_out(vty, "%12g\n",
a4d82a8a 10807 ts.total_space * pow(2.0, -128 + 32));
8d0ab76d
DL
10808 vty_out(vty, "%30s: ", "/48 equivalent ");
10809 vty_out(vty, "%12g\n",
a4d82a8a 10810 ts.total_space * pow(2.0, -128 + 48));
8d0ab76d
DL
10811 } else {
10812 vty_out(vty, "%30s: ", "% announced ");
10813 vty_out(vty, "%12.2f\n",
10814 ts.total_space * 100. * pow(2.0, -32));
10815 vty_out(vty, "%30s: ", "/8 equivalent ");
10816 vty_out(vty, "%12.2f\n",
a4d82a8a 10817 ts.total_space * pow(2.0, -32 + 8));
8d0ab76d
DL
10818 vty_out(vty, "%30s: ", "/24 equivalent ");
10819 vty_out(vty, "%12.2f\n",
a4d82a8a 10820 ts.total_space * pow(2.0, -32 + 24));
8d0ab76d 10821 }
d62a17ae 10822 break;
10823 default:
10824 vty_out(vty, "%-30s: ", table_stats_strs[i]);
10825 vty_out(vty, "%12llu", ts.counts[i]);
10826 }
ff7924f6 10827
d62a17ae 10828 vty_out(vty, "\n");
10829 }
10830 return CMD_SUCCESS;
10831}
10832
10833enum bgp_pcounts {
10834 PCOUNT_ADJ_IN = 0,
10835 PCOUNT_DAMPED,
10836 PCOUNT_REMOVED,
10837 PCOUNT_HISTORY,
10838 PCOUNT_STALE,
10839 PCOUNT_VALID,
10840 PCOUNT_ALL,
10841 PCOUNT_COUNTED,
10842 PCOUNT_PFCNT, /* the figure we display to users */
10843 PCOUNT_MAX,
a636c635 10844};
718e3744 10845
d62a17ae 10846static const char *pcount_strs[] = {
9d303b37
DL
10847 [PCOUNT_ADJ_IN] = "Adj-in",
10848 [PCOUNT_DAMPED] = "Damped",
10849 [PCOUNT_REMOVED] = "Removed",
10850 [PCOUNT_HISTORY] = "History",
10851 [PCOUNT_STALE] = "Stale",
10852 [PCOUNT_VALID] = "Valid",
10853 [PCOUNT_ALL] = "All RIB",
10854 [PCOUNT_COUNTED] = "PfxCt counted",
10855 [PCOUNT_PFCNT] = "Useable",
10856 [PCOUNT_MAX] = NULL,
a636c635 10857};
718e3744 10858
d62a17ae 10859struct peer_pcounts {
10860 unsigned int count[PCOUNT_MAX];
10861 const struct peer *peer;
10862 const struct bgp_table *table;
a636c635 10863};
47fc97cc 10864
d62a17ae 10865static int bgp_peer_count_walker(struct thread *t)
10866{
10867 struct bgp_node *rn;
10868 struct peer_pcounts *pc = THREAD_ARG(t);
10869 const struct peer *peer = pc->peer;
10870
10871 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn)) {
10872 struct bgp_adj_in *ain;
40381db7 10873 struct bgp_path_info *pi;
d62a17ae 10874
10875 for (ain = rn->adj_in; ain; ain = ain->next)
10876 if (ain->peer == peer)
10877 pc->count[PCOUNT_ADJ_IN]++;
10878
6f94b685
DS
10879 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
10880
40381db7 10881 if (pi->peer != peer)
d62a17ae 10882 continue;
10883
10884 pc->count[PCOUNT_ALL]++;
10885
40381db7 10886 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
d62a17ae 10887 pc->count[PCOUNT_DAMPED]++;
40381db7 10888 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
d62a17ae 10889 pc->count[PCOUNT_HISTORY]++;
40381db7 10890 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
d62a17ae 10891 pc->count[PCOUNT_REMOVED]++;
40381db7 10892 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 10893 pc->count[PCOUNT_STALE]++;
40381db7 10894 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
d62a17ae 10895 pc->count[PCOUNT_VALID]++;
40381db7 10896 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
d62a17ae 10897 pc->count[PCOUNT_PFCNT]++;
10898
40381db7 10899 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 10900 pc->count[PCOUNT_COUNTED]++;
40381db7 10901 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
1c50c1c0
QY
10902 flog_err(
10903 EC_LIB_DEVELOPMENT,
10904 "Attempting to count but flags say it is unusable");
d62a17ae 10905 } else {
40381db7 10906 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
1c50c1c0
QY
10907 flog_err(
10908 EC_LIB_DEVELOPMENT,
10909 "Not counted but flags say we should");
d62a17ae 10910 }
10911 }
10912 }
10913 return 0;
718e3744 10914}
10915
d62a17ae 10916static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 10917 safi_t safi, bool use_json)
856ca177 10918{
d62a17ae 10919 struct peer_pcounts pcounts = {.peer = peer};
10920 unsigned int i;
10921 json_object *json = NULL;
10922 json_object *json_loop = NULL;
856ca177 10923
d62a17ae 10924 if (use_json) {
10925 json = json_object_new_object();
10926 json_loop = json_object_new_object();
10927 }
718e3744 10928
d62a17ae 10929 if (!peer || !peer->bgp || !peer->afc[afi][safi]
10930 || !peer->bgp->rib[afi][safi]) {
10931 if (use_json) {
10932 json_object_string_add(
10933 json, "warning",
10934 "No such neighbor or address family");
10935 vty_out(vty, "%s\n", json_object_to_json_string(json));
10936 json_object_free(json);
10937 } else
10938 vty_out(vty, "%% No such neighbor or address family\n");
10939
10940 return CMD_WARNING;
10941 }
2a71e9ce 10942
d62a17ae 10943 memset(&pcounts, 0, sizeof(pcounts));
10944 pcounts.peer = peer;
10945 pcounts.table = peer->bgp->rib[afi][safi];
10946
10947 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
10948 * stats for the thread-walk (i.e. ensure this can't be blamed on
10949 * on just vty_read()).
10950 */
d62a17ae 10951 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
10952
10953 if (use_json) {
10954 json_object_string_add(json, "prefixCountsFor", peer->host);
10955 json_object_string_add(json, "multiProtocol",
5cb5f4d0 10956 get_afi_safi_str(afi, safi, true));
d62a17ae 10957 json_object_int_add(json, "pfxCounter",
10958 peer->pcount[afi][safi]);
10959
10960 for (i = 0; i < PCOUNT_MAX; i++)
10961 json_object_int_add(json_loop, pcount_strs[i],
10962 pcounts.count[i]);
10963
10964 json_object_object_add(json, "ribTableWalkCounters", json_loop);
10965
10966 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
10967 json_object_string_add(json, "pfxctDriftFor",
10968 peer->host);
10969 json_object_string_add(
10970 json, "recommended",
10971 "Please report this bug, with the above command output");
10972 }
996c9314
LB
10973 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10974 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 10975 json_object_free(json);
10976 } else {
10977
10978 if (peer->hostname
10979 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
10980 vty_out(vty, "Prefix counts for %s/%s, %s\n",
10981 peer->hostname, peer->host,
5cb5f4d0 10982 get_afi_safi_str(afi, safi, false));
d62a17ae 10983 } else {
10984 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 10985 get_afi_safi_str(afi, safi, false));
d62a17ae 10986 }
10987
a0a87037 10988 vty_out(vty, "PfxCt: %" PRIu32 "\n", peer->pcount[afi][safi]);
d62a17ae 10989 vty_out(vty, "\nCounts from RIB table walk:\n\n");
10990
10991 for (i = 0; i < PCOUNT_MAX; i++)
10992 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
10993 pcounts.count[i]);
10994
10995 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
10996 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
10997 vty_out(vty,
10998 "Please report this bug, with the above command output\n");
10999 }
11000 }
11001
11002 return CMD_SUCCESS;
718e3744 11003}
11004
a636c635
DW
11005DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
11006 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
c1a44e43 11007 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] "
30a6a167 11008 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
718e3744 11009 SHOW_STR
11010 IP_STR
11011 BGP_STR
8386ac43 11012 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
11013 BGP_AFI_HELP_STR
11014 BGP_SAFI_HELP_STR
0b16f239
DS
11015 "Detailed information on TCP and BGP neighbor connections\n"
11016 "Neighbor to display information about\n"
11017 "Neighbor to display information about\n"
91d37724 11018 "Neighbor on BGP configured interface\n"
a636c635 11019 "Display detailed prefix count information\n"
9973d184 11020 JSON_STR)
0b16f239 11021{
d62a17ae 11022 afi_t afi = AFI_IP6;
11023 safi_t safi = SAFI_UNICAST;
11024 struct peer *peer;
11025 int idx = 0;
11026 struct bgp *bgp = NULL;
9f049418
DS
11027 bool uj = use_json(argc, argv);
11028
11029 if (uj)
11030 argc--;
856ca177 11031
d62a17ae 11032 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11033 &bgp, uj);
d62a17ae 11034 if (!idx)
11035 return CMD_WARNING;
0b16f239 11036
d62a17ae 11037 argv_find(argv, argc, "neighbors", &idx);
11038 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
11039 if (!peer)
11040 return CMD_WARNING;
bb46e94f 11041
29c8d9da 11042 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 11043}
0b16f239 11044
d6902373
PG
11045#ifdef KEEP_OLD_VPN_COMMANDS
11046DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
11047 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
11048 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
11049 SHOW_STR
11050 IP_STR
11051 BGP_STR
d6902373 11052 BGP_VPNVX_HELP_STR
91d37724 11053 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
11054 "Detailed information on TCP and BGP neighbor connections\n"
11055 "Neighbor to display information about\n"
11056 "Neighbor to display information about\n"
91d37724 11057 "Neighbor on BGP configured interface\n"
a636c635 11058 "Display detailed prefix count information\n"
9973d184 11059 JSON_STR)
a636c635 11060{
d62a17ae 11061 int idx_peer = 6;
11062 struct peer *peer;
9f049418 11063 bool uj = use_json(argc, argv);
a636c635 11064
d62a17ae 11065 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
11066 if (!peer)
11067 return CMD_WARNING;
11068
11069 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
11070}
11071
d6902373
PG
11072DEFUN (show_ip_bgp_vpn_all_route_prefix,
11073 show_ip_bgp_vpn_all_route_prefix_cmd,
11074 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
11075 SHOW_STR
11076 IP_STR
11077 BGP_STR
d6902373 11078 BGP_VPNVX_HELP_STR
91d37724
QY
11079 "Display information about all VPNv4 NLRIs\n"
11080 "Network in the BGP routing table to display\n"
3a2d747c 11081 "Network in the BGP routing table to display\n"
9973d184 11082 JSON_STR)
91d37724 11083{
d62a17ae 11084 int idx = 0;
11085 char *network = NULL;
11086 struct bgp *bgp = bgp_get_default();
11087 if (!bgp) {
11088 vty_out(vty, "Can't find default instance\n");
11089 return CMD_WARNING;
11090 }
87e34b58 11091
d62a17ae 11092 if (argv_find(argv, argc, "A.B.C.D", &idx))
11093 network = argv[idx]->arg;
11094 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
11095 network = argv[idx]->arg;
11096 else {
11097 vty_out(vty, "Unable to figure out Network\n");
11098 return CMD_WARNING;
11099 }
87e34b58 11100
d62a17ae 11101 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 11102 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 11103}
d6902373 11104#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 11105
44c69747
LK
11106DEFUN (show_bgp_l2vpn_evpn_route_prefix,
11107 show_bgp_l2vpn_evpn_route_prefix_cmd,
11108 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 11109 SHOW_STR
4c63a661
PG
11110 BGP_STR
11111 L2VPN_HELP_STR
11112 EVPN_HELP_STR
44c69747
LK
11113 "Network in the BGP routing table to display\n"
11114 "Network in the BGP routing table to display\n"
4c63a661
PG
11115 "Network in the BGP routing table to display\n"
11116 "Network in the BGP routing table to display\n"
11117 JSON_STR)
11118{
d62a17ae 11119 int idx = 0;
11120 char *network = NULL;
44c69747 11121 int prefix_check = 0;
a636c635 11122
44c69747
LK
11123 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
11124 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 11125 network = argv[idx]->arg;
44c69747 11126 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 11127 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 11128 network = argv[idx]->arg;
44c69747
LK
11129 prefix_check = 1;
11130 } else {
d62a17ae 11131 vty_out(vty, "Unable to figure out Network\n");
11132 return CMD_WARNING;
11133 }
44c69747
LK
11134 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
11135 prefix_check, BGP_PATH_SHOW_ALL,
11136 use_json(argc, argv));
d62a17ae 11137}
11138
11139static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 11140 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 11141 const char *rmap_name, bool use_json,
6392aaa6 11142 json_object *json)
d62a17ae 11143{
11144 struct bgp_table *table;
11145 struct bgp_adj_in *ain;
11146 struct bgp_adj_out *adj;
11147 unsigned long output_count;
11148 unsigned long filtered_count;
11149 struct bgp_node *rn;
11150 int header1 = 1;
11151 struct bgp *bgp;
11152 int header2 = 1;
11153 struct attr attr;
11154 int ret;
11155 struct update_subgroup *subgrp;
11156 json_object *json_scode = NULL;
11157 json_object *json_ocode = NULL;
11158 json_object *json_ar = NULL;
11159 struct peer_af *paf;
f99def61 11160 bool route_filtered;
d62a17ae 11161
11162 if (use_json) {
11163 json_scode = json_object_new_object();
11164 json_ocode = json_object_new_object();
11165 json_ar = json_object_new_object();
11166
11167 json_object_string_add(json_scode, "suppressed", "s");
11168 json_object_string_add(json_scode, "damped", "d");
11169 json_object_string_add(json_scode, "history", "h");
11170 json_object_string_add(json_scode, "valid", "*");
11171 json_object_string_add(json_scode, "best", ">");
11172 json_object_string_add(json_scode, "multipath", "=");
11173 json_object_string_add(json_scode, "internal", "i");
11174 json_object_string_add(json_scode, "ribFailure", "r");
11175 json_object_string_add(json_scode, "stale", "S");
11176 json_object_string_add(json_scode, "removed", "R");
11177
11178 json_object_string_add(json_ocode, "igp", "i");
11179 json_object_string_add(json_ocode, "egp", "e");
11180 json_object_string_add(json_ocode, "incomplete", "?");
11181 }
a636c635 11182
d62a17ae 11183 bgp = peer->bgp;
a636c635 11184
d62a17ae 11185 if (!bgp) {
11186 if (use_json) {
11187 json_object_string_add(json, "alert", "no BGP");
11188 vty_out(vty, "%s\n", json_object_to_json_string(json));
11189 json_object_free(json);
11190 } else
11191 vty_out(vty, "%% No bgp\n");
11192 return;
11193 }
a636c635 11194
c512a642
EDP
11195 /* labeled-unicast routes live in the unicast table */
11196 if (safi == SAFI_LABELED_UNICAST)
11197 table = bgp->rib[afi][SAFI_UNICAST];
11198 else
11199 table = bgp->rib[afi][safi];
d62a17ae 11200
11201 output_count = filtered_count = 0;
11202 subgrp = peer_subgroup(peer, afi, safi);
11203
6392aaa6 11204 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 11205 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
11206 if (use_json) {
11207 json_object_int_add(json, "bgpTableVersion",
11208 table->version);
11209 json_object_string_add(json, "bgpLocalRouterId",
11210 inet_ntoa(bgp->router_id));
01eced22
AD
11211 json_object_int_add(json, "defaultLocPrf",
11212 bgp->default_local_pref);
11213 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 11214 json_object_object_add(json, "bgpStatusCodes",
11215 json_scode);
11216 json_object_object_add(json, "bgpOriginCodes",
11217 json_ocode);
07d0c4ed
DA
11218 json_object_string_add(
11219 json, "bgpOriginatingDefaultNetwork",
11220 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 11221 } else {
996c9314 11222 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 11223 ", local router ID is %s, vrf id ",
d62a17ae 11224 table->version, inet_ntoa(bgp->router_id));
9df8b37c
PZ
11225 if (bgp->vrf_id == VRF_UNKNOWN)
11226 vty_out(vty, "%s", VRFID_NONE_STR);
11227 else
11228 vty_out(vty, "%u", bgp->vrf_id);
11229 vty_out(vty, "\n");
01eced22
AD
11230 vty_out(vty, "Default local pref %u, ",
11231 bgp->default_local_pref);
11232 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 11233 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11234 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 11235 vty_out(vty, BGP_SHOW_OCODE_HEADER);
11236
07d0c4ed
DA
11237 vty_out(vty, "Originating default network %s\n\n",
11238 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 11239 }
11240 header1 = 0;
11241 }
a636c635 11242
d62a17ae 11243 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6392aaa6
PM
11244 if (type == bgp_show_adj_route_received
11245 || type == bgp_show_adj_route_filtered) {
d62a17ae 11246 for (ain = rn->adj_in; ain; ain = ain->next) {
05864da7 11247 if (ain->peer != peer)
ea47320b 11248 continue;
6392aaa6 11249
ea47320b
DL
11250 if (header1) {
11251 if (use_json) {
11252 json_object_int_add(
60466a63 11253 json, "bgpTableVersion",
ea47320b
DL
11254 0);
11255 json_object_string_add(
11256 json,
11257 "bgpLocalRouterId",
11258 inet_ntoa(
11259 bgp->router_id));
01eced22
AD
11260 json_object_int_add(json,
11261 "defaultLocPrf",
11262 bgp->default_local_pref);
11263 json_object_int_add(json,
11264 "localAS", bgp->as);
ea47320b 11265 json_object_object_add(
60466a63 11266 json, "bgpStatusCodes",
ea47320b
DL
11267 json_scode);
11268 json_object_object_add(
60466a63 11269 json, "bgpOriginCodes",
ea47320b
DL
11270 json_ocode);
11271 } else {
11272 vty_out(vty,
9df8b37c 11273 "BGP table version is 0, local router ID is %s, vrf id ",
ea47320b 11274 inet_ntoa(
9df8b37c
PZ
11275 bgp->router_id));
11276 if (bgp->vrf_id == VRF_UNKNOWN)
11277 vty_out(vty, "%s",
11278 VRFID_NONE_STR);
11279 else
11280 vty_out(vty, "%u",
11281 bgp->vrf_id);
11282 vty_out(vty, "\n");
01eced22
AD
11283 vty_out(vty,
11284 "Default local pref %u, ",
11285 bgp->default_local_pref);
11286 vty_out(vty, "local AS %u\n",
11287 bgp->as);
ea47320b
DL
11288 vty_out(vty,
11289 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
11290 vty_out(vty,
11291 BGP_SHOW_NCODE_HEADER);
ea47320b
DL
11292 vty_out(vty,
11293 BGP_SHOW_OCODE_HEADER);
d62a17ae 11294 }
ea47320b
DL
11295 header1 = 0;
11296 }
11297 if (header2) {
11298 if (!use_json)
11299 vty_out(vty, BGP_SHOW_HEADER);
11300 header2 = 0;
11301 }
6392aaa6
PM
11302
11303 bgp_attr_dup(&attr, ain->attr);
f99def61
AD
11304 route_filtered = false;
11305
11306 /* Filter prefix using distribute list,
11307 * filter list or prefix list
11308 */
11309 if ((bgp_input_filter(peer, &rn->p, &attr, afi,
11310 safi)) == FILTER_DENY)
11311 route_filtered = true;
11312
11313 /* Filter prefix using route-map */
6392aaa6 11314 ret = bgp_input_modifier(peer, &rn->p, &attr,
196c6b09
LK
11315 afi, safi, rmap_name, NULL, 0,
11316 NULL);
6392aaa6 11317
13c8e163
AD
11318 if (type == bgp_show_adj_route_filtered &&
11319 !route_filtered && ret != RMAP_DENY) {
b755861b 11320 bgp_attr_undup(&attr, ain->attr);
6392aaa6 11321 continue;
d62a17ae 11322 }
6392aaa6 11323
13c8e163
AD
11324 if (type == bgp_show_adj_route_received &&
11325 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
11326 filtered_count++;
11327
11328 route_vty_out_tmp(vty, &rn->p, &attr, safi,
11329 use_json, json_ar);
b755861b 11330 bgp_attr_undup(&attr, ain->attr);
6392aaa6 11331 output_count++;
d62a17ae 11332 }
6392aaa6 11333 } else if (type == bgp_show_adj_route_advertised) {
a79c04e7 11334 RB_FOREACH (adj, bgp_adj_out_rb, &rn->adj_out)
924c3f6a 11335 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 11336 if (paf->peer != peer || !adj->attr)
924c3f6a 11337 continue;
d62a17ae 11338
924c3f6a
DS
11339 if (header1) {
11340 if (use_json) {
11341 json_object_int_add(
11342 json,
11343 "bgpTableVersion",
11344 table->version);
11345 json_object_string_add(
11346 json,
11347 "bgpLocalRouterId",
11348 inet_ntoa(
11349 bgp->router_id));
01eced22
AD
11350 json_object_int_add(
11351 json, "defaultLocPrf",
11352 bgp->default_local_pref
11353 );
11354 json_object_int_add(
11355 json, "localAS",
11356 bgp->as);
924c3f6a
DS
11357 json_object_object_add(
11358 json,
11359 "bgpStatusCodes",
11360 json_scode);
11361 json_object_object_add(
11362 json,
11363 "bgpOriginCodes",
11364 json_ocode);
11365 } else {
11366 vty_out(vty,
11367 "BGP table version is %" PRIu64
9df8b37c 11368 ", local router ID is %s, vrf id ",
924c3f6a
DS
11369 table->version,
11370 inet_ntoa(
11371 bgp->router_id));
9df8b37c
PZ
11372 if (bgp->vrf_id ==
11373 VRF_UNKNOWN)
11374 vty_out(vty,
11375 "%s",
11376 VRFID_NONE_STR);
11377 else
11378 vty_out(vty,
11379 "%u",
11380 bgp->vrf_id);
11381 vty_out(vty, "\n");
01eced22
AD
11382 vty_out(vty,
11383 "Default local pref %u, ",
11384 bgp->default_local_pref
11385 );
11386 vty_out(vty,
11387 "local AS %u\n",
11388 bgp->as);
924c3f6a
DS
11389 vty_out(vty,
11390 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
11391 vty_out(vty,
11392 BGP_SHOW_NCODE_HEADER);
924c3f6a
DS
11393 vty_out(vty,
11394 BGP_SHOW_OCODE_HEADER);
a2addae8 11395 }
924c3f6a
DS
11396 header1 = 0;
11397 }
924c3f6a
DS
11398 if (header2) {
11399 if (!use_json)
11400 vty_out(vty,
11401 BGP_SHOW_HEADER);
11402 header2 = 0;
11403 }
d62a17ae 11404
b755861b
PM
11405 bgp_attr_dup(&attr, adj->attr);
11406 ret = bgp_output_modifier(
11407 peer, &rn->p, &attr, afi, safi,
11408 rmap_name);
f46d8e1e 11409
b755861b
PM
11410 if (ret != RMAP_DENY) {
11411 route_vty_out_tmp(vty, &rn->p,
11412 &attr, safi,
11413 use_json,
11414 json_ar);
11415 output_count++;
11416 } else {
11417 filtered_count++;
a2addae8 11418 }
b755861b
PM
11419
11420 bgp_attr_undup(&attr, adj->attr);
924c3f6a 11421 }
d62a17ae 11422 }
11423 }
d62a17ae 11424
d62a17ae 11425 if (use_json) {
6392aaa6
PM
11426 json_object_object_add(json, "advertisedRoutes", json_ar);
11427 json_object_int_add(json, "totalPrefixCounter", output_count);
11428 json_object_int_add(json, "filteredPrefixCounter",
11429 filtered_count);
11430
996c9314
LB
11431 vty_out(vty, "%s\n", json_object_to_json_string_ext(
11432 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 11433 json_object_free(json);
6392aaa6
PM
11434 } else if (output_count > 0) {
11435 if (filtered_count > 0)
11436 vty_out(vty,
11437 "\nTotal number of prefixes %ld (%ld filtered)\n",
11438 output_count, filtered_count);
11439 else
11440 vty_out(vty, "\nTotal number of prefixes %ld\n",
11441 output_count);
d62a17ae 11442 }
a636c635 11443}
2a71e9ce 11444
d62a17ae 11445static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 11446 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 11447 const char *rmap_name, bool use_json)
0b16f239 11448{
d62a17ae 11449 json_object *json = NULL;
0b16f239 11450
d62a17ae 11451 if (use_json)
11452 json = json_object_new_object();
0b16f239 11453
d62a17ae 11454 if (!peer || !peer->afc[afi][safi]) {
11455 if (use_json) {
11456 json_object_string_add(
11457 json, "warning",
11458 "No such neighbor or address family");
11459 vty_out(vty, "%s\n", json_object_to_json_string(json));
11460 json_object_free(json);
11461 } else
11462 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 11463
d62a17ae 11464 return CMD_WARNING;
11465 }
11466
6392aaa6
PM
11467 if ((type == bgp_show_adj_route_received
11468 || type == bgp_show_adj_route_filtered)
d62a17ae 11469 && !CHECK_FLAG(peer->af_flags[afi][safi],
11470 PEER_FLAG_SOFT_RECONFIG)) {
11471 if (use_json) {
11472 json_object_string_add(
11473 json, "warning",
11474 "Inbound soft reconfiguration not enabled");
11475 vty_out(vty, "%s\n", json_object_to_json_string(json));
11476 json_object_free(json);
11477 } else
11478 vty_out(vty,
11479 "%% Inbound soft reconfiguration not enabled\n");
11480
11481 return CMD_WARNING;
11482 }
0b16f239 11483
6392aaa6 11484 show_adj_route(vty, peer, afi, safi, type, rmap_name, use_json, json);
0b16f239 11485
d62a17ae 11486 return CMD_SUCCESS;
a636c635 11487}
50ef26d4 11488
a636c635
DW
11489DEFUN (show_ip_bgp_instance_neighbor_advertised_route,
11490 show_ip_bgp_instance_neighbor_advertised_route_cmd,
4dd6177e 11491 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
6392aaa6 11492 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
718e3744 11493 SHOW_STR
11494 IP_STR
11495 BGP_STR
a636c635 11496 BGP_INSTANCE_HELP_STR
7395a2c9 11497 BGP_AFI_HELP_STR
4dd6177e 11498 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 11499 "Detailed information on TCP and BGP neighbor connections\n"
11500 "Neighbor to display information about\n"
11501 "Neighbor to display information about\n"
91d37724 11502 "Neighbor on BGP configured interface\n"
a636c635 11503 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
11504 "Display the received routes from neighbor\n"
11505 "Display the filtered routes received from neighbor\n"
a636c635
DW
11506 "Route-map to modify the attributes\n"
11507 "Name of the route map\n"
9973d184 11508 JSON_STR)
718e3744 11509{
d62a17ae 11510 afi_t afi = AFI_IP6;
11511 safi_t safi = SAFI_UNICAST;
11512 char *rmap_name = NULL;
11513 char *peerstr = NULL;
d62a17ae 11514 struct bgp *bgp = NULL;
11515 struct peer *peer;
6392aaa6 11516 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 11517 int idx = 0;
9f049418 11518 bool uj = use_json(argc, argv);
6392aaa6 11519
d62a17ae 11520 if (uj)
11521 argc--;
30a6a167 11522
9f049418
DS
11523 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11524 &bgp, uj);
11525 if (!idx)
11526 return CMD_WARNING;
11527
d62a17ae 11528 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11529 argv_find(argv, argc, "neighbors", &idx);
11530 peerstr = argv[++idx]->arg;
8c3deaae 11531
d62a17ae 11532 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
11533 if (!peer)
11534 return CMD_WARNING;
856ca177 11535
d62a17ae 11536 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
11537 type = bgp_show_adj_route_advertised;
11538 else if (argv_find(argv, argc, "received-routes", &idx))
11539 type = bgp_show_adj_route_received;
11540 else if (argv_find(argv, argc, "filtered-routes", &idx))
11541 type = bgp_show_adj_route_filtered;
11542
d62a17ae 11543 if (argv_find(argv, argc, "route-map", &idx))
11544 rmap_name = argv[++idx]->arg;
95cbbd2a 11545
6392aaa6 11546 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj);
95cbbd2a
ML
11547}
11548
718e3744 11549DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
11550 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 11551 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 11552 SHOW_STR
11553 IP_STR
11554 BGP_STR
8c3deaae
QY
11555 "Address Family\n"
11556 "Address Family\n"
718e3744 11557 "Address Family modifier\n"
11558 "Detailed information on TCP and BGP neighbor connections\n"
11559 "Neighbor to display information about\n"
11560 "Neighbor to display information about\n"
91d37724 11561 "Neighbor on BGP configured interface\n"
718e3744 11562 "Display information received from a BGP neighbor\n"
856ca177 11563 "Display the prefixlist filter\n"
9973d184 11564 JSON_STR)
718e3744 11565{
d62a17ae 11566 afi_t afi = AFI_IP6;
11567 safi_t safi = SAFI_UNICAST;
11568 char *peerstr = NULL;
11569
11570 char name[BUFSIZ];
11571 union sockunion su;
11572 struct peer *peer;
11573 int count, ret;
11574
11575 int idx = 0;
11576
11577 /* show [ip] bgp */
11578 if (argv_find(argv, argc, "ip", &idx))
11579 afi = AFI_IP;
11580 /* [<ipv4|ipv6> [unicast]] */
11581 if (argv_find(argv, argc, "ipv4", &idx))
11582 afi = AFI_IP;
11583 if (argv_find(argv, argc, "ipv6", &idx))
11584 afi = AFI_IP6;
11585 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11586 argv_find(argv, argc, "neighbors", &idx);
11587 peerstr = argv[++idx]->arg;
11588
9f049418 11589 bool uj = use_json(argc, argv);
d62a17ae 11590
11591 ret = str2sockunion(peerstr, &su);
11592 if (ret < 0) {
11593 peer = peer_lookup_by_conf_if(NULL, peerstr);
11594 if (!peer) {
11595 if (uj)
11596 vty_out(vty, "{}\n");
11597 else
11598 vty_out(vty,
11599 "%% Malformed address or name: %s\n",
11600 peerstr);
11601 return CMD_WARNING;
11602 }
11603 } else {
11604 peer = peer_lookup(NULL, &su);
11605 if (!peer) {
11606 if (uj)
11607 vty_out(vty, "{}\n");
11608 else
11609 vty_out(vty, "No peer\n");
11610 return CMD_WARNING;
11611 }
11612 }
718e3744 11613
d62a17ae 11614 sprintf(name, "%s.%d.%d", peer->host, afi, safi);
11615 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
11616 if (count) {
11617 if (!uj)
11618 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 11619 get_afi_safi_str(afi, safi, false));
d62a17ae 11620 prefix_bgp_show_prefix_list(vty, afi, name, uj);
11621 } else {
11622 if (uj)
11623 vty_out(vty, "{}\n");
11624 else
11625 vty_out(vty, "No functional output\n");
11626 }
718e3744 11627
d62a17ae 11628 return CMD_SUCCESS;
11629}
11630
11631static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
11632 afi_t afi, safi_t safi,
9f049418 11633 enum bgp_show_type type, bool use_json)
d62a17ae 11634{
8a893163
DW
11635 /* labeled-unicast routes live in the unicast table */
11636 if (safi == SAFI_LABELED_UNICAST)
11637 safi = SAFI_UNICAST;
11638
d62a17ae 11639 if (!peer || !peer->afc[afi][safi]) {
11640 if (use_json) {
11641 json_object *json_no = NULL;
11642 json_no = json_object_new_object();
11643 json_object_string_add(
11644 json_no, "warning",
11645 "No such neighbor or address family");
11646 vty_out(vty, "%s\n",
11647 json_object_to_json_string(json_no));
11648 json_object_free(json_no);
11649 } else
11650 vty_out(vty, "%% No such neighbor or address family\n");
11651 return CMD_WARNING;
11652 }
47fc97cc 11653
d62a17ae 11654 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json);
718e3744 11655}
11656
dba3c1d3
PG
11657DEFUN (show_ip_bgp_flowspec_routes_detailed,
11658 show_ip_bgp_flowspec_routes_detailed_cmd,
11659 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
11660 SHOW_STR
11661 IP_STR
11662 BGP_STR
11663 BGP_INSTANCE_HELP_STR
11664 BGP_AFI_HELP_STR
11665 "SAFI Flowspec\n"
11666 "Detailed information on flowspec entries\n"
11667 JSON_STR)
11668{
11669 afi_t afi = AFI_IP;
11670 safi_t safi = SAFI_UNICAST;
11671 struct bgp *bgp = NULL;
11672 int idx = 0;
9f049418
DS
11673 bool uj = use_json(argc, argv);
11674
11675 if (uj)
11676 argc--;
dba3c1d3
PG
11677
11678 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11679 &bgp, uj);
dba3c1d3
PG
11680 if (!idx)
11681 return CMD_WARNING;
11682
9f049418 11683 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL, uj);
dba3c1d3
PG
11684}
11685
718e3744 11686DEFUN (show_ip_bgp_neighbor_routes,
11687 show_ip_bgp_neighbor_routes_cmd,
4dd6177e 11688 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
30a6a167 11689 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
50ef26d4 11690 SHOW_STR
11691 IP_STR
11692 BGP_STR
8386ac43 11693 BGP_INSTANCE_HELP_STR
4f280b15 11694 BGP_AFI_HELP_STR
4dd6177e 11695 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 11696 "Detailed information on TCP and BGP neighbor connections\n"
11697 "Neighbor to display information about\n"
11698 "Neighbor to display information about\n"
91d37724 11699 "Neighbor on BGP configured interface\n"
2525cf39 11700 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
11701 "Display the dampened routes received from neighbor\n"
11702 "Display routes learned from neighbor\n"
9973d184 11703 JSON_STR)
718e3744 11704{
d62a17ae 11705 char *peerstr = NULL;
11706 struct bgp *bgp = NULL;
11707 afi_t afi = AFI_IP6;
11708 safi_t safi = SAFI_UNICAST;
11709 struct peer *peer;
11710 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 11711 int idx = 0;
9f049418
DS
11712 bool uj = use_json(argc, argv);
11713
11714 if (uj)
11715 argc--;
bb46e94f 11716
d62a17ae 11717 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11718 &bgp, uj);
d62a17ae 11719 if (!idx)
11720 return CMD_WARNING;
c493f2d8 11721
d62a17ae 11722 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11723 argv_find(argv, argc, "neighbors", &idx);
11724 peerstr = argv[++idx]->arg;
8c3deaae 11725
d62a17ae 11726 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 11727 if (!peer)
d62a17ae 11728 return CMD_WARNING;
bb46e94f 11729
d62a17ae 11730 if (argv_find(argv, argc, "flap-statistics", &idx))
11731 sh_type = bgp_show_type_flap_neighbor;
11732 else if (argv_find(argv, argc, "dampened-routes", &idx))
11733 sh_type = bgp_show_type_damp_neighbor;
11734 else if (argv_find(argv, argc, "routes", &idx))
11735 sh_type = bgp_show_type_neighbor;
2525cf39 11736
d62a17ae 11737 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 11738}
6b0655a2 11739
734b349e 11740struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 11741
d62a17ae 11742struct bgp_distance {
11743 /* Distance value for the IP source prefix. */
d7c0a89a 11744 uint8_t distance;
718e3744 11745
d62a17ae 11746 /* Name of the access-list to be matched. */
11747 char *access_list;
718e3744 11748};
11749
4f280b15
LB
11750DEFUN (show_bgp_afi_vpn_rd_route,
11751 show_bgp_afi_vpn_rd_route_cmd,
d114b977 11752 "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
11753 SHOW_STR
11754 BGP_STR
11755 BGP_AFI_HELP_STR
11756 "Address Family modifier\n"
11757 "Display information for a route distinguisher\n"
11758 "Route Distinguisher\n"
7395a2c9
DS
11759 "Network in the BGP routing table to display\n"
11760 "Network in the BGP routing table to display\n"
11761 JSON_STR)
4f280b15 11762{
d62a17ae 11763 int ret;
11764 struct prefix_rd prd;
11765 afi_t afi = AFI_MAX;
11766 int idx = 0;
4f280b15 11767
ff6566f3
DS
11768 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
11769 vty_out(vty, "%% Malformed Address Family\n");
11770 return CMD_WARNING;
11771 }
11772
d62a17ae 11773 ret = str2prefix_rd(argv[5]->arg, &prd);
11774 if (!ret) {
11775 vty_out(vty, "%% Malformed Route Distinguisher\n");
11776 return CMD_WARNING;
11777 }
ff6566f3 11778
d62a17ae 11779 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 11780 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
11781}
11782
d62a17ae 11783static struct bgp_distance *bgp_distance_new(void)
718e3744 11784{
d62a17ae 11785 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 11786}
11787
d62a17ae 11788static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 11789{
d62a17ae 11790 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 11791}
11792
d62a17ae 11793static int bgp_distance_set(struct vty *vty, const char *distance_str,
11794 const char *ip_str, const char *access_list_str)
718e3744 11795{
d62a17ae 11796 int ret;
11797 afi_t afi;
11798 safi_t safi;
11799 struct prefix p;
d7c0a89a 11800 uint8_t distance;
d62a17ae 11801 struct bgp_node *rn;
11802 struct bgp_distance *bdistance;
718e3744 11803
d62a17ae 11804 afi = bgp_node_afi(vty);
11805 safi = bgp_node_safi(vty);
734b349e 11806
d62a17ae 11807 ret = str2prefix(ip_str, &p);
11808 if (ret == 0) {
11809 vty_out(vty, "Malformed prefix\n");
11810 return CMD_WARNING_CONFIG_FAILED;
11811 }
718e3744 11812
d62a17ae 11813 distance = atoi(distance_str);
718e3744 11814
d62a17ae 11815 /* Get BGP distance node. */
11816 rn = bgp_node_get(bgp_distance_table[afi][safi], (struct prefix *)&p);
5b00b40e 11817 bdistance = bgp_node_get_bgp_distance_info(rn);
ca2e160d 11818 if (bdistance)
d62a17ae 11819 bgp_unlock_node(rn);
ca2e160d 11820 else {
d62a17ae 11821 bdistance = bgp_distance_new();
5b00b40e 11822 bgp_node_set_bgp_distance_info(rn, bdistance);
d62a17ae 11823 }
718e3744 11824
d62a17ae 11825 /* Set distance value. */
11826 bdistance->distance = distance;
718e3744 11827
d62a17ae 11828 /* Reset access-list configuration. */
11829 if (bdistance->access_list) {
11830 XFREE(MTYPE_AS_LIST, bdistance->access_list);
11831 bdistance->access_list = NULL;
11832 }
11833 if (access_list_str)
11834 bdistance->access_list =
11835 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 11836
d62a17ae 11837 return CMD_SUCCESS;
718e3744 11838}
11839
d62a17ae 11840static int bgp_distance_unset(struct vty *vty, const char *distance_str,
11841 const char *ip_str, const char *access_list_str)
718e3744 11842{
d62a17ae 11843 int ret;
11844 afi_t afi;
11845 safi_t safi;
11846 struct prefix p;
11847 int distance;
11848 struct bgp_node *rn;
11849 struct bgp_distance *bdistance;
718e3744 11850
d62a17ae 11851 afi = bgp_node_afi(vty);
11852 safi = bgp_node_safi(vty);
734b349e 11853
d62a17ae 11854 ret = str2prefix(ip_str, &p);
11855 if (ret == 0) {
11856 vty_out(vty, "Malformed prefix\n");
11857 return CMD_WARNING_CONFIG_FAILED;
11858 }
718e3744 11859
d62a17ae 11860 rn = bgp_node_lookup(bgp_distance_table[afi][safi],
11861 (struct prefix *)&p);
11862 if (!rn) {
11863 vty_out(vty, "Can't find specified prefix\n");
11864 return CMD_WARNING_CONFIG_FAILED;
11865 }
718e3744 11866
5b00b40e 11867 bdistance = bgp_node_get_bgp_distance_info(rn);
d62a17ae 11868 distance = atoi(distance_str);
1f9a9fff 11869
d62a17ae 11870 if (bdistance->distance != distance) {
11871 vty_out(vty, "Distance does not match configured\n");
11872 return CMD_WARNING_CONFIG_FAILED;
11873 }
718e3744 11874
0a22ddfb 11875 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 11876 bgp_distance_free(bdistance);
718e3744 11877
6f94b685 11878 bgp_node_set_bgp_path_info(rn, NULL);
d62a17ae 11879 bgp_unlock_node(rn);
11880 bgp_unlock_node(rn);
718e3744 11881
d62a17ae 11882 return CMD_SUCCESS;
718e3744 11883}
11884
718e3744 11885/* Apply BGP information to distance method. */
40381db7 11886uint8_t bgp_distance_apply(struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 11887 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 11888{
11889 struct bgp_node *rn;
11890 struct prefix q;
11891 struct peer *peer;
11892 struct bgp_distance *bdistance;
11893 struct access_list *alist;
11894 struct bgp_static *bgp_static;
11895
11896 if (!bgp)
11897 return 0;
11898
40381db7 11899 peer = pinfo->peer;
d62a17ae 11900
7b7d48e5
DS
11901 if (pinfo->attr->distance)
11902 return pinfo->attr->distance;
11903
d62a17ae 11904 /* Check source address. */
11905 sockunion2hostprefix(&peer->su, &q);
11906 rn = bgp_node_match(bgp_distance_table[afi][safi], &q);
11907 if (rn) {
5b00b40e 11908 bdistance = bgp_node_get_bgp_distance_info(rn);
d62a17ae 11909 bgp_unlock_node(rn);
11910
11911 if (bdistance->access_list) {
11912 alist = access_list_lookup(afi, bdistance->access_list);
11913 if (alist
11914 && access_list_apply(alist, p) == FILTER_PERMIT)
11915 return bdistance->distance;
11916 } else
11917 return bdistance->distance;
718e3744 11918 }
718e3744 11919
d62a17ae 11920 /* Backdoor check. */
11921 rn = bgp_node_lookup(bgp->route[afi][safi], p);
11922 if (rn) {
5a8ba9fc 11923 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 11924 bgp_unlock_node(rn);
718e3744 11925
d62a17ae 11926 if (bgp_static->backdoor) {
11927 if (bgp->distance_local[afi][safi])
11928 return bgp->distance_local[afi][safi];
11929 else
11930 return ZEBRA_IBGP_DISTANCE_DEFAULT;
11931 }
718e3744 11932 }
718e3744 11933
d62a17ae 11934 if (peer->sort == BGP_PEER_EBGP) {
11935 if (bgp->distance_ebgp[afi][safi])
11936 return bgp->distance_ebgp[afi][safi];
11937 return ZEBRA_EBGP_DISTANCE_DEFAULT;
11938 } else {
11939 if (bgp->distance_ibgp[afi][safi])
11940 return bgp->distance_ibgp[afi][safi];
11941 return ZEBRA_IBGP_DISTANCE_DEFAULT;
11942 }
718e3744 11943}
11944
a612fb77
DA
11945/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
11946 * we should tell ZEBRA update the routes for a specific
11947 * AFI/SAFI to reflect changes in RIB.
11948 */
8b54bc30
DA
11949static void bgp_announce_routes_distance_update(struct bgp *bgp,
11950 afi_t update_afi,
11951 safi_t update_safi)
a612fb77
DA
11952{
11953 afi_t afi;
11954 safi_t safi;
11955
11956 FOREACH_AFI_SAFI (afi, safi) {
11957 if (!bgp_fibupd_safi(safi))
11958 continue;
11959
8b54bc30
DA
11960 if (afi != update_afi && safi != update_safi)
11961 continue;
11962
11963 if (BGP_DEBUG(zebra, ZEBRA))
11964 zlog_debug(
11965 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
11966 __func__, afi, safi);
11967 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
11968 }
11969}
11970
718e3744 11971DEFUN (bgp_distance,
11972 bgp_distance_cmd,
6147e2c6 11973 "distance bgp (1-255) (1-255) (1-255)",
718e3744 11974 "Define an administrative distance\n"
11975 "BGP distance\n"
11976 "Distance for routes external to the AS\n"
11977 "Distance for routes internal to the AS\n"
11978 "Distance for local routes\n")
11979{
d62a17ae 11980 VTY_DECLVAR_CONTEXT(bgp, bgp);
11981 int idx_number = 2;
11982 int idx_number_2 = 3;
11983 int idx_number_3 = 4;
8b54bc30
DA
11984 int distance_ebgp = atoi(argv[idx_number]->arg);
11985 int distance_ibgp = atoi(argv[idx_number_2]->arg);
11986 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 11987 afi_t afi;
11988 safi_t safi;
718e3744 11989
d62a17ae 11990 afi = bgp_node_afi(vty);
11991 safi = bgp_node_safi(vty);
718e3744 11992
8b54bc30
DA
11993 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
11994 || bgp->distance_ibgp[afi][safi] != distance_ibgp
11995 || bgp->distance_local[afi][safi] != distance_local) {
11996 bgp->distance_ebgp[afi][safi] = distance_ebgp;
11997 bgp->distance_ibgp[afi][safi] = distance_ibgp;
11998 bgp->distance_local[afi][safi] = distance_local;
11999 bgp_announce_routes_distance_update(bgp, afi, safi);
12000 }
d62a17ae 12001 return CMD_SUCCESS;
718e3744 12002}
12003
12004DEFUN (no_bgp_distance,
12005 no_bgp_distance_cmd,
a636c635 12006 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 12007 NO_STR
12008 "Define an administrative distance\n"
12009 "BGP distance\n"
12010 "Distance for routes external to the AS\n"
12011 "Distance for routes internal to the AS\n"
12012 "Distance for local routes\n")
12013{
d62a17ae 12014 VTY_DECLVAR_CONTEXT(bgp, bgp);
12015 afi_t afi;
12016 safi_t safi;
718e3744 12017
d62a17ae 12018 afi = bgp_node_afi(vty);
12019 safi = bgp_node_safi(vty);
718e3744 12020
8b54bc30
DA
12021 if (bgp->distance_ebgp[afi][safi] != 0
12022 || bgp->distance_ibgp[afi][safi] != 0
12023 || bgp->distance_local[afi][safi] != 0) {
12024 bgp->distance_ebgp[afi][safi] = 0;
12025 bgp->distance_ibgp[afi][safi] = 0;
12026 bgp->distance_local[afi][safi] = 0;
12027 bgp_announce_routes_distance_update(bgp, afi, safi);
12028 }
d62a17ae 12029 return CMD_SUCCESS;
718e3744 12030}
12031
718e3744 12032
12033DEFUN (bgp_distance_source,
12034 bgp_distance_source_cmd,
6147e2c6 12035 "distance (1-255) A.B.C.D/M",
718e3744 12036 "Define an administrative distance\n"
12037 "Administrative distance\n"
12038 "IP source prefix\n")
12039{
d62a17ae 12040 int idx_number = 1;
12041 int idx_ipv4_prefixlen = 2;
12042 bgp_distance_set(vty, argv[idx_number]->arg,
12043 argv[idx_ipv4_prefixlen]->arg, NULL);
12044 return CMD_SUCCESS;
718e3744 12045}
12046
12047DEFUN (no_bgp_distance_source,
12048 no_bgp_distance_source_cmd,
6147e2c6 12049 "no distance (1-255) A.B.C.D/M",
718e3744 12050 NO_STR
12051 "Define an administrative distance\n"
12052 "Administrative distance\n"
12053 "IP source prefix\n")
12054{
d62a17ae 12055 int idx_number = 2;
12056 int idx_ipv4_prefixlen = 3;
12057 bgp_distance_unset(vty, argv[idx_number]->arg,
12058 argv[idx_ipv4_prefixlen]->arg, NULL);
12059 return CMD_SUCCESS;
718e3744 12060}
12061
12062DEFUN (bgp_distance_source_access_list,
12063 bgp_distance_source_access_list_cmd,
6147e2c6 12064 "distance (1-255) A.B.C.D/M WORD",
718e3744 12065 "Define an administrative distance\n"
12066 "Administrative distance\n"
12067 "IP source prefix\n"
12068 "Access list name\n")
12069{
d62a17ae 12070 int idx_number = 1;
12071 int idx_ipv4_prefixlen = 2;
12072 int idx_word = 3;
12073 bgp_distance_set(vty, argv[idx_number]->arg,
12074 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12075 return CMD_SUCCESS;
718e3744 12076}
12077
12078DEFUN (no_bgp_distance_source_access_list,
12079 no_bgp_distance_source_access_list_cmd,
6147e2c6 12080 "no distance (1-255) A.B.C.D/M WORD",
718e3744 12081 NO_STR
12082 "Define an administrative distance\n"
12083 "Administrative distance\n"
12084 "IP source prefix\n"
12085 "Access list name\n")
12086{
d62a17ae 12087 int idx_number = 2;
12088 int idx_ipv4_prefixlen = 3;
12089 int idx_word = 4;
12090 bgp_distance_unset(vty, argv[idx_number]->arg,
12091 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12092 return CMD_SUCCESS;
718e3744 12093}
6b0655a2 12094
734b349e
MZ
12095DEFUN (ipv6_bgp_distance_source,
12096 ipv6_bgp_distance_source_cmd,
39e92c06 12097 "distance (1-255) X:X::X:X/M",
734b349e
MZ
12098 "Define an administrative distance\n"
12099 "Administrative distance\n"
12100 "IP source prefix\n")
12101{
d62a17ae 12102 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
12103 return CMD_SUCCESS;
734b349e
MZ
12104}
12105
12106DEFUN (no_ipv6_bgp_distance_source,
12107 no_ipv6_bgp_distance_source_cmd,
39e92c06 12108 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
12109 NO_STR
12110 "Define an administrative distance\n"
12111 "Administrative distance\n"
12112 "IP source prefix\n")
12113{
d62a17ae 12114 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
12115 return CMD_SUCCESS;
734b349e
MZ
12116}
12117
12118DEFUN (ipv6_bgp_distance_source_access_list,
12119 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12120 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12121 "Define an administrative distance\n"
12122 "Administrative distance\n"
12123 "IP source prefix\n"
12124 "Access list name\n")
12125{
d62a17ae 12126 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
12127 return CMD_SUCCESS;
734b349e
MZ
12128}
12129
12130DEFUN (no_ipv6_bgp_distance_source_access_list,
12131 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12132 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12133 NO_STR
12134 "Define an administrative distance\n"
12135 "Administrative distance\n"
12136 "IP source prefix\n"
12137 "Access list name\n")
12138{
d62a17ae 12139 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
12140 return CMD_SUCCESS;
734b349e
MZ
12141}
12142
718e3744 12143DEFUN (bgp_damp_set,
12144 bgp_damp_set_cmd,
31500417 12145 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 12146 "BGP Specific commands\n"
12147 "Enable route-flap dampening\n"
12148 "Half-life time for the penalty\n"
12149 "Value to start reusing a route\n"
12150 "Value to start suppressing a route\n"
12151 "Maximum duration to suppress a stable route\n")
12152{
d62a17ae 12153 VTY_DECLVAR_CONTEXT(bgp, bgp);
12154 int idx_half_life = 2;
12155 int idx_reuse = 3;
12156 int idx_suppress = 4;
12157 int idx_max_suppress = 5;
12158 int half = DEFAULT_HALF_LIFE * 60;
12159 int reuse = DEFAULT_REUSE;
12160 int suppress = DEFAULT_SUPPRESS;
12161 int max = 4 * half;
12162
12163 if (argc == 6) {
12164 half = atoi(argv[idx_half_life]->arg) * 60;
12165 reuse = atoi(argv[idx_reuse]->arg);
12166 suppress = atoi(argv[idx_suppress]->arg);
12167 max = atoi(argv[idx_max_suppress]->arg) * 60;
12168 } else if (argc == 3) {
12169 half = atoi(argv[idx_half_life]->arg) * 60;
12170 max = 4 * half;
12171 }
718e3744 12172
d62a17ae 12173 if (suppress < reuse) {
12174 vty_out(vty,
12175 "Suppress value cannot be less than reuse value \n");
12176 return 0;
12177 }
7ebe9748 12178
d62a17ae 12179 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
12180 reuse, suppress, max);
718e3744 12181}
12182
718e3744 12183DEFUN (bgp_damp_unset,
12184 bgp_damp_unset_cmd,
d04c479d 12185 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 12186 NO_STR
12187 "BGP Specific commands\n"
16cedbb0
QY
12188 "Enable route-flap dampening\n"
12189 "Half-life time for the penalty\n"
12190 "Value to start reusing a route\n"
12191 "Value to start suppressing a route\n"
12192 "Maximum duration to suppress a stable route\n")
718e3744 12193{
d62a17ae 12194 VTY_DECLVAR_CONTEXT(bgp, bgp);
12195 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 12196}
12197
718e3744 12198/* Display specified route of BGP table. */
d62a17ae 12199static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
12200 const char *ip_str, afi_t afi, safi_t safi,
12201 struct prefix_rd *prd, int prefix_check)
12202{
12203 int ret;
12204 struct prefix match;
12205 struct bgp_node *rn;
12206 struct bgp_node *rm;
40381db7
DS
12207 struct bgp_path_info *pi;
12208 struct bgp_path_info *pi_temp;
d62a17ae 12209 struct bgp *bgp;
12210 struct bgp_table *table;
12211
12212 /* BGP structure lookup. */
12213 if (view_name) {
12214 bgp = bgp_lookup_by_name(view_name);
12215 if (bgp == NULL) {
12216 vty_out(vty, "%% Can't find BGP instance %s\n",
12217 view_name);
12218 return CMD_WARNING;
12219 }
12220 } else {
12221 bgp = bgp_get_default();
12222 if (bgp == NULL) {
12223 vty_out(vty, "%% No BGP process is configured\n");
12224 return CMD_WARNING;
12225 }
718e3744 12226 }
718e3744 12227
d62a17ae 12228 /* Check IP address argument. */
12229 ret = str2prefix(ip_str, &match);
12230 if (!ret) {
12231 vty_out(vty, "%% address is malformed\n");
12232 return CMD_WARNING;
12233 }
718e3744 12234
d62a17ae 12235 match.family = afi2family(afi);
12236
12237 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
12238 || (safi == SAFI_EVPN)) {
12239 for (rn = bgp_table_top(bgp->rib[AFI_IP][safi]); rn;
12240 rn = bgp_route_next(rn)) {
12241 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
12242 continue;
67009e22
DS
12243 table = bgp_node_get_bgp_table_info(rn);
12244 if (!table)
ea47320b
DL
12245 continue;
12246 if ((rm = bgp_node_match(table, &match)) == NULL)
12247 continue;
d62a17ae 12248
ea47320b
DL
12249 if (!prefix_check
12250 || rm->p.prefixlen == match.prefixlen) {
6f94b685 12251 pi = bgp_node_get_bgp_path_info(rm);
40381db7
DS
12252 while (pi) {
12253 if (pi->extra && pi->extra->damp_info) {
12254 pi_temp = pi->next;
ea47320b 12255 bgp_damp_info_free(
40381db7 12256 pi->extra->damp_info,
a935f597 12257 1, afi, safi);
40381db7 12258 pi = pi_temp;
ea47320b 12259 } else
40381db7 12260 pi = pi->next;
d62a17ae 12261 }
ea47320b
DL
12262 }
12263
12264 bgp_unlock_node(rm);
d62a17ae 12265 }
12266 } else {
12267 if ((rn = bgp_node_match(bgp->rib[afi][safi], &match))
12268 != NULL) {
12269 if (!prefix_check
12270 || rn->p.prefixlen == match.prefixlen) {
6f94b685 12271 pi = bgp_node_get_bgp_path_info(rn);
40381db7
DS
12272 while (pi) {
12273 if (pi->extra && pi->extra->damp_info) {
12274 pi_temp = pi->next;
d62a17ae 12275 bgp_damp_info_free(
40381db7 12276 pi->extra->damp_info,
a935f597 12277 1, afi, safi);
40381db7 12278 pi = pi_temp;
d62a17ae 12279 } else
40381db7 12280 pi = pi->next;
d62a17ae 12281 }
12282 }
12283
12284 bgp_unlock_node(rn);
12285 }
12286 }
718e3744 12287
d62a17ae 12288 return CMD_SUCCESS;
718e3744 12289}
12290
12291DEFUN (clear_ip_bgp_dampening,
12292 clear_ip_bgp_dampening_cmd,
12293 "clear ip bgp dampening",
12294 CLEAR_STR
12295 IP_STR
12296 BGP_STR
12297 "Clear route flap dampening information\n")
12298{
a935f597 12299 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 12300 return CMD_SUCCESS;
718e3744 12301}
12302
12303DEFUN (clear_ip_bgp_dampening_prefix,
12304 clear_ip_bgp_dampening_prefix_cmd,
12305 "clear ip bgp dampening A.B.C.D/M",
12306 CLEAR_STR
12307 IP_STR
12308 BGP_STR
12309 "Clear route flap dampening information\n"
0c7b1b01 12310 "IPv4 prefix\n")
718e3744 12311{
d62a17ae 12312 int idx_ipv4_prefixlen = 4;
12313 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
12314 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 12315}
12316
12317DEFUN (clear_ip_bgp_dampening_address,
12318 clear_ip_bgp_dampening_address_cmd,
12319 "clear ip bgp dampening A.B.C.D",
12320 CLEAR_STR
12321 IP_STR
12322 BGP_STR
12323 "Clear route flap dampening information\n"
12324 "Network to clear damping information\n")
12325{
d62a17ae 12326 int idx_ipv4 = 4;
12327 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
12328 SAFI_UNICAST, NULL, 0);
718e3744 12329}
12330
12331DEFUN (clear_ip_bgp_dampening_address_mask,
12332 clear_ip_bgp_dampening_address_mask_cmd,
12333 "clear ip bgp dampening A.B.C.D A.B.C.D",
12334 CLEAR_STR
12335 IP_STR
12336 BGP_STR
12337 "Clear route flap dampening information\n"
12338 "Network to clear damping information\n"
12339 "Network mask\n")
12340{
d62a17ae 12341 int idx_ipv4 = 4;
12342 int idx_ipv4_2 = 5;
12343 int ret;
12344 char prefix_str[BUFSIZ];
718e3744 12345
d62a17ae 12346 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
12347 prefix_str);
12348 if (!ret) {
12349 vty_out(vty, "%% Inconsistent address and mask\n");
12350 return CMD_WARNING;
12351 }
718e3744 12352
d62a17ae 12353 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
12354 NULL, 0);
718e3744 12355}
6b0655a2 12356
e3b78da8 12357static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
12358{
12359 struct vty *vty = arg;
e3b78da8 12360 struct peer *peer = bucket->data;
825d9834
DS
12361 char buf[SU_ADDRSTRLEN];
12362
12363 vty_out(vty, "\tPeer: %s %s\n", peer->host,
12364 sockunion2str(&peer->su, buf, sizeof(buf)));
12365}
12366
12367DEFUN (show_bgp_peerhash,
12368 show_bgp_peerhash_cmd,
12369 "show bgp peerhash",
12370 SHOW_STR
12371 BGP_STR
12372 "Display information about the BGP peerhash\n")
12373{
12374 struct list *instances = bm->bgp;
12375 struct listnode *node;
12376 struct bgp *bgp;
12377
12378 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
12379 vty_out(vty, "BGP: %s\n", bgp->name);
12380 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
12381 vty);
12382 }
12383
12384 return CMD_SUCCESS;
12385}
12386
587ff0fd 12387/* also used for encap safi */
2b791107
DL
12388static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
12389 afi_t afi, safi_t safi)
d62a17ae 12390{
12391 struct bgp_node *prn;
12392 struct bgp_node *rn;
12393 struct bgp_table *table;
12394 struct prefix *p;
12395 struct prefix_rd *prd;
12396 struct bgp_static *bgp_static;
12397 mpls_label_t label;
12398 char buf[SU_ADDRSTRLEN];
12399 char rdbuf[RD_ADDRSTRLEN];
12400
12401 /* Network configuration. */
12402 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b 12403 prn = bgp_route_next(prn)) {
67009e22
DS
12404 table = bgp_node_get_bgp_table_info(prn);
12405 if (!table)
ea47320b 12406 continue;
d62a17ae 12407
60466a63 12408 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5a8ba9fc 12409 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12410 if (bgp_static == NULL)
ea47320b 12411 continue;
d62a17ae 12412
ea47320b
DL
12413 p = &rn->p;
12414 prd = (struct prefix_rd *)&prn->p;
d62a17ae 12415
ea47320b 12416 /* "network" configuration display. */
06b9f471 12417 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
12418 label = decode_label(&bgp_static->label);
12419
12420 vty_out(vty, " network %s/%d rd %s",
12421 inet_ntop(p->family, &p->u.prefix, buf,
12422 SU_ADDRSTRLEN),
12423 p->prefixlen, rdbuf);
12424 if (safi == SAFI_MPLS_VPN)
12425 vty_out(vty, " label %u", label);
12426
12427 if (bgp_static->rmap.name)
12428 vty_out(vty, " route-map %s",
12429 bgp_static->rmap.name);
e2a86ad9
DS
12430
12431 if (bgp_static->backdoor)
12432 vty_out(vty, " backdoor");
12433
ea47320b
DL
12434 vty_out(vty, "\n");
12435 }
12436 }
d62a17ae 12437}
12438
2b791107
DL
12439static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
12440 afi_t afi, safi_t safi)
d62a17ae 12441{
12442 struct bgp_node *prn;
12443 struct bgp_node *rn;
12444 struct bgp_table *table;
12445 struct prefix *p;
12446 struct prefix_rd *prd;
12447 struct bgp_static *bgp_static;
ff44f570 12448 char buf[PREFIX_STRLEN * 2];
d62a17ae 12449 char buf2[SU_ADDRSTRLEN];
12450 char rdbuf[RD_ADDRSTRLEN];
12451
12452 /* Network configuration. */
12453 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b 12454 prn = bgp_route_next(prn)) {
67009e22
DS
12455 table = bgp_node_get_bgp_table_info(prn);
12456 if (!table)
ea47320b 12457 continue;
d62a17ae 12458
60466a63 12459 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5a8ba9fc 12460 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12461 if (bgp_static == NULL)
ea47320b 12462 continue;
d62a17ae 12463
ea47320b
DL
12464 char *macrouter = NULL;
12465 char *esi = NULL;
d62a17ae 12466
ea47320b
DL
12467 if (bgp_static->router_mac)
12468 macrouter = prefix_mac2str(
12469 bgp_static->router_mac, NULL, 0);
12470 if (bgp_static->eth_s_id)
12471 esi = esi2str(bgp_static->eth_s_id);
12472 p = &rn->p;
12473 prd = (struct prefix_rd *)&prn->p;
d62a17ae 12474
ea47320b 12475 /* "network" configuration display. */
06b9f471 12476 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
12477 if (p->u.prefix_evpn.route_type == 5) {
12478 char local_buf[PREFIX_STRLEN];
3714a385 12479 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
12480 struct prefix_evpn *)p)
12481 ? AF_INET
12482 : AF_INET6;
3714a385 12483 inet_ntop(family,
12484 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a
PZ
12485 local_buf, PREFIX_STRLEN);
12486 sprintf(buf, "%s/%u", local_buf,
3714a385 12487 p->u.prefix_evpn.prefix_addr.ip_prefix_length);
197cb530
PG
12488 } else {
12489 prefix2str(p, buf, sizeof(buf));
12490 }
ea47320b 12491
a4d82a8a
PZ
12492 if (bgp_static->gatewayIp.family == AF_INET
12493 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
12494 inet_ntop(bgp_static->gatewayIp.family,
12495 &bgp_static->gatewayIp.u.prefix, buf2,
12496 sizeof(buf2));
ea47320b 12497 vty_out(vty,
7bcc8dac 12498 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 12499 buf, rdbuf,
12500 p->u.prefix_evpn.prefix_addr.eth_tag,
60466a63 12501 decode_label(&bgp_static->label), esi, buf2,
ea47320b
DL
12502 macrouter);
12503
0a22ddfb
QY
12504 XFREE(MTYPE_TMP, macrouter);
12505 XFREE(MTYPE_TMP, esi);
ea47320b
DL
12506 }
12507 }
3da6fcd5
PG
12508}
12509
718e3744 12510/* Configuration of static route announcement and aggregate
12511 information. */
2b791107
DL
12512void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
12513 safi_t safi)
d62a17ae 12514{
12515 struct bgp_node *rn;
12516 struct prefix *p;
12517 struct bgp_static *bgp_static;
12518 struct bgp_aggregate *bgp_aggregate;
12519 char buf[SU_ADDRSTRLEN];
12520
2b791107
DL
12521 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
12522 bgp_config_write_network_vpn(vty, bgp, afi, safi);
12523 return;
12524 }
d62a17ae 12525
2b791107
DL
12526 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
12527 bgp_config_write_network_evpn(vty, bgp, afi, safi);
12528 return;
12529 }
d62a17ae 12530
12531 /* Network configuration. */
12532 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
ea47320b 12533 rn = bgp_route_next(rn)) {
5a8ba9fc 12534 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12535 if (bgp_static == NULL)
ea47320b 12536 continue;
d62a17ae 12537
ea47320b 12538 p = &rn->p;
d62a17ae 12539
d8a9922d
DS
12540 vty_out(vty, " network %s/%d",
12541 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
12542 p->prefixlen);
d62a17ae 12543
ea47320b
DL
12544 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
12545 vty_out(vty, " label-index %u",
12546 bgp_static->label_index);
d62a17ae 12547
ea47320b
DL
12548 if (bgp_static->rmap.name)
12549 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
12550
12551 if (bgp_static->backdoor)
12552 vty_out(vty, " backdoor");
718e3744 12553
ea47320b
DL
12554 vty_out(vty, "\n");
12555 }
12556
d62a17ae 12557 /* Aggregate-address configuration. */
12558 for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn;
ea47320b 12559 rn = bgp_route_next(rn)) {
b613a918 12560 bgp_aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 12561 if (bgp_aggregate == NULL)
ea47320b 12562 continue;
d62a17ae 12563
ea47320b 12564 p = &rn->p;
d62a17ae 12565
d8a9922d
DS
12566 vty_out(vty, " aggregate-address %s/%d",
12567 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
12568 p->prefixlen);
d62a17ae 12569
ea47320b
DL
12570 if (bgp_aggregate->as_set)
12571 vty_out(vty, " as-set");
d62a17ae 12572
ea47320b
DL
12573 if (bgp_aggregate->summary_only)
12574 vty_out(vty, " summary-only");
718e3744 12575
20894f50
DA
12576 if (bgp_aggregate->rmap.name)
12577 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
12578
ea47320b
DL
12579 vty_out(vty, "\n");
12580 }
d62a17ae 12581}
734b349e 12582
2b791107 12583void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 12584 safi_t safi)
d62a17ae 12585{
12586 struct bgp_node *rn;
12587 struct bgp_distance *bdistance;
12588
12589 /* Distance configuration. */
12590 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
12591 && bgp->distance_local[afi][safi]
12592 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
12593 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
12594 || bgp->distance_local[afi][safi]
12595 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 12596 vty_out(vty, " distance bgp %d %d %d\n",
12597 bgp->distance_ebgp[afi][safi],
12598 bgp->distance_ibgp[afi][safi],
12599 bgp->distance_local[afi][safi]);
12600 }
734b349e 12601
d62a17ae 12602 for (rn = bgp_table_top(bgp_distance_table[afi][safi]); rn;
ca2e160d 12603 rn = bgp_route_next(rn)) {
5b00b40e 12604 bdistance = bgp_node_get_bgp_distance_info(rn);
ca2e160d 12605 if (bdistance != NULL) {
d62a17ae 12606 char buf[PREFIX_STRLEN];
12607
d62a17ae 12608 vty_out(vty, " distance %d %s %s\n",
12609 bdistance->distance,
12610 prefix2str(&rn->p, buf, sizeof(buf)),
12611 bdistance->access_list ? bdistance->access_list
12612 : "");
12613 }
ca2e160d 12614 }
718e3744 12615}
12616
12617/* Allocate routing table structure and install commands. */
d62a17ae 12618void bgp_route_init(void)
12619{
12620 afi_t afi;
12621 safi_t safi;
12622
12623 /* Init BGP distance table. */
05c7a1cc 12624 FOREACH_AFI_SAFI (afi, safi)
960035b2 12625 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 12626
12627 /* IPv4 BGP commands. */
12628 install_element(BGP_NODE, &bgp_table_map_cmd);
12629 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 12630 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 12631
12632 install_element(BGP_NODE, &aggregate_address_cmd);
12633 install_element(BGP_NODE, &aggregate_address_mask_cmd);
12634 install_element(BGP_NODE, &no_aggregate_address_cmd);
12635 install_element(BGP_NODE, &no_aggregate_address_mask_cmd);
12636
12637 /* IPv4 unicast configuration. */
12638 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
12639 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 12640 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 12641
12642 install_element(BGP_IPV4_NODE, &aggregate_address_cmd);
12643 install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd);
12644 install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd);
12645 install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
12646
12647 /* IPv4 multicast configuration. */
12648 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
12649 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 12650 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
d62a17ae 12651 install_element(BGP_IPV4M_NODE, &aggregate_address_cmd);
12652 install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
12653 install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd);
12654 install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
12655
12656 /* IPv4 labeled-unicast configuration. */
12657 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
12658 install_element(VIEW_NODE, &show_ip_bgp_cmd);
7b2ff250 12659 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 12660 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
12661 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
12662
12663 install_element(VIEW_NODE,
12664 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
12665 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
12666 install_element(VIEW_NODE,
12667 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 12668#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 12669 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 12670#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 12671 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
12672 install_element(VIEW_NODE,
44c69747 12673 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 12674
d62a17ae 12675 /* BGP dampening clear commands */
12676 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
12677 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 12678
d62a17ae 12679 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
12680 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
12681
12682 /* prefix count */
12683 install_element(ENABLE_NODE,
12684 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 12685#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 12686 install_element(ENABLE_NODE,
12687 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 12688#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 12689
d62a17ae 12690 /* New config IPv6 BGP commands. */
12691 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
12692 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 12693 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 12694
12695 install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
12696 install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
12697
12698 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 12699
d62a17ae 12700 install_element(BGP_NODE, &bgp_distance_cmd);
12701 install_element(BGP_NODE, &no_bgp_distance_cmd);
12702 install_element(BGP_NODE, &bgp_distance_source_cmd);
12703 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
12704 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
12705 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
12706 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
12707 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
12708 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
12709 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
12710 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
12711 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
12712 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
12713 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
12714 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
12715 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
12716 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
12717 install_element(BGP_IPV4M_NODE,
12718 &no_bgp_distance_source_access_list_cmd);
12719 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
12720 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
12721 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
12722 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
12723 install_element(BGP_IPV6_NODE,
12724 &ipv6_bgp_distance_source_access_list_cmd);
12725 install_element(BGP_IPV6_NODE,
12726 &no_ipv6_bgp_distance_source_access_list_cmd);
12727 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
12728 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
12729 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
12730 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
12731 install_element(BGP_IPV6M_NODE,
12732 &ipv6_bgp_distance_source_access_list_cmd);
12733 install_element(BGP_IPV6M_NODE,
12734 &no_ipv6_bgp_distance_source_access_list_cmd);
12735
12736 install_element(BGP_NODE, &bgp_damp_set_cmd);
12737 install_element(BGP_NODE, &bgp_damp_unset_cmd);
12738 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
12739 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
12740
12741 /* IPv4 Multicast Mode */
12742 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
12743 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
12744
12745 /* Large Communities */
12746 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
12747 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
12748
12749 /* show bgp ipv4 flowspec detailed */
12750 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
12751
825d9834 12752 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 12753}
12754
12755void bgp_route_finish(void)
12756{
12757 afi_t afi;
12758 safi_t safi;
12759
05c7a1cc
QY
12760 FOREACH_AFI_SAFI (afi, safi) {
12761 bgp_table_unlock(bgp_distance_table[afi][safi]);
12762 bgp_distance_table[afi][safi] = NULL;
12763 }
228da428 12764}