]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
bgpd: Reflect the distance in RIB when it is changed for an arbitrary afi/safi
[mirror_frr.git] / bgpd / bgp_route.c
CommitLineData
718e3744 1/* BGP routing information
896014f4
DL
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
718e3744 21
22#include <zebra.h>
8d0ab76d 23#include <math.h>
718e3744 24
2618a52e 25#include "printfrr.h"
718e3744 26#include "prefix.h"
27#include "linklist.h"
28#include "memory.h"
29#include "command.h"
30#include "stream.h"
31#include "filter.h"
718e3744 32#include "log.h"
33#include "routemap.h"
34#include "buffer.h"
35#include "sockunion.h"
36#include "plist.h"
37#include "thread.h"
200df115 38#include "workqueue.h"
3f9c7369 39#include "queue.h"
6e919709 40#include "memory.h"
4dcadbef 41#include "lib/json.h"
d8d084d9 42#include "lib_errors.h"
718e3744 43
44#include "bgpd/bgpd.h"
45#include "bgpd/bgp_table.h"
46#include "bgpd/bgp_route.h"
47#include "bgpd/bgp_attr.h"
48#include "bgpd/bgp_debug.h"
14454c9f 49#include "bgpd/bgp_errors.h"
718e3744 50#include "bgpd/bgp_aspath.h"
51#include "bgpd/bgp_regex.h"
52#include "bgpd/bgp_community.h"
53#include "bgpd/bgp_ecommunity.h"
57d187bc 54#include "bgpd/bgp_lcommunity.h"
718e3744 55#include "bgpd/bgp_clist.h"
56#include "bgpd/bgp_packet.h"
57#include "bgpd/bgp_filter.h"
58#include "bgpd/bgp_fsm.h"
59#include "bgpd/bgp_mplsvpn.h"
60#include "bgpd/bgp_nexthop.h"
61#include "bgpd/bgp_damp.h"
62#include "bgpd/bgp_advertise.h"
63#include "bgpd/bgp_zebra.h"
0a486e5f 64#include "bgpd/bgp_vty.h"
96450faf 65#include "bgpd/bgp_mpath.h"
fc9a856f 66#include "bgpd/bgp_nht.h"
3f9c7369 67#include "bgpd/bgp_updgrp.h"
cd1964ff 68#include "bgpd/bgp_label.h"
dcc68b5e 69#include "bgpd/bgp_addpath.h"
4e802e66 70#include "bgpd/bgp_mac.h"
718e3744 71
65efcfce 72#if ENABLE_BGP_VNC
f8b6f499
LB
73#include "bgpd/rfapi/rfapi_backend.h"
74#include "bgpd/rfapi/vnc_import_bgp.h"
75#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 76#endif
aee875b5
PG
77#include "bgpd/bgp_encap_types.h"
78#include "bgpd/bgp_encap_tlv.h"
684a7227 79#include "bgpd/bgp_evpn.h"
3da6fcd5 80#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 81#include "bgpd/bgp_flowspec.h"
98a9dbc7 82#include "bgpd/bgp_flowspec_util.h"
45918cfb 83#include "bgpd/bgp_pbr.h"
65efcfce 84
e2a86ad9
DS
85#ifndef VTYSH_EXTRACT_PL
86#include "bgpd/bgp_route_clippy.c"
87#endif
aee875b5 88
718e3744 89/* Extern from bgp_dump.c */
dde72586
SH
90extern const char *bgp_origin_str[];
91extern const char *bgp_origin_long_str[];
6b0655a2 92
b7d08f5a 93/* PMSI strings. */
94#define PMSI_TNLTYPE_STR_NO_INFO "No info"
95#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
96static const struct message bgp_pmsi_tnltype_str[] = {
97 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
98 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
99 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
100 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
101 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
102 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
103 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
104 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 105 {0}
106};
b7d08f5a 107
9df8b37c
PZ
108#define VRFID_NONE_STR "-"
109
4a11bf2c
DL
110DEFINE_HOOK(bgp_process,
111 (struct bgp *bgp, afi_t afi, safi_t safi,
112 struct bgp_node *bn, struct peer *peer, bool withdraw),
113 (bgp, afi, safi, bn, peer, withdraw))
114
115
d62a17ae 116struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
117 safi_t safi, struct prefix *p,
118 struct prefix_rd *prd)
119{
120 struct bgp_node *rn;
121 struct bgp_node *prn = NULL;
122
123 assert(table);
124 if (!table)
125 return NULL;
126
127 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
128 || (safi == SAFI_EVPN)) {
129 prn = bgp_node_get(table, (struct prefix *)prd);
130
67009e22
DS
131 if (!bgp_node_has_bgp_path_info_data(prn))
132 bgp_node_set_bgp_table_info(
133 prn, bgp_table_init(table->bgp, afi, safi));
d62a17ae 134 else
135 bgp_unlock_node(prn);
67009e22 136 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 137 }
718e3744 138
d62a17ae 139 rn = bgp_node_get(table, p);
718e3744 140
d62a17ae 141 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
142 || (safi == SAFI_EVPN))
143 rn->prn = prn;
718e3744 144
d62a17ae 145 return rn;
718e3744 146}
6b0655a2 147
d62a17ae 148struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
149 safi_t safi, struct prefix *p,
150 struct prefix_rd *prd)
128ea8ab 151{
d62a17ae 152 struct bgp_node *rn;
153 struct bgp_node *prn = NULL;
128ea8ab 154
d62a17ae 155 if (!table)
156 return NULL;
128ea8ab 157
d62a17ae 158 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
159 || (safi == SAFI_EVPN)) {
160 prn = bgp_node_lookup(table, (struct prefix *)prd);
161 if (!prn)
162 return NULL;
128ea8ab 163
6f94b685 164 if (!bgp_node_has_bgp_path_info_data(prn)) {
d62a17ae 165 bgp_unlock_node(prn);
166 return NULL;
167 }
128ea8ab 168
67009e22 169 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 170 }
128ea8ab 171
d62a17ae 172 rn = bgp_node_lookup(table, p);
128ea8ab 173
d62a17ae 174 return rn;
128ea8ab 175}
176
18ee8310
DS
177/* Allocate bgp_path_info_extra */
178static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 179{
4b7e6066
DS
180 struct bgp_path_info_extra *new;
181 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
182 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
183 new->label[0] = MPLS_INVALID_LABEL;
184 new->num_labels = 0;
3e3708cb
PG
185 new->bgp_fs_pbr = NULL;
186 new->bgp_fs_iprule = NULL;
d62a17ae 187 return new;
fb982c25
PJ
188}
189
a2e219fe 190void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 191{
4b7e6066 192 struct bgp_path_info_extra *e;
d62a17ae 193
c93a3b77
DS
194 if (!extra || !*extra)
195 return;
d62a17ae 196
c93a3b77
DS
197 e = *extra;
198 if (e->damp_info)
199 bgp_damp_info_free(e->damp_info, 0);
d62a17ae 200
c93a3b77
DS
201 e->damp_info = NULL;
202 if (e->parent) {
40381db7 203 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 204
40381db7 205 if (bpi->net) {
0e70e6c8
DL
206 /* FIXME: since multiple e may have the same e->parent
207 * and e->parent->net is holding a refcount for each
208 * of them, we need to do some fudging here.
209 *
40381db7
DS
210 * WARNING: if bpi->net->lock drops to 0, bpi may be
211 * freed as well (because bpi->net was holding the
212 * last reference to bpi) => write after free!
0e70e6c8
DL
213 */
214 unsigned refcount;
215
40381db7
DS
216 bpi = bgp_path_info_lock(bpi);
217 refcount = bpi->net->lock - 1;
218 bgp_unlock_node((struct bgp_node *)bpi->net);
0e70e6c8 219 if (!refcount)
40381db7
DS
220 bpi->net = NULL;
221 bgp_path_info_unlock(bpi);
0e70e6c8 222 }
18ee8310 223 bgp_path_info_unlock(e->parent);
c93a3b77 224 e->parent = NULL;
d62a17ae 225 }
c93a3b77
DS
226
227 if (e->bgp_orig)
228 bgp_unlock(e->bgp_orig);
c26edcda 229
ce3c0614
PG
230 if ((*extra)->bgp_fs_iprule)
231 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 232 if ((*extra)->bgp_fs_pbr)
6a154c88 233 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77
DS
234 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
235
236 *extra = NULL;
fb982c25
PJ
237}
238
18ee8310
DS
239/* Get bgp_path_info extra information for the given bgp_path_info, lazy
240 * allocated if required.
fb982c25 241 */
40381db7 242struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 243{
40381db7
DS
244 if (!pi->extra)
245 pi->extra = bgp_path_info_extra_new();
246 return pi->extra;
fb982c25
PJ
247}
248
718e3744 249/* Free bgp route information. */
9b6d8fcf 250static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 251{
05864da7 252 bgp_attr_unintern(&path->attr);
fb018d25 253
9b6d8fcf
DS
254 bgp_unlink_nexthop(path);
255 bgp_path_info_extra_free(&path->extra);
256 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
257 if (path->net)
258 bgp_addpath_free_info_data(&path->tx_addpath,
259 &path->net->tx_addpath);
718e3744 260
9b6d8fcf 261 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 262
9b6d8fcf 263 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 264}
265
9b6d8fcf 266struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 267{
9b6d8fcf
DS
268 path->lock++;
269 return path;
200df115 270}
271
9b6d8fcf 272struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 273{
9b6d8fcf
DS
274 assert(path && path->lock > 0);
275 path->lock--;
d62a17ae 276
9b6d8fcf 277 if (path->lock == 0) {
200df115 278#if 0
279 zlog_debug ("%s: unlocked and freeing", __func__);
280 zlog_backtrace (LOG_DEBUG);
281#endif
9b6d8fcf 282 bgp_path_info_free(path);
d62a17ae 283 return NULL;
284 }
200df115 285
286#if 0
9b6d8fcf 287 if (path->lock == 1)
200df115 288 {
289 zlog_debug ("%s: unlocked to 1", __func__);
290 zlog_backtrace (LOG_DEBUG);
291 }
292#endif
d62a17ae 293
9b6d8fcf 294 return path;
200df115 295}
296
40381db7 297void bgp_path_info_add(struct bgp_node *rn, struct bgp_path_info *pi)
718e3744 298{
4b7e6066 299 struct bgp_path_info *top;
718e3744 300
6f94b685 301 top = bgp_node_get_bgp_path_info(rn);
d62a17ae 302
6f94b685 303 pi->next = top;
40381db7 304 pi->prev = NULL;
d62a17ae 305 if (top)
40381db7 306 top->prev = pi;
6f94b685 307 bgp_node_set_bgp_path_info(rn, pi);
d62a17ae 308
40381db7 309 bgp_path_info_lock(pi);
d62a17ae 310 bgp_lock_node(rn);
40381db7 311 peer_lock(pi->peer); /* bgp_path_info peer reference */
718e3744 312}
313
d62a17ae 314/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 315 completion callback *only* */
40381db7 316void bgp_path_info_reap(struct bgp_node *rn, struct bgp_path_info *pi)
718e3744 317{
40381db7
DS
318 if (pi->next)
319 pi->next->prev = pi->prev;
320 if (pi->prev)
321 pi->prev->next = pi->next;
d62a17ae 322 else
6f94b685 323 bgp_node_set_bgp_path_info(rn, pi->next);
d62a17ae 324
40381db7
DS
325 bgp_path_info_mpath_dequeue(pi);
326 bgp_path_info_unlock(pi);
d62a17ae 327 bgp_unlock_node(rn);
718e3744 328}
329
40381db7 330void bgp_path_info_delete(struct bgp_node *rn, struct bgp_path_info *pi)
b40d939b 331{
40381db7 332 bgp_path_info_set_flag(rn, pi, BGP_PATH_REMOVED);
d62a17ae 333 /* set of previous already took care of pcount */
40381db7 334 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 335}
336
18ee8310 337/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
338 called when a route is deleted and then quickly re-added before the
339 deletion has been processed */
40381db7 340void bgp_path_info_restore(struct bgp_node *rn, struct bgp_path_info *pi)
8d45210e 341{
40381db7 342 bgp_path_info_unset_flag(rn, pi, BGP_PATH_REMOVED);
d62a17ae 343 /* unset of previous already took care of pcount */
40381db7 344 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
345}
346
d62a17ae 347/* Adjust pcount as required */
40381db7 348static void bgp_pcount_adjust(struct bgp_node *rn, struct bgp_path_info *pi)
1a392d46 349{
d62a17ae 350 struct bgp_table *table;
67174041 351
d62a17ae 352 assert(rn && bgp_node_table(rn));
40381db7 353 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 354
d62a17ae 355 table = bgp_node_table(rn);
67174041 356
40381db7 357 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 358 return;
359
40381db7
DS
360 if (!BGP_PATH_COUNTABLE(pi)
361 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 362
40381db7 363 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 364
365 /* slight hack, but more robust against errors. */
40381db7
DS
366 if (pi->peer->pcount[table->afi][table->safi])
367 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 368 else
450971aa 369 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 370 "Asked to decrement 0 prefix count for peer");
40381db7
DS
371 } else if (BGP_PATH_COUNTABLE(pi)
372 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
373 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
374 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 375 }
1a392d46
PJ
376}
377
40381db7
DS
378static int bgp_label_index_differs(struct bgp_path_info *pi1,
379 struct bgp_path_info *pi2)
28d58fd7 380{
40381db7 381 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 382}
1a392d46 383
18ee8310 384/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
385 * This is here primarily to keep prefix-count in check.
386 */
40381db7 387void bgp_path_info_set_flag(struct bgp_node *rn, struct bgp_path_info *pi,
18ee8310 388 uint32_t flag)
1a392d46 389{
40381db7 390 SET_FLAG(pi->flags, flag);
d62a17ae 391
392 /* early bath if we know it's not a flag that changes countability state
393 */
394 if (!CHECK_FLAG(flag,
1defdda8 395 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 396 return;
397
40381db7 398 bgp_pcount_adjust(rn, pi);
1a392d46
PJ
399}
400
40381db7 401void bgp_path_info_unset_flag(struct bgp_node *rn, struct bgp_path_info *pi,
18ee8310 402 uint32_t flag)
1a392d46 403{
40381db7 404 UNSET_FLAG(pi->flags, flag);
d62a17ae 405
406 /* early bath if we know it's not a flag that changes countability state
407 */
408 if (!CHECK_FLAG(flag,
1defdda8 409 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 410 return;
411
40381db7 412 bgp_pcount_adjust(rn, pi);
1a392d46
PJ
413}
414
718e3744 415/* Get MED value. If MED value is missing and "bgp bestpath
416 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 417static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 418{
419 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
420 return attr->med;
421 else {
422 if (bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST))
423 return BGP_MED_MAX;
424 else
425 return 0;
426 }
718e3744 427}
428
40381db7 429void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf)
2ec1e66f 430{
40381db7
DS
431 if (pi->addpath_rx_id)
432 sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
433 pi->addpath_rx_id);
d62a17ae 434 else
40381db7 435 sprintf(buf, "path %s", pi->peer->host);
d62a17ae 436}
9fbdd100 437
d62a17ae 438/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
439 */
18ee8310
DS
440static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
441 struct bgp_path_info *exist, int *paths_eq,
442 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
443 char *pfx_buf, afi_t afi, safi_t safi,
444 enum bgp_path_selection_reason *reason)
d62a17ae 445{
446 struct attr *newattr, *existattr;
447 bgp_peer_sort_t new_sort;
448 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
449 uint32_t new_pref;
450 uint32_t exist_pref;
451 uint32_t new_med;
452 uint32_t exist_med;
453 uint32_t new_weight;
454 uint32_t exist_weight;
d62a17ae 455 uint32_t newm, existm;
456 struct in_addr new_id;
457 struct in_addr exist_id;
458 int new_cluster;
459 int exist_cluster;
460 int internal_as_route;
461 int confed_as_route;
04d14c8b 462 int ret = 0;
d62a17ae 463 char new_buf[PATH_ADDPATH_STR_BUFFER];
464 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
465 uint32_t new_mm_seq;
466 uint32_t exist_mm_seq;
6d8c603a 467 int nh_cmp;
d62a17ae 468
469 *paths_eq = 0;
470
471 /* 0. Null check. */
472 if (new == NULL) {
fdf81fa0 473 *reason = bgp_path_selection_none;
d62a17ae 474 if (debug)
475 zlog_debug("%s: new is NULL", pfx_buf);
476 return 0;
477 }
2ec1e66f 478
d62a17ae 479 if (debug)
18ee8310 480 bgp_path_info_path_with_addpath_rx_str(new, new_buf);
718e3744 481
d62a17ae 482 if (exist == NULL) {
fdf81fa0 483 *reason = bgp_path_selection_first;
d62a17ae 484 if (debug)
485 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
486 new_buf);
487 return 1;
488 }
2ec1e66f 489
d62a17ae 490 if (debug) {
18ee8310 491 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
d62a17ae 492 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
493 pfx_buf, new_buf, new->flags, exist_buf,
494 exist->flags);
495 }
8ff56318 496
d62a17ae 497 newattr = new->attr;
498 existattr = exist->attr;
499
500 /* For EVPN routes, we cannot just go by local vs remote, we have to
501 * look at the MAC mobility sequence number, if present.
502 */
503 if (safi == SAFI_EVPN) {
504 /* This is an error condition described in RFC 7432 Section
505 * 15.2. The RFC
506 * states that in this scenario "the PE MUST alert the operator"
507 * but it
508 * does not state what other action to take. In order to provide
509 * some
510 * consistency in this scenario we are going to prefer the path
511 * with the
512 * sticky flag.
513 */
514 if (newattr->sticky != existattr->sticky) {
515 if (!debug) {
516 prefix2str(&new->net->p, pfx_buf,
517 sizeof(*pfx_buf)
518 * PREFIX2STR_BUFFER);
18ee8310
DS
519 bgp_path_info_path_with_addpath_rx_str(new,
520 new_buf);
521 bgp_path_info_path_with_addpath_rx_str(
522 exist, exist_buf);
d62a17ae 523 }
524
525 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 526 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
527 if (debug)
528 zlog_debug(
529 "%s: %s wins over %s due to sticky MAC flag",
530 pfx_buf, new_buf, exist_buf);
d62a17ae 531 return 1;
532 }
533
534 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 535 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
536 if (debug)
537 zlog_debug(
538 "%s: %s loses to %s due to sticky MAC flag",
539 pfx_buf, new_buf, exist_buf);
d62a17ae 540 return 0;
541 }
542 }
128ea8ab 543
d62a17ae 544 new_mm_seq = mac_mobility_seqnum(newattr);
545 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 546
d62a17ae 547 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 548 *reason = bgp_path_selection_evpn_seq;
d62a17ae 549 if (debug)
550 zlog_debug(
551 "%s: %s wins over %s due to MM seq %u > %u",
552 pfx_buf, new_buf, exist_buf, new_mm_seq,
553 exist_mm_seq);
554 return 1;
555 }
8ff56318 556
d62a17ae 557 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 558 *reason = bgp_path_selection_evpn_seq;
d62a17ae 559 if (debug)
560 zlog_debug(
561 "%s: %s loses to %s due to MM seq %u < %u",
562 pfx_buf, new_buf, exist_buf, new_mm_seq,
563 exist_mm_seq);
564 return 0;
565 }
6d8c603a
AK
566
567 /*
568 * if sequence numbers are the same path with the lowest IP
569 * wins
570 */
571 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
572 if (nh_cmp < 0) {
fdf81fa0 573 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
574 if (debug)
575 zlog_debug(
576 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
577 pfx_buf, new_buf, exist_buf, new_mm_seq,
578 inet_ntoa(new->attr->nexthop));
579 return 1;
580 }
581 if (nh_cmp > 0) {
fdf81fa0 582 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
583 if (debug)
584 zlog_debug(
585 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
586 pfx_buf, new_buf, exist_buf, new_mm_seq,
587 inet_ntoa(new->attr->nexthop));
588 return 0;
589 }
d62a17ae 590 }
9fbdd100 591
d62a17ae 592 /* 1. Weight check. */
d62a17ae 593 new_weight = newattr->weight;
594 exist_weight = existattr->weight;
8ff56318 595
d62a17ae 596 if (new_weight > exist_weight) {
fdf81fa0 597 *reason = bgp_path_selection_weight;
d62a17ae 598 if (debug)
599 zlog_debug("%s: %s wins over %s due to weight %d > %d",
600 pfx_buf, new_buf, exist_buf, new_weight,
601 exist_weight);
602 return 1;
603 }
718e3744 604
d62a17ae 605 if (new_weight < exist_weight) {
fdf81fa0 606 *reason = bgp_path_selection_weight;
d62a17ae 607 if (debug)
608 zlog_debug("%s: %s loses to %s due to weight %d < %d",
609 pfx_buf, new_buf, exist_buf, new_weight,
610 exist_weight);
611 return 0;
612 }
9fbdd100 613
d62a17ae 614 /* 2. Local preference check. */
615 new_pref = exist_pref = bgp->default_local_pref;
616
617 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
618 new_pref = newattr->local_pref;
619 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
620 exist_pref = existattr->local_pref;
621
622 if (new_pref > exist_pref) {
fdf81fa0 623 *reason = bgp_path_selection_local_pref;
d62a17ae 624 if (debug)
625 zlog_debug(
626 "%s: %s wins over %s due to localpref %d > %d",
627 pfx_buf, new_buf, exist_buf, new_pref,
628 exist_pref);
629 return 1;
630 }
718e3744 631
d62a17ae 632 if (new_pref < exist_pref) {
fdf81fa0 633 *reason = bgp_path_selection_local_pref;
d62a17ae 634 if (debug)
635 zlog_debug(
636 "%s: %s loses to %s due to localpref %d < %d",
637 pfx_buf, new_buf, exist_buf, new_pref,
638 exist_pref);
639 return 0;
640 }
9fbdd100 641
d62a17ae 642 /* 3. Local route check. We prefer:
643 * - BGP_ROUTE_STATIC
644 * - BGP_ROUTE_AGGREGATE
645 * - BGP_ROUTE_REDISTRIBUTE
646 */
90f4f482 647 if (!(new->sub_type == BGP_ROUTE_NORMAL ||
648 new->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 649 *reason = bgp_path_selection_local_route;
d62a17ae 650 if (debug)
651 zlog_debug(
652 "%s: %s wins over %s due to preferred BGP_ROUTE type",
653 pfx_buf, new_buf, exist_buf);
654 return 1;
655 }
718e3744 656
90f4f482 657 if (!(exist->sub_type == BGP_ROUTE_NORMAL ||
88493076 658 exist->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 659 *reason = bgp_path_selection_local_route;
d62a17ae 660 if (debug)
661 zlog_debug(
662 "%s: %s loses to %s due to preferred BGP_ROUTE type",
663 pfx_buf, new_buf, exist_buf);
664 return 0;
6811845b 665 }
718e3744 666
d62a17ae 667 /* 4. AS path length check. */
668 if (!bgp_flag_check(bgp, BGP_FLAG_ASPATH_IGNORE)) {
669 int exist_hops = aspath_count_hops(existattr->aspath);
670 int exist_confeds = aspath_count_confeds(existattr->aspath);
671
672 if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_CONFED)) {
673 int aspath_hops;
674
675 aspath_hops = aspath_count_hops(newattr->aspath);
676 aspath_hops += aspath_count_confeds(newattr->aspath);
677
678 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 679 *reason = bgp_path_selection_confed_as_path;
d62a17ae 680 if (debug)
681 zlog_debug(
682 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
683 pfx_buf, new_buf, exist_buf,
684 aspath_hops,
685 (exist_hops + exist_confeds));
686 return 1;
687 }
688
689 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 690 *reason = bgp_path_selection_confed_as_path;
d62a17ae 691 if (debug)
692 zlog_debug(
693 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
694 pfx_buf, new_buf, exist_buf,
695 aspath_hops,
696 (exist_hops + exist_confeds));
697 return 0;
698 }
699 } else {
700 int newhops = aspath_count_hops(newattr->aspath);
701
702 if (newhops < exist_hops) {
fdf81fa0 703 *reason = bgp_path_selection_as_path;
d62a17ae 704 if (debug)
705 zlog_debug(
706 "%s: %s wins over %s due to aspath hopcount %d < %d",
707 pfx_buf, new_buf, exist_buf,
708 newhops, exist_hops);
709 return 1;
710 }
711
712 if (newhops > exist_hops) {
fdf81fa0 713 *reason = bgp_path_selection_as_path;
d62a17ae 714 if (debug)
715 zlog_debug(
716 "%s: %s loses to %s due to aspath hopcount %d > %d",
717 pfx_buf, new_buf, exist_buf,
718 newhops, exist_hops);
719 return 0;
720 }
721 }
722 }
9fbdd100 723
d62a17ae 724 /* 5. Origin check. */
725 if (newattr->origin < existattr->origin) {
fdf81fa0 726 *reason = bgp_path_selection_origin;
d62a17ae 727 if (debug)
728 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
729 pfx_buf, new_buf, exist_buf,
730 bgp_origin_long_str[newattr->origin],
731 bgp_origin_long_str[existattr->origin]);
732 return 1;
733 }
718e3744 734
d62a17ae 735 if (newattr->origin > existattr->origin) {
fdf81fa0 736 *reason = bgp_path_selection_origin;
d62a17ae 737 if (debug)
738 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
739 pfx_buf, new_buf, exist_buf,
740 bgp_origin_long_str[newattr->origin],
741 bgp_origin_long_str[existattr->origin]);
742 return 0;
743 }
718e3744 744
d62a17ae 745 /* 6. MED check. */
746 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
747 && aspath_count_hops(existattr->aspath) == 0);
748 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
749 && aspath_count_confeds(existattr->aspath) > 0
750 && aspath_count_hops(newattr->aspath) == 0
751 && aspath_count_hops(existattr->aspath) == 0);
752
753 if (bgp_flag_check(bgp, BGP_FLAG_ALWAYS_COMPARE_MED)
754 || (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED) && confed_as_route)
755 || aspath_cmp_left(newattr->aspath, existattr->aspath)
756 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
757 || internal_as_route) {
758 new_med = bgp_med_value(new->attr, bgp);
759 exist_med = bgp_med_value(exist->attr, bgp);
760
761 if (new_med < exist_med) {
fdf81fa0 762 *reason = bgp_path_selection_med;
d62a17ae 763 if (debug)
764 zlog_debug(
765 "%s: %s wins over %s due to MED %d < %d",
766 pfx_buf, new_buf, exist_buf, new_med,
767 exist_med);
768 return 1;
769 }
8ff56318 770
d62a17ae 771 if (new_med > exist_med) {
fdf81fa0 772 *reason = bgp_path_selection_med;
d62a17ae 773 if (debug)
774 zlog_debug(
775 "%s: %s loses to %s due to MED %d > %d",
776 pfx_buf, new_buf, exist_buf, new_med,
777 exist_med);
778 return 0;
779 }
780 }
9fbdd100 781
d62a17ae 782 /* 7. Peer type check. */
783 new_sort = new->peer->sort;
784 exist_sort = exist->peer->sort;
785
786 if (new_sort == BGP_PEER_EBGP
787 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 788 *reason = bgp_path_selection_peer;
d62a17ae 789 if (debug)
790 zlog_debug(
791 "%s: %s wins over %s due to eBGP peer > iBGP peer",
792 pfx_buf, new_buf, exist_buf);
793 return 1;
794 }
718e3744 795
d62a17ae 796 if (exist_sort == BGP_PEER_EBGP
797 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 798 *reason = bgp_path_selection_peer;
d62a17ae 799 if (debug)
800 zlog_debug(
801 "%s: %s loses to %s due to iBGP peer < eBGP peer",
802 pfx_buf, new_buf, exist_buf);
803 return 0;
804 }
8ff56318 805
d62a17ae 806 /* 8. IGP metric check. */
807 newm = existm = 0;
8ff56318 808
d62a17ae 809 if (new->extra)
810 newm = new->extra->igpmetric;
811 if (exist->extra)
812 existm = exist->extra->igpmetric;
9fbdd100 813
d62a17ae 814 if (newm < existm) {
815 if (debug)
816 zlog_debug(
817 "%s: %s wins over %s due to IGP metric %d < %d",
818 pfx_buf, new_buf, exist_buf, newm, existm);
819 ret = 1;
820 }
718e3744 821
d62a17ae 822 if (newm > existm) {
823 if (debug)
824 zlog_debug(
825 "%s: %s loses to %s due to IGP metric %d > %d",
826 pfx_buf, new_buf, exist_buf, newm, existm);
827 ret = 0;
5e242b0d 828 }
5e242b0d 829
d62a17ae 830 /* 9. Same IGP metric. Compare the cluster list length as
831 representative of IGP hops metric. Rewrite the metric value
832 pair (newm, existm) with the cluster list length. Prefer the
833 path with smaller cluster list length. */
834 if (newm == existm) {
835 if (peer_sort(new->peer) == BGP_PEER_IBGP
836 && peer_sort(exist->peer) == BGP_PEER_IBGP
837 && (mpath_cfg == NULL
838 || CHECK_FLAG(
839 mpath_cfg->ibgp_flags,
840 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
841 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
842 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
843
844 if (newm < existm) {
845 if (debug)
846 zlog_debug(
847 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
848 pfx_buf, new_buf, exist_buf,
849 newm, existm);
850 ret = 1;
851 }
852
853 if (newm > existm) {
854 if (debug)
855 zlog_debug(
856 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
857 pfx_buf, new_buf, exist_buf,
858 newm, existm);
859 ret = 0;
860 }
861 }
862 }
31a4638f 863
d62a17ae 864 /* 10. confed-external vs. confed-internal */
865 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
866 if (new_sort == BGP_PEER_CONFED
867 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 868 *reason = bgp_path_selection_confed;
d62a17ae 869 if (debug)
870 zlog_debug(
871 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
872 pfx_buf, new_buf, exist_buf);
873 return 1;
874 }
718e3744 875
d62a17ae 876 if (exist_sort == BGP_PEER_CONFED
877 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 878 *reason = bgp_path_selection_confed;
d62a17ae 879 if (debug)
880 zlog_debug(
881 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
882 pfx_buf, new_buf, exist_buf);
883 return 0;
884 }
885 }
718e3744 886
d62a17ae 887 /* 11. Maximum path check. */
888 if (newm == existm) {
889 /* If one path has a label but the other does not, do not treat
890 * them as equals for multipath
891 */
a4d82a8a 892 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 893 != (exist->extra
b57ba6d2 894 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 895 if (debug)
896 zlog_debug(
897 "%s: %s and %s cannot be multipath, one has a label while the other does not",
898 pfx_buf, new_buf, exist_buf);
899 } else if (bgp_flag_check(bgp,
900 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
901
902 /*
903 * For the two paths, all comparison steps till IGP
904 * metric
905 * have succeeded - including AS_PATH hop count. Since
906 * 'bgp
907 * bestpath as-path multipath-relax' knob is on, we
908 * don't need
909 * an exact match of AS_PATH. Thus, mark the paths are
910 * equal.
911 * That will trigger both these paths to get into the
912 * multipath
913 * array.
914 */
915 *paths_eq = 1;
916
917 if (debug)
918 zlog_debug(
919 "%s: %s and %s are equal via multipath-relax",
920 pfx_buf, new_buf, exist_buf);
921 } else if (new->peer->sort == BGP_PEER_IBGP) {
922 if (aspath_cmp(new->attr->aspath,
923 exist->attr->aspath)) {
924 *paths_eq = 1;
925
926 if (debug)
927 zlog_debug(
928 "%s: %s and %s are equal via matching aspaths",
929 pfx_buf, new_buf, exist_buf);
930 }
931 } else if (new->peer->as == exist->peer->as) {
932 *paths_eq = 1;
933
934 if (debug)
935 zlog_debug(
936 "%s: %s and %s are equal via same remote-as",
937 pfx_buf, new_buf, exist_buf);
938 }
939 } else {
940 /*
941 * TODO: If unequal cost ibgp multipath is enabled we can
942 * mark the paths as equal here instead of returning
943 */
944 if (debug) {
945 if (ret == 1)
946 zlog_debug(
947 "%s: %s wins over %s after IGP metric comparison",
948 pfx_buf, new_buf, exist_buf);
949 else
950 zlog_debug(
951 "%s: %s loses to %s after IGP metric comparison",
952 pfx_buf, new_buf, exist_buf);
953 }
fdf81fa0 954 *reason = bgp_path_selection_igp_metric;
d62a17ae 955 return ret;
956 }
718e3744 957
d62a17ae 958 /* 12. If both paths are external, prefer the path that was received
959 first (the oldest one). This step minimizes route-flap, since a
960 newer path won't displace an older one, even if it was the
961 preferred route based on the additional decision criteria below. */
962 if (!bgp_flag_check(bgp, BGP_FLAG_COMPARE_ROUTER_ID)
963 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 964 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 965 *reason = bgp_path_selection_older;
d62a17ae 966 if (debug)
967 zlog_debug(
968 "%s: %s wins over %s due to oldest external",
969 pfx_buf, new_buf, exist_buf);
970 return 1;
971 }
9fbdd100 972
1defdda8 973 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 974 *reason = bgp_path_selection_older;
d62a17ae 975 if (debug)
976 zlog_debug(
977 "%s: %s loses to %s due to oldest external",
978 pfx_buf, new_buf, exist_buf);
979 return 0;
980 }
981 }
718e3744 982
d62a17ae 983 /* 13. Router-ID comparision. */
984 /* If one of the paths is "stale", the corresponding peer router-id will
985 * be 0 and would always win over the other path. If originator id is
986 * used for the comparision, it will decide which path is better.
987 */
988 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
989 new_id.s_addr = newattr->originator_id.s_addr;
990 else
991 new_id.s_addr = new->peer->remote_id.s_addr;
992 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
993 exist_id.s_addr = existattr->originator_id.s_addr;
994 else
995 exist_id.s_addr = exist->peer->remote_id.s_addr;
996
997 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 998 *reason = bgp_path_selection_router_id;
d62a17ae 999 if (debug)
1000 zlog_debug(
1001 "%s: %s wins over %s due to Router-ID comparison",
1002 pfx_buf, new_buf, exist_buf);
1003 return 1;
1004 }
718e3744 1005
d62a17ae 1006 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1007 *reason = bgp_path_selection_router_id;
d62a17ae 1008 if (debug)
1009 zlog_debug(
1010 "%s: %s loses to %s due to Router-ID comparison",
1011 pfx_buf, new_buf, exist_buf);
1012 return 0;
1013 }
9fbdd100 1014
d62a17ae 1015 /* 14. Cluster length comparision. */
1016 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1017 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1018
1019 if (new_cluster < exist_cluster) {
fdf81fa0 1020 *reason = bgp_path_selection_cluster_length;
d62a17ae 1021 if (debug)
1022 zlog_debug(
1023 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1024 pfx_buf, new_buf, exist_buf, new_cluster,
1025 exist_cluster);
1026 return 1;
1027 }
718e3744 1028
d62a17ae 1029 if (new_cluster > exist_cluster) {
fdf81fa0 1030 *reason = bgp_path_selection_cluster_length;
d62a17ae 1031 if (debug)
1032 zlog_debug(
1033 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1034 pfx_buf, new_buf, exist_buf, new_cluster,
1035 exist_cluster);
1036 return 0;
1037 }
9fbdd100 1038
d62a17ae 1039 /* 15. Neighbor address comparision. */
1040 /* Do this only if neither path is "stale" as stale paths do not have
1041 * valid peer information (as the connection may or may not be up).
1042 */
1defdda8 1043 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1044 *reason = bgp_path_selection_stale;
d62a17ae 1045 if (debug)
1046 zlog_debug(
1047 "%s: %s wins over %s due to latter path being STALE",
1048 pfx_buf, new_buf, exist_buf);
1049 return 1;
1050 }
0de5153c 1051
1defdda8 1052 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1053 *reason = bgp_path_selection_stale;
d62a17ae 1054 if (debug)
1055 zlog_debug(
1056 "%s: %s loses to %s due to former path being STALE",
1057 pfx_buf, new_buf, exist_buf);
1058 return 0;
1059 }
718e3744 1060
d62a17ae 1061 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1062 if (new->peer->su_remote == NULL) {
1063 *reason = bgp_path_selection_local_configured;
d62a17ae 1064 return 0;
fdf81fa0
DS
1065 }
1066 if (exist->peer->su_remote == NULL) {
1067 *reason = bgp_path_selection_local_configured;
d62a17ae 1068 return 1;
fdf81fa0 1069 }
9fbdd100 1070
d62a17ae 1071 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1072
1073 if (ret == 1) {
fdf81fa0 1074 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1075 if (debug)
1076 zlog_debug(
1077 "%s: %s loses to %s due to Neighor IP comparison",
1078 pfx_buf, new_buf, exist_buf);
1079 return 0;
1080 }
1081
1082 if (ret == -1) {
fdf81fa0 1083 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1084 if (debug)
1085 zlog_debug(
1086 "%s: %s wins over %s due to Neighor IP comparison",
1087 pfx_buf, new_buf, exist_buf);
1088 return 1;
1089 }
9fbdd100 1090
fdf81fa0 1091 *reason = bgp_path_selection_default;
d62a17ae 1092 if (debug)
1093 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1094 pfx_buf, new_buf, exist_buf);
718e3744 1095
d62a17ae 1096 return 1;
718e3744 1097}
1098
65efcfce
LB
1099/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1100 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1101 * multipath is enabled
65efcfce 1102 * This version is compatible with */
18ee8310
DS
1103int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1104 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1105 afi_t afi, safi_t safi,
1106 enum bgp_path_selection_reason *reason)
d62a17ae 1107{
1108 int paths_eq;
1109 int ret;
18ee8310 1110 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1111 afi, safi, reason);
d62a17ae 1112
1113 if (paths_eq)
1114 ret = 0;
1115 else {
1116 if (ret == 1)
1117 ret = -1;
1118 else
1119 ret = 1;
1120 }
1121 return ret;
65efcfce
LB
1122}
1123
d62a17ae 1124static enum filter_type bgp_input_filter(struct peer *peer, struct prefix *p,
1125 struct attr *attr, afi_t afi,
1126 safi_t safi)
718e3744 1127{
d62a17ae 1128 struct bgp_filter *filter;
718e3744 1129
d62a17ae 1130 filter = &peer->filter[afi][safi];
718e3744 1131
d62a17ae 1132#define FILTER_EXIST_WARN(F, f, filter) \
1133 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1134 zlog_debug("%s: Could not find configured input %s-list %s!", \
1135 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1136
1137 if (DISTRIBUTE_IN_NAME(filter)) {
1138 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1139
1140 if (access_list_apply(DISTRIBUTE_IN(filter), p) == FILTER_DENY)
1141 return FILTER_DENY;
1142 }
1143
1144 if (PREFIX_LIST_IN_NAME(filter)) {
1145 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1146
1147 if (prefix_list_apply(PREFIX_LIST_IN(filter), p) == PREFIX_DENY)
1148 return FILTER_DENY;
1149 }
1150
1151 if (FILTER_LIST_IN_NAME(filter)) {
1152 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1153
1154 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
1155 == AS_FILTER_DENY)
1156 return FILTER_DENY;
1157 }
1158
1159 return FILTER_PERMIT;
650f76c2 1160#undef FILTER_EXIST_WARN
718e3744 1161}
1162
d62a17ae 1163static enum filter_type bgp_output_filter(struct peer *peer, struct prefix *p,
1164 struct attr *attr, afi_t afi,
1165 safi_t safi)
718e3744 1166{
d62a17ae 1167 struct bgp_filter *filter;
1168
1169 filter = &peer->filter[afi][safi];
1170
1171#define FILTER_EXIST_WARN(F, f, filter) \
1172 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1173 zlog_debug("%s: Could not find configured output %s-list %s!", \
1174 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1175
d62a17ae 1176 if (DISTRIBUTE_OUT_NAME(filter)) {
1177 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1178
d62a17ae 1179 if (access_list_apply(DISTRIBUTE_OUT(filter), p) == FILTER_DENY)
1180 return FILTER_DENY;
1181 }
1182
1183 if (PREFIX_LIST_OUT_NAME(filter)) {
1184 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1185
d62a17ae 1186 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
1187 == PREFIX_DENY)
1188 return FILTER_DENY;
1189 }
718e3744 1190
d62a17ae 1191 if (FILTER_LIST_OUT_NAME(filter)) {
1192 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1193
d62a17ae 1194 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
1195 == AS_FILTER_DENY)
1196 return FILTER_DENY;
1197 }
718e3744 1198
d62a17ae 1199 return FILTER_PERMIT;
650f76c2 1200#undef FILTER_EXIST_WARN
718e3744 1201}
1202
1203/* If community attribute includes no_export then return 1. */
d62a17ae 1204static int bgp_community_filter(struct peer *peer, struct attr *attr)
1205{
1206 if (attr->community) {
1207 /* NO_ADVERTISE check. */
1208 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
1209 return 1;
1210
1211 /* NO_EXPORT check. */
1212 if (peer->sort == BGP_PEER_EBGP
1213 && community_include(attr->community, COMMUNITY_NO_EXPORT))
1214 return 1;
1215
1216 /* NO_EXPORT_SUBCONFED check. */
1217 if (peer->sort == BGP_PEER_EBGP
1218 || peer->sort == BGP_PEER_CONFED)
1219 if (community_include(attr->community,
1220 COMMUNITY_NO_EXPORT_SUBCONFED))
1221 return 1;
1222 }
1223 return 0;
718e3744 1224}
1225
1226/* Route reflection loop check. */
d62a17ae 1227static int bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1228{
d62a17ae 1229 struct in_addr cluster_id;
718e3744 1230
d62a17ae 1231 if (attr->cluster) {
1232 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1233 cluster_id = peer->bgp->cluster_id;
1234 else
1235 cluster_id = peer->bgp->router_id;
1236
1237 if (cluster_loop_check(attr->cluster, cluster_id))
1238 return 1;
1239 }
1240 return 0;
718e3744 1241}
6b0655a2 1242
d62a17ae 1243static int bgp_input_modifier(struct peer *peer, struct prefix *p,
1244 struct attr *attr, afi_t afi, safi_t safi,
82b692c0
LK
1245 const char *rmap_name, mpls_label_t *label,
1246 uint32_t num_labels)
718e3744 1247{
d62a17ae 1248 struct bgp_filter *filter;
82b692c0
LK
1249 struct bgp_path_info rmap_path = { 0 };
1250 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1251 route_map_result_t ret;
1252 struct route_map *rmap = NULL;
718e3744 1253
d62a17ae 1254 filter = &peer->filter[afi][safi];
718e3744 1255
d62a17ae 1256 /* Apply default weight value. */
1257 if (peer->weight[afi][safi])
1258 attr->weight = peer->weight[afi][safi];
718e3744 1259
d62a17ae 1260 if (rmap_name) {
1261 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1262
d62a17ae 1263 if (rmap == NULL)
1264 return RMAP_DENY;
1265 } else {
1266 if (ROUTE_MAP_IN_NAME(filter)) {
1267 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1268
d62a17ae 1269 if (rmap == NULL)
1270 return RMAP_DENY;
1271 }
1272 }
0b16f239 1273
d62a17ae 1274 /* Route map apply. */
1275 if (rmap) {
40381db7 1276 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1277 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1278 rmap_path.peer = peer;
1279 rmap_path.attr = attr;
82b692c0
LK
1280 rmap_path.extra = &extra;
1281 extra.num_labels = num_labels;
1282 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1283 memcpy(extra.label, label,
1284 num_labels * sizeof(mpls_label_t));
718e3744 1285
d62a17ae 1286 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1287
d62a17ae 1288 /* Apply BGP route map to the attribute. */
40381db7 1289 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
0b16f239 1290
d62a17ae 1291 peer->rmap_type = 0;
0b16f239 1292
1f2263be 1293 if (ret == RMAP_DENYMATCH)
d62a17ae 1294 return RMAP_DENY;
0b16f239 1295 }
d62a17ae 1296 return RMAP_PERMIT;
0b16f239
DS
1297}
1298
d62a17ae 1299static int bgp_output_modifier(struct peer *peer, struct prefix *p,
1300 struct attr *attr, afi_t afi, safi_t safi,
1301 const char *rmap_name)
0b16f239 1302{
40381db7 1303 struct bgp_path_info rmap_path;
d62a17ae 1304 route_map_result_t ret;
1305 struct route_map *rmap = NULL;
d7c0a89a 1306 uint8_t rmap_type;
0b16f239 1307
b787157a
DS
1308 /*
1309 * So if we get to this point and have no rmap_name
1310 * we want to just show the output as it currently
1311 * exists.
1312 */
1313 if (!rmap_name)
1314 return RMAP_PERMIT;
0b16f239 1315
d62a17ae 1316 /* Apply default weight value. */
1317 if (peer->weight[afi][safi])
1318 attr->weight = peer->weight[afi][safi];
0b16f239 1319
b787157a 1320 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1321
b787157a
DS
1322 /*
1323 * If we have a route map name and we do not find
1324 * the routemap that means we have an implicit
1325 * deny.
1326 */
1327 if (rmap == NULL)
1328 return RMAP_DENY;
0b16f239 1329
40381db7 1330 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1331 /* Route map apply. */
b787157a 1332 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1333 rmap_path.peer = peer;
1334 rmap_path.attr = attr;
0b16f239 1335
0f672529 1336 rmap_type = peer->rmap_type;
b787157a 1337 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1338
b787157a 1339 /* Apply BGP route map to the attribute. */
40381db7 1340 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
ac41b2a2 1341
0f672529 1342 peer->rmap_type = rmap_type;
b787157a
DS
1343
1344 if (ret == RMAP_DENYMATCH)
1345 /*
1346 * caller has multiple error paths with bgp_attr_flush()
1347 */
1348 return RMAP_DENY;
ac41b2a2 1349
d62a17ae 1350 return RMAP_PERMIT;
718e3744 1351}
6b0655a2 1352
5000f21c 1353/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1354static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1355 struct peer *peer, struct attr *attr)
1356{
1357 if (peer->sort == BGP_PEER_EBGP
1358 && (peer_af_flag_check(peer, afi, safi,
1359 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1360 || peer_af_flag_check(peer, afi, safi,
1361 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1362 || peer_af_flag_check(peer, afi, safi,
1363 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1364 || peer_af_flag_check(peer, afi, safi,
1365 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1366 // Take action on the entire aspath
1367 if (peer_af_flag_check(peer, afi, safi,
1368 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1369 || peer_af_flag_check(peer, afi, safi,
1370 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1371 if (peer_af_flag_check(
1372 peer, afi, safi,
1373 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1374 attr->aspath = aspath_replace_private_asns(
bf26b80e 1375 attr->aspath, bgp->as, peer->as);
d62a17ae 1376
1377 // The entire aspath consists of private ASNs so create
1378 // an empty aspath
1379 else if (aspath_private_as_check(attr->aspath))
1380 attr->aspath = aspath_empty_get();
1381
1382 // There are some public and some private ASNs, remove
1383 // the private ASNs
1384 else
1385 attr->aspath = aspath_remove_private_asns(
bf26b80e 1386 attr->aspath, peer->as);
d62a17ae 1387 }
1388
1389 // 'all' was not specified so the entire aspath must be private
1390 // ASNs
1391 // for us to do anything
1392 else if (aspath_private_as_check(attr->aspath)) {
1393 if (peer_af_flag_check(
1394 peer, afi, safi,
1395 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1396 attr->aspath = aspath_replace_private_asns(
bf26b80e 1397 attr->aspath, bgp->as, peer->as);
d62a17ae 1398 else
1399 attr->aspath = aspath_empty_get();
1400 }
1401 }
5000f21c
DS
1402}
1403
c7122e14 1404/* If this is an EBGP peer with as-override */
d62a17ae 1405static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1406 struct peer *peer, struct attr *attr)
1407{
1408 if (peer->sort == BGP_PEER_EBGP
1409 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1410 if (aspath_single_asn_check(attr->aspath, peer->as))
1411 attr->aspath = aspath_replace_specific_asn(
1412 attr->aspath, peer->as, bgp->as);
1413 }
1414}
1415
7f323236
DW
1416void bgp_attr_add_gshut_community(struct attr *attr)
1417{
1418 struct community *old;
1419 struct community *new;
1420 struct community *merge;
1421 struct community *gshut;
1422
1423 old = attr->community;
1424 gshut = community_str2com("graceful-shutdown");
1425
990f4f91 1426 assert(gshut);
1427
7f323236
DW
1428 if (old) {
1429 merge = community_merge(community_dup(old), gshut);
1430
a4d82a8a 1431 if (old->refcnt == 0)
3c1f53de 1432 community_free(&old);
7f323236
DW
1433
1434 new = community_uniq_sort(merge);
3c1f53de 1435 community_free(&merge);
7f323236
DW
1436 } else {
1437 new = community_dup(gshut);
1438 }
1439
3c1f53de 1440 community_free(&gshut);
7f323236
DW
1441 attr->community = new;
1442 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1443
1444 /* When we add the graceful-shutdown community we must also
1445 * lower the local-preference */
1446 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1447 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1448}
1449
1450
d7c0a89a 1451static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1452{
960035b2 1453 if (family == AF_INET) {
d62a17ae 1454 attr->nexthop.s_addr = 0;
960035b2
PZ
1455 attr->mp_nexthop_global_in.s_addr = 0;
1456 }
d62a17ae 1457 if (family == AF_INET6)
1458 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1459 if (family == AF_EVPN)
1460 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1461}
1462
40381db7 1463int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
d62a17ae 1464 struct update_subgroup *subgrp, struct prefix *p,
1465 struct attr *attr)
1466{
1467 struct bgp_filter *filter;
1468 struct peer *from;
1469 struct peer *peer;
1470 struct peer *onlypeer;
1471 struct bgp *bgp;
40381db7 1472 struct attr *piattr;
d62a17ae 1473 char buf[PREFIX_STRLEN];
b68885f9 1474 route_map_result_t ret;
d62a17ae 1475 int transparent;
1476 int reflect;
1477 afi_t afi;
1478 safi_t safi;
1479 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
1480
1481 if (DISABLE_BGP_ANNOUNCE)
1482 return 0;
1483
1484 afi = SUBGRP_AFI(subgrp);
1485 safi = SUBGRP_SAFI(subgrp);
1486 peer = SUBGRP_PEER(subgrp);
1487 onlypeer = NULL;
1488 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1489 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1490
40381db7 1491 from = pi->peer;
d62a17ae 1492 filter = &peer->filter[afi][safi];
1493 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1494 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1495 : pi->attr;
3f9c7369 1496
65efcfce 1497#if ENABLE_BGP_VNC
d62a17ae 1498 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1499 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1500 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1501
1502 /*
1503 * direct and direct_ext type routes originate internally even
1504 * though they can have peer pointers that reference other
1505 * systems
1506 */
1507 prefix2str(p, buf, PREFIX_STRLEN);
1508 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1509 __func__, buf);
1510 samepeer_safe = 1;
1511 }
65efcfce
LB
1512#endif
1513
ddb5b488
PZ
1514 if (((afi == AFI_IP) || (afi == AFI_IP6))
1515 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1516 && (pi->type == ZEBRA_ROUTE_BGP)
1517 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1518
1519 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1520
1521 samepeer_safe = 1;
1522 }
1523
d62a17ae 1524 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1525 * pi is valid */
1526 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1527 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1528 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 1529 return 0;
1530 }
adbac85e 1531
d62a17ae 1532 /* If this is not the bestpath then check to see if there is an enabled
1533 * addpath
1534 * feature that requires us to advertise it */
40381db7 1535 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1536 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
d62a17ae 1537 return 0;
1538 }
1539 }
06370dac 1540
d62a17ae 1541 /* Aggregate-address suppress check. */
40381db7 1542 if (pi->extra && pi->extra->suppress)
d62a17ae 1543 if (!UNSUPPRESS_MAP_NAME(filter)) {
1544 return 0;
1545 }
3f9c7369 1546
13b7e7f0
DS
1547 /*
1548 * If we are doing VRF 2 VRF leaking via the import
1549 * statement, we want to prevent the route going
1550 * off box as that the RT and RD created are localy
1551 * significant and globaly useless.
1552 */
40381db7
DS
1553 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1554 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
13b7e7f0
DS
1555 return 0;
1556
d62a17ae 1557 /* If it's labeled safi, make sure the route has a valid label. */
1558 if (safi == SAFI_LABELED_UNICAST) {
40381db7 1559 mpls_label_t label = bgp_adv_label(rn, pi, peer, afi, safi);
d62a17ae 1560 if (!bgp_is_valid_label(&label)) {
1561 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1562 zlog_debug("u%" PRIu64 ":s%" PRIu64
1563 " %s/%d is filtered - no label (%p)",
1564 subgrp->update_group->id, subgrp->id,
1565 inet_ntop(p->family, &p->u.prefix,
1566 buf, SU_ADDRSTRLEN),
1567 p->prefixlen, &label);
1568 return 0;
1569 }
1570 }
cd1964ff 1571
d62a17ae 1572 /* Do not send back route to sender. */
1573 if (onlypeer && from == onlypeer) {
1574 return 0;
1575 }
3f9c7369 1576
d62a17ae 1577 /* Do not send the default route in the BGP table if the neighbor is
1578 * configured for default-originate */
1579 if (CHECK_FLAG(peer->af_flags[afi][safi],
1580 PEER_FLAG_DEFAULT_ORIGINATE)) {
1581 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
1582 return 0;
1583 else if (p->family == AF_INET6 && p->prefixlen == 0)
1584 return 0;
1585 }
4125bb67 1586
d62a17ae 1587 /* Transparency check. */
1588 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1589 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1590 transparent = 1;
1591 else
1592 transparent = 0;
1593
1594 /* If community is not disabled check the no-export and local. */
40381db7 1595 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1596 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1597 zlog_debug(
1598 "subgrpannouncecheck: community filter check fail");
1599 return 0;
1600 }
3f9c7369 1601
d62a17ae 1602 /* If the attribute has originator-id and it is same as remote
1603 peer's id. */
40381db7
DS
1604 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1605 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1606 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1607 zlog_debug(
1608 "%s [Update:SEND] %s originator-id is same as "
1609 "remote router-id",
1610 onlypeer->host,
1611 prefix2str(p, buf, sizeof(buf)));
1612 return 0;
1613 }
3f9c7369 1614
d62a17ae 1615 /* ORF prefix-list filter check */
1616 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1617 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1618 || CHECK_FLAG(peer->af_cap[afi][safi],
1619 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1620 if (peer->orf_plist[afi][safi]) {
1621 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1622 == PREFIX_DENY) {
1623 if (bgp_debug_update(NULL, p,
1624 subgrp->update_group, 0))
1625 zlog_debug(
1626 "%s [Update:SEND] %s is filtered via ORF",
1627 peer->host,
1628 prefix2str(p, buf,
1629 sizeof(buf)));
1630 return 0;
1631 }
1632 }
1633
1634 /* Output filter check. */
40381db7 1635 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1636 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1637 zlog_debug("%s [Update:SEND] %s is filtered",
1638 peer->host, prefix2str(p, buf, sizeof(buf)));
1639 return 0;
1640 }
3f9c7369 1641
d62a17ae 1642 /* AS path loop check. */
2b31007c
RZ
1643 if (onlypeer && onlypeer->as_path_loop_detection
1644 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1645 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1646 zlog_debug(
1647 "%s [Update:SEND] suppress announcement to peer AS %u "
1648 "that is part of AS path.",
1649 onlypeer->host, onlypeer->as);
1650 return 0;
1651 }
3f9c7369 1652
d62a17ae 1653 /* If we're a CONFED we need to loop check the CONFED ID too */
1654 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1655 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1656 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1657 zlog_debug(
1658 "%s [Update:SEND] suppress announcement to peer AS %u"
1659 " is AS path.",
1660 peer->host, bgp->confed_id);
1661 return 0;
1662 }
3f9c7369 1663 }
3f9c7369 1664
d62a17ae 1665 /* Route-Reflect check. */
1666 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1667 reflect = 1;
1668 else
1669 reflect = 0;
1670
1671 /* IBGP reflection check. */
1672 if (reflect && !samepeer_safe) {
1673 /* A route from a Client peer. */
1674 if (CHECK_FLAG(from->af_flags[afi][safi],
1675 PEER_FLAG_REFLECTOR_CLIENT)) {
1676 /* Reflect to all the Non-Client peers and also to the
1677 Client peers other than the originator. Originator
1678 check
1679 is already done. So there is noting to do. */
1680 /* no bgp client-to-client reflection check. */
1681 if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
1682 if (CHECK_FLAG(peer->af_flags[afi][safi],
1683 PEER_FLAG_REFLECTOR_CLIENT))
1684 return 0;
1685 } else {
1686 /* A route from a Non-client peer. Reflect to all other
1687 clients. */
1688 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1689 PEER_FLAG_REFLECTOR_CLIENT))
1690 return 0;
1691 }
1692 }
3f9c7369 1693
d62a17ae 1694 /* For modify attribute, copy it to temporary structure. */
40381db7 1695 bgp_attr_dup(attr, piattr);
d62a17ae 1696
1697 /* If local-preference is not set. */
1698 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1699 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1700 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1701 attr->local_pref = bgp->default_local_pref;
3f9c7369 1702 }
3f9c7369 1703
d62a17ae 1704 /* If originator-id is not set and the route is to be reflected,
1705 set the originator id */
1706 if (reflect
1707 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1708 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1709 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1710 }
3f9c7369 1711
d62a17ae 1712 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1713 */
1714 if (peer->sort == BGP_PEER_EBGP
1715 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1716 if (from != bgp->peer_self && !transparent
1717 && !CHECK_FLAG(peer->af_flags[afi][safi],
1718 PEER_FLAG_MED_UNCHANGED))
1719 attr->flag &=
1720 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1721 }
3f9c7369 1722
d62a17ae 1723 /* Since the nexthop attribute can vary per peer, it is not explicitly
1724 * set
1725 * in announce check, only certain flags and length (or number of
1726 * nexthops
1727 * -- for IPv6/MP_REACH) are set here in order to guide the update
1728 * formation
1729 * code in setting the nexthop(s) on a per peer basis in
1730 * reformat_peer().
1731 * Typically, the source nexthop in the attribute is preserved but in
1732 * the
1733 * scenarios where we know it will always be overwritten, we reset the
1734 * nexthop to "0" in an attempt to achieve better Update packing. An
1735 * example of this is when a prefix from each of 2 IBGP peers needs to
1736 * be
1737 * announced to an EBGP peer (and they have the same attributes barring
1738 * their nexthop).
1739 */
1740 if (reflect)
1741 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1742
1743#define NEXTHOP_IS_V6 \
1744 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1745 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1746 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1747 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1748
1749 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1750 * if
1751 * the peer (group) is configured to receive link-local nexthop
1752 * unchanged
c728d027
DA
1753 * and it is available in the prefix OR we're not reflecting the route,
1754 * link-local nexthop address is valid and
d62a17ae 1755 * the peer (group) to whom we're going to announce is on a shared
1756 * network
1757 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
1758 * By checking if nexthop LL address is valid we are sure that
1759 * we do not announce LL address as `::`.
d62a17ae 1760 */
1761 if (NEXTHOP_IS_V6) {
1762 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
1763 if ((CHECK_FLAG(peer->af_flags[afi][safi],
1764 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
1765 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
1766 || (!reflect
1767 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
1768 && peer->shared_network
d62a17ae 1769 && (from == bgp->peer_self
1770 || peer->sort == BGP_PEER_EBGP))) {
1771 attr->mp_nexthop_len =
1772 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
1773 }
3f9c7369 1774
d62a17ae 1775 /* Clear off link-local nexthop in source, whenever it is not
1776 * needed to
1777 * ensure more prefixes share the same attribute for
1778 * announcement.
1779 */
1780 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
1781 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
1782 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
1783 }
3f9c7369 1784
d62a17ae 1785 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
1786 bgp_peer_as_override(bgp, afi, safi, peer, attr);
1787
1788 /* Route map & unsuppress-map apply. */
40381db7 1789 if (ROUTE_MAP_OUT_NAME(filter) || (pi->extra && pi->extra->suppress)) {
b8694ef4
DS
1790 struct bgp_path_info rmap_path = {0};
1791 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
1792 struct attr dummy_attr = {0};
d62a17ae 1793
40381db7
DS
1794 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
1795 rmap_path.peer = peer;
1796 rmap_path.attr = attr;
d37ba549 1797
40381db7
DS
1798 if (pi->extra) {
1799 memcpy(&dummy_rmap_path_extra, pi->extra,
4b7e6066 1800 sizeof(struct bgp_path_info_extra));
40381db7 1801 rmap_path.extra = &dummy_rmap_path_extra;
16f7ce2b
MK
1802 }
1803
d62a17ae 1804 /* don't confuse inbound and outbound setting */
1805 RESET_FLAG(attr->rmap_change_flags);
1806
1807 /*
1808 * The route reflector is not allowed to modify the attributes
1809 * of the reflected IBGP routes unless explicitly allowed.
1810 */
1811 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1812 && !bgp_flag_check(bgp,
1813 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
1814 bgp_attr_dup(&dummy_attr, attr);
40381db7 1815 rmap_path.attr = &dummy_attr;
d62a17ae 1816 }
3f9c7369 1817
d62a17ae 1818 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 1819
40381db7 1820 if (pi->extra && pi->extra->suppress)
d62a17ae 1821 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
40381db7 1822 RMAP_BGP, &rmap_path);
d62a17ae 1823 else
1824 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
40381db7 1825 RMAP_BGP, &rmap_path);
d62a17ae 1826
1827 peer->rmap_type = 0;
1828
1829 if (ret == RMAP_DENYMATCH) {
778048bf
AD
1830 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1831 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1832 peer->host, prefix2str(p, buf, sizeof(buf)));
1833
d62a17ae 1834 bgp_attr_flush(attr);
1835 return 0;
1836 }
3f9c7369 1837 }
3f9c7369 1838
9dac9fc8
DA
1839 /* RFC 8212 to prevent route leaks.
1840 * This specification intends to improve this situation by requiring the
1841 * explicit configuration of both BGP Import and Export Policies for any
1842 * External BGP (EBGP) session such as customers, peers, or
1843 * confederation boundaries for all enabled address families. Through
1844 * codification of the aforementioned requirement, operators will
1845 * benefit from consistent behavior across different BGP
1846 * implementations.
1847 */
1848 if (peer->bgp->ebgp_requires_policy
1849 == DEFAULT_EBGP_POLICY_ENABLED)
1850 if (!bgp_outbound_policy_exists(peer, filter))
1851 return 0;
1852
7f323236 1853 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
a4d82a8a
PZ
1854 if (peer->sort == BGP_PEER_IBGP
1855 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
1856 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1857 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1858 } else {
1859 bgp_attr_add_gshut_community(attr);
1860 }
1861 }
1862
d62a17ae 1863 /* After route-map has been applied, we check to see if the nexthop to
1864 * be carried in the attribute (that is used for the announcement) can
1865 * be cleared off or not. We do this in all cases where we would be
1866 * setting the nexthop to "ourselves". For IPv6, we only need to
1867 * consider
1868 * the global nexthop here; the link-local nexthop would have been
1869 * cleared
1870 * already, and if not, it is required by the update formation code.
1871 * Also see earlier comments in this function.
1872 */
1873 /*
1874 * If route-map has performed some operation on the nexthop or the peer
1875 * configuration says to pass it unchanged, we cannot reset the nexthop
1876 * here, so only attempt to do it if these aren't true. Note that the
1877 * route-map handler itself might have cleared the nexthop, if for
1878 * example,
1879 * it is configured as 'peer-address'.
1880 */
1881 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 1882 piattr->rmap_change_flags)
d62a17ae 1883 && !transparent
1884 && !CHECK_FLAG(peer->af_flags[afi][safi],
1885 PEER_FLAG_NEXTHOP_UNCHANGED)) {
1886 /* We can reset the nexthop, if setting (or forcing) it to
1887 * 'self' */
1888 if (CHECK_FLAG(peer->af_flags[afi][safi],
1889 PEER_FLAG_NEXTHOP_SELF)
1890 || CHECK_FLAG(peer->af_flags[afi][safi],
1891 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
1892 if (!reflect
1893 || CHECK_FLAG(peer->af_flags[afi][safi],
1894 PEER_FLAG_FORCE_NEXTHOP_SELF))
1895 subgroup_announce_reset_nhop(
1896 (peer_cap_enhe(peer, afi, safi)
1897 ? AF_INET6
1898 : p->family),
1899 attr);
1900 } else if (peer->sort == BGP_PEER_EBGP) {
1901 /* Can also reset the nexthop if announcing to EBGP, but
1902 * only if
1903 * no peer in the subgroup is on a shared subnet.
1904 * Note: 3rd party nexthop currently implemented for
1905 * IPv4 only.
1906 */
737af885
BS
1907 if ((p->family == AF_INET) &&
1908 (!bgp_subgrp_multiaccess_check_v4(
1909 piattr->nexthop,
1910 subgrp)))
d62a17ae 1911 subgroup_announce_reset_nhop(
1912 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
1913 ? AF_INET6
1914 : p->family),
737af885
BS
1915 attr);
1916
1917 if ((p->family == AF_INET6) &&
1918 (!bgp_subgrp_multiaccess_check_v6(
1919 piattr->mp_nexthop_global,
1920 subgrp)))
1921 subgroup_announce_reset_nhop(
1922 (peer_cap_enhe(peer, afi, safi)
1923 ? AF_INET6
1924 : p->family),
1925 attr);
1926
1927
1928
40381db7 1929 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
1930 /*
1931 * This flag is used for leaked vpn-vrf routes
1932 */
1933 int family = p->family;
1934
1935 if (peer_cap_enhe(peer, afi, safi))
1936 family = AF_INET6;
1937
1938 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1939 zlog_debug(
1defdda8 1940 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
1941 __func__, family2str(family));
1942 subgroup_announce_reset_nhop(family, attr);
d62a17ae 1943 }
960035b2 1944
d62a17ae 1945 /* If IPv6/MP and nexthop does not have any override and happens
1946 * to
1947 * be a link-local address, reset it so that we don't pass along
1948 * the
1949 * source's link-local IPv6 address to recipients who may not be
1950 * on
1951 * the same interface.
1952 */
1953 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
1954 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global))
1955 subgroup_announce_reset_nhop(AF_INET6, attr);
1956 }
1957 }
3f9c7369 1958
d62a17ae 1959 return 1;
3f9c7369
DS
1960}
1961
d62a17ae 1962void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
1963 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
1964 struct bgp_path_info_pair *result, afi_t afi,
1965 safi_t safi)
1966{
1967 struct bgp_path_info *new_select;
1968 struct bgp_path_info *old_select;
40381db7
DS
1969 struct bgp_path_info *pi;
1970 struct bgp_path_info *pi1;
1971 struct bgp_path_info *pi2;
1972 struct bgp_path_info *nextpi = NULL;
d62a17ae 1973 int paths_eq, do_mpath, debug;
1974 struct list mp_list;
1975 char pfx_buf[PREFIX2STR_BUFFER];
1976 char path_buf[PATH_ADDPATH_STR_BUFFER];
1977
1978 bgp_mp_list_init(&mp_list);
1979 do_mpath =
1980 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
1981
1982 debug = bgp_debug_bestpath(&rn->p);
1983
1984 if (debug)
1985 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
1986
1987 /* bgp deterministic-med */
1988 new_select = NULL;
1989 if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)) {
1990
1defdda8 1991 /* Clear BGP_PATH_DMED_SELECTED for all paths */
6f94b685
DS
1992 for (pi1 = bgp_node_get_bgp_path_info(rn); pi1;
1993 pi1 = pi1->next)
40381db7 1994 bgp_path_info_unset_flag(rn, pi1,
18ee8310 1995 BGP_PATH_DMED_SELECTED);
d62a17ae 1996
6f94b685
DS
1997 for (pi1 = bgp_node_get_bgp_path_info(rn); pi1;
1998 pi1 = pi1->next) {
40381db7 1999 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2000 continue;
40381db7 2001 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2002 continue;
ea8b2282 2003 if (pi1->peer != bgp->peer_self)
40381db7 2004 if (pi1->peer->status != Established)
d62a17ae 2005 continue;
2006
40381db7
DS
2007 new_select = pi1;
2008 if (pi1->next) {
2009 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2010 if (CHECK_FLAG(pi2->flags,
1defdda8 2011 BGP_PATH_DMED_CHECK))
d62a17ae 2012 continue;
40381db7 2013 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2014 continue;
ea8b2282 2015 if (pi2->peer != bgp->peer_self
d62a17ae 2016 && !CHECK_FLAG(
ea8b2282
DS
2017 pi2->peer->sflags,
2018 PEER_STATUS_NSF_WAIT))
40381db7 2019 if (pi2->peer->status
d62a17ae 2020 != Established)
2021 continue;
2022
121e245d
DS
2023 if (!aspath_cmp_left(pi1->attr->aspath,
2024 pi2->attr->aspath)
2025 && !aspath_cmp_left_confed(
40381db7 2026 pi1->attr->aspath,
121e245d
DS
2027 pi2->attr->aspath))
2028 continue;
d62a17ae 2029
121e245d
DS
2030 if (bgp_path_info_cmp(
2031 bgp, pi2, new_select,
2032 &paths_eq, mpath_cfg, debug,
fdf81fa0
DS
2033 pfx_buf, afi, safi,
2034 &rn->reason)) {
121e245d
DS
2035 bgp_path_info_unset_flag(
2036 rn, new_select,
2037 BGP_PATH_DMED_SELECTED);
2038 new_select = pi2;
d62a17ae 2039 }
121e245d
DS
2040
2041 bgp_path_info_set_flag(
2042 rn, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2043 }
2044 }
18ee8310
DS
2045 bgp_path_info_set_flag(rn, new_select,
2046 BGP_PATH_DMED_CHECK);
2047 bgp_path_info_set_flag(rn, new_select,
2048 BGP_PATH_DMED_SELECTED);
d62a17ae 2049
2050 if (debug) {
18ee8310
DS
2051 bgp_path_info_path_with_addpath_rx_str(
2052 new_select, path_buf);
c66faab1 2053 zlog_debug("%s: %s is the bestpath from AS %u",
d62a17ae 2054 pfx_buf, path_buf,
2055 aspath_get_first_as(
2056 new_select->attr->aspath));
2057 }
2058 }
2059 }
96450faf 2060
d62a17ae 2061 /* Check old selected route and new selected route. */
2062 old_select = NULL;
2063 new_select = NULL;
6f94b685
DS
2064 for (pi = bgp_node_get_bgp_path_info(rn);
2065 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
40381db7
DS
2066 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2067 old_select = pi;
d62a17ae 2068
40381db7 2069 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2070 /* reap REMOVED routes, if needs be
2071 * selected route must stay for a while longer though
2072 */
40381db7
DS
2073 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2074 && (pi != old_select))
2075 bgp_path_info_reap(rn, pi);
d62a17ae 2076
ddb5b488 2077 if (debug)
40381db7
DS
2078 zlog_debug("%s: pi %p in holddown", __func__,
2079 pi);
ddb5b488 2080
d62a17ae 2081 continue;
2082 }
96450faf 2083
40381db7
DS
2084 if (pi->peer && pi->peer != bgp->peer_self
2085 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2086 if (pi->peer->status != Established) {
ddb5b488
PZ
2087
2088 if (debug)
2089 zlog_debug(
40381db7
DS
2090 "%s: pi %p non self peer %s not estab state",
2091 __func__, pi, pi->peer->host);
ddb5b488 2092
d62a17ae 2093 continue;
ddb5b488 2094 }
9fbdd100 2095
d62a17ae 2096 if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)
40381db7
DS
2097 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
2098 bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2099 if (debug)
40381db7 2100 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2101 continue;
2102 }
9fbdd100 2103
40381db7 2104 bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK);
06370dac 2105
40381db7 2106 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
fdf81fa0 2107 debug, pfx_buf, afi, safi, &rn->reason)) {
40381db7 2108 new_select = pi;
d62a17ae 2109 }
2110 }
718e3744 2111
d62a17ae 2112 /* Now that we know which path is the bestpath see if any of the other
2113 * paths
2114 * qualify as multipaths
2115 */
2116 if (debug) {
2117 if (new_select)
18ee8310
DS
2118 bgp_path_info_path_with_addpath_rx_str(new_select,
2119 path_buf);
d62a17ae 2120 else
2121 sprintf(path_buf, "NONE");
2122 zlog_debug(
2123 "%s: After path selection, newbest is %s oldbest was %s",
2124 pfx_buf, path_buf,
2125 old_select ? old_select->peer->host : "NONE");
96450faf 2126 }
9fbdd100 2127
d62a17ae 2128 if (do_mpath && new_select) {
6f94b685
DS
2129 for (pi = bgp_node_get_bgp_path_info(rn);
2130 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2131
2132 if (debug)
18ee8310 2133 bgp_path_info_path_with_addpath_rx_str(
40381db7 2134 pi, path_buf);
d62a17ae 2135
40381db7 2136 if (pi == new_select) {
d62a17ae 2137 if (debug)
2138 zlog_debug(
2139 "%s: %s is the bestpath, add to the multipath list",
2140 pfx_buf, path_buf);
40381db7 2141 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2142 continue;
2143 }
2144
40381db7 2145 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2146 continue;
2147
40381db7
DS
2148 if (pi->peer && pi->peer != bgp->peer_self
2149 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2150 PEER_STATUS_NSF_WAIT))
40381db7 2151 if (pi->peer->status != Established)
d62a17ae 2152 continue;
2153
40381db7 2154 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2155 if (debug)
2156 zlog_debug(
2157 "%s: %s has the same nexthop as the bestpath, skip it",
2158 pfx_buf, path_buf);
2159 continue;
2160 }
2161
40381db7 2162 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0
DS
2163 mpath_cfg, debug, pfx_buf, afi, safi,
2164 &rn->reason);
d62a17ae 2165
2166 if (paths_eq) {
2167 if (debug)
2168 zlog_debug(
2169 "%s: %s is equivalent to the bestpath, add to the multipath list",
2170 pfx_buf, path_buf);
40381db7 2171 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2172 }
2173 }
2174 }
fee0f4c6 2175
18ee8310
DS
2176 bgp_path_info_mpath_update(rn, new_select, old_select, &mp_list,
2177 mpath_cfg);
2178 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2179 bgp_mp_list_clear(&mp_list);
96450faf 2180
dcc68b5e
MS
2181 bgp_addpath_update_ids(bgp, rn, afi, safi);
2182
d62a17ae 2183 result->old = old_select;
2184 result->new = new_select;
96450faf 2185
d62a17ae 2186 return;
fee0f4c6 2187}
2188
3f9c7369
DS
2189/*
2190 * A new route/change in bestpath of an existing route. Evaluate the path
2191 * for advertisement to the subgroup.
2192 */
d62a17ae 2193int subgroup_process_announce_selected(struct update_subgroup *subgrp,
4b7e6066 2194 struct bgp_path_info *selected,
d62a17ae 2195 struct bgp_node *rn,
d7c0a89a 2196 uint32_t addpath_tx_id)
d62a17ae 2197{
2198 struct prefix *p;
2199 struct peer *onlypeer;
2200 struct attr attr;
2201 afi_t afi;
2202 safi_t safi;
adbac85e 2203
d62a17ae 2204 p = &rn->p;
2205 afi = SUBGRP_AFI(subgrp);
2206 safi = SUBGRP_SAFI(subgrp);
2207 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2208 : NULL);
2209
e0207895
PZ
2210 if (BGP_DEBUG(update, UPDATE_OUT)) {
2211 char buf_prefix[PREFIX_STRLEN];
2212 prefix2str(p, buf_prefix, sizeof(buf_prefix));
ddb5b488
PZ
2213 zlog_debug("%s: p=%s, selected=%p", __func__, buf_prefix,
2214 selected);
e0207895
PZ
2215 }
2216
d62a17ae 2217 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2218 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2219 PEER_STATUS_ORF_WAIT_REFRESH))
d62a17ae 2220 return 0;
2221
2222 memset(&attr, 0, sizeof(struct attr));
2223 /* It's initialized in bgp_announce_check() */
2224
2225 /* Announcement to the subgroup. If the route is filtered withdraw it.
2226 */
2227 if (selected) {
2228 if (subgroup_announce_check(rn, selected, subgrp, p, &attr))
2229 bgp_adj_out_set_subgroup(rn, subgrp, &attr, selected);
2230 else
2231 bgp_adj_out_unset_subgroup(rn, subgrp, 1,
dcc68b5e 2232 addpath_tx_id);
d62a17ae 2233 }
2234
2235 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2236 else {
2237 bgp_adj_out_unset_subgroup(rn, subgrp, 1, addpath_tx_id);
2238 }
558d1fec 2239
d62a17ae 2240 return 0;
200df115 2241}
fee0f4c6 2242
3064bf43 2243/*
e1072051 2244 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2245 * This is called at the end of route processing.
3064bf43 2246 */
d62a17ae 2247void bgp_zebra_clear_route_change_flags(struct bgp_node *rn)
3064bf43 2248{
40381db7 2249 struct bgp_path_info *pi;
3064bf43 2250
6f94b685 2251 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 2252 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2253 continue;
40381db7
DS
2254 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2255 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2256 }
3064bf43 2257}
2258
2259/*
2260 * Has the route changed from the RIB's perspective? This is invoked only
2261 * if the route selection returns the same best route as earlier - to
2262 * determine if we need to update zebra or not.
2263 */
4b7e6066
DS
2264int bgp_zebra_has_route_changed(struct bgp_node *rn,
2265 struct bgp_path_info *selected)
d62a17ae 2266{
4b7e6066 2267 struct bgp_path_info *mpinfo;
d62a17ae 2268
2bb9eff4
DS
2269 /* If this is multipath, check all selected paths for any nexthop
2270 * change or attribute change. Some attribute changes (e.g., community)
2271 * aren't of relevance to the RIB, but we'll update zebra to ensure
2272 * we handle the case of BGP nexthop change. This is the behavior
2273 * when the best path has an attribute change anyway.
d62a17ae 2274 */
1defdda8
DS
2275 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
2276 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG))
d62a17ae 2277 return 1;
2278
2bb9eff4
DS
2279 /*
2280 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2281 */
18ee8310
DS
2282 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2283 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2284 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2285 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
d62a17ae 2286 return 1;
2287 }
3064bf43 2288
d62a17ae 2289 /* Nothing has changed from the RIB's perspective. */
2290 return 0;
3064bf43 2291}
2292
d62a17ae 2293struct bgp_process_queue {
2294 struct bgp *bgp;
a4d82a8a 2295 STAILQ_HEAD(, bgp_node) pqueue;
aac24838
JB
2296#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2297 unsigned int flags;
2298 unsigned int queued;
200df115 2299};
2300
3103e8d2
DS
2301/*
2302 * old_select = The old best path
2303 * new_select = the new best path
2304 *
2305 * if (!old_select && new_select)
2306 * We are sending new information on.
2307 *
2308 * if (old_select && new_select) {
2309 * if (new_select != old_select)
2310 * We have a new best path send a change
2311 * else
2312 * We've received a update with new attributes that needs
2313 * to be passed on.
2314 * }
2315 *
2316 * if (old_select && !new_select)
2317 * We have no eligible route that we can announce or the rn
2318 * is being removed.
2319 */
aac24838
JB
2320static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
2321 afi_t afi, safi_t safi)
d62a17ae 2322{
4b7e6066
DS
2323 struct bgp_path_info *new_select;
2324 struct bgp_path_info *old_select;
2325 struct bgp_path_info_pair old_and_new;
ddb5b488
PZ
2326 char pfx_buf[PREFIX2STR_BUFFER];
2327 int debug = 0;
d62a17ae 2328
f4c713ae
LB
2329 if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS)) {
2330 if (rn)
2331 debug = bgp_debug_bestpath(&rn->p);
2332 if (debug) {
2333 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2334 zlog_debug(
2335 "%s: bgp delete in progress, ignoring event, p=%s",
2336 __func__, pfx_buf);
2337 }
2338 return;
2339 }
d62a17ae 2340 /* Is it end of initial update? (after startup) */
2341 if (!rn) {
2342 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2343 sizeof(bgp->update_delay_zebra_resume_time));
2344
2345 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2346 FOREACH_AFI_SAFI (afi, safi) {
2347 if (bgp_fibupd_safi(safi))
2348 bgp_zebra_announce_table(bgp, afi, safi);
2349 }
d62a17ae 2350 bgp->main_peers_update_hold = 0;
2351
2352 bgp_start_routeadv(bgp);
aac24838 2353 return;
d62a17ae 2354 }
cb1faec9 2355
b575a12c
A
2356 struct prefix *p = &rn->p;
2357
ddb5b488
PZ
2358 debug = bgp_debug_bestpath(&rn->p);
2359 if (debug) {
2360 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2361 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__, pfx_buf,
2362 afi2str(afi), safi2str(safi));
2363 }
2364
d62a17ae 2365 /* Best path selection. */
2366 bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new,
2367 afi, safi);
2368 old_select = old_and_new.old;
2369 new_select = old_and_new.new;
2370
2371 /* Do we need to allocate or free labels?
2372 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2373 * necessary to do this upon changes to best path. Exceptions:
2374 * - label index has changed -> recalculate resulting label
2375 * - path_info sub_type changed -> switch to/from implicit-null
2376 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2377 */
318cac96 2378 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2379 if (new_select) {
2380 if (!old_select
2381 || bgp_label_index_differs(new_select, old_select)
57592a53
AD
2382 || new_select->sub_type != old_select->sub_type
2383 || !bgp_is_valid_label(&rn->local_label)) {
2384 /* Enforced penultimate hop popping:
2385 * implicit-null for local routes, aggregate
2386 * and redistributed routes
2387 */
d62a17ae 2388 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2389 || new_select->sub_type
2390 == BGP_ROUTE_AGGREGATE
2391 || new_select->sub_type
2392 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2393 if (CHECK_FLAG(
2394 rn->flags,
2395 BGP_NODE_REGISTERED_FOR_LABEL))
2396 bgp_unregister_for_label(rn);
70e98a7f 2397 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
d62a17ae 2398 &rn->local_label);
2399 bgp_set_valid_label(&rn->local_label);
2400 } else
2401 bgp_register_for_label(rn, new_select);
2402 }
a4d82a8a
PZ
2403 } else if (CHECK_FLAG(rn->flags,
2404 BGP_NODE_REGISTERED_FOR_LABEL)) {
d62a17ae 2405 bgp_unregister_for_label(rn);
318cac96
DW
2406 }
2407 } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
2408 bgp_unregister_for_label(rn);
d62a17ae 2409 }
cd1964ff 2410
ddb5b488
PZ
2411 if (debug) {
2412 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2413 zlog_debug(
2414 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2415 __func__, pfx_buf, afi2str(afi), safi2str(safi),
2416 old_select, new_select);
2417 }
2418
d62a17ae 2419 /* If best route remains the same and this is not due to user-initiated
2420 * clear, see exactly what needs to be done.
2421 */
d62a17ae 2422 if (old_select && old_select == new_select
2423 && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
1defdda8 2424 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2425 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 2426 if (bgp_zebra_has_route_changed(rn, old_select)) {
65efcfce 2427#if ENABLE_BGP_VNC
d62a17ae 2428 vnc_import_bgp_add_route(bgp, p, old_select);
2429 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2430#endif
bb744275 2431 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2432 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2433
2434 if (new_select->type == ZEBRA_ROUTE_BGP
2435 && (new_select->sub_type == BGP_ROUTE_NORMAL
2436 || new_select->sub_type
2437 == BGP_ROUTE_IMPORTED))
2438
2439 bgp_zebra_announce(rn, p, old_select,
2440 bgp, afi, safi);
2441 }
d62a17ae 2442 }
1defdda8 2443 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
d62a17ae 2444 bgp_zebra_clear_route_change_flags(rn);
2445
2446 /* If there is a change of interest to peers, reannounce the
2447 * route. */
1defdda8 2448 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
d62a17ae 2449 || CHECK_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED)) {
2450 group_announce_route(bgp, afi, safi, rn, new_select);
2451
2452 /* unicast routes must also be annouced to
2453 * labeled-unicast update-groups */
2454 if (safi == SAFI_UNICAST)
2455 group_announce_route(bgp, afi,
2456 SAFI_LABELED_UNICAST, rn,
2457 new_select);
2458
1defdda8 2459 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2460 UNSET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED);
2461 }
fee0f4c6 2462
d62a17ae 2463 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2464 return;
d62a17ae 2465 }
8ad7271d 2466
d62a17ae 2467 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2468 */
2469 UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR);
2470
2471 /* bestpath has changed; bump version */
2472 if (old_select || new_select) {
2473 bgp_bump_version(rn);
2474
2475 if (!bgp->t_rmap_def_originate_eval) {
2476 bgp_lock(bgp);
2477 thread_add_timer(
2478 bm->master,
2479 update_group_refresh_default_originate_route_map,
2480 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2481 &bgp->t_rmap_def_originate_eval);
2482 }
2483 }
3f9c7369 2484
d62a17ae 2485 if (old_select)
18ee8310 2486 bgp_path_info_unset_flag(rn, old_select, BGP_PATH_SELECTED);
d62a17ae 2487 if (new_select) {
ddb5b488
PZ
2488 if (debug)
2489 zlog_debug("%s: setting SELECTED flag", __func__);
18ee8310
DS
2490 bgp_path_info_set_flag(rn, new_select, BGP_PATH_SELECTED);
2491 bgp_path_info_unset_flag(rn, new_select, BGP_PATH_ATTR_CHANGED);
1defdda8 2492 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
d62a17ae 2493 }
338b3424 2494
65efcfce 2495#if ENABLE_BGP_VNC
d62a17ae 2496 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2497 if (old_select != new_select) {
2498 if (old_select) {
2499 vnc_import_bgp_exterior_del_route(bgp, p,
2500 old_select);
2501 vnc_import_bgp_del_route(bgp, p, old_select);
2502 }
2503 if (new_select) {
2504 vnc_import_bgp_exterior_add_route(bgp, p,
2505 new_select);
2506 vnc_import_bgp_add_route(bgp, p, new_select);
2507 }
2508 }
2509 }
65efcfce
LB
2510#endif
2511
d62a17ae 2512 group_announce_route(bgp, afi, safi, rn, new_select);
2513
2514 /* unicast routes must also be annouced to labeled-unicast update-groups
2515 */
2516 if (safi == SAFI_UNICAST)
2517 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, rn,
2518 new_select);
2519
2520 /* FIB update. */
2521 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2522 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2523 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2524 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2525 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2526 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2527
2528 /* if this is an evpn imported type-5 prefix,
2529 * we need to withdraw the route first to clear
2530 * the nh neigh and the RMAC entry.
2531 */
2532 if (old_select &&
2533 is_route_parent_evpn(old_select))
2534 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2535
d62a17ae 2536 bgp_zebra_announce(rn, p, new_select, bgp, afi, safi);
2b659f33 2537 } else {
d62a17ae 2538 /* Withdraw the route from the kernel. */
2539 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2540 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2541 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2542 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2543
568e10ca 2544 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2545 }
718e3744 2546 }
3064bf43 2547
5424b7ba
MK
2548 /* advertise/withdraw type-5 routes */
2549 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
f106e3a7 2550 if (advertise_type5_routes(bgp, afi) &&
2551 new_select &&
2552 is_route_injectable_into_evpn(new_select)) {
7e4ed18e
MK
2553
2554 /* apply the route-map */
2555 if (bgp->adv_cmd_rmap[afi][safi].map) {
b68885f9 2556 route_map_result_t ret;
7e4ed18e 2557
3518f352
DS
2558 ret = route_map_apply(
2559 bgp->adv_cmd_rmap[afi][safi].map,
2560 &rn->p, RMAP_BGP, new_select);
b68885f9 2561 if (ret == RMAP_PERMITMATCH)
3518f352
DS
2562 bgp_evpn_advertise_type5_route(
2563 bgp, &rn->p, new_select->attr,
2564 afi, safi);
c27ee4c4 2565 else
2566 bgp_evpn_withdraw_type5_route(
2567 bgp, &rn->p, afi, safi);
7e4ed18e
MK
2568 } else {
2569 bgp_evpn_advertise_type5_route(bgp,
2570 &rn->p,
2571 new_select->attr,
2572 afi, safi);
2573
2574 }
f106e3a7 2575 } else if (advertise_type5_routes(bgp, afi) &&
2576 old_select &&
2577 is_route_injectable_into_evpn(old_select))
31310b25 2578 bgp_evpn_withdraw_type5_route(bgp, &rn->p, afi, safi);
5424b7ba
MK
2579 }
2580
d62a17ae 2581 /* Clear any route change flags. */
2582 bgp_zebra_clear_route_change_flags(rn);
3064bf43 2583
18ee8310 2584 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2585 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
18ee8310 2586 bgp_path_info_reap(rn, old_select);
d62a17ae 2587
2588 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2589 return;
718e3744 2590}
2591
aac24838 2592static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 2593{
aac24838
JB
2594 struct bgp_process_queue *pqnode = data;
2595 struct bgp *bgp = pqnode->bgp;
d62a17ae 2596 struct bgp_table *table;
ac021f40 2597 struct bgp_node *rn;
aac24838
JB
2598
2599 /* eoiu marker */
2600 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
2601 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
2602 /* should always have dedicated wq call */
2603 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
2604 return WQ_SUCCESS;
2605 }
2606
ac021f40
LB
2607 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
2608 rn = STAILQ_FIRST(&pqnode->pqueue);
2609 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
b3e1dd3c 2610 STAILQ_NEXT(rn, pq) = NULL; /* complete unlink */
aac24838 2611 table = bgp_node_table(rn);
ac021f40 2612 /* note, new RNs may be added as part of processing */
aac24838 2613 bgp_process_main_one(bgp, rn, table->afi, table->safi);
cb1faec9 2614
aac24838 2615 bgp_unlock_node(rn);
d62a17ae 2616 bgp_table_unlock(table);
2617 }
aac24838
JB
2618
2619 return WQ_SUCCESS;
2620}
2621
2622static void bgp_processq_del(struct work_queue *wq, void *data)
2623{
2624 struct bgp_process_queue *pqnode = data;
2625
2626 bgp_unlock(pqnode->bgp);
2627
2628 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 2629}
2630
d62a17ae 2631void bgp_process_queue_init(void)
200df115 2632{
0ce1ca80 2633 if (!bm->process_main_queue)
d62a17ae 2634 bm->process_main_queue =
2635 work_queue_new(bm->master, "process_main_queue");
2636
aac24838 2637 bm->process_main_queue->spec.workfunc = &bgp_process_wq;
d62a17ae 2638 bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
2639 bm->process_main_queue->spec.max_retries = 0;
2640 bm->process_main_queue->spec.hold = 50;
2641 /* Use a higher yield value of 50ms for main queue processing */
2642 bm->process_main_queue->spec.yield = 50 * 1000L;
200df115 2643}
2644
cfe8d15a 2645static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
2646{
2647 struct bgp_process_queue *pqnode;
2648
a4d82a8a
PZ
2649 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
2650 sizeof(struct bgp_process_queue));
aac24838
JB
2651
2652 /* unlocked in bgp_processq_del */
2653 pqnode->bgp = bgp_lock(bgp);
2654 STAILQ_INIT(&pqnode->pqueue);
2655
aac24838
JB
2656 return pqnode;
2657}
2658
d62a17ae 2659void bgp_process(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)
fee0f4c6 2660{
aac24838
JB
2661#define ARBITRARY_PROCESS_QLEN 10000
2662 struct work_queue *wq = bm->process_main_queue;
d62a17ae 2663 struct bgp_process_queue *pqnode;
cfe8d15a 2664 int pqnode_reuse = 0;
495f0b13 2665
d62a17ae 2666 /* already scheduled for processing? */
2667 if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED))
2668 return;
2e02b9b2 2669
aac24838 2670 if (wq == NULL)
d62a17ae 2671 return;
2672
aac24838 2673 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
2674 limit only if is from the same BGP view and it's not an EOIU marker
2675 */
aac24838
JB
2676 if (work_queue_item_count(wq)) {
2677 struct work_queue_item *item = work_queue_last_item(wq);
2678 pqnode = item->data;
228da428 2679
a4d82a8a
PZ
2680 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
2681 || pqnode->bgp != bgp
2682 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
2683 pqnode = bgp_processq_alloc(bgp);
2684 else
2685 pqnode_reuse = 1;
aac24838 2686 } else
cfe8d15a 2687 pqnode = bgp_processq_alloc(bgp);
aac24838 2688 /* all unlocked in bgp_process_wq */
d62a17ae 2689 bgp_table_lock(bgp_node_table(rn));
aac24838 2690
d62a17ae 2691 SET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838
JB
2692 bgp_lock_node(rn);
2693
60466a63
QY
2694 /* can't be enqueued twice */
2695 assert(STAILQ_NEXT(rn, pq) == NULL);
aac24838
JB
2696 STAILQ_INSERT_TAIL(&pqnode->pqueue, rn, pq);
2697 pqnode->queued++;
2698
cfe8d15a
LB
2699 if (!pqnode_reuse)
2700 work_queue_add(wq, pqnode);
2701
d62a17ae 2702 return;
fee0f4c6 2703}
0a486e5f 2704
d62a17ae 2705void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 2706{
d62a17ae 2707 struct bgp_process_queue *pqnode;
cb1faec9 2708
d62a17ae 2709 if (bm->process_main_queue == NULL)
2710 return;
2e02b9b2 2711
cfe8d15a 2712 pqnode = bgp_processq_alloc(bgp);
cb1faec9 2713
aac24838 2714 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
cfe8d15a 2715 work_queue_add(bm->process_main_queue, pqnode);
cb1faec9
DS
2716}
2717
d62a17ae 2718static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 2719{
d62a17ae 2720 struct peer *peer;
0a486e5f 2721
d62a17ae 2722 peer = THREAD_ARG(thread);
2723 peer->t_pmax_restart = NULL;
0a486e5f 2724
d62a17ae 2725 if (bgp_debug_neighbor_events(peer))
2726 zlog_debug(
2727 "%s Maximum-prefix restart timer expired, restore peering",
2728 peer->host);
0a486e5f 2729
a9bafa95
DS
2730 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
2731 zlog_debug("%s: %s peer_clear failed",
2732 __PRETTY_FUNCTION__, peer->host);
0a486e5f 2733
d62a17ae 2734 return 0;
0a486e5f 2735}
2736
d62a17ae 2737int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
2738 int always)
718e3744 2739{
d62a17ae 2740 iana_afi_t pkt_afi;
5c525538 2741 iana_safi_t pkt_safi;
9cabb64b 2742
d62a17ae 2743 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
2744 return 0;
e0701b79 2745
d62a17ae 2746 if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) {
2747 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2748 PEER_STATUS_PREFIX_LIMIT)
2749 && !always)
2750 return 0;
e0701b79 2751
d62a17ae 2752 zlog_info(
a0a87037
DA
2753 "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32
2754 " exceed, limit %" PRIu32,
5cb5f4d0 2755 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 2756 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2757 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
2758
2759 if (CHECK_FLAG(peer->af_flags[afi][safi],
2760 PEER_FLAG_MAX_PREFIX_WARNING))
2761 return 0;
2762
2763 /* Convert AFI, SAFI to values for packet. */
2764 pkt_afi = afi_int2iana(afi);
2765 pkt_safi = safi_int2iana(safi);
2766 {
d7c0a89a 2767 uint8_t ndata[7];
d62a17ae 2768
2769 ndata[0] = (pkt_afi >> 8);
2770 ndata[1] = pkt_afi;
2771 ndata[2] = pkt_safi;
2772 ndata[3] = (peer->pmax[afi][safi] >> 24);
2773 ndata[4] = (peer->pmax[afi][safi] >> 16);
2774 ndata[5] = (peer->pmax[afi][safi] >> 8);
2775 ndata[6] = (peer->pmax[afi][safi]);
2776
2777 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2778 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
2779 BGP_NOTIFY_CEASE_MAX_PREFIX,
2780 ndata, 7);
2781 }
2782
2783 /* Dynamic peers will just close their connection. */
2784 if (peer_dynamic_neighbor(peer))
2785 return 1;
2786
2787 /* restart timer start */
2788 if (peer->pmax_restart[afi][safi]) {
2789 peer->v_pmax_restart =
2790 peer->pmax_restart[afi][safi] * 60;
2791
2792 if (bgp_debug_neighbor_events(peer))
2793 zlog_debug(
2794 "%s Maximum-prefix restart timer started for %d secs",
2795 peer->host, peer->v_pmax_restart);
2796
2797 BGP_TIMER_ON(peer->t_pmax_restart,
2798 bgp_maximum_prefix_restart_timer,
2799 peer->v_pmax_restart);
2800 }
2801
2802 return 1;
2803 } else
2804 UNSET_FLAG(peer->af_sflags[afi][safi],
2805 PEER_STATUS_PREFIX_LIMIT);
2806
2807 if (peer->pcount[afi][safi]
2808 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
2809 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2810 PEER_STATUS_PREFIX_THRESHOLD)
2811 && !always)
2812 return 0;
2813
2814 zlog_info(
a0a87037
DA
2815 "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32
2816 ", max %" PRIu32,
5cb5f4d0 2817 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 2818 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2819 SET_FLAG(peer->af_sflags[afi][safi],
2820 PEER_STATUS_PREFIX_THRESHOLD);
2821 } else
2822 UNSET_FLAG(peer->af_sflags[afi][safi],
2823 PEER_STATUS_PREFIX_THRESHOLD);
2824 return 0;
718e3744 2825}
2826
b40d939b 2827/* Unconditionally remove the route from the RIB, without taking
2828 * damping into consideration (eg, because the session went down)
2829 */
40381db7 2830void bgp_rib_remove(struct bgp_node *rn, struct bgp_path_info *pi,
4b7e6066 2831 struct peer *peer, afi_t afi, safi_t safi)
718e3744 2832{
40381db7 2833 bgp_aggregate_decrement(peer->bgp, &rn->p, pi, afi, safi);
d62a17ae 2834
40381db7
DS
2835 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
2836 bgp_path_info_delete(rn, pi); /* keep historical info */
d62a17ae 2837
4a11bf2c
DL
2838 hook_call(bgp_process, peer->bgp, afi, safi, rn, peer, true);
2839
d62a17ae 2840 bgp_process(peer->bgp, rn, afi, safi);
2841}
2842
40381db7 2843static void bgp_rib_withdraw(struct bgp_node *rn, struct bgp_path_info *pi,
d62a17ae 2844 struct peer *peer, afi_t afi, safi_t safi,
2845 struct prefix_rd *prd)
2846{
d62a17ae 2847 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 2848 * the bgp_path_info in the RIB for historical reference.
d62a17ae 2849 */
2850 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
2851 && peer->sort == BGP_PEER_EBGP)
40381db7 2852 if ((bgp_damp_withdraw(pi, rn, afi, safi, 0))
d62a17ae 2853 == BGP_DAMP_SUPPRESSED) {
40381db7 2854 bgp_aggregate_decrement(peer->bgp, &rn->p, pi, afi,
d62a17ae 2855 safi);
2856 return;
2857 }
2858
65efcfce 2859#if ENABLE_BGP_VNC
d62a17ae 2860 if (safi == SAFI_MPLS_VPN) {
2861 struct bgp_node *prn = NULL;
2862 struct bgp_table *table = NULL;
2863
2864 prn = bgp_node_get(peer->bgp->rib[afi][safi],
2865 (struct prefix *)prd);
67009e22
DS
2866 if (bgp_node_has_bgp_path_info_data(prn)) {
2867 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 2868
2869 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 2870 peer->bgp, prd, table, &rn->p, pi);
d62a17ae 2871 }
2872 bgp_unlock_node(prn);
2873 }
2874 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 2875 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 2876
40381db7 2877 vnc_import_bgp_del_route(peer->bgp, &rn->p, pi);
d62a17ae 2878 vnc_import_bgp_exterior_del_route(peer->bgp, &rn->p,
40381db7 2879 pi);
d62a17ae 2880 }
65efcfce 2881 }
d62a17ae 2882#endif
128ea8ab 2883
d62a17ae 2884 /* If this is an EVPN route, process for un-import. */
2885 if (safi == SAFI_EVPN)
40381db7 2886 bgp_evpn_unimport_route(peer->bgp, afi, safi, &rn->p, pi);
128ea8ab 2887
40381db7 2888 bgp_rib_remove(rn, pi, peer, afi, safi);
718e3744 2889}
2890
4b7e6066
DS
2891struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
2892 struct peer *peer, struct attr *attr,
2893 struct bgp_node *rn)
fb018d25 2894{
4b7e6066 2895 struct bgp_path_info *new;
fb018d25 2896
d62a17ae 2897 /* Make new BGP info. */
4b7e6066 2898 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 2899 new->type = type;
2900 new->instance = instance;
2901 new->sub_type = sub_type;
2902 new->peer = peer;
2903 new->attr = attr;
2904 new->uptime = bgp_clock();
2905 new->net = rn;
d62a17ae 2906 return new;
fb018d25
DS
2907}
2908
d62a17ae 2909static void overlay_index_update(struct attr *attr,
2910 struct eth_segment_id *eth_s_id,
2911 union gw_addr *gw_ip)
684a7227 2912{
d62a17ae 2913 if (!attr)
2914 return;
684a7227 2915
d62a17ae 2916 if (eth_s_id == NULL) {
2917 memset(&(attr->evpn_overlay.eth_s_id), 0,
2918 sizeof(struct eth_segment_id));
2919 } else {
2920 memcpy(&(attr->evpn_overlay.eth_s_id), eth_s_id,
2921 sizeof(struct eth_segment_id));
2922 }
2923 if (gw_ip == NULL) {
2924 memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr));
2925 } else {
2926 memcpy(&(attr->evpn_overlay.gw_ip), gw_ip,
2927 sizeof(union gw_addr));
2928 }
684a7227
PG
2929}
2930
40381db7 2931static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 2932 struct eth_segment_id *eth_s_id,
2933 union gw_addr *gw_ip)
2934{
40381db7
DS
2935 struct eth_segment_id *path_eth_s_id, *path_eth_s_id_remote;
2936 union gw_addr *path_gw_ip, *path_gw_ip_remote;
11ebf4ed
DS
2937 union {
2938 struct eth_segment_id esi;
2939 union gw_addr ip;
2940 } temp;
d62a17ae 2941
2942 if (afi != AFI_L2VPN)
2943 return true;
11ebf4ed 2944
05864da7
DS
2945 path_eth_s_id = &(path->attr->evpn_overlay.eth_s_id);
2946 path_gw_ip = &(path->attr->evpn_overlay.gw_ip);
11ebf4ed
DS
2947
2948 if (gw_ip == NULL) {
2949 memset(&temp, 0, sizeof(temp));
40381db7 2950 path_gw_ip_remote = &temp.ip;
11ebf4ed 2951 } else
40381db7 2952 path_gw_ip_remote = gw_ip;
11ebf4ed
DS
2953
2954 if (eth_s_id == NULL) {
2955 memset(&temp, 0, sizeof(temp));
40381db7 2956 path_eth_s_id_remote = &temp.esi;
11ebf4ed 2957 } else
40381db7 2958 path_eth_s_id_remote = eth_s_id;
11ebf4ed 2959
40381db7 2960 if (!memcmp(path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr)))
d62a17ae 2961 return false;
11ebf4ed 2962
40381db7 2963 return !memcmp(path_eth_s_id, path_eth_s_id_remote,
d62a17ae 2964 sizeof(struct eth_segment_id));
684a7227
PG
2965}
2966
c265ee22 2967/* Check if received nexthop is valid or not. */
d62a17ae 2968static int bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
2969 struct attr *attr)
2970{
2971 int ret = 0;
2972
2973 /* Only validated for unicast and multicast currently. */
2974 /* Also valid for EVPN where the nexthop is an IP address. */
2975 if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN)
2976 return 0;
2977
2978 /* If NEXT_HOP is present, validate it. */
2979 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
2980 if (attr->nexthop.s_addr == 0
2981 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
2982 || bgp_nexthop_self(bgp, attr->nexthop))
2983 return 1;
2984 }
c265ee22 2985
d62a17ae 2986 /* If MP_NEXTHOP is present, validate it. */
2987 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2988 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2989 * it is not an IPv6 link-local address.
2990 */
2991 if (attr->mp_nexthop_len) {
2992 switch (attr->mp_nexthop_len) {
2993 case BGP_ATTR_NHLEN_IPV4:
2994 case BGP_ATTR_NHLEN_VPNV4:
2995 ret = (attr->mp_nexthop_global_in.s_addr == 0
2996 || IPV4_CLASS_DE(ntohl(
2997 attr->mp_nexthop_global_in.s_addr))
2998 || bgp_nexthop_self(bgp,
2999 attr->mp_nexthop_global_in));
3000 break;
3001
3002 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
3003 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3004 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
3005 ret = (IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global)
3006 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3007 || IN6_IS_ADDR_MULTICAST(
5e76ce50 3008 &attr->mp_nexthop_global));
d62a17ae 3009 break;
3010
3011 default:
3012 ret = 1;
3013 break;
3014 }
3015 }
c265ee22 3016
d62a17ae 3017 return ret;
3018}
3019
d7c0a89a 3020int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
d62a17ae 3021 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3022 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3023 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3024 struct bgp_route_evpn *evpn)
d62a17ae 3025{
3026 int ret;
3027 int aspath_loop_count = 0;
3028 struct bgp_node *rn;
3029 struct bgp *bgp;
3030 struct attr new_attr;
3031 struct attr *attr_new;
40381db7 3032 struct bgp_path_info *pi;
4b7e6066
DS
3033 struct bgp_path_info *new;
3034 struct bgp_path_info_extra *extra;
d62a17ae 3035 const char *reason;
3036 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3037 int connected = 0;
3038 int do_loop_check = 1;
3039 int has_valid_label = 0;
65efcfce 3040#if ENABLE_BGP_VNC
d62a17ae 3041 int vnc_implicit_withdraw = 0;
65efcfce 3042#endif
d62a17ae 3043 int same_attr = 0;
718e3744 3044
d62a17ae 3045 memset(&new_attr, 0, sizeof(struct attr));
3046 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3047 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3048
d62a17ae 3049 bgp = peer->bgp;
3050 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3051 /* TODO: Check to see if we can get rid of "is_valid_label" */
3052 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3053 has_valid_label = (num_labels > 0) ? 1 : 0;
3054 else
3055 has_valid_label = bgp_is_valid_label(label);
718e3744 3056
d62a17ae 3057 /* When peer's soft reconfiguration enabled. Record input packet in
3058 Adj-RIBs-In. */
3059 if (!soft_reconfig
3060 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3061 && peer != bgp->peer_self)
3062 bgp_adj_in_set(rn, peer, attr, addpath_id);
3063
3064 /* Check previously received route. */
6f94b685 3065 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
3066 if (pi->peer == peer && pi->type == type
3067 && pi->sub_type == sub_type
3068 && pi->addpath_rx_id == addpath_id)
d62a17ae 3069 break;
3070
3071 /* AS path local-as loop check. */
3072 if (peer->change_local_as) {
c4368918
DW
3073 if (peer->allowas_in[afi][safi])
3074 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3075 else if (!CHECK_FLAG(peer->flags,
3076 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3077 aspath_loop_count = 1;
3078
3079 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3080 > aspath_loop_count) {
b4d46cc9 3081 peer->stat_pfx_aspath_loop++;
d62a17ae 3082 reason = "as-path contains our own AS;";
3083 goto filtered;
3084 }
718e3744 3085 }
718e3744 3086
d62a17ae 3087 /* If the peer is configured for "allowas-in origin" and the last ASN in
3088 * the
3089 * as-path is our ASN then we do not need to call aspath_loop_check
3090 */
3091 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3092 if (aspath_get_last_as(attr->aspath) == bgp->as)
3093 do_loop_check = 0;
3094
3095 /* AS path loop check. */
3096 if (do_loop_check) {
3097 if (aspath_loop_check(attr->aspath, bgp->as)
3098 > peer->allowas_in[afi][safi]
3099 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3100 && aspath_loop_check(attr->aspath, bgp->confed_id)
3101 > peer->allowas_in[afi][safi])) {
b4d46cc9 3102 peer->stat_pfx_aspath_loop++;
d62a17ae 3103 reason = "as-path contains our own AS;";
3104 goto filtered;
3105 }
3106 }
aac9ef6c 3107
d62a17ae 3108 /* Route reflector originator ID check. */
3109 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3110 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3111 peer->stat_pfx_originator_loop++;
d62a17ae 3112 reason = "originator is us;";
3113 goto filtered;
3114 }
718e3744 3115
d62a17ae 3116 /* Route reflector cluster ID check. */
3117 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3118 peer->stat_pfx_cluster_loop++;
d62a17ae 3119 reason = "reflected from the same cluster;";
3120 goto filtered;
3121 }
718e3744 3122
d62a17ae 3123 /* Apply incoming filter. */
3124 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3125 peer->stat_pfx_filter++;
d62a17ae 3126 reason = "filter;";
3127 goto filtered;
3128 }
718e3744 3129
a8b72dc6
DA
3130 /* RFC 8212 to prevent route leaks.
3131 * This specification intends to improve this situation by requiring the
3132 * explicit configuration of both BGP Import and Export Policies for any
3133 * External BGP (EBGP) session such as customers, peers, or
3134 * confederation boundaries for all enabled address families. Through
3135 * codification of the aforementioned requirement, operators will
3136 * benefit from consistent behavior across different BGP
3137 * implementations.
3138 */
3139 if (peer->bgp->ebgp_requires_policy == DEFAULT_EBGP_POLICY_ENABLED)
3140 if (!bgp_inbound_policy_exists(peer,
3141 &peer->filter[afi][safi])) {
3142 reason = "inbound policy missing";
3143 goto filtered;
3144 }
3145
d62a17ae 3146 bgp_attr_dup(&new_attr, attr);
3147
3148 /* Apply incoming route-map.
3149 * NB: new_attr may now contain newly allocated values from route-map
3150 * "set"
3151 * commands, so we need bgp_attr_flush in the error paths, until we
3152 * intern
3153 * the attr (which takes over the memory references) */
82b692c0
LK
3154 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL,
3155 label, num_labels) == RMAP_DENY) {
b4d46cc9 3156 peer->stat_pfx_filter++;
d62a17ae 3157 reason = "route-map;";
3158 bgp_attr_flush(&new_attr);
3159 goto filtered;
3160 }
718e3744 3161
05864da7 3162 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3163 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3164 /* remove from RIB previous entry */
3165 bgp_zebra_withdraw(p, pi, bgp, safi);
3166 }
3167
7f323236
DW
3168 if (peer->sort == BGP_PEER_EBGP) {
3169
a4d82a8a
PZ
3170 /* If we receive the graceful-shutdown community from an eBGP
3171 * peer we must lower local-preference */
3172 if (new_attr.community
3173 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3174 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3175 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3176
a4d82a8a
PZ
3177 /* If graceful-shutdown is configured then add the GSHUT
3178 * community to all paths received from eBGP peers */
3179 } else if (bgp_flag_check(peer->bgp,
3180 BGP_FLAG_GRACEFUL_SHUTDOWN)) {
7f323236
DW
3181 bgp_attr_add_gshut_community(&new_attr);
3182 }
3183 }
3184
d62a17ae 3185 /* next hop check. */
a4d82a8a
PZ
3186 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
3187 && bgp_update_martian_nexthop(bgp, afi, safi, &new_attr)) {
b4d46cc9 3188 peer->stat_pfx_nh_invalid++;
d62a17ae 3189 reason = "martian or self next-hop;";
3190 bgp_attr_flush(&new_attr);
3191 goto filtered;
3192 }
718e3744 3193
5c14a191 3194 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3195 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3196 reason = "self mac;";
3197 goto filtered;
3198 }
3199
d62a17ae 3200 attr_new = bgp_attr_intern(&new_attr);
3201
3202 /* If the update is implicit withdraw. */
40381db7
DS
3203 if (pi) {
3204 pi->uptime = bgp_clock();
3205 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3206
4a11bf2c
DL
3207 hook_call(bgp_process, bgp, afi, safi, rn, peer, true);
3208
d62a17ae 3209 /* Same attribute comes in. */
40381db7
DS
3210 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3211 && attrhash_cmp(pi->attr, attr_new)
d62a17ae 3212 && (!has_valid_label
40381db7 3213 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3214 num_labels * sizeof(mpls_label_t))
d62a17ae 3215 == 0)
3216 && (overlay_index_equal(
40381db7 3217 afi, pi, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3218 evpn == NULL ? NULL : &evpn->gw_ip))) {
3219 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3220 BGP_CONFIG_DAMPENING)
3221 && peer->sort == BGP_PEER_EBGP
40381db7 3222 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3223 if (bgp_debug_update(peer, p, NULL, 1)) {
3224 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3225 afi, safi, prd, p, label,
3226 num_labels, addpath_id ? 1 : 0,
3227 addpath_id, pfx_buf,
3228 sizeof(pfx_buf));
d62a17ae 3229 zlog_debug("%s rcvd %s", peer->host,
3230 pfx_buf);
3231 }
3232
40381db7 3233 if (bgp_damp_update(pi, rn, afi, safi)
d62a17ae 3234 != BGP_DAMP_SUPPRESSED) {
40381db7 3235 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3236 safi);
3237 bgp_process(bgp, rn, afi, safi);
3238 }
3239 } else /* Duplicate - odd */
3240 {
3241 if (bgp_debug_update(peer, p, NULL, 1)) {
3242 if (!peer->rcvd_attr_printed) {
3243 zlog_debug(
3244 "%s rcvd UPDATE w/ attr: %s",
3245 peer->host,
3246 peer->rcvd_attr_str);
3247 peer->rcvd_attr_printed = 1;
3248 }
3249
3250 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3251 afi, safi, prd, p, label,
3252 num_labels, addpath_id ? 1 : 0,
3253 addpath_id, pfx_buf,
3254 sizeof(pfx_buf));
d62a17ae 3255 zlog_debug(
3256 "%s rcvd %s...duplicate ignored",
3257 peer->host, pfx_buf);
3258 }
3259
3260 /* graceful restart STALE flag unset. */
40381db7 3261 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3262 bgp_path_info_unset_flag(
40381db7 3263 rn, pi, BGP_PATH_STALE);
d62a17ae 3264 bgp_process(bgp, rn, afi, safi);
3265 }
3266 }
3267
3268 bgp_unlock_node(rn);
3269 bgp_attr_unintern(&attr_new);
3270
3271 return 0;
3272 }
718e3744 3273
d62a17ae 3274 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3275 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3276 if (bgp_debug_update(peer, p, NULL, 1)) {
3277 bgp_debug_rdpfxpath2str(
a4d82a8a 3278 afi, safi, prd, p, label, num_labels,
d62a17ae 3279 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3280 sizeof(pfx_buf));
3281 zlog_debug(
3282 "%s rcvd %s, flapped quicker than processing",
3283 peer->host, pfx_buf);
3284 }
3285
40381db7 3286 bgp_path_info_restore(rn, pi);
d62a17ae 3287 }
718e3744 3288
d62a17ae 3289 /* Received Logging. */
3290 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3291 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3292 num_labels, addpath_id ? 1 : 0,
3293 addpath_id, pfx_buf,
3294 sizeof(pfx_buf));
d62a17ae 3295 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3296 }
718e3744 3297
d62a17ae 3298 /* graceful restart STALE flag unset. */
40381db7
DS
3299 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
3300 bgp_path_info_unset_flag(rn, pi, BGP_PATH_STALE);
d62a17ae 3301
3302 /* The attribute is changed. */
40381db7 3303 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3304
3305 /* implicit withdraw, decrement aggregate and pcount here.
3306 * only if update is accepted, they'll increment below.
3307 */
40381db7 3308 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3309
3310 /* Update bgp route dampening information. */
3311 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3312 && peer->sort == BGP_PEER_EBGP) {
3313 /* This is implicit withdraw so we should update
3314 dampening
3315 information. */
40381db7
DS
3316 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
3317 bgp_damp_withdraw(pi, rn, afi, safi, 1);
d62a17ae 3318 }
65efcfce 3319#if ENABLE_BGP_VNC
d62a17ae 3320 if (safi == SAFI_MPLS_VPN) {
3321 struct bgp_node *prn = NULL;
3322 struct bgp_table *table = NULL;
3323
3324 prn = bgp_node_get(bgp->rib[afi][safi],
3325 (struct prefix *)prd);
67009e22
DS
3326 if (bgp_node_has_bgp_path_info_data(prn)) {
3327 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3328
3329 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3330 bgp, prd, table, p, pi);
d62a17ae 3331 }
3332 bgp_unlock_node(prn);
3333 }
3334 if ((afi == AFI_IP || afi == AFI_IP6)
3335 && (safi == SAFI_UNICAST)) {
40381db7 3336 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3337 /*
3338 * Implicit withdraw case.
3339 */
3340 ++vnc_implicit_withdraw;
40381db7
DS
3341 vnc_import_bgp_del_route(bgp, p, pi);
3342 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3343 }
3344 }
65efcfce 3345#endif
128ea8ab 3346
d62a17ae 3347 /* Special handling for EVPN update of an existing route. If the
3348 * extended community attribute has changed, we need to
3349 * un-import
3350 * the route using its existing extended community. It will be
3351 * subsequently processed for import with the new extended
3352 * community.
3353 */
3354 if (safi == SAFI_EVPN && !same_attr) {
40381db7 3355 if ((pi->attr->flag
d62a17ae 3356 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3357 && (attr_new->flag
3358 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3359 int cmp;
3360
40381db7 3361 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3362 attr_new->ecommunity);
3363 if (!cmp) {
3364 if (bgp_debug_update(peer, p, NULL, 1))
3365 zlog_debug(
3366 "Change in EXT-COMM, existing %s new %s",
3367 ecommunity_str(
40381db7 3368 pi->attr->ecommunity),
d62a17ae 3369 ecommunity_str(
3370 attr_new->ecommunity));
3371 bgp_evpn_unimport_route(bgp, afi, safi,
40381db7 3372 p, pi);
d62a17ae 3373 }
3374 }
3375 }
718e3744 3376
d62a17ae 3377 /* Update to new attribute. */
40381db7
DS
3378 bgp_attr_unintern(&pi->attr);
3379 pi->attr = attr_new;
d62a17ae 3380
3381 /* Update MPLS label */
3382 if (has_valid_label) {
40381db7 3383 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3384 if (extra->label != label) {
3385 memcpy(&extra->label, label,
dbd587da 3386 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3387 extra->num_labels = num_labels;
3388 }
b57ba6d2
MK
3389 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3390 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3391 }
718e3744 3392
65efcfce 3393#if ENABLE_BGP_VNC
d62a17ae 3394 if ((afi == AFI_IP || afi == AFI_IP6)
3395 && (safi == SAFI_UNICAST)) {
3396 if (vnc_implicit_withdraw) {
3397 /*
3398 * Add back the route with its new attributes
3399 * (e.g., nexthop).
3400 * The route is still selected, until the route
3401 * selection
3402 * queued by bgp_process actually runs. We have
3403 * to make this
3404 * update to the VNC side immediately to avoid
3405 * racing against
3406 * configuration changes (e.g., route-map
3407 * changes) which
3408 * trigger re-importation of the entire RIB.
3409 */
40381db7
DS
3410 vnc_import_bgp_add_route(bgp, p, pi);
3411 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 3412 }
3413 }
65efcfce 3414#endif
d62a17ae 3415 /* Update Overlay Index */
3416 if (afi == AFI_L2VPN) {
3417 overlay_index_update(
40381db7 3418 pi->attr, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3419 evpn == NULL ? NULL : &evpn->gw_ip);
3420 }
65efcfce 3421
d62a17ae 3422 /* Update bgp route dampening information. */
3423 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3424 && peer->sort == BGP_PEER_EBGP) {
3425 /* Now we do normal update dampening. */
40381db7 3426 ret = bgp_damp_update(pi, rn, afi, safi);
d62a17ae 3427 if (ret == BGP_DAMP_SUPPRESSED) {
3428 bgp_unlock_node(rn);
3429 return 0;
3430 }
3431 }
128ea8ab 3432
d62a17ae 3433 /* Nexthop reachability check - for unicast and
3434 * labeled-unicast.. */
3435 if ((afi == AFI_IP || afi == AFI_IP6)
3436 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
3437 if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1
3438 && !CHECK_FLAG(peer->flags,
3439 PEER_FLAG_DISABLE_CONNECTED_CHECK)
3440 && !bgp_flag_check(
3441 bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
3442 connected = 1;
3443 else
3444 connected = 0;
3445
960035b2
PZ
3446 struct bgp *bgp_nexthop = bgp;
3447
40381db7
DS
3448 if (pi->extra && pi->extra->bgp_orig)
3449 bgp_nexthop = pi->extra->bgp_orig;
960035b2 3450
40381db7
DS
3451 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, afi, pi,
3452 NULL, connected)
a4d82a8a 3453 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
40381db7 3454 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 3455 else {
3456 if (BGP_DEBUG(nht, NHT)) {
3457 char buf1[INET6_ADDRSTRLEN];
3458 inet_ntop(AF_INET,
3459 (const void *)&attr_new
3460 ->nexthop,
3461 buf1, INET6_ADDRSTRLEN);
3462 zlog_debug("%s(%s): NH unresolved",
3463 __FUNCTION__, buf1);
3464 }
40381db7 3465 bgp_path_info_unset_flag(rn, pi,
18ee8310 3466 BGP_PATH_VALID);
d62a17ae 3467 }
3468 } else
40381db7 3469 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 3470
3471#if ENABLE_BGP_VNC
3472 if (safi == SAFI_MPLS_VPN) {
3473 struct bgp_node *prn = NULL;
3474 struct bgp_table *table = NULL;
3475
3476 prn = bgp_node_get(bgp->rib[afi][safi],
3477 (struct prefix *)prd);
67009e22
DS
3478 if (bgp_node_has_bgp_path_info_data(prn)) {
3479 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3480
3481 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 3482 bgp, prd, table, p, pi);
d62a17ae 3483 }
3484 bgp_unlock_node(prn);
3485 }
3486#endif
718e3744 3487
d62a17ae 3488 /* If this is an EVPN route and some attribute has changed,
3489 * process
3490 * route for import. If the extended community has changed, we
3491 * would
3492 * have done the un-import earlier and the import would result
3493 * in the
3494 * route getting injected into appropriate L2 VNIs. If it is
3495 * just
3496 * some other attribute change, the import will result in
3497 * updating
3498 * the attributes for the route in the VNI(s).
3499 */
3500 if (safi == SAFI_EVPN && !same_attr)
40381db7 3501 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 3502
3503 /* Process change. */
40381db7 3504 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 3505
3506 bgp_process(bgp, rn, afi, safi);
3507 bgp_unlock_node(rn);
558d1fec 3508
ddb5b488
PZ
3509 if (SAFI_UNICAST == safi
3510 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3511 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3512
40381db7 3513 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3514 }
3515 if ((SAFI_MPLS_VPN == safi)
3516 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3517
40381db7 3518 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
3519 }
3520
28070ee3 3521#if ENABLE_BGP_VNC
d62a17ae 3522 if (SAFI_MPLS_VPN == safi) {
3523 mpls_label_t label_decoded = decode_label(label);
28070ee3 3524
d62a17ae 3525 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3526 type, sub_type, &label_decoded);
3527 }
3528 if (SAFI_ENCAP == safi) {
3529 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3530 type, sub_type, NULL);
3531 }
28070ee3
PZ
3532#endif
3533
d62a17ae 3534 return 0;
3535 } // End of implicit withdraw
718e3744 3536
d62a17ae 3537 /* Received Logging. */
3538 if (bgp_debug_update(peer, p, NULL, 1)) {
3539 if (!peer->rcvd_attr_printed) {
3540 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3541 peer->rcvd_attr_str);
3542 peer->rcvd_attr_printed = 1;
3543 }
718e3744 3544
a4d82a8a 3545 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3546 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3547 sizeof(pfx_buf));
3548 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3549 }
718e3744 3550
d62a17ae 3551 /* Make new BGP info. */
3552 new = info_make(type, sub_type, 0, peer, attr_new, rn);
718e3744 3553
d62a17ae 3554 /* Update MPLS label */
3555 if (has_valid_label) {
18ee8310 3556 extra = bgp_path_info_extra_get(new);
8ba71050 3557 if (extra->label != label) {
dbd587da
QY
3558 memcpy(&extra->label, label,
3559 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3560 extra->num_labels = num_labels;
3561 }
b57ba6d2
MK
3562 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3563 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3564 }
718e3744 3565
d62a17ae 3566 /* Update Overlay Index */
3567 if (afi == AFI_L2VPN) {
3568 overlay_index_update(new->attr,
3569 evpn == NULL ? NULL : &evpn->eth_s_id,
3570 evpn == NULL ? NULL : &evpn->gw_ip);
3571 }
3572 /* Nexthop reachability check. */
3573 if ((afi == AFI_IP || afi == AFI_IP6)
3574 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
3575 if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1
3576 && !CHECK_FLAG(peer->flags,
3577 PEER_FLAG_DISABLE_CONNECTED_CHECK)
3578 && !bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
3579 connected = 1;
3580 else
3581 connected = 0;
3582
960035b2 3583 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, connected)
a4d82a8a 3584 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
18ee8310 3585 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
d62a17ae 3586 else {
3587 if (BGP_DEBUG(nht, NHT)) {
3588 char buf1[INET6_ADDRSTRLEN];
3589 inet_ntop(AF_INET,
3590 (const void *)&attr_new->nexthop,
3591 buf1, INET6_ADDRSTRLEN);
3592 zlog_debug("%s(%s): NH unresolved",
3593 __FUNCTION__, buf1);
3594 }
18ee8310 3595 bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID);
d62a17ae 3596 }
3597 } else
18ee8310 3598 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
a82478b9 3599
d62a17ae 3600 /* Addpath ID */
3601 new->addpath_rx_id = addpath_id;
3602
3603 /* Increment prefix */
3604 bgp_aggregate_increment(bgp, p, new, afi, safi);
3605
3606 /* Register new BGP information. */
18ee8310 3607 bgp_path_info_add(rn, new);
d62a17ae 3608
3609 /* route_node_get lock */
3610 bgp_unlock_node(rn);
558d1fec 3611
65efcfce 3612#if ENABLE_BGP_VNC
d62a17ae 3613 if (safi == SAFI_MPLS_VPN) {
3614 struct bgp_node *prn = NULL;
3615 struct bgp_table *table = NULL;
3616
3617 prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
67009e22
DS
3618 if (bgp_node_has_bgp_path_info_data(prn)) {
3619 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3620
3621 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3622 bgp, prd, table, p, new);
3623 }
3624 bgp_unlock_node(prn);
3625 }
65efcfce
LB
3626#endif
3627
d62a17ae 3628 /* If maximum prefix count is configured and current prefix
3629 count exeed it. */
3630 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3631 return -1;
718e3744 3632
d62a17ae 3633 /* If this is an EVPN route, process for import. */
3634 if (safi == SAFI_EVPN)
3635 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 3636
4a11bf2c
DL
3637 hook_call(bgp_process, bgp, afi, safi, rn, peer, false);
3638
d62a17ae 3639 /* Process change. */
3640 bgp_process(bgp, rn, afi, safi);
718e3744 3641
ddb5b488
PZ
3642 if (SAFI_UNICAST == safi
3643 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3644 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3645 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
3646 }
3647 if ((SAFI_MPLS_VPN == safi)
3648 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3649
3650 vpn_leak_to_vrf_update(bgp, new);
3651 }
28070ee3 3652#if ENABLE_BGP_VNC
d62a17ae 3653 if (SAFI_MPLS_VPN == safi) {
3654 mpls_label_t label_decoded = decode_label(label);
28070ee3 3655
d62a17ae 3656 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3657 sub_type, &label_decoded);
3658 }
3659 if (SAFI_ENCAP == safi) {
3660 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3661 sub_type, NULL);
3662 }
28070ee3
PZ
3663#endif
3664
d62a17ae 3665 return 0;
718e3744 3666
d62a17ae 3667/* This BGP update is filtered. Log the reason then update BGP
3668 entry. */
3669filtered:
4a11bf2c
DL
3670 hook_call(bgp_process, bgp, afi, safi, rn, peer, true);
3671
d62a17ae 3672 if (bgp_debug_update(peer, p, NULL, 1)) {
3673 if (!peer->rcvd_attr_printed) {
3674 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3675 peer->rcvd_attr_str);
3676 peer->rcvd_attr_printed = 1;
3677 }
718e3744 3678
a4d82a8a 3679 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3680 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3681 sizeof(pfx_buf));
3682 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3683 peer->host, pfx_buf, reason);
3684 }
128ea8ab 3685
40381db7 3686 if (pi) {
d62a17ae 3687 /* If this is an EVPN route, un-import it as it is now filtered.
3688 */
3689 if (safi == SAFI_EVPN)
40381db7 3690 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 3691
ddb5b488
PZ
3692 if (SAFI_UNICAST == safi
3693 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3694 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3695
40381db7 3696 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3697 }
3698 if ((SAFI_MPLS_VPN == safi)
3699 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3700
40381db7 3701 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
3702 }
3703
40381db7 3704 bgp_rib_remove(rn, pi, peer, afi, safi);
d62a17ae 3705 }
3706
3707 bgp_unlock_node(rn);
558d1fec 3708
97736e32 3709#if ENABLE_BGP_VNC
d62a17ae 3710 /*
3711 * Filtered update is treated as an implicit withdrawal (see
3712 * bgp_rib_remove()
3713 * a few lines above)
3714 */
3715 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
3716 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
3717 0);
3718 }
97736e32
PZ
3719#endif
3720
d62a17ae 3721 return 0;
718e3744 3722}
3723
d7c0a89a 3724int bgp_withdraw(struct peer *peer, struct prefix *p, uint32_t addpath_id,
d62a17ae 3725 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3726 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3727 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 3728{
d62a17ae 3729 struct bgp *bgp;
3730 char pfx_buf[BGP_PRD_PATH_STRLEN];
3731 struct bgp_node *rn;
40381db7 3732 struct bgp_path_info *pi;
718e3744 3733
28070ee3 3734#if ENABLE_BGP_VNC
d62a17ae 3735 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
3736 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
3737 0);
3738 }
28070ee3
PZ
3739#endif
3740
d62a17ae 3741 bgp = peer->bgp;
3742
3743 /* Lookup node. */
3744 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
3745
3746 /* If peer is soft reconfiguration enabled. Record input packet for
3747 * further calculation.
3748 *
3749 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3750 * routes that are filtered. This tanks out Quagga RS pretty badly due
3751 * to
3752 * the iteration over all RS clients.
3753 * Since we need to remove the entry from adj_in anyway, do that first
3754 * and
3755 * if there was no entry, we don't need to do anything more.
3756 */
3757 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3758 && peer != bgp->peer_self)
3759 if (!bgp_adj_in_unset(rn, peer, addpath_id)) {
b4d46cc9
DL
3760 peer->stat_pfx_dup_withdraw++;
3761
d62a17ae 3762 if (bgp_debug_update(peer, p, NULL, 1)) {
3763 bgp_debug_rdpfxpath2str(
a4d82a8a 3764 afi, safi, prd, p, label, num_labels,
d62a17ae 3765 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3766 sizeof(pfx_buf));
3767 zlog_debug(
3768 "%s withdrawing route %s not in adj-in",
3769 peer->host, pfx_buf);
3770 }
3771 bgp_unlock_node(rn);
3772 return 0;
3773 }
cd808e74 3774
d62a17ae 3775 /* Lookup withdrawn route. */
6f94b685 3776 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
3777 if (pi->peer == peer && pi->type == type
3778 && pi->sub_type == sub_type
3779 && pi->addpath_rx_id == addpath_id)
d62a17ae 3780 break;
3781
3782 /* Logging. */
3783 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 3784 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3785 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3786 sizeof(pfx_buf));
3787 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
3788 pfx_buf);
3789 }
718e3744 3790
d62a17ae 3791 /* Withdraw specified route from routing table. */
40381db7
DS
3792 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
3793 bgp_rib_withdraw(rn, pi, peer, afi, safi, prd);
ddb5b488
PZ
3794 if (SAFI_UNICAST == safi
3795 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3796 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 3797 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3798 }
3799 if ((SAFI_MPLS_VPN == safi)
3800 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3801
40381db7 3802 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
3803 }
3804 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 3805 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3806 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3807 sizeof(pfx_buf));
3808 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
3809 }
718e3744 3810
d62a17ae 3811 /* Unlock bgp_node_get() lock. */
3812 bgp_unlock_node(rn);
3813
3814 return 0;
718e3744 3815}
6b0655a2 3816
d62a17ae 3817void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
3818 int withdraw)
718e3744 3819{
d62a17ae 3820 struct update_subgroup *subgrp;
3821 subgrp = peer_subgroup(peer, afi, safi);
3822 subgroup_default_originate(subgrp, withdraw);
3f9c7369 3823}
6182d65b 3824
718e3744 3825
3f9c7369
DS
3826/*
3827 * bgp_stop_announce_route_timer
3828 */
d62a17ae 3829void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 3830{
d62a17ae 3831 if (!paf->t_announce_route)
3832 return;
3833
3834 THREAD_TIMER_OFF(paf->t_announce_route);
718e3744 3835}
6b0655a2 3836
3f9c7369
DS
3837/*
3838 * bgp_announce_route_timer_expired
3839 *
3840 * Callback that is invoked when the route announcement timer for a
3841 * peer_af expires.
3842 */
d62a17ae 3843static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 3844{
d62a17ae 3845 struct peer_af *paf;
3846 struct peer *peer;
558d1fec 3847
d62a17ae 3848 paf = THREAD_ARG(t);
3849 peer = paf->peer;
718e3744 3850
d62a17ae 3851 if (peer->status != Established)
3852 return 0;
3f9c7369 3853
d62a17ae 3854 if (!peer->afc_nego[paf->afi][paf->safi])
3855 return 0;
3f9c7369 3856
d62a17ae 3857 peer_af_announce_route(paf, 1);
3858 return 0;
718e3744 3859}
3860
3f9c7369
DS
3861/*
3862 * bgp_announce_route
3863 *
3864 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3865 */
d62a17ae 3866void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
3867{
3868 struct peer_af *paf;
3869 struct update_subgroup *subgrp;
3870
3871 paf = peer_af_find(peer, afi, safi);
3872 if (!paf)
3873 return;
3874 subgrp = PAF_SUBGRP(paf);
3875
3876 /*
3877 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3878 * or a refresh has already been triggered.
3879 */
3880 if (!subgrp || paf->t_announce_route)
3881 return;
3882
3883 /*
3884 * Start a timer to stagger/delay the announce. This serves
3885 * two purposes - announcement can potentially be combined for
3886 * multiple peers and the announcement doesn't happen in the
3887 * vty context.
3888 */
3889 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
3890 (subgrp->peer_count == 1)
3891 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3892 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
3893 &paf->t_announce_route);
3f9c7369
DS
3894}
3895
3896/*
3897 * Announce routes from all AF tables to a peer.
3898 *
3899 * This should ONLY be called when there is a need to refresh the
3900 * routes to the peer based on a policy change for this peer alone
3901 * or a route refresh request received from the peer.
3902 * The operation will result in splitting the peer from its existing
3903 * subgroups and putting it in new subgroups.
3904 */
d62a17ae 3905void bgp_announce_route_all(struct peer *peer)
718e3744 3906{
d62a17ae 3907 afi_t afi;
3908 safi_t safi;
3909
05c7a1cc
QY
3910 FOREACH_AFI_SAFI (afi, safi)
3911 bgp_announce_route(peer, afi, safi);
718e3744 3912}
6b0655a2 3913
d62a17ae 3914static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
3915 struct bgp_table *table,
3916 struct prefix_rd *prd)
718e3744 3917{
d62a17ae 3918 int ret;
3919 struct bgp_node *rn;
3920 struct bgp_adj_in *ain;
718e3744 3921
d62a17ae 3922 if (!table)
3923 table = peer->bgp->rib[afi][safi];
718e3744 3924
d62a17ae 3925 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
3926 for (ain = rn->adj_in; ain; ain = ain->next) {
ea47320b
DL
3927 if (ain->peer != peer)
3928 continue;
8692c506 3929
d7d15889 3930 struct bgp_path_info *pi;
d7c0a89a 3931 uint32_t num_labels = 0;
b57ba6d2 3932 mpls_label_t *label_pnt = NULL;
8cb687c2 3933 struct bgp_route_evpn evpn;
b57ba6d2 3934
d7d15889
DS
3935 for (pi = bgp_node_get_bgp_path_info(rn); pi;
3936 pi = pi->next)
3937 if (pi->peer == peer)
3938 break;
3939
40381db7
DS
3940 if (pi && pi->extra)
3941 num_labels = pi->extra->num_labels;
b57ba6d2 3942 if (num_labels)
40381db7 3943 label_pnt = &pi->extra->label[0];
8cb687c2
DS
3944 if (pi)
3945 memcpy(&evpn, &pi->attr->evpn_overlay,
3946 sizeof(evpn));
3947 else
3948 memset(&evpn, 0, sizeof(evpn));
8692c506 3949
ea47320b
DL
3950 ret = bgp_update(peer, &rn->p, ain->addpath_rx_id,
3951 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
a4d82a8a 3952 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 3953 num_labels, 1, &evpn);
ea47320b
DL
3954
3955 if (ret < 0) {
3956 bgp_unlock_node(rn);
3957 return;
d62a17ae 3958 }
3959 }
718e3744 3960}
3961
d62a17ae 3962void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 3963{
d62a17ae 3964 struct bgp_node *rn;
3965 struct bgp_table *table;
718e3744 3966
d62a17ae 3967 if (peer->status != Established)
3968 return;
718e3744 3969
d62a17ae 3970 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
3971 && (safi != SAFI_EVPN))
3972 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
3973 else
3974 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
67009e22
DS
3975 rn = bgp_route_next(rn)) {
3976 table = bgp_node_get_bgp_table_info(rn);
3977 if (table != NULL) {
d62a17ae 3978 struct prefix_rd prd;
67009e22 3979
d62a17ae 3980 prd.family = AF_UNSPEC;
3981 prd.prefixlen = 64;
3982 memcpy(&prd.val, rn->p.u.val, 8);
8692c506 3983
d62a17ae 3984 bgp_soft_reconfig_table(peer, afi, safi, table,
3985 &prd);
3986 }
67009e22 3987 }
718e3744 3988}
6b0655a2 3989
228da428 3990
d62a17ae 3991struct bgp_clear_node_queue {
3992 struct bgp_node *rn;
228da428
CC
3993};
3994
d62a17ae 3995static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 3996{
d62a17ae 3997 struct bgp_clear_node_queue *cnq = data;
3998 struct bgp_node *rn = cnq->rn;
3999 struct peer *peer = wq->spec.data;
40381db7 4000 struct bgp_path_info *pi;
3103e8d2 4001 struct bgp *bgp;
d62a17ae 4002 afi_t afi = bgp_node_table(rn)->afi;
4003 safi_t safi = bgp_node_table(rn)->safi;
4004
4005 assert(rn && peer);
3103e8d2 4006 bgp = peer->bgp;
d62a17ae 4007
4008 /* It is possible that we have multiple paths for a prefix from a peer
4009 * if that peer is using AddPath.
4010 */
6f94b685 4011 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 4012 if (pi->peer != peer)
ea47320b
DL
4013 continue;
4014
4015 /* graceful restart STALE flag set. */
4016 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4017 && peer->nsf[afi][safi]
40381db7
DS
4018 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4019 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
4020 bgp_path_info_set_flag(rn, pi, BGP_PATH_STALE);
ea47320b
DL
4021 else {
4022 /* If this is an EVPN route, process for
4023 * un-import. */
4024 if (safi == SAFI_EVPN)
40381db7
DS
4025 bgp_evpn_unimport_route(bgp, afi, safi, &rn->p,
4026 pi);
3103e8d2
DS
4027 /* Handle withdraw for VRF route-leaking and L3VPN */
4028 if (SAFI_UNICAST == safi
4029 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4030 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4031 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4032 bgp, pi);
960035b2 4033 }
3103e8d2 4034 if (SAFI_MPLS_VPN == safi &&
960035b2 4035 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4036 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4037 }
3103e8d2 4038
40381db7 4039 bgp_rib_remove(rn, pi, peer, afi, safi);
d62a17ae 4040 }
ea47320b 4041 }
d62a17ae 4042 return WQ_SUCCESS;
200df115 4043}
4044
d62a17ae 4045static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4046{
d62a17ae 4047 struct bgp_clear_node_queue *cnq = data;
4048 struct bgp_node *rn = cnq->rn;
4049 struct bgp_table *table = bgp_node_table(rn);
228da428 4050
d62a17ae 4051 bgp_unlock_node(rn);
4052 bgp_table_unlock(table);
4053 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4054}
4055
d62a17ae 4056static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4057{
d62a17ae 4058 struct peer *peer = wq->spec.data;
64e580a7 4059
d62a17ae 4060 /* Tickle FSM to start moving again */
4061 BGP_EVENT_ADD(peer, Clearing_Completed);
4062
4063 peer_unlock(peer); /* bgp_clear_route */
200df115 4064}
718e3744 4065
d62a17ae 4066static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4067{
d62a17ae 4068 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4069
4070 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4071#undef CLEAR_QUEUE_NAME_LEN
4072
0ce1ca80 4073 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4074 peer->clear_node_queue->spec.hold = 10;
4075 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4076 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4077 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4078 peer->clear_node_queue->spec.max_retries = 0;
4079
4080 /* we only 'lock' this peer reference when the queue is actually active
4081 */
4082 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4083}
4084
d62a17ae 4085static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4086 struct bgp_table *table)
65ca75e0 4087{
d62a17ae 4088 struct bgp_node *rn;
4089 int force = bm->process_main_queue ? 0 : 1;
6cf159b9 4090
d62a17ae 4091 if (!table)
4092 table = peer->bgp->rib[afi][safi];
dc83d712 4093
d62a17ae 4094 /* If still no table => afi/safi isn't configured at all or smth. */
4095 if (!table)
4096 return;
dc83d712 4097
d62a17ae 4098 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
40381db7 4099 struct bgp_path_info *pi, *next;
d62a17ae 4100 struct bgp_adj_in *ain;
4101 struct bgp_adj_in *ain_next;
4102
4103 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4104 * queued for every clearing peer, regardless of whether it is
4105 * relevant to the peer at hand.
4106 *
4107 * Overview: There are 3 different indices which need to be
4108 * scrubbed, potentially, when a peer is removed:
4109 *
4110 * 1 peer's routes visible via the RIB (ie accepted routes)
4111 * 2 peer's routes visible by the (optional) peer's adj-in index
4112 * 3 other routes visible by the peer's adj-out index
4113 *
4114 * 3 there is no hurry in scrubbing, once the struct peer is
4115 * removed from bgp->peer, we could just GC such deleted peer's
4116 * adj-outs at our leisure.
4117 *
4118 * 1 and 2 must be 'scrubbed' in some way, at least made
4119 * invisible via RIB index before peer session is allowed to be
4120 * brought back up. So one needs to know when such a 'search' is
4121 * complete.
4122 *
4123 * Ideally:
4124 *
4125 * - there'd be a single global queue or a single RIB walker
4126 * - rather than tracking which route_nodes still need to be
4127 * examined on a peer basis, we'd track which peers still
4128 * aren't cleared
4129 *
4130 * Given that our per-peer prefix-counts now should be reliable,
4131 * this may actually be achievable. It doesn't seem to be a huge
4132 * problem at this time,
4133 *
4134 * It is possible that we have multiple paths for a prefix from
4135 * a peer
4136 * if that peer is using AddPath.
4137 */
4138 ain = rn->adj_in;
4139 while (ain) {
4140 ain_next = ain->next;
4141
4142 if (ain->peer == peer) {
4143 bgp_adj_in_remove(rn, ain);
4144 bgp_unlock_node(rn);
4145 }
4146
4147 ain = ain_next;
4148 }
4149
6f94b685 4150 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
40381db7
DS
4151 next = pi->next;
4152 if (pi->peer != peer)
d62a17ae 4153 continue;
4154
4155 if (force)
40381db7 4156 bgp_path_info_reap(rn, pi);
d62a17ae 4157 else {
4158 struct bgp_clear_node_queue *cnq;
4159
4160 /* both unlocked in bgp_clear_node_queue_del */
4161 bgp_table_lock(bgp_node_table(rn));
4162 bgp_lock_node(rn);
4163 cnq = XCALLOC(
4164 MTYPE_BGP_CLEAR_NODE_QUEUE,
4165 sizeof(struct bgp_clear_node_queue));
4166 cnq->rn = rn;
4167 work_queue_add(peer->clear_node_queue, cnq);
4168 break;
4169 }
4170 }
4171 }
4172 return;
4173}
4174
4175void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4176{
4177 struct bgp_node *rn;
4178 struct bgp_table *table;
4179
4180 if (peer->clear_node_queue == NULL)
4181 bgp_clear_node_queue_init(peer);
4182
4183 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4184 * Idle until it receives a Clearing_Completed event. This protects
4185 * against peers which flap faster than we can we clear, which could
4186 * lead to:
4187 *
4188 * a) race with routes from the new session being installed before
4189 * clear_route_node visits the node (to delete the route of that
4190 * peer)
4191 * b) resource exhaustion, clear_route_node likely leads to an entry
4192 * on the process_main queue. Fast-flapping could cause that queue
4193 * to grow and grow.
4194 */
4195
4196 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4197 * the unlock will happen upon work-queue completion; other wise, the
4198 * unlock happens at the end of this function.
4199 */
4200 if (!peer->clear_node_queue->thread)
4201 peer_lock(peer);
4202
4203 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4204 bgp_clear_route_table(peer, afi, safi, NULL);
4205 else
4206 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
67009e22
DS
4207 rn = bgp_route_next(rn)) {
4208 table = bgp_node_get_bgp_table_info(rn);
4209 if (!table)
4210 continue;
4211
4212 bgp_clear_route_table(peer, afi, safi, table);
4213 }
d62a17ae 4214
4215 /* unlock if no nodes got added to the clear-node-queue. */
4216 if (!peer->clear_node_queue->thread)
4217 peer_unlock(peer);
718e3744 4218}
d62a17ae 4219
4220void bgp_clear_route_all(struct peer *peer)
718e3744 4221{
d62a17ae 4222 afi_t afi;
4223 safi_t safi;
718e3744 4224
05c7a1cc
QY
4225 FOREACH_AFI_SAFI (afi, safi)
4226 bgp_clear_route(peer, afi, safi);
65efcfce
LB
4227
4228#if ENABLE_BGP_VNC
d62a17ae 4229 rfapiProcessPeerDown(peer);
65efcfce 4230#endif
718e3744 4231}
4232
d62a17ae 4233void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4234{
d62a17ae 4235 struct bgp_table *table;
4236 struct bgp_node *rn;
4237 struct bgp_adj_in *ain;
4238 struct bgp_adj_in *ain_next;
718e3744 4239
d62a17ae 4240 table = peer->bgp->rib[afi][safi];
718e3744 4241
d62a17ae 4242 /* It is possible that we have multiple paths for a prefix from a peer
4243 * if that peer is using AddPath.
4244 */
4245 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
4246 ain = rn->adj_in;
43143c8f 4247
d62a17ae 4248 while (ain) {
4249 ain_next = ain->next;
43143c8f 4250
d62a17ae 4251 if (ain->peer == peer) {
4252 bgp_adj_in_remove(rn, ain);
4253 bgp_unlock_node(rn);
4254 }
43143c8f 4255
d62a17ae 4256 ain = ain_next;
4257 }
4258 }
718e3744 4259}
93406d87 4260
d62a17ae 4261void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4262{
4263 struct bgp_node *rn;
40381db7 4264 struct bgp_path_info *pi;
d62a17ae 4265 struct bgp_table *table;
4266
4267 if (safi == SAFI_MPLS_VPN) {
4268 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4269 rn = bgp_route_next(rn)) {
4270 struct bgp_node *rm;
d62a17ae 4271
4272 /* look for neighbor in tables */
67009e22
DS
4273 table = bgp_node_get_bgp_table_info(rn);
4274 if (!table)
ea47320b
DL
4275 continue;
4276
4277 for (rm = bgp_table_top(table); rm;
4278 rm = bgp_route_next(rm))
6f94b685
DS
4279 for (pi = bgp_node_get_bgp_path_info(rm); pi;
4280 pi = pi->next) {
40381db7 4281 if (pi->peer != peer)
ea47320b 4282 continue;
40381db7 4283 if (!CHECK_FLAG(pi->flags,
1defdda8 4284 BGP_PATH_STALE))
ea47320b
DL
4285 break;
4286
40381db7 4287 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4288 break;
4289 }
d62a17ae 4290 }
4291 } else {
4292 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4293 rn = bgp_route_next(rn))
6f94b685
DS
4294 for (pi = bgp_node_get_bgp_path_info(rn); pi;
4295 pi = pi->next) {
40381db7 4296 if (pi->peer != peer)
ea47320b 4297 continue;
40381db7 4298 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4299 break;
40381db7 4300 bgp_rib_remove(rn, pi, peer, afi, safi);
ea47320b
DL
4301 break;
4302 }
d62a17ae 4303 }
93406d87 4304}
6b0655a2 4305
9dac9fc8
DA
4306int bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
4307{
4308 if (peer->sort == BGP_PEER_EBGP
4309 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
4310 || FILTER_LIST_OUT_NAME(filter)
4311 || DISTRIBUTE_OUT_NAME(filter)))
4312 return 1;
4313 return 0;
4314}
4315
4316int bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
4317{
4318 if (peer->sort == BGP_PEER_EBGP
4319 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
4320 || FILTER_LIST_IN_NAME(filter)
4321 || DISTRIBUTE_IN_NAME(filter)))
4322 return 1;
4323 return 0;
4324}
4325
568e10ca 4326static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
4327 safi_t safi)
bb86c601 4328{
d62a17ae 4329 struct bgp_node *rn;
40381db7 4330 struct bgp_path_info *pi;
4b7e6066 4331 struct bgp_path_info *next;
bb86c601 4332
d62a17ae 4333 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
6f94b685 4334 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
40381db7 4335 next = pi->next;
1b7bb747
CS
4336
4337 /* Unimport EVPN routes from VRFs */
4338 if (safi == SAFI_EVPN)
4339 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
4340 SAFI_EVPN,
4341 &rn->p, pi);
4342
40381db7
DS
4343 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
4344 && pi->type == ZEBRA_ROUTE_BGP
4345 && (pi->sub_type == BGP_ROUTE_NORMAL
4346 || pi->sub_type == BGP_ROUTE_AGGREGATE
4347 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 4348
d62a17ae 4349 if (bgp_fibupd_safi(safi))
40381db7
DS
4350 bgp_zebra_withdraw(&rn->p, pi, bgp,
4351 safi);
4352 bgp_path_info_reap(rn, pi);
d62a17ae 4353 }
4354 }
bb86c601
LB
4355}
4356
718e3744 4357/* Delete all kernel routes. */
d62a17ae 4358void bgp_cleanup_routes(struct bgp *bgp)
4359{
4360 afi_t afi;
4361 struct bgp_node *rn;
67009e22 4362 struct bgp_table *table;
d62a17ae 4363
4364 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
4365 if (afi == AFI_L2VPN)
4366 continue;
568e10ca 4367 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
4368 SAFI_UNICAST);
d62a17ae 4369 /*
4370 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4371 */
4372 if (afi != AFI_L2VPN) {
4373 safi_t safi;
4374 safi = SAFI_MPLS_VPN;
4375 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4376 rn = bgp_route_next(rn)) {
67009e22
DS
4377 table = bgp_node_get_bgp_table_info(rn);
4378 if (table != NULL) {
4379 bgp_cleanup_table(bgp, table, safi);
4380 bgp_table_finish(&table);
4381 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4382 bgp_unlock_node(rn);
4383 }
4384 }
4385 safi = SAFI_ENCAP;
4386 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4387 rn = bgp_route_next(rn)) {
67009e22
DS
4388 table = bgp_node_get_bgp_table_info(rn);
4389 if (table != NULL) {
4390 bgp_cleanup_table(bgp, table, safi);
4391 bgp_table_finish(&table);
4392 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4393 bgp_unlock_node(rn);
4394 }
4395 }
4396 }
4397 }
4398 for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn;
4399 rn = bgp_route_next(rn)) {
67009e22
DS
4400 table = bgp_node_get_bgp_table_info(rn);
4401 if (table != NULL) {
4402 bgp_cleanup_table(bgp, table, SAFI_EVPN);
4403 bgp_table_finish(&table);
4404 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4405 bgp_unlock_node(rn);
4406 }
bb86c601 4407 }
718e3744 4408}
4409
d62a17ae 4410void bgp_reset(void)
718e3744 4411{
d62a17ae 4412 vty_reset();
4413 bgp_zclient_reset();
4414 access_list_reset();
4415 prefix_list_reset();
718e3744 4416}
6b0655a2 4417
d62a17ae 4418static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 4419{
d62a17ae 4420 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
4421 && CHECK_FLAG(peer->af_cap[afi][safi],
4422 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
4423}
4424
718e3744 4425/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4426 value. */
d62a17ae 4427int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
4428 struct bgp_nlri *packet)
4429{
d7c0a89a
QY
4430 uint8_t *pnt;
4431 uint8_t *lim;
d62a17ae 4432 struct prefix p;
4433 int psize;
4434 int ret;
4435 afi_t afi;
4436 safi_t safi;
4437 int addpath_encoded;
d7c0a89a 4438 uint32_t addpath_id;
d62a17ae 4439
d62a17ae 4440 pnt = packet->nlri;
4441 lim = pnt + packet->length;
4442 afi = packet->afi;
4443 safi = packet->safi;
4444 addpath_id = 0;
4445 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
4446
4447 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4448 syntactic validity. If the field is syntactically incorrect,
4449 then the Error Subcode is set to Invalid Network Field. */
4450 for (; pnt < lim; pnt += psize) {
4451 /* Clear prefix structure. */
4452 memset(&p, 0, sizeof(struct prefix));
4453
4454 if (addpath_encoded) {
4455
4456 /* When packet overflow occurs return immediately. */
4457 if (pnt + BGP_ADDPATH_ID_LEN > lim)
513386b5 4458 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4459
4460 addpath_id = ntohl(*((uint32_t *)pnt));
4461 pnt += BGP_ADDPATH_ID_LEN;
4462 }
718e3744 4463
d62a17ae 4464 /* Fetch prefix length. */
4465 p.prefixlen = *pnt++;
4466 /* afi/safi validity already verified by caller,
4467 * bgp_update_receive */
4468 p.family = afi2family(afi);
4469
4470 /* Prefix length check. */
4471 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 4472 flog_err(
e50f7cfd 4473 EC_BGP_UPDATE_RCV,
14454c9f 4474 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 4475 peer->host, p.prefixlen, packet->afi);
513386b5 4476 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 4477 }
6b0655a2 4478
d62a17ae 4479 /* Packet size overflow check. */
4480 psize = PSIZE(p.prefixlen);
4481
4482 /* When packet overflow occur return immediately. */
4483 if (pnt + psize > lim) {
af4c2728 4484 flog_err(
e50f7cfd 4485 EC_BGP_UPDATE_RCV,
d62a17ae 4486 "%s [Error] Update packet error (prefix length %d overflows packet)",
4487 peer->host, p.prefixlen);
513386b5 4488 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4489 }
4490
4491 /* Defensive coding, double-check the psize fits in a struct
4492 * prefix */
4493 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 4494 flog_err(
e50f7cfd 4495 EC_BGP_UPDATE_RCV,
d62a17ae 4496 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4497 peer->host, p.prefixlen, sizeof(p.u));
513386b5 4498 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4499 }
4500
4501 /* Fetch prefix from NLRI packet. */
a85297a7 4502 memcpy(p.u.val, pnt, psize);
d62a17ae 4503
4504 /* Check address. */
4505 if (afi == AFI_IP && safi == SAFI_UNICAST) {
4506 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
4507 /* From RFC4271 Section 6.3:
4508 *
4509 * If a prefix in the NLRI field is semantically
4510 * incorrect
4511 * (e.g., an unexpected multicast IP address),
4512 * an error SHOULD
4513 * be logged locally, and the prefix SHOULD be
4514 * ignored.
a4d82a8a 4515 */
af4c2728 4516 flog_err(
e50f7cfd 4517 EC_BGP_UPDATE_RCV,
d62a17ae 4518 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4519 peer->host, inet_ntoa(p.u.prefix4));
4520 continue;
4521 }
4522 }
4523
4524 /* Check address. */
4525 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
4526 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4527 char buf[BUFSIZ];
4528
af4c2728 4529 flog_err(
e50f7cfd 4530 EC_BGP_UPDATE_RCV,
d62a17ae 4531 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4532 peer->host,
4533 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4534 BUFSIZ));
4535
4536 continue;
4537 }
4538 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
4539 char buf[BUFSIZ];
4540
af4c2728 4541 flog_err(
e50f7cfd 4542 EC_BGP_UPDATE_RCV,
d62a17ae 4543 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4544 peer->host,
4545 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4546 BUFSIZ));
4547
4548 continue;
4549 }
4550 }
4551
4552 /* Normal process. */
4553 if (attr)
4554 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
4555 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 4556 NULL, NULL, 0, 0, NULL);
d62a17ae 4557 else
4558 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
4559 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
4560 BGP_ROUTE_NORMAL, NULL, NULL, 0,
4561 NULL);
d62a17ae 4562
513386b5
DA
4563 /* Do not send BGP notification twice when maximum-prefix count
4564 * overflow. */
4565 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4566 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
4567
4568 /* Address family configuration mismatch. */
d62a17ae 4569 if (ret < 0)
513386b5 4570 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 4571 }
4572
4573 /* Packet length consistency check. */
4574 if (pnt != lim) {
af4c2728 4575 flog_err(
e50f7cfd 4576 EC_BGP_UPDATE_RCV,
d62a17ae 4577 "%s [Error] Update packet error (prefix length mismatch with total length)",
4578 peer->host);
513386b5 4579 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4580 }
6b0655a2 4581
513386b5 4582 return BGP_NLRI_PARSE_OK;
718e3744 4583}
4584
d62a17ae 4585static struct bgp_static *bgp_static_new(void)
718e3744 4586{
d62a17ae 4587 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 4588}
4589
d62a17ae 4590static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 4591{
0a22ddfb 4592 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 4593 route_map_counter_decrement(bgp_static->rmap.map);
4594
0a22ddfb 4595 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 4596 XFREE(MTYPE_BGP_STATIC, bgp_static);
4597}
4598
4599void bgp_static_update(struct bgp *bgp, struct prefix *p,
4600 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
4601{
4602 struct bgp_node *rn;
40381db7 4603 struct bgp_path_info *pi;
4b7e6066 4604 struct bgp_path_info *new;
40381db7 4605 struct bgp_path_info rmap_path;
d62a17ae 4606 struct attr attr;
4607 struct attr *attr_new;
b68885f9 4608 route_map_result_t ret;
65efcfce 4609#if ENABLE_BGP_VNC
d62a17ae 4610 int vnc_implicit_withdraw = 0;
65efcfce 4611#endif
fee0f4c6 4612
d62a17ae 4613 assert(bgp_static);
4614 if (!bgp_static)
4615 return;
dd8103a9 4616
d62a17ae 4617 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4618
d62a17ae 4619 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 4620
d62a17ae 4621 attr.nexthop = bgp_static->igpnexthop;
4622 attr.med = bgp_static->igpmetric;
4623 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 4624
d62a17ae 4625 if (bgp_static->atomic)
4626 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 4627
d62a17ae 4628 /* Store label index, if required. */
4629 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
4630 attr.label_index = bgp_static->label_index;
4631 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
4632 }
718e3744 4633
d62a17ae 4634 /* Apply route-map. */
4635 if (bgp_static->rmap.name) {
4636 struct attr attr_tmp = attr;
80ced710 4637
40381db7
DS
4638 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
4639 rmap_path.peer = bgp->peer_self;
4640 rmap_path.attr = &attr_tmp;
fee0f4c6 4641
d62a17ae 4642 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 4643
40381db7
DS
4644 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
4645 &rmap_path);
fee0f4c6 4646
d62a17ae 4647 bgp->peer_self->rmap_type = 0;
718e3744 4648
d62a17ae 4649 if (ret == RMAP_DENYMATCH) {
4650 /* Free uninterned attribute. */
4651 bgp_attr_flush(&attr_tmp);
718e3744 4652
d62a17ae 4653 /* Unintern original. */
4654 aspath_unintern(&attr.aspath);
4655 bgp_static_withdraw(bgp, p, afi, safi);
4656 return;
4657 }
7f323236
DW
4658
4659 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
4660 bgp_attr_add_gshut_community(&attr_tmp);
4661
d62a17ae 4662 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
4663 } else {
4664
4665 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
4666 bgp_attr_add_gshut_community(&attr);
4667
d62a17ae 4668 attr_new = bgp_attr_intern(&attr);
7f323236 4669 }
718e3744 4670
6f94b685 4671 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4672 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4673 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4674 break;
4675
40381db7
DS
4676 if (pi) {
4677 if (attrhash_cmp(pi->attr, attr_new)
4678 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
d62a17ae 4679 && !bgp_flag_check(bgp, BGP_FLAG_FORCE_STATIC_PROCESS)) {
4680 bgp_unlock_node(rn);
4681 bgp_attr_unintern(&attr_new);
4682 aspath_unintern(&attr.aspath);
4683 return;
4684 } else {
4685 /* The attribute is changed. */
40381db7 4686 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4687
4688 /* Rewrite BGP route information. */
40381db7
DS
4689 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
4690 bgp_path_info_restore(rn, pi);
d62a17ae 4691 else
40381db7 4692 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
65efcfce 4693#if ENABLE_BGP_VNC
d62a17ae 4694 if ((afi == AFI_IP || afi == AFI_IP6)
4695 && (safi == SAFI_UNICAST)) {
40381db7 4696 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4697 /*
4698 * Implicit withdraw case.
40381db7 4699 * We have to do this before pi is
d62a17ae 4700 * changed
4701 */
4702 ++vnc_implicit_withdraw;
40381db7 4703 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 4704 vnc_import_bgp_exterior_del_route(
40381db7 4705 bgp, p, pi);
d62a17ae 4706 }
4707 }
65efcfce 4708#endif
40381db7
DS
4709 bgp_attr_unintern(&pi->attr);
4710 pi->attr = attr_new;
4711 pi->uptime = bgp_clock();
65efcfce 4712#if ENABLE_BGP_VNC
d62a17ae 4713 if ((afi == AFI_IP || afi == AFI_IP6)
4714 && (safi == SAFI_UNICAST)) {
4715 if (vnc_implicit_withdraw) {
40381db7 4716 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 4717 vnc_import_bgp_exterior_add_route(
40381db7 4718 bgp, p, pi);
d62a17ae 4719 }
4720 }
65efcfce 4721#endif
718e3744 4722
d62a17ae 4723 /* Nexthop reachability check. */
4724 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
4725 && (safi == SAFI_UNICAST
4726 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
4727
4728 struct bgp *bgp_nexthop = bgp;
4729
40381db7
DS
4730 if (pi->extra && pi->extra->bgp_orig)
4731 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
4732
4733 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
40381db7
DS
4734 afi, pi, NULL, 0))
4735 bgp_path_info_set_flag(rn, pi,
18ee8310 4736 BGP_PATH_VALID);
d62a17ae 4737 else {
4738 if (BGP_DEBUG(nht, NHT)) {
4739 char buf1[INET6_ADDRSTRLEN];
4740 inet_ntop(p->family,
4741 &p->u.prefix, buf1,
4742 INET6_ADDRSTRLEN);
4743 zlog_debug(
4744 "%s(%s): Route not in table, not advertising",
4745 __FUNCTION__, buf1);
4746 }
18ee8310 4747 bgp_path_info_unset_flag(
40381db7 4748 rn, pi, BGP_PATH_VALID);
d62a17ae 4749 }
4750 } else {
4751 /* Delete the NHT structure if any, if we're
4752 * toggling between
4753 * enabling/disabling import check. We
4754 * deregister the route
4755 * from NHT to avoid overloading NHT and the
4756 * process interaction
4757 */
40381db7
DS
4758 bgp_unlink_nexthop(pi);
4759 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 4760 }
4761 /* Process change. */
40381db7 4762 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4763 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
4764
4765 if (SAFI_UNICAST == safi
4766 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4767 || bgp->inst_type
4768 == BGP_INSTANCE_TYPE_DEFAULT)) {
4769 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 4770 pi);
ddb5b488
PZ
4771 }
4772
d62a17ae 4773 bgp_unlock_node(rn);
4774 aspath_unintern(&attr.aspath);
4775 return;
4776 }
718e3744 4777 }
718e3744 4778
d62a17ae 4779 /* Make new BGP info. */
4780 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
4781 attr_new, rn);
4782 /* Nexthop reachability check. */
4783 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
4784 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 4785 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
18ee8310 4786 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
d62a17ae 4787 else {
4788 if (BGP_DEBUG(nht, NHT)) {
4789 char buf1[INET6_ADDRSTRLEN];
4790 inet_ntop(p->family, &p->u.prefix, buf1,
4791 INET6_ADDRSTRLEN);
4792 zlog_debug(
4793 "%s(%s): Route not in table, not advertising",
4794 __FUNCTION__, buf1);
4795 }
18ee8310 4796 bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID);
d62a17ae 4797 }
4798 } else {
4799 /* Delete the NHT structure if any, if we're toggling between
4800 * enabling/disabling import check. We deregister the route
4801 * from NHT to avoid overloading NHT and the process interaction
4802 */
4803 bgp_unlink_nexthop(new);
4804
18ee8310 4805 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
fc9a856f 4806 }
078430f6 4807
d62a17ae 4808 /* Aggregate address increment. */
4809 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 4810
d62a17ae 4811 /* Register new BGP information. */
18ee8310 4812 bgp_path_info_add(rn, new);
718e3744 4813
d62a17ae 4814 /* route_node_get lock */
4815 bgp_unlock_node(rn);
4816
4817 /* Process change. */
4818 bgp_process(bgp, rn, afi, safi);
4819
ddb5b488
PZ
4820 if (SAFI_UNICAST == safi
4821 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4822 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4823 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4824 }
4825
d62a17ae 4826 /* Unintern original. */
4827 aspath_unintern(&attr.aspath);
718e3744 4828}
4829
d62a17ae 4830void bgp_static_withdraw(struct bgp *bgp, struct prefix *p, afi_t afi,
4831 safi_t safi)
718e3744 4832{
d62a17ae 4833 struct bgp_node *rn;
40381db7 4834 struct bgp_path_info *pi;
718e3744 4835
d62a17ae 4836 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4837
d62a17ae 4838 /* Check selected route and self inserted route. */
6f94b685 4839 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4840 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4841 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4842 break;
4843
4844 /* Withdraw static BGP route from routing table. */
40381db7 4845 if (pi) {
ddb5b488
PZ
4846 if (SAFI_UNICAST == safi
4847 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4848 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4849 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 4850 }
40381db7
DS
4851 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
4852 bgp_unlink_nexthop(pi);
4853 bgp_path_info_delete(rn, pi);
d62a17ae 4854 bgp_process(bgp, rn, afi, safi);
4855 }
718e3744 4856
d62a17ae 4857 /* Unlock bgp_node_lookup. */
4858 bgp_unlock_node(rn);
718e3744 4859}
4860
137446f9
LB
4861/*
4862 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4863 */
d62a17ae 4864static void bgp_static_withdraw_safi(struct bgp *bgp, struct prefix *p,
4865 afi_t afi, safi_t safi,
4866 struct prefix_rd *prd)
718e3744 4867{
d62a17ae 4868 struct bgp_node *rn;
40381db7 4869 struct bgp_path_info *pi;
718e3744 4870
d62a17ae 4871 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 4872
d62a17ae 4873 /* Check selected route and self inserted route. */
6f94b685 4874 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4875 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4876 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4877 break;
718e3744 4878
d62a17ae 4879 /* Withdraw static BGP route from routing table. */
40381db7 4880 if (pi) {
65efcfce 4881#if ENABLE_BGP_VNC
d62a17ae 4882 rfapiProcessWithdraw(
40381db7 4883 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 4884 1); /* Kill, since it is an administrative change */
65efcfce 4885#endif
ddb5b488
PZ
4886 if (SAFI_MPLS_VPN == safi
4887 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4888 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 4889 }
40381db7
DS
4890 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
4891 bgp_path_info_delete(rn, pi);
d62a17ae 4892 bgp_process(bgp, rn, afi, safi);
4893 }
718e3744 4894
d62a17ae 4895 /* Unlock bgp_node_lookup. */
4896 bgp_unlock_node(rn);
718e3744 4897}
4898
d62a17ae 4899static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p,
4900 struct bgp_static *bgp_static, afi_t afi,
4901 safi_t safi)
137446f9 4902{
d62a17ae 4903 struct bgp_node *rn;
4b7e6066 4904 struct bgp_path_info *new;
d62a17ae 4905 struct attr *attr_new;
4906 struct attr attr = {0};
40381db7 4907 struct bgp_path_info *pi;
65efcfce 4908#if ENABLE_BGP_VNC
d62a17ae 4909 mpls_label_t label = 0;
65efcfce 4910#endif
d7c0a89a 4911 uint32_t num_labels = 0;
d62a17ae 4912 union gw_addr add;
137446f9 4913
d62a17ae 4914 assert(bgp_static);
137446f9 4915
b57ba6d2
MK
4916 if (bgp_static->label != MPLS_INVALID_LABEL)
4917 num_labels = 1;
d62a17ae 4918 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
4919 &bgp_static->prd);
137446f9 4920
d62a17ae 4921 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 4922
d62a17ae 4923 attr.nexthop = bgp_static->igpnexthop;
4924 attr.med = bgp_static->igpmetric;
4925 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 4926
d62a17ae 4927 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
4928 || (safi == SAFI_ENCAP)) {
4929 if (afi == AFI_IP) {
4930 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
4931 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
4932 }
4933 }
4934 if (afi == AFI_L2VPN) {
4935 if (bgp_static->gatewayIp.family == AF_INET)
4936 add.ipv4.s_addr =
4937 bgp_static->gatewayIp.u.prefix4.s_addr;
4938 else if (bgp_static->gatewayIp.family == AF_INET6)
4939 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
4940 sizeof(struct in6_addr));
4941 overlay_index_update(&attr, bgp_static->eth_s_id, &add);
4942 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
4943 struct bgp_encap_type_vxlan bet;
4944 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 4945 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 4946 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
4947 }
4948 if (bgp_static->router_mac) {
4949 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
4950 }
4951 }
4952 /* Apply route-map. */
4953 if (bgp_static->rmap.name) {
4954 struct attr attr_tmp = attr;
40381db7 4955 struct bgp_path_info rmap_path;
b68885f9 4956 route_map_result_t ret;
137446f9 4957
40381db7
DS
4958 rmap_path.peer = bgp->peer_self;
4959 rmap_path.attr = &attr_tmp;
137446f9 4960
d62a17ae 4961 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 4962
40381db7
DS
4963 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
4964 &rmap_path);
137446f9 4965
d62a17ae 4966 bgp->peer_self->rmap_type = 0;
137446f9 4967
d62a17ae 4968 if (ret == RMAP_DENYMATCH) {
4969 /* Free uninterned attribute. */
4970 bgp_attr_flush(&attr_tmp);
137446f9 4971
d62a17ae 4972 /* Unintern original. */
4973 aspath_unintern(&attr.aspath);
4974 bgp_static_withdraw_safi(bgp, p, afi, safi,
4975 &bgp_static->prd);
4976 return;
4977 }
137446f9 4978
d62a17ae 4979 attr_new = bgp_attr_intern(&attr_tmp);
4980 } else {
4981 attr_new = bgp_attr_intern(&attr);
4982 }
137446f9 4983
6f94b685 4984 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4985 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4986 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4987 break;
4988
40381db7 4989 if (pi) {
d62a17ae 4990 memset(&add, 0, sizeof(union gw_addr));
40381db7
DS
4991 if (attrhash_cmp(pi->attr, attr_new)
4992 && overlay_index_equal(afi, pi, bgp_static->eth_s_id, &add)
4993 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4994 bgp_unlock_node(rn);
4995 bgp_attr_unintern(&attr_new);
4996 aspath_unintern(&attr.aspath);
4997 return;
4998 } else {
4999 /* The attribute is changed. */
40381db7 5000 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5001
5002 /* Rewrite BGP route information. */
40381db7
DS
5003 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
5004 bgp_path_info_restore(rn, pi);
d62a17ae 5005 else
40381db7
DS
5006 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5007 bgp_attr_unintern(&pi->attr);
5008 pi->attr = attr_new;
5009 pi->uptime = bgp_clock();
65efcfce 5010#if ENABLE_BGP_VNC
40381db7
DS
5011 if (pi->extra)
5012 label = decode_label(&pi->extra->label[0]);
65efcfce 5013#endif
137446f9 5014
d62a17ae 5015 /* Process change. */
40381db7 5016 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 5017 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
5018
5019 if (SAFI_MPLS_VPN == safi
5020 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5021 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5022 }
65efcfce 5023#if ENABLE_BGP_VNC
40381db7
DS
5024 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5025 pi->attr, afi, safi, pi->type,
5026 pi->sub_type, &label);
65efcfce 5027#endif
d62a17ae 5028 bgp_unlock_node(rn);
5029 aspath_unintern(&attr.aspath);
5030 return;
5031 }
5032 }
137446f9
LB
5033
5034
d62a17ae 5035 /* Make new BGP info. */
5036 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
5037 attr_new, rn);
1defdda8 5038 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5039 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5040 if (num_labels) {
5041 new->extra->label[0] = bgp_static->label;
5042 new->extra->num_labels = num_labels;
5043 }
65efcfce 5044#if ENABLE_BGP_VNC
d62a17ae 5045 label = decode_label(&bgp_static->label);
65efcfce 5046#endif
137446f9 5047
d62a17ae 5048 /* Aggregate address increment. */
5049 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5050
d62a17ae 5051 /* Register new BGP information. */
18ee8310 5052 bgp_path_info_add(rn, new);
d62a17ae 5053 /* route_node_get lock */
5054 bgp_unlock_node(rn);
137446f9 5055
d62a17ae 5056 /* Process change. */
5057 bgp_process(bgp, rn, afi, safi);
137446f9 5058
ddb5b488
PZ
5059 if (SAFI_MPLS_VPN == safi
5060 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5061 vpn_leak_to_vrf_update(bgp, new);
5062 }
65efcfce 5063#if ENABLE_BGP_VNC
d62a17ae 5064 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5065 safi, new->type, new->sub_type, &label);
65efcfce
LB
5066#endif
5067
d62a17ae 5068 /* Unintern original. */
5069 aspath_unintern(&attr.aspath);
137446f9
LB
5070}
5071
718e3744 5072/* Configure static BGP network. When user don't run zebra, static
5073 route should be installed as valid. */
e2a86ad9
DS
5074static int bgp_static_set(struct vty *vty, const char *negate,
5075 const char *ip_str, afi_t afi, safi_t safi,
d7c0a89a 5076 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 5077{
5078 VTY_DECLVAR_CONTEXT(bgp, bgp);
5079 int ret;
5080 struct prefix p;
5081 struct bgp_static *bgp_static;
5082 struct bgp_node *rn;
d7c0a89a 5083 uint8_t need_update = 0;
d62a17ae 5084
5085 /* Convert IP prefix string to struct prefix. */
5086 ret = str2prefix(ip_str, &p);
5087 if (!ret) {
5088 vty_out(vty, "%% Malformed prefix\n");
5089 return CMD_WARNING_CONFIG_FAILED;
5090 }
5091 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5092 vty_out(vty, "%% Malformed prefix (link-local address)\n");
5093 return CMD_WARNING_CONFIG_FAILED;
5094 }
718e3744 5095
d62a17ae 5096 apply_mask(&p);
718e3744 5097
e2a86ad9 5098 if (negate) {
718e3744 5099
e2a86ad9
DS
5100 /* Set BGP static route configuration. */
5101 rn = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5102
e2a86ad9 5103 if (!rn) {
a4d82a8a 5104 vty_out(vty, "%% Can't find static route specified\n");
d62a17ae 5105 return CMD_WARNING_CONFIG_FAILED;
5106 }
5107
5a8ba9fc 5108 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 5109
e2a86ad9
DS
5110 if ((label_index != BGP_INVALID_LABEL_INDEX)
5111 && (label_index != bgp_static->label_index)) {
5112 vty_out(vty,
5113 "%% label-index doesn't match static route\n");
5114 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5115 }
d62a17ae 5116
e2a86ad9
DS
5117 if ((rmap && bgp_static->rmap.name)
5118 && strcmp(rmap, bgp_static->rmap.name)) {
5119 vty_out(vty,
5120 "%% route-map name doesn't match static route\n");
5121 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5122 }
718e3744 5123
e2a86ad9
DS
5124 /* Update BGP RIB. */
5125 if (!bgp_static->backdoor)
5126 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5127
e2a86ad9
DS
5128 /* Clear configuration. */
5129 bgp_static_free(bgp_static);
5a8ba9fc 5130 bgp_node_set_bgp_static_info(rn, NULL);
e2a86ad9
DS
5131 bgp_unlock_node(rn);
5132 bgp_unlock_node(rn);
5133 } else {
718e3744 5134
e2a86ad9
DS
5135 /* Set BGP static route configuration. */
5136 rn = bgp_node_get(bgp->route[afi][safi], &p);
718e3744 5137
5a8ba9fc 5138 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 5139 if (bgp_static) {
e2a86ad9 5140 /* Configuration change. */
e2a86ad9
DS
5141 /* Label index cannot be changed. */
5142 if (bgp_static->label_index != label_index) {
5143 vty_out(vty, "%% cannot change label-index\n");
5144 return CMD_WARNING_CONFIG_FAILED;
5145 }
d62a17ae 5146
e2a86ad9 5147 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5148 if (bgp_static->valid
5149 && bgp_static->backdoor != backdoor)
e2a86ad9 5150 need_update = 1;
718e3744 5151
e2a86ad9 5152 bgp_static->backdoor = backdoor;
718e3744 5153
e2a86ad9 5154 if (rmap) {
0a22ddfb
QY
5155 XFREE(MTYPE_ROUTE_MAP_NAME,
5156 bgp_static->rmap.name);
b4897fa5 5157 route_map_counter_decrement(
5158 bgp_static->rmap.map);
e2a86ad9
DS
5159 bgp_static->rmap.name =
5160 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5161 bgp_static->rmap.map =
5162 route_map_lookup_by_name(rmap);
b4897fa5 5163 route_map_counter_increment(
5164 bgp_static->rmap.map);
e2a86ad9 5165 } else {
0a22ddfb
QY
5166 XFREE(MTYPE_ROUTE_MAP_NAME,
5167 bgp_static->rmap.name);
b4897fa5 5168 route_map_counter_decrement(
5169 bgp_static->rmap.map);
e2a86ad9
DS
5170 bgp_static->rmap.name = NULL;
5171 bgp_static->rmap.map = NULL;
5172 bgp_static->valid = 0;
5173 }
5174 bgp_unlock_node(rn);
5175 } else {
5176 /* New configuration. */
5177 bgp_static = bgp_static_new();
5178 bgp_static->backdoor = backdoor;
5179 bgp_static->valid = 0;
5180 bgp_static->igpmetric = 0;
5181 bgp_static->igpnexthop.s_addr = 0;
5182 bgp_static->label_index = label_index;
718e3744 5183
e2a86ad9 5184 if (rmap) {
0a22ddfb
QY
5185 XFREE(MTYPE_ROUTE_MAP_NAME,
5186 bgp_static->rmap.name);
b4897fa5 5187 route_map_counter_decrement(
5188 bgp_static->rmap.map);
e2a86ad9
DS
5189 bgp_static->rmap.name =
5190 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5191 bgp_static->rmap.map =
5192 route_map_lookup_by_name(rmap);
b4897fa5 5193 route_map_counter_increment(
5194 bgp_static->rmap.map);
e2a86ad9 5195 }
5a8ba9fc 5196 bgp_node_set_bgp_static_info(rn, bgp_static);
e2a86ad9 5197 }
d62a17ae 5198
e2a86ad9
DS
5199 bgp_static->valid = 1;
5200 if (need_update)
5201 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5202
e2a86ad9
DS
5203 if (!bgp_static->backdoor)
5204 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5205 }
d62a17ae 5206
5207 return CMD_SUCCESS;
5208}
5209
5210void bgp_static_add(struct bgp *bgp)
5211{
5212 afi_t afi;
5213 safi_t safi;
5214 struct bgp_node *rn;
5215 struct bgp_node *rm;
5216 struct bgp_table *table;
5217 struct bgp_static *bgp_static;
5218
05c7a1cc
QY
5219 FOREACH_AFI_SAFI (afi, safi)
5220 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5221 rn = bgp_route_next(rn)) {
67009e22 5222 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5223 continue;
ea47320b 5224
05c7a1cc
QY
5225 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5226 || (safi == SAFI_EVPN)) {
67009e22 5227 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5228
5229 for (rm = bgp_table_top(table); rm;
5230 rm = bgp_route_next(rm)) {
a78beeb5 5231 bgp_static =
5a8ba9fc
DS
5232 bgp_node_get_bgp_static_info(
5233 rm);
05c7a1cc
QY
5234 bgp_static_update_safi(bgp, &rm->p,
5235 bgp_static, afi,
5236 safi);
d62a17ae 5237 }
05c7a1cc 5238 } else {
5a8ba9fc
DS
5239 bgp_static_update(
5240 bgp, &rn->p,
5241 bgp_node_get_bgp_static_info(rn), afi,
5242 safi);
ea47320b 5243 }
05c7a1cc 5244 }
6aeb9e78
DS
5245}
5246
718e3744 5247/* Called from bgp_delete(). Delete all static routes from the BGP
5248 instance. */
d62a17ae 5249void bgp_static_delete(struct bgp *bgp)
5250{
5251 afi_t afi;
5252 safi_t safi;
5253 struct bgp_node *rn;
5254 struct bgp_node *rm;
5255 struct bgp_table *table;
5256 struct bgp_static *bgp_static;
5257
05c7a1cc
QY
5258 FOREACH_AFI_SAFI (afi, safi)
5259 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5260 rn = bgp_route_next(rn)) {
67009e22 5261 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5262 continue;
ea47320b 5263
05c7a1cc
QY
5264 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5265 || (safi == SAFI_EVPN)) {
67009e22 5266 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5267
5268 for (rm = bgp_table_top(table); rm;
5269 rm = bgp_route_next(rm)) {
a78beeb5 5270 bgp_static =
5a8ba9fc
DS
5271 bgp_node_get_bgp_static_info(
5272 rm);
c7d14ba6
PG
5273 if (!bgp_static)
5274 continue;
5275
05c7a1cc
QY
5276 bgp_static_withdraw_safi(
5277 bgp, &rm->p, AFI_IP, safi,
5278 (struct prefix_rd *)&rn->p);
ea47320b 5279 bgp_static_free(bgp_static);
5a8ba9fc 5280 bgp_node_set_bgp_static_info(rn, NULL);
ea47320b 5281 bgp_unlock_node(rn);
d62a17ae 5282 }
05c7a1cc 5283 } else {
5a8ba9fc 5284 bgp_static = bgp_node_get_bgp_static_info(rn);
05c7a1cc
QY
5285 bgp_static_withdraw(bgp, &rn->p, afi, safi);
5286 bgp_static_free(bgp_static);
5a8ba9fc 5287 bgp_node_set_bgp_static_info(rn, NULL);
05c7a1cc 5288 bgp_unlock_node(rn);
ea47320b 5289 }
05c7a1cc 5290 }
d62a17ae 5291}
5292
5293void bgp_static_redo_import_check(struct bgp *bgp)
5294{
5295 afi_t afi;
5296 safi_t safi;
5297 struct bgp_node *rn;
5298 struct bgp_node *rm;
5299 struct bgp_table *table;
5300 struct bgp_static *bgp_static;
5301
5302 /* Use this flag to force reprocessing of the route */
5303 bgp_flag_set(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc
QY
5304 FOREACH_AFI_SAFI (afi, safi) {
5305 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5306 rn = bgp_route_next(rn)) {
67009e22 5307 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5308 continue;
ea47320b 5309
05c7a1cc
QY
5310 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5311 || (safi == SAFI_EVPN)) {
67009e22 5312 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5313
5314 for (rm = bgp_table_top(table); rm;
5315 rm = bgp_route_next(rm)) {
a78beeb5 5316 bgp_static =
5a8ba9fc
DS
5317 bgp_node_get_bgp_static_info(
5318 rm);
05c7a1cc
QY
5319 bgp_static_update_safi(bgp, &rm->p,
5320 bgp_static, afi,
5321 safi);
d62a17ae 5322 }
05c7a1cc 5323 } else {
5a8ba9fc 5324 bgp_static = bgp_node_get_bgp_static_info(rn);
05c7a1cc
QY
5325 bgp_static_update(bgp, &rn->p, bgp_static, afi,
5326 safi);
ea47320b 5327 }
05c7a1cc
QY
5328 }
5329 }
d62a17ae 5330 bgp_flag_unset(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
5331}
5332
5333static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
5334 safi_t safi)
5335{
5336 struct bgp_table *table;
5337 struct bgp_node *rn;
40381db7 5338 struct bgp_path_info *pi;
d62a17ae 5339
dfb6fd1d
NT
5340 /* Do not install the aggregate route if BGP is in the
5341 * process of termination.
5342 */
5343 if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS) ||
5344 (bgp->peer_self == NULL))
5345 return;
5346
d62a17ae 5347 table = bgp->rib[afi][safi];
5348 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685 5349 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7
DS
5350 if (pi->peer == bgp->peer_self
5351 && ((pi->type == ZEBRA_ROUTE_BGP
5352 && pi->sub_type == BGP_ROUTE_STATIC)
5353 || (pi->type != ZEBRA_ROUTE_BGP
5354 && pi->sub_type
d62a17ae 5355 == BGP_ROUTE_REDISTRIBUTE))) {
40381db7 5356 bgp_aggregate_decrement(bgp, &rn->p, pi, afi,
d62a17ae 5357 safi);
40381db7
DS
5358 bgp_unlink_nexthop(pi);
5359 bgp_path_info_delete(rn, pi);
d62a17ae 5360 bgp_process(bgp, rn, afi, safi);
5361 }
5362 }
5363 }
ad4cbda1 5364}
5365
5366/*
5367 * Purge all networks and redistributed routes from routing table.
5368 * Invoked upon the instance going down.
5369 */
d62a17ae 5370void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 5371{
d62a17ae 5372 afi_t afi;
5373 safi_t safi;
ad4cbda1 5374
05c7a1cc
QY
5375 FOREACH_AFI_SAFI (afi, safi)
5376 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 5377}
5378
137446f9
LB
5379/*
5380 * gpz 110624
5381 * Currently this is used to set static routes for VPN and ENCAP.
5382 * I think it can probably be factored with bgp_static_set.
5383 */
d62a17ae 5384int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
5385 const char *ip_str, const char *rd_str,
5386 const char *label_str, const char *rmap_str,
5387 int evpn_type, const char *esi, const char *gwip,
5388 const char *ethtag, const char *routermac)
5389{
5390 VTY_DECLVAR_CONTEXT(bgp, bgp);
5391 int ret;
5392 struct prefix p;
5393 struct prefix_rd prd;
5394 struct bgp_node *prn;
5395 struct bgp_node *rn;
5396 struct bgp_table *table;
5397 struct bgp_static *bgp_static;
5398 mpls_label_t label = MPLS_INVALID_LABEL;
5399 struct prefix gw_ip;
5400
5401 /* validate ip prefix */
5402 ret = str2prefix(ip_str, &p);
5403 if (!ret) {
5404 vty_out(vty, "%% Malformed prefix\n");
5405 return CMD_WARNING_CONFIG_FAILED;
5406 }
5407 apply_mask(&p);
5408 if ((afi == AFI_L2VPN)
5409 && (bgp_build_evpn_prefix(evpn_type,
5410 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5411 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5412 return CMD_WARNING_CONFIG_FAILED;
5413 }
718e3744 5414
d62a17ae 5415 ret = str2prefix_rd(rd_str, &prd);
5416 if (!ret) {
5417 vty_out(vty, "%% Malformed rd\n");
5418 return CMD_WARNING_CONFIG_FAILED;
5419 }
718e3744 5420
d62a17ae 5421 if (label_str) {
5422 unsigned long label_val;
5423 label_val = strtoul(label_str, NULL, 10);
5424 encode_label(label_val, &label);
5425 }
9bedbb1e 5426
d62a17ae 5427 if (safi == SAFI_EVPN) {
5428 if (esi && str2esi(esi, NULL) == 0) {
5429 vty_out(vty, "%% Malformed ESI\n");
5430 return CMD_WARNING_CONFIG_FAILED;
5431 }
5432 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
5433 vty_out(vty, "%% Malformed Router MAC\n");
5434 return CMD_WARNING_CONFIG_FAILED;
5435 }
5436 if (gwip) {
5437 memset(&gw_ip, 0, sizeof(struct prefix));
5438 ret = str2prefix(gwip, &gw_ip);
5439 if (!ret) {
5440 vty_out(vty, "%% Malformed GatewayIp\n");
5441 return CMD_WARNING_CONFIG_FAILED;
5442 }
5443 if ((gw_ip.family == AF_INET
3714a385 5444 && is_evpn_prefix_ipaddr_v6(
d62a17ae 5445 (struct prefix_evpn *)&p))
5446 || (gw_ip.family == AF_INET6
3714a385 5447 && is_evpn_prefix_ipaddr_v4(
d62a17ae 5448 (struct prefix_evpn *)&p))) {
5449 vty_out(vty,
5450 "%% GatewayIp family differs with IP prefix\n");
5451 return CMD_WARNING_CONFIG_FAILED;
5452 }
5453 }
5454 }
5455 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
67009e22
DS
5456 if (!bgp_node_has_bgp_path_info_data(prn))
5457 bgp_node_set_bgp_table_info(prn,
5458 bgp_table_init(bgp, afi, safi));
67009e22 5459 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 5460
5461 rn = bgp_node_get(table, &p);
5462
67009e22 5463 if (bgp_node_has_bgp_path_info_data(rn)) {
d62a17ae 5464 vty_out(vty, "%% Same network configuration exists\n");
5465 bgp_unlock_node(rn);
5466 } else {
5467 /* New configuration. */
5468 bgp_static = bgp_static_new();
5469 bgp_static->backdoor = 0;
5470 bgp_static->valid = 0;
5471 bgp_static->igpmetric = 0;
5472 bgp_static->igpnexthop.s_addr = 0;
5473 bgp_static->label = label;
5474 bgp_static->prd = prd;
5475
5476 if (rmap_str) {
0a22ddfb 5477 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5478 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 5479 bgp_static->rmap.name =
5480 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
5481 bgp_static->rmap.map =
5482 route_map_lookup_by_name(rmap_str);
b4897fa5 5483 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 5484 }
718e3744 5485
d62a17ae 5486 if (safi == SAFI_EVPN) {
5487 if (esi) {
5488 bgp_static->eth_s_id =
5489 XCALLOC(MTYPE_ATTR,
5490 sizeof(struct eth_segment_id));
5491 str2esi(esi, bgp_static->eth_s_id);
5492 }
5493 if (routermac) {
5494 bgp_static->router_mac =
28328ea9 5495 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
5496 (void)prefix_str2mac(routermac,
5497 bgp_static->router_mac);
d62a17ae 5498 }
5499 if (gwip)
5500 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
5501 }
5a8ba9fc 5502 bgp_node_set_bgp_static_info(rn, bgp_static);
718e3744 5503
d62a17ae 5504 bgp_static->valid = 1;
5505 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
5506 }
718e3744 5507
d62a17ae 5508 return CMD_SUCCESS;
718e3744 5509}
5510
5511/* Configure static BGP network. */
d62a17ae 5512int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
5513 const char *ip_str, const char *rd_str,
5514 const char *label_str, int evpn_type, const char *esi,
5515 const char *gwip, const char *ethtag)
5516{
5517 VTY_DECLVAR_CONTEXT(bgp, bgp);
5518 int ret;
5519 struct prefix p;
5520 struct prefix_rd prd;
5521 struct bgp_node *prn;
5522 struct bgp_node *rn;
5523 struct bgp_table *table;
5524 struct bgp_static *bgp_static;
5525 mpls_label_t label = MPLS_INVALID_LABEL;
5526
5527 /* Convert IP prefix string to struct prefix. */
5528 ret = str2prefix(ip_str, &p);
5529 if (!ret) {
5530 vty_out(vty, "%% Malformed prefix\n");
5531 return CMD_WARNING_CONFIG_FAILED;
5532 }
5533 apply_mask(&p);
5534 if ((afi == AFI_L2VPN)
5535 && (bgp_build_evpn_prefix(evpn_type,
5536 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5537 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5538 return CMD_WARNING_CONFIG_FAILED;
5539 }
5540 ret = str2prefix_rd(rd_str, &prd);
5541 if (!ret) {
5542 vty_out(vty, "%% Malformed rd\n");
5543 return CMD_WARNING_CONFIG_FAILED;
5544 }
718e3744 5545
d62a17ae 5546 if (label_str) {
5547 unsigned long label_val;
5548 label_val = strtoul(label_str, NULL, 10);
5549 encode_label(label_val, &label);
5550 }
718e3744 5551
d62a17ae 5552 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
67009e22
DS
5553 if (!bgp_node_has_bgp_path_info_data(prn))
5554 bgp_node_set_bgp_table_info(prn,
5555 bgp_table_init(bgp, afi, safi));
d62a17ae 5556 else
5557 bgp_unlock_node(prn);
67009e22 5558 table = bgp_node_get_bgp_table_info(prn);
718e3744 5559
d62a17ae 5560 rn = bgp_node_lookup(table, &p);
6b0655a2 5561
d62a17ae 5562 if (rn) {
5563 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 5564
5a8ba9fc 5565 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 5566 bgp_static_free(bgp_static);
5a8ba9fc 5567 bgp_node_set_bgp_static_info(rn, NULL);
d62a17ae 5568 bgp_unlock_node(rn);
5569 bgp_unlock_node(rn);
5570 } else
5571 vty_out(vty, "%% Can't find the route\n");
5572
5573 return CMD_SUCCESS;
5574}
5575
5576static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
5577 const char *rmap_name)
5578{
5579 VTY_DECLVAR_CONTEXT(bgp, bgp);
5580 struct bgp_rmap *rmap;
5581
5582 rmap = &bgp->table_map[afi][safi];
5583 if (rmap_name) {
0a22ddfb 5584 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5585 route_map_counter_decrement(rmap->map);
d62a17ae 5586 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
5587 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 5588 route_map_counter_increment(rmap->map);
d62a17ae 5589 } else {
0a22ddfb 5590 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5591 route_map_counter_decrement(rmap->map);
d62a17ae 5592 rmap->name = NULL;
5593 rmap->map = NULL;
5594 }
73ac8160 5595
d62a17ae 5596 if (bgp_fibupd_safi(safi))
5597 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5598
d62a17ae 5599 return CMD_SUCCESS;
73ac8160
DS
5600}
5601
d62a17ae 5602static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
5603 const char *rmap_name)
73ac8160 5604{
d62a17ae 5605 VTY_DECLVAR_CONTEXT(bgp, bgp);
5606 struct bgp_rmap *rmap;
73ac8160 5607
d62a17ae 5608 rmap = &bgp->table_map[afi][safi];
0a22ddfb 5609 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5610 route_map_counter_decrement(rmap->map);
d62a17ae 5611 rmap->name = NULL;
5612 rmap->map = NULL;
73ac8160 5613
d62a17ae 5614 if (bgp_fibupd_safi(safi))
5615 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5616
d62a17ae 5617 return CMD_SUCCESS;
73ac8160
DS
5618}
5619
2b791107 5620void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 5621 safi_t safi)
73ac8160 5622{
d62a17ae 5623 if (bgp->table_map[afi][safi].name) {
d62a17ae 5624 vty_out(vty, " table-map %s\n",
5625 bgp->table_map[afi][safi].name);
5626 }
73ac8160
DS
5627}
5628
73ac8160
DS
5629DEFUN (bgp_table_map,
5630 bgp_table_map_cmd,
5631 "table-map WORD",
5632 "BGP table to RIB route download filter\n"
5633 "Name of the route map\n")
5634{
d62a17ae 5635 int idx_word = 1;
5636 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5637 argv[idx_word]->arg);
73ac8160
DS
5638}
5639DEFUN (no_bgp_table_map,
5640 no_bgp_table_map_cmd,
5641 "no table-map WORD",
3a2d747c 5642 NO_STR
73ac8160
DS
5643 "BGP table to RIB route download filter\n"
5644 "Name of the route map\n")
5645{
d62a17ae 5646 int idx_word = 2;
5647 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5648 argv[idx_word]->arg);
73ac8160
DS
5649}
5650
e2a86ad9
DS
5651DEFPY(bgp_network,
5652 bgp_network_cmd,
5653 "[no] network \
5654 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5655 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5656 backdoor$backdoor}]",
5657 NO_STR
5658 "Specify a network to announce via BGP\n"
5659 "IPv4 prefix\n"
5660 "Network number\n"
5661 "Network mask\n"
5662 "Network mask\n"
5663 "Route-map to modify the attributes\n"
5664 "Name of the route map\n"
5665 "Label index to associate with the prefix\n"
5666 "Label index value\n"
5667 "Specify a BGP backdoor route\n")
5668{
5669 char addr_prefix_str[BUFSIZ];
5670
5671 if (address_str) {
5672 int ret;
718e3744 5673
e2a86ad9
DS
5674 ret = netmask_str2prefix_str(address_str, netmask_str,
5675 addr_prefix_str);
5676 if (!ret) {
5677 vty_out(vty, "%% Inconsistent address and mask\n");
5678 return CMD_WARNING_CONFIG_FAILED;
5679 }
d62a17ae 5680 }
718e3744 5681
a4d82a8a
PZ
5682 return bgp_static_set(
5683 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
5684 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
5685 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 5686}
5687
e2a86ad9
DS
5688DEFPY(ipv6_bgp_network,
5689 ipv6_bgp_network_cmd,
5690 "[no] network X:X::X:X/M$prefix \
5691 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5692 NO_STR
5693 "Specify a network to announce via BGP\n"
5694 "IPv6 prefix\n"
5695 "Route-map to modify the attributes\n"
5696 "Name of the route map\n"
5697 "Label index to associate with the prefix\n"
5698 "Label index value\n")
718e3744 5699{
a4d82a8a
PZ
5700 return bgp_static_set(
5701 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
5702 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
5703}
5704
d62a17ae 5705static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 5706{
d62a17ae 5707 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 5708}
5709
d62a17ae 5710static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 5711{
20894f50
DA
5712 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
5713 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 5714 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
5715}
718e3744 5716
40381db7 5717static int bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
29f7d023 5718 struct aspath *aspath,
3da2cc32 5719 struct community *comm,
dd18c5a9
DS
5720 struct ecommunity *ecomm,
5721 struct lcommunity *lcomm)
eaaf8adb
DS
5722{
5723 static struct aspath *ae = NULL;
5724
5725 if (!ae)
5726 ae = aspath_empty();
5727
40381db7 5728 if (!pi)
eaaf8adb
DS
5729 return 0;
5730
40381db7 5731 if (origin != pi->attr->origin)
eaaf8adb
DS
5732 return 0;
5733
40381db7 5734 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
29f7d023
DS
5735 return 0;
5736
40381db7 5737 if (!community_cmp(pi->attr->community, comm))
eaaf8adb
DS
5738 return 0;
5739
3da2cc32 5740 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
eaaf8adb
DS
5741 return 0;
5742
dd18c5a9
DS
5743 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
5744 return 0;
5745
40381db7 5746 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
7ce8a8e0
DS
5747 return 0;
5748
eaaf8adb
DS
5749 return 1;
5750}
5751
c701010e
DS
5752static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi,
5753 struct prefix *p, uint8_t origin,
5754 struct aspath *aspath,
5755 struct community *community,
3da2cc32 5756 struct ecommunity *ecommunity,
dd18c5a9 5757 struct lcommunity *lcommunity,
c701010e
DS
5758 uint8_t atomic_aggregate,
5759 struct bgp_aggregate *aggregate)
5760{
5761 struct bgp_node *rn;
5762 struct bgp_table *table;
6f94b685 5763 struct bgp_path_info *pi, *orig, *new;
20894f50 5764 struct attr *attr;
c701010e
DS
5765
5766 table = bgp->rib[afi][safi];
5767
5768 rn = bgp_node_get(table, p);
eaaf8adb 5769
6f94b685 5770 for (orig = pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
5771 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5772 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
5773 break;
5774
c701010e 5775 if (aggregate->count > 0) {
eaaf8adb
DS
5776 /*
5777 * If the aggregate information has not changed
5778 * no need to re-install it again.
5779 */
6f94b685 5780 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 5781 ecommunity, lcommunity)) {
eaaf8adb
DS
5782 bgp_unlock_node(rn);
5783
5784 if (aspath)
5785 aspath_free(aspath);
5786 if (community)
3c1f53de 5787 community_free(&community);
3da2cc32
DS
5788 if (ecommunity)
5789 ecommunity_free(&ecommunity);
dd18c5a9
DS
5790 if (lcommunity)
5791 lcommunity_free(&lcommunity);
eaaf8adb
DS
5792
5793 return;
5794 }
5795
5796 /*
5797 * Mark the old as unusable
5798 */
40381db7
DS
5799 if (pi)
5800 bgp_path_info_delete(rn, pi);
eaaf8adb 5801
20894f50
DA
5802 attr = bgp_attr_aggregate_intern(
5803 bgp, origin, aspath, community, ecommunity, lcommunity,
5804 aggregate, atomic_aggregate, p);
5805
5806 if (!attr) {
5807 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
5808 return;
5809 }
5810
3da2cc32 5811 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
20894f50
DA
5812 bgp->peer_self, attr, rn);
5813
1defdda8 5814 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 5815
18ee8310 5816 bgp_path_info_add(rn, new);
c701010e
DS
5817 bgp_process(bgp, rn, afi, safi);
5818 } else {
6f94b685 5819 for (pi = orig; pi; pi = pi->next)
40381db7
DS
5820 if (pi->peer == bgp->peer_self
5821 && pi->type == ZEBRA_ROUTE_BGP
5822 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
5823 break;
5824
5825 /* Withdraw static BGP route from routing table. */
40381db7
DS
5826 if (pi) {
5827 bgp_path_info_delete(rn, pi);
c701010e
DS
5828 bgp_process(bgp, rn, afi, safi);
5829 }
5830 }
5831
5832 bgp_unlock_node(rn);
5833}
5834
b5d58c32 5835/* Update an aggregate as routes are added/removed from the BGP table */
20894f50 5836void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
fc968841 5837 afi_t afi, safi_t safi,
d62a17ae 5838 struct bgp_aggregate *aggregate)
5839{
5840 struct bgp_table *table;
5841 struct bgp_node *top;
5842 struct bgp_node *rn;
d7c0a89a 5843 uint8_t origin;
d62a17ae 5844 struct aspath *aspath = NULL;
d62a17ae 5845 struct community *community = NULL;
3da2cc32 5846 struct ecommunity *ecommunity = NULL;
dd18c5a9 5847 struct lcommunity *lcommunity = NULL;
40381db7 5848 struct bgp_path_info *pi;
d62a17ae 5849 unsigned long match = 0;
d7c0a89a 5850 uint8_t atomic_aggregate = 0;
d62a17ae 5851
9f822fa2
S
5852 /* If the bgp instance is being deleted or self peer is deleted
5853 * then do not create aggregate route
5854 */
5855 if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS) ||
5856 (bgp->peer_self == NULL))
5857 return;
5858
d62a17ae 5859 /* ORIGIN attribute: If at least one route among routes that are
5860 aggregated has ORIGIN with the value INCOMPLETE, then the
5861 aggregated route must have the ORIGIN attribute with the value
5862 INCOMPLETE. Otherwise, if at least one route among routes that
5863 are aggregated has ORIGIN with the value EGP, then the aggregated
5864 route must have the origin attribute with the value EGP. In all
5865 other case the value of the ORIGIN attribute of the aggregated
5866 route is INTERNAL. */
5867 origin = BGP_ORIGIN_IGP;
718e3744 5868
d62a17ae 5869 table = bgp->rib[afi][safi];
718e3744 5870
d62a17ae 5871 top = bgp_node_get(table, p);
5872 for (rn = bgp_node_get(table, p); rn;
c2ff8b3e
DS
5873 rn = bgp_route_next_until(rn, top)) {
5874 if (rn->p.prefixlen <= p->prefixlen)
5875 continue;
d62a17ae 5876
c2ff8b3e 5877 match = 0;
d62a17ae 5878
6f94b685 5879 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 5880 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 5881 continue;
718e3744 5882
40381db7 5883 if (pi->attr->flag
c2ff8b3e
DS
5884 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
5885 atomic_aggregate = 1;
d62a17ae 5886
40381db7 5887 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 5888 continue;
d62a17ae 5889
f273fef1
DS
5890 /*
5891 * summary-only aggregate route suppress
5892 * aggregated route announcements.
5893 */
c2ff8b3e 5894 if (aggregate->summary_only) {
40381db7
DS
5895 (bgp_path_info_extra_get(pi))->suppress++;
5896 bgp_path_info_set_flag(rn, pi,
18ee8310 5897 BGP_PATH_ATTR_CHANGED);
c2ff8b3e 5898 match++;
d62a17ae 5899 }
c2ff8b3e
DS
5900
5901 aggregate->count++;
5902
f273fef1
DS
5903 /*
5904 * If at least one route among routes that are
5905 * aggregated has ORIGIN with the value INCOMPLETE,
5906 * then the aggregated route MUST have the ORIGIN
5907 * attribute with the value INCOMPLETE. Otherwise, if
5908 * at least one route among routes that are aggregated
5909 * has ORIGIN with the value EGP, then the aggregated
5910 * route MUST have the ORIGIN attribute with the value
5911 * EGP.
5912 */
fc968841
NT
5913 switch (pi->attr->origin) {
5914 case BGP_ORIGIN_INCOMPLETE:
5915 aggregate->incomplete_origin_count++;
5916 break;
5917 case BGP_ORIGIN_EGP:
5918 aggregate->egp_origin_count++;
5919 break;
5920 default:
5921 /*Do nothing.
5922 */
5923 break;
5924 }
c2ff8b3e
DS
5925
5926 if (!aggregate->as_set)
5927 continue;
5928
f273fef1
DS
5929 /*
5930 * as-set aggregate route generate origin, as path,
5931 * and community aggregation.
5932 */
fc968841
NT
5933 /* Compute aggregate route's as-path.
5934 */
ef51a7d8 5935 bgp_compute_aggregate_aspath_hash(aggregate,
5936 pi->attr->aspath);
c2ff8b3e 5937
fc968841
NT
5938 /* Compute aggregate route's community.
5939 */
5940 if (pi->attr->community)
21fec674 5941 bgp_compute_aggregate_community_hash(
fc968841
NT
5942 aggregate,
5943 pi->attr->community);
dd18c5a9 5944
fc968841
NT
5945 /* Compute aggregate route's extended community.
5946 */
5947 if (pi->attr->ecommunity)
4edd83f9 5948 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
5949 aggregate,
5950 pi->attr->ecommunity);
5951
5952 /* Compute aggregate route's large community.
5953 */
5954 if (pi->attr->lcommunity)
f1eb1f05 5955 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
5956 aggregate,
5957 pi->attr->lcommunity);
d62a17ae 5958 }
c2ff8b3e
DS
5959 if (match)
5960 bgp_process(bgp, rn, afi, safi);
5961 }
21fec674 5962 if (aggregate->as_set) {
ef51a7d8 5963 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 5964 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 5965 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 5966 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 5967 }
5968
f1eb1f05 5969
d62a17ae 5970 bgp_unlock_node(top);
718e3744 5971
718e3744 5972
fc968841
NT
5973 if (aggregate->incomplete_origin_count > 0)
5974 origin = BGP_ORIGIN_INCOMPLETE;
5975 else if (aggregate->egp_origin_count > 0)
5976 origin = BGP_ORIGIN_EGP;
d62a17ae 5977
fc968841
NT
5978 if (aggregate->as_set) {
5979 if (aggregate->aspath)
5980 /* Retrieve aggregate route's as-path.
5981 */
5982 aspath = aspath_dup(aggregate->aspath);
d62a17ae 5983
fc968841
NT
5984 if (aggregate->community)
5985 /* Retrieve aggregate route's community.
5986 */
5987 community = community_dup(aggregate->community);
3da2cc32 5988
fc968841
NT
5989 if (aggregate->ecommunity)
5990 /* Retrieve aggregate route's ecommunity.
5991 */
5992 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 5993
fc968841
NT
5994 if (aggregate->lcommunity)
5995 /* Retrieve aggregate route's lcommunity.
5996 */
5997 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 5998 }
718e3744 5999
c701010e 6000 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
6001 ecommunity, lcommunity, atomic_aggregate,
6002 aggregate);
718e3744 6003}
6004
20894f50 6005void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
3b7db173
DS
6006 safi_t safi, struct bgp_aggregate *aggregate)
6007{
6008 struct bgp_table *table;
6009 struct bgp_node *top;
6010 struct bgp_node *rn;
40381db7 6011 struct bgp_path_info *pi;
3b7db173
DS
6012 unsigned long match;
6013
6014 table = bgp->rib[afi][safi];
6015
6016 /* If routes exists below this node, generate aggregate routes. */
6017 top = bgp_node_get(table, p);
6018 for (rn = bgp_node_get(table, p); rn;
6019 rn = bgp_route_next_until(rn, top)) {
6020 if (rn->p.prefixlen <= p->prefixlen)
6021 continue;
6022 match = 0;
6023
6f94b685 6024 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 6025 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
6026 continue;
6027
40381db7 6028 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
6029 continue;
6030
40381db7
DS
6031 if (aggregate->summary_only && pi->extra) {
6032 pi->extra->suppress--;
3b7db173 6033
40381db7 6034 if (pi->extra->suppress == 0) {
18ee8310 6035 bgp_path_info_set_flag(
40381db7 6036 rn, pi, BGP_PATH_ATTR_CHANGED);
3b7db173
DS
6037 match++;
6038 }
6039 }
6040 aggregate->count--;
fc968841
NT
6041
6042 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6043 aggregate->incomplete_origin_count--;
6044 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6045 aggregate->egp_origin_count--;
6046
6047 if (aggregate->as_set) {
6048 /* Remove as-path from aggregate.
6049 */
ef51a7d8 6050 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
6051 aggregate,
6052 pi->attr->aspath);
6053
6054 if (pi->attr->community)
6055 /* Remove community from aggregate.
6056 */
21fec674 6057 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
6058 aggregate,
6059 pi->attr->community);
6060
6061 if (pi->attr->ecommunity)
6062 /* Remove ecommunity from aggregate.
6063 */
4edd83f9 6064 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
6065 aggregate,
6066 pi->attr->ecommunity);
6067
6068 if (pi->attr->lcommunity)
6069 /* Remove lcommunity from aggregate.
6070 */
f1eb1f05 6071 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
6072 aggregate,
6073 pi->attr->lcommunity);
6074 }
6075
3b7db173
DS
6076 }
6077
6078 /* If this node was suppressed, process the change. */
6079 if (match)
6080 bgp_process(bgp, rn, afi, safi);
6081 }
f1eb1f05 6082 if (aggregate->as_set) {
ef51a7d8 6083 aspath_free(aggregate->aspath);
6084 aggregate->aspath = NULL;
21fec674 6085 if (aggregate->community)
6086 community_free(&aggregate->community);
4edd83f9 6087 if (aggregate->ecommunity)
6088 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 6089 if (aggregate->lcommunity)
6090 lcommunity_free(&aggregate->lcommunity);
6091 }
6092
3b7db173
DS
6093 bgp_unlock_node(top);
6094}
718e3744 6095
fc968841
NT
6096static void bgp_add_route_to_aggregate(struct bgp *bgp, struct prefix *aggr_p,
6097 struct bgp_path_info *pinew, afi_t afi,
6098 safi_t safi,
6099 struct bgp_aggregate *aggregate)
6100{
6101 uint8_t origin;
6102 struct aspath *aspath = NULL;
6103 uint8_t atomic_aggregate = 0;
6104 struct community *community = NULL;
6105 struct ecommunity *ecommunity = NULL;
6106 struct lcommunity *lcommunity = NULL;
6107
6108 /* ORIGIN attribute: If at least one route among routes that are
6109 * aggregated has ORIGIN with the value INCOMPLETE, then the
6110 * aggregated route must have the ORIGIN attribute with the value
6111 * INCOMPLETE. Otherwise, if at least one route among routes that
6112 * are aggregated has ORIGIN with the value EGP, then the aggregated
6113 * route must have the origin attribute with the value EGP. In all
6114 * other case the value of the ORIGIN attribute of the aggregated
6115 * route is INTERNAL.
6116 */
6117 origin = BGP_ORIGIN_IGP;
6118
6119 aggregate->count++;
6120
6121 if (aggregate->summary_only)
6122 (bgp_path_info_extra_get(pinew))->suppress++;
6123
6124 switch (pinew->attr->origin) {
6125 case BGP_ORIGIN_INCOMPLETE:
6126 aggregate->incomplete_origin_count++;
6127 break;
6128 case BGP_ORIGIN_EGP:
6129 aggregate->egp_origin_count++;
6130 break;
6131 default:
6132 /* Do nothing.
6133 */
6134 break;
6135 }
6136
6137 if (aggregate->incomplete_origin_count > 0)
6138 origin = BGP_ORIGIN_INCOMPLETE;
6139 else if (aggregate->egp_origin_count > 0)
6140 origin = BGP_ORIGIN_EGP;
6141
6142 if (aggregate->as_set) {
6143 /* Compute aggregate route's as-path.
6144 */
6145 bgp_compute_aggregate_aspath(aggregate,
6146 pinew->attr->aspath);
6147
6148 /* Compute aggregate route's community.
6149 */
6150 if (pinew->attr->community)
6151 bgp_compute_aggregate_community(
6152 aggregate,
6153 pinew->attr->community);
6154
6155 /* Compute aggregate route's extended community.
6156 */
6157 if (pinew->attr->ecommunity)
6158 bgp_compute_aggregate_ecommunity(
6159 aggregate,
6160 pinew->attr->ecommunity);
6161
6162 /* Compute aggregate route's large community.
6163 */
6164 if (pinew->attr->lcommunity)
6165 bgp_compute_aggregate_lcommunity(
6166 aggregate,
6167 pinew->attr->lcommunity);
6168
6169 /* Retrieve aggregate route's as-path.
6170 */
6171 if (aggregate->aspath)
6172 aspath = aspath_dup(aggregate->aspath);
6173
6174 /* Retrieve aggregate route's community.
6175 */
6176 if (aggregate->community)
6177 community = community_dup(aggregate->community);
6178
6179 /* Retrieve aggregate route's ecommunity.
6180 */
6181 if (aggregate->ecommunity)
6182 ecommunity = ecommunity_dup(aggregate->ecommunity);
6183
6184 /* Retrieve aggregate route's lcommunity.
6185 */
6186 if (aggregate->lcommunity)
6187 lcommunity = lcommunity_dup(aggregate->lcommunity);
6188 }
6189
6190 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6191 aspath, community, ecommunity,
6192 lcommunity, atomic_aggregate, aggregate);
6193}
6194
6195static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
6196 safi_t safi,
6197 struct bgp_path_info *pi,
6198 struct bgp_aggregate *aggregate,
6199 struct prefix *aggr_p)
6200{
6201 uint8_t origin;
6202 struct aspath *aspath = NULL;
6203 uint8_t atomic_aggregate = 0;
6204 struct community *community = NULL;
6205 struct ecommunity *ecommunity = NULL;
6206 struct lcommunity *lcommunity = NULL;
6207 unsigned long match = 0;
6208
6209 if (BGP_PATH_HOLDDOWN(pi))
6210 return;
6211
6212 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6213 return;
6214
6215 if (aggregate->summary_only
6216 && pi->extra
6217 && pi->extra->suppress > 0) {
6218 pi->extra->suppress--;
6219
6220 if (pi->extra->suppress == 0) {
6221 bgp_path_info_set_flag(pi->net, pi,
6222 BGP_PATH_ATTR_CHANGED);
6223 match++;
6224 }
6225 }
6226
6227 if (aggregate->count > 0)
6228 aggregate->count--;
6229
6230 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6231 aggregate->incomplete_origin_count--;
6232 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6233 aggregate->egp_origin_count--;
6234
6235 if (aggregate->as_set) {
6236 /* Remove as-path from aggregate.
6237 */
6238 bgp_remove_aspath_from_aggregate(aggregate,
6239 pi->attr->aspath);
6240
6241 if (pi->attr->community)
6242 /* Remove community from aggregate.
6243 */
6244 bgp_remove_community_from_aggregate(
6245 aggregate,
6246 pi->attr->community);
6247
6248 if (pi->attr->ecommunity)
6249 /* Remove ecommunity from aggregate.
6250 */
6251 bgp_remove_ecommunity_from_aggregate(
6252 aggregate,
6253 pi->attr->ecommunity);
6254
6255 if (pi->attr->lcommunity)
6256 /* Remove lcommunity from aggregate.
6257 */
6258 bgp_remove_lcommunity_from_aggregate(
6259 aggregate,
6260 pi->attr->lcommunity);
6261 }
6262
6263 /* If this node was suppressed, process the change. */
6264 if (match)
6265 bgp_process(bgp, pi->net, afi, safi);
6266
6267 origin = BGP_ORIGIN_IGP;
6268 if (aggregate->incomplete_origin_count > 0)
6269 origin = BGP_ORIGIN_INCOMPLETE;
6270 else if (aggregate->egp_origin_count > 0)
6271 origin = BGP_ORIGIN_EGP;
6272
6273 if (aggregate->as_set) {
6274 /* Retrieve aggregate route's as-path.
6275 */
6276 if (aggregate->aspath)
6277 aspath = aspath_dup(aggregate->aspath);
6278
6279 /* Retrieve aggregate route's community.
6280 */
6281 if (aggregate->community)
6282 community = community_dup(aggregate->community);
6283
6284 /* Retrieve aggregate route's ecommunity.
6285 */
6286 if (aggregate->ecommunity)
6287 ecommunity = ecommunity_dup(aggregate->ecommunity);
6288
6289 /* Retrieve aggregate route's lcommunity.
6290 */
6291 if (aggregate->lcommunity)
6292 lcommunity = lcommunity_dup(aggregate->lcommunity);
6293 }
6294
6295 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6296 aspath, community, ecommunity,
6297 lcommunity, atomic_aggregate, aggregate);
6298}
6299
d62a17ae 6300void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p,
40381db7 6301 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 6302{
d62a17ae 6303 struct bgp_node *child;
6304 struct bgp_node *rn;
6305 struct bgp_aggregate *aggregate;
6306 struct bgp_table *table;
718e3744 6307
d62a17ae 6308 table = bgp->aggregate[afi][safi];
f018db83 6309
d62a17ae 6310 /* No aggregates configured. */
6311 if (bgp_table_top_nolock(table) == NULL)
6312 return;
f018db83 6313
d62a17ae 6314 if (p->prefixlen == 0)
6315 return;
718e3744 6316
40381db7 6317 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 6318 return;
718e3744 6319
d62a17ae 6320 child = bgp_node_get(table, p);
718e3744 6321
d62a17ae 6322 /* Aggregate address configuration check. */
b1e62edd 6323 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
b613a918 6324 aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 6325 if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
fc968841
NT
6326 bgp_add_route_to_aggregate(bgp, &rn->p, pi, afi,
6327 safi, aggregate);
d62a17ae 6328 }
b1e62edd 6329 }
d62a17ae 6330 bgp_unlock_node(child);
718e3744 6331}
6332
d62a17ae 6333void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p,
4b7e6066 6334 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 6335{
d62a17ae 6336 struct bgp_node *child;
6337 struct bgp_node *rn;
6338 struct bgp_aggregate *aggregate;
6339 struct bgp_table *table;
718e3744 6340
d62a17ae 6341 table = bgp->aggregate[afi][safi];
718e3744 6342
d62a17ae 6343 /* No aggregates configured. */
6344 if (bgp_table_top_nolock(table) == NULL)
6345 return;
718e3744 6346
d62a17ae 6347 if (p->prefixlen == 0)
6348 return;
718e3744 6349
d62a17ae 6350 child = bgp_node_get(table, p);
718e3744 6351
d62a17ae 6352 /* Aggregate address configuration check. */
b1e62edd 6353 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
b613a918 6354 aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 6355 if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
fc968841
NT
6356 bgp_remove_route_from_aggregate(bgp, afi, safi,
6357 del, aggregate, &rn->p);
d62a17ae 6358 }
b1e62edd 6359 }
d62a17ae 6360 bgp_unlock_node(child);
6361}
718e3744 6362
718e3744 6363/* Aggregate route attribute. */
6364#define AGGREGATE_SUMMARY_ONLY 1
6365#define AGGREGATE_AS_SET 1
6366
d62a17ae 6367static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
6368 afi_t afi, safi_t safi)
718e3744 6369{
d62a17ae 6370 VTY_DECLVAR_CONTEXT(bgp, bgp);
6371 int ret;
6372 struct prefix p;
6373 struct bgp_node *rn;
6374 struct bgp_aggregate *aggregate;
718e3744 6375
d62a17ae 6376 /* Convert string to prefix structure. */
6377 ret = str2prefix(prefix_str, &p);
6378 if (!ret) {
6379 vty_out(vty, "Malformed prefix\n");
6380 return CMD_WARNING_CONFIG_FAILED;
6381 }
6382 apply_mask(&p);
6383
6384 /* Old configuration check. */
6385 rn = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
6386 if (!rn) {
6387 vty_out(vty,
6388 "%% There is no aggregate-address configuration.\n");
6389 return CMD_WARNING_CONFIG_FAILED;
6390 }
f6269b4f 6391
b613a918 6392 aggregate = bgp_node_get_bgp_aggregate_info(rn);
09990cdd 6393 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
dd18c5a9
DS
6394 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
6395 NULL, NULL, 0, aggregate);
d62a17ae 6396
6397 /* Unlock aggregate address configuration. */
b613a918 6398 bgp_node_set_bgp_aggregate_info(rn, NULL);
fc968841
NT
6399
6400 if (aggregate->community)
6401 community_free(&aggregate->community);
6402
6403 if (aggregate->community_hash) {
6404 /* Delete all communities in the hash.
6405 */
6406 hash_clean(aggregate->community_hash,
6407 bgp_aggr_community_remove);
6408 /* Free up the community_hash.
6409 */
6410 hash_free(aggregate->community_hash);
6411 }
6412
6413 if (aggregate->ecommunity)
6414 ecommunity_free(&aggregate->ecommunity);
6415
6416 if (aggregate->ecommunity_hash) {
6417 /* Delete all ecommunities in the hash.
6418 */
6419 hash_clean(aggregate->ecommunity_hash,
6420 bgp_aggr_ecommunity_remove);
6421 /* Free up the ecommunity_hash.
6422 */
6423 hash_free(aggregate->ecommunity_hash);
6424 }
6425
6426 if (aggregate->lcommunity)
6427 lcommunity_free(&aggregate->lcommunity);
6428
6429 if (aggregate->lcommunity_hash) {
6430 /* Delete all lcommunities in the hash.
6431 */
6432 hash_clean(aggregate->lcommunity_hash,
6433 bgp_aggr_lcommunity_remove);
6434 /* Free up the lcommunity_hash.
6435 */
6436 hash_free(aggregate->lcommunity_hash);
6437 }
6438
6439 if (aggregate->aspath)
6440 aspath_free(aggregate->aspath);
6441
6442 if (aggregate->aspath_hash) {
6443 /* Delete all as-paths in the hash.
6444 */
6445 hash_clean(aggregate->aspath_hash,
6446 bgp_aggr_aspath_remove);
6447 /* Free up the aspath_hash.
6448 */
6449 hash_free(aggregate->aspath_hash);
6450 }
6451
d62a17ae 6452 bgp_aggregate_free(aggregate);
6453 bgp_unlock_node(rn);
6454 bgp_unlock_node(rn);
6455
6456 return CMD_SUCCESS;
6457}
6458
6459static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
20894f50
DA
6460 safi_t safi, const char *rmap, uint8_t summary_only,
6461 uint8_t as_set)
d62a17ae 6462{
6463 VTY_DECLVAR_CONTEXT(bgp, bgp);
6464 int ret;
6465 struct prefix p;
6466 struct bgp_node *rn;
6467 struct bgp_aggregate *aggregate;
6468
6469 /* Convert string to prefix structure. */
6470 ret = str2prefix(prefix_str, &p);
6471 if (!ret) {
6472 vty_out(vty, "Malformed prefix\n");
6473 return CMD_WARNING_CONFIG_FAILED;
6474 }
6475 apply_mask(&p);
6476
3624ac81
DS
6477 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
6478 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
6479 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6480 prefix_str);
6481 return CMD_WARNING_CONFIG_FAILED;
6482 }
6483
d62a17ae 6484 /* Old configuration check. */
6485 rn = bgp_node_get(bgp->aggregate[afi][safi], &p);
20894f50 6486 aggregate = bgp_node_get_bgp_aggregate_info(rn);
d62a17ae 6487
20894f50 6488 if (aggregate) {
d62a17ae 6489 vty_out(vty, "There is already same aggregate network.\n");
6490 /* try to remove the old entry */
6491 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
6492 if (ret) {
6493 vty_out(vty, "Error deleting aggregate.\n");
6494 bgp_unlock_node(rn);
6495 return CMD_WARNING_CONFIG_FAILED;
6496 }
6497 }
718e3744 6498
d62a17ae 6499 /* Make aggregate address structure. */
6500 aggregate = bgp_aggregate_new();
6501 aggregate->summary_only = summary_only;
6502 aggregate->as_set = as_set;
6503 aggregate->safi = safi;
20894f50
DA
6504
6505 if (rmap) {
6506 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6507 route_map_counter_decrement(aggregate->rmap.map);
6508 aggregate->rmap.name =
6509 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6510 aggregate->rmap.map = route_map_lookup_by_name(rmap);
6511 route_map_counter_increment(aggregate->rmap.map);
6512 }
b613a918 6513 bgp_node_set_bgp_aggregate_info(rn, aggregate);
718e3744 6514
d62a17ae 6515 /* Aggregate address insert into BGP routing table. */
fc968841 6516 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 6517
d62a17ae 6518 return CMD_SUCCESS;
718e3744 6519}
6520
6521DEFUN (aggregate_address,
6522 aggregate_address_cmd,
20894f50 6523 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6524 "Configure BGP aggregate entries\n"
6525 "Aggregate prefix\n"
6526 "Generate AS set path information\n"
a636c635
DW
6527 "Filter more specific routes from updates\n"
6528 "Filter more specific routes from updates\n"
20894f50
DA
6529 "Generate AS set path information\n"
6530 "Apply route map to aggregate network\n"
6531 "Name of route map\n")
718e3744 6532{
d62a17ae 6533 int idx = 0;
6534 argv_find(argv, argc, "A.B.C.D/M", &idx);
6535 char *prefix = argv[idx]->arg;
20894f50 6536 char *rmap = NULL;
d62a17ae 6537 int as_set =
6538 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
6539 idx = 0;
6540 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6541 ? AGGREGATE_SUMMARY_ONLY
6542 : 0;
e3e6107d 6543
20894f50
DA
6544 idx = 0;
6545 argv_find(argv, argc, "WORD", &idx);
6546 if (idx)
6547 rmap = argv[idx]->arg;
6548
d62a17ae 6549 return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty),
20894f50 6550 rmap, summary_only, as_set);
718e3744 6551}
6552
e3e6107d
QY
6553DEFUN (aggregate_address_mask,
6554 aggregate_address_mask_cmd,
20894f50 6555 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6556 "Configure BGP aggregate entries\n"
6557 "Aggregate address\n"
6558 "Aggregate mask\n"
6559 "Generate AS set path information\n"
a636c635
DW
6560 "Filter more specific routes from updates\n"
6561 "Filter more specific routes from updates\n"
20894f50
DA
6562 "Generate AS set path information\n"
6563 "Apply route map to aggregate network\n"
6564 "Name of route map\n")
718e3744 6565{
d62a17ae 6566 int idx = 0;
6567 argv_find(argv, argc, "A.B.C.D", &idx);
6568 char *prefix = argv[idx]->arg;
6569 char *mask = argv[idx + 1]->arg;
cf40d052 6570 bool rmap_found;
20894f50 6571 char *rmap = NULL;
d62a17ae 6572 int as_set =
6573 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
6574 idx = 0;
6575 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6576 ? AGGREGATE_SUMMARY_ONLY
6577 : 0;
6578
cf40d052
DS
6579 rmap_found = argv_find(argv, argc, "WORD", &idx);
6580 if (rmap_found)
20894f50
DA
6581 rmap = argv[idx]->arg;
6582
d62a17ae 6583 char prefix_str[BUFSIZ];
6584 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
6585
6586 if (!ret) {
6587 vty_out(vty, "%% Inconsistent address and mask\n");
6588 return CMD_WARNING_CONFIG_FAILED;
6589 }
718e3744 6590
d62a17ae 6591 return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
20894f50 6592 rmap, summary_only, as_set);
718e3744 6593}
6594
718e3744 6595DEFUN (no_aggregate_address,
6596 no_aggregate_address_cmd,
b84da0db 6597 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6598 NO_STR
6599 "Configure BGP aggregate entries\n"
a636c635
DW
6600 "Aggregate prefix\n"
6601 "Generate AS set path information\n"
e3e6107d
QY
6602 "Filter more specific routes from updates\n"
6603 "Filter more specific routes from updates\n"
b84da0db
DA
6604 "Generate AS set path information\n"
6605 "Apply route map to aggregate network\n"
6606 "Name of route map\n")
718e3744 6607{
d62a17ae 6608 int idx = 0;
6609 argv_find(argv, argc, "A.B.C.D/M", &idx);
6610 char *prefix = argv[idx]->arg;
6611 return bgp_aggregate_unset(vty, prefix, AFI_IP, bgp_node_safi(vty));
718e3744 6612}
6613
718e3744 6614DEFUN (no_aggregate_address_mask,
6615 no_aggregate_address_mask_cmd,
b84da0db 6616 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6617 NO_STR
6618 "Configure BGP aggregate entries\n"
6619 "Aggregate address\n"
a636c635
DW
6620 "Aggregate mask\n"
6621 "Generate AS set path information\n"
e3e6107d
QY
6622 "Filter more specific routes from updates\n"
6623 "Filter more specific routes from updates\n"
b84da0db
DA
6624 "Generate AS set path information\n"
6625 "Apply route map to aggregate network\n"
6626 "Name of route map\n")
718e3744 6627{
d62a17ae 6628 int idx = 0;
6629 argv_find(argv, argc, "A.B.C.D", &idx);
6630 char *prefix = argv[idx]->arg;
6631 char *mask = argv[idx + 1]->arg;
718e3744 6632
d62a17ae 6633 char prefix_str[BUFSIZ];
6634 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
718e3744 6635
d62a17ae 6636 if (!ret) {
6637 vty_out(vty, "%% Inconsistent address and mask\n");
6638 return CMD_WARNING_CONFIG_FAILED;
6639 }
718e3744 6640
d62a17ae 6641 return bgp_aggregate_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
718e3744 6642}
6643
718e3744 6644DEFUN (ipv6_aggregate_address,
6645 ipv6_aggregate_address_cmd,
20894f50 6646 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6647 "Configure BGP aggregate entries\n"
6648 "Aggregate prefix\n"
5101fece 6649 "Generate AS set path information\n"
6650 "Filter more specific routes from updates\n"
6651 "Filter more specific routes from updates\n"
20894f50
DA
6652 "Generate AS set path information\n"
6653 "Apply route map to aggregate network\n"
6654 "Name of route map\n")
718e3744 6655{
d62a17ae 6656 int idx = 0;
6657 argv_find(argv, argc, "X:X::X:X/M", &idx);
6658 char *prefix = argv[idx]->arg;
20894f50 6659 char *rmap = NULL;
273fae13 6660 bool rmap_found;
5101fece 6661 int as_set =
6662 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
6663
6664 idx = 0;
d62a17ae 6665 int sum_only = argv_find(argv, argc, "summary-only", &idx)
6666 ? AGGREGATE_SUMMARY_ONLY
6667 : 0;
20894f50 6668
273fae13
DA
6669 rmap_found = argv_find(argv, argc, "WORD", &idx);
6670 if (rmap_found)
20894f50
DA
6671 rmap = argv[idx]->arg;
6672
6673 return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, rmap,
6674 sum_only, as_set);
718e3744 6675}
6676
6677DEFUN (no_ipv6_aggregate_address,
6678 no_ipv6_aggregate_address_cmd,
b84da0db 6679 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6680 NO_STR
6681 "Configure BGP aggregate entries\n"
16cedbb0 6682 "Aggregate prefix\n"
5101fece 6683 "Generate AS set path information\n"
6684 "Filter more specific routes from updates\n"
6685 "Filter more specific routes from updates\n"
b84da0db
DA
6686 "Generate AS set path information\n"
6687 "Apply route map to aggregate network\n"
6688 "Name of route map\n")
718e3744 6689{
d62a17ae 6690 int idx = 0;
6691 argv_find(argv, argc, "X:X::X:X/M", &idx);
6692 char *prefix = argv[idx]->arg;
6693 return bgp_aggregate_unset(vty, prefix, AFI_IP6, SAFI_UNICAST);
718e3744 6694}
6695
718e3744 6696/* Redistribute route treatment. */
d62a17ae 6697void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
6698 const union g_addr *nexthop, ifindex_t ifindex,
6699 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
6700 uint8_t type, unsigned short instance,
6701 route_tag_t tag)
d62a17ae 6702{
4b7e6066 6703 struct bgp_path_info *new;
40381db7
DS
6704 struct bgp_path_info *bpi;
6705 struct bgp_path_info rmap_path;
d62a17ae 6706 struct bgp_node *bn;
6707 struct attr attr;
6708 struct attr *new_attr;
6709 afi_t afi;
b68885f9 6710 route_map_result_t ret;
d62a17ae 6711 struct bgp_redist *red;
6712
6713 /* Make default attribute. */
6714 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
6715 /*
6716 * This must not be NULL to satisfy Coverity SA
6717 */
6718 assert(attr.aspath);
9de1f7ff 6719
a4d82a8a 6720 switch (nhtype) {
9de1f7ff
DS
6721 case NEXTHOP_TYPE_IFINDEX:
6722 break;
6723 case NEXTHOP_TYPE_IPV4:
6724 case NEXTHOP_TYPE_IPV4_IFINDEX:
6725 attr.nexthop = nexthop->ipv4;
6726 break;
6727 case NEXTHOP_TYPE_IPV6:
6728 case NEXTHOP_TYPE_IPV6_IFINDEX:
6729 attr.mp_nexthop_global = nexthop->ipv6;
6730 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
6731 break;
6732 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
6733 switch (p->family) {
6734 case AF_INET:
9de1f7ff 6735 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
6736 break;
6737 case AF_INET6:
9de1f7ff
DS
6738 memset(&attr.mp_nexthop_global, 0,
6739 sizeof(attr.mp_nexthop_global));
74489921 6740 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 6741 break;
74489921 6742 }
9de1f7ff 6743 break;
d62a17ae 6744 }
74489921 6745 attr.nh_ifindex = ifindex;
f04a80a5 6746
d62a17ae 6747 attr.med = metric;
6748 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
6749 attr.tag = tag;
718e3744 6750
d62a17ae 6751 afi = family2afi(p->family);
6aeb9e78 6752
d62a17ae 6753 red = bgp_redist_lookup(bgp, afi, type, instance);
6754 if (red) {
6755 struct attr attr_new;
718e3744 6756
d62a17ae 6757 /* Copy attribute for modification. */
6758 bgp_attr_dup(&attr_new, &attr);
718e3744 6759
d62a17ae 6760 if (red->redist_metric_flag)
6761 attr_new.med = red->redist_metric;
718e3744 6762
d62a17ae 6763 /* Apply route-map. */
6764 if (red->rmap.name) {
40381db7
DS
6765 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
6766 rmap_path.peer = bgp->peer_self;
6767 rmap_path.attr = &attr_new;
718e3744 6768
d62a17ae 6769 SET_FLAG(bgp->peer_self->rmap_type,
6770 PEER_RMAP_TYPE_REDISTRIBUTE);
6771
6772 ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
40381db7 6773 &rmap_path);
d62a17ae 6774
6775 bgp->peer_self->rmap_type = 0;
6776
6777 if (ret == RMAP_DENYMATCH) {
6778 /* Free uninterned attribute. */
6779 bgp_attr_flush(&attr_new);
6780
6781 /* Unintern original. */
6782 aspath_unintern(&attr.aspath);
6783 bgp_redistribute_delete(bgp, p, type, instance);
6784 return;
6785 }
6786 }
6787
7f323236
DW
6788 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
6789 bgp_attr_add_gshut_community(&attr_new);
6790
d62a17ae 6791 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
6792 SAFI_UNICAST, p, NULL);
6793
6794 new_attr = bgp_attr_intern(&attr_new);
6795
6f94b685
DS
6796 for (bpi = bgp_node_get_bgp_path_info(bn); bpi;
6797 bpi = bpi->next)
40381db7
DS
6798 if (bpi->peer == bgp->peer_self
6799 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 6800 break;
6801
40381db7 6802 if (bpi) {
d62a17ae 6803 /* Ensure the (source route) type is updated. */
40381db7
DS
6804 bpi->type = type;
6805 if (attrhash_cmp(bpi->attr, new_attr)
6806 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 6807 bgp_attr_unintern(&new_attr);
6808 aspath_unintern(&attr.aspath);
6809 bgp_unlock_node(bn);
6810 return;
6811 } else {
6812 /* The attribute is changed. */
40381db7 6813 bgp_path_info_set_flag(bn, bpi,
18ee8310 6814 BGP_PATH_ATTR_CHANGED);
d62a17ae 6815
6816 /* Rewrite BGP route information. */
40381db7
DS
6817 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
6818 bgp_path_info_restore(bn, bpi);
d62a17ae 6819 else
40381db7
DS
6820 bgp_aggregate_decrement(
6821 bgp, p, bpi, afi, SAFI_UNICAST);
6822 bgp_attr_unintern(&bpi->attr);
6823 bpi->attr = new_attr;
6824 bpi->uptime = bgp_clock();
d62a17ae 6825
6826 /* Process change. */
40381db7 6827 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 6828 SAFI_UNICAST);
6829 bgp_process(bgp, bn, afi, SAFI_UNICAST);
6830 bgp_unlock_node(bn);
6831 aspath_unintern(&attr.aspath);
ddb5b488
PZ
6832
6833 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6834 || (bgp->inst_type
6835 == BGP_INSTANCE_TYPE_DEFAULT)) {
6836
6837 vpn_leak_from_vrf_update(
40381db7 6838 bgp_get_default(), bgp, bpi);
ddb5b488 6839 }
d62a17ae 6840 return;
6841 }
6842 }
6843
6844 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
6845 bgp->peer_self, new_attr, bn);
1defdda8 6846 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 6847
6848 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 6849 bgp_path_info_add(bn, new);
d62a17ae 6850 bgp_unlock_node(bn);
6851 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
6852
6853 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6854 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6855
6856 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6857 }
d62a17ae 6858 }
6859
6860 /* Unintern original. */
6861 aspath_unintern(&attr.aspath);
718e3744 6862}
6863
d7c0a89a
QY
6864void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
6865 unsigned short instance)
718e3744 6866{
d62a17ae 6867 afi_t afi;
6868 struct bgp_node *rn;
40381db7 6869 struct bgp_path_info *pi;
d62a17ae 6870 struct bgp_redist *red;
718e3744 6871
d62a17ae 6872 afi = family2afi(p->family);
718e3744 6873
d62a17ae 6874 red = bgp_redist_lookup(bgp, afi, type, instance);
6875 if (red) {
6876 rn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
6877 SAFI_UNICAST, p, NULL);
6878
6f94b685 6879 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7 6880 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 6881 break;
6882
40381db7 6883 if (pi) {
ddb5b488
PZ
6884 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6885 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6886
6887 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 6888 bgp, pi);
ddb5b488 6889 }
40381db7
DS
6890 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
6891 bgp_path_info_delete(rn, pi);
d62a17ae 6892 bgp_process(bgp, rn, afi, SAFI_UNICAST);
6893 }
6894 bgp_unlock_node(rn);
6895 }
6896}
6897
6898/* Withdraw specified route type's route. */
6899void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 6900 unsigned short instance)
d62a17ae 6901{
6902 struct bgp_node *rn;
40381db7 6903 struct bgp_path_info *pi;
d62a17ae 6904 struct bgp_table *table;
6905
6906 table = bgp->rib[afi][SAFI_UNICAST];
6907
6908 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685 6909 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
6910 if (pi->peer == bgp->peer_self && pi->type == type
6911 && pi->instance == instance)
d62a17ae 6912 break;
6913
40381db7 6914 if (pi) {
ddb5b488
PZ
6915 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6916 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6917
6918 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 6919 bgp, pi);
ddb5b488 6920 }
40381db7 6921 bgp_aggregate_decrement(bgp, &rn->p, pi, afi,
d62a17ae 6922 SAFI_UNICAST);
40381db7 6923 bgp_path_info_delete(rn, pi);
d62a17ae 6924 bgp_process(bgp, rn, afi, SAFI_UNICAST);
6925 }
718e3744 6926 }
718e3744 6927}
6b0655a2 6928
718e3744 6929/* Static function to display route. */
9c92b5f7
MK
6930static void route_vty_out_route(struct prefix *p, struct vty *vty,
6931 json_object *json)
718e3744 6932{
be054588 6933 int len = 0;
d62a17ae 6934 char buf[BUFSIZ];
50e05855 6935 char buf2[BUFSIZ];
718e3744 6936
d62a17ae 6937 if (p->family == AF_INET) {
c6462ff4 6938 if (!json) {
89e5e9f0
PM
6939 len = vty_out(
6940 vty, "%s/%d",
6941 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
6942 p->prefixlen);
c6462ff4
MK
6943 } else {
6944 json_object_string_add(json, "prefix",
6945 inet_ntop(p->family,
6946 &p->u.prefix, buf,
6947 BUFSIZ));
6948 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 6949 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 6950 json_object_string_add(json, "network", buf2);
c6462ff4 6951 }
d62a17ae 6952 } else if (p->family == AF_ETHERNET) {
b03b8898
DS
6953 prefix2str(p, buf, PREFIX_STRLEN);
6954 len = vty_out(vty, "%s", buf);
6955 } else if (p->family == AF_EVPN) {
57f7feb6 6956 if (!json)
60466a63
QY
6957 len = vty_out(
6958 vty, "%s",
6959 bgp_evpn_route2str((struct prefix_evpn *)p, buf,
6960 BUFSIZ));
57f7feb6 6961 else
60466a63 6962 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
6963 } else if (p->family == AF_FLOWSPEC) {
6964 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
6965 json ?
6966 NLRI_STRING_FORMAT_JSON_SIMPLE :
6967 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 6968 } else {
c6462ff4 6969 if (!json)
60466a63
QY
6970 len = vty_out(
6971 vty, "%s/%d",
6972 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
6973 p->prefixlen);
50e05855
AD
6974 else {
6975 json_object_string_add(json, "prefix",
6976 inet_ntop(p->family,
6977 &p->u.prefix, buf,
6978 BUFSIZ));
6979 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
6980 prefix2str(p, buf2, PREFIX_STRLEN);
6981 json_object_string_add(json, "network", buf2);
6982 }
9c92b5f7 6983 }
d62a17ae 6984
9c92b5f7
MK
6985 if (!json) {
6986 len = 17 - len;
6987 if (len < 1)
6988 vty_out(vty, "\n%*s", 20, " ");
6989 else
6990 vty_out(vty, "%*s", len, " ");
6991 }
718e3744 6992}
6993
d62a17ae 6994enum bgp_display_type {
6995 normal_list,
718e3744 6996};
6997
18ee8310 6998/* Print the short form route status for a bgp_path_info */
4b7e6066 6999static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 7000 struct bgp_path_info *path,
d62a17ae 7001 json_object *json_path)
718e3744 7002{
d62a17ae 7003 if (json_path) {
b05a1c8b 7004
d62a17ae 7005 /* Route status display. */
9b6d8fcf 7006 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7007 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 7008
9b6d8fcf 7009 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7010 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 7011
9b6d8fcf 7012 if (path->extra && path->extra->suppress)
d62a17ae 7013 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 7014
9b6d8fcf
DS
7015 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7016 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7017 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 7018
d62a17ae 7019 /* Selected */
9b6d8fcf 7020 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7021 json_object_boolean_true_add(json_path, "history");
b05a1c8b 7022
9b6d8fcf 7023 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7024 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 7025
9b6d8fcf 7026 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7027 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b 7028
9b6d8fcf 7029 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7030 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 7031
d62a17ae 7032 /* Internal route. */
9b6d8fcf
DS
7033 if ((path->peer->as)
7034 && (path->peer->as == path->peer->local_as))
d62a17ae 7035 json_object_string_add(json_path, "pathFrom",
7036 "internal");
7037 else
7038 json_object_string_add(json_path, "pathFrom",
7039 "external");
b05a1c8b 7040
d62a17ae 7041 return;
7042 }
b05a1c8b 7043
d62a17ae 7044 /* Route status display. */
9b6d8fcf 7045 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7046 vty_out(vty, "R");
9b6d8fcf 7047 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7048 vty_out(vty, "S");
9b6d8fcf 7049 else if (path->extra && path->extra->suppress)
d62a17ae 7050 vty_out(vty, "s");
9b6d8fcf
DS
7051 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7052 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7053 vty_out(vty, "*");
7054 else
7055 vty_out(vty, " ");
7056
7057 /* Selected */
9b6d8fcf 7058 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7059 vty_out(vty, "h");
9b6d8fcf 7060 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7061 vty_out(vty, "d");
9b6d8fcf 7062 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7063 vty_out(vty, ">");
9b6d8fcf 7064 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7065 vty_out(vty, "=");
7066 else
7067 vty_out(vty, " ");
718e3744 7068
d62a17ae 7069 /* Internal route. */
9b6d8fcf
DS
7070 if (path->peer && (path->peer->as)
7071 && (path->peer->as == path->peer->local_as))
d62a17ae 7072 vty_out(vty, "i");
7073 else
7074 vty_out(vty, " ");
b40d939b 7075}
7076
25b5da8d
DA
7077static char *bgp_nexthop_fqdn(struct peer *peer)
7078{
7079 if (peer->hostname && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
7080 return peer->hostname;
7081 return NULL;
7082}
7083
b40d939b 7084/* called from terminal list command */
4b7e6066 7085void route_vty_out(struct vty *vty, struct prefix *p,
9b6d8fcf 7086 struct bgp_path_info *path, int display, safi_t safi,
4b7e6066 7087 json_object *json_paths)
d62a17ae 7088{
7089 struct attr *attr;
7090 json_object *json_path = NULL;
7091 json_object *json_nexthops = NULL;
7092 json_object *json_nexthop_global = NULL;
7093 json_object *json_nexthop_ll = NULL;
6f214dd3 7094 json_object *json_ext_community = NULL;
9df8b37c 7095 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 7096 bool nexthop_self =
9b6d8fcf 7097 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 7098 bool nexthop_othervrf = false;
43089216 7099 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 7100 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
25b5da8d 7101 char *nexthop_fqdn = bgp_nexthop_fqdn(path->peer);
d62a17ae 7102
7103 if (json_paths)
7104 json_path = json_object_new_object();
7105
7106 /* short status lead text */
9b6d8fcf 7107 route_vty_short_status_out(vty, path, json_path);
d62a17ae 7108
7109 if (!json_paths) {
7110 /* print prefix and mask */
7111 if (!display)
9c92b5f7 7112 route_vty_out_route(p, vty, json_path);
d62a17ae 7113 else
7114 vty_out(vty, "%*s", 17, " ");
9c92b5f7 7115 } else {
b682f6de 7116 route_vty_out_route(p, vty, json_path);
d62a17ae 7117 }
47fc97cc 7118
d62a17ae 7119 /* Print attribute */
9b6d8fcf 7120 attr = path->attr;
445c2480 7121
9df8b37c
PZ
7122 /*
7123 * If vrf id of nexthop is different from that of prefix,
7124 * set up printable string to append
7125 */
9b6d8fcf 7126 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
7127 const char *self = "";
7128
7129 if (nexthop_self)
7130 self = "<";
7131
7132 nexthop_othervrf = true;
9b6d8fcf 7133 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 7134
9b6d8fcf 7135 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
7136 snprintf(vrf_id_str, sizeof(vrf_id_str),
7137 "@%s%s", VRFID_NONE_STR, self);
7138 else
7139 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 7140 path->extra->bgp_orig->vrf_id, self);
9df8b37c 7141
9b6d8fcf
DS
7142 if (path->extra->bgp_orig->inst_type
7143 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 7144
9b6d8fcf 7145 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
7146 } else {
7147 const char *self = "";
7148
7149 if (nexthop_self)
7150 self = "<";
7151
7152 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
7153 }
7154
445c2480
DS
7155 /*
7156 * For ENCAP and EVPN routes, nexthop address family is not
7157 * neccessarily the same as the prefix address family.
7158 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7159 * EVPN routes are also exchanged with a MP nexthop. Currently,
7160 * this
7161 * is only IPv4, the value will be present in either
7162 * attr->nexthop or
7163 * attr->mp_nexthop_global_in
7164 */
7165 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
7166 char buf[BUFSIZ];
7167 char nexthop[128];
7168 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
7169
7170 switch (af) {
7171 case AF_INET:
7172 sprintf(nexthop, "%s",
a4d82a8a
PZ
7173 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
7174 BUFSIZ));
445c2480
DS
7175 break;
7176 case AF_INET6:
7177 sprintf(nexthop, "%s",
a4d82a8a
PZ
7178 inet_ntop(af, &attr->mp_nexthop_global, buf,
7179 BUFSIZ));
445c2480
DS
7180 break;
7181 default:
7182 sprintf(nexthop, "?");
7183 break;
d62a17ae 7184 }
d62a17ae 7185
445c2480
DS
7186 if (json_paths) {
7187 json_nexthop_global = json_object_new_object();
7188
25b5da8d
DA
7189 json_object_string_add(
7190 json_nexthop_global, "afi",
7191 nexthop_fqdn ? "fqdn"
7192 : (af == AF_INET) ? "ip" : "ipv6");
7193 json_object_string_add(
7194 json_nexthop_global,
7195 nexthop_fqdn ? "fqdn"
7196 : (af == AF_INET) ? "ip" : "ipv6",
7197 nexthop_fqdn ? nexthop_fqdn : nexthop);
445c2480
DS
7198 json_object_boolean_true_add(json_nexthop_global,
7199 "used");
7200 } else
25b5da8d
DA
7201 vty_out(vty, "%s%s",
7202 nexthop_fqdn ? nexthop_fqdn : nexthop,
7203 vrf_id_str);
445c2480
DS
7204 } else if (safi == SAFI_EVPN) {
7205 if (json_paths) {
7206 json_nexthop_global = json_object_new_object();
7207
25b5da8d
DA
7208 json_object_string_add(
7209 json_nexthop_global,
7210 nexthop_fqdn ? "fqdn" : "ip",
7211 nexthop_fqdn ? nexthop_fqdn
7212 : inet_ntoa(attr->nexthop));
a4d82a8a
PZ
7213 json_object_string_add(json_nexthop_global, "afi",
7214 "ipv4");
445c2480
DS
7215 json_object_boolean_true_add(json_nexthop_global,
7216 "used");
7217 } else
25b5da8d
DA
7218 vty_out(vty, "%-16s%s",
7219 nexthop_fqdn ?: inet_ntoa(attr->nexthop),
9df8b37c 7220 vrf_id_str);
d33fc23b 7221 } else if (safi == SAFI_FLOWSPEC) {
026b914a
PG
7222 if (attr->nexthop.s_addr != 0) {
7223 if (json_paths) {
7224 json_nexthop_global = json_object_new_object();
7225 json_object_string_add(
25b5da8d
DA
7226 json_nexthop_global,
7227 nexthop_fqdn ? "fqdn" : "ip",
7228 nexthop_fqdn
7229 ? nexthop_fqdn
7230 : inet_ntoa(attr->nexthop));
026b914a
PG
7231 json_object_string_add(json_nexthop_global,
7232 "afi", "ipv4");
50e05855
AD
7233 json_object_boolean_true_add(
7234 json_nexthop_global,
026b914a
PG
7235 "used");
7236 } else {
25b5da8d
DA
7237 vty_out(vty, "%-16s",
7238 nexthop_fqdn
7239 ? nexthop_fqdn
7240 : inet_ntoa(attr->nexthop));
026b914a
PG
7241 }
7242 }
d33fc23b 7243 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
7244 if (json_paths) {
7245 json_nexthop_global = json_object_new_object();
d62a17ae 7246
22df2d8a
DS
7247 json_object_string_add(json_nexthop_global,
7248 nexthop_fqdn ? "fqdn" : "ip",
7249 nexthop_fqdn
7250 ? nexthop_fqdn
7251 : inet_ntoa(attr->nexthop));
445c2480 7252
a4d82a8a
PZ
7253 json_object_string_add(json_nexthop_global, "afi",
7254 "ipv4");
445c2480
DS
7255 json_object_boolean_true_add(json_nexthop_global,
7256 "used");
7257 } else {
9df8b37c
PZ
7258 char buf[BUFSIZ];
7259
d87ff2dd 7260 snprintf(buf, sizeof(buf), "%s%s",
25b5da8d
DA
7261 nexthop_fqdn ? nexthop_fqdn
7262 : inet_ntoa(attr->nexthop),
7263 vrf_id_str);
9df8b37c 7264 vty_out(vty, "%-16s", buf);
d62a17ae 7265 }
445c2480 7266 }
b05a1c8b 7267
445c2480 7268 /* IPv6 Next Hop */
a4d82a8a 7269 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
7270 int len;
7271 char buf[BUFSIZ];
d62a17ae 7272
445c2480
DS
7273 if (json_paths) {
7274 json_nexthop_global = json_object_new_object();
a4d82a8a 7275 json_object_string_add(
25b5da8d
DA
7276 json_nexthop_global,
7277 nexthop_fqdn ? "fqdn" : "ip",
7278 nexthop_fqdn
7279 ? nexthop_fqdn
7280 : inet_ntop(AF_INET6,
7281 &attr->mp_nexthop_global,
7282 buf, BUFSIZ));
a4d82a8a
PZ
7283 json_object_string_add(json_nexthop_global, "afi",
7284 "ipv6");
7285 json_object_string_add(json_nexthop_global, "scope",
7286 "global");
445c2480
DS
7287
7288 /* We display both LL & GL if both have been
7289 * received */
0606039c
DA
7290 if ((attr->mp_nexthop_len
7291 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 7292 || (path->peer->conf_if)) {
a4d82a8a 7293 json_nexthop_ll = json_object_new_object();
d62a17ae 7294 json_object_string_add(
25b5da8d
DA
7295 json_nexthop_ll,
7296 nexthop_fqdn ? "fqdn" : "ip",
7297 nexthop_fqdn
7298 ? nexthop_fqdn
7299 : inet_ntop(
7300 AF_INET6,
7301 &attr->mp_nexthop_local,
7302 buf, BUFSIZ));
a4d82a8a
PZ
7303 json_object_string_add(json_nexthop_ll, "afi",
7304 "ipv6");
7305 json_object_string_add(json_nexthop_ll, "scope",
445c2480 7306 "link-local");
d62a17ae 7307
a4d82a8a
PZ
7308 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
7309 &attr->mp_nexthop_local)
445c2480
DS
7310 != 0)
7311 && !attr->mp_nexthop_prefer_global)
d62a17ae 7312 json_object_boolean_true_add(
a4d82a8a 7313 json_nexthop_ll, "used");
445c2480
DS
7314 else
7315 json_object_boolean_true_add(
a4d82a8a 7316 json_nexthop_global, "used");
445c2480
DS
7317 } else
7318 json_object_boolean_true_add(
7319 json_nexthop_global, "used");
7320 } else {
7321 /* Display LL if LL/Global both in table unless
7322 * prefer-global is set */
0606039c
DA
7323 if (((attr->mp_nexthop_len
7324 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 7325 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
7326 || (path->peer->conf_if)) {
7327 if (path->peer->conf_if) {
a4d82a8a 7328 len = vty_out(vty, "%s",
9b6d8fcf 7329 path->peer->conf_if);
445c2480
DS
7330 len = 16 - len; /* len of IPv6
7331 addr + max
7332 len of def
7333 ifname */
7334
7335 if (len < 1)
a4d82a8a 7336 vty_out(vty, "\n%*s", 36, " ");
445c2480 7337 else
a4d82a8a 7338 vty_out(vty, "%*s", len, " ");
d62a17ae 7339 } else {
7340 len = vty_out(
9df8b37c 7341 vty, "%s%s",
25b5da8d
DA
7342 nexthop_fqdn
7343 ? nexthop_fqdn
7344 : inet_ntop(
7345 AF_INET6,
7346 &attr->mp_nexthop_local,
7347 buf, BUFSIZ),
9df8b37c 7348 vrf_id_str);
d62a17ae 7349 len = 16 - len;
7350
7351 if (len < 1)
a4d82a8a 7352 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 7353 else
a4d82a8a 7354 vty_out(vty, "%*s", len, " ");
d62a17ae 7355 }
445c2480 7356 } else {
a4d82a8a 7357 len = vty_out(
9df8b37c 7358 vty, "%s%s",
25b5da8d
DA
7359 nexthop_fqdn
7360 ? nexthop_fqdn
7361 : inet_ntop(
7362 AF_INET6,
7363 &attr->mp_nexthop_global,
7364 buf, BUFSIZ),
7365 vrf_id_str);
445c2480
DS
7366 len = 16 - len;
7367
7368 if (len < 1)
7369 vty_out(vty, "\n%*s", 36, " ");
7370 else
7371 vty_out(vty, "%*s", len, " ");
d62a17ae 7372 }
7373 }
445c2480 7374 }
718e3744 7375
445c2480
DS
7376 /* MED/Metric */
7377 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
50e05855
AD
7378 if (json_paths) {
7379
7380 /*
7381 * Adding "metric" field to match with corresponding
7382 * CLI. "med" will be deprecated in future.
7383 */
a4d82a8a 7384 json_object_int_add(json_path, "med", attr->med);
50e05855
AD
7385 json_object_int_add(json_path, "metric", attr->med);
7386 } else
445c2480
DS
7387 vty_out(vty, "%10u", attr->med);
7388 else if (!json_paths)
7389 vty_out(vty, " ");
d62a17ae 7390
445c2480
DS
7391 /* Local Pref */
7392 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855
AD
7393 if (json_paths) {
7394
7395 /*
7396 * Adding "locPrf" field to match with corresponding
7397 * CLI. "localPref" will be deprecated in future.
7398 */
445c2480
DS
7399 json_object_int_add(json_path, "localpref",
7400 attr->local_pref);
50e05855
AD
7401 json_object_int_add(json_path, "locPrf",
7402 attr->local_pref);
7403 } else
445c2480
DS
7404 vty_out(vty, "%7u", attr->local_pref);
7405 else if (!json_paths)
7406 vty_out(vty, " ");
d62a17ae 7407
445c2480
DS
7408 if (json_paths)
7409 json_object_int_add(json_path, "weight", attr->weight);
7410 else
7411 vty_out(vty, "%7u ", attr->weight);
47fc97cc 7412
445c2480
DS
7413 if (json_paths) {
7414 char buf[BUFSIZ];
a4d82a8a
PZ
7415 json_object_string_add(
7416 json_path, "peerId",
9b6d8fcf 7417 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 7418 }
b05a1c8b 7419
445c2480
DS
7420 /* Print aspath */
7421 if (attr->aspath) {
50e05855
AD
7422 if (json_paths) {
7423
7424 /*
7425 * Adding "path" field to match with corresponding
7426 * CLI. "aspath" will be deprecated in future.
7427 */
445c2480
DS
7428 json_object_string_add(json_path, "aspath",
7429 attr->aspath->str);
50e05855
AD
7430 json_object_string_add(json_path, "path",
7431 attr->aspath->str);
7432 } else
445c2480 7433 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 7434 }
f1aa5d8a 7435
445c2480
DS
7436 /* Print origin */
7437 if (json_paths)
a4d82a8a
PZ
7438 json_object_string_add(json_path, "origin",
7439 bgp_origin_long_str[attr->origin]);
445c2480
DS
7440 else
7441 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7442
9df8b37c 7443 if (json_paths) {
6f214dd3
CS
7444 if (safi == SAFI_EVPN &&
7445 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7446 json_ext_community = json_object_new_object();
7447 json_object_string_add(json_ext_community,
7448 "string",
7449 attr->ecommunity->str);
7450 json_object_object_add(json_path,
7451 "extendedCommunity",
7452 json_ext_community);
7453 }
7454
9df8b37c
PZ
7455 if (nexthop_self)
7456 json_object_boolean_true_add(json_path,
7457 "announceNexthopSelf");
7458 if (nexthop_othervrf) {
7459 json_object_string_add(json_path, "nhVrfName",
7460 nexthop_vrfname);
7461
7462 json_object_int_add(json_path, "nhVrfId",
7463 ((nexthop_vrfid == VRF_UNKNOWN)
7464 ? -1
7465 : (int)nexthop_vrfid));
7466 }
7467 }
7468
d62a17ae 7469 if (json_paths) {
7470 if (json_nexthop_global || json_nexthop_ll) {
7471 json_nexthops = json_object_new_array();
f1aa5d8a 7472
d62a17ae 7473 if (json_nexthop_global)
7474 json_object_array_add(json_nexthops,
7475 json_nexthop_global);
f1aa5d8a 7476
d62a17ae 7477 if (json_nexthop_ll)
7478 json_object_array_add(json_nexthops,
7479 json_nexthop_ll);
f1aa5d8a 7480
d62a17ae 7481 json_object_object_add(json_path, "nexthops",
7482 json_nexthops);
7483 }
7484
7485 json_object_array_add(json_paths, json_path);
7486 } else {
7487 vty_out(vty, "\n");
6f214dd3
CS
7488
7489 if (safi == SAFI_EVPN &&
7490 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7491 vty_out(vty, "%*s", 20, " ");
7492 vty_out(vty, "%s\n", attr->ecommunity->str);
7493 }
7494
65efcfce 7495#if ENABLE_BGP_VNC
d62a17ae 7496 /* prints an additional line, indented, with VNC info, if
7497 * present */
7498 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 7499 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 7500#endif
d62a17ae 7501 }
7502}
718e3744 7503
7504/* called from terminal list command */
d62a17ae 7505void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr,
9f049418 7506 safi_t safi, bool use_json, json_object *json_ar)
d62a17ae 7507{
7508 json_object *json_status = NULL;
7509 json_object *json_net = NULL;
7510 char buff[BUFSIZ];
dc387b0f 7511
d62a17ae 7512 /* Route status display. */
7513 if (use_json) {
7514 json_status = json_object_new_object();
7515 json_net = json_object_new_object();
7516 } else {
7517 vty_out(vty, "*");
7518 vty_out(vty, ">");
7519 vty_out(vty, " ");
7520 }
718e3744 7521
d62a17ae 7522 /* print prefix and mask */
50e05855 7523 if (use_json) {
dc387b0f
LK
7524 if (safi == SAFI_EVPN)
7525 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
7526 else if (p->family == AF_INET || p->family == AF_INET6) {
7527 json_object_string_add(
7528 json_net, "addrPrefix",
7529 inet_ntop(p->family, &p->u.prefix, buff,
7530 BUFSIZ));
7531 json_object_int_add(json_net, "prefixLen",
7532 p->prefixlen);
7533 prefix2str(p, buff, PREFIX_STRLEN);
7534 json_object_string_add(json_net, "network", buff);
7535 }
50e05855 7536 } else
9c92b5f7 7537 route_vty_out_route(p, vty, NULL);
d62a17ae 7538
7539 /* Print attribute */
7540 if (attr) {
7541 if (use_json) {
7542 if (p->family == AF_INET
7543 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 7544 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 7545 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 7546 json_object_string_add(
7547 json_net, "nextHop",
7548 inet_ntoa(
7549 attr->mp_nexthop_global_in));
7550 else
7551 json_object_string_add(
7552 json_net, "nextHop",
7553 inet_ntoa(attr->nexthop));
7554 } else if (p->family == AF_INET6
7555 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
7556 char buf[BUFSIZ];
7557
7558 json_object_string_add(
aa0a10fc 7559 json_net, "nextHopGlobal",
d62a17ae 7560 inet_ntop(AF_INET6,
7561 &attr->mp_nexthop_global, buf,
7562 BUFSIZ));
dc387b0f
LK
7563 } else if (p->family == AF_EVPN &&
7564 !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
7565 json_object_string_add(json_net,
7566 "nextHop", inet_ntoa(
7567 attr->mp_nexthop_global_in));
d62a17ae 7568
7569 if (attr->flag
7570 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
7571 json_object_int_add(json_net, "metric",
7572 attr->med);
7573
50e05855
AD
7574 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
7575
7576 /*
7577 * Adding "locPrf" field to match with
7578 * corresponding CLI. "localPref" will be
7579 * deprecated in future.
7580 */
d62a17ae 7581 json_object_int_add(json_net, "localPref",
7582 attr->local_pref);
50e05855
AD
7583 json_object_int_add(json_net, "locPrf",
7584 attr->local_pref);
7585 }
d62a17ae 7586
7587 json_object_int_add(json_net, "weight", attr->weight);
7588
7589 /* Print aspath */
50e05855
AD
7590 if (attr->aspath) {
7591
7592 /*
7593 * Adding "path" field to match with
7594 * corresponding CLI. "localPref" will be
7595 * deprecated in future.
7596 */
d62a17ae 7597 json_object_string_add(json_net, "asPath",
7598 attr->aspath->str);
50e05855
AD
7599 json_object_string_add(json_net, "path",
7600 attr->aspath->str);
7601 }
d62a17ae 7602
7603 /* Print origin */
7604 json_object_string_add(json_net, "bgpOriginCode",
7605 bgp_origin_str[attr->origin]);
7606 } else {
7607 if (p->family == AF_INET
7608 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7609 || safi == SAFI_EVPN
7610 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7611 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7612 || safi == SAFI_EVPN)
7613 vty_out(vty, "%-16s",
7614 inet_ntoa(
7615 attr->mp_nexthop_global_in));
7616 else
7617 vty_out(vty, "%-16s",
7618 inet_ntoa(attr->nexthop));
7619 } else if (p->family == AF_INET6
7620 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
7621 int len;
7622 char buf[BUFSIZ];
7623
7624 len = vty_out(
7625 vty, "%s",
7626 inet_ntop(AF_INET6,
7627 &attr->mp_nexthop_global, buf,
7628 BUFSIZ));
7629 len = 16 - len;
7630 if (len < 1)
7631 vty_out(vty, "\n%*s", 36, " ");
7632 else
7633 vty_out(vty, "%*s", len, " ");
7634 }
7635 if (attr->flag
7636 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
7637 vty_out(vty, "%10u", attr->med);
7638 else
7639 vty_out(vty, " ");
718e3744 7640
d62a17ae 7641 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
7642 vty_out(vty, "%7u", attr->local_pref);
7643 else
7644 vty_out(vty, " ");
7645
7646 vty_out(vty, "%7u ", attr->weight);
7647
7648 /* Print aspath */
7649 if (attr->aspath)
7650 aspath_print_vty(vty, "%s", attr->aspath, " ");
7651
7652 /* Print origin */
7653 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7654 }
7655 }
7656 if (use_json) {
7657 json_object_boolean_true_add(json_status, "*");
7658 json_object_boolean_true_add(json_status, ">");
7659 json_object_object_add(json_net, "appliedStatusSymbols",
7660 json_status);
1608ff77 7661
dc387b0f
LK
7662 prefix2str(p, buff, PREFIX_STRLEN);
7663 json_object_object_add(json_ar, buff, json_net);
d62a17ae 7664 } else
7665 vty_out(vty, "\n");
7666}
7667
7668void route_vty_out_tag(struct vty *vty, struct prefix *p,
9b6d8fcf 7669 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 7670 json_object *json)
7671{
7672 json_object *json_out = NULL;
7673 struct attr *attr;
7674 mpls_label_t label = MPLS_INVALID_LABEL;
7675
9b6d8fcf 7676 if (!path->extra)
d62a17ae 7677 return;
7678
7679 if (json)
7680 json_out = json_object_new_object();
7681
7682 /* short status lead text */
9b6d8fcf 7683 route_vty_short_status_out(vty, path, json_out);
d62a17ae 7684
7685 /* print prefix and mask */
7686 if (json == NULL) {
7687 if (!display)
9c92b5f7 7688 route_vty_out_route(p, vty, NULL);
d62a17ae 7689 else
7690 vty_out(vty, "%*s", 17, " ");
7691 }
7692
7693 /* Print attribute */
9b6d8fcf 7694 attr = path->attr;
05864da7
DS
7695 if (((p->family == AF_INET)
7696 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
7697 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
7698 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7699 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7700 || safi == SAFI_EVPN) {
7701 if (json)
7702 json_object_string_add(
7703 json_out, "mpNexthopGlobalIn",
7704 inet_ntoa(attr->mp_nexthop_global_in));
7705 else
7706 vty_out(vty, "%-16s",
7707 inet_ntoa(attr->mp_nexthop_global_in));
7708 } else {
7709 if (json)
7710 json_object_string_add(
7711 json_out, "nexthop",
7712 inet_ntoa(attr->nexthop));
7713 else
7714 vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
7715 }
7716 } else if (((p->family == AF_INET6)
7717 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
7718 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
7719 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7720 char buf_a[512];
7721
7722 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
7723 if (json)
7724 json_object_string_add(
7725 json_out, "mpNexthopGlobalIn",
7726 inet_ntop(AF_INET6,
7727 &attr->mp_nexthop_global,
7728 buf_a, sizeof(buf_a)));
7729 else
7730 vty_out(vty, "%s",
7731 inet_ntop(AF_INET6,
7732 &attr->mp_nexthop_global,
7733 buf_a, sizeof(buf_a)));
7734 } else if (attr->mp_nexthop_len
7735 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
7736 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
7737 &attr->mp_nexthop_global,
7738 &attr->mp_nexthop_local);
7739 if (json)
7740 json_object_string_add(json_out,
7741 "mpNexthopGlobalLocal",
7742 buf_a);
7743 else
7744 vty_out(vty, "%s", buf_a);
d62a17ae 7745 }
7746 }
7747
9b6d8fcf 7748 label = decode_label(&path->extra->label[0]);
d62a17ae 7749
7750 if (bgp_is_valid_label(&label)) {
7751 if (json) {
7752 json_object_int_add(json_out, "notag", label);
7753 json_object_array_add(json, json_out);
7754 } else {
7755 vty_out(vty, "notag/%d", label);
7756 vty_out(vty, "\n");
7757 }
7758 }
7759}
718e3744 7760
d62a17ae 7761void route_vty_out_overlay(struct vty *vty, struct prefix *p,
9b6d8fcf 7762 struct bgp_path_info *path, int display,
d62a17ae 7763 json_object *json_paths)
718e3744 7764{
d62a17ae 7765 struct attr *attr;
14f51eba 7766 char buf[BUFSIZ] = {0};
d62a17ae 7767 json_object *json_path = NULL;
14f51eba
LK
7768 json_object *json_nexthop = NULL;
7769 json_object *json_overlay = NULL;
856ca177 7770
9b6d8fcf 7771 if (!path->extra)
d62a17ae 7772 return;
718e3744 7773
14f51eba
LK
7774 if (json_paths) {
7775 json_path = json_object_new_object();
7776 json_overlay = json_object_new_object();
7777 json_nexthop = json_object_new_object();
7778 }
7779
d62a17ae 7780 /* short status lead text */
9b6d8fcf 7781 route_vty_short_status_out(vty, path, json_path);
856ca177 7782
d62a17ae 7783 /* print prefix and mask */
7784 if (!display)
14f51eba 7785 route_vty_out_route(p, vty, json_path);
d62a17ae 7786 else
7787 vty_out(vty, "%*s", 17, " ");
7788
7789 /* Print attribute */
9b6d8fcf 7790 attr = path->attr;
05864da7
DS
7791 char buf1[BUFSIZ];
7792 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 7793
05864da7
DS
7794 switch (af) {
7795 case AF_INET:
7796 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
7797 if (!json_path) {
7798 vty_out(vty, "%-16s", buf);
7799 } else {
7800 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 7801
05864da7 7802 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 7803
05864da7
DS
7804 json_object_object_add(json_path, "nexthop",
7805 json_nexthop);
7806 }
7807 break;
7808 case AF_INET6:
7809 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
7810 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
7811 if (!json_path) {
7812 vty_out(vty, "%s(%s)", buf, buf1);
7813 } else {
7814 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 7815
05864da7
DS
7816 json_object_string_add(json_nexthop, "ipv6LinkLocal",
7817 buf1);
14f51eba 7818
05864da7 7819 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 7820
05864da7
DS
7821 json_object_object_add(json_path, "nexthop",
7822 json_nexthop);
7823 }
7824 break;
7825 default:
7826 if (!json_path) {
7827 vty_out(vty, "?");
7828 } else {
7829 json_object_string_add(json_nexthop, "Error",
7830 "Unsupported address-family");
d62a17ae 7831 }
05864da7 7832 }
988258b4 7833
05864da7 7834 char *str = esi2str(&(attr->evpn_overlay.eth_s_id));
988258b4 7835
05864da7
DS
7836 if (!json_path)
7837 vty_out(vty, "%s", str);
7838 else
7839 json_object_string_add(json_overlay, "esi", str);
25b5da8d 7840
05864da7 7841 XFREE(MTYPE_TMP, str);
988258b4 7842
05864da7
DS
7843 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
7844 inet_ntop(AF_INET, &(attr->evpn_overlay.gw_ip.ipv4), buf,
7845 BUFSIZ);
7846 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
7847 inet_ntop(AF_INET6, &(attr->evpn_overlay.gw_ip.ipv6), buf,
7848 BUFSIZ);
7849 }
14f51eba 7850
05864da7
DS
7851 if (!json_path)
7852 vty_out(vty, "/%s", buf);
7853 else
7854 json_object_string_add(json_overlay, "gw", buf);
7855
7856 if (attr->ecommunity) {
7857 char *mac = NULL;
7858 struct ecommunity_val *routermac = ecommunity_lookup(
7859 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
7860 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
7861
7862 if (routermac)
7863 mac = ecom_mac2str((char *)routermac->val);
7864 if (mac) {
7865 if (!json_path) {
7866 vty_out(vty, "/%s", (char *)mac);
7867 } else {
7868 json_object_string_add(json_overlay, "rmac",
7869 mac);
988258b4 7870 }
05864da7 7871 XFREE(MTYPE_TMP, mac);
988258b4 7872 }
05864da7 7873 }
718e3744 7874
05864da7
DS
7875 if (!json_path) {
7876 vty_out(vty, "\n");
7877 } else {
7878 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 7879
05864da7 7880 json_object_array_add(json_paths, json_path);
14f51eba 7881 }
d62a17ae 7882}
718e3744 7883
d62a17ae 7884/* dampening route */
7885static void damp_route_vty_out(struct vty *vty, struct prefix *p,
9b6d8fcf 7886 struct bgp_path_info *path, int display,
4b7e6066 7887 safi_t safi, bool use_json, json_object *json)
d62a17ae 7888{
7889 struct attr *attr;
7890 int len;
7891 char timebuf[BGP_UPTIME_LEN];
7892
7893 /* short status lead text */
9b6d8fcf 7894 route_vty_short_status_out(vty, path, json);
d62a17ae 7895
7896 /* print prefix and mask */
7897 if (!use_json) {
7898 if (!display)
9c92b5f7 7899 route_vty_out_route(p, vty, NULL);
d62a17ae 7900 else
7901 vty_out(vty, "%*s", 17, " ");
7902 }
7903
9b6d8fcf 7904 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 7905 len = 17 - len;
7906 if (len < 1) {
7907 if (!use_json)
7908 vty_out(vty, "\n%*s", 34, " ");
7909 } else {
7910 if (use_json)
7911 json_object_int_add(json, "peerHost", len);
7912 else
7913 vty_out(vty, "%*s", len, " ");
7914 }
7915
7916 if (use_json)
9b6d8fcf 7917 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN,
d62a17ae 7918 use_json, json);
7919 else
9b6d8fcf
DS
7920 vty_out(vty, "%s ",
7921 bgp_damp_reuse_time_vty(vty, path, timebuf,
7922 BGP_UPTIME_LEN, use_json,
7923 json));
d62a17ae 7924
7925 /* Print attribute */
9b6d8fcf 7926 attr = path->attr;
d62a17ae 7927
05864da7
DS
7928 /* Print aspath */
7929 if (attr->aspath) {
d62a17ae 7930 if (use_json)
05864da7
DS
7931 json_object_string_add(json, "asPath",
7932 attr->aspath->str);
d62a17ae 7933 else
05864da7 7934 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 7935 }
05864da7
DS
7936
7937 /* Print origin */
7938 if (use_json)
7939 json_object_string_add(json, "origin",
7940 bgp_origin_str[attr->origin]);
7941 else
7942 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7943
d62a17ae 7944 if (!use_json)
7945 vty_out(vty, "\n");
7946}
718e3744 7947
d62a17ae 7948/* flap route */
7949static void flap_route_vty_out(struct vty *vty, struct prefix *p,
9b6d8fcf 7950 struct bgp_path_info *path, int display,
4b7e6066 7951 safi_t safi, bool use_json, json_object *json)
784d3a42 7952{
d62a17ae 7953 struct attr *attr;
7954 struct bgp_damp_info *bdi;
7955 char timebuf[BGP_UPTIME_LEN];
7956 int len;
784d3a42 7957
9b6d8fcf 7958 if (!path->extra)
d62a17ae 7959 return;
784d3a42 7960
9b6d8fcf 7961 bdi = path->extra->damp_info;
784d3a42 7962
d62a17ae 7963 /* short status lead text */
9b6d8fcf 7964 route_vty_short_status_out(vty, path, json);
784d3a42 7965
d62a17ae 7966 /* print prefix and mask */
7967 if (!use_json) {
7968 if (!display)
9c92b5f7 7969 route_vty_out_route(p, vty, NULL);
d62a17ae 7970 else
7971 vty_out(vty, "%*s", 17, " ");
7972 }
784d3a42 7973
9b6d8fcf 7974 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 7975 len = 16 - len;
7976 if (len < 1) {
7977 if (!use_json)
7978 vty_out(vty, "\n%*s", 33, " ");
7979 } else {
7980 if (use_json)
7981 json_object_int_add(json, "peerHost", len);
7982 else
7983 vty_out(vty, "%*s", len, " ");
7984 }
784d3a42 7985
d62a17ae 7986 len = vty_out(vty, "%d", bdi->flap);
7987 len = 5 - len;
7988 if (len < 1) {
7989 if (!use_json)
7990 vty_out(vty, " ");
7991 } else {
7992 if (use_json)
7993 json_object_int_add(json, "bdiFlap", len);
7994 else
7995 vty_out(vty, "%*s", len, " ");
7996 }
7997
7998 if (use_json)
7999 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
8000 json);
8001 else
996c9314
LB
8002 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
8003 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 8004
9b6d8fcf
DS
8005 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
8006 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 8007 if (use_json)
9b6d8fcf 8008 bgp_damp_reuse_time_vty(vty, path, timebuf,
d62a17ae 8009 BGP_UPTIME_LEN, use_json, json);
8010 else
8011 vty_out(vty, "%s ",
9b6d8fcf 8012 bgp_damp_reuse_time_vty(vty, path, timebuf,
d62a17ae 8013 BGP_UPTIME_LEN,
8014 use_json, json));
8015 } else {
8016 if (!use_json)
8017 vty_out(vty, "%*s ", 8, " ");
8018 }
8019
8020 /* Print attribute */
9b6d8fcf 8021 attr = path->attr;
d62a17ae 8022
05864da7
DS
8023 /* Print aspath */
8024 if (attr->aspath) {
d62a17ae 8025 if (use_json)
05864da7
DS
8026 json_object_string_add(json, "asPath",
8027 attr->aspath->str);
d62a17ae 8028 else
05864da7 8029 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8030 }
05864da7
DS
8031
8032 /* Print origin */
8033 if (use_json)
8034 json_object_string_add(json, "origin",
8035 bgp_origin_str[attr->origin]);
8036 else
8037 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8038
d62a17ae 8039 if (!use_json)
8040 vty_out(vty, "\n");
8041}
8042
8043static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
8044 int *first, const char *header,
8045 json_object *json_adv_to)
8046{
8047 char buf1[INET6_ADDRSTRLEN];
8048 json_object *json_peer = NULL;
8049
8050 if (json_adv_to) {
8051 /* 'advertised-to' is a dictionary of peers we have advertised
8052 * this
8053 * prefix too. The key is the peer's IP or swpX, the value is
8054 * the
8055 * hostname if we know it and "" if not.
8056 */
8057 json_peer = json_object_new_object();
8058
8059 if (peer->hostname)
8060 json_object_string_add(json_peer, "hostname",
8061 peer->hostname);
8062
8063 if (peer->conf_if)
8064 json_object_object_add(json_adv_to, peer->conf_if,
8065 json_peer);
8066 else
8067 json_object_object_add(
8068 json_adv_to,
8069 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
8070 json_peer);
8071 } else {
8072 if (*first) {
8073 vty_out(vty, "%s", header);
8074 *first = 0;
8075 }
8076
8077 if (peer->hostname
8078 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
8079 if (peer->conf_if)
8080 vty_out(vty, " %s(%s)", peer->hostname,
8081 peer->conf_if);
8082 else
8083 vty_out(vty, " %s(%s)", peer->hostname,
8084 sockunion2str(&peer->su, buf1,
8085 SU_ADDRSTRLEN));
8086 } else {
8087 if (peer->conf_if)
8088 vty_out(vty, " %s", peer->conf_if);
8089 else
8090 vty_out(vty, " %s",
8091 sockunion2str(&peer->su, buf1,
8092 SU_ADDRSTRLEN));
8093 }
8094 }
784d3a42
PG
8095}
8096
dcc68b5e
MS
8097static void route_vty_out_tx_ids(struct vty *vty,
8098 struct bgp_addpath_info_data *d)
8099{
8100 int i;
8101
8102 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
8103 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
8104 d->addpath_tx_id[i],
8105 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
8106 }
8107}
8108
0dc8ee70
DS
8109static const char *bgp_path_selection_reason2str(
8110 enum bgp_path_selection_reason reason)
8111{
8112 switch (reason) {
8113 case bgp_path_selection_none:
8114 return "Nothing to Select";
8115 break;
8116 case bgp_path_selection_first:
8117 return "First path received";
8118 break;
8119 case bgp_path_selection_evpn_sticky_mac:
8120 return "EVPN Sticky Mac";
8121 break;
8122 case bgp_path_selection_evpn_seq:
8123 return "EVPN sequence number";
8124 break;
8125 case bgp_path_selection_evpn_lower_ip:
8126 return "EVPN lower IP";
8127 break;
8128 case bgp_path_selection_weight:
8129 return "Weight";
8130 break;
8131 case bgp_path_selection_local_pref:
8132 return "Local Pref";
8133 break;
8134 case bgp_path_selection_local_route:
8135 return "Local Route";
8136 break;
8137 case bgp_path_selection_confed_as_path:
8138 return "Confederation based AS Path";
8139 break;
8140 case bgp_path_selection_as_path:
8141 return "AS Path";
8142 break;
8143 case bgp_path_selection_origin:
8144 return "Origin";
8145 break;
8146 case bgp_path_selection_med:
8147 return "MED";
8148 break;
8149 case bgp_path_selection_peer:
8150 return "Peer Type";
8151 break;
8152 case bgp_path_selection_confed:
8153 return "Confed Peer Type";
8154 break;
8155 case bgp_path_selection_igp_metric:
8156 return "IGP Metric";
8157 break;
8158 case bgp_path_selection_older:
8159 return "Older Path";
8160 break;
8161 case bgp_path_selection_router_id:
8162 return "Router ID";
8163 break;
8164 case bgp_path_selection_cluster_length:
8165 return "Cluser length";
8166 break;
8167 case bgp_path_selection_stale:
8168 return "Path Staleness";
8169 break;
8170 case bgp_path_selection_local_configured:
8171 return "Locally configured route";
8172 break;
8173 case bgp_path_selection_neighbor_ip:
8174 return "Neighbor IP";
8175 break;
8176 case bgp_path_selection_default:
8177 return "Nothing left to compare";
8178 break;
8179 }
a74879b2 8180 return "Invalid (internal error)";
0dc8ee70
DS
8181}
8182
f08b5ca0
DS
8183void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
8184 struct bgp_node *bn, struct bgp_path_info *path,
8185 afi_t afi, safi_t safi, json_object *json_paths)
d62a17ae 8186{
8187 char buf[INET6_ADDRSTRLEN];
8188 char buf1[BUFSIZ];
d62a17ae 8189 char buf2[EVPN_ROUTE_STRLEN];
d62a17ae 8190 struct attr *attr;
8191 int sockunion_vty_out(struct vty *, union sockunion *);
8192 time_t tbuf;
8193 json_object *json_bestpath = NULL;
8194 json_object *json_cluster_list = NULL;
8195 json_object *json_cluster_list_list = NULL;
8196 json_object *json_ext_community = NULL;
8197 json_object *json_last_update = NULL;
7fd077aa 8198 json_object *json_pmsi = NULL;
d62a17ae 8199 json_object *json_nexthop_global = NULL;
8200 json_object *json_nexthop_ll = NULL;
8201 json_object *json_nexthops = NULL;
8202 json_object *json_path = NULL;
8203 json_object *json_peer = NULL;
8204 json_object *json_string = NULL;
8205 json_object *json_adv_to = NULL;
8206 int first = 0;
8207 struct listnode *node, *nnode;
8208 struct peer *peer;
8209 int addpath_capable;
8210 int has_adj;
8211 unsigned int first_as;
1defdda8 8212 bool nexthop_self =
9b6d8fcf 8213 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 8214 int i;
25b5da8d 8215 char *nexthop_fqdn = bgp_nexthop_fqdn(path->peer);
d62a17ae 8216
8217 if (json_paths) {
8218 json_path = json_object_new_object();
8219 json_peer = json_object_new_object();
8220 json_nexthop_global = json_object_new_object();
8221 }
8222
44c69747 8223 if (path->extra) {
b57ba6d2 8224 char tag_buf[30];
d62a17ae 8225
d7325ee7 8226 buf2[0] = '\0';
d62a17ae 8227 tag_buf[0] = '\0';
9b6d8fcf
DS
8228 if (path->extra && path->extra->num_labels) {
8229 bgp_evpn_label2str(path->extra->label,
8230 path->extra->num_labels, tag_buf,
a4d82a8a 8231 sizeof(tag_buf));
d62a17ae 8232 }
d7325ee7 8233 if (safi == SAFI_EVPN) {
44c69747
LK
8234 if (!json_paths) {
8235 bgp_evpn_route2str((struct prefix_evpn *)&bn->p,
8236 buf2, sizeof(buf2));
8237 vty_out(vty, " Route %s", buf2);
8238 if (tag_buf[0] != '\0')
8239 vty_out(vty, " VNI %s", tag_buf);
8240 vty_out(vty, "\n");
8241 } else {
8242 if (tag_buf[0])
8243 json_object_string_add(json_path, "VNI",
8244 tag_buf);
8245 }
d7325ee7
DD
8246 }
8247
44c69747 8248 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 8249 struct bgp_path_info *parent_ri;
d62a17ae 8250 struct bgp_node *rn, *prn;
8251
9b6d8fcf 8252 parent_ri = (struct bgp_path_info *)path->extra->parent;
d62a17ae 8253 rn = parent_ri->net;
8254 if (rn && rn->prn) {
8255 prn = rn->prn;
d7325ee7
DD
8256 prefix_rd2str((struct prefix_rd *)&prn->p,
8257 buf1, sizeof(buf1));
8258 if (is_pi_family_evpn(parent_ri)) {
8259 bgp_evpn_route2str((struct prefix_evpn *)&rn->p,
8260 buf2, sizeof(buf2));
8261 vty_out(vty, " Imported from %s:%s, VNI %s\n", buf1, buf2, tag_buf);
8262 } else
8263 vty_out(vty, " Imported from %s:%s\n", buf1, buf2);
d62a17ae 8264 }
8265 }
8266 }
d62a17ae 8267
9b6d8fcf 8268 attr = path->attr;
d62a17ae 8269
05864da7
DS
8270 /* Line1 display AS-path, Aggregator */
8271 if (attr->aspath) {
8272 if (json_paths) {
8273 if (!attr->aspath->json)
8274 aspath_str_update(attr->aspath, true);
8275 json_object_lock(attr->aspath->json);
8276 json_object_object_add(json_path, "aspath",
8277 attr->aspath->json);
8278 } else {
8279 if (attr->aspath->segments)
8280 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 8281 else
05864da7 8282 vty_out(vty, " Local");
d62a17ae 8283 }
05864da7 8284 }
d62a17ae 8285
05864da7
DS
8286 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
8287 if (json_paths)
8288 json_object_boolean_true_add(json_path, "removed");
8289 else
8290 vty_out(vty, ", (removed)");
8291 }
d62a17ae 8292
05864da7
DS
8293 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
8294 if (json_paths)
8295 json_object_boolean_true_add(json_path, "stale");
8296 else
8297 vty_out(vty, ", (stale)");
8298 }
d62a17ae 8299
05864da7
DS
8300 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
8301 if (json_paths) {
8302 json_object_int_add(json_path, "aggregatorAs",
8303 attr->aggregator_as);
8304 json_object_string_add(
8305 json_path, "aggregatorId",
8306 inet_ntoa(attr->aggregator_addr));
8307 } else {
8308 vty_out(vty, ", (aggregated by %u %s)",
8309 attr->aggregator_as,
8310 inet_ntoa(attr->aggregator_addr));
d62a17ae 8311 }
05864da7 8312 }
d62a17ae 8313
05864da7
DS
8314 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
8315 PEER_FLAG_REFLECTOR_CLIENT)) {
8316 if (json_paths)
8317 json_object_boolean_true_add(json_path,
8318 "rxedFromRrClient");
8319 else
8320 vty_out(vty, ", (Received from a RR-client)");
8321 }
d62a17ae 8322
05864da7
DS
8323 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
8324 PEER_FLAG_RSERVER_CLIENT)) {
8325 if (json_paths)
8326 json_object_boolean_true_add(json_path,
8327 "rxedFromRsClient");
8328 else
8329 vty_out(vty, ", (Received from a RS-client)");
8330 }
d62a17ae 8331
05864da7
DS
8332 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
8333 if (json_paths)
8334 json_object_boolean_true_add(json_path,
8335 "dampeningHistoryEntry");
8336 else
8337 vty_out(vty, ", (history entry)");
8338 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
8339 if (json_paths)
8340 json_object_boolean_true_add(json_path,
8341 "dampeningSuppressed");
8342 else
8343 vty_out(vty, ", (suppressed due to dampening)");
8344 }
d62a17ae 8345
05864da7
DS
8346 if (!json_paths)
8347 vty_out(vty, "\n");
d62a17ae 8348
05864da7
DS
8349 /* Line2 display Next-hop, Neighbor, Router-id */
8350 /* Display the nexthop */
8351 if ((bn->p.family == AF_INET || bn->p.family == AF_ETHERNET
8352 || bn->p.family == AF_EVPN)
8353 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
8354 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8355 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8356 || safi == SAFI_EVPN) {
d62a17ae 8357 if (json_paths)
d62a17ae 8358 json_object_string_add(
25b5da8d
DA
8359 json_nexthop_global,
8360 nexthop_fqdn ? "fqdn" : "ip",
8361 nexthop_fqdn
8362 ? nexthop_fqdn
05864da7
DS
8363 : inet_ntoa(
8364 attr->mp_nexthop_global_in));
8365 else
d62a17ae 8366 vty_out(vty, " %s",
25b5da8d
DA
8367 nexthop_fqdn
8368 ? nexthop_fqdn
05864da7
DS
8369 : inet_ntoa(
8370 attr->mp_nexthop_global_in));
d62a17ae 8371 } else {
d62a17ae 8372 if (json_paths)
05864da7
DS
8373 json_object_string_add(
8374 json_nexthop_global,
8375 nexthop_fqdn ? "fqdn" : "ip",
8376 nexthop_fqdn
8377 ? nexthop_fqdn
8378 : inet_ntoa(attr->nexthop));
d62a17ae 8379 else
05864da7
DS
8380 vty_out(vty, " %s",
8381 nexthop_fqdn
8382 ? nexthop_fqdn
8383 : inet_ntoa(attr->nexthop));
d62a17ae 8384 }
8385
05864da7
DS
8386 if (json_paths)
8387 json_object_string_add(json_nexthop_global, "afi",
8388 "ipv4");
8389 } else {
8390 if (json_paths) {
8391 json_object_string_add(
8392 json_nexthop_global,
8393 nexthop_fqdn ? "fqdn" : "ip",
8394 nexthop_fqdn
8395 ? nexthop_fqdn
8396 : inet_ntop(AF_INET6,
8397 &attr->mp_nexthop_global,
8398 buf, INET6_ADDRSTRLEN));
8399 json_object_string_add(json_nexthop_global, "afi",
8400 "ipv6");
8401 json_object_string_add(json_nexthop_global, "scope",
8402 "global");
8403 } else {
8404 vty_out(vty, " %s",
8405 nexthop_fqdn
8406 ? nexthop_fqdn
8407 : inet_ntop(AF_INET6,
8408 &attr->mp_nexthop_global,
8409 buf, INET6_ADDRSTRLEN));
d62a17ae 8410 }
05864da7 8411 }
d62a17ae 8412
05864da7
DS
8413 /* Display the IGP cost or 'inaccessible' */
8414 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
8415 if (json_paths)
8416 json_object_boolean_false_add(json_nexthop_global,
8417 "accessible");
8418 else
8419 vty_out(vty, " (inaccessible)");
8420 } else {
8421 if (path->extra && path->extra->igpmetric) {
d62a17ae 8422 if (json_paths)
05864da7
DS
8423 json_object_int_add(json_nexthop_global,
8424 "metric",
8425 path->extra->igpmetric);
d62a17ae 8426 else
05864da7
DS
8427 vty_out(vty, " (metric %u)",
8428 path->extra->igpmetric);
d62a17ae 8429 }
8430
05864da7 8431 /* IGP cost is 0, display this only for json */
d62a17ae 8432 else {
d62a17ae 8433 if (json_paths)
05864da7
DS
8434 json_object_int_add(json_nexthop_global,
8435 "metric", 0);
d62a17ae 8436 }
d62a17ae 8437
05864da7
DS
8438 if (json_paths)
8439 json_object_boolean_true_add(json_nexthop_global,
8440 "accessible");
8441 }
d62a17ae 8442
05864da7
DS
8443 /* Display peer "from" output */
8444 /* This path was originated locally */
8445 if (path->peer == bgp->peer_self) {
d62a17ae 8446
05864da7
DS
8447 if (safi == SAFI_EVPN
8448 || (bn->p.family == AF_INET
8449 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 8450 if (json_paths)
05864da7
DS
8451 json_object_string_add(json_peer, "peerId",
8452 "0.0.0.0");
d62a17ae 8453 else
05864da7
DS
8454 vty_out(vty, " from 0.0.0.0 ");
8455 } else {
d62a17ae 8456 if (json_paths)
05864da7
DS
8457 json_object_string_add(json_peer, "peerId",
8458 "::");
d62a17ae 8459 else
05864da7 8460 vty_out(vty, " from :: ");
d62a17ae 8461 }
d62a17ae 8462
05864da7
DS
8463 if (json_paths)
8464 json_object_string_add(json_peer, "routerId",
8465 inet_ntoa(bgp->router_id));
8466 else
8467 vty_out(vty, "(%s)", inet_ntoa(bgp->router_id));
8468 }
d62a17ae 8469
05864da7
DS
8470 /* We RXed this path from one of our peers */
8471 else {
8472
8473 if (json_paths) {
8474 json_object_string_add(json_peer, "peerId",
8475 sockunion2str(&path->peer->su,
8476 buf,
8477 SU_ADDRSTRLEN));
8478 json_object_string_add(json_peer, "routerId",
8479 inet_ntop(AF_INET,
8480 &path->peer->remote_id,
8481 buf1, sizeof(buf1)));
8482
8483 if (path->peer->hostname)
8484 json_object_string_add(json_peer, "hostname",
8485 path->peer->hostname);
8486
8487 if (path->peer->domainname)
8488 json_object_string_add(json_peer, "domainname",
8489 path->peer->domainname);
8490
8491 if (path->peer->conf_if)
8492 json_object_string_add(json_peer, "interface",
8493 path->peer->conf_if);
8494 } else {
8495 if (path->peer->conf_if) {
8496 if (path->peer->hostname
8497 && bgp_flag_check(path->peer->bgp,
8498 BGP_FLAG_SHOW_HOSTNAME))
8499 vty_out(vty, " from %s(%s)",
8500 path->peer->hostname,
8501 path->peer->conf_if);
d62a17ae 8502 else
05864da7 8503 vty_out(vty, " from %s",
9b6d8fcf 8504 path->peer->conf_if);
d62a17ae 8505 } else {
05864da7
DS
8506 if (path->peer->hostname
8507 && bgp_flag_check(path->peer->bgp,
8508 BGP_FLAG_SHOW_HOSTNAME))
8509 vty_out(vty, " from %s(%s)",
8510 path->peer->hostname,
8511 path->peer->host);
d62a17ae 8512 else
05864da7
DS
8513 vty_out(vty, " from %s",
8514 sockunion2str(&path->peer->su,
8515 buf,
8516 SU_ADDRSTRLEN));
d62a17ae 8517 }
d62a17ae 8518
05864da7
DS
8519 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
8520 vty_out(vty, " (%s)",
8521 inet_ntoa(attr->originator_id));
8522 else
8523 vty_out(vty, " (%s)",
8524 inet_ntop(AF_INET,
8525 &path->peer->remote_id, buf1,
8526 sizeof(buf1)));
d62a17ae 8527 }
05864da7 8528 }
9df8b37c 8529
05864da7
DS
8530 /*
8531 * Note when vrfid of nexthop is different from that of prefix
8532 */
8533 if (path->extra && path->extra->bgp_orig) {
8534 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8535
05864da7
DS
8536 if (json_paths) {
8537 const char *vn;
9df8b37c 8538
05864da7
DS
8539 if (path->extra->bgp_orig->inst_type
8540 == BGP_INSTANCE_TYPE_DEFAULT)
8541 vn = VRF_DEFAULT_NAME;
8542 else
8543 vn = path->extra->bgp_orig->name;
9df8b37c 8544
05864da7 8545 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 8546
05864da7
DS
8547 if (nexthop_vrfid == VRF_UNKNOWN) {
8548 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 8549 } else {
05864da7
DS
8550 json_object_int_add(json_path, "nhVrfId",
8551 (int)nexthop_vrfid);
9df8b37c 8552 }
05864da7
DS
8553 } else {
8554 if (nexthop_vrfid == VRF_UNKNOWN)
8555 vty_out(vty, " vrf ?");
d62a17ae 8556 else
05864da7 8557 vty_out(vty, " vrf %u", nexthop_vrfid);
9df8b37c 8558 }
05864da7 8559 }
9df8b37c 8560
05864da7
DS
8561 if (nexthop_self) {
8562 if (json_paths) {
8563 json_object_boolean_true_add(json_path,
8564 "announceNexthopSelf");
8565 } else {
8566 vty_out(vty, " announce-nh-self");
9df8b37c 8567 }
05864da7 8568 }
9df8b37c 8569
05864da7
DS
8570 if (!json_paths)
8571 vty_out(vty, "\n");
d62a17ae 8572
05864da7
DS
8573 /* display the link-local nexthop */
8574 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
8575 if (json_paths) {
8576 json_nexthop_ll = json_object_new_object();
8577 json_object_string_add(
8578 json_nexthop_ll, nexthop_fqdn ? "fqdn" : "ip",
8579 nexthop_fqdn
8580 ? nexthop_fqdn
8581 : inet_ntop(AF_INET6,
8582 &attr->mp_nexthop_local,
8583 buf, INET6_ADDRSTRLEN));
8584 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
8585 json_object_string_add(json_nexthop_ll, "scope",
8586 "link-local");
d62a17ae 8587
05864da7
DS
8588 json_object_boolean_true_add(json_nexthop_ll,
8589 "accessible");
d62a17ae 8590
05864da7 8591 if (!attr->mp_nexthop_prefer_global)
d62a17ae 8592 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
8593 "used");
8594 else
8595 json_object_boolean_true_add(
8596 json_nexthop_global, "used");
8597 } else {
8598 vty_out(vty, " (%s) %s\n",
8599 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
8600 buf, INET6_ADDRSTRLEN),
8601 attr->mp_nexthop_prefer_global
8602 ? "(prefer-global)"
8603 : "(used)");
d62a17ae 8604 }
05864da7
DS
8605 }
8606 /* If we do not have a link-local nexthop then we must flag the
8607 global as "used" */
8608 else {
8609 if (json_paths)
8610 json_object_boolean_true_add(json_nexthop_global,
8611 "used");
8612 }
d62a17ae 8613
05864da7
DS
8614 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8615 * Int/Ext/Local, Atomic, best */
8616 if (json_paths)
8617 json_object_string_add(json_path, "origin",
8618 bgp_origin_long_str[attr->origin]);
8619 else
8620 vty_out(vty, " Origin %s",
8621 bgp_origin_long_str[attr->origin]);
9df8b37c 8622
05864da7
DS
8623 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
8624 if (json_paths) {
8625 /*
8626 * Adding "metric" field to match with
8627 * corresponding CLI. "med" will be
8628 * deprecated in future.
8629 */
8630 json_object_int_add(json_path, "med", attr->med);
8631 json_object_int_add(json_path, "metric", attr->med);
8632 } else
8633 vty_out(vty, ", metric %u", attr->med);
8634 }
9df8b37c 8635
05864da7
DS
8636 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
8637 if (json_paths)
8638 json_object_int_add(json_path, "localpref",
8639 attr->local_pref);
8640 else
8641 vty_out(vty, ", localpref %u", attr->local_pref);
8642 }
9df8b37c 8643
05864da7
DS
8644 if (attr->weight != 0) {
8645 if (json_paths)
8646 json_object_int_add(json_path, "weight", attr->weight);
8647 else
8648 vty_out(vty, ", weight %u", attr->weight);
8649 }
9df8b37c 8650
05864da7
DS
8651 if (attr->tag != 0) {
8652 if (json_paths)
8653 json_object_int_add(json_path, "tag", attr->tag);
8654 else
8655 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
8656 }
9df8b37c 8657
05864da7
DS
8658 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
8659 if (json_paths)
8660 json_object_boolean_false_add(json_path, "valid");
8661 else
8662 vty_out(vty, ", invalid");
8663 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
8664 if (json_paths)
8665 json_object_boolean_true_add(json_path, "valid");
8666 else
8667 vty_out(vty, ", valid");
8668 }
9df8b37c 8669
05864da7
DS
8670 if (path->peer != bgp->peer_self) {
8671 if (path->peer->as == path->peer->local_as) {
8672 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
8673 if (json_paths)
8674 json_object_string_add(
8675 json_peer, "type",
8676 "confed-internal");
d62a17ae 8677 else
05864da7 8678 vty_out(vty, ", confed-internal");
d62a17ae 8679 } else {
05864da7
DS
8680 if (json_paths)
8681 json_object_string_add(
8682 json_peer, "type", "internal");
8683 else
8684 vty_out(vty, ", internal");
9df8b37c 8685 }
05864da7
DS
8686 } else {
8687 if (bgp_confederation_peers_check(bgp,
8688 path->peer->as)) {
8689 if (json_paths)
8690 json_object_string_add(
8691 json_peer, "type",
8692 "confed-external");
d62a17ae 8693 else
05864da7 8694 vty_out(vty, ", confed-external");
d62a17ae 8695 } else {
05864da7
DS
8696 if (json_paths)
8697 json_object_string_add(
8698 json_peer, "type", "external");
8699 else
8700 vty_out(vty, ", external");
d62a17ae 8701 }
8702 }
05864da7
DS
8703 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
8704 if (json_paths) {
8705 json_object_boolean_true_add(json_path, "aggregated");
8706 json_object_boolean_true_add(json_path, "local");
8707 } else {
8708 vty_out(vty, ", aggregated, local");
8709 }
8710 } else if (path->type != ZEBRA_ROUTE_BGP) {
8711 if (json_paths)
8712 json_object_boolean_true_add(json_path, "sourced");
8713 else
8714 vty_out(vty, ", sourced");
8715 } else {
8716 if (json_paths) {
8717 json_object_boolean_true_add(json_path, "sourced");
8718 json_object_boolean_true_add(json_path, "local");
8719 } else {
8720 vty_out(vty, ", sourced, local");
d62a17ae 8721 }
05864da7 8722 }
718e3744 8723
05864da7 8724 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 8725 if (json_paths)
05864da7
DS
8726 json_object_boolean_true_add(json_path,
8727 "atomicAggregate");
d62a17ae 8728 else
05864da7
DS
8729 vty_out(vty, ", atomic-aggregate");
8730 }
d62a17ae 8731
05864da7
DS
8732 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
8733 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
8734 && bgp_path_info_mpath_count(path))) {
8735 if (json_paths)
8736 json_object_boolean_true_add(json_path, "multipath");
8737 else
8738 vty_out(vty, ", multipath");
8739 }
50e05855 8740
05864da7
DS
8741 // Mark the bestpath(s)
8742 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
8743 first_as = aspath_get_first_as(attr->aspath);
718e3744 8744
05864da7
DS
8745 if (json_paths) {
8746 if (!json_bestpath)
8747 json_bestpath = json_object_new_object();
8748 json_object_int_add(json_bestpath, "bestpathFromAs",
8749 first_as);
8750 } else {
8751 if (first_as)
8752 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 8753 else
05864da7 8754 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 8755 }
05864da7 8756 }
718e3744 8757
05864da7
DS
8758 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
8759 if (json_paths) {
8760 if (!json_bestpath)
8761 json_bestpath = json_object_new_object();
8762 json_object_boolean_true_add(json_bestpath, "overall");
8763 json_object_string_add(
8764 json_bestpath, "selectionReason",
8765 bgp_path_selection_reason2str(bn->reason));
8766 } else {
8767 vty_out(vty, ", best");
8768 vty_out(vty, " (%s)",
8769 bgp_path_selection_reason2str(bn->reason));
d62a17ae 8770 }
05864da7 8771 }
718e3744 8772
05864da7
DS
8773 if (json_bestpath)
8774 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 8775
05864da7
DS
8776 if (!json_paths)
8777 vty_out(vty, "\n");
8778
8779 /* Line 4 display Community */
8780 if (attr->community) {
8781 if (json_paths) {
8782 if (!attr->community->json)
8783 community_str(attr->community, true);
8784 json_object_lock(attr->community->json);
8785 json_object_object_add(json_path, "community",
8786 attr->community->json);
8787 } else {
8788 vty_out(vty, " Community: %s\n",
8789 attr->community->str);
d62a17ae 8790 }
05864da7 8791 }
718e3744 8792
05864da7
DS
8793 /* Line 5 display Extended-community */
8794 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8795 if (json_paths) {
8796 json_ext_community = json_object_new_object();
8797 json_object_string_add(json_ext_community, "string",
8798 attr->ecommunity->str);
8799 json_object_object_add(json_path, "extendedCommunity",
8800 json_ext_community);
d62a17ae 8801 } else {
05864da7
DS
8802 vty_out(vty, " Extended Community: %s\n",
8803 attr->ecommunity->str);
d62a17ae 8804 }
05864da7 8805 }
718e3744 8806
05864da7
DS
8807 /* Line 6 display Large community */
8808 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
8809 if (json_paths) {
8810 if (!attr->lcommunity->json)
8811 lcommunity_str(attr->lcommunity, true);
8812 json_object_lock(attr->lcommunity->json);
8813 json_object_object_add(json_path, "largeCommunity",
8814 attr->lcommunity->json);
8815 } else {
8816 vty_out(vty, " Large Community: %s\n",
8817 attr->lcommunity->str);
d62a17ae 8818 }
05864da7 8819 }
718e3744 8820
05864da7
DS
8821 /* Line 7 display Originator, Cluster-id */
8822 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
8823 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
8824 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 8825 if (json_paths)
05864da7
DS
8826 json_object_string_add(
8827 json_path, "originatorId",
8828 inet_ntoa(attr->originator_id));
d62a17ae 8829 else
05864da7
DS
8830 vty_out(vty, " Originator: %s",
8831 inet_ntoa(attr->originator_id));
d62a17ae 8832 }
856ca177 8833
05864da7
DS
8834 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
8835 int i;
d62a17ae 8836
8837 if (json_paths) {
05864da7
DS
8838 json_cluster_list = json_object_new_object();
8839 json_cluster_list_list =
8840 json_object_new_array();
8841
8842 for (i = 0; i < attr->cluster->length / 4;
8843 i++) {
8844 json_string = json_object_new_string(
8845 inet_ntoa(attr->cluster
8846 ->list[i]));
8847 json_object_array_add(
8848 json_cluster_list_list,
8849 json_string);
8850 }
718e3744 8851
05864da7
DS
8852 /*
8853 * struct cluster_list does not have
8854 * "str" variable like aspath and community
8855 * do. Add this someday if someone asks
8856 * for it.
8857 * json_object_string_add(json_cluster_list,
8858 * "string", attr->cluster->str);
8859 */
8860 json_object_object_add(json_cluster_list,
8861 "list",
8862 json_cluster_list_list);
8863 json_object_object_add(json_path, "clusterList",
8864 json_cluster_list);
0dc8ee70 8865 } else {
05864da7
DS
8866 vty_out(vty, ", Cluster list: ");
8867
8868 for (i = 0; i < attr->cluster->length / 4;
8869 i++) {
8870 vty_out(vty, "%s ",
8871 inet_ntoa(attr->cluster
8872 ->list[i]));
8873 }
0dc8ee70 8874 }
d62a17ae 8875 }
718e3744 8876
d62a17ae 8877 if (!json_paths)
8878 vty_out(vty, "\n");
05864da7 8879 }
d62a17ae 8880
05864da7
DS
8881 if (path->extra && path->extra->damp_info)
8882 bgp_damp_info_vty(vty, path, json_path);
adbac85e 8883
05864da7
DS
8884 /* Remote Label */
8885 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
8886 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
8887 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 8888
05864da7
DS
8889 if (json_paths)
8890 json_object_int_add(json_path, "remoteLabel", label);
8891 else
8892 vty_out(vty, " Remote label: %d\n", label);
8893 }
d62a17ae 8894
05864da7
DS
8895 /* Label Index */
8896 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
8897 if (json_paths)
8898 json_object_int_add(json_path, "labelIndex",
8899 attr->label_index);
8900 else
8901 vty_out(vty, " Label Index: %d\n",
8902 attr->label_index);
8903 }
d62a17ae 8904
05864da7
DS
8905 /* Line 8 display Addpath IDs */
8906 if (path->addpath_rx_id
8907 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
8908 if (json_paths) {
8909 json_object_int_add(json_path, "addpathRxId",
8910 path->addpath_rx_id);
d62a17ae 8911
05864da7
DS
8912 /* Keep backwards compatibility with the old API
8913 * by putting TX All's ID in the old field
8914 */
8915 json_object_int_add(
8916 json_path, "addpathTxId",
8917 path->tx_addpath
8918 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 8919
05864da7
DS
8920 /* ... but create a specific field for each
8921 * strategy
8922 */
8923 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
8924 json_object_int_add(
8925 json_path,
8926 bgp_addpath_names(i)->id_json_name,
8927 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 8928 }
05864da7
DS
8929 } else {
8930 vty_out(vty, " AddPath ID: RX %u, ",
8931 path->addpath_rx_id);
d62a17ae 8932
05864da7 8933 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 8934 }
05864da7 8935 }
520d5d76 8936
05864da7
DS
8937 /* If we used addpath to TX a non-bestpath we need to display
8938 * "Advertised to" on a path-by-path basis
8939 */
8940 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
8941 first = 1;
dcc68b5e 8942
05864da7
DS
8943 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
8944 addpath_capable =
8945 bgp_addpath_encode_tx(peer, afi, safi);
8946 has_adj = bgp_adj_out_lookup(
8947 peer, path->net,
8948 bgp_addpath_id_for_peer(peer, afi, safi,
8949 &path->tx_addpath));
8950
8951 if ((addpath_capable && has_adj)
8952 || (!addpath_capable && has_adj
8953 && CHECK_FLAG(path->flags,
8954 BGP_PATH_SELECTED))) {
8955 if (json_path && !json_adv_to)
8956 json_adv_to = json_object_new_object();
dcc68b5e 8957
05864da7
DS
8958 route_vty_out_advertised_to(
8959 vty, peer, &first,
8960 " Advertised to:", json_adv_to);
d62a17ae 8961 }
8962 }
718e3744 8963
05864da7
DS
8964 if (json_path) {
8965 if (json_adv_to) {
8966 json_object_object_add(
8967 json_path, "advertisedTo", json_adv_to);
d62a17ae 8968 }
05864da7
DS
8969 } else {
8970 if (!first) {
8971 vty_out(vty, "\n");
d62a17ae 8972 }
8973 }
05864da7 8974 }
b05a1c8b 8975
05864da7
DS
8976 /* Line 9 display Uptime */
8977 tbuf = time(NULL) - (bgp_clock() - path->uptime);
8978 if (json_paths) {
8979 json_last_update = json_object_new_object();
8980 json_object_int_add(json_last_update, "epoch", tbuf);
8981 json_object_string_add(json_last_update, "string",
8982 ctime(&tbuf));
8983 json_object_object_add(json_path, "lastUpdate",
8984 json_last_update);
8985 } else
8986 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 8987
05864da7
DS
8988 /* Line 10 display PMSI tunnel attribute, if present */
8989 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
8990 const char *str =
8991 lookup_msg(bgp_pmsi_tnltype_str, attr->pmsi_tnl_type,
8992 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 8993
05864da7
DS
8994 if (json_paths) {
8995 json_pmsi = json_object_new_object();
8996 json_object_string_add(json_pmsi, "tunnelType", str);
8997 json_object_int_add(json_pmsi, "label",
8998 label2vni(&attr->label));
8999 json_object_object_add(json_path, "pmsi", json_pmsi);
9000 } else
9001 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
9002 str, label2vni(&attr->label));
d62a17ae 9003 }
f1aa5d8a 9004
d62a17ae 9005 /* We've constructed the json object for this path, add it to the json
9006 * array of paths
9007 */
9008 if (json_paths) {
9009 if (json_nexthop_global || json_nexthop_ll) {
9010 json_nexthops = json_object_new_array();
f1aa5d8a 9011
d62a17ae 9012 if (json_nexthop_global)
9013 json_object_array_add(json_nexthops,
9014 json_nexthop_global);
f1aa5d8a 9015
d62a17ae 9016 if (json_nexthop_ll)
9017 json_object_array_add(json_nexthops,
9018 json_nexthop_ll);
f1aa5d8a 9019
d62a17ae 9020 json_object_object_add(json_path, "nexthops",
9021 json_nexthops);
9022 }
9023
9024 json_object_object_add(json_path, "peer", json_peer);
9025 json_object_array_add(json_paths, json_path);
05864da7 9026 }
b366b518
BB
9027}
9028
96ade3ed 9029#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
9030#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9031#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 9032
d62a17ae 9033static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
9034 const char *prefix_list_str, afi_t afi,
9035 safi_t safi, enum bgp_show_type type);
9036static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
9037 const char *filter, afi_t afi, safi_t safi,
9038 enum bgp_show_type type);
9039static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
9040 const char *rmap_str, afi_t afi, safi_t safi,
9041 enum bgp_show_type type);
9042static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
9043 const char *com, int exact, afi_t afi,
9044 safi_t safi);
9045static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
9046 const char *prefix, afi_t afi, safi_t safi,
9047 enum bgp_show_type type);
a4d82a8a
PZ
9048static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
9049 afi_t afi, safi_t safi, enum bgp_show_type type);
7f323236
DW
9050static int bgp_show_community(struct vty *vty, struct bgp *bgp,
9051 const char *comstr, int exact, afi_t afi,
9f049418 9052 safi_t safi, bool use_json);
d62a17ae 9053
1ae44dfc
LB
9054
9055static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 9056 struct bgp_table *table, enum bgp_show_type type,
9f049418 9057 void *output_arg, bool use_json, char *rd,
a4d82a8a
PZ
9058 int is_last, unsigned long *output_cum,
9059 unsigned long *total_cum,
9386b588 9060 unsigned long *json_header_depth)
d62a17ae 9061{
40381db7 9062 struct bgp_path_info *pi;
d62a17ae 9063 struct bgp_node *rn;
9064 int header = 1;
9065 int display;
1ae44dfc
LB
9066 unsigned long output_count = 0;
9067 unsigned long total_count = 0;
d62a17ae 9068 struct prefix *p;
d62a17ae 9069 char buf2[BUFSIZ];
9070 json_object *json_paths = NULL;
9071 int first = 1;
9072
1ae44dfc
LB
9073 if (output_cum && *output_cum != 0)
9074 header = 0;
9075
9386b588 9076 if (use_json && !*json_header_depth) {
d62a17ae 9077 vty_out(vty,
66f80d74 9078 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
01eced22
AD
9079 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9080 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 9081 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b
DS
9082 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
9083 ? VRF_DEFAULT_NAME
9084 : bgp->name,
01eced22
AD
9085 table->version, inet_ntoa(bgp->router_id),
9086 bgp->default_local_pref, bgp->as);
9386b588
PZ
9087 *json_header_depth = 2;
9088 if (rd) {
445c2480 9089 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
9090 ++*json_header_depth;
9091 }
d62a17ae 9092 }
718e3744 9093
445c2480
DS
9094 if (use_json && rd) {
9095 vty_out(vty, " \"%s\" : { ", rd);
9096 }
9097
d62a17ae 9098 /* Start processing of routes. */
98ce9a06 9099 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685
DS
9100 pi = bgp_node_get_bgp_path_info(rn);
9101 if (pi == NULL)
98ce9a06 9102 continue;
d62a17ae 9103
98ce9a06 9104 display = 0;
98ce9a06
DS
9105 if (use_json)
9106 json_paths = json_object_new_array();
9107 else
9108 json_paths = NULL;
d62a17ae 9109
6f94b685 9110 for (; pi; pi = pi->next) {
98ce9a06
DS
9111 total_count++;
9112 if (type == bgp_show_type_flap_statistics
9113 || type == bgp_show_type_flap_neighbor
9114 || type == bgp_show_type_dampend_paths
9115 || type == bgp_show_type_damp_neighbor) {
40381db7 9116 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
9117 continue;
9118 }
9119 if (type == bgp_show_type_regexp) {
9120 regex_t *regex = output_arg;
d62a17ae 9121
40381db7 9122 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
9123 == REG_NOMATCH)
9124 continue;
9125 }
9126 if (type == bgp_show_type_prefix_list) {
9127 struct prefix_list *plist = output_arg;
d62a17ae 9128
98ce9a06
DS
9129 if (prefix_list_apply(plist, &rn->p)
9130 != PREFIX_PERMIT)
9131 continue;
9132 }
9133 if (type == bgp_show_type_filter_list) {
9134 struct as_list *as_list = output_arg;
d62a17ae 9135
40381db7 9136 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
9137 != AS_FILTER_PERMIT)
9138 continue;
9139 }
9140 if (type == bgp_show_type_route_map) {
9141 struct route_map *rmap = output_arg;
9b6d8fcf 9142 struct bgp_path_info path;
98ce9a06 9143 struct attr dummy_attr;
b68885f9 9144 route_map_result_t ret;
d62a17ae 9145
40381db7 9146 bgp_attr_dup(&dummy_attr, pi->attr);
d62a17ae 9147
40381db7 9148 path.peer = pi->peer;
9b6d8fcf 9149 path.attr = &dummy_attr;
d62a17ae 9150
a4d82a8a 9151 ret = route_map_apply(rmap, &rn->p, RMAP_BGP,
9b6d8fcf 9152 &path);
98ce9a06
DS
9153 if (ret == RMAP_DENYMATCH)
9154 continue;
9155 }
9156 if (type == bgp_show_type_neighbor
9157 || type == bgp_show_type_flap_neighbor
9158 || type == bgp_show_type_damp_neighbor) {
9159 union sockunion *su = output_arg;
9160
40381db7
DS
9161 if (pi->peer == NULL
9162 || pi->peer->su_remote == NULL
9163 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
9164 continue;
9165 }
9166 if (type == bgp_show_type_cidr_only) {
d7c0a89a 9167 uint32_t destination;
d62a17ae 9168
98ce9a06
DS
9169 destination = ntohl(rn->p.u.prefix4.s_addr);
9170 if (IN_CLASSC(destination)
9171 && rn->p.prefixlen == 24)
9172 continue;
9173 if (IN_CLASSB(destination)
9174 && rn->p.prefixlen == 16)
9175 continue;
9176 if (IN_CLASSA(destination)
9177 && rn->p.prefixlen == 8)
9178 continue;
9179 }
9180 if (type == bgp_show_type_prefix_longer) {
f7813c7c 9181 p = output_arg;
98ce9a06
DS
9182 if (!prefix_match(p, &rn->p))
9183 continue;
9184 }
9185 if (type == bgp_show_type_community_all) {
40381db7 9186 if (!pi->attr->community)
98ce9a06
DS
9187 continue;
9188 }
9189 if (type == bgp_show_type_community) {
9190 struct community *com = output_arg;
d62a17ae 9191
40381db7
DS
9192 if (!pi->attr->community
9193 || !community_match(pi->attr->community,
98ce9a06
DS
9194 com))
9195 continue;
9196 }
9197 if (type == bgp_show_type_community_exact) {
9198 struct community *com = output_arg;
d62a17ae 9199
40381db7
DS
9200 if (!pi->attr->community
9201 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
9202 continue;
9203 }
9204 if (type == bgp_show_type_community_list) {
9205 struct community_list *list = output_arg;
d62a17ae 9206
40381db7 9207 if (!community_list_match(pi->attr->community,
a4d82a8a 9208 list))
98ce9a06
DS
9209 continue;
9210 }
a4d82a8a 9211 if (type == bgp_show_type_community_list_exact) {
98ce9a06 9212 struct community_list *list = output_arg;
d62a17ae 9213
98ce9a06 9214 if (!community_list_exact_match(
40381db7 9215 pi->attr->community, list))
98ce9a06
DS
9216 continue;
9217 }
9218 if (type == bgp_show_type_lcommunity) {
9219 struct lcommunity *lcom = output_arg;
d62a17ae 9220
40381db7
DS
9221 if (!pi->attr->lcommunity
9222 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
9223 lcom))
9224 continue;
9225 }
36a206db 9226
9227 if (type == bgp_show_type_lcommunity_exact) {
9228 struct lcommunity *lcom = output_arg;
9229
9230 if (!pi->attr->lcommunity
9231 || !lcommunity_cmp(pi->attr->lcommunity,
9232 lcom))
9233 continue;
9234 }
98ce9a06
DS
9235 if (type == bgp_show_type_lcommunity_list) {
9236 struct community_list *list = output_arg;
d62a17ae 9237
40381db7 9238 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 9239 list))
98ce9a06
DS
9240 continue;
9241 }
36a206db 9242 if (type
9243 == bgp_show_type_lcommunity_list_exact) {
9244 struct community_list *list = output_arg;
9245
9246 if (!lcommunity_list_exact_match(
9247 pi->attr->lcommunity, list))
9248 continue;
9249 }
98ce9a06 9250 if (type == bgp_show_type_lcommunity_all) {
40381db7 9251 if (!pi->attr->lcommunity)
98ce9a06
DS
9252 continue;
9253 }
9254 if (type == bgp_show_type_dampend_paths
9255 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
9256 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
9257 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
9258 continue;
9259 }
9260
9261 if (!use_json && header) {
996c9314 9262 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 9263 ", local router ID is %s, vrf id ",
98ce9a06
DS
9264 table->version,
9265 inet_ntoa(bgp->router_id));
9df8b37c
PZ
9266 if (bgp->vrf_id == VRF_UNKNOWN)
9267 vty_out(vty, "%s", VRFID_NONE_STR);
9268 else
9269 vty_out(vty, "%u", bgp->vrf_id);
9270 vty_out(vty, "\n");
01eced22
AD
9271 vty_out(vty, "Default local pref %u, ",
9272 bgp->default_local_pref);
9273 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 9274 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 9275 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 9276 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 9277 if (type == bgp_show_type_dampend_paths
9278 || type == bgp_show_type_damp_neighbor)
98ce9a06 9279 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
9280 else if (type == bgp_show_type_flap_statistics
9281 || type == bgp_show_type_flap_neighbor)
98ce9a06 9282 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 9283 else
98ce9a06
DS
9284 vty_out(vty, BGP_SHOW_HEADER);
9285 header = 0;
d62a17ae 9286 }
98ce9a06
DS
9287 if (rd != NULL && !display && !output_count) {
9288 if (!use_json)
9289 vty_out(vty,
9290 "Route Distinguisher: %s\n",
9291 rd);
d62a17ae 9292 }
98ce9a06
DS
9293 if (type == bgp_show_type_dampend_paths
9294 || type == bgp_show_type_damp_neighbor)
40381db7 9295 damp_route_vty_out(vty, &rn->p, pi, display,
a4d82a8a 9296 safi, use_json, json_paths);
98ce9a06
DS
9297 else if (type == bgp_show_type_flap_statistics
9298 || type == bgp_show_type_flap_neighbor)
40381db7 9299 flap_route_vty_out(vty, &rn->p, pi, display,
a4d82a8a 9300 safi, use_json, json_paths);
98ce9a06 9301 else
40381db7 9302 route_vty_out(vty, &rn->p, pi, display, safi,
a4d82a8a 9303 json_paths);
98ce9a06 9304 display++;
d62a17ae 9305 }
9306
98ce9a06
DS
9307 if (display) {
9308 output_count++;
9309 if (!use_json)
9310 continue;
9311
9312 p = &rn->p;
625d2931
PG
9313 /* encode prefix */
9314 if (p->family == AF_FLOWSPEC) {
9315 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
9316
9317 bgp_fs_nlri_get_string((unsigned char *)
9318 p->u.prefix_flowspec.ptr,
9319 p->u.prefix_flowspec
9320 .prefixlen,
9321 retstr,
9322 NLRI_STRING_FORMAT_MIN,
9323 NULL);
9324 if (first)
9325 vty_out(vty, "\"%s/%d\": ",
9326 retstr,
9327 p->u.prefix_flowspec.prefixlen);
9328 else
9329 vty_out(vty, ",\"%s/%d\": ",
9330 retstr,
9331 p->u.prefix_flowspec.prefixlen);
9332 } else {
9333 prefix2str(p, buf2, sizeof(buf2));
9334 if (first)
9335 vty_out(vty, "\"%s\": ", buf2);
9336 else
9337 vty_out(vty, ",\"%s\": ", buf2);
9338 }
98ce9a06 9339 vty_out(vty, "%s",
23b2a7ef 9340 json_object_to_json_string(json_paths));
98ce9a06 9341 json_object_free(json_paths);
449feb8e 9342 json_paths = NULL;
98ce9a06
DS
9343 first = 0;
9344 }
9345 }
9346
1ae44dfc
LB
9347 if (output_cum) {
9348 output_count += *output_cum;
9349 *output_cum = output_count;
9350 }
9351 if (total_cum) {
9352 total_count += *total_cum;
9353 *total_cum = total_count;
9354 }
d62a17ae 9355 if (use_json) {
9386b588 9356 if (rd) {
a4d82a8a 9357 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
9358 }
9359 if (is_last) {
a4d82a8a
PZ
9360 unsigned long i;
9361 for (i = 0; i < *json_header_depth; ++i)
9362 vty_out(vty, " } ");
faf6559a 9363 vty_out(vty, "\n");
9386b588 9364 }
d62a17ae 9365 } else {
1ae44dfc
LB
9366 if (is_last) {
9367 /* No route is displayed */
9368 if (output_count == 0) {
9369 if (type == bgp_show_type_normal)
9370 vty_out(vty,
9371 "No BGP prefixes displayed, %ld exist\n",
9372 total_count);
9373 } else
d62a17ae 9374 vty_out(vty,
1ae44dfc
LB
9375 "\nDisplayed %ld routes and %ld total paths\n",
9376 output_count, total_count);
9377 }
d62a17ae 9378 }
718e3744 9379
d62a17ae 9380 return CMD_SUCCESS;
718e3744 9381}
9382
1ae44dfc
LB
9383int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
9384 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 9385 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc
LB
9386{
9387 struct bgp_node *rn, *next;
9388 unsigned long output_cum = 0;
9389 unsigned long total_cum = 0;
9386b588 9390 unsigned long json_header_depth = 0;
67009e22 9391 struct bgp_table *itable;
0136788c
LB
9392 bool show_msg;
9393
9394 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc
LB
9395
9396 for (rn = bgp_table_top(table); rn; rn = next) {
9397 next = bgp_route_next(rn);
9398 if (prd_match && memcmp(rn->p.u.val, prd_match->val, 8) != 0)
9399 continue;
67009e22
DS
9400
9401 itable = bgp_node_get_bgp_table_info(rn);
9402 if (itable != NULL) {
1ae44dfc 9403 struct prefix_rd prd;
06b9f471 9404 char rd[RD_ADDRSTRLEN];
1ae44dfc
LB
9405
9406 memcpy(&prd, &(rn->p), sizeof(struct prefix_rd));
06b9f471 9407 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22
DS
9408 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
9409 use_json, rd, next == NULL, &output_cum,
9410 &total_cum, &json_header_depth);
0136788c
LB
9411 if (next == NULL)
9412 show_msg = false;
1ae44dfc
LB
9413 }
9414 }
0136788c
LB
9415 if (show_msg) {
9416 if (output_cum == 0)
9417 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
9418 total_cum);
9419 else
9420 vty_out(vty,
9421 "\nDisplayed %ld routes and %ld total paths\n",
9422 output_cum, total_cum);
9423 }
1ae44dfc
LB
9424 return CMD_SUCCESS;
9425}
d62a17ae 9426static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
9f049418 9427 enum bgp_show_type type, void *output_arg, bool use_json)
fee0f4c6 9428{
d62a17ae 9429 struct bgp_table *table;
9386b588 9430 unsigned long json_header_depth = 0;
fee0f4c6 9431
d62a17ae 9432 if (bgp == NULL) {
9433 bgp = bgp_get_default();
9434 }
fee0f4c6 9435
d62a17ae 9436 if (bgp == NULL) {
9437 if (!use_json)
9438 vty_out(vty, "No BGP process is configured\n");
16307668
RW
9439 else
9440 vty_out(vty, "{}\n");
d62a17ae 9441 return CMD_WARNING;
9442 }
4dd6177e 9443
1ae44dfc 9444 table = bgp->rib[afi][safi];
d62a17ae 9445 /* use MPLS and ENCAP specific shows until they are merged */
9446 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
9447 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
9448 output_arg, use_json);
d62a17ae 9449 }
dba3c1d3
PG
9450
9451 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
9452 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
9453 output_arg, use_json,
9454 1, NULL, NULL);
9455 }
d62a17ae 9456 /* labeled-unicast routes live in the unicast table */
9457 else if (safi == SAFI_LABELED_UNICAST)
9458 safi = SAFI_UNICAST;
fee0f4c6 9459
1ae44dfc 9460 return bgp_show_table(vty, bgp, safi, table, type, output_arg, use_json,
9386b588 9461 NULL, 1, NULL, NULL, &json_header_depth);
fee0f4c6 9462}
9463
d62a17ae 9464static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
9f049418 9465 safi_t safi, bool use_json)
f186de26 9466{
d62a17ae 9467 struct listnode *node, *nnode;
9468 struct bgp *bgp;
9469 int is_first = 1;
9f049418 9470 bool route_output = false;
f186de26 9471
d62a17ae 9472 if (use_json)
9473 vty_out(vty, "{\n");
9f689658 9474
d62a17ae 9475 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 9476 route_output = true;
d62a17ae 9477 if (use_json) {
9478 if (!is_first)
9479 vty_out(vty, ",\n");
9480 else
9481 is_first = 0;
9482
9483 vty_out(vty, "\"%s\":",
9484 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 9485 ? VRF_DEFAULT_NAME
d62a17ae 9486 : bgp->name);
9487 } else {
9488 vty_out(vty, "\nInstance %s:\n",
9489 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 9490 ? VRF_DEFAULT_NAME
d62a17ae 9491 : bgp->name);
9492 }
9493 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
9494 use_json);
9495 }
9f689658 9496
d62a17ae 9497 if (use_json)
9498 vty_out(vty, "}\n");
9f049418
DS
9499 else if (!route_output)
9500 vty_out(vty, "%% BGP instance not found\n");
f186de26 9501}
9502
718e3744 9503/* Header of detailed BGP route information */
d62a17ae 9504void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9505 struct bgp_node *rn, struct prefix_rd *prd,
9506 afi_t afi, safi_t safi, json_object *json)
9507{
40381db7 9508 struct bgp_path_info *pi;
d62a17ae 9509 struct prefix *p;
9510 struct peer *peer;
9511 struct listnode *node, *nnode;
06b9f471 9512 char buf1[RD_ADDRSTRLEN];
d62a17ae 9513 char buf2[INET6_ADDRSTRLEN];
d62a17ae 9514 char buf3[EVPN_ROUTE_STRLEN];
0291c246 9515 char prefix_str[BUFSIZ];
d62a17ae 9516 int count = 0;
9517 int best = 0;
9518 int suppress = 0;
c5f1e1b2
C
9519 int accept_own = 0;
9520 int route_filter_translated_v4 = 0;
9521 int route_filter_v4 = 0;
9522 int route_filter_translated_v6 = 0;
9523 int route_filter_v6 = 0;
9524 int llgr_stale = 0;
9525 int no_llgr = 0;
9526 int accept_own_nexthop = 0;
9527 int blackhole = 0;
d62a17ae 9528 int no_export = 0;
9529 int no_advertise = 0;
9530 int local_as = 0;
c5f1e1b2 9531 int no_peer = 0;
d62a17ae 9532 int first = 1;
9533 int has_valid_label = 0;
9534 mpls_label_t label = 0;
9535 json_object *json_adv_to = NULL;
9bedbb1e 9536
d62a17ae 9537 p = &rn->p;
9538 has_valid_label = bgp_is_valid_label(&rn->local_label);
9539
9540 if (has_valid_label)
9541 label = label_pton(&rn->local_label);
9542
44c69747 9543 if (safi == SAFI_EVPN) {
d62a17ae 9544
44c69747 9545 if (!json) {
d62a17ae 9546 vty_out(vty, "BGP routing table entry for %s%s%s\n",
06b9f471 9547 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
44c69747 9548 : "", prd ? ":" : "",
d62a17ae 9549 bgp_evpn_route2str((struct prefix_evpn *)p,
44c69747
LK
9550 buf3, sizeof(buf3)));
9551 } else {
9552 json_object_string_add(json, "rd",
9553 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
9554 "");
9555 bgp_evpn_route2json((struct prefix_evpn *)p, json);
9556 }
9557 } else {
9558 if (!json) {
d62a17ae 9559 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
9560 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
44c69747
LK
9561 ? prefix_rd2str(prd, buf1,
9562 sizeof(buf1))
9563 : ""),
d62a17ae 9564 safi == SAFI_MPLS_VPN ? ":" : "",
9565 inet_ntop(p->family, &p->u.prefix, buf2,
44c69747 9566 INET6_ADDRSTRLEN),
d62a17ae 9567 p->prefixlen);
cd1964ff 9568
44c69747
LK
9569 } else
9570 json_object_string_add(json, "prefix",
9571 prefix2str(p, prefix_str, sizeof(prefix_str)));
9572 }
9573
9574 if (has_valid_label) {
9575 if (json)
9576 json_object_int_add(json, "localLabel", label);
9577 else
d62a17ae 9578 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
9579 }
9580
9581 if (!json)
d62a17ae 9582 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 9583 vty_out(vty, "not allocated\n");
718e3744 9584
6f94b685 9585 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
d62a17ae 9586 count++;
40381db7 9587 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 9588 best = count;
40381db7 9589 if (pi->extra && pi->extra->suppress)
d62a17ae 9590 suppress = 1;
cee9c031 9591
40381db7 9592 if (pi->attr->community == NULL)
cee9c031
QY
9593 continue;
9594
9595 no_advertise += community_include(
40381db7
DS
9596 pi->attr->community, COMMUNITY_NO_ADVERTISE);
9597 no_export += community_include(pi->attr->community,
cee9c031 9598 COMMUNITY_NO_EXPORT);
40381db7 9599 local_as += community_include(pi->attr->community,
cee9c031 9600 COMMUNITY_LOCAL_AS);
40381db7 9601 accept_own += community_include(pi->attr->community,
cee9c031
QY
9602 COMMUNITY_ACCEPT_OWN);
9603 route_filter_translated_v4 += community_include(
40381db7 9604 pi->attr->community,
cee9c031
QY
9605 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
9606 route_filter_translated_v6 += community_include(
40381db7 9607 pi->attr->community,
cee9c031
QY
9608 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
9609 route_filter_v4 += community_include(
40381db7 9610 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 9611 route_filter_v6 += community_include(
40381db7
DS
9612 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
9613 llgr_stale += community_include(pi->attr->community,
cee9c031 9614 COMMUNITY_LLGR_STALE);
40381db7 9615 no_llgr += community_include(pi->attr->community,
cee9c031
QY
9616 COMMUNITY_NO_LLGR);
9617 accept_own_nexthop +=
40381db7 9618 community_include(pi->attr->community,
cee9c031 9619 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 9620 blackhole += community_include(pi->attr->community,
cee9c031 9621 COMMUNITY_BLACKHOLE);
40381db7 9622 no_peer += community_include(pi->attr->community,
cee9c031 9623 COMMUNITY_NO_PEER);
d62a17ae 9624 }
718e3744 9625 }
718e3744 9626
d62a17ae 9627 if (!json) {
9628 vty_out(vty, "Paths: (%d available", count);
9629 if (best) {
9630 vty_out(vty, ", best #%d", best);
b84060bb
PG
9631 if (safi == SAFI_UNICAST) {
9632 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
9633 vty_out(vty, ", table %s",
9634 VRF_DEFAULT_NAME);
9635 else
9636 vty_out(vty, ", vrf %s",
9637 bgp->name);
9638 }
d62a17ae 9639 } else
9640 vty_out(vty, ", no best path");
9641
c5f1e1b2
C
9642 if (accept_own)
9643 vty_out(vty,
9644 ", accept own local route exported and imported in different VRF");
9645 else if (route_filter_translated_v4)
9646 vty_out(vty,
9647 ", mark translated RTs for VPNv4 route filtering");
9648 else if (route_filter_v4)
9649 vty_out(vty,
9650 ", attach RT as-is for VPNv4 route filtering");
9651 else if (route_filter_translated_v6)
9652 vty_out(vty,
9653 ", mark translated RTs for VPNv6 route filtering");
9654 else if (route_filter_v6)
9655 vty_out(vty,
9656 ", attach RT as-is for VPNv6 route filtering");
9657 else if (llgr_stale)
9658 vty_out(vty,
9659 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9660 else if (no_llgr)
9661 vty_out(vty,
9662 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9663 else if (accept_own_nexthop)
9664 vty_out(vty,
9665 ", accept local nexthop");
9666 else if (blackhole)
9667 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 9668 else if (no_export)
9669 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
9670 else if (no_advertise)
9671 vty_out(vty, ", not advertised to any peer");
d62a17ae 9672 else if (local_as)
9673 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
9674 else if (no_peer)
9675 vty_out(vty,
9676 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 9677
9678 if (suppress)
9679 vty_out(vty,
9680 ", Advertisements suppressed by an aggregate.");
9681 vty_out(vty, ")\n");
9682 }
718e3744 9683
d62a17ae 9684 /* If we are not using addpath then we can display Advertised to and
9685 * that will
9686 * show what peers we advertised the bestpath to. If we are using
9687 * addpath
9688 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 9689 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 9690 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9691 if (bgp_adj_out_lookup(peer, rn, 0)) {
9692 if (json && !json_adv_to)
9693 json_adv_to = json_object_new_object();
9694
9695 route_vty_out_advertised_to(
9696 vty, peer, &first,
9697 " Advertised to non peer-group peers:\n ",
9698 json_adv_to);
9699 }
9700 }
9701
9702 if (json) {
9703 if (json_adv_to) {
9704 json_object_object_add(json, "advertisedTo",
9705 json_adv_to);
9706 }
9707 } else {
9708 if (first)
9709 vty_out(vty, " Not advertised to any peer");
9710 vty_out(vty, "\n");
9711 }
9712 }
718e3744 9713}
9714
44c69747
LK
9715static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9716 struct bgp_node *bgp_node, struct vty *vty,
9717 struct bgp *bgp, afi_t afi,
9718 safi_t safi, json_object *json,
9719 enum bgp_path_type pathtype, int *display)
9720{
9721 struct bgp_path_info *pi;
9722 int header = 1;
9723 char rdbuf[RD_ADDRSTRLEN];
9724 json_object *json_header = NULL;
9725 json_object *json_paths = NULL;
9726
9727 for (pi = bgp_node_get_bgp_path_info(bgp_node); pi;
9728 pi = pi->next) {
9729
9730 if (json && !json_paths) {
9731 /* Instantiate json_paths only if path is valid */
9732 json_paths = json_object_new_array();
9733 if (pfx_rd) {
9734 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
9735 json_header = json_object_new_object();
9736 } else
9737 json_header = json;
9738 }
9739
9740 if (header) {
9741 route_vty_out_detail_header(
9742 vty, bgp, bgp_node, pfx_rd,
9743 AFI_IP, safi, json_header);
9744 header = 0;
9745 }
9746 (*display)++;
9747
9748 if (pathtype == BGP_PATH_SHOW_ALL
9749 || (pathtype == BGP_PATH_SHOW_BESTPATH
9750 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
9751 || (pathtype == BGP_PATH_SHOW_MULTIPATH
9752 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
9753 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
9754 route_vty_out_detail(vty, bgp, bgp_node,
9755 pi, AFI_IP, safi,
9756 json_paths);
9757 }
9758
9759 if (json && json_paths) {
9760 json_object_object_add(json_header, "paths", json_paths);
9761
9762 if (pfx_rd)
9763 json_object_object_add(json, rdbuf, json_header);
9764 }
9765}
9766
718e3744 9767/* Display specified route of BGP table. */
d62a17ae 9768static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
9769 struct bgp_table *rib, const char *ip_str,
9770 afi_t afi, safi_t safi,
9771 struct prefix_rd *prd, int prefix_check,
9f049418 9772 enum bgp_path_type pathtype, bool use_json)
d62a17ae 9773{
9774 int ret;
d62a17ae 9775 int display = 0;
9776 struct prefix match;
9777 struct bgp_node *rn;
9778 struct bgp_node *rm;
d62a17ae 9779 struct bgp_table *table;
9780 json_object *json = NULL;
9781 json_object *json_paths = NULL;
9782
9783 /* Check IP address argument. */
9784 ret = str2prefix(ip_str, &match);
9785 if (!ret) {
9786 vty_out(vty, "address is malformed\n");
9787 return CMD_WARNING;
9788 }
718e3744 9789
d62a17ae 9790 match.family = afi2family(afi);
b05a1c8b 9791
44c69747 9792 if (use_json)
d62a17ae 9793 json = json_object_new_object();
718e3744 9794
44c69747 9795 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
d62a17ae 9796 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
9797 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
9798 continue;
67009e22
DS
9799 table = bgp_node_get_bgp_table_info(rn);
9800 if (!table)
ea47320b 9801 continue;
d62a17ae 9802
ea47320b
DL
9803 if ((rm = bgp_node_match(table, &match)) == NULL)
9804 continue;
d62a17ae 9805
ea47320b
DL
9806 if (prefix_check
9807 && rm->p.prefixlen != match.prefixlen) {
9808 bgp_unlock_node(rm);
9809 continue;
9810 }
d62a17ae 9811
44c69747
LK
9812 bgp_show_path_info((struct prefix_rd *)&rn->p, rm,
9813 vty, bgp, afi, safi, json,
9814 pathtype, &display);
9815
9816 bgp_unlock_node(rm);
9817 }
9818 } else if (safi == SAFI_EVPN) {
9819 struct bgp_node *longest_pfx;
9820 bool is_exact_pfxlen_match = FALSE;
9821
9822 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
9823 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
9824 continue;
9825 table = bgp_node_get_bgp_table_info(rn);
9826 if (!table)
9827 continue;
9828
9829 longest_pfx = NULL;
9830 is_exact_pfxlen_match = FALSE;
9831 /*
9832 * Search through all the prefixes for a match. The
9833 * pfx's are enumerated in ascending order of pfxlens.
9834 * So, the last pfx match is the longest match. Set
9835 * is_exact_pfxlen_match when we get exact pfxlen match
9836 */
9837 for (rm = bgp_table_top(table); rm;
9838 rm = bgp_route_next(rm)) {
9839 /*
9840 * Get prefixlen of the ip-prefix within type5
9841 * evpn route
9842 */
9843 if (evpn_type5_prefix_match(&rm->p,
9844 &match) && rm->info) {
9845 longest_pfx = rm;
9846 int type5_pfxlen =
9847 bgp_evpn_get_type5_prefixlen(&rm->p);
9848 if (type5_pfxlen == match.prefixlen) {
9849 is_exact_pfxlen_match = TRUE;
9850 bgp_unlock_node(rm);
9851 break;
9852 }
d62a17ae 9853 }
9854 }
ea47320b 9855
44c69747
LK
9856 if (!longest_pfx)
9857 continue;
9858
9859 if (prefix_check && !is_exact_pfxlen_match)
9860 continue;
9861
9862 rm = longest_pfx;
9863 bgp_lock_node(rm);
9864
9865 bgp_show_path_info((struct prefix_rd *)&rn->p, rm,
9866 vty, bgp, afi, safi, json,
9867 pathtype, &display);
9868
ea47320b 9869 bgp_unlock_node(rm);
d62a17ae 9870 }
98a9dbc7 9871 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
9872 if (use_json)
9873 json_paths = json_object_new_array();
9874
63a0b7a9
PG
9875 display = bgp_flowspec_display_match_per_ip(afi, rib,
9876 &match, prefix_check,
9877 vty,
9878 use_json,
9879 json_paths);
44c69747
LK
9880 if (use_json && display)
9881 json_object_object_add(json, "paths", json_paths);
d62a17ae 9882 } else {
d62a17ae 9883 if ((rn = bgp_node_match(rib, &match)) != NULL) {
9884 if (!prefix_check
9885 || rn->p.prefixlen == match.prefixlen) {
44c69747
LK
9886 bgp_show_path_info(NULL, rn, vty, bgp, afi,
9887 safi, json,
9888 pathtype, &display);
d62a17ae 9889 }
9890
9891 bgp_unlock_node(rn);
9892 }
9893 }
e5eee9af 9894
d62a17ae 9895 if (use_json) {
996c9314 9896 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
9897 json, JSON_C_TO_STRING_PRETTY |
9898 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 9899 json_object_free(json);
9900 } else {
9901 if (!display) {
9902 vty_out(vty, "%% Network not in table\n");
9903 return CMD_WARNING;
9904 }
9905 }
b05a1c8b 9906
d62a17ae 9907 return CMD_SUCCESS;
718e3744 9908}
9909
fee0f4c6 9910/* Display specified route of Main RIB */
d62a17ae 9911static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
9912 afi_t afi, safi_t safi, struct prefix_rd *prd,
9913 int prefix_check, enum bgp_path_type pathtype,
9f049418 9914 bool use_json)
d62a17ae 9915{
9b86009a 9916 if (!bgp) {
d62a17ae 9917 bgp = bgp_get_default();
9b86009a
RW
9918 if (!bgp) {
9919 if (!use_json)
9920 vty_out(vty, "No BGP process is configured\n");
16307668
RW
9921 else
9922 vty_out(vty, "{}\n");
9b86009a
RW
9923 return CMD_WARNING;
9924 }
9925 }
d62a17ae 9926
9927 /* labeled-unicast routes live in the unicast table */
9928 if (safi == SAFI_LABELED_UNICAST)
9929 safi = SAFI_UNICAST;
9930
9931 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
9932 afi, safi, prd, prefix_check, pathtype,
9933 use_json);
9934}
9935
9936static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 9937 struct cmd_token **argv, bool exact, afi_t afi,
9938 safi_t safi, bool uj)
d62a17ae 9939{
9940 struct lcommunity *lcom;
9941 struct buffer *b;
9942 int i;
9943 char *str;
9944 int first = 0;
9945
9946 b = buffer_new(1024);
9947 for (i = 0; i < argc; i++) {
9948 if (first)
9949 buffer_putc(b, ' ');
9950 else {
9951 if (strmatch(argv[i]->text, "AA:BB:CC")) {
9952 first = 1;
9953 buffer_putstr(b, argv[i]->arg);
9954 }
9955 }
9956 }
9957 buffer_putc(b, '\0');
57d187bc 9958
d62a17ae 9959 str = buffer_getstr(b);
9960 buffer_free(b);
57d187bc 9961
d62a17ae 9962 lcom = lcommunity_str2com(str);
9963 XFREE(MTYPE_TMP, str);
9964 if (!lcom) {
9965 vty_out(vty, "%% Large-community malformed\n");
9966 return CMD_WARNING;
9967 }
57d187bc 9968
36a206db 9969 return bgp_show(vty, bgp, afi, safi,
9970 (exact ? bgp_show_type_lcommunity_exact
9971 : bgp_show_type_lcommunity),
9972 lcom, uj);
57d187bc
JS
9973}
9974
d62a17ae 9975static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 9976 const char *lcom, bool exact, afi_t afi,
9977 safi_t safi, bool uj)
57d187bc 9978{
d62a17ae 9979 struct community_list *list;
57d187bc 9980
e237b0d2 9981 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 9982 LARGE_COMMUNITY_LIST_MASTER);
9983 if (list == NULL) {
9984 vty_out(vty, "%% %s is not a valid large-community-list name\n",
9985 lcom);
9986 return CMD_WARNING;
9987 }
57d187bc 9988
36a206db 9989 return bgp_show(vty, bgp, afi, safi,
9990 (exact ? bgp_show_type_lcommunity_list_exact
9991 : bgp_show_type_lcommunity_list),
d62a17ae 9992 list, uj);
fee0f4c6 9993}
9994
52951b63
DS
9995DEFUN (show_ip_bgp_large_community_list,
9996 show_ip_bgp_large_community_list_cmd,
36a206db 9997 "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
9998 SHOW_STR
9999 IP_STR
10000 BGP_STR
10001 BGP_INSTANCE_HELP_STR
9bedbb1e 10002 BGP_AFI_HELP_STR
4dd6177e 10003 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10004 "Display routes matching the large-community-list\n"
10005 "large-community-list number\n"
10006 "large-community-list name\n"
36a206db 10007 "Exact match of the large-communities\n"
52951b63
DS
10008 JSON_STR)
10009{
d62a17ae 10010 char *vrf = NULL;
10011 afi_t afi = AFI_IP6;
10012 safi_t safi = SAFI_UNICAST;
10013 int idx = 0;
36a206db 10014 bool exact_match = 0;
d62a17ae 10015
10016 if (argv_find(argv, argc, "ip", &idx))
10017 afi = AFI_IP;
10018 if (argv_find(argv, argc, "view", &idx)
10019 || argv_find(argv, argc, "vrf", &idx))
10020 vrf = argv[++idx]->arg;
10021 if (argv_find(argv, argc, "ipv4", &idx)
10022 || argv_find(argv, argc, "ipv6", &idx)) {
10023 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
10024 if (argv_find(argv, argc, "unicast", &idx)
10025 || argv_find(argv, argc, "multicast", &idx))
10026 safi = bgp_vty_safi_from_str(argv[idx]->text);
10027 }
10028
9f049418 10029 bool uj = use_json(argc, argv);
d62a17ae 10030
10031 struct bgp *bgp = bgp_lookup_by_name(vrf);
10032 if (bgp == NULL) {
10033 vty_out(vty, "Can't find BGP instance %s\n", vrf);
10034 return CMD_WARNING;
10035 }
10036
10037 argv_find(argv, argc, "large-community-list", &idx);
36a206db 10038
10039 const char *clist_number_or_name = argv[++idx]->arg;
10040
10041 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10042 exact_match = 1;
10043
10044 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
10045 exact_match, afi, safi, uj);
52951b63
DS
10046}
10047DEFUN (show_ip_bgp_large_community,
10048 show_ip_bgp_large_community_cmd,
36a206db 10049 "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
10050 SHOW_STR
10051 IP_STR
10052 BGP_STR
10053 BGP_INSTANCE_HELP_STR
9bedbb1e 10054 BGP_AFI_HELP_STR
4dd6177e 10055 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10056 "Display routes matching the large-communities\n"
10057 "List of large-community numbers\n"
36a206db 10058 "Exact match of the large-communities\n"
52951b63
DS
10059 JSON_STR)
10060{
d62a17ae 10061 char *vrf = NULL;
10062 afi_t afi = AFI_IP6;
10063 safi_t safi = SAFI_UNICAST;
10064 int idx = 0;
36a206db 10065 bool exact_match = 0;
d62a17ae 10066
10067 if (argv_find(argv, argc, "ip", &idx))
10068 afi = AFI_IP;
10069 if (argv_find(argv, argc, "view", &idx)
10070 || argv_find(argv, argc, "vrf", &idx))
10071 vrf = argv[++idx]->arg;
10072 if (argv_find(argv, argc, "ipv4", &idx)
10073 || argv_find(argv, argc, "ipv6", &idx)) {
10074 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
10075 if (argv_find(argv, argc, "unicast", &idx)
10076 || argv_find(argv, argc, "multicast", &idx))
10077 safi = bgp_vty_safi_from_str(argv[idx]->text);
10078 }
10079
9f049418 10080 bool uj = use_json(argc, argv);
d62a17ae 10081
10082 struct bgp *bgp = bgp_lookup_by_name(vrf);
10083 if (bgp == NULL) {
10084 vty_out(vty, "Can't find BGP instance %s\n", vrf);
10085 return CMD_WARNING;
10086 }
10087
36a206db 10088 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
10089 if (argv_find(argv, argc, "exact-match", &idx))
10090 exact_match = 1;
10091 return bgp_show_lcommunity(vty, bgp, argc, argv,
10092 exact_match, afi, safi, uj);
10093 } else
d62a17ae 10094 return bgp_show(vty, bgp, afi, safi,
10095 bgp_show_type_lcommunity_all, NULL, uj);
52951b63
DS
10096}
10097
d62a17ae 10098static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
10099 safi_t safi);
e01ca200 10100
7b2ff250
DW
10101
10102/* BGP route print out function without JSON */
af462945
DS
10103DEFUN (show_ip_bgp,
10104 show_ip_bgp_cmd,
4dd6177e 10105 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
7b2ff250
DW
10106 <dampening <parameters>\
10107 |route-map WORD\
10108 |prefix-list WORD\
10109 |filter-list WORD\
10110 |statistics\
7b2ff250
DW
10111 |community-list <(1-500)|WORD> [exact-match]\
10112 |A.B.C.D/M longer-prefixes\
10113 |X:X::X:X/M longer-prefixes\
10114 >",
718e3744 10115 SHOW_STR
10116 IP_STR
10117 BGP_STR
a636c635 10118 BGP_INSTANCE_HELP_STR
4f280b15 10119 BGP_AFI_HELP_STR
4dd6177e 10120 BGP_SAFI_WITH_LABEL_HELP_STR
a636c635 10121 "Display detailed information about dampening\n"
af462945 10122 "Display detail of configured dampening parameters\n"
a636c635
DW
10123 "Display routes matching the route-map\n"
10124 "A route-map to match on\n"
10125 "Display routes conforming to the prefix-list\n"
8c3deaae 10126 "Prefix-list name\n"
a636c635
DW
10127 "Display routes conforming to the filter-list\n"
10128 "Regular expression access list name\n"
e01ca200 10129 "BGP RIB advertisement statistics\n"
a636c635
DW
10130 "Display routes matching the community-list\n"
10131 "community-list number\n"
10132 "community-list name\n"
10133 "Exact match of the communities\n"
0c7b1b01 10134 "IPv4 prefix\n"
8c3deaae 10135 "Display route and more specific routes\n"
0c7b1b01 10136 "IPv6 prefix\n"
7b2ff250 10137 "Display route and more specific routes\n")
718e3744 10138{
d62a17ae 10139 afi_t afi = AFI_IP6;
10140 safi_t safi = SAFI_UNICAST;
10141 int exact_match = 0;
d62a17ae 10142 struct bgp *bgp = NULL;
10143 int idx = 0;
10144
10145 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10146 &bgp, false);
d62a17ae 10147 if (!idx)
10148 return CMD_WARNING;
10149
d62a17ae 10150 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 10151 if (argv_find(argv, argc, "parameters", &idx))
d62a17ae 10152 return bgp_show_dampening_parameters(vty, afi, safi);
10153 }
c016b6c7 10154
d62a17ae 10155 if (argv_find(argv, argc, "prefix-list", &idx))
10156 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
10157 safi, bgp_show_type_prefix_list);
10158
10159 if (argv_find(argv, argc, "filter-list", &idx))
10160 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
10161 safi, bgp_show_type_filter_list);
10162
10163 if (argv_find(argv, argc, "statistics", &idx))
10164 return bgp_table_stats(vty, bgp, afi, safi);
10165
10166 if (argv_find(argv, argc, "route-map", &idx))
10167 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
10168 safi, bgp_show_type_route_map);
10169
d62a17ae 10170 if (argv_find(argv, argc, "community-list", &idx)) {
10171 const char *clist_number_or_name = argv[++idx]->arg;
10172 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10173 exact_match = 1;
10174 return bgp_show_community_list(vty, bgp, clist_number_or_name,
10175 exact_match, afi, safi);
10176 }
10177 /* prefix-longer */
10178 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10179 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10180 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
10181 safi,
10182 bgp_show_type_prefix_longer);
10183
7b2ff250
DW
10184 return CMD_WARNING;
10185}
10186
10187/* BGP route print out function with JSON */
10188DEFUN (show_ip_bgp_json,
10189 show_ip_bgp_json_cmd,
10190 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
cf4898bc
QY
10191 [cidr-only\
10192 |dampening <flap-statistics|dampened-paths>\
10193 |community [AA:NN|local-AS|no-advertise|no-export\
10194 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10195 |accept-own|accept-own-nexthop|route-filter-v6\
10196 |route-filter-v4|route-filter-translated-v6\
10197 |route-filter-translated-v4] [exact-match]\
10198 ] [json]",
7b2ff250
DW
10199 SHOW_STR
10200 IP_STR
10201 BGP_STR
10202 BGP_INSTANCE_HELP_STR
10203 BGP_AFI_HELP_STR
10204 BGP_SAFI_WITH_LABEL_HELP_STR
10205 "Display only routes with non-natural netmasks\n"
10206 "Display detailed information about dampening\n"
10207 "Display flap statistics of routes\n"
10208 "Display paths suppressed due to dampening\n"
10209 "Display routes matching the communities\n"
d0086e8e
AD
10210 COMMUNITY_AANN_STR
10211 "Do not send outside local AS (well-known community)\n"
10212 "Do not advertise to any peer (well-known community)\n"
10213 "Do not export to next AS (well-known community)\n"
10214 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
10215 "Do not export to any peer (well-known community)\n"
10216 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10217 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10218 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10219 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10220 "Should accept VPN route with local nexthop (well-known community)\n"
10221 "RT VPNv6 route filtering (well-known community)\n"
10222 "RT VPNv4 route filtering (well-known community)\n"
10223 "RT translated VPNv6 route filtering (well-known community)\n"
10224 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 10225 "Exact match of the communities\n"
7b2ff250
DW
10226 JSON_STR)
10227{
10228 afi_t afi = AFI_IP6;
10229 safi_t safi = SAFI_UNICAST;
10230 enum bgp_show_type sh_type = bgp_show_type_normal;
10231 struct bgp *bgp = NULL;
10232 int idx = 0;
d0086e8e 10233 int exact_match = 0;
9f049418
DS
10234 bool uj = use_json(argc, argv);
10235
10236 if (uj)
10237 argc--;
7b2ff250
DW
10238
10239 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10240 &bgp, uj);
7b2ff250
DW
10241 if (!idx)
10242 return CMD_WARNING;
10243
7b2ff250
DW
10244 if (argv_find(argv, argc, "cidr-only", &idx))
10245 return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
10246 NULL, uj);
10247
10248 if (argv_find(argv, argc, "dampening", &idx)) {
10249 if (argv_find(argv, argc, "dampened-paths", &idx))
10250 return bgp_show(vty, bgp, afi, safi,
10251 bgp_show_type_dampend_paths, NULL, uj);
10252 else if (argv_find(argv, argc, "flap-statistics", &idx))
10253 return bgp_show(vty, bgp, afi, safi,
10254 bgp_show_type_flap_statistics, NULL,
10255 uj);
10256 }
10257
10258 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 10259 char *maybecomm = NULL;
cf4898bc 10260 char *community = NULL;
d0086e8e 10261
79bc257a
RW
10262 if (idx + 1 < argc) {
10263 if (argv[idx + 1]->type == VARIABLE_TKN)
10264 maybecomm = argv[idx + 1]->arg;
10265 else
10266 maybecomm = argv[idx + 1]->text;
10267 }
10268
cf4898bc
QY
10269 if (maybecomm && !strmatch(maybecomm, "json")
10270 && !strmatch(maybecomm, "exact-match"))
10271 community = maybecomm;
d0086e8e 10272
cf4898bc
QY
10273 if (argv_find(argv, argc, "exact-match", &idx))
10274 exact_match = 1;
d0086e8e 10275
cf4898bc
QY
10276 if (community)
10277 return bgp_show_community(vty, bgp, community,
10278 exact_match, afi, safi, uj);
10279 else
d0086e8e 10280 return (bgp_show(vty, bgp, afi, safi,
cf4898bc
QY
10281 bgp_show_type_community_all, NULL,
10282 uj));
7b2ff250 10283 }
d0086e8e 10284
1ae44dfc 10285 return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj);
a636c635 10286}
47fc97cc 10287
718e3744 10288DEFUN (show_ip_bgp_route,
10289 show_ip_bgp_route_cmd,
4dd6177e 10290 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]"
ae19d7dd 10291 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
718e3744 10292 SHOW_STR
10293 IP_STR
10294 BGP_STR
a636c635 10295 BGP_INSTANCE_HELP_STR
4f280b15 10296 BGP_AFI_HELP_STR
4dd6177e 10297 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 10298 "Network in the BGP routing table to display\n"
0c7b1b01 10299 "IPv4 prefix\n"
8c3deaae 10300 "Network in the BGP routing table to display\n"
0c7b1b01 10301 "IPv6 prefix\n"
4092b06c 10302 "Display only the bestpath\n"
b05a1c8b 10303 "Display only multipaths\n"
9973d184 10304 JSON_STR)
4092b06c 10305{
d62a17ae 10306 int prefix_check = 0;
ae19d7dd 10307
d62a17ae 10308 afi_t afi = AFI_IP6;
10309 safi_t safi = SAFI_UNICAST;
10310 char *prefix = NULL;
10311 struct bgp *bgp = NULL;
10312 enum bgp_path_type path_type;
9f049418 10313 bool uj = use_json(argc, argv);
b05a1c8b 10314
d62a17ae 10315 int idx = 0;
ae19d7dd 10316
d62a17ae 10317 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10318 &bgp, uj);
d62a17ae 10319 if (!idx)
10320 return CMD_WARNING;
c41247f5 10321
d62a17ae 10322 if (!bgp) {
10323 vty_out(vty,
10324 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10325 return CMD_WARNING;
10326 }
a636c635 10327
d62a17ae 10328 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10329 if (argv_find(argv, argc, "A.B.C.D", &idx)
10330 || argv_find(argv, argc, "X:X::X:X", &idx))
10331 prefix_check = 0;
10332 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10333 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10334 prefix_check = 1;
10335
10336 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
10337 && afi != AFI_IP6) {
10338 vty_out(vty,
10339 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10340 return CMD_WARNING;
10341 }
10342 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
10343 && afi != AFI_IP) {
10344 vty_out(vty,
10345 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10346 return CMD_WARNING;
10347 }
10348
10349 prefix = argv[idx]->arg;
10350
10351 /* [<bestpath|multipath>] */
10352 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 10353 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 10354 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 10355 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 10356 else
360660c6 10357 path_type = BGP_PATH_SHOW_ALL;
a636c635 10358
d62a17ae 10359 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
10360 path_type, uj);
4092b06c
DS
10361}
10362
8c3deaae
QY
10363DEFUN (show_ip_bgp_regexp,
10364 show_ip_bgp_regexp_cmd,
4dd6177e 10365 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX...",
8c3deaae
QY
10366 SHOW_STR
10367 IP_STR
10368 BGP_STR
b00b230a 10369 BGP_INSTANCE_HELP_STR
4f280b15 10370 BGP_AFI_HELP_STR
4dd6177e 10371 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 10372 "Display routes matching the AS path regular expression\n"
a818ea74 10373 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n")
8c3deaae 10374{
d62a17ae 10375 afi_t afi = AFI_IP6;
10376 safi_t safi = SAFI_UNICAST;
10377 struct bgp *bgp = NULL;
8c3deaae 10378
d62a17ae 10379 int idx = 0;
10380 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10381 &bgp, false);
d62a17ae 10382 if (!idx)
10383 return CMD_WARNING;
8c3deaae 10384
d62a17ae 10385 // get index of regex
10386 argv_find(argv, argc, "regexp", &idx);
10387 idx++;
8c3deaae 10388
d62a17ae 10389 char *regstr = argv_concat(argv, argc, idx);
e889891d 10390 int rc = bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
d62a17ae 10391 bgp_show_type_regexp);
10392 XFREE(MTYPE_TMP, regstr);
10393 return rc;
8c3deaae
QY
10394}
10395
a636c635
DW
10396DEFUN (show_ip_bgp_instance_all,
10397 show_ip_bgp_instance_all_cmd,
4dd6177e 10398 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json]",
4092b06c 10399 SHOW_STR
a636c635 10400 IP_STR
4092b06c 10401 BGP_STR
a636c635 10402 BGP_INSTANCE_ALL_HELP_STR
4f280b15 10403 BGP_AFI_HELP_STR
4dd6177e 10404 BGP_SAFI_WITH_LABEL_HELP_STR
9973d184 10405 JSON_STR)
4092b06c 10406{
d62a17ae 10407 afi_t afi = AFI_IP;
10408 safi_t safi = SAFI_UNICAST;
10409 struct bgp *bgp = NULL;
d62a17ae 10410 int idx = 0;
9f049418 10411 bool uj = use_json(argc, argv);
ae19d7dd 10412
d62a17ae 10413 if (uj)
10414 argc--;
e3e29b32 10415
9f049418
DS
10416 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10417 &bgp, uj);
10418 if (!idx)
10419 return CMD_WARNING;
10420
d62a17ae 10421 bgp_show_all_instances_routes_vty(vty, afi, safi, uj);
10422 return CMD_SUCCESS;
e3e29b32
LB
10423}
10424
a4d82a8a
PZ
10425static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
10426 afi_t afi, safi_t safi, enum bgp_show_type type)
718e3744 10427{
d62a17ae 10428 regex_t *regex;
10429 int rc;
e3e29b32 10430
c3900853
DA
10431 if (!config_bgp_aspath_validate(regstr)) {
10432 vty_out(vty, "Invalid character in as-path access-list %s\n",
10433 regstr);
10434 return CMD_WARNING_CONFIG_FAILED;
10435 }
10436
d62a17ae 10437 regex = bgp_regcomp(regstr);
10438 if (!regex) {
10439 vty_out(vty, "Can't compile regexp %s\n", regstr);
10440 return CMD_WARNING;
10441 }
a636c635 10442
e889891d 10443 rc = bgp_show(vty, bgp, afi, safi, type, regex, 0);
d62a17ae 10444 bgp_regex_free(regex);
10445 return rc;
e3e29b32
LB
10446}
10447
d62a17ae 10448static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10449 const char *prefix_list_str, afi_t afi,
10450 safi_t safi, enum bgp_show_type type)
e3e29b32 10451{
d62a17ae 10452 struct prefix_list *plist;
718e3744 10453
d62a17ae 10454 plist = prefix_list_lookup(afi, prefix_list_str);
10455 if (plist == NULL) {
10456 vty_out(vty, "%% %s is not a valid prefix-list name\n",
10457 prefix_list_str);
10458 return CMD_WARNING;
10459 }
718e3744 10460
d62a17ae 10461 return bgp_show(vty, bgp, afi, safi, type, plist, 0);
4092b06c
DS
10462}
10463
d62a17ae 10464static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10465 const char *filter, afi_t afi, safi_t safi,
10466 enum bgp_show_type type)
4092b06c 10467{
d62a17ae 10468 struct as_list *as_list;
718e3744 10469
d62a17ae 10470 as_list = as_list_lookup(filter);
10471 if (as_list == NULL) {
10472 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
10473 filter);
10474 return CMD_WARNING;
10475 }
a636c635 10476
d62a17ae 10477 return bgp_show(vty, bgp, afi, safi, type, as_list, 0);
718e3744 10478}
10479
d62a17ae 10480static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10481 const char *rmap_str, afi_t afi, safi_t safi,
10482 enum bgp_show_type type)
718e3744 10483{
d62a17ae 10484 struct route_map *rmap;
bb46e94f 10485
d62a17ae 10486 rmap = route_map_lookup_by_name(rmap_str);
10487 if (!rmap) {
10488 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
10489 return CMD_WARNING;
10490 }
10491
10492 return bgp_show(vty, bgp, afi, safi, type, rmap, 0);
10493}
10494
7f323236
DW
10495static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10496 const char *comstr, int exact, afi_t afi,
9f049418 10497 safi_t safi, bool use_json)
d62a17ae 10498{
10499 struct community *com;
d62a17ae 10500 int ret = 0;
10501
7f323236 10502 com = community_str2com(comstr);
d62a17ae 10503 if (!com) {
7f323236 10504 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 10505 return CMD_WARNING;
10506 }
10507
10508 ret = bgp_show(vty, bgp, afi, safi,
10509 (exact ? bgp_show_type_community_exact
10510 : bgp_show_type_community),
d0086e8e 10511 com, use_json);
3c1f53de 10512 community_free(&com);
46c3ce83 10513
d62a17ae 10514 return ret;
718e3744 10515}
10516
d62a17ae 10517static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10518 const char *com, int exact, afi_t afi,
10519 safi_t safi)
50ef26d4 10520{
d62a17ae 10521 struct community_list *list;
50ef26d4 10522
e237b0d2 10523 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 10524 if (list == NULL) {
10525 vty_out(vty, "%% %s is not a valid community-list name\n", com);
10526 return CMD_WARNING;
10527 }
718e3744 10528
d62a17ae 10529 return bgp_show(vty, bgp, afi, safi,
10530 (exact ? bgp_show_type_community_list_exact
10531 : bgp_show_type_community_list),
10532 list, 0);
50ef26d4 10533}
10534
d62a17ae 10535static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10536 const char *prefix, afi_t afi, safi_t safi,
10537 enum bgp_show_type type)
718e3744 10538{
d62a17ae 10539 int ret;
10540 struct prefix *p;
47fc97cc 10541
d62a17ae 10542 p = prefix_new();
95cbbd2a 10543
d62a17ae 10544 ret = str2prefix(prefix, p);
10545 if (!ret) {
10546 vty_out(vty, "%% Malformed Prefix\n");
10547 return CMD_WARNING;
10548 }
47e9b292 10549
d62a17ae 10550 ret = bgp_show(vty, bgp, afi, safi, type, p, 0);
10551 prefix_free(p);
10552 return ret;
10553}
10554
d62a17ae 10555enum bgp_stats {
10556 BGP_STATS_MAXBITLEN = 0,
10557 BGP_STATS_RIB,
10558 BGP_STATS_PREFIXES,
10559 BGP_STATS_TOTPLEN,
10560 BGP_STATS_UNAGGREGATEABLE,
10561 BGP_STATS_MAX_AGGREGATEABLE,
10562 BGP_STATS_AGGREGATES,
10563 BGP_STATS_SPACE,
10564 BGP_STATS_ASPATH_COUNT,
10565 BGP_STATS_ASPATH_MAXHOPS,
10566 BGP_STATS_ASPATH_TOTHOPS,
10567 BGP_STATS_ASPATH_MAXSIZE,
10568 BGP_STATS_ASPATH_TOTSIZE,
10569 BGP_STATS_ASN_HIGHEST,
10570 BGP_STATS_MAX,
a636c635 10571};
2815e61f 10572
d62a17ae 10573static const char *table_stats_strs[] = {
9d303b37
DL
10574 [BGP_STATS_PREFIXES] = "Total Prefixes",
10575 [BGP_STATS_TOTPLEN] = "Average prefix length",
10576 [BGP_STATS_RIB] = "Total Advertisements",
10577 [BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes",
10578 [BGP_STATS_MAX_AGGREGATEABLE] =
10579 "Maximum aggregateable prefixes",
10580 [BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements",
10581 [BGP_STATS_SPACE] = "Address space advertised",
10582 [BGP_STATS_ASPATH_COUNT] = "Advertisements with paths",
10583 [BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)",
10584 [BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)",
10585 [BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)",
10586 [BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)",
10587 [BGP_STATS_ASN_HIGHEST] = "Highest public ASN",
10588 [BGP_STATS_MAX] = NULL,
a636c635 10589};
2815e61f 10590
d62a17ae 10591struct bgp_table_stats {
10592 struct bgp_table *table;
10593 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 10594 double total_space;
ff7924f6
PJ
10595};
10596
a636c635
DW
10597#if 0
10598#define TALLY_SIGFIG 100000
10599static unsigned long
10600ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 10601{
a636c635
DW
10602 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
10603 unsigned long res = (newtot * TALLY_SIGFIG) / count;
10604 unsigned long ret = newtot / count;
07d0c4ed 10605
a636c635
DW
10606 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
10607 return ret + 1;
10608 else
10609 return ret;
10610}
10611#endif
ff7924f6 10612
9c14ec72
RW
10613static void bgp_table_stats_rn(struct bgp_node *rn, struct bgp_node *top,
10614 struct bgp_table_stats *ts, unsigned int space)
2815e61f 10615{
9c14ec72
RW
10616 struct bgp_node *prn = bgp_node_parent_nolock(rn);
10617 struct bgp_path_info *pi;
d62a17ae 10618
9c14ec72
RW
10619 if (rn == top)
10620 return;
d62a17ae 10621
9c14ec72
RW
10622 if (!bgp_node_has_bgp_path_info_data(rn))
10623 return;
d62a17ae 10624
9c14ec72
RW
10625 ts->counts[BGP_STATS_PREFIXES]++;
10626 ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
ff7924f6 10627
a636c635
DW
10628#if 0
10629 ts->counts[BGP_STATS_AVGPLEN]
10630 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
10631 ts->counts[BGP_STATS_AVGPLEN],
10632 rn->p.prefixlen);
10633#endif
d62a17ae 10634
9c14ec72
RW
10635 /* check if the prefix is included by any other announcements */
10636 while (prn && !bgp_node_has_bgp_path_info_data(prn))
10637 prn = bgp_node_parent_nolock(prn);
d62a17ae 10638
9c14ec72
RW
10639 if (prn == NULL || prn == top) {
10640 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
10641 /* announced address space */
10642 if (space)
10643 ts->total_space += pow(2.0, space - rn->p.prefixlen);
10644 } else if (bgp_node_has_bgp_path_info_data(prn))
10645 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 10646
9c14ec72
RW
10647
10648 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
10649 ts->counts[BGP_STATS_RIB]++;
10650
05864da7
DS
10651 if (CHECK_FLAG(pi->attr->flag,
10652 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
10653 ts->counts[BGP_STATS_AGGREGATES]++;
10654
10655 /* as-path stats */
05864da7 10656 if (pi->attr->aspath) {
9c14ec72
RW
10657 unsigned int hops = aspath_count_hops(pi->attr->aspath);
10658 unsigned int size = aspath_size(pi->attr->aspath);
10659 as_t highest = aspath_highest(pi->attr->aspath);
10660
10661 ts->counts[BGP_STATS_ASPATH_COUNT]++;
10662
10663 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
10664 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
10665
10666 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
10667 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
10668
10669 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
10670 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 10671#if 0
07d0c4ed 10672 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
10673 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
10674 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
10675 hops);
10676 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
10677 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
10678 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
10679 size);
10680#endif
9c14ec72
RW
10681 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
10682 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
10683 }
10684 }
10685}
10686
10687static int bgp_table_stats_walker(struct thread *t)
10688{
10689 struct bgp_node *rn, *nrn;
10690 struct bgp_node *top;
10691 struct bgp_table_stats *ts = THREAD_ARG(t);
10692 unsigned int space = 0;
10693
10694 if (!(top = bgp_table_top(ts->table)))
10695 return 0;
10696
10697 switch (ts->table->afi) {
10698 case AFI_IP:
10699 space = IPV4_MAX_BITLEN;
10700 break;
10701 case AFI_IP6:
10702 space = IPV6_MAX_BITLEN;
10703 break;
10704 default:
10705 return 0;
10706 }
10707
10708 ts->counts[BGP_STATS_MAXBITLEN] = space;
10709
10710 for (rn = top; rn; rn = bgp_route_next(rn)) {
10711 if (ts->table->safi == SAFI_MPLS_VPN) {
10712 struct bgp_table *table;
10713
10714 table = bgp_node_get_bgp_table_info(rn);
10715 if (!table)
10716 continue;
10717
10718 top = bgp_table_top(table);
10719 for (nrn = bgp_table_top(table); nrn;
10720 nrn = bgp_route_next(nrn))
10721 bgp_table_stats_rn(nrn, top, ts, space);
10722 } else {
10723 bgp_table_stats_rn(rn, top, ts, space);
d62a17ae 10724 }
10725 }
9c14ec72 10726
d62a17ae 10727 return 0;
2815e61f 10728}
ff7924f6 10729
d62a17ae 10730static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
10731 safi_t safi)
2815e61f 10732{
d62a17ae 10733 struct bgp_table_stats ts;
10734 unsigned int i;
019386c2 10735
d62a17ae 10736 if (!bgp->rib[afi][safi]) {
10737 vty_out(vty, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10738 afi, safi);
10739 return CMD_WARNING;
10740 }
019386c2 10741
5cb5f4d0 10742 vty_out(vty, "BGP %s RIB statistics\n", get_afi_safi_str(afi, safi, false));
019386c2 10743
d62a17ae 10744 /* labeled-unicast routes live in the unicast table */
10745 if (safi == SAFI_LABELED_UNICAST)
10746 safi = SAFI_UNICAST;
019386c2 10747
d62a17ae 10748 memset(&ts, 0, sizeof(ts));
10749 ts.table = bgp->rib[afi][safi];
10750 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 10751
d62a17ae 10752 for (i = 0; i < BGP_STATS_MAX; i++) {
10753 if (!table_stats_strs[i])
10754 continue;
10755
10756 switch (i) {
a636c635
DW
10757#if 0
10758 case BGP_STATS_ASPATH_AVGHOPS:
10759 case BGP_STATS_ASPATH_AVGSIZE:
10760 case BGP_STATS_AVGPLEN:
10761 vty_out (vty, "%-30s: ", table_stats_strs[i]);
10762 vty_out (vty, "%12.2f",
10763 (float)ts.counts[i] / (float)TALLY_SIGFIG);
10764 break;
10765#endif
d62a17ae 10766 case BGP_STATS_ASPATH_TOTHOPS:
10767 case BGP_STATS_ASPATH_TOTSIZE:
10768 vty_out(vty, "%-30s: ", table_stats_strs[i]);
10769 vty_out(vty, "%12.2f",
10770 ts.counts[i]
10771 ? (float)ts.counts[i]
10772 / (float)ts.counts
10773 [BGP_STATS_ASPATH_COUNT]
10774 : 0);
10775 break;
10776 case BGP_STATS_TOTPLEN:
10777 vty_out(vty, "%-30s: ", table_stats_strs[i]);
10778 vty_out(vty, "%12.2f",
10779 ts.counts[i]
10780 ? (float)ts.counts[i]
10781 / (float)ts.counts
10782 [BGP_STATS_PREFIXES]
10783 : 0);
10784 break;
10785 case BGP_STATS_SPACE:
10786 vty_out(vty, "%-30s: ", table_stats_strs[i]);
8d0ab76d
DL
10787 vty_out(vty, "%12g\n", ts.total_space);
10788
10789 if (afi == AFI_IP6) {
10790 vty_out(vty, "%30s: ", "/32 equivalent ");
10791 vty_out(vty, "%12g\n",
a4d82a8a 10792 ts.total_space * pow(2.0, -128 + 32));
8d0ab76d
DL
10793 vty_out(vty, "%30s: ", "/48 equivalent ");
10794 vty_out(vty, "%12g\n",
a4d82a8a 10795 ts.total_space * pow(2.0, -128 + 48));
8d0ab76d
DL
10796 } else {
10797 vty_out(vty, "%30s: ", "% announced ");
10798 vty_out(vty, "%12.2f\n",
10799 ts.total_space * 100. * pow(2.0, -32));
10800 vty_out(vty, "%30s: ", "/8 equivalent ");
10801 vty_out(vty, "%12.2f\n",
a4d82a8a 10802 ts.total_space * pow(2.0, -32 + 8));
8d0ab76d
DL
10803 vty_out(vty, "%30s: ", "/24 equivalent ");
10804 vty_out(vty, "%12.2f\n",
a4d82a8a 10805 ts.total_space * pow(2.0, -32 + 24));
8d0ab76d 10806 }
d62a17ae 10807 break;
10808 default:
10809 vty_out(vty, "%-30s: ", table_stats_strs[i]);
10810 vty_out(vty, "%12llu", ts.counts[i]);
10811 }
ff7924f6 10812
d62a17ae 10813 vty_out(vty, "\n");
10814 }
10815 return CMD_SUCCESS;
10816}
10817
10818enum bgp_pcounts {
10819 PCOUNT_ADJ_IN = 0,
10820 PCOUNT_DAMPED,
10821 PCOUNT_REMOVED,
10822 PCOUNT_HISTORY,
10823 PCOUNT_STALE,
10824 PCOUNT_VALID,
10825 PCOUNT_ALL,
10826 PCOUNT_COUNTED,
10827 PCOUNT_PFCNT, /* the figure we display to users */
10828 PCOUNT_MAX,
a636c635 10829};
718e3744 10830
d62a17ae 10831static const char *pcount_strs[] = {
9d303b37
DL
10832 [PCOUNT_ADJ_IN] = "Adj-in",
10833 [PCOUNT_DAMPED] = "Damped",
10834 [PCOUNT_REMOVED] = "Removed",
10835 [PCOUNT_HISTORY] = "History",
10836 [PCOUNT_STALE] = "Stale",
10837 [PCOUNT_VALID] = "Valid",
10838 [PCOUNT_ALL] = "All RIB",
10839 [PCOUNT_COUNTED] = "PfxCt counted",
10840 [PCOUNT_PFCNT] = "Useable",
10841 [PCOUNT_MAX] = NULL,
a636c635 10842};
718e3744 10843
d62a17ae 10844struct peer_pcounts {
10845 unsigned int count[PCOUNT_MAX];
10846 const struct peer *peer;
10847 const struct bgp_table *table;
a636c635 10848};
47fc97cc 10849
d62a17ae 10850static int bgp_peer_count_walker(struct thread *t)
10851{
10852 struct bgp_node *rn;
10853 struct peer_pcounts *pc = THREAD_ARG(t);
10854 const struct peer *peer = pc->peer;
10855
10856 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn)) {
10857 struct bgp_adj_in *ain;
40381db7 10858 struct bgp_path_info *pi;
d62a17ae 10859
10860 for (ain = rn->adj_in; ain; ain = ain->next)
10861 if (ain->peer == peer)
10862 pc->count[PCOUNT_ADJ_IN]++;
10863
6f94b685
DS
10864 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
10865
40381db7 10866 if (pi->peer != peer)
d62a17ae 10867 continue;
10868
10869 pc->count[PCOUNT_ALL]++;
10870
40381db7 10871 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
d62a17ae 10872 pc->count[PCOUNT_DAMPED]++;
40381db7 10873 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
d62a17ae 10874 pc->count[PCOUNT_HISTORY]++;
40381db7 10875 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
d62a17ae 10876 pc->count[PCOUNT_REMOVED]++;
40381db7 10877 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 10878 pc->count[PCOUNT_STALE]++;
40381db7 10879 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
d62a17ae 10880 pc->count[PCOUNT_VALID]++;
40381db7 10881 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
d62a17ae 10882 pc->count[PCOUNT_PFCNT]++;
10883
40381db7 10884 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 10885 pc->count[PCOUNT_COUNTED]++;
40381db7 10886 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
1c50c1c0
QY
10887 flog_err(
10888 EC_LIB_DEVELOPMENT,
10889 "Attempting to count but flags say it is unusable");
d62a17ae 10890 } else {
40381db7 10891 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
1c50c1c0
QY
10892 flog_err(
10893 EC_LIB_DEVELOPMENT,
10894 "Not counted but flags say we should");
d62a17ae 10895 }
10896 }
10897 }
10898 return 0;
718e3744 10899}
10900
d62a17ae 10901static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 10902 safi_t safi, bool use_json)
856ca177 10903{
d62a17ae 10904 struct peer_pcounts pcounts = {.peer = peer};
10905 unsigned int i;
10906 json_object *json = NULL;
10907 json_object *json_loop = NULL;
856ca177 10908
d62a17ae 10909 if (use_json) {
10910 json = json_object_new_object();
10911 json_loop = json_object_new_object();
10912 }
718e3744 10913
d62a17ae 10914 if (!peer || !peer->bgp || !peer->afc[afi][safi]
10915 || !peer->bgp->rib[afi][safi]) {
10916 if (use_json) {
10917 json_object_string_add(
10918 json, "warning",
10919 "No such neighbor or address family");
10920 vty_out(vty, "%s\n", json_object_to_json_string(json));
10921 json_object_free(json);
10922 } else
10923 vty_out(vty, "%% No such neighbor or address family\n");
10924
10925 return CMD_WARNING;
10926 }
2a71e9ce 10927
d62a17ae 10928 memset(&pcounts, 0, sizeof(pcounts));
10929 pcounts.peer = peer;
10930 pcounts.table = peer->bgp->rib[afi][safi];
10931
10932 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
10933 * stats for the thread-walk (i.e. ensure this can't be blamed on
10934 * on just vty_read()).
10935 */
d62a17ae 10936 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
10937
10938 if (use_json) {
10939 json_object_string_add(json, "prefixCountsFor", peer->host);
10940 json_object_string_add(json, "multiProtocol",
5cb5f4d0 10941 get_afi_safi_str(afi, safi, true));
d62a17ae 10942 json_object_int_add(json, "pfxCounter",
10943 peer->pcount[afi][safi]);
10944
10945 for (i = 0; i < PCOUNT_MAX; i++)
10946 json_object_int_add(json_loop, pcount_strs[i],
10947 pcounts.count[i]);
10948
10949 json_object_object_add(json, "ribTableWalkCounters", json_loop);
10950
10951 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
10952 json_object_string_add(json, "pfxctDriftFor",
10953 peer->host);
10954 json_object_string_add(
10955 json, "recommended",
10956 "Please report this bug, with the above command output");
10957 }
996c9314
LB
10958 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10959 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 10960 json_object_free(json);
10961 } else {
10962
10963 if (peer->hostname
10964 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
10965 vty_out(vty, "Prefix counts for %s/%s, %s\n",
10966 peer->hostname, peer->host,
5cb5f4d0 10967 get_afi_safi_str(afi, safi, false));
d62a17ae 10968 } else {
10969 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 10970 get_afi_safi_str(afi, safi, false));
d62a17ae 10971 }
10972
a0a87037 10973 vty_out(vty, "PfxCt: %" PRIu32 "\n", peer->pcount[afi][safi]);
d62a17ae 10974 vty_out(vty, "\nCounts from RIB table walk:\n\n");
10975
10976 for (i = 0; i < PCOUNT_MAX; i++)
10977 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
10978 pcounts.count[i]);
10979
10980 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
10981 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
10982 vty_out(vty,
10983 "Please report this bug, with the above command output\n");
10984 }
10985 }
10986
10987 return CMD_SUCCESS;
718e3744 10988}
10989
a636c635
DW
10990DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
10991 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
c1a44e43 10992 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] "
30a6a167 10993 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
718e3744 10994 SHOW_STR
10995 IP_STR
10996 BGP_STR
8386ac43 10997 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
10998 BGP_AFI_HELP_STR
10999 BGP_SAFI_HELP_STR
0b16f239
DS
11000 "Detailed information on TCP and BGP neighbor connections\n"
11001 "Neighbor to display information about\n"
11002 "Neighbor to display information about\n"
91d37724 11003 "Neighbor on BGP configured interface\n"
a636c635 11004 "Display detailed prefix count information\n"
9973d184 11005 JSON_STR)
0b16f239 11006{
d62a17ae 11007 afi_t afi = AFI_IP6;
11008 safi_t safi = SAFI_UNICAST;
11009 struct peer *peer;
11010 int idx = 0;
11011 struct bgp *bgp = NULL;
9f049418
DS
11012 bool uj = use_json(argc, argv);
11013
11014 if (uj)
11015 argc--;
856ca177 11016
d62a17ae 11017 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11018 &bgp, uj);
d62a17ae 11019 if (!idx)
11020 return CMD_WARNING;
0b16f239 11021
d62a17ae 11022 argv_find(argv, argc, "neighbors", &idx);
11023 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
11024 if (!peer)
11025 return CMD_WARNING;
bb46e94f 11026
29c8d9da 11027 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 11028}
0b16f239 11029
d6902373
PG
11030#ifdef KEEP_OLD_VPN_COMMANDS
11031DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
11032 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
11033 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
11034 SHOW_STR
11035 IP_STR
11036 BGP_STR
d6902373 11037 BGP_VPNVX_HELP_STR
91d37724 11038 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
11039 "Detailed information on TCP and BGP neighbor connections\n"
11040 "Neighbor to display information about\n"
11041 "Neighbor to display information about\n"
91d37724 11042 "Neighbor on BGP configured interface\n"
a636c635 11043 "Display detailed prefix count information\n"
9973d184 11044 JSON_STR)
a636c635 11045{
d62a17ae 11046 int idx_peer = 6;
11047 struct peer *peer;
9f049418 11048 bool uj = use_json(argc, argv);
a636c635 11049
d62a17ae 11050 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
11051 if (!peer)
11052 return CMD_WARNING;
11053
11054 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
11055}
11056
d6902373
PG
11057DEFUN (show_ip_bgp_vpn_all_route_prefix,
11058 show_ip_bgp_vpn_all_route_prefix_cmd,
11059 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
11060 SHOW_STR
11061 IP_STR
11062 BGP_STR
d6902373 11063 BGP_VPNVX_HELP_STR
91d37724
QY
11064 "Display information about all VPNv4 NLRIs\n"
11065 "Network in the BGP routing table to display\n"
3a2d747c 11066 "Network in the BGP routing table to display\n"
9973d184 11067 JSON_STR)
91d37724 11068{
d62a17ae 11069 int idx = 0;
11070 char *network = NULL;
11071 struct bgp *bgp = bgp_get_default();
11072 if (!bgp) {
11073 vty_out(vty, "Can't find default instance\n");
11074 return CMD_WARNING;
11075 }
87e34b58 11076
d62a17ae 11077 if (argv_find(argv, argc, "A.B.C.D", &idx))
11078 network = argv[idx]->arg;
11079 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
11080 network = argv[idx]->arg;
11081 else {
11082 vty_out(vty, "Unable to figure out Network\n");
11083 return CMD_WARNING;
11084 }
87e34b58 11085
d62a17ae 11086 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 11087 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 11088}
d6902373 11089#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 11090
44c69747
LK
11091DEFUN (show_bgp_l2vpn_evpn_route_prefix,
11092 show_bgp_l2vpn_evpn_route_prefix_cmd,
11093 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 11094 SHOW_STR
4c63a661
PG
11095 BGP_STR
11096 L2VPN_HELP_STR
11097 EVPN_HELP_STR
44c69747
LK
11098 "Network in the BGP routing table to display\n"
11099 "Network in the BGP routing table to display\n"
4c63a661
PG
11100 "Network in the BGP routing table to display\n"
11101 "Network in the BGP routing table to display\n"
11102 JSON_STR)
11103{
d62a17ae 11104 int idx = 0;
11105 char *network = NULL;
44c69747 11106 int prefix_check = 0;
a636c635 11107
44c69747
LK
11108 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
11109 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 11110 network = argv[idx]->arg;
44c69747
LK
11111 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
11112 argv_find(argv, argc, "A.B.C.D/M", &idx)) {
d62a17ae 11113 network = argv[idx]->arg;
44c69747
LK
11114 prefix_check = 1;
11115 } else {
d62a17ae 11116 vty_out(vty, "Unable to figure out Network\n");
11117 return CMD_WARNING;
11118 }
44c69747
LK
11119 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
11120 prefix_check, BGP_PATH_SHOW_ALL,
11121 use_json(argc, argv));
d62a17ae 11122}
11123
11124static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 11125 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 11126 const char *rmap_name, bool use_json,
6392aaa6 11127 json_object *json)
d62a17ae 11128{
11129 struct bgp_table *table;
11130 struct bgp_adj_in *ain;
11131 struct bgp_adj_out *adj;
11132 unsigned long output_count;
11133 unsigned long filtered_count;
11134 struct bgp_node *rn;
11135 int header1 = 1;
11136 struct bgp *bgp;
11137 int header2 = 1;
11138 struct attr attr;
11139 int ret;
11140 struct update_subgroup *subgrp;
11141 json_object *json_scode = NULL;
11142 json_object *json_ocode = NULL;
11143 json_object *json_ar = NULL;
11144 struct peer_af *paf;
f99def61 11145 bool route_filtered;
d62a17ae 11146
11147 if (use_json) {
11148 json_scode = json_object_new_object();
11149 json_ocode = json_object_new_object();
11150 json_ar = json_object_new_object();
11151
11152 json_object_string_add(json_scode, "suppressed", "s");
11153 json_object_string_add(json_scode, "damped", "d");
11154 json_object_string_add(json_scode, "history", "h");
11155 json_object_string_add(json_scode, "valid", "*");
11156 json_object_string_add(json_scode, "best", ">");
11157 json_object_string_add(json_scode, "multipath", "=");
11158 json_object_string_add(json_scode, "internal", "i");
11159 json_object_string_add(json_scode, "ribFailure", "r");
11160 json_object_string_add(json_scode, "stale", "S");
11161 json_object_string_add(json_scode, "removed", "R");
11162
11163 json_object_string_add(json_ocode, "igp", "i");
11164 json_object_string_add(json_ocode, "egp", "e");
11165 json_object_string_add(json_ocode, "incomplete", "?");
11166 }
a636c635 11167
d62a17ae 11168 bgp = peer->bgp;
a636c635 11169
d62a17ae 11170 if (!bgp) {
11171 if (use_json) {
11172 json_object_string_add(json, "alert", "no BGP");
11173 vty_out(vty, "%s\n", json_object_to_json_string(json));
11174 json_object_free(json);
11175 } else
11176 vty_out(vty, "%% No bgp\n");
11177 return;
11178 }
a636c635 11179
c512a642
EDP
11180 /* labeled-unicast routes live in the unicast table */
11181 if (safi == SAFI_LABELED_UNICAST)
11182 table = bgp->rib[afi][SAFI_UNICAST];
11183 else
11184 table = bgp->rib[afi][safi];
d62a17ae 11185
11186 output_count = filtered_count = 0;
11187 subgrp = peer_subgroup(peer, afi, safi);
11188
6392aaa6 11189 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 11190 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
11191 if (use_json) {
11192 json_object_int_add(json, "bgpTableVersion",
11193 table->version);
11194 json_object_string_add(json, "bgpLocalRouterId",
11195 inet_ntoa(bgp->router_id));
01eced22
AD
11196 json_object_int_add(json, "defaultLocPrf",
11197 bgp->default_local_pref);
11198 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 11199 json_object_object_add(json, "bgpStatusCodes",
11200 json_scode);
11201 json_object_object_add(json, "bgpOriginCodes",
11202 json_ocode);
07d0c4ed
DA
11203 json_object_string_add(
11204 json, "bgpOriginatingDefaultNetwork",
11205 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 11206 } else {
996c9314 11207 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 11208 ", local router ID is %s, vrf id ",
d62a17ae 11209 table->version, inet_ntoa(bgp->router_id));
9df8b37c
PZ
11210 if (bgp->vrf_id == VRF_UNKNOWN)
11211 vty_out(vty, "%s", VRFID_NONE_STR);
11212 else
11213 vty_out(vty, "%u", bgp->vrf_id);
11214 vty_out(vty, "\n");
01eced22
AD
11215 vty_out(vty, "Default local pref %u, ",
11216 bgp->default_local_pref);
11217 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 11218 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11219 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 11220 vty_out(vty, BGP_SHOW_OCODE_HEADER);
11221
07d0c4ed
DA
11222 vty_out(vty, "Originating default network %s\n\n",
11223 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 11224 }
11225 header1 = 0;
11226 }
a636c635 11227
d62a17ae 11228 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6392aaa6
PM
11229 if (type == bgp_show_adj_route_received
11230 || type == bgp_show_adj_route_filtered) {
d62a17ae 11231 for (ain = rn->adj_in; ain; ain = ain->next) {
05864da7 11232 if (ain->peer != peer)
ea47320b 11233 continue;
6392aaa6 11234
ea47320b
DL
11235 if (header1) {
11236 if (use_json) {
11237 json_object_int_add(
60466a63 11238 json, "bgpTableVersion",
ea47320b
DL
11239 0);
11240 json_object_string_add(
11241 json,
11242 "bgpLocalRouterId",
11243 inet_ntoa(
11244 bgp->router_id));
01eced22
AD
11245 json_object_int_add(json,
11246 "defaultLocPrf",
11247 bgp->default_local_pref);
11248 json_object_int_add(json,
11249 "localAS", bgp->as);
ea47320b 11250 json_object_object_add(
60466a63 11251 json, "bgpStatusCodes",
ea47320b
DL
11252 json_scode);
11253 json_object_object_add(
60466a63 11254 json, "bgpOriginCodes",
ea47320b
DL
11255 json_ocode);
11256 } else {
11257 vty_out(vty,
9df8b37c 11258 "BGP table version is 0, local router ID is %s, vrf id ",
ea47320b 11259 inet_ntoa(
9df8b37c
PZ
11260 bgp->router_id));
11261 if (bgp->vrf_id == VRF_UNKNOWN)
11262 vty_out(vty, "%s",
11263 VRFID_NONE_STR);
11264 else
11265 vty_out(vty, "%u",
11266 bgp->vrf_id);
11267 vty_out(vty, "\n");
01eced22
AD
11268 vty_out(vty,
11269 "Default local pref %u, ",
11270 bgp->default_local_pref);
11271 vty_out(vty, "local AS %u\n",
11272 bgp->as);
ea47320b
DL
11273 vty_out(vty,
11274 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
11275 vty_out(vty,
11276 BGP_SHOW_NCODE_HEADER);
ea47320b
DL
11277 vty_out(vty,
11278 BGP_SHOW_OCODE_HEADER);
d62a17ae 11279 }
ea47320b
DL
11280 header1 = 0;
11281 }
11282 if (header2) {
11283 if (!use_json)
11284 vty_out(vty, BGP_SHOW_HEADER);
11285 header2 = 0;
11286 }
6392aaa6
PM
11287
11288 bgp_attr_dup(&attr, ain->attr);
f99def61
AD
11289 route_filtered = false;
11290
11291 /* Filter prefix using distribute list,
11292 * filter list or prefix list
11293 */
11294 if ((bgp_input_filter(peer, &rn->p, &attr, afi,
11295 safi)) == FILTER_DENY)
11296 route_filtered = true;
11297
11298 /* Filter prefix using route-map */
6392aaa6 11299 ret = bgp_input_modifier(peer, &rn->p, &attr,
82b692c0 11300 afi, safi, rmap_name, NULL, 0);
6392aaa6 11301
13c8e163
AD
11302 if (type == bgp_show_adj_route_filtered &&
11303 !route_filtered && ret != RMAP_DENY) {
b755861b 11304 bgp_attr_undup(&attr, ain->attr);
6392aaa6 11305 continue;
d62a17ae 11306 }
6392aaa6 11307
13c8e163
AD
11308 if (type == bgp_show_adj_route_received &&
11309 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
11310 filtered_count++;
11311
11312 route_vty_out_tmp(vty, &rn->p, &attr, safi,
11313 use_json, json_ar);
b755861b 11314 bgp_attr_undup(&attr, ain->attr);
6392aaa6 11315 output_count++;
d62a17ae 11316 }
6392aaa6 11317 } else if (type == bgp_show_adj_route_advertised) {
a79c04e7 11318 RB_FOREACH (adj, bgp_adj_out_rb, &rn->adj_out)
924c3f6a 11319 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 11320 if (paf->peer != peer || !adj->attr)
924c3f6a 11321 continue;
d62a17ae 11322
924c3f6a
DS
11323 if (header1) {
11324 if (use_json) {
11325 json_object_int_add(
11326 json,
11327 "bgpTableVersion",
11328 table->version);
11329 json_object_string_add(
11330 json,
11331 "bgpLocalRouterId",
11332 inet_ntoa(
11333 bgp->router_id));
01eced22
AD
11334 json_object_int_add(
11335 json, "defaultLocPrf",
11336 bgp->default_local_pref
11337 );
11338 json_object_int_add(
11339 json, "localAS",
11340 bgp->as);
924c3f6a
DS
11341 json_object_object_add(
11342 json,
11343 "bgpStatusCodes",
11344 json_scode);
11345 json_object_object_add(
11346 json,
11347 "bgpOriginCodes",
11348 json_ocode);
11349 } else {
11350 vty_out(vty,
11351 "BGP table version is %" PRIu64
9df8b37c 11352 ", local router ID is %s, vrf id ",
924c3f6a
DS
11353 table->version,
11354 inet_ntoa(
11355 bgp->router_id));
9df8b37c
PZ
11356 if (bgp->vrf_id ==
11357 VRF_UNKNOWN)
11358 vty_out(vty,
11359 "%s",
11360 VRFID_NONE_STR);
11361 else
11362 vty_out(vty,
11363 "%u",
11364 bgp->vrf_id);
11365 vty_out(vty, "\n");
01eced22
AD
11366 vty_out(vty,
11367 "Default local pref %u, ",
11368 bgp->default_local_pref
11369 );
11370 vty_out(vty,
11371 "local AS %u\n",
11372 bgp->as);
924c3f6a
DS
11373 vty_out(vty,
11374 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
11375 vty_out(vty,
11376 BGP_SHOW_NCODE_HEADER);
924c3f6a
DS
11377 vty_out(vty,
11378 BGP_SHOW_OCODE_HEADER);
a2addae8 11379 }
924c3f6a
DS
11380 header1 = 0;
11381 }
924c3f6a
DS
11382 if (header2) {
11383 if (!use_json)
11384 vty_out(vty,
11385 BGP_SHOW_HEADER);
11386 header2 = 0;
11387 }
d62a17ae 11388
b755861b
PM
11389 bgp_attr_dup(&attr, adj->attr);
11390 ret = bgp_output_modifier(
11391 peer, &rn->p, &attr, afi, safi,
11392 rmap_name);
f46d8e1e 11393
b755861b
PM
11394 if (ret != RMAP_DENY) {
11395 route_vty_out_tmp(vty, &rn->p,
11396 &attr, safi,
11397 use_json,
11398 json_ar);
11399 output_count++;
11400 } else {
11401 filtered_count++;
a2addae8 11402 }
b755861b
PM
11403
11404 bgp_attr_undup(&attr, adj->attr);
924c3f6a 11405 }
d62a17ae 11406 }
11407 }
d62a17ae 11408
d62a17ae 11409 if (use_json) {
6392aaa6
PM
11410 json_object_object_add(json, "advertisedRoutes", json_ar);
11411 json_object_int_add(json, "totalPrefixCounter", output_count);
11412 json_object_int_add(json, "filteredPrefixCounter",
11413 filtered_count);
11414
996c9314
LB
11415 vty_out(vty, "%s\n", json_object_to_json_string_ext(
11416 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 11417 json_object_free(json);
6392aaa6
PM
11418 } else if (output_count > 0) {
11419 if (filtered_count > 0)
11420 vty_out(vty,
11421 "\nTotal number of prefixes %ld (%ld filtered)\n",
11422 output_count, filtered_count);
11423 else
11424 vty_out(vty, "\nTotal number of prefixes %ld\n",
11425 output_count);
d62a17ae 11426 }
a636c635 11427}
2a71e9ce 11428
d62a17ae 11429static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 11430 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 11431 const char *rmap_name, bool use_json)
0b16f239 11432{
d62a17ae 11433 json_object *json = NULL;
0b16f239 11434
d62a17ae 11435 if (use_json)
11436 json = json_object_new_object();
0b16f239 11437
d62a17ae 11438 if (!peer || !peer->afc[afi][safi]) {
11439 if (use_json) {
11440 json_object_string_add(
11441 json, "warning",
11442 "No such neighbor or address family");
11443 vty_out(vty, "%s\n", json_object_to_json_string(json));
11444 json_object_free(json);
11445 } else
11446 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 11447
d62a17ae 11448 return CMD_WARNING;
11449 }
11450
6392aaa6
PM
11451 if ((type == bgp_show_adj_route_received
11452 || type == bgp_show_adj_route_filtered)
d62a17ae 11453 && !CHECK_FLAG(peer->af_flags[afi][safi],
11454 PEER_FLAG_SOFT_RECONFIG)) {
11455 if (use_json) {
11456 json_object_string_add(
11457 json, "warning",
11458 "Inbound soft reconfiguration not enabled");
11459 vty_out(vty, "%s\n", json_object_to_json_string(json));
11460 json_object_free(json);
11461 } else
11462 vty_out(vty,
11463 "%% Inbound soft reconfiguration not enabled\n");
11464
11465 return CMD_WARNING;
11466 }
0b16f239 11467
6392aaa6 11468 show_adj_route(vty, peer, afi, safi, type, rmap_name, use_json, json);
0b16f239 11469
d62a17ae 11470 return CMD_SUCCESS;
a636c635 11471}
50ef26d4 11472
a636c635
DW
11473DEFUN (show_ip_bgp_instance_neighbor_advertised_route,
11474 show_ip_bgp_instance_neighbor_advertised_route_cmd,
4dd6177e 11475 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
6392aaa6 11476 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
718e3744 11477 SHOW_STR
11478 IP_STR
11479 BGP_STR
a636c635 11480 BGP_INSTANCE_HELP_STR
7395a2c9 11481 BGP_AFI_HELP_STR
4dd6177e 11482 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 11483 "Detailed information on TCP and BGP neighbor connections\n"
11484 "Neighbor to display information about\n"
11485 "Neighbor to display information about\n"
91d37724 11486 "Neighbor on BGP configured interface\n"
a636c635 11487 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
11488 "Display the received routes from neighbor\n"
11489 "Display the filtered routes received from neighbor\n"
a636c635
DW
11490 "Route-map to modify the attributes\n"
11491 "Name of the route map\n"
9973d184 11492 JSON_STR)
718e3744 11493{
d62a17ae 11494 afi_t afi = AFI_IP6;
11495 safi_t safi = SAFI_UNICAST;
11496 char *rmap_name = NULL;
11497 char *peerstr = NULL;
d62a17ae 11498 struct bgp *bgp = NULL;
11499 struct peer *peer;
6392aaa6 11500 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 11501 int idx = 0;
9f049418 11502 bool uj = use_json(argc, argv);
6392aaa6 11503
d62a17ae 11504 if (uj)
11505 argc--;
30a6a167 11506
9f049418
DS
11507 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11508 &bgp, uj);
11509 if (!idx)
11510 return CMD_WARNING;
11511
d62a17ae 11512 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11513 argv_find(argv, argc, "neighbors", &idx);
11514 peerstr = argv[++idx]->arg;
8c3deaae 11515
d62a17ae 11516 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
11517 if (!peer)
11518 return CMD_WARNING;
856ca177 11519
d62a17ae 11520 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
11521 type = bgp_show_adj_route_advertised;
11522 else if (argv_find(argv, argc, "received-routes", &idx))
11523 type = bgp_show_adj_route_received;
11524 else if (argv_find(argv, argc, "filtered-routes", &idx))
11525 type = bgp_show_adj_route_filtered;
11526
d62a17ae 11527 if (argv_find(argv, argc, "route-map", &idx))
11528 rmap_name = argv[++idx]->arg;
95cbbd2a 11529
6392aaa6 11530 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj);
95cbbd2a
ML
11531}
11532
718e3744 11533DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
11534 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 11535 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 11536 SHOW_STR
11537 IP_STR
11538 BGP_STR
8c3deaae
QY
11539 "Address Family\n"
11540 "Address Family\n"
718e3744 11541 "Address Family modifier\n"
11542 "Detailed information on TCP and BGP neighbor connections\n"
11543 "Neighbor to display information about\n"
11544 "Neighbor to display information about\n"
91d37724 11545 "Neighbor on BGP configured interface\n"
718e3744 11546 "Display information received from a BGP neighbor\n"
856ca177 11547 "Display the prefixlist filter\n"
9973d184 11548 JSON_STR)
718e3744 11549{
d62a17ae 11550 afi_t afi = AFI_IP6;
11551 safi_t safi = SAFI_UNICAST;
11552 char *peerstr = NULL;
11553
11554 char name[BUFSIZ];
11555 union sockunion su;
11556 struct peer *peer;
11557 int count, ret;
11558
11559 int idx = 0;
11560
11561 /* show [ip] bgp */
11562 if (argv_find(argv, argc, "ip", &idx))
11563 afi = AFI_IP;
11564 /* [<ipv4|ipv6> [unicast]] */
11565 if (argv_find(argv, argc, "ipv4", &idx))
11566 afi = AFI_IP;
11567 if (argv_find(argv, argc, "ipv6", &idx))
11568 afi = AFI_IP6;
11569 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11570 argv_find(argv, argc, "neighbors", &idx);
11571 peerstr = argv[++idx]->arg;
11572
9f049418 11573 bool uj = use_json(argc, argv);
d62a17ae 11574
11575 ret = str2sockunion(peerstr, &su);
11576 if (ret < 0) {
11577 peer = peer_lookup_by_conf_if(NULL, peerstr);
11578 if (!peer) {
11579 if (uj)
11580 vty_out(vty, "{}\n");
11581 else
11582 vty_out(vty,
11583 "%% Malformed address or name: %s\n",
11584 peerstr);
11585 return CMD_WARNING;
11586 }
11587 } else {
11588 peer = peer_lookup(NULL, &su);
11589 if (!peer) {
11590 if (uj)
11591 vty_out(vty, "{}\n");
11592 else
11593 vty_out(vty, "No peer\n");
11594 return CMD_WARNING;
11595 }
11596 }
718e3744 11597
d62a17ae 11598 sprintf(name, "%s.%d.%d", peer->host, afi, safi);
11599 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
11600 if (count) {
11601 if (!uj)
11602 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 11603 get_afi_safi_str(afi, safi, false));
d62a17ae 11604 prefix_bgp_show_prefix_list(vty, afi, name, uj);
11605 } else {
11606 if (uj)
11607 vty_out(vty, "{}\n");
11608 else
11609 vty_out(vty, "No functional output\n");
11610 }
718e3744 11611
d62a17ae 11612 return CMD_SUCCESS;
11613}
11614
11615static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
11616 afi_t afi, safi_t safi,
9f049418 11617 enum bgp_show_type type, bool use_json)
d62a17ae 11618{
8a893163
DW
11619 /* labeled-unicast routes live in the unicast table */
11620 if (safi == SAFI_LABELED_UNICAST)
11621 safi = SAFI_UNICAST;
11622
d62a17ae 11623 if (!peer || !peer->afc[afi][safi]) {
11624 if (use_json) {
11625 json_object *json_no = NULL;
11626 json_no = json_object_new_object();
11627 json_object_string_add(
11628 json_no, "warning",
11629 "No such neighbor or address family");
11630 vty_out(vty, "%s\n",
11631 json_object_to_json_string(json_no));
11632 json_object_free(json_no);
11633 } else
11634 vty_out(vty, "%% No such neighbor or address family\n");
11635 return CMD_WARNING;
11636 }
47fc97cc 11637
d62a17ae 11638 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json);
718e3744 11639}
11640
dba3c1d3
PG
11641DEFUN (show_ip_bgp_flowspec_routes_detailed,
11642 show_ip_bgp_flowspec_routes_detailed_cmd,
11643 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
11644 SHOW_STR
11645 IP_STR
11646 BGP_STR
11647 BGP_INSTANCE_HELP_STR
11648 BGP_AFI_HELP_STR
11649 "SAFI Flowspec\n"
11650 "Detailed information on flowspec entries\n"
11651 JSON_STR)
11652{
11653 afi_t afi = AFI_IP;
11654 safi_t safi = SAFI_UNICAST;
11655 struct bgp *bgp = NULL;
11656 int idx = 0;
9f049418
DS
11657 bool uj = use_json(argc, argv);
11658
11659 if (uj)
11660 argc--;
dba3c1d3
PG
11661
11662 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11663 &bgp, uj);
dba3c1d3
PG
11664 if (!idx)
11665 return CMD_WARNING;
11666
9f049418 11667 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL, uj);
dba3c1d3
PG
11668}
11669
718e3744 11670DEFUN (show_ip_bgp_neighbor_routes,
11671 show_ip_bgp_neighbor_routes_cmd,
4dd6177e 11672 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
30a6a167 11673 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
50ef26d4 11674 SHOW_STR
11675 IP_STR
11676 BGP_STR
8386ac43 11677 BGP_INSTANCE_HELP_STR
4f280b15 11678 BGP_AFI_HELP_STR
4dd6177e 11679 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 11680 "Detailed information on TCP and BGP neighbor connections\n"
11681 "Neighbor to display information about\n"
11682 "Neighbor to display information about\n"
91d37724 11683 "Neighbor on BGP configured interface\n"
2525cf39 11684 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
11685 "Display the dampened routes received from neighbor\n"
11686 "Display routes learned from neighbor\n"
9973d184 11687 JSON_STR)
718e3744 11688{
d62a17ae 11689 char *peerstr = NULL;
11690 struct bgp *bgp = NULL;
11691 afi_t afi = AFI_IP6;
11692 safi_t safi = SAFI_UNICAST;
11693 struct peer *peer;
11694 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 11695 int idx = 0;
9f049418
DS
11696 bool uj = use_json(argc, argv);
11697
11698 if (uj)
11699 argc--;
bb46e94f 11700
d62a17ae 11701 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11702 &bgp, uj);
d62a17ae 11703 if (!idx)
11704 return CMD_WARNING;
c493f2d8 11705
d62a17ae 11706 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11707 argv_find(argv, argc, "neighbors", &idx);
11708 peerstr = argv[++idx]->arg;
8c3deaae 11709
d62a17ae 11710 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 11711 if (!peer)
d62a17ae 11712 return CMD_WARNING;
bb46e94f 11713
d62a17ae 11714 if (argv_find(argv, argc, "flap-statistics", &idx))
11715 sh_type = bgp_show_type_flap_neighbor;
11716 else if (argv_find(argv, argc, "dampened-routes", &idx))
11717 sh_type = bgp_show_type_damp_neighbor;
11718 else if (argv_find(argv, argc, "routes", &idx))
11719 sh_type = bgp_show_type_neighbor;
2525cf39 11720
d62a17ae 11721 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 11722}
6b0655a2 11723
734b349e 11724struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 11725
d62a17ae 11726struct bgp_distance {
11727 /* Distance value for the IP source prefix. */
d7c0a89a 11728 uint8_t distance;
718e3744 11729
d62a17ae 11730 /* Name of the access-list to be matched. */
11731 char *access_list;
718e3744 11732};
11733
4f280b15
LB
11734DEFUN (show_bgp_afi_vpn_rd_route,
11735 show_bgp_afi_vpn_rd_route_cmd,
d114b977 11736 "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
11737 SHOW_STR
11738 BGP_STR
11739 BGP_AFI_HELP_STR
11740 "Address Family modifier\n"
11741 "Display information for a route distinguisher\n"
11742 "Route Distinguisher\n"
7395a2c9
DS
11743 "Network in the BGP routing table to display\n"
11744 "Network in the BGP routing table to display\n"
11745 JSON_STR)
4f280b15 11746{
d62a17ae 11747 int ret;
11748 struct prefix_rd prd;
11749 afi_t afi = AFI_MAX;
11750 int idx = 0;
4f280b15 11751
ff6566f3
DS
11752 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
11753 vty_out(vty, "%% Malformed Address Family\n");
11754 return CMD_WARNING;
11755 }
11756
d62a17ae 11757 ret = str2prefix_rd(argv[5]->arg, &prd);
11758 if (!ret) {
11759 vty_out(vty, "%% Malformed Route Distinguisher\n");
11760 return CMD_WARNING;
11761 }
ff6566f3 11762
d62a17ae 11763 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 11764 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
11765}
11766
d62a17ae 11767static struct bgp_distance *bgp_distance_new(void)
718e3744 11768{
d62a17ae 11769 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 11770}
11771
d62a17ae 11772static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 11773{
d62a17ae 11774 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 11775}
11776
d62a17ae 11777static int bgp_distance_set(struct vty *vty, const char *distance_str,
11778 const char *ip_str, const char *access_list_str)
718e3744 11779{
d62a17ae 11780 int ret;
11781 afi_t afi;
11782 safi_t safi;
11783 struct prefix p;
d7c0a89a 11784 uint8_t distance;
d62a17ae 11785 struct bgp_node *rn;
11786 struct bgp_distance *bdistance;
718e3744 11787
d62a17ae 11788 afi = bgp_node_afi(vty);
11789 safi = bgp_node_safi(vty);
734b349e 11790
d62a17ae 11791 ret = str2prefix(ip_str, &p);
11792 if (ret == 0) {
11793 vty_out(vty, "Malformed prefix\n");
11794 return CMD_WARNING_CONFIG_FAILED;
11795 }
718e3744 11796
d62a17ae 11797 distance = atoi(distance_str);
718e3744 11798
d62a17ae 11799 /* Get BGP distance node. */
11800 rn = bgp_node_get(bgp_distance_table[afi][safi], (struct prefix *)&p);
5b00b40e 11801 bdistance = bgp_node_get_bgp_distance_info(rn);
ca2e160d 11802 if (bdistance)
d62a17ae 11803 bgp_unlock_node(rn);
ca2e160d 11804 else {
d62a17ae 11805 bdistance = bgp_distance_new();
5b00b40e 11806 bgp_node_set_bgp_distance_info(rn, bdistance);
d62a17ae 11807 }
718e3744 11808
d62a17ae 11809 /* Set distance value. */
11810 bdistance->distance = distance;
718e3744 11811
d62a17ae 11812 /* Reset access-list configuration. */
11813 if (bdistance->access_list) {
11814 XFREE(MTYPE_AS_LIST, bdistance->access_list);
11815 bdistance->access_list = NULL;
11816 }
11817 if (access_list_str)
11818 bdistance->access_list =
11819 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 11820
d62a17ae 11821 return CMD_SUCCESS;
718e3744 11822}
11823
d62a17ae 11824static int bgp_distance_unset(struct vty *vty, const char *distance_str,
11825 const char *ip_str, const char *access_list_str)
718e3744 11826{
d62a17ae 11827 int ret;
11828 afi_t afi;
11829 safi_t safi;
11830 struct prefix p;
11831 int distance;
11832 struct bgp_node *rn;
11833 struct bgp_distance *bdistance;
718e3744 11834
d62a17ae 11835 afi = bgp_node_afi(vty);
11836 safi = bgp_node_safi(vty);
734b349e 11837
d62a17ae 11838 ret = str2prefix(ip_str, &p);
11839 if (ret == 0) {
11840 vty_out(vty, "Malformed prefix\n");
11841 return CMD_WARNING_CONFIG_FAILED;
11842 }
718e3744 11843
d62a17ae 11844 rn = bgp_node_lookup(bgp_distance_table[afi][safi],
11845 (struct prefix *)&p);
11846 if (!rn) {
11847 vty_out(vty, "Can't find specified prefix\n");
11848 return CMD_WARNING_CONFIG_FAILED;
11849 }
718e3744 11850
5b00b40e 11851 bdistance = bgp_node_get_bgp_distance_info(rn);
d62a17ae 11852 distance = atoi(distance_str);
1f9a9fff 11853
d62a17ae 11854 if (bdistance->distance != distance) {
11855 vty_out(vty, "Distance does not match configured\n");
11856 return CMD_WARNING_CONFIG_FAILED;
11857 }
718e3744 11858
0a22ddfb 11859 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 11860 bgp_distance_free(bdistance);
718e3744 11861
6f94b685 11862 bgp_node_set_bgp_path_info(rn, NULL);
d62a17ae 11863 bgp_unlock_node(rn);
11864 bgp_unlock_node(rn);
718e3744 11865
d62a17ae 11866 return CMD_SUCCESS;
718e3744 11867}
11868
718e3744 11869/* Apply BGP information to distance method. */
40381db7 11870uint8_t bgp_distance_apply(struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 11871 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 11872{
11873 struct bgp_node *rn;
11874 struct prefix q;
11875 struct peer *peer;
11876 struct bgp_distance *bdistance;
11877 struct access_list *alist;
11878 struct bgp_static *bgp_static;
11879
11880 if (!bgp)
11881 return 0;
11882
40381db7 11883 peer = pinfo->peer;
d62a17ae 11884
7b7d48e5
DS
11885 if (pinfo->attr->distance)
11886 return pinfo->attr->distance;
11887
d62a17ae 11888 /* Check source address. */
11889 sockunion2hostprefix(&peer->su, &q);
11890 rn = bgp_node_match(bgp_distance_table[afi][safi], &q);
11891 if (rn) {
5b00b40e 11892 bdistance = bgp_node_get_bgp_distance_info(rn);
d62a17ae 11893 bgp_unlock_node(rn);
11894
11895 if (bdistance->access_list) {
11896 alist = access_list_lookup(afi, bdistance->access_list);
11897 if (alist
11898 && access_list_apply(alist, p) == FILTER_PERMIT)
11899 return bdistance->distance;
11900 } else
11901 return bdistance->distance;
718e3744 11902 }
718e3744 11903
d62a17ae 11904 /* Backdoor check. */
11905 rn = bgp_node_lookup(bgp->route[afi][safi], p);
11906 if (rn) {
5a8ba9fc 11907 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 11908 bgp_unlock_node(rn);
718e3744 11909
d62a17ae 11910 if (bgp_static->backdoor) {
11911 if (bgp->distance_local[afi][safi])
11912 return bgp->distance_local[afi][safi];
11913 else
11914 return ZEBRA_IBGP_DISTANCE_DEFAULT;
11915 }
718e3744 11916 }
718e3744 11917
d62a17ae 11918 if (peer->sort == BGP_PEER_EBGP) {
11919 if (bgp->distance_ebgp[afi][safi])
11920 return bgp->distance_ebgp[afi][safi];
11921 return ZEBRA_EBGP_DISTANCE_DEFAULT;
11922 } else {
11923 if (bgp->distance_ibgp[afi][safi])
11924 return bgp->distance_ibgp[afi][safi];
11925 return ZEBRA_IBGP_DISTANCE_DEFAULT;
11926 }
718e3744 11927}
11928
a612fb77
DA
11929/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
11930 * we should tell ZEBRA update the routes for a specific
11931 * AFI/SAFI to reflect changes in RIB.
11932 */
11933static void bgp_announce_routes_distance_update(struct bgp *bgp)
11934{
11935 afi_t afi;
11936 safi_t safi;
11937
11938 FOREACH_AFI_SAFI (afi, safi) {
11939 if (!bgp_fibupd_safi(safi))
11940 continue;
11941
11942 if (bgp->distance_ebgp[afi][safi]
11943 && bgp->distance_ibgp[afi][safi]
11944 && bgp->distance_local[afi][safi]) {
11945 if (BGP_DEBUG(zebra, ZEBRA))
11946 zlog_debug(
11947 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
11948 __func__, afi, safi);
11949 bgp_zebra_announce_table(bgp, afi, safi);
11950 }
11951 }
11952}
11953
718e3744 11954DEFUN (bgp_distance,
11955 bgp_distance_cmd,
6147e2c6 11956 "distance bgp (1-255) (1-255) (1-255)",
718e3744 11957 "Define an administrative distance\n"
11958 "BGP distance\n"
11959 "Distance for routes external to the AS\n"
11960 "Distance for routes internal to the AS\n"
11961 "Distance for local routes\n")
11962{
d62a17ae 11963 VTY_DECLVAR_CONTEXT(bgp, bgp);
11964 int idx_number = 2;
11965 int idx_number_2 = 3;
11966 int idx_number_3 = 4;
11967 afi_t afi;
11968 safi_t safi;
718e3744 11969
d62a17ae 11970 afi = bgp_node_afi(vty);
11971 safi = bgp_node_safi(vty);
718e3744 11972
d62a17ae 11973 bgp->distance_ebgp[afi][safi] = atoi(argv[idx_number]->arg);
11974 bgp->distance_ibgp[afi][safi] = atoi(argv[idx_number_2]->arg);
11975 bgp->distance_local[afi][safi] = atoi(argv[idx_number_3]->arg);
a612fb77 11976 bgp_announce_routes_distance_update(bgp);
d62a17ae 11977 return CMD_SUCCESS;
718e3744 11978}
11979
11980DEFUN (no_bgp_distance,
11981 no_bgp_distance_cmd,
a636c635 11982 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 11983 NO_STR
11984 "Define an administrative distance\n"
11985 "BGP distance\n"
11986 "Distance for routes external to the AS\n"
11987 "Distance for routes internal to the AS\n"
11988 "Distance for local routes\n")
11989{
d62a17ae 11990 VTY_DECLVAR_CONTEXT(bgp, bgp);
11991 afi_t afi;
11992 safi_t safi;
718e3744 11993
d62a17ae 11994 afi = bgp_node_afi(vty);
11995 safi = bgp_node_safi(vty);
718e3744 11996
d62a17ae 11997 bgp->distance_ebgp[afi][safi] = 0;
11998 bgp->distance_ibgp[afi][safi] = 0;
11999 bgp->distance_local[afi][safi] = 0;
a612fb77 12000 bgp_announce_routes_distance_update(bgp);
d62a17ae 12001 return CMD_SUCCESS;
718e3744 12002}
12003
718e3744 12004
12005DEFUN (bgp_distance_source,
12006 bgp_distance_source_cmd,
6147e2c6 12007 "distance (1-255) A.B.C.D/M",
718e3744 12008 "Define an administrative distance\n"
12009 "Administrative distance\n"
12010 "IP source prefix\n")
12011{
d62a17ae 12012 int idx_number = 1;
12013 int idx_ipv4_prefixlen = 2;
12014 bgp_distance_set(vty, argv[idx_number]->arg,
12015 argv[idx_ipv4_prefixlen]->arg, NULL);
12016 return CMD_SUCCESS;
718e3744 12017}
12018
12019DEFUN (no_bgp_distance_source,
12020 no_bgp_distance_source_cmd,
6147e2c6 12021 "no distance (1-255) A.B.C.D/M",
718e3744 12022 NO_STR
12023 "Define an administrative distance\n"
12024 "Administrative distance\n"
12025 "IP source prefix\n")
12026{
d62a17ae 12027 int idx_number = 2;
12028 int idx_ipv4_prefixlen = 3;
12029 bgp_distance_unset(vty, argv[idx_number]->arg,
12030 argv[idx_ipv4_prefixlen]->arg, NULL);
12031 return CMD_SUCCESS;
718e3744 12032}
12033
12034DEFUN (bgp_distance_source_access_list,
12035 bgp_distance_source_access_list_cmd,
6147e2c6 12036 "distance (1-255) A.B.C.D/M WORD",
718e3744 12037 "Define an administrative distance\n"
12038 "Administrative distance\n"
12039 "IP source prefix\n"
12040 "Access list name\n")
12041{
d62a17ae 12042 int idx_number = 1;
12043 int idx_ipv4_prefixlen = 2;
12044 int idx_word = 3;
12045 bgp_distance_set(vty, argv[idx_number]->arg,
12046 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12047 return CMD_SUCCESS;
718e3744 12048}
12049
12050DEFUN (no_bgp_distance_source_access_list,
12051 no_bgp_distance_source_access_list_cmd,
6147e2c6 12052 "no distance (1-255) A.B.C.D/M WORD",
718e3744 12053 NO_STR
12054 "Define an administrative distance\n"
12055 "Administrative distance\n"
12056 "IP source prefix\n"
12057 "Access list name\n")
12058{
d62a17ae 12059 int idx_number = 2;
12060 int idx_ipv4_prefixlen = 3;
12061 int idx_word = 4;
12062 bgp_distance_unset(vty, argv[idx_number]->arg,
12063 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12064 return CMD_SUCCESS;
718e3744 12065}
6b0655a2 12066
734b349e
MZ
12067DEFUN (ipv6_bgp_distance_source,
12068 ipv6_bgp_distance_source_cmd,
39e92c06 12069 "distance (1-255) X:X::X:X/M",
734b349e
MZ
12070 "Define an administrative distance\n"
12071 "Administrative distance\n"
12072 "IP source prefix\n")
12073{
d62a17ae 12074 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
12075 return CMD_SUCCESS;
734b349e
MZ
12076}
12077
12078DEFUN (no_ipv6_bgp_distance_source,
12079 no_ipv6_bgp_distance_source_cmd,
39e92c06 12080 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
12081 NO_STR
12082 "Define an administrative distance\n"
12083 "Administrative distance\n"
12084 "IP source prefix\n")
12085{
d62a17ae 12086 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
12087 return CMD_SUCCESS;
734b349e
MZ
12088}
12089
12090DEFUN (ipv6_bgp_distance_source_access_list,
12091 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12092 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12093 "Define an administrative distance\n"
12094 "Administrative distance\n"
12095 "IP source prefix\n"
12096 "Access list name\n")
12097{
d62a17ae 12098 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
12099 return CMD_SUCCESS;
734b349e
MZ
12100}
12101
12102DEFUN (no_ipv6_bgp_distance_source_access_list,
12103 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12104 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12105 NO_STR
12106 "Define an administrative distance\n"
12107 "Administrative distance\n"
12108 "IP source prefix\n"
12109 "Access list name\n")
12110{
d62a17ae 12111 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
12112 return CMD_SUCCESS;
734b349e
MZ
12113}
12114
718e3744 12115DEFUN (bgp_damp_set,
12116 bgp_damp_set_cmd,
31500417 12117 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 12118 "BGP Specific commands\n"
12119 "Enable route-flap dampening\n"
12120 "Half-life time for the penalty\n"
12121 "Value to start reusing a route\n"
12122 "Value to start suppressing a route\n"
12123 "Maximum duration to suppress a stable route\n")
12124{
d62a17ae 12125 VTY_DECLVAR_CONTEXT(bgp, bgp);
12126 int idx_half_life = 2;
12127 int idx_reuse = 3;
12128 int idx_suppress = 4;
12129 int idx_max_suppress = 5;
12130 int half = DEFAULT_HALF_LIFE * 60;
12131 int reuse = DEFAULT_REUSE;
12132 int suppress = DEFAULT_SUPPRESS;
12133 int max = 4 * half;
12134
12135 if (argc == 6) {
12136 half = atoi(argv[idx_half_life]->arg) * 60;
12137 reuse = atoi(argv[idx_reuse]->arg);
12138 suppress = atoi(argv[idx_suppress]->arg);
12139 max = atoi(argv[idx_max_suppress]->arg) * 60;
12140 } else if (argc == 3) {
12141 half = atoi(argv[idx_half_life]->arg) * 60;
12142 max = 4 * half;
12143 }
718e3744 12144
d62a17ae 12145 if (suppress < reuse) {
12146 vty_out(vty,
12147 "Suppress value cannot be less than reuse value \n");
12148 return 0;
12149 }
7ebe9748 12150
d62a17ae 12151 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
12152 reuse, suppress, max);
718e3744 12153}
12154
718e3744 12155DEFUN (bgp_damp_unset,
12156 bgp_damp_unset_cmd,
d04c479d 12157 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 12158 NO_STR
12159 "BGP Specific commands\n"
16cedbb0
QY
12160 "Enable route-flap dampening\n"
12161 "Half-life time for the penalty\n"
12162 "Value to start reusing a route\n"
12163 "Value to start suppressing a route\n"
12164 "Maximum duration to suppress a stable route\n")
718e3744 12165{
d62a17ae 12166 VTY_DECLVAR_CONTEXT(bgp, bgp);
12167 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 12168}
12169
718e3744 12170/* Display specified route of BGP table. */
d62a17ae 12171static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
12172 const char *ip_str, afi_t afi, safi_t safi,
12173 struct prefix_rd *prd, int prefix_check)
12174{
12175 int ret;
12176 struct prefix match;
12177 struct bgp_node *rn;
12178 struct bgp_node *rm;
40381db7
DS
12179 struct bgp_path_info *pi;
12180 struct bgp_path_info *pi_temp;
d62a17ae 12181 struct bgp *bgp;
12182 struct bgp_table *table;
12183
12184 /* BGP structure lookup. */
12185 if (view_name) {
12186 bgp = bgp_lookup_by_name(view_name);
12187 if (bgp == NULL) {
12188 vty_out(vty, "%% Can't find BGP instance %s\n",
12189 view_name);
12190 return CMD_WARNING;
12191 }
12192 } else {
12193 bgp = bgp_get_default();
12194 if (bgp == NULL) {
12195 vty_out(vty, "%% No BGP process is configured\n");
12196 return CMD_WARNING;
12197 }
718e3744 12198 }
718e3744 12199
d62a17ae 12200 /* Check IP address argument. */
12201 ret = str2prefix(ip_str, &match);
12202 if (!ret) {
12203 vty_out(vty, "%% address is malformed\n");
12204 return CMD_WARNING;
12205 }
718e3744 12206
d62a17ae 12207 match.family = afi2family(afi);
12208
12209 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
12210 || (safi == SAFI_EVPN)) {
12211 for (rn = bgp_table_top(bgp->rib[AFI_IP][safi]); rn;
12212 rn = bgp_route_next(rn)) {
12213 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
12214 continue;
67009e22
DS
12215 table = bgp_node_get_bgp_table_info(rn);
12216 if (!table)
ea47320b
DL
12217 continue;
12218 if ((rm = bgp_node_match(table, &match)) == NULL)
12219 continue;
d62a17ae 12220
ea47320b
DL
12221 if (!prefix_check
12222 || rm->p.prefixlen == match.prefixlen) {
6f94b685 12223 pi = bgp_node_get_bgp_path_info(rm);
40381db7
DS
12224 while (pi) {
12225 if (pi->extra && pi->extra->damp_info) {
12226 pi_temp = pi->next;
ea47320b 12227 bgp_damp_info_free(
40381db7 12228 pi->extra->damp_info,
60466a63 12229 1);
40381db7 12230 pi = pi_temp;
ea47320b 12231 } else
40381db7 12232 pi = pi->next;
d62a17ae 12233 }
ea47320b
DL
12234 }
12235
12236 bgp_unlock_node(rm);
d62a17ae 12237 }
12238 } else {
12239 if ((rn = bgp_node_match(bgp->rib[afi][safi], &match))
12240 != NULL) {
12241 if (!prefix_check
12242 || rn->p.prefixlen == match.prefixlen) {
6f94b685 12243 pi = bgp_node_get_bgp_path_info(rn);
40381db7
DS
12244 while (pi) {
12245 if (pi->extra && pi->extra->damp_info) {
12246 pi_temp = pi->next;
d62a17ae 12247 bgp_damp_info_free(
40381db7 12248 pi->extra->damp_info,
d62a17ae 12249 1);
40381db7 12250 pi = pi_temp;
d62a17ae 12251 } else
40381db7 12252 pi = pi->next;
d62a17ae 12253 }
12254 }
12255
12256 bgp_unlock_node(rn);
12257 }
12258 }
718e3744 12259
d62a17ae 12260 return CMD_SUCCESS;
718e3744 12261}
12262
12263DEFUN (clear_ip_bgp_dampening,
12264 clear_ip_bgp_dampening_cmd,
12265 "clear ip bgp dampening",
12266 CLEAR_STR
12267 IP_STR
12268 BGP_STR
12269 "Clear route flap dampening information\n")
12270{
d62a17ae 12271 bgp_damp_info_clean();
12272 return CMD_SUCCESS;
718e3744 12273}
12274
12275DEFUN (clear_ip_bgp_dampening_prefix,
12276 clear_ip_bgp_dampening_prefix_cmd,
12277 "clear ip bgp dampening A.B.C.D/M",
12278 CLEAR_STR
12279 IP_STR
12280 BGP_STR
12281 "Clear route flap dampening information\n"
0c7b1b01 12282 "IPv4 prefix\n")
718e3744 12283{
d62a17ae 12284 int idx_ipv4_prefixlen = 4;
12285 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
12286 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 12287}
12288
12289DEFUN (clear_ip_bgp_dampening_address,
12290 clear_ip_bgp_dampening_address_cmd,
12291 "clear ip bgp dampening A.B.C.D",
12292 CLEAR_STR
12293 IP_STR
12294 BGP_STR
12295 "Clear route flap dampening information\n"
12296 "Network to clear damping information\n")
12297{
d62a17ae 12298 int idx_ipv4 = 4;
12299 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
12300 SAFI_UNICAST, NULL, 0);
718e3744 12301}
12302
12303DEFUN (clear_ip_bgp_dampening_address_mask,
12304 clear_ip_bgp_dampening_address_mask_cmd,
12305 "clear ip bgp dampening A.B.C.D A.B.C.D",
12306 CLEAR_STR
12307 IP_STR
12308 BGP_STR
12309 "Clear route flap dampening information\n"
12310 "Network to clear damping information\n"
12311 "Network mask\n")
12312{
d62a17ae 12313 int idx_ipv4 = 4;
12314 int idx_ipv4_2 = 5;
12315 int ret;
12316 char prefix_str[BUFSIZ];
718e3744 12317
d62a17ae 12318 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
12319 prefix_str);
12320 if (!ret) {
12321 vty_out(vty, "%% Inconsistent address and mask\n");
12322 return CMD_WARNING;
12323 }
718e3744 12324
d62a17ae 12325 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
12326 NULL, 0);
718e3744 12327}
6b0655a2 12328
e3b78da8 12329static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
12330{
12331 struct vty *vty = arg;
e3b78da8 12332 struct peer *peer = bucket->data;
825d9834
DS
12333 char buf[SU_ADDRSTRLEN];
12334
12335 vty_out(vty, "\tPeer: %s %s\n", peer->host,
12336 sockunion2str(&peer->su, buf, sizeof(buf)));
12337}
12338
12339DEFUN (show_bgp_peerhash,
12340 show_bgp_peerhash_cmd,
12341 "show bgp peerhash",
12342 SHOW_STR
12343 BGP_STR
12344 "Display information about the BGP peerhash\n")
12345{
12346 struct list *instances = bm->bgp;
12347 struct listnode *node;
12348 struct bgp *bgp;
12349
12350 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
12351 vty_out(vty, "BGP: %s\n", bgp->name);
12352 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
12353 vty);
12354 }
12355
12356 return CMD_SUCCESS;
12357}
12358
587ff0fd 12359/* also used for encap safi */
2b791107
DL
12360static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
12361 afi_t afi, safi_t safi)
d62a17ae 12362{
12363 struct bgp_node *prn;
12364 struct bgp_node *rn;
12365 struct bgp_table *table;
12366 struct prefix *p;
12367 struct prefix_rd *prd;
12368 struct bgp_static *bgp_static;
12369 mpls_label_t label;
12370 char buf[SU_ADDRSTRLEN];
12371 char rdbuf[RD_ADDRSTRLEN];
12372
12373 /* Network configuration. */
12374 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b 12375 prn = bgp_route_next(prn)) {
67009e22
DS
12376 table = bgp_node_get_bgp_table_info(prn);
12377 if (!table)
ea47320b 12378 continue;
d62a17ae 12379
60466a63 12380 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5a8ba9fc 12381 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12382 if (bgp_static == NULL)
ea47320b 12383 continue;
d62a17ae 12384
ea47320b
DL
12385 p = &rn->p;
12386 prd = (struct prefix_rd *)&prn->p;
d62a17ae 12387
ea47320b 12388 /* "network" configuration display. */
06b9f471 12389 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
12390 label = decode_label(&bgp_static->label);
12391
12392 vty_out(vty, " network %s/%d rd %s",
12393 inet_ntop(p->family, &p->u.prefix, buf,
12394 SU_ADDRSTRLEN),
12395 p->prefixlen, rdbuf);
12396 if (safi == SAFI_MPLS_VPN)
12397 vty_out(vty, " label %u", label);
12398
12399 if (bgp_static->rmap.name)
12400 vty_out(vty, " route-map %s",
12401 bgp_static->rmap.name);
e2a86ad9
DS
12402
12403 if (bgp_static->backdoor)
12404 vty_out(vty, " backdoor");
12405
ea47320b
DL
12406 vty_out(vty, "\n");
12407 }
12408 }
d62a17ae 12409}
12410
2b791107
DL
12411static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
12412 afi_t afi, safi_t safi)
d62a17ae 12413{
12414 struct bgp_node *prn;
12415 struct bgp_node *rn;
12416 struct bgp_table *table;
12417 struct prefix *p;
12418 struct prefix_rd *prd;
12419 struct bgp_static *bgp_static;
ff44f570 12420 char buf[PREFIX_STRLEN * 2];
d62a17ae 12421 char buf2[SU_ADDRSTRLEN];
12422 char rdbuf[RD_ADDRSTRLEN];
12423
12424 /* Network configuration. */
12425 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b 12426 prn = bgp_route_next(prn)) {
67009e22
DS
12427 table = bgp_node_get_bgp_table_info(prn);
12428 if (!table)
ea47320b 12429 continue;
d62a17ae 12430
60466a63 12431 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5a8ba9fc 12432 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12433 if (bgp_static == NULL)
ea47320b 12434 continue;
d62a17ae 12435
ea47320b
DL
12436 char *macrouter = NULL;
12437 char *esi = NULL;
d62a17ae 12438
ea47320b
DL
12439 if (bgp_static->router_mac)
12440 macrouter = prefix_mac2str(
12441 bgp_static->router_mac, NULL, 0);
12442 if (bgp_static->eth_s_id)
12443 esi = esi2str(bgp_static->eth_s_id);
12444 p = &rn->p;
12445 prd = (struct prefix_rd *)&prn->p;
d62a17ae 12446
ea47320b 12447 /* "network" configuration display. */
06b9f471 12448 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
12449 if (p->u.prefix_evpn.route_type == 5) {
12450 char local_buf[PREFIX_STRLEN];
3714a385 12451 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
12452 struct prefix_evpn *)p)
12453 ? AF_INET
12454 : AF_INET6;
3714a385 12455 inet_ntop(family,
12456 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a
PZ
12457 local_buf, PREFIX_STRLEN);
12458 sprintf(buf, "%s/%u", local_buf,
3714a385 12459 p->u.prefix_evpn.prefix_addr.ip_prefix_length);
197cb530
PG
12460 } else {
12461 prefix2str(p, buf, sizeof(buf));
12462 }
ea47320b 12463
a4d82a8a
PZ
12464 if (bgp_static->gatewayIp.family == AF_INET
12465 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
12466 inet_ntop(bgp_static->gatewayIp.family,
12467 &bgp_static->gatewayIp.u.prefix, buf2,
12468 sizeof(buf2));
ea47320b 12469 vty_out(vty,
7bcc8dac 12470 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 12471 buf, rdbuf,
12472 p->u.prefix_evpn.prefix_addr.eth_tag,
60466a63 12473 decode_label(&bgp_static->label), esi, buf2,
ea47320b
DL
12474 macrouter);
12475
0a22ddfb
QY
12476 XFREE(MTYPE_TMP, macrouter);
12477 XFREE(MTYPE_TMP, esi);
ea47320b
DL
12478 }
12479 }
3da6fcd5
PG
12480}
12481
718e3744 12482/* Configuration of static route announcement and aggregate
12483 information. */
2b791107
DL
12484void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
12485 safi_t safi)
d62a17ae 12486{
12487 struct bgp_node *rn;
12488 struct prefix *p;
12489 struct bgp_static *bgp_static;
12490 struct bgp_aggregate *bgp_aggregate;
12491 char buf[SU_ADDRSTRLEN];
12492
2b791107
DL
12493 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
12494 bgp_config_write_network_vpn(vty, bgp, afi, safi);
12495 return;
12496 }
d62a17ae 12497
2b791107
DL
12498 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
12499 bgp_config_write_network_evpn(vty, bgp, afi, safi);
12500 return;
12501 }
d62a17ae 12502
12503 /* Network configuration. */
12504 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
ea47320b 12505 rn = bgp_route_next(rn)) {
5a8ba9fc 12506 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12507 if (bgp_static == NULL)
ea47320b 12508 continue;
d62a17ae 12509
ea47320b 12510 p = &rn->p;
d62a17ae 12511
d8a9922d
DS
12512 vty_out(vty, " network %s/%d",
12513 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
12514 p->prefixlen);
d62a17ae 12515
ea47320b
DL
12516 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
12517 vty_out(vty, " label-index %u",
12518 bgp_static->label_index);
d62a17ae 12519
ea47320b
DL
12520 if (bgp_static->rmap.name)
12521 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
12522
12523 if (bgp_static->backdoor)
12524 vty_out(vty, " backdoor");
718e3744 12525
ea47320b
DL
12526 vty_out(vty, "\n");
12527 }
12528
d62a17ae 12529 /* Aggregate-address configuration. */
12530 for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn;
ea47320b 12531 rn = bgp_route_next(rn)) {
b613a918 12532 bgp_aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 12533 if (bgp_aggregate == NULL)
ea47320b 12534 continue;
d62a17ae 12535
ea47320b 12536 p = &rn->p;
d62a17ae 12537
d8a9922d
DS
12538 vty_out(vty, " aggregate-address %s/%d",
12539 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
12540 p->prefixlen);
d62a17ae 12541
ea47320b
DL
12542 if (bgp_aggregate->as_set)
12543 vty_out(vty, " as-set");
d62a17ae 12544
ea47320b
DL
12545 if (bgp_aggregate->summary_only)
12546 vty_out(vty, " summary-only");
718e3744 12547
20894f50
DA
12548 if (bgp_aggregate->rmap.name)
12549 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
12550
ea47320b
DL
12551 vty_out(vty, "\n");
12552 }
d62a17ae 12553}
734b349e 12554
2b791107 12555void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 12556 safi_t safi)
d62a17ae 12557{
12558 struct bgp_node *rn;
12559 struct bgp_distance *bdistance;
12560
12561 /* Distance configuration. */
12562 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
12563 && bgp->distance_local[afi][safi]
12564 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
12565 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
12566 || bgp->distance_local[afi][safi]
12567 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 12568 vty_out(vty, " distance bgp %d %d %d\n",
12569 bgp->distance_ebgp[afi][safi],
12570 bgp->distance_ibgp[afi][safi],
12571 bgp->distance_local[afi][safi]);
12572 }
734b349e 12573
d62a17ae 12574 for (rn = bgp_table_top(bgp_distance_table[afi][safi]); rn;
ca2e160d 12575 rn = bgp_route_next(rn)) {
5b00b40e 12576 bdistance = bgp_node_get_bgp_distance_info(rn);
ca2e160d 12577 if (bdistance != NULL) {
d62a17ae 12578 char buf[PREFIX_STRLEN];
12579
d62a17ae 12580 vty_out(vty, " distance %d %s %s\n",
12581 bdistance->distance,
12582 prefix2str(&rn->p, buf, sizeof(buf)),
12583 bdistance->access_list ? bdistance->access_list
12584 : "");
12585 }
ca2e160d 12586 }
718e3744 12587}
12588
12589/* Allocate routing table structure and install commands. */
d62a17ae 12590void bgp_route_init(void)
12591{
12592 afi_t afi;
12593 safi_t safi;
12594
12595 /* Init BGP distance table. */
05c7a1cc 12596 FOREACH_AFI_SAFI (afi, safi)
960035b2 12597 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 12598
12599 /* IPv4 BGP commands. */
12600 install_element(BGP_NODE, &bgp_table_map_cmd);
12601 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 12602 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 12603
12604 install_element(BGP_NODE, &aggregate_address_cmd);
12605 install_element(BGP_NODE, &aggregate_address_mask_cmd);
12606 install_element(BGP_NODE, &no_aggregate_address_cmd);
12607 install_element(BGP_NODE, &no_aggregate_address_mask_cmd);
12608
12609 /* IPv4 unicast configuration. */
12610 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
12611 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 12612 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 12613
12614 install_element(BGP_IPV4_NODE, &aggregate_address_cmd);
12615 install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd);
12616 install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd);
12617 install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
12618
12619 /* IPv4 multicast configuration. */
12620 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
12621 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 12622 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
d62a17ae 12623 install_element(BGP_IPV4M_NODE, &aggregate_address_cmd);
12624 install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
12625 install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd);
12626 install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
12627
12628 /* IPv4 labeled-unicast configuration. */
12629 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
12630 install_element(VIEW_NODE, &show_ip_bgp_cmd);
7b2ff250 12631 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 12632 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
12633 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
12634
12635 install_element(VIEW_NODE,
12636 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
12637 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
12638 install_element(VIEW_NODE,
12639 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 12640#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 12641 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 12642#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 12643 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
12644 install_element(VIEW_NODE,
44c69747 12645 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 12646
d62a17ae 12647 /* BGP dampening clear commands */
12648 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
12649 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 12650
d62a17ae 12651 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
12652 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
12653
12654 /* prefix count */
12655 install_element(ENABLE_NODE,
12656 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 12657#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 12658 install_element(ENABLE_NODE,
12659 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 12660#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 12661
d62a17ae 12662 /* New config IPv6 BGP commands. */
12663 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
12664 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 12665 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 12666
12667 install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
12668 install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
12669
12670 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 12671
d62a17ae 12672 install_element(BGP_NODE, &bgp_distance_cmd);
12673 install_element(BGP_NODE, &no_bgp_distance_cmd);
12674 install_element(BGP_NODE, &bgp_distance_source_cmd);
12675 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
12676 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
12677 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
12678 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
12679 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
12680 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
12681 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
12682 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
12683 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
12684 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
12685 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
12686 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
12687 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
12688 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
12689 install_element(BGP_IPV4M_NODE,
12690 &no_bgp_distance_source_access_list_cmd);
12691 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
12692 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
12693 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
12694 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
12695 install_element(BGP_IPV6_NODE,
12696 &ipv6_bgp_distance_source_access_list_cmd);
12697 install_element(BGP_IPV6_NODE,
12698 &no_ipv6_bgp_distance_source_access_list_cmd);
12699 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
12700 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
12701 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
12702 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
12703 install_element(BGP_IPV6M_NODE,
12704 &ipv6_bgp_distance_source_access_list_cmd);
12705 install_element(BGP_IPV6M_NODE,
12706 &no_ipv6_bgp_distance_source_access_list_cmd);
12707
12708 install_element(BGP_NODE, &bgp_damp_set_cmd);
12709 install_element(BGP_NODE, &bgp_damp_unset_cmd);
12710 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
12711 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
12712
12713 /* IPv4 Multicast Mode */
12714 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
12715 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
12716
12717 /* Large Communities */
12718 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
12719 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
12720
12721 /* show bgp ipv4 flowspec detailed */
12722 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
12723
825d9834 12724 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 12725}
12726
12727void bgp_route_finish(void)
12728{
12729 afi_t afi;
12730 safi_t safi;
12731
05c7a1cc
QY
12732 FOREACH_AFI_SAFI (afi, safi) {
12733 bgp_table_unlock(bgp_distance_table[afi][safi]);
12734 bgp_distance_table[afi][safi] = NULL;
12735 }
228da428 12736}