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