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