]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
bgpd: Adding new bgp evpn cli's for ip-prefix lookup
[mirror_frr.git] / bgpd / bgp_route.c
CommitLineData
718e3744 1/* BGP routing information
896014f4
DL
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
718e3744 21
22#include <zebra.h>
8d0ab76d 23#include <math.h>
718e3744 24
2618a52e 25#include "printfrr.h"
718e3744 26#include "prefix.h"
27#include "linklist.h"
28#include "memory.h"
29#include "command.h"
30#include "stream.h"
31#include "filter.h"
718e3744 32#include "log.h"
33#include "routemap.h"
34#include "buffer.h"
35#include "sockunion.h"
36#include "plist.h"
37#include "thread.h"
200df115 38#include "workqueue.h"
3f9c7369 39#include "queue.h"
6e919709 40#include "memory.h"
4dcadbef 41#include "lib/json.h"
d8d084d9 42#include "lib_errors.h"
718e3744 43
44#include "bgpd/bgpd.h"
45#include "bgpd/bgp_table.h"
46#include "bgpd/bgp_route.h"
47#include "bgpd/bgp_attr.h"
48#include "bgpd/bgp_debug.h"
14454c9f 49#include "bgpd/bgp_errors.h"
718e3744 50#include "bgpd/bgp_aspath.h"
51#include "bgpd/bgp_regex.h"
52#include "bgpd/bgp_community.h"
53#include "bgpd/bgp_ecommunity.h"
57d187bc 54#include "bgpd/bgp_lcommunity.h"
718e3744 55#include "bgpd/bgp_clist.h"
56#include "bgpd/bgp_packet.h"
57#include "bgpd/bgp_filter.h"
58#include "bgpd/bgp_fsm.h"
59#include "bgpd/bgp_mplsvpn.h"
60#include "bgpd/bgp_nexthop.h"
61#include "bgpd/bgp_damp.h"
62#include "bgpd/bgp_advertise.h"
63#include "bgpd/bgp_zebra.h"
0a486e5f 64#include "bgpd/bgp_vty.h"
96450faf 65#include "bgpd/bgp_mpath.h"
fc9a856f 66#include "bgpd/bgp_nht.h"
3f9c7369 67#include "bgpd/bgp_updgrp.h"
cd1964ff 68#include "bgpd/bgp_label.h"
dcc68b5e 69#include "bgpd/bgp_addpath.h"
4e802e66 70#include "bgpd/bgp_mac.h"
718e3744 71
65efcfce 72#if ENABLE_BGP_VNC
f8b6f499
LB
73#include "bgpd/rfapi/rfapi_backend.h"
74#include "bgpd/rfapi/vnc_import_bgp.h"
75#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 76#endif
aee875b5
PG
77#include "bgpd/bgp_encap_types.h"
78#include "bgpd/bgp_encap_tlv.h"
684a7227 79#include "bgpd/bgp_evpn.h"
3da6fcd5 80#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 81#include "bgpd/bgp_flowspec.h"
98a9dbc7 82#include "bgpd/bgp_flowspec_util.h"
45918cfb 83#include "bgpd/bgp_pbr.h"
65efcfce 84
e2a86ad9
DS
85#ifndef VTYSH_EXTRACT_PL
86#include "bgpd/bgp_route_clippy.c"
87#endif
aee875b5 88
718e3744 89/* Extern from bgp_dump.c */
dde72586
SH
90extern const char *bgp_origin_str[];
91extern const char *bgp_origin_long_str[];
6b0655a2 92
b7d08f5a 93/* PMSI strings. */
94#define PMSI_TNLTYPE_STR_NO_INFO "No info"
95#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
96static const struct message bgp_pmsi_tnltype_str[] = {
97 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
98 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
99 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
100 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
101 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
102 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
103 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
104 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 105 {0}
106};
b7d08f5a 107
9df8b37c
PZ
108#define VRFID_NONE_STR "-"
109
4a11bf2c
DL
110DEFINE_HOOK(bgp_process,
111 (struct bgp *bgp, afi_t afi, safi_t safi,
112 struct bgp_node *bn, struct peer *peer, bool withdraw),
113 (bgp, afi, safi, bn, peer, withdraw))
114
115
d62a17ae 116struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
117 safi_t safi, struct prefix *p,
118 struct prefix_rd *prd)
119{
120 struct bgp_node *rn;
121 struct bgp_node *prn = NULL;
122
123 assert(table);
124 if (!table)
125 return NULL;
126
127 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
128 || (safi == SAFI_EVPN)) {
129 prn = bgp_node_get(table, (struct prefix *)prd);
130
67009e22
DS
131 if (!bgp_node_has_bgp_path_info_data(prn))
132 bgp_node_set_bgp_table_info(
133 prn, bgp_table_init(table->bgp, afi, safi));
d62a17ae 134 else
135 bgp_unlock_node(prn);
67009e22 136 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 137 }
718e3744 138
d62a17ae 139 rn = bgp_node_get(table, p);
718e3744 140
d62a17ae 141 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
142 || (safi == SAFI_EVPN))
143 rn->prn = prn;
718e3744 144
d62a17ae 145 return rn;
718e3744 146}
6b0655a2 147
d62a17ae 148struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
149 safi_t safi, struct prefix *p,
150 struct prefix_rd *prd)
128ea8ab 151{
d62a17ae 152 struct bgp_node *rn;
153 struct bgp_node *prn = NULL;
128ea8ab 154
d62a17ae 155 if (!table)
156 return NULL;
128ea8ab 157
d62a17ae 158 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
159 || (safi == SAFI_EVPN)) {
160 prn = bgp_node_lookup(table, (struct prefix *)prd);
161 if (!prn)
162 return NULL;
128ea8ab 163
6f94b685 164 if (!bgp_node_has_bgp_path_info_data(prn)) {
d62a17ae 165 bgp_unlock_node(prn);
166 return NULL;
167 }
128ea8ab 168
67009e22 169 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 170 }
128ea8ab 171
d62a17ae 172 rn = bgp_node_lookup(table, p);
128ea8ab 173
d62a17ae 174 return rn;
128ea8ab 175}
176
18ee8310
DS
177/* Allocate bgp_path_info_extra */
178static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 179{
4b7e6066
DS
180 struct bgp_path_info_extra *new;
181 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
182 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
183 new->label[0] = MPLS_INVALID_LABEL;
184 new->num_labels = 0;
3e3708cb
PG
185 new->bgp_fs_pbr = NULL;
186 new->bgp_fs_iprule = NULL;
d62a17ae 187 return new;
fb982c25
PJ
188}
189
a2e219fe 190void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 191{
4b7e6066 192 struct bgp_path_info_extra *e;
d62a17ae 193
c93a3b77
DS
194 if (!extra || !*extra)
195 return;
d62a17ae 196
c93a3b77
DS
197 e = *extra;
198 if (e->damp_info)
199 bgp_damp_info_free(e->damp_info, 0);
d62a17ae 200
c93a3b77
DS
201 e->damp_info = NULL;
202 if (e->parent) {
40381db7 203 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 204
40381db7 205 if (bpi->net) {
0e70e6c8
DL
206 /* FIXME: since multiple e may have the same e->parent
207 * and e->parent->net is holding a refcount for each
208 * of them, we need to do some fudging here.
209 *
40381db7
DS
210 * WARNING: if bpi->net->lock drops to 0, bpi may be
211 * freed as well (because bpi->net was holding the
212 * last reference to bpi) => write after free!
0e70e6c8
DL
213 */
214 unsigned refcount;
215
40381db7
DS
216 bpi = bgp_path_info_lock(bpi);
217 refcount = bpi->net->lock - 1;
218 bgp_unlock_node((struct bgp_node *)bpi->net);
0e70e6c8 219 if (!refcount)
40381db7
DS
220 bpi->net = NULL;
221 bgp_path_info_unlock(bpi);
0e70e6c8 222 }
18ee8310 223 bgp_path_info_unlock(e->parent);
c93a3b77 224 e->parent = NULL;
d62a17ae 225 }
c93a3b77
DS
226
227 if (e->bgp_orig)
228 bgp_unlock(e->bgp_orig);
c26edcda 229
ce3c0614
PG
230 if ((*extra)->bgp_fs_iprule)
231 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 232 if ((*extra)->bgp_fs_pbr)
6a154c88 233 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77
DS
234 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
235
236 *extra = NULL;
fb982c25
PJ
237}
238
18ee8310
DS
239/* Get bgp_path_info extra information for the given bgp_path_info, lazy
240 * allocated if required.
fb982c25 241 */
40381db7 242struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 243{
40381db7
DS
244 if (!pi->extra)
245 pi->extra = bgp_path_info_extra_new();
246 return pi->extra;
fb982c25
PJ
247}
248
718e3744 249/* Free bgp route information. */
9b6d8fcf 250static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 251{
9b6d8fcf
DS
252 if (path->attr)
253 bgp_attr_unintern(&path->attr);
fb018d25 254
9b6d8fcf
DS
255 bgp_unlink_nexthop(path);
256 bgp_path_info_extra_free(&path->extra);
257 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
258 if (path->net)
259 bgp_addpath_free_info_data(&path->tx_addpath,
260 &path->net->tx_addpath);
718e3744 261
9b6d8fcf 262 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 263
9b6d8fcf 264 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 265}
266
9b6d8fcf 267struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 268{
9b6d8fcf
DS
269 path->lock++;
270 return path;
200df115 271}
272
9b6d8fcf 273struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 274{
9b6d8fcf
DS
275 assert(path && path->lock > 0);
276 path->lock--;
d62a17ae 277
9b6d8fcf 278 if (path->lock == 0) {
200df115 279#if 0
280 zlog_debug ("%s: unlocked and freeing", __func__);
281 zlog_backtrace (LOG_DEBUG);
282#endif
9b6d8fcf 283 bgp_path_info_free(path);
d62a17ae 284 return NULL;
285 }
200df115 286
287#if 0
9b6d8fcf 288 if (path->lock == 1)
200df115 289 {
290 zlog_debug ("%s: unlocked to 1", __func__);
291 zlog_backtrace (LOG_DEBUG);
292 }
293#endif
d62a17ae 294
9b6d8fcf 295 return path;
200df115 296}
297
40381db7 298void bgp_path_info_add(struct bgp_node *rn, struct bgp_path_info *pi)
718e3744 299{
4b7e6066 300 struct bgp_path_info *top;
718e3744 301
6f94b685 302 top = bgp_node_get_bgp_path_info(rn);
d62a17ae 303
6f94b685 304 pi->next = top;
40381db7 305 pi->prev = NULL;
d62a17ae 306 if (top)
40381db7 307 top->prev = pi;
6f94b685 308 bgp_node_set_bgp_path_info(rn, pi);
d62a17ae 309
40381db7 310 bgp_path_info_lock(pi);
d62a17ae 311 bgp_lock_node(rn);
40381db7 312 peer_lock(pi->peer); /* bgp_path_info peer reference */
718e3744 313}
314
d62a17ae 315/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 316 completion callback *only* */
40381db7 317void bgp_path_info_reap(struct bgp_node *rn, struct bgp_path_info *pi)
718e3744 318{
40381db7
DS
319 if (pi->next)
320 pi->next->prev = pi->prev;
321 if (pi->prev)
322 pi->prev->next = pi->next;
d62a17ae 323 else
6f94b685 324 bgp_node_set_bgp_path_info(rn, pi->next);
d62a17ae 325
40381db7
DS
326 bgp_path_info_mpath_dequeue(pi);
327 bgp_path_info_unlock(pi);
d62a17ae 328 bgp_unlock_node(rn);
718e3744 329}
330
40381db7 331void bgp_path_info_delete(struct bgp_node *rn, struct bgp_path_info *pi)
b40d939b 332{
40381db7 333 bgp_path_info_set_flag(rn, pi, BGP_PATH_REMOVED);
d62a17ae 334 /* set of previous already took care of pcount */
40381db7 335 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 336}
337
18ee8310 338/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
339 called when a route is deleted and then quickly re-added before the
340 deletion has been processed */
40381db7 341void bgp_path_info_restore(struct bgp_node *rn, struct bgp_path_info *pi)
8d45210e 342{
40381db7 343 bgp_path_info_unset_flag(rn, pi, BGP_PATH_REMOVED);
d62a17ae 344 /* unset of previous already took care of pcount */
40381db7 345 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
346}
347
d62a17ae 348/* Adjust pcount as required */
40381db7 349static void bgp_pcount_adjust(struct bgp_node *rn, struct bgp_path_info *pi)
1a392d46 350{
d62a17ae 351 struct bgp_table *table;
67174041 352
d62a17ae 353 assert(rn && bgp_node_table(rn));
40381db7 354 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 355
d62a17ae 356 table = bgp_node_table(rn);
67174041 357
40381db7 358 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 359 return;
360
40381db7
DS
361 if (!BGP_PATH_COUNTABLE(pi)
362 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 363
40381db7 364 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 365
366 /* slight hack, but more robust against errors. */
40381db7
DS
367 if (pi->peer->pcount[table->afi][table->safi])
368 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 369 else
450971aa 370 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 371 "Asked to decrement 0 prefix count for peer");
40381db7
DS
372 } else if (BGP_PATH_COUNTABLE(pi)
373 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
374 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
375 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 376 }
1a392d46
PJ
377}
378
40381db7
DS
379static int bgp_label_index_differs(struct bgp_path_info *pi1,
380 struct bgp_path_info *pi2)
28d58fd7 381{
40381db7 382 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 383}
1a392d46 384
18ee8310 385/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
386 * This is here primarily to keep prefix-count in check.
387 */
40381db7 388void bgp_path_info_set_flag(struct bgp_node *rn, struct bgp_path_info *pi,
18ee8310 389 uint32_t flag)
1a392d46 390{
40381db7 391 SET_FLAG(pi->flags, flag);
d62a17ae 392
393 /* early bath if we know it's not a flag that changes countability state
394 */
395 if (!CHECK_FLAG(flag,
1defdda8 396 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 397 return;
398
40381db7 399 bgp_pcount_adjust(rn, pi);
1a392d46
PJ
400}
401
40381db7 402void bgp_path_info_unset_flag(struct bgp_node *rn, struct bgp_path_info *pi,
18ee8310 403 uint32_t flag)
1a392d46 404{
40381db7 405 UNSET_FLAG(pi->flags, flag);
d62a17ae 406
407 /* early bath if we know it's not a flag that changes countability state
408 */
409 if (!CHECK_FLAG(flag,
1defdda8 410 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 411 return;
412
40381db7 413 bgp_pcount_adjust(rn, pi);
1a392d46
PJ
414}
415
718e3744 416/* Get MED value. If MED value is missing and "bgp bestpath
417 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 418static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 419{
420 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
421 return attr->med;
422 else {
423 if (bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST))
424 return BGP_MED_MAX;
425 else
426 return 0;
427 }
718e3744 428}
429
40381db7 430void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf)
2ec1e66f 431{
40381db7
DS
432 if (pi->addpath_rx_id)
433 sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
434 pi->addpath_rx_id);
d62a17ae 435 else
40381db7 436 sprintf(buf, "path %s", pi->peer->host);
d62a17ae 437}
9fbdd100 438
d62a17ae 439/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
440 */
18ee8310
DS
441static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
442 struct bgp_path_info *exist, int *paths_eq,
443 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
444 char *pfx_buf, afi_t afi, safi_t safi,
445 enum bgp_path_selection_reason *reason)
d62a17ae 446{
447 struct attr *newattr, *existattr;
448 bgp_peer_sort_t new_sort;
449 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
450 uint32_t new_pref;
451 uint32_t exist_pref;
452 uint32_t new_med;
453 uint32_t exist_med;
454 uint32_t new_weight;
455 uint32_t exist_weight;
d62a17ae 456 uint32_t newm, existm;
457 struct in_addr new_id;
458 struct in_addr exist_id;
459 int new_cluster;
460 int exist_cluster;
461 int internal_as_route;
462 int confed_as_route;
04d14c8b 463 int ret = 0;
d62a17ae 464 char new_buf[PATH_ADDPATH_STR_BUFFER];
465 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
466 uint32_t new_mm_seq;
467 uint32_t exist_mm_seq;
6d8c603a 468 int nh_cmp;
d62a17ae 469
470 *paths_eq = 0;
471
472 /* 0. Null check. */
473 if (new == NULL) {
fdf81fa0 474 *reason = bgp_path_selection_none;
d62a17ae 475 if (debug)
476 zlog_debug("%s: new is NULL", pfx_buf);
477 return 0;
478 }
2ec1e66f 479
d62a17ae 480 if (debug)
18ee8310 481 bgp_path_info_path_with_addpath_rx_str(new, new_buf);
718e3744 482
d62a17ae 483 if (exist == NULL) {
fdf81fa0 484 *reason = bgp_path_selection_first;
d62a17ae 485 if (debug)
486 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
487 new_buf);
488 return 1;
489 }
2ec1e66f 490
d62a17ae 491 if (debug) {
18ee8310 492 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
d62a17ae 493 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
494 pfx_buf, new_buf, new->flags, exist_buf,
495 exist->flags);
496 }
8ff56318 497
d62a17ae 498 newattr = new->attr;
499 existattr = exist->attr;
500
501 /* For EVPN routes, we cannot just go by local vs remote, we have to
502 * look at the MAC mobility sequence number, if present.
503 */
504 if (safi == SAFI_EVPN) {
505 /* This is an error condition described in RFC 7432 Section
506 * 15.2. The RFC
507 * states that in this scenario "the PE MUST alert the operator"
508 * but it
509 * does not state what other action to take. In order to provide
510 * some
511 * consistency in this scenario we are going to prefer the path
512 * with the
513 * sticky flag.
514 */
515 if (newattr->sticky != existattr->sticky) {
516 if (!debug) {
517 prefix2str(&new->net->p, pfx_buf,
518 sizeof(*pfx_buf)
519 * PREFIX2STR_BUFFER);
18ee8310
DS
520 bgp_path_info_path_with_addpath_rx_str(new,
521 new_buf);
522 bgp_path_info_path_with_addpath_rx_str(
523 exist, exist_buf);
d62a17ae 524 }
525
526 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 527 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
528 if (debug)
529 zlog_debug(
530 "%s: %s wins over %s due to sticky MAC flag",
531 pfx_buf, new_buf, exist_buf);
d62a17ae 532 return 1;
533 }
534
535 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 536 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
537 if (debug)
538 zlog_debug(
539 "%s: %s loses to %s due to sticky MAC flag",
540 pfx_buf, new_buf, exist_buf);
d62a17ae 541 return 0;
542 }
543 }
128ea8ab 544
d62a17ae 545 new_mm_seq = mac_mobility_seqnum(newattr);
546 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 547
d62a17ae 548 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 549 *reason = bgp_path_selection_evpn_seq;
d62a17ae 550 if (debug)
551 zlog_debug(
552 "%s: %s wins over %s due to MM seq %u > %u",
553 pfx_buf, new_buf, exist_buf, new_mm_seq,
554 exist_mm_seq);
555 return 1;
556 }
8ff56318 557
d62a17ae 558 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 559 *reason = bgp_path_selection_evpn_seq;
d62a17ae 560 if (debug)
561 zlog_debug(
562 "%s: %s loses to %s due to MM seq %u < %u",
563 pfx_buf, new_buf, exist_buf, new_mm_seq,
564 exist_mm_seq);
565 return 0;
566 }
6d8c603a
AK
567
568 /*
569 * if sequence numbers are the same path with the lowest IP
570 * wins
571 */
572 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
573 if (nh_cmp < 0) {
fdf81fa0 574 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
575 if (debug)
576 zlog_debug(
577 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
578 pfx_buf, new_buf, exist_buf, new_mm_seq,
579 inet_ntoa(new->attr->nexthop));
580 return 1;
581 }
582 if (nh_cmp > 0) {
fdf81fa0 583 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
584 if (debug)
585 zlog_debug(
586 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
587 pfx_buf, new_buf, exist_buf, new_mm_seq,
588 inet_ntoa(new->attr->nexthop));
589 return 0;
590 }
d62a17ae 591 }
9fbdd100 592
d62a17ae 593 /* 1. Weight check. */
d62a17ae 594 new_weight = newattr->weight;
595 exist_weight = existattr->weight;
8ff56318 596
d62a17ae 597 if (new_weight > exist_weight) {
fdf81fa0 598 *reason = bgp_path_selection_weight;
d62a17ae 599 if (debug)
600 zlog_debug("%s: %s wins over %s due to weight %d > %d",
601 pfx_buf, new_buf, exist_buf, new_weight,
602 exist_weight);
603 return 1;
604 }
718e3744 605
d62a17ae 606 if (new_weight < exist_weight) {
fdf81fa0 607 *reason = bgp_path_selection_weight;
d62a17ae 608 if (debug)
609 zlog_debug("%s: %s loses to %s due to weight %d < %d",
610 pfx_buf, new_buf, exist_buf, new_weight,
611 exist_weight);
612 return 0;
613 }
9fbdd100 614
d62a17ae 615 /* 2. Local preference check. */
616 new_pref = exist_pref = bgp->default_local_pref;
617
618 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
619 new_pref = newattr->local_pref;
620 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
621 exist_pref = existattr->local_pref;
622
623 if (new_pref > exist_pref) {
fdf81fa0 624 *reason = bgp_path_selection_local_pref;
d62a17ae 625 if (debug)
626 zlog_debug(
627 "%s: %s wins over %s due to localpref %d > %d",
628 pfx_buf, new_buf, exist_buf, new_pref,
629 exist_pref);
630 return 1;
631 }
718e3744 632
d62a17ae 633 if (new_pref < exist_pref) {
fdf81fa0 634 *reason = bgp_path_selection_local_pref;
d62a17ae 635 if (debug)
636 zlog_debug(
637 "%s: %s loses to %s due to localpref %d < %d",
638 pfx_buf, new_buf, exist_buf, new_pref,
639 exist_pref);
640 return 0;
641 }
9fbdd100 642
d62a17ae 643 /* 3. Local route check. We prefer:
644 * - BGP_ROUTE_STATIC
645 * - BGP_ROUTE_AGGREGATE
646 * - BGP_ROUTE_REDISTRIBUTE
647 */
90f4f482 648 if (!(new->sub_type == BGP_ROUTE_NORMAL ||
649 new->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 650 *reason = bgp_path_selection_local_route;
d62a17ae 651 if (debug)
652 zlog_debug(
653 "%s: %s wins over %s due to preferred BGP_ROUTE type",
654 pfx_buf, new_buf, exist_buf);
655 return 1;
656 }
718e3744 657
90f4f482 658 if (!(exist->sub_type == BGP_ROUTE_NORMAL ||
88493076 659 exist->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 660 *reason = bgp_path_selection_local_route;
d62a17ae 661 if (debug)
662 zlog_debug(
663 "%s: %s loses to %s due to preferred BGP_ROUTE type",
664 pfx_buf, new_buf, exist_buf);
665 return 0;
6811845b 666 }
718e3744 667
d62a17ae 668 /* 4. AS path length check. */
669 if (!bgp_flag_check(bgp, BGP_FLAG_ASPATH_IGNORE)) {
670 int exist_hops = aspath_count_hops(existattr->aspath);
671 int exist_confeds = aspath_count_confeds(existattr->aspath);
672
673 if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_CONFED)) {
674 int aspath_hops;
675
676 aspath_hops = aspath_count_hops(newattr->aspath);
677 aspath_hops += aspath_count_confeds(newattr->aspath);
678
679 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 680 *reason = bgp_path_selection_confed_as_path;
d62a17ae 681 if (debug)
682 zlog_debug(
683 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
684 pfx_buf, new_buf, exist_buf,
685 aspath_hops,
686 (exist_hops + exist_confeds));
687 return 1;
688 }
689
690 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 691 *reason = bgp_path_selection_confed_as_path;
d62a17ae 692 if (debug)
693 zlog_debug(
694 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
695 pfx_buf, new_buf, exist_buf,
696 aspath_hops,
697 (exist_hops + exist_confeds));
698 return 0;
699 }
700 } else {
701 int newhops = aspath_count_hops(newattr->aspath);
702
703 if (newhops < exist_hops) {
fdf81fa0 704 *reason = bgp_path_selection_as_path;
d62a17ae 705 if (debug)
706 zlog_debug(
707 "%s: %s wins over %s due to aspath hopcount %d < %d",
708 pfx_buf, new_buf, exist_buf,
709 newhops, exist_hops);
710 return 1;
711 }
712
713 if (newhops > exist_hops) {
fdf81fa0 714 *reason = bgp_path_selection_as_path;
d62a17ae 715 if (debug)
716 zlog_debug(
717 "%s: %s loses to %s due to aspath hopcount %d > %d",
718 pfx_buf, new_buf, exist_buf,
719 newhops, exist_hops);
720 return 0;
721 }
722 }
723 }
9fbdd100 724
d62a17ae 725 /* 5. Origin check. */
726 if (newattr->origin < existattr->origin) {
fdf81fa0 727 *reason = bgp_path_selection_origin;
d62a17ae 728 if (debug)
729 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
730 pfx_buf, new_buf, exist_buf,
731 bgp_origin_long_str[newattr->origin],
732 bgp_origin_long_str[existattr->origin]);
733 return 1;
734 }
718e3744 735
d62a17ae 736 if (newattr->origin > existattr->origin) {
fdf81fa0 737 *reason = bgp_path_selection_origin;
d62a17ae 738 if (debug)
739 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
740 pfx_buf, new_buf, exist_buf,
741 bgp_origin_long_str[newattr->origin],
742 bgp_origin_long_str[existattr->origin]);
743 return 0;
744 }
718e3744 745
d62a17ae 746 /* 6. MED check. */
747 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
748 && aspath_count_hops(existattr->aspath) == 0);
749 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
750 && aspath_count_confeds(existattr->aspath) > 0
751 && aspath_count_hops(newattr->aspath) == 0
752 && aspath_count_hops(existattr->aspath) == 0);
753
754 if (bgp_flag_check(bgp, BGP_FLAG_ALWAYS_COMPARE_MED)
755 || (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED) && confed_as_route)
756 || aspath_cmp_left(newattr->aspath, existattr->aspath)
757 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
758 || internal_as_route) {
759 new_med = bgp_med_value(new->attr, bgp);
760 exist_med = bgp_med_value(exist->attr, bgp);
761
762 if (new_med < exist_med) {
fdf81fa0 763 *reason = bgp_path_selection_med;
d62a17ae 764 if (debug)
765 zlog_debug(
766 "%s: %s wins over %s due to MED %d < %d",
767 pfx_buf, new_buf, exist_buf, new_med,
768 exist_med);
769 return 1;
770 }
8ff56318 771
d62a17ae 772 if (new_med > exist_med) {
fdf81fa0 773 *reason = bgp_path_selection_med;
d62a17ae 774 if (debug)
775 zlog_debug(
776 "%s: %s loses to %s due to MED %d > %d",
777 pfx_buf, new_buf, exist_buf, new_med,
778 exist_med);
779 return 0;
780 }
781 }
9fbdd100 782
d62a17ae 783 /* 7. Peer type check. */
784 new_sort = new->peer->sort;
785 exist_sort = exist->peer->sort;
786
787 if (new_sort == BGP_PEER_EBGP
788 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 789 *reason = bgp_path_selection_peer;
d62a17ae 790 if (debug)
791 zlog_debug(
792 "%s: %s wins over %s due to eBGP peer > iBGP peer",
793 pfx_buf, new_buf, exist_buf);
794 return 1;
795 }
718e3744 796
d62a17ae 797 if (exist_sort == BGP_PEER_EBGP
798 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 799 *reason = bgp_path_selection_peer;
d62a17ae 800 if (debug)
801 zlog_debug(
802 "%s: %s loses to %s due to iBGP peer < eBGP peer",
803 pfx_buf, new_buf, exist_buf);
804 return 0;
805 }
8ff56318 806
d62a17ae 807 /* 8. IGP metric check. */
808 newm = existm = 0;
8ff56318 809
d62a17ae 810 if (new->extra)
811 newm = new->extra->igpmetric;
812 if (exist->extra)
813 existm = exist->extra->igpmetric;
9fbdd100 814
d62a17ae 815 if (newm < existm) {
816 if (debug)
817 zlog_debug(
818 "%s: %s wins over %s due to IGP metric %d < %d",
819 pfx_buf, new_buf, exist_buf, newm, existm);
820 ret = 1;
821 }
718e3744 822
d62a17ae 823 if (newm > existm) {
824 if (debug)
825 zlog_debug(
826 "%s: %s loses to %s due to IGP metric %d > %d",
827 pfx_buf, new_buf, exist_buf, newm, existm);
828 ret = 0;
5e242b0d 829 }
5e242b0d 830
d62a17ae 831 /* 9. Same IGP metric. Compare the cluster list length as
832 representative of IGP hops metric. Rewrite the metric value
833 pair (newm, existm) with the cluster list length. Prefer the
834 path with smaller cluster list length. */
835 if (newm == existm) {
836 if (peer_sort(new->peer) == BGP_PEER_IBGP
837 && peer_sort(exist->peer) == BGP_PEER_IBGP
838 && (mpath_cfg == NULL
839 || CHECK_FLAG(
840 mpath_cfg->ibgp_flags,
841 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
842 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
843 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
844
845 if (newm < existm) {
846 if (debug)
847 zlog_debug(
848 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
849 pfx_buf, new_buf, exist_buf,
850 newm, existm);
851 ret = 1;
852 }
853
854 if (newm > existm) {
855 if (debug)
856 zlog_debug(
857 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
858 pfx_buf, new_buf, exist_buf,
859 newm, existm);
860 ret = 0;
861 }
862 }
863 }
31a4638f 864
d62a17ae 865 /* 10. confed-external vs. confed-internal */
866 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
867 if (new_sort == BGP_PEER_CONFED
868 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 869 *reason = bgp_path_selection_confed;
d62a17ae 870 if (debug)
871 zlog_debug(
872 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
873 pfx_buf, new_buf, exist_buf);
874 return 1;
875 }
718e3744 876
d62a17ae 877 if (exist_sort == BGP_PEER_CONFED
878 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 879 *reason = bgp_path_selection_confed;
d62a17ae 880 if (debug)
881 zlog_debug(
882 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
883 pfx_buf, new_buf, exist_buf);
884 return 0;
885 }
886 }
718e3744 887
d62a17ae 888 /* 11. Maximum path check. */
889 if (newm == existm) {
890 /* If one path has a label but the other does not, do not treat
891 * them as equals for multipath
892 */
a4d82a8a 893 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 894 != (exist->extra
b57ba6d2 895 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 896 if (debug)
897 zlog_debug(
898 "%s: %s and %s cannot be multipath, one has a label while the other does not",
899 pfx_buf, new_buf, exist_buf);
900 } else if (bgp_flag_check(bgp,
901 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
902
903 /*
904 * For the two paths, all comparison steps till IGP
905 * metric
906 * have succeeded - including AS_PATH hop count. Since
907 * 'bgp
908 * bestpath as-path multipath-relax' knob is on, we
909 * don't need
910 * an exact match of AS_PATH. Thus, mark the paths are
911 * equal.
912 * That will trigger both these paths to get into the
913 * multipath
914 * array.
915 */
916 *paths_eq = 1;
917
918 if (debug)
919 zlog_debug(
920 "%s: %s and %s are equal via multipath-relax",
921 pfx_buf, new_buf, exist_buf);
922 } else if (new->peer->sort == BGP_PEER_IBGP) {
923 if (aspath_cmp(new->attr->aspath,
924 exist->attr->aspath)) {
925 *paths_eq = 1;
926
927 if (debug)
928 zlog_debug(
929 "%s: %s and %s are equal via matching aspaths",
930 pfx_buf, new_buf, exist_buf);
931 }
932 } else if (new->peer->as == exist->peer->as) {
933 *paths_eq = 1;
934
935 if (debug)
936 zlog_debug(
937 "%s: %s and %s are equal via same remote-as",
938 pfx_buf, new_buf, exist_buf);
939 }
940 } else {
941 /*
942 * TODO: If unequal cost ibgp multipath is enabled we can
943 * mark the paths as equal here instead of returning
944 */
945 if (debug) {
946 if (ret == 1)
947 zlog_debug(
948 "%s: %s wins over %s after IGP metric comparison",
949 pfx_buf, new_buf, exist_buf);
950 else
951 zlog_debug(
952 "%s: %s loses to %s after IGP metric comparison",
953 pfx_buf, new_buf, exist_buf);
954 }
fdf81fa0 955 *reason = bgp_path_selection_igp_metric;
d62a17ae 956 return ret;
957 }
718e3744 958
d62a17ae 959 /* 12. If both paths are external, prefer the path that was received
960 first (the oldest one). This step minimizes route-flap, since a
961 newer path won't displace an older one, even if it was the
962 preferred route based on the additional decision criteria below. */
963 if (!bgp_flag_check(bgp, BGP_FLAG_COMPARE_ROUTER_ID)
964 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 965 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 966 *reason = bgp_path_selection_older;
d62a17ae 967 if (debug)
968 zlog_debug(
969 "%s: %s wins over %s due to oldest external",
970 pfx_buf, new_buf, exist_buf);
971 return 1;
972 }
9fbdd100 973
1defdda8 974 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 975 *reason = bgp_path_selection_older;
d62a17ae 976 if (debug)
977 zlog_debug(
978 "%s: %s loses to %s due to oldest external",
979 pfx_buf, new_buf, exist_buf);
980 return 0;
981 }
982 }
718e3744 983
d62a17ae 984 /* 13. Router-ID comparision. */
985 /* If one of the paths is "stale", the corresponding peer router-id will
986 * be 0 and would always win over the other path. If originator id is
987 * used for the comparision, it will decide which path is better.
988 */
989 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
990 new_id.s_addr = newattr->originator_id.s_addr;
991 else
992 new_id.s_addr = new->peer->remote_id.s_addr;
993 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
994 exist_id.s_addr = existattr->originator_id.s_addr;
995 else
996 exist_id.s_addr = exist->peer->remote_id.s_addr;
997
998 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 999 *reason = bgp_path_selection_router_id;
d62a17ae 1000 if (debug)
1001 zlog_debug(
1002 "%s: %s wins over %s due to Router-ID comparison",
1003 pfx_buf, new_buf, exist_buf);
1004 return 1;
1005 }
718e3744 1006
d62a17ae 1007 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1008 *reason = bgp_path_selection_router_id;
d62a17ae 1009 if (debug)
1010 zlog_debug(
1011 "%s: %s loses to %s due to Router-ID comparison",
1012 pfx_buf, new_buf, exist_buf);
1013 return 0;
1014 }
9fbdd100 1015
d62a17ae 1016 /* 14. Cluster length comparision. */
1017 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1018 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1019
1020 if (new_cluster < exist_cluster) {
fdf81fa0 1021 *reason = bgp_path_selection_cluster_length;
d62a17ae 1022 if (debug)
1023 zlog_debug(
1024 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1025 pfx_buf, new_buf, exist_buf, new_cluster,
1026 exist_cluster);
1027 return 1;
1028 }
718e3744 1029
d62a17ae 1030 if (new_cluster > exist_cluster) {
fdf81fa0 1031 *reason = bgp_path_selection_cluster_length;
d62a17ae 1032 if (debug)
1033 zlog_debug(
1034 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1035 pfx_buf, new_buf, exist_buf, new_cluster,
1036 exist_cluster);
1037 return 0;
1038 }
9fbdd100 1039
d62a17ae 1040 /* 15. Neighbor address comparision. */
1041 /* Do this only if neither path is "stale" as stale paths do not have
1042 * valid peer information (as the connection may or may not be up).
1043 */
1defdda8 1044 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1045 *reason = bgp_path_selection_stale;
d62a17ae 1046 if (debug)
1047 zlog_debug(
1048 "%s: %s wins over %s due to latter path being STALE",
1049 pfx_buf, new_buf, exist_buf);
1050 return 1;
1051 }
0de5153c 1052
1defdda8 1053 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1054 *reason = bgp_path_selection_stale;
d62a17ae 1055 if (debug)
1056 zlog_debug(
1057 "%s: %s loses to %s due to former path being STALE",
1058 pfx_buf, new_buf, exist_buf);
1059 return 0;
1060 }
718e3744 1061
d62a17ae 1062 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1063 if (new->peer->su_remote == NULL) {
1064 *reason = bgp_path_selection_local_configured;
d62a17ae 1065 return 0;
fdf81fa0
DS
1066 }
1067 if (exist->peer->su_remote == NULL) {
1068 *reason = bgp_path_selection_local_configured;
d62a17ae 1069 return 1;
fdf81fa0 1070 }
9fbdd100 1071
d62a17ae 1072 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1073
1074 if (ret == 1) {
fdf81fa0 1075 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1076 if (debug)
1077 zlog_debug(
1078 "%s: %s loses to %s due to Neighor IP comparison",
1079 pfx_buf, new_buf, exist_buf);
1080 return 0;
1081 }
1082
1083 if (ret == -1) {
fdf81fa0 1084 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1085 if (debug)
1086 zlog_debug(
1087 "%s: %s wins over %s due to Neighor IP comparison",
1088 pfx_buf, new_buf, exist_buf);
1089 return 1;
1090 }
9fbdd100 1091
fdf81fa0 1092 *reason = bgp_path_selection_default;
d62a17ae 1093 if (debug)
1094 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1095 pfx_buf, new_buf, exist_buf);
718e3744 1096
d62a17ae 1097 return 1;
718e3744 1098}
1099
65efcfce
LB
1100/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1101 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1102 * multipath is enabled
65efcfce 1103 * This version is compatible with */
18ee8310
DS
1104int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1105 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1106 afi_t afi, safi_t safi,
1107 enum bgp_path_selection_reason *reason)
d62a17ae 1108{
1109 int paths_eq;
1110 int ret;
18ee8310 1111 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1112 afi, safi, reason);
d62a17ae 1113
1114 if (paths_eq)
1115 ret = 0;
1116 else {
1117 if (ret == 1)
1118 ret = -1;
1119 else
1120 ret = 1;
1121 }
1122 return ret;
65efcfce
LB
1123}
1124
d62a17ae 1125static enum filter_type bgp_input_filter(struct peer *peer, struct prefix *p,
1126 struct attr *attr, afi_t afi,
1127 safi_t safi)
718e3744 1128{
d62a17ae 1129 struct bgp_filter *filter;
718e3744 1130
d62a17ae 1131 filter = &peer->filter[afi][safi];
718e3744 1132
d62a17ae 1133#define FILTER_EXIST_WARN(F, f, filter) \
1134 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1135 zlog_debug("%s: Could not find configured input %s-list %s!", \
1136 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1137
1138 if (DISTRIBUTE_IN_NAME(filter)) {
1139 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1140
1141 if (access_list_apply(DISTRIBUTE_IN(filter), p) == FILTER_DENY)
1142 return FILTER_DENY;
1143 }
1144
1145 if (PREFIX_LIST_IN_NAME(filter)) {
1146 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1147
1148 if (prefix_list_apply(PREFIX_LIST_IN(filter), p) == PREFIX_DENY)
1149 return FILTER_DENY;
1150 }
1151
1152 if (FILTER_LIST_IN_NAME(filter)) {
1153 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1154
1155 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
1156 == AS_FILTER_DENY)
1157 return FILTER_DENY;
1158 }
1159
1160 return FILTER_PERMIT;
650f76c2 1161#undef FILTER_EXIST_WARN
718e3744 1162}
1163
d62a17ae 1164static enum filter_type bgp_output_filter(struct peer *peer, struct prefix *p,
1165 struct attr *attr, afi_t afi,
1166 safi_t safi)
718e3744 1167{
d62a17ae 1168 struct bgp_filter *filter;
1169
1170 filter = &peer->filter[afi][safi];
1171
1172#define FILTER_EXIST_WARN(F, f, filter) \
1173 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1174 zlog_debug("%s: Could not find configured output %s-list %s!", \
1175 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1176
d62a17ae 1177 if (DISTRIBUTE_OUT_NAME(filter)) {
1178 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1179
d62a17ae 1180 if (access_list_apply(DISTRIBUTE_OUT(filter), p) == FILTER_DENY)
1181 return FILTER_DENY;
1182 }
1183
1184 if (PREFIX_LIST_OUT_NAME(filter)) {
1185 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1186
d62a17ae 1187 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
1188 == PREFIX_DENY)
1189 return FILTER_DENY;
1190 }
718e3744 1191
d62a17ae 1192 if (FILTER_LIST_OUT_NAME(filter)) {
1193 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1194
d62a17ae 1195 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
1196 == AS_FILTER_DENY)
1197 return FILTER_DENY;
1198 }
718e3744 1199
d62a17ae 1200 return FILTER_PERMIT;
650f76c2 1201#undef FILTER_EXIST_WARN
718e3744 1202}
1203
1204/* If community attribute includes no_export then return 1. */
d62a17ae 1205static int bgp_community_filter(struct peer *peer, struct attr *attr)
1206{
1207 if (attr->community) {
1208 /* NO_ADVERTISE check. */
1209 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
1210 return 1;
1211
1212 /* NO_EXPORT check. */
1213 if (peer->sort == BGP_PEER_EBGP
1214 && community_include(attr->community, COMMUNITY_NO_EXPORT))
1215 return 1;
1216
1217 /* NO_EXPORT_SUBCONFED check. */
1218 if (peer->sort == BGP_PEER_EBGP
1219 || peer->sort == BGP_PEER_CONFED)
1220 if (community_include(attr->community,
1221 COMMUNITY_NO_EXPORT_SUBCONFED))
1222 return 1;
1223 }
1224 return 0;
718e3744 1225}
1226
1227/* Route reflection loop check. */
d62a17ae 1228static int bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1229{
d62a17ae 1230 struct in_addr cluster_id;
718e3744 1231
d62a17ae 1232 if (attr->cluster) {
1233 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1234 cluster_id = peer->bgp->cluster_id;
1235 else
1236 cluster_id = peer->bgp->router_id;
1237
1238 if (cluster_loop_check(attr->cluster, cluster_id))
1239 return 1;
1240 }
1241 return 0;
718e3744 1242}
6b0655a2 1243
d62a17ae 1244static int bgp_input_modifier(struct peer *peer, struct prefix *p,
1245 struct attr *attr, afi_t afi, safi_t safi,
82b692c0
LK
1246 const char *rmap_name, mpls_label_t *label,
1247 uint32_t num_labels)
718e3744 1248{
d62a17ae 1249 struct bgp_filter *filter;
82b692c0
LK
1250 struct bgp_path_info rmap_path = { 0 };
1251 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1252 route_map_result_t ret;
1253 struct route_map *rmap = NULL;
718e3744 1254
d62a17ae 1255 filter = &peer->filter[afi][safi];
718e3744 1256
d62a17ae 1257 /* Apply default weight value. */
1258 if (peer->weight[afi][safi])
1259 attr->weight = peer->weight[afi][safi];
718e3744 1260
d62a17ae 1261 if (rmap_name) {
1262 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1263
d62a17ae 1264 if (rmap == NULL)
1265 return RMAP_DENY;
1266 } else {
1267 if (ROUTE_MAP_IN_NAME(filter)) {
1268 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1269
d62a17ae 1270 if (rmap == NULL)
1271 return RMAP_DENY;
1272 }
1273 }
0b16f239 1274
d62a17ae 1275 /* Route map apply. */
1276 if (rmap) {
40381db7 1277 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1278 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1279 rmap_path.peer = peer;
1280 rmap_path.attr = attr;
82b692c0
LK
1281 rmap_path.extra = &extra;
1282 extra.num_labels = num_labels;
1283 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1284 memcpy(extra.label, label,
1285 num_labels * sizeof(mpls_label_t));
718e3744 1286
d62a17ae 1287 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1288
d62a17ae 1289 /* Apply BGP route map to the attribute. */
40381db7 1290 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
0b16f239 1291
d62a17ae 1292 peer->rmap_type = 0;
0b16f239 1293
1f2263be 1294 if (ret == RMAP_DENYMATCH)
d62a17ae 1295 return RMAP_DENY;
0b16f239 1296 }
d62a17ae 1297 return RMAP_PERMIT;
0b16f239
DS
1298}
1299
d62a17ae 1300static int bgp_output_modifier(struct peer *peer, struct prefix *p,
1301 struct attr *attr, afi_t afi, safi_t safi,
1302 const char *rmap_name)
0b16f239 1303{
40381db7 1304 struct bgp_path_info rmap_path;
d62a17ae 1305 route_map_result_t ret;
1306 struct route_map *rmap = NULL;
d7c0a89a 1307 uint8_t rmap_type;
0b16f239 1308
b787157a
DS
1309 /*
1310 * So if we get to this point and have no rmap_name
1311 * we want to just show the output as it currently
1312 * exists.
1313 */
1314 if (!rmap_name)
1315 return RMAP_PERMIT;
0b16f239 1316
d62a17ae 1317 /* Apply default weight value. */
1318 if (peer->weight[afi][safi])
1319 attr->weight = peer->weight[afi][safi];
0b16f239 1320
b787157a 1321 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1322
b787157a
DS
1323 /*
1324 * If we have a route map name and we do not find
1325 * the routemap that means we have an implicit
1326 * deny.
1327 */
1328 if (rmap == NULL)
1329 return RMAP_DENY;
0b16f239 1330
40381db7 1331 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1332 /* Route map apply. */
b787157a 1333 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1334 rmap_path.peer = peer;
1335 rmap_path.attr = attr;
0b16f239 1336
0f672529 1337 rmap_type = peer->rmap_type;
b787157a 1338 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1339
b787157a 1340 /* Apply BGP route map to the attribute. */
40381db7 1341 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
ac41b2a2 1342
0f672529 1343 peer->rmap_type = rmap_type;
b787157a
DS
1344
1345 if (ret == RMAP_DENYMATCH)
1346 /*
1347 * caller has multiple error paths with bgp_attr_flush()
1348 */
1349 return RMAP_DENY;
ac41b2a2 1350
d62a17ae 1351 return RMAP_PERMIT;
718e3744 1352}
6b0655a2 1353
5000f21c 1354/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1355static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1356 struct peer *peer, struct attr *attr)
1357{
1358 if (peer->sort == BGP_PEER_EBGP
1359 && (peer_af_flag_check(peer, afi, safi,
1360 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1361 || peer_af_flag_check(peer, afi, safi,
1362 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1363 || peer_af_flag_check(peer, afi, safi,
1364 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1365 || peer_af_flag_check(peer, afi, safi,
1366 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1367 // Take action on the entire aspath
1368 if (peer_af_flag_check(peer, afi, safi,
1369 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1370 || peer_af_flag_check(peer, afi, safi,
1371 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1372 if (peer_af_flag_check(
1373 peer, afi, safi,
1374 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1375 attr->aspath = aspath_replace_private_asns(
bf26b80e 1376 attr->aspath, bgp->as, peer->as);
d62a17ae 1377
1378 // The entire aspath consists of private ASNs so create
1379 // an empty aspath
1380 else if (aspath_private_as_check(attr->aspath))
1381 attr->aspath = aspath_empty_get();
1382
1383 // There are some public and some private ASNs, remove
1384 // the private ASNs
1385 else
1386 attr->aspath = aspath_remove_private_asns(
bf26b80e 1387 attr->aspath, peer->as);
d62a17ae 1388 }
1389
1390 // 'all' was not specified so the entire aspath must be private
1391 // ASNs
1392 // for us to do anything
1393 else if (aspath_private_as_check(attr->aspath)) {
1394 if (peer_af_flag_check(
1395 peer, afi, safi,
1396 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1397 attr->aspath = aspath_replace_private_asns(
bf26b80e 1398 attr->aspath, bgp->as, peer->as);
d62a17ae 1399 else
1400 attr->aspath = aspath_empty_get();
1401 }
1402 }
5000f21c
DS
1403}
1404
c7122e14 1405/* If this is an EBGP peer with as-override */
d62a17ae 1406static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1407 struct peer *peer, struct attr *attr)
1408{
1409 if (peer->sort == BGP_PEER_EBGP
1410 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1411 if (aspath_single_asn_check(attr->aspath, peer->as))
1412 attr->aspath = aspath_replace_specific_asn(
1413 attr->aspath, peer->as, bgp->as);
1414 }
1415}
1416
7f323236
DW
1417void bgp_attr_add_gshut_community(struct attr *attr)
1418{
1419 struct community *old;
1420 struct community *new;
1421 struct community *merge;
1422 struct community *gshut;
1423
1424 old = attr->community;
1425 gshut = community_str2com("graceful-shutdown");
1426
990f4f91 1427 assert(gshut);
1428
7f323236
DW
1429 if (old) {
1430 merge = community_merge(community_dup(old), gshut);
1431
a4d82a8a 1432 if (old->refcnt == 0)
3c1f53de 1433 community_free(&old);
7f323236
DW
1434
1435 new = community_uniq_sort(merge);
3c1f53de 1436 community_free(&merge);
7f323236
DW
1437 } else {
1438 new = community_dup(gshut);
1439 }
1440
3c1f53de 1441 community_free(&gshut);
7f323236
DW
1442 attr->community = new;
1443 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1444
1445 /* When we add the graceful-shutdown community we must also
1446 * lower the local-preference */
1447 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1448 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1449}
1450
1451
d7c0a89a 1452static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1453{
960035b2 1454 if (family == AF_INET) {
d62a17ae 1455 attr->nexthop.s_addr = 0;
960035b2
PZ
1456 attr->mp_nexthop_global_in.s_addr = 0;
1457 }
d62a17ae 1458 if (family == AF_INET6)
1459 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1460 if (family == AF_EVPN)
1461 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1462}
1463
40381db7 1464int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
d62a17ae 1465 struct update_subgroup *subgrp, struct prefix *p,
1466 struct attr *attr)
1467{
1468 struct bgp_filter *filter;
1469 struct peer *from;
1470 struct peer *peer;
1471 struct peer *onlypeer;
1472 struct bgp *bgp;
40381db7 1473 struct attr *piattr;
d62a17ae 1474 char buf[PREFIX_STRLEN];
b68885f9 1475 route_map_result_t ret;
d62a17ae 1476 int transparent;
1477 int reflect;
1478 afi_t afi;
1479 safi_t safi;
1480 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
1481
1482 if (DISABLE_BGP_ANNOUNCE)
1483 return 0;
1484
1485 afi = SUBGRP_AFI(subgrp);
1486 safi = SUBGRP_SAFI(subgrp);
1487 peer = SUBGRP_PEER(subgrp);
1488 onlypeer = NULL;
1489 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1490 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1491
40381db7 1492 from = pi->peer;
d62a17ae 1493 filter = &peer->filter[afi][safi];
1494 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1495 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1496 : pi->attr;
3f9c7369 1497
65efcfce 1498#if ENABLE_BGP_VNC
d62a17ae 1499 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1500 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1501 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1502
1503 /*
1504 * direct and direct_ext type routes originate internally even
1505 * though they can have peer pointers that reference other
1506 * systems
1507 */
1508 prefix2str(p, buf, PREFIX_STRLEN);
1509 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1510 __func__, buf);
1511 samepeer_safe = 1;
1512 }
65efcfce
LB
1513#endif
1514
ddb5b488
PZ
1515 if (((afi == AFI_IP) || (afi == AFI_IP6))
1516 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1517 && (pi->type == ZEBRA_ROUTE_BGP)
1518 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1519
1520 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1521
1522 samepeer_safe = 1;
1523 }
1524
d62a17ae 1525 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1526 * pi is valid */
1527 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1528 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1529 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 1530 return 0;
1531 }
adbac85e 1532
d62a17ae 1533 /* If this is not the bestpath then check to see if there is an enabled
1534 * addpath
1535 * feature that requires us to advertise it */
40381db7 1536 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1537 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
d62a17ae 1538 return 0;
1539 }
1540 }
06370dac 1541
d62a17ae 1542 /* Aggregate-address suppress check. */
40381db7 1543 if (pi->extra && pi->extra->suppress)
d62a17ae 1544 if (!UNSUPPRESS_MAP_NAME(filter)) {
1545 return 0;
1546 }
3f9c7369 1547
13b7e7f0
DS
1548 /*
1549 * If we are doing VRF 2 VRF leaking via the import
1550 * statement, we want to prevent the route going
1551 * off box as that the RT and RD created are localy
1552 * significant and globaly useless.
1553 */
40381db7
DS
1554 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1555 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
13b7e7f0
DS
1556 return 0;
1557
d62a17ae 1558 /* If it's labeled safi, make sure the route has a valid label. */
1559 if (safi == SAFI_LABELED_UNICAST) {
40381db7 1560 mpls_label_t label = bgp_adv_label(rn, pi, peer, afi, safi);
d62a17ae 1561 if (!bgp_is_valid_label(&label)) {
1562 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1563 zlog_debug("u%" PRIu64 ":s%" PRIu64
1564 " %s/%d is filtered - no label (%p)",
1565 subgrp->update_group->id, subgrp->id,
1566 inet_ntop(p->family, &p->u.prefix,
1567 buf, SU_ADDRSTRLEN),
1568 p->prefixlen, &label);
1569 return 0;
1570 }
1571 }
cd1964ff 1572
d62a17ae 1573 /* Do not send back route to sender. */
1574 if (onlypeer && from == onlypeer) {
1575 return 0;
1576 }
3f9c7369 1577
d62a17ae 1578 /* Do not send the default route in the BGP table if the neighbor is
1579 * configured for default-originate */
1580 if (CHECK_FLAG(peer->af_flags[afi][safi],
1581 PEER_FLAG_DEFAULT_ORIGINATE)) {
1582 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
1583 return 0;
1584 else if (p->family == AF_INET6 && p->prefixlen == 0)
1585 return 0;
1586 }
4125bb67 1587
d62a17ae 1588 /* Transparency check. */
1589 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1590 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1591 transparent = 1;
1592 else
1593 transparent = 0;
1594
1595 /* If community is not disabled check the no-export and local. */
40381db7 1596 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1597 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1598 zlog_debug(
1599 "subgrpannouncecheck: community filter check fail");
1600 return 0;
1601 }
3f9c7369 1602
d62a17ae 1603 /* If the attribute has originator-id and it is same as remote
1604 peer's id. */
40381db7
DS
1605 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1606 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1607 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1608 zlog_debug(
1609 "%s [Update:SEND] %s originator-id is same as "
1610 "remote router-id",
1611 onlypeer->host,
1612 prefix2str(p, buf, sizeof(buf)));
1613 return 0;
1614 }
3f9c7369 1615
d62a17ae 1616 /* ORF prefix-list filter check */
1617 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1618 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1619 || CHECK_FLAG(peer->af_cap[afi][safi],
1620 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1621 if (peer->orf_plist[afi][safi]) {
1622 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1623 == PREFIX_DENY) {
1624 if (bgp_debug_update(NULL, p,
1625 subgrp->update_group, 0))
1626 zlog_debug(
1627 "%s [Update:SEND] %s is filtered via ORF",
1628 peer->host,
1629 prefix2str(p, buf,
1630 sizeof(buf)));
1631 return 0;
1632 }
1633 }
1634
1635 /* Output filter check. */
40381db7 1636 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1637 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1638 zlog_debug("%s [Update:SEND] %s is filtered",
1639 peer->host, prefix2str(p, buf, sizeof(buf)));
1640 return 0;
1641 }
3f9c7369
DS
1642
1643#ifdef BGP_SEND_ASPATH_CHECK
d62a17ae 1644 /* AS path loop check. */
40381db7 1645 if (onlypeer && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1646 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1647 zlog_debug(
1648 "%s [Update:SEND] suppress announcement to peer AS %u "
1649 "that is part of AS path.",
1650 onlypeer->host, onlypeer->as);
1651 return 0;
1652 }
3f9c7369
DS
1653#endif /* BGP_SEND_ASPATH_CHECK */
1654
d62a17ae 1655 /* If we're a CONFED we need to loop check the CONFED ID too */
1656 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1657 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1658 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1659 zlog_debug(
1660 "%s [Update:SEND] suppress announcement to peer AS %u"
1661 " is AS path.",
1662 peer->host, bgp->confed_id);
1663 return 0;
1664 }
3f9c7369 1665 }
3f9c7369 1666
d62a17ae 1667 /* Route-Reflect check. */
1668 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1669 reflect = 1;
1670 else
1671 reflect = 0;
1672
1673 /* IBGP reflection check. */
1674 if (reflect && !samepeer_safe) {
1675 /* A route from a Client peer. */
1676 if (CHECK_FLAG(from->af_flags[afi][safi],
1677 PEER_FLAG_REFLECTOR_CLIENT)) {
1678 /* Reflect to all the Non-Client peers and also to the
1679 Client peers other than the originator. Originator
1680 check
1681 is already done. So there is noting to do. */
1682 /* no bgp client-to-client reflection check. */
1683 if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
1684 if (CHECK_FLAG(peer->af_flags[afi][safi],
1685 PEER_FLAG_REFLECTOR_CLIENT))
1686 return 0;
1687 } else {
1688 /* A route from a Non-client peer. Reflect to all other
1689 clients. */
1690 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1691 PEER_FLAG_REFLECTOR_CLIENT))
1692 return 0;
1693 }
1694 }
3f9c7369 1695
d62a17ae 1696 /* For modify attribute, copy it to temporary structure. */
40381db7 1697 bgp_attr_dup(attr, piattr);
d62a17ae 1698
1699 /* If local-preference is not set. */
1700 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1701 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1702 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1703 attr->local_pref = bgp->default_local_pref;
3f9c7369 1704 }
3f9c7369 1705
d62a17ae 1706 /* If originator-id is not set and the route is to be reflected,
1707 set the originator id */
1708 if (reflect
1709 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1710 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1711 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1712 }
3f9c7369 1713
d62a17ae 1714 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1715 */
1716 if (peer->sort == BGP_PEER_EBGP
1717 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1718 if (from != bgp->peer_self && !transparent
1719 && !CHECK_FLAG(peer->af_flags[afi][safi],
1720 PEER_FLAG_MED_UNCHANGED))
1721 attr->flag &=
1722 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1723 }
3f9c7369 1724
d62a17ae 1725 /* Since the nexthop attribute can vary per peer, it is not explicitly
1726 * set
1727 * in announce check, only certain flags and length (or number of
1728 * nexthops
1729 * -- for IPv6/MP_REACH) are set here in order to guide the update
1730 * formation
1731 * code in setting the nexthop(s) on a per peer basis in
1732 * reformat_peer().
1733 * Typically, the source nexthop in the attribute is preserved but in
1734 * the
1735 * scenarios where we know it will always be overwritten, we reset the
1736 * nexthop to "0" in an attempt to achieve better Update packing. An
1737 * example of this is when a prefix from each of 2 IBGP peers needs to
1738 * be
1739 * announced to an EBGP peer (and they have the same attributes barring
1740 * their nexthop).
1741 */
1742 if (reflect)
1743 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1744
1745#define NEXTHOP_IS_V6 \
1746 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1747 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1748 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1749 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1750
1751 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1752 * if
1753 * the peer (group) is configured to receive link-local nexthop
1754 * unchanged
1755 * and it is available in the prefix OR we're not reflecting the route
1756 * and
1757 * the peer (group) to whom we're going to announce is on a shared
1758 * network
1759 * and this is either a self-originated route or the peer is EBGP.
1760 */
1761 if (NEXTHOP_IS_V6) {
1762 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
1763 if ((CHECK_FLAG(peer->af_flags[afi][safi],
1764 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
1765 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
1766 || (!reflect && peer->shared_network
1767 && (from == bgp->peer_self
1768 || peer->sort == BGP_PEER_EBGP))) {
1769 attr->mp_nexthop_len =
1770 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
1771 }
3f9c7369 1772
d62a17ae 1773 /* Clear off link-local nexthop in source, whenever it is not
1774 * needed to
1775 * ensure more prefixes share the same attribute for
1776 * announcement.
1777 */
1778 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
1779 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
1780 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
1781 }
3f9c7369 1782
d62a17ae 1783 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
1784 bgp_peer_as_override(bgp, afi, safi, peer, attr);
1785
1786 /* Route map & unsuppress-map apply. */
40381db7
DS
1787 if (ROUTE_MAP_OUT_NAME(filter) || (pi->extra && pi->extra->suppress)) {
1788 struct bgp_path_info rmap_path;
1789 struct bgp_path_info_extra dummy_rmap_path_extra;
d62a17ae 1790 struct attr dummy_attr;
1791
40381db7
DS
1792 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
1793 rmap_path.peer = peer;
1794 rmap_path.attr = attr;
d37ba549 1795
40381db7
DS
1796 if (pi->extra) {
1797 memcpy(&dummy_rmap_path_extra, pi->extra,
4b7e6066 1798 sizeof(struct bgp_path_info_extra));
40381db7 1799 rmap_path.extra = &dummy_rmap_path_extra;
16f7ce2b
MK
1800 }
1801
d62a17ae 1802 /* don't confuse inbound and outbound setting */
1803 RESET_FLAG(attr->rmap_change_flags);
1804
1805 /*
1806 * The route reflector is not allowed to modify the attributes
1807 * of the reflected IBGP routes unless explicitly allowed.
1808 */
1809 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1810 && !bgp_flag_check(bgp,
1811 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
1812 bgp_attr_dup(&dummy_attr, attr);
40381db7 1813 rmap_path.attr = &dummy_attr;
d62a17ae 1814 }
3f9c7369 1815
d62a17ae 1816 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 1817
40381db7 1818 if (pi->extra && pi->extra->suppress)
d62a17ae 1819 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
40381db7 1820 RMAP_BGP, &rmap_path);
d62a17ae 1821 else
1822 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
40381db7 1823 RMAP_BGP, &rmap_path);
d62a17ae 1824
1825 peer->rmap_type = 0;
1826
1827 if (ret == RMAP_DENYMATCH) {
778048bf
AD
1828 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1829 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1830 peer->host, prefix2str(p, buf, sizeof(buf)));
1831
d62a17ae 1832 bgp_attr_flush(attr);
1833 return 0;
1834 }
3f9c7369 1835 }
3f9c7369 1836
9dac9fc8
DA
1837 /* RFC 8212 to prevent route leaks.
1838 * This specification intends to improve this situation by requiring the
1839 * explicit configuration of both BGP Import and Export Policies for any
1840 * External BGP (EBGP) session such as customers, peers, or
1841 * confederation boundaries for all enabled address families. Through
1842 * codification of the aforementioned requirement, operators will
1843 * benefit from consistent behavior across different BGP
1844 * implementations.
1845 */
1846 if (peer->bgp->ebgp_requires_policy
1847 == DEFAULT_EBGP_POLICY_ENABLED)
1848 if (!bgp_outbound_policy_exists(peer, filter))
1849 return 0;
1850
7f323236 1851 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
a4d82a8a
PZ
1852 if (peer->sort == BGP_PEER_IBGP
1853 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
1854 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1855 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1856 } else {
1857 bgp_attr_add_gshut_community(attr);
1858 }
1859 }
1860
d62a17ae 1861 /* After route-map has been applied, we check to see if the nexthop to
1862 * be carried in the attribute (that is used for the announcement) can
1863 * be cleared off or not. We do this in all cases where we would be
1864 * setting the nexthop to "ourselves". For IPv6, we only need to
1865 * consider
1866 * the global nexthop here; the link-local nexthop would have been
1867 * cleared
1868 * already, and if not, it is required by the update formation code.
1869 * Also see earlier comments in this function.
1870 */
1871 /*
1872 * If route-map has performed some operation on the nexthop or the peer
1873 * configuration says to pass it unchanged, we cannot reset the nexthop
1874 * here, so only attempt to do it if these aren't true. Note that the
1875 * route-map handler itself might have cleared the nexthop, if for
1876 * example,
1877 * it is configured as 'peer-address'.
1878 */
1879 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 1880 piattr->rmap_change_flags)
d62a17ae 1881 && !transparent
1882 && !CHECK_FLAG(peer->af_flags[afi][safi],
1883 PEER_FLAG_NEXTHOP_UNCHANGED)) {
1884 /* We can reset the nexthop, if setting (or forcing) it to
1885 * 'self' */
1886 if (CHECK_FLAG(peer->af_flags[afi][safi],
1887 PEER_FLAG_NEXTHOP_SELF)
1888 || CHECK_FLAG(peer->af_flags[afi][safi],
1889 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
1890 if (!reflect
1891 || CHECK_FLAG(peer->af_flags[afi][safi],
1892 PEER_FLAG_FORCE_NEXTHOP_SELF))
1893 subgroup_announce_reset_nhop(
1894 (peer_cap_enhe(peer, afi, safi)
1895 ? AF_INET6
1896 : p->family),
1897 attr);
1898 } else if (peer->sort == BGP_PEER_EBGP) {
1899 /* Can also reset the nexthop if announcing to EBGP, but
1900 * only if
1901 * no peer in the subgroup is on a shared subnet.
1902 * Note: 3rd party nexthop currently implemented for
1903 * IPv4 only.
1904 */
737af885
BS
1905 if ((p->family == AF_INET) &&
1906 (!bgp_subgrp_multiaccess_check_v4(
1907 piattr->nexthop,
1908 subgrp)))
d62a17ae 1909 subgroup_announce_reset_nhop(
1910 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
1911 ? AF_INET6
1912 : p->family),
737af885
BS
1913 attr);
1914
1915 if ((p->family == AF_INET6) &&
1916 (!bgp_subgrp_multiaccess_check_v6(
1917 piattr->mp_nexthop_global,
1918 subgrp)))
1919 subgroup_announce_reset_nhop(
1920 (peer_cap_enhe(peer, afi, safi)
1921 ? AF_INET6
1922 : p->family),
1923 attr);
1924
1925
1926
40381db7 1927 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
1928 /*
1929 * This flag is used for leaked vpn-vrf routes
1930 */
1931 int family = p->family;
1932
1933 if (peer_cap_enhe(peer, afi, safi))
1934 family = AF_INET6;
1935
1936 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1937 zlog_debug(
1defdda8 1938 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
1939 __func__, family2str(family));
1940 subgroup_announce_reset_nhop(family, attr);
d62a17ae 1941 }
960035b2 1942
d62a17ae 1943 /* If IPv6/MP and nexthop does not have any override and happens
1944 * to
1945 * be a link-local address, reset it so that we don't pass along
1946 * the
1947 * source's link-local IPv6 address to recipients who may not be
1948 * on
1949 * the same interface.
1950 */
1951 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
1952 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global))
1953 subgroup_announce_reset_nhop(AF_INET6, attr);
1954 }
1955 }
3f9c7369 1956
d62a17ae 1957 return 1;
3f9c7369
DS
1958}
1959
d62a17ae 1960void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
1961 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
1962 struct bgp_path_info_pair *result, afi_t afi,
1963 safi_t safi)
1964{
1965 struct bgp_path_info *new_select;
1966 struct bgp_path_info *old_select;
40381db7
DS
1967 struct bgp_path_info *pi;
1968 struct bgp_path_info *pi1;
1969 struct bgp_path_info *pi2;
1970 struct bgp_path_info *nextpi = NULL;
d62a17ae 1971 int paths_eq, do_mpath, debug;
1972 struct list mp_list;
1973 char pfx_buf[PREFIX2STR_BUFFER];
1974 char path_buf[PATH_ADDPATH_STR_BUFFER];
1975
1976 bgp_mp_list_init(&mp_list);
1977 do_mpath =
1978 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
1979
1980 debug = bgp_debug_bestpath(&rn->p);
1981
1982 if (debug)
1983 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
1984
1985 /* bgp deterministic-med */
1986 new_select = NULL;
1987 if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)) {
1988
1defdda8 1989 /* Clear BGP_PATH_DMED_SELECTED for all paths */
6f94b685
DS
1990 for (pi1 = bgp_node_get_bgp_path_info(rn); pi1;
1991 pi1 = pi1->next)
40381db7 1992 bgp_path_info_unset_flag(rn, pi1,
18ee8310 1993 BGP_PATH_DMED_SELECTED);
d62a17ae 1994
6f94b685
DS
1995 for (pi1 = bgp_node_get_bgp_path_info(rn); pi1;
1996 pi1 = pi1->next) {
40381db7 1997 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 1998 continue;
40381db7 1999 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2000 continue;
ea8b2282 2001 if (pi1->peer != bgp->peer_self)
40381db7 2002 if (pi1->peer->status != Established)
d62a17ae 2003 continue;
2004
40381db7
DS
2005 new_select = pi1;
2006 if (pi1->next) {
2007 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2008 if (CHECK_FLAG(pi2->flags,
1defdda8 2009 BGP_PATH_DMED_CHECK))
d62a17ae 2010 continue;
40381db7 2011 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2012 continue;
ea8b2282 2013 if (pi2->peer != bgp->peer_self
d62a17ae 2014 && !CHECK_FLAG(
ea8b2282
DS
2015 pi2->peer->sflags,
2016 PEER_STATUS_NSF_WAIT))
40381db7 2017 if (pi2->peer->status
d62a17ae 2018 != Established)
2019 continue;
2020
121e245d
DS
2021 if (!aspath_cmp_left(pi1->attr->aspath,
2022 pi2->attr->aspath)
2023 && !aspath_cmp_left_confed(
40381db7 2024 pi1->attr->aspath,
121e245d
DS
2025 pi2->attr->aspath))
2026 continue;
d62a17ae 2027
121e245d
DS
2028 if (bgp_path_info_cmp(
2029 bgp, pi2, new_select,
2030 &paths_eq, mpath_cfg, debug,
fdf81fa0
DS
2031 pfx_buf, afi, safi,
2032 &rn->reason)) {
121e245d
DS
2033 bgp_path_info_unset_flag(
2034 rn, new_select,
2035 BGP_PATH_DMED_SELECTED);
2036 new_select = pi2;
d62a17ae 2037 }
121e245d
DS
2038
2039 bgp_path_info_set_flag(
2040 rn, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2041 }
2042 }
18ee8310
DS
2043 bgp_path_info_set_flag(rn, new_select,
2044 BGP_PATH_DMED_CHECK);
2045 bgp_path_info_set_flag(rn, new_select,
2046 BGP_PATH_DMED_SELECTED);
d62a17ae 2047
2048 if (debug) {
18ee8310
DS
2049 bgp_path_info_path_with_addpath_rx_str(
2050 new_select, path_buf);
c66faab1 2051 zlog_debug("%s: %s is the bestpath from AS %u",
d62a17ae 2052 pfx_buf, path_buf,
2053 aspath_get_first_as(
2054 new_select->attr->aspath));
2055 }
2056 }
2057 }
96450faf 2058
d62a17ae 2059 /* Check old selected route and new selected route. */
2060 old_select = NULL;
2061 new_select = NULL;
6f94b685
DS
2062 for (pi = bgp_node_get_bgp_path_info(rn);
2063 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
40381db7
DS
2064 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2065 old_select = pi;
d62a17ae 2066
40381db7 2067 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2068 /* reap REMOVED routes, if needs be
2069 * selected route must stay for a while longer though
2070 */
40381db7
DS
2071 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2072 && (pi != old_select))
2073 bgp_path_info_reap(rn, pi);
d62a17ae 2074
ddb5b488 2075 if (debug)
40381db7
DS
2076 zlog_debug("%s: pi %p in holddown", __func__,
2077 pi);
ddb5b488 2078
d62a17ae 2079 continue;
2080 }
96450faf 2081
40381db7
DS
2082 if (pi->peer && pi->peer != bgp->peer_self
2083 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2084 if (pi->peer->status != Established) {
ddb5b488
PZ
2085
2086 if (debug)
2087 zlog_debug(
40381db7
DS
2088 "%s: pi %p non self peer %s not estab state",
2089 __func__, pi, pi->peer->host);
ddb5b488 2090
d62a17ae 2091 continue;
ddb5b488 2092 }
9fbdd100 2093
d62a17ae 2094 if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)
40381db7
DS
2095 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
2096 bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2097 if (debug)
40381db7 2098 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2099 continue;
2100 }
9fbdd100 2101
40381db7 2102 bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK);
06370dac 2103
40381db7 2104 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
fdf81fa0 2105 debug, pfx_buf, afi, safi, &rn->reason)) {
40381db7 2106 new_select = pi;
d62a17ae 2107 }
2108 }
718e3744 2109
d62a17ae 2110 /* Now that we know which path is the bestpath see if any of the other
2111 * paths
2112 * qualify as multipaths
2113 */
2114 if (debug) {
2115 if (new_select)
18ee8310
DS
2116 bgp_path_info_path_with_addpath_rx_str(new_select,
2117 path_buf);
d62a17ae 2118 else
2119 sprintf(path_buf, "NONE");
2120 zlog_debug(
2121 "%s: After path selection, newbest is %s oldbest was %s",
2122 pfx_buf, path_buf,
2123 old_select ? old_select->peer->host : "NONE");
96450faf 2124 }
9fbdd100 2125
d62a17ae 2126 if (do_mpath && new_select) {
6f94b685
DS
2127 for (pi = bgp_node_get_bgp_path_info(rn);
2128 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2129
2130 if (debug)
18ee8310 2131 bgp_path_info_path_with_addpath_rx_str(
40381db7 2132 pi, path_buf);
d62a17ae 2133
40381db7 2134 if (pi == new_select) {
d62a17ae 2135 if (debug)
2136 zlog_debug(
2137 "%s: %s is the bestpath, add to the multipath list",
2138 pfx_buf, path_buf);
40381db7 2139 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2140 continue;
2141 }
2142
40381db7 2143 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2144 continue;
2145
40381db7
DS
2146 if (pi->peer && pi->peer != bgp->peer_self
2147 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2148 PEER_STATUS_NSF_WAIT))
40381db7 2149 if (pi->peer->status != Established)
d62a17ae 2150 continue;
2151
40381db7 2152 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2153 if (debug)
2154 zlog_debug(
2155 "%s: %s has the same nexthop as the bestpath, skip it",
2156 pfx_buf, path_buf);
2157 continue;
2158 }
2159
40381db7 2160 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0
DS
2161 mpath_cfg, debug, pfx_buf, afi, safi,
2162 &rn->reason);
d62a17ae 2163
2164 if (paths_eq) {
2165 if (debug)
2166 zlog_debug(
2167 "%s: %s is equivalent to the bestpath, add to the multipath list",
2168 pfx_buf, path_buf);
40381db7 2169 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2170 }
2171 }
2172 }
fee0f4c6 2173
18ee8310
DS
2174 bgp_path_info_mpath_update(rn, new_select, old_select, &mp_list,
2175 mpath_cfg);
2176 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2177 bgp_mp_list_clear(&mp_list);
96450faf 2178
dcc68b5e
MS
2179 bgp_addpath_update_ids(bgp, rn, afi, safi);
2180
d62a17ae 2181 result->old = old_select;
2182 result->new = new_select;
96450faf 2183
d62a17ae 2184 return;
fee0f4c6 2185}
2186
3f9c7369
DS
2187/*
2188 * A new route/change in bestpath of an existing route. Evaluate the path
2189 * for advertisement to the subgroup.
2190 */
d62a17ae 2191int subgroup_process_announce_selected(struct update_subgroup *subgrp,
4b7e6066 2192 struct bgp_path_info *selected,
d62a17ae 2193 struct bgp_node *rn,
d7c0a89a 2194 uint32_t addpath_tx_id)
d62a17ae 2195{
2196 struct prefix *p;
2197 struct peer *onlypeer;
2198 struct attr attr;
2199 afi_t afi;
2200 safi_t safi;
adbac85e 2201
d62a17ae 2202 p = &rn->p;
2203 afi = SUBGRP_AFI(subgrp);
2204 safi = SUBGRP_SAFI(subgrp);
2205 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2206 : NULL);
2207
e0207895
PZ
2208 if (BGP_DEBUG(update, UPDATE_OUT)) {
2209 char buf_prefix[PREFIX_STRLEN];
2210 prefix2str(p, buf_prefix, sizeof(buf_prefix));
ddb5b488
PZ
2211 zlog_debug("%s: p=%s, selected=%p", __func__, buf_prefix,
2212 selected);
e0207895
PZ
2213 }
2214
d62a17ae 2215 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2216 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2217 PEER_STATUS_ORF_WAIT_REFRESH))
d62a17ae 2218 return 0;
2219
2220 memset(&attr, 0, sizeof(struct attr));
2221 /* It's initialized in bgp_announce_check() */
2222
2223 /* Announcement to the subgroup. If the route is filtered withdraw it.
2224 */
2225 if (selected) {
2226 if (subgroup_announce_check(rn, selected, subgrp, p, &attr))
2227 bgp_adj_out_set_subgroup(rn, subgrp, &attr, selected);
2228 else
2229 bgp_adj_out_unset_subgroup(rn, subgrp, 1,
dcc68b5e 2230 addpath_tx_id);
d62a17ae 2231 }
2232
2233 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2234 else {
2235 bgp_adj_out_unset_subgroup(rn, subgrp, 1, addpath_tx_id);
2236 }
558d1fec 2237
d62a17ae 2238 return 0;
200df115 2239}
fee0f4c6 2240
3064bf43 2241/*
e1072051 2242 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2243 * This is called at the end of route processing.
3064bf43 2244 */
d62a17ae 2245void bgp_zebra_clear_route_change_flags(struct bgp_node *rn)
3064bf43 2246{
40381db7 2247 struct bgp_path_info *pi;
3064bf43 2248
6f94b685 2249 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 2250 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2251 continue;
40381db7
DS
2252 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2253 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2254 }
3064bf43 2255}
2256
2257/*
2258 * Has the route changed from the RIB's perspective? This is invoked only
2259 * if the route selection returns the same best route as earlier - to
2260 * determine if we need to update zebra or not.
2261 */
4b7e6066
DS
2262int bgp_zebra_has_route_changed(struct bgp_node *rn,
2263 struct bgp_path_info *selected)
d62a17ae 2264{
4b7e6066 2265 struct bgp_path_info *mpinfo;
d62a17ae 2266
2bb9eff4
DS
2267 /* If this is multipath, check all selected paths for any nexthop
2268 * change or attribute change. Some attribute changes (e.g., community)
2269 * aren't of relevance to the RIB, but we'll update zebra to ensure
2270 * we handle the case of BGP nexthop change. This is the behavior
2271 * when the best path has an attribute change anyway.
d62a17ae 2272 */
1defdda8
DS
2273 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
2274 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG))
d62a17ae 2275 return 1;
2276
2bb9eff4
DS
2277 /*
2278 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2279 */
18ee8310
DS
2280 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2281 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2282 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2283 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
d62a17ae 2284 return 1;
2285 }
3064bf43 2286
d62a17ae 2287 /* Nothing has changed from the RIB's perspective. */
2288 return 0;
3064bf43 2289}
2290
d62a17ae 2291struct bgp_process_queue {
2292 struct bgp *bgp;
a4d82a8a 2293 STAILQ_HEAD(, bgp_node) pqueue;
aac24838
JB
2294#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2295 unsigned int flags;
2296 unsigned int queued;
200df115 2297};
2298
3103e8d2
DS
2299/*
2300 * old_select = The old best path
2301 * new_select = the new best path
2302 *
2303 * if (!old_select && new_select)
2304 * We are sending new information on.
2305 *
2306 * if (old_select && new_select) {
2307 * if (new_select != old_select)
2308 * We have a new best path send a change
2309 * else
2310 * We've received a update with new attributes that needs
2311 * to be passed on.
2312 * }
2313 *
2314 * if (old_select && !new_select)
2315 * We have no eligible route that we can announce or the rn
2316 * is being removed.
2317 */
aac24838
JB
2318static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
2319 afi_t afi, safi_t safi)
d62a17ae 2320{
4b7e6066
DS
2321 struct bgp_path_info *new_select;
2322 struct bgp_path_info *old_select;
2323 struct bgp_path_info_pair old_and_new;
ddb5b488
PZ
2324 char pfx_buf[PREFIX2STR_BUFFER];
2325 int debug = 0;
d62a17ae 2326
f4c713ae
LB
2327 if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS)) {
2328 if (rn)
2329 debug = bgp_debug_bestpath(&rn->p);
2330 if (debug) {
2331 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2332 zlog_debug(
2333 "%s: bgp delete in progress, ignoring event, p=%s",
2334 __func__, pfx_buf);
2335 }
2336 return;
2337 }
d62a17ae 2338 /* Is it end of initial update? (after startup) */
2339 if (!rn) {
2340 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2341 sizeof(bgp->update_delay_zebra_resume_time));
2342
2343 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2344 FOREACH_AFI_SAFI (afi, safi) {
2345 if (bgp_fibupd_safi(safi))
2346 bgp_zebra_announce_table(bgp, afi, safi);
2347 }
d62a17ae 2348 bgp->main_peers_update_hold = 0;
2349
2350 bgp_start_routeadv(bgp);
aac24838 2351 return;
d62a17ae 2352 }
cb1faec9 2353
b575a12c
A
2354 struct prefix *p = &rn->p;
2355
ddb5b488
PZ
2356 debug = bgp_debug_bestpath(&rn->p);
2357 if (debug) {
2358 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2359 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__, pfx_buf,
2360 afi2str(afi), safi2str(safi));
2361 }
2362
d62a17ae 2363 /* Best path selection. */
2364 bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new,
2365 afi, safi);
2366 old_select = old_and_new.old;
2367 new_select = old_and_new.new;
2368
2369 /* Do we need to allocate or free labels?
2370 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2371 * necessary to do this upon changes to best path. Exceptions:
2372 * - label index has changed -> recalculate resulting label
2373 * - path_info sub_type changed -> switch to/from implicit-null
2374 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2375 */
318cac96 2376 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2377 if (new_select) {
2378 if (!old_select
2379 || bgp_label_index_differs(new_select, old_select)
57592a53
AD
2380 || new_select->sub_type != old_select->sub_type
2381 || !bgp_is_valid_label(&rn->local_label)) {
2382 /* Enforced penultimate hop popping:
2383 * implicit-null for local routes, aggregate
2384 * and redistributed routes
2385 */
d62a17ae 2386 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2387 || new_select->sub_type
2388 == BGP_ROUTE_AGGREGATE
2389 || new_select->sub_type
2390 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2391 if (CHECK_FLAG(
2392 rn->flags,
2393 BGP_NODE_REGISTERED_FOR_LABEL))
2394 bgp_unregister_for_label(rn);
70e98a7f 2395 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
d62a17ae 2396 &rn->local_label);
2397 bgp_set_valid_label(&rn->local_label);
2398 } else
2399 bgp_register_for_label(rn, new_select);
2400 }
a4d82a8a
PZ
2401 } else if (CHECK_FLAG(rn->flags,
2402 BGP_NODE_REGISTERED_FOR_LABEL)) {
d62a17ae 2403 bgp_unregister_for_label(rn);
318cac96
DW
2404 }
2405 } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
2406 bgp_unregister_for_label(rn);
d62a17ae 2407 }
cd1964ff 2408
ddb5b488
PZ
2409 if (debug) {
2410 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2411 zlog_debug(
2412 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2413 __func__, pfx_buf, afi2str(afi), safi2str(safi),
2414 old_select, new_select);
2415 }
2416
d62a17ae 2417 /* If best route remains the same and this is not due to user-initiated
2418 * clear, see exactly what needs to be done.
2419 */
d62a17ae 2420 if (old_select && old_select == new_select
2421 && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
1defdda8 2422 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2423 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 2424 if (bgp_zebra_has_route_changed(rn, old_select)) {
65efcfce 2425#if ENABLE_BGP_VNC
d62a17ae 2426 vnc_import_bgp_add_route(bgp, p, old_select);
2427 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2428#endif
bb744275 2429 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2430 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2431
2432 if (new_select->type == ZEBRA_ROUTE_BGP
2433 && (new_select->sub_type == BGP_ROUTE_NORMAL
2434 || new_select->sub_type
2435 == BGP_ROUTE_IMPORTED))
2436
2437 bgp_zebra_announce(rn, p, old_select,
2438 bgp, afi, safi);
2439 }
d62a17ae 2440 }
1defdda8 2441 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
d62a17ae 2442 bgp_zebra_clear_route_change_flags(rn);
2443
2444 /* If there is a change of interest to peers, reannounce the
2445 * route. */
1defdda8 2446 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
d62a17ae 2447 || CHECK_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED)) {
2448 group_announce_route(bgp, afi, safi, rn, new_select);
2449
2450 /* unicast routes must also be annouced to
2451 * labeled-unicast update-groups */
2452 if (safi == SAFI_UNICAST)
2453 group_announce_route(bgp, afi,
2454 SAFI_LABELED_UNICAST, rn,
2455 new_select);
2456
1defdda8 2457 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2458 UNSET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED);
2459 }
fee0f4c6 2460
d62a17ae 2461 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2462 return;
d62a17ae 2463 }
8ad7271d 2464
d62a17ae 2465 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2466 */
2467 UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR);
2468
2469 /* bestpath has changed; bump version */
2470 if (old_select || new_select) {
2471 bgp_bump_version(rn);
2472
2473 if (!bgp->t_rmap_def_originate_eval) {
2474 bgp_lock(bgp);
2475 thread_add_timer(
2476 bm->master,
2477 update_group_refresh_default_originate_route_map,
2478 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2479 &bgp->t_rmap_def_originate_eval);
2480 }
2481 }
3f9c7369 2482
d62a17ae 2483 if (old_select)
18ee8310 2484 bgp_path_info_unset_flag(rn, old_select, BGP_PATH_SELECTED);
d62a17ae 2485 if (new_select) {
ddb5b488
PZ
2486 if (debug)
2487 zlog_debug("%s: setting SELECTED flag", __func__);
18ee8310
DS
2488 bgp_path_info_set_flag(rn, new_select, BGP_PATH_SELECTED);
2489 bgp_path_info_unset_flag(rn, new_select, BGP_PATH_ATTR_CHANGED);
1defdda8 2490 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
d62a17ae 2491 }
338b3424 2492
65efcfce 2493#if ENABLE_BGP_VNC
d62a17ae 2494 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2495 if (old_select != new_select) {
2496 if (old_select) {
2497 vnc_import_bgp_exterior_del_route(bgp, p,
2498 old_select);
2499 vnc_import_bgp_del_route(bgp, p, old_select);
2500 }
2501 if (new_select) {
2502 vnc_import_bgp_exterior_add_route(bgp, p,
2503 new_select);
2504 vnc_import_bgp_add_route(bgp, p, new_select);
2505 }
2506 }
2507 }
65efcfce
LB
2508#endif
2509
d62a17ae 2510 group_announce_route(bgp, afi, safi, rn, new_select);
2511
2512 /* unicast routes must also be annouced to labeled-unicast update-groups
2513 */
2514 if (safi == SAFI_UNICAST)
2515 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, rn,
2516 new_select);
2517
2518 /* FIB update. */
2519 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2520 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2521 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2522 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2523 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2524 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2525
2526 /* if this is an evpn imported type-5 prefix,
2527 * we need to withdraw the route first to clear
2528 * the nh neigh and the RMAC entry.
2529 */
2530 if (old_select &&
2531 is_route_parent_evpn(old_select))
2532 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2533
d62a17ae 2534 bgp_zebra_announce(rn, p, new_select, bgp, afi, safi);
2b659f33 2535 } else {
d62a17ae 2536 /* Withdraw the route from the kernel. */
2537 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2538 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2539 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2540 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2541
568e10ca 2542 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2543 }
718e3744 2544 }
3064bf43 2545
5424b7ba
MK
2546 /* advertise/withdraw type-5 routes */
2547 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
f106e3a7 2548 if (advertise_type5_routes(bgp, afi) &&
2549 new_select &&
2550 is_route_injectable_into_evpn(new_select)) {
7e4ed18e
MK
2551
2552 /* apply the route-map */
2553 if (bgp->adv_cmd_rmap[afi][safi].map) {
b68885f9 2554 route_map_result_t ret;
7e4ed18e 2555
3518f352
DS
2556 ret = route_map_apply(
2557 bgp->adv_cmd_rmap[afi][safi].map,
2558 &rn->p, RMAP_BGP, new_select);
b68885f9 2559 if (ret == RMAP_PERMITMATCH)
3518f352
DS
2560 bgp_evpn_advertise_type5_route(
2561 bgp, &rn->p, new_select->attr,
2562 afi, safi);
c27ee4c4 2563 else
2564 bgp_evpn_withdraw_type5_route(
2565 bgp, &rn->p, afi, safi);
7e4ed18e
MK
2566 } else {
2567 bgp_evpn_advertise_type5_route(bgp,
2568 &rn->p,
2569 new_select->attr,
2570 afi, safi);
2571
2572 }
f106e3a7 2573 } else if (advertise_type5_routes(bgp, afi) &&
2574 old_select &&
2575 is_route_injectable_into_evpn(old_select))
31310b25 2576 bgp_evpn_withdraw_type5_route(bgp, &rn->p, afi, safi);
5424b7ba
MK
2577 }
2578
d62a17ae 2579 /* Clear any route change flags. */
2580 bgp_zebra_clear_route_change_flags(rn);
3064bf43 2581
18ee8310 2582 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2583 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
18ee8310 2584 bgp_path_info_reap(rn, old_select);
d62a17ae 2585
2586 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2587 return;
718e3744 2588}
2589
aac24838 2590static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 2591{
aac24838
JB
2592 struct bgp_process_queue *pqnode = data;
2593 struct bgp *bgp = pqnode->bgp;
d62a17ae 2594 struct bgp_table *table;
ac021f40 2595 struct bgp_node *rn;
aac24838
JB
2596
2597 /* eoiu marker */
2598 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
2599 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
2600 /* should always have dedicated wq call */
2601 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
2602 return WQ_SUCCESS;
2603 }
2604
ac021f40
LB
2605 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
2606 rn = STAILQ_FIRST(&pqnode->pqueue);
2607 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
b3e1dd3c 2608 STAILQ_NEXT(rn, pq) = NULL; /* complete unlink */
aac24838 2609 table = bgp_node_table(rn);
ac021f40 2610 /* note, new RNs may be added as part of processing */
aac24838 2611 bgp_process_main_one(bgp, rn, table->afi, table->safi);
cb1faec9 2612
aac24838 2613 bgp_unlock_node(rn);
d62a17ae 2614 bgp_table_unlock(table);
2615 }
aac24838
JB
2616
2617 return WQ_SUCCESS;
2618}
2619
2620static void bgp_processq_del(struct work_queue *wq, void *data)
2621{
2622 struct bgp_process_queue *pqnode = data;
2623
2624 bgp_unlock(pqnode->bgp);
2625
2626 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 2627}
2628
d62a17ae 2629void bgp_process_queue_init(void)
200df115 2630{
0ce1ca80 2631 if (!bm->process_main_queue)
d62a17ae 2632 bm->process_main_queue =
2633 work_queue_new(bm->master, "process_main_queue");
2634
aac24838 2635 bm->process_main_queue->spec.workfunc = &bgp_process_wq;
d62a17ae 2636 bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
2637 bm->process_main_queue->spec.max_retries = 0;
2638 bm->process_main_queue->spec.hold = 50;
2639 /* Use a higher yield value of 50ms for main queue processing */
2640 bm->process_main_queue->spec.yield = 50 * 1000L;
200df115 2641}
2642
cfe8d15a 2643static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
2644{
2645 struct bgp_process_queue *pqnode;
2646
a4d82a8a
PZ
2647 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
2648 sizeof(struct bgp_process_queue));
aac24838
JB
2649
2650 /* unlocked in bgp_processq_del */
2651 pqnode->bgp = bgp_lock(bgp);
2652 STAILQ_INIT(&pqnode->pqueue);
2653
aac24838
JB
2654 return pqnode;
2655}
2656
d62a17ae 2657void bgp_process(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)
fee0f4c6 2658{
aac24838
JB
2659#define ARBITRARY_PROCESS_QLEN 10000
2660 struct work_queue *wq = bm->process_main_queue;
d62a17ae 2661 struct bgp_process_queue *pqnode;
cfe8d15a 2662 int pqnode_reuse = 0;
495f0b13 2663
d62a17ae 2664 /* already scheduled for processing? */
2665 if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED))
2666 return;
2e02b9b2 2667
aac24838 2668 if (wq == NULL)
d62a17ae 2669 return;
2670
aac24838 2671 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
2672 limit only if is from the same BGP view and it's not an EOIU marker
2673 */
aac24838
JB
2674 if (work_queue_item_count(wq)) {
2675 struct work_queue_item *item = work_queue_last_item(wq);
2676 pqnode = item->data;
228da428 2677
a4d82a8a
PZ
2678 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
2679 || pqnode->bgp != bgp
2680 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
2681 pqnode = bgp_processq_alloc(bgp);
2682 else
2683 pqnode_reuse = 1;
aac24838 2684 } else
cfe8d15a 2685 pqnode = bgp_processq_alloc(bgp);
aac24838 2686 /* all unlocked in bgp_process_wq */
d62a17ae 2687 bgp_table_lock(bgp_node_table(rn));
aac24838 2688
d62a17ae 2689 SET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838
JB
2690 bgp_lock_node(rn);
2691
60466a63
QY
2692 /* can't be enqueued twice */
2693 assert(STAILQ_NEXT(rn, pq) == NULL);
aac24838
JB
2694 STAILQ_INSERT_TAIL(&pqnode->pqueue, rn, pq);
2695 pqnode->queued++;
2696
cfe8d15a
LB
2697 if (!pqnode_reuse)
2698 work_queue_add(wq, pqnode);
2699
d62a17ae 2700 return;
fee0f4c6 2701}
0a486e5f 2702
d62a17ae 2703void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 2704{
d62a17ae 2705 struct bgp_process_queue *pqnode;
cb1faec9 2706
d62a17ae 2707 if (bm->process_main_queue == NULL)
2708 return;
2e02b9b2 2709
cfe8d15a 2710 pqnode = bgp_processq_alloc(bgp);
cb1faec9 2711
aac24838 2712 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
cfe8d15a 2713 work_queue_add(bm->process_main_queue, pqnode);
cb1faec9
DS
2714}
2715
d62a17ae 2716static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 2717{
d62a17ae 2718 struct peer *peer;
0a486e5f 2719
d62a17ae 2720 peer = THREAD_ARG(thread);
2721 peer->t_pmax_restart = NULL;
0a486e5f 2722
d62a17ae 2723 if (bgp_debug_neighbor_events(peer))
2724 zlog_debug(
2725 "%s Maximum-prefix restart timer expired, restore peering",
2726 peer->host);
0a486e5f 2727
a9bafa95
DS
2728 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
2729 zlog_debug("%s: %s peer_clear failed",
2730 __PRETTY_FUNCTION__, peer->host);
0a486e5f 2731
d62a17ae 2732 return 0;
0a486e5f 2733}
2734
d62a17ae 2735int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
2736 int always)
718e3744 2737{
d62a17ae 2738 iana_afi_t pkt_afi;
5c525538 2739 iana_safi_t pkt_safi;
9cabb64b 2740
d62a17ae 2741 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
2742 return 0;
e0701b79 2743
d62a17ae 2744 if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) {
2745 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2746 PEER_STATUS_PREFIX_LIMIT)
2747 && !always)
2748 return 0;
e0701b79 2749
d62a17ae 2750 zlog_info(
2751 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2752 "limit %ld",
5cb5f4d0 2753 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 2754 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2755 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
2756
2757 if (CHECK_FLAG(peer->af_flags[afi][safi],
2758 PEER_FLAG_MAX_PREFIX_WARNING))
2759 return 0;
2760
2761 /* Convert AFI, SAFI to values for packet. */
2762 pkt_afi = afi_int2iana(afi);
2763 pkt_safi = safi_int2iana(safi);
2764 {
d7c0a89a 2765 uint8_t ndata[7];
d62a17ae 2766
2767 ndata[0] = (pkt_afi >> 8);
2768 ndata[1] = pkt_afi;
2769 ndata[2] = pkt_safi;
2770 ndata[3] = (peer->pmax[afi][safi] >> 24);
2771 ndata[4] = (peer->pmax[afi][safi] >> 16);
2772 ndata[5] = (peer->pmax[afi][safi] >> 8);
2773 ndata[6] = (peer->pmax[afi][safi]);
2774
2775 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2776 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
2777 BGP_NOTIFY_CEASE_MAX_PREFIX,
2778 ndata, 7);
2779 }
2780
2781 /* Dynamic peers will just close their connection. */
2782 if (peer_dynamic_neighbor(peer))
2783 return 1;
2784
2785 /* restart timer start */
2786 if (peer->pmax_restart[afi][safi]) {
2787 peer->v_pmax_restart =
2788 peer->pmax_restart[afi][safi] * 60;
2789
2790 if (bgp_debug_neighbor_events(peer))
2791 zlog_debug(
2792 "%s Maximum-prefix restart timer started for %d secs",
2793 peer->host, peer->v_pmax_restart);
2794
2795 BGP_TIMER_ON(peer->t_pmax_restart,
2796 bgp_maximum_prefix_restart_timer,
2797 peer->v_pmax_restart);
2798 }
2799
2800 return 1;
2801 } else
2802 UNSET_FLAG(peer->af_sflags[afi][safi],
2803 PEER_STATUS_PREFIX_LIMIT);
2804
2805 if (peer->pcount[afi][safi]
2806 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
2807 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2808 PEER_STATUS_PREFIX_THRESHOLD)
2809 && !always)
2810 return 0;
2811
2812 zlog_info(
2813 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
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;
40381db7 2941 if (!path->attr) {
11ebf4ed 2942 memset(&temp, 0, sizeof(temp));
40381db7
DS
2943 path_eth_s_id = &temp.esi;
2944 path_gw_ip = &temp.ip;
11ebf4ed 2945
d62a17ae 2946 if (eth_s_id == NULL && gw_ip == NULL)
2947 return true;
2948 } else {
40381db7
DS
2949 path_eth_s_id = &(path->attr->evpn_overlay.eth_s_id);
2950 path_gw_ip = &(path->attr->evpn_overlay.gw_ip);
d62a17ae 2951 }
11ebf4ed
DS
2952
2953 if (gw_ip == NULL) {
2954 memset(&temp, 0, sizeof(temp));
40381db7 2955 path_gw_ip_remote = &temp.ip;
11ebf4ed 2956 } else
40381db7 2957 path_gw_ip_remote = gw_ip;
11ebf4ed
DS
2958
2959 if (eth_s_id == NULL) {
2960 memset(&temp, 0, sizeof(temp));
40381db7 2961 path_eth_s_id_remote = &temp.esi;
11ebf4ed 2962 } else
40381db7 2963 path_eth_s_id_remote = eth_s_id;
11ebf4ed 2964
40381db7 2965 if (!memcmp(path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr)))
d62a17ae 2966 return false;
11ebf4ed 2967
40381db7 2968 return !memcmp(path_eth_s_id, path_eth_s_id_remote,
d62a17ae 2969 sizeof(struct eth_segment_id));
684a7227
PG
2970}
2971
c265ee22 2972/* Check if received nexthop is valid or not. */
d62a17ae 2973static int bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
2974 struct attr *attr)
2975{
2976 int ret = 0;
2977
2978 /* Only validated for unicast and multicast currently. */
2979 /* Also valid for EVPN where the nexthop is an IP address. */
2980 if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN)
2981 return 0;
2982
2983 /* If NEXT_HOP is present, validate it. */
2984 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
2985 if (attr->nexthop.s_addr == 0
2986 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
2987 || bgp_nexthop_self(bgp, attr->nexthop))
2988 return 1;
2989 }
c265ee22 2990
d62a17ae 2991 /* If MP_NEXTHOP is present, validate it. */
2992 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2993 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2994 * it is not an IPv6 link-local address.
2995 */
2996 if (attr->mp_nexthop_len) {
2997 switch (attr->mp_nexthop_len) {
2998 case BGP_ATTR_NHLEN_IPV4:
2999 case BGP_ATTR_NHLEN_VPNV4:
3000 ret = (attr->mp_nexthop_global_in.s_addr == 0
3001 || IPV4_CLASS_DE(ntohl(
3002 attr->mp_nexthop_global_in.s_addr))
3003 || bgp_nexthop_self(bgp,
3004 attr->mp_nexthop_global_in));
3005 break;
3006
3007 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
3008 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3009 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
3010 ret = (IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global)
3011 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3012 || IN6_IS_ADDR_MULTICAST(
5e76ce50 3013 &attr->mp_nexthop_global));
d62a17ae 3014 break;
3015
3016 default:
3017 ret = 1;
3018 break;
3019 }
3020 }
c265ee22 3021
d62a17ae 3022 return ret;
3023}
3024
d7c0a89a 3025int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
d62a17ae 3026 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3027 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3028 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3029 struct bgp_route_evpn *evpn)
d62a17ae 3030{
3031 int ret;
3032 int aspath_loop_count = 0;
3033 struct bgp_node *rn;
3034 struct bgp *bgp;
3035 struct attr new_attr;
3036 struct attr *attr_new;
40381db7 3037 struct bgp_path_info *pi;
4b7e6066
DS
3038 struct bgp_path_info *new;
3039 struct bgp_path_info_extra *extra;
d62a17ae 3040 const char *reason;
3041 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3042 int connected = 0;
3043 int do_loop_check = 1;
3044 int has_valid_label = 0;
65efcfce 3045#if ENABLE_BGP_VNC
d62a17ae 3046 int vnc_implicit_withdraw = 0;
65efcfce 3047#endif
d62a17ae 3048 int same_attr = 0;
718e3744 3049
d62a17ae 3050 memset(&new_attr, 0, sizeof(struct attr));
3051 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3052 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3053
d62a17ae 3054 bgp = peer->bgp;
3055 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3056 /* TODO: Check to see if we can get rid of "is_valid_label" */
3057 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3058 has_valid_label = (num_labels > 0) ? 1 : 0;
3059 else
3060 has_valid_label = bgp_is_valid_label(label);
718e3744 3061
d62a17ae 3062 /* When peer's soft reconfiguration enabled. Record input packet in
3063 Adj-RIBs-In. */
3064 if (!soft_reconfig
3065 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3066 && peer != bgp->peer_self)
3067 bgp_adj_in_set(rn, peer, attr, addpath_id);
3068
3069 /* Check previously received route. */
6f94b685 3070 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
3071 if (pi->peer == peer && pi->type == type
3072 && pi->sub_type == sub_type
3073 && pi->addpath_rx_id == addpath_id)
d62a17ae 3074 break;
3075
3076 /* AS path local-as loop check. */
3077 if (peer->change_local_as) {
c4368918
DW
3078 if (peer->allowas_in[afi][safi])
3079 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3080 else if (!CHECK_FLAG(peer->flags,
3081 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3082 aspath_loop_count = 1;
3083
3084 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3085 > aspath_loop_count) {
b4d46cc9 3086 peer->stat_pfx_aspath_loop++;
d62a17ae 3087 reason = "as-path contains our own AS;";
3088 goto filtered;
3089 }
718e3744 3090 }
718e3744 3091
d62a17ae 3092 /* If the peer is configured for "allowas-in origin" and the last ASN in
3093 * the
3094 * as-path is our ASN then we do not need to call aspath_loop_check
3095 */
3096 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3097 if (aspath_get_last_as(attr->aspath) == bgp->as)
3098 do_loop_check = 0;
3099
3100 /* AS path loop check. */
3101 if (do_loop_check) {
3102 if (aspath_loop_check(attr->aspath, bgp->as)
3103 > peer->allowas_in[afi][safi]
3104 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3105 && aspath_loop_check(attr->aspath, bgp->confed_id)
3106 > peer->allowas_in[afi][safi])) {
b4d46cc9 3107 peer->stat_pfx_aspath_loop++;
d62a17ae 3108 reason = "as-path contains our own AS;";
3109 goto filtered;
3110 }
3111 }
aac9ef6c 3112
d62a17ae 3113 /* Route reflector originator ID check. */
3114 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3115 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3116 peer->stat_pfx_originator_loop++;
d62a17ae 3117 reason = "originator is us;";
3118 goto filtered;
3119 }
718e3744 3120
d62a17ae 3121 /* Route reflector cluster ID check. */
3122 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3123 peer->stat_pfx_cluster_loop++;
d62a17ae 3124 reason = "reflected from the same cluster;";
3125 goto filtered;
3126 }
718e3744 3127
d62a17ae 3128 /* Apply incoming filter. */
3129 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3130 peer->stat_pfx_filter++;
d62a17ae 3131 reason = "filter;";
3132 goto filtered;
3133 }
718e3744 3134
a8b72dc6
DA
3135 /* RFC 8212 to prevent route leaks.
3136 * This specification intends to improve this situation by requiring the
3137 * explicit configuration of both BGP Import and Export Policies for any
3138 * External BGP (EBGP) session such as customers, peers, or
3139 * confederation boundaries for all enabled address families. Through
3140 * codification of the aforementioned requirement, operators will
3141 * benefit from consistent behavior across different BGP
3142 * implementations.
3143 */
3144 if (peer->bgp->ebgp_requires_policy == DEFAULT_EBGP_POLICY_ENABLED)
3145 if (!bgp_inbound_policy_exists(peer,
3146 &peer->filter[afi][safi])) {
3147 reason = "inbound policy missing";
3148 goto filtered;
3149 }
3150
d62a17ae 3151 bgp_attr_dup(&new_attr, attr);
3152
3153 /* Apply incoming route-map.
3154 * NB: new_attr may now contain newly allocated values from route-map
3155 * "set"
3156 * commands, so we need bgp_attr_flush in the error paths, until we
3157 * intern
3158 * the attr (which takes over the memory references) */
82b692c0
LK
3159 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL,
3160 label, num_labels) == RMAP_DENY) {
b4d46cc9 3161 peer->stat_pfx_filter++;
d62a17ae 3162 reason = "route-map;";
3163 bgp_attr_flush(&new_attr);
3164 goto filtered;
3165 }
718e3744 3166
7f323236
DW
3167 if (peer->sort == BGP_PEER_EBGP) {
3168
a4d82a8a
PZ
3169 /* If we receive the graceful-shutdown community from an eBGP
3170 * peer we must lower local-preference */
3171 if (new_attr.community
3172 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3173 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3174 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3175
a4d82a8a
PZ
3176 /* If graceful-shutdown is configured then add the GSHUT
3177 * community to all paths received from eBGP peers */
3178 } else if (bgp_flag_check(peer->bgp,
3179 BGP_FLAG_GRACEFUL_SHUTDOWN)) {
7f323236
DW
3180 bgp_attr_add_gshut_community(&new_attr);
3181 }
3182 }
3183
d62a17ae 3184 /* next hop check. */
a4d82a8a
PZ
3185 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
3186 && bgp_update_martian_nexthop(bgp, afi, safi, &new_attr)) {
b4d46cc9 3187 peer->stat_pfx_nh_invalid++;
d62a17ae 3188 reason = "martian or self next-hop;";
3189 bgp_attr_flush(&new_attr);
3190 goto filtered;
3191 }
718e3744 3192
5c14a191 3193 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3194 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3195 reason = "self mac;";
3196 goto filtered;
3197 }
3198
d62a17ae 3199 attr_new = bgp_attr_intern(&new_attr);
3200
3201 /* If the update is implicit withdraw. */
40381db7
DS
3202 if (pi) {
3203 pi->uptime = bgp_clock();
3204 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3205
4a11bf2c
DL
3206 hook_call(bgp_process, bgp, afi, safi, rn, peer, true);
3207
d62a17ae 3208 /* Same attribute comes in. */
40381db7
DS
3209 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3210 && attrhash_cmp(pi->attr, attr_new)
d62a17ae 3211 && (!has_valid_label
40381db7 3212 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3213 num_labels * sizeof(mpls_label_t))
d62a17ae 3214 == 0)
3215 && (overlay_index_equal(
40381db7 3216 afi, pi, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3217 evpn == NULL ? NULL : &evpn->gw_ip))) {
3218 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3219 BGP_CONFIG_DAMPENING)
3220 && peer->sort == BGP_PEER_EBGP
40381db7 3221 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3222 if (bgp_debug_update(peer, p, NULL, 1)) {
3223 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3224 afi, safi, prd, p, label,
3225 num_labels, addpath_id ? 1 : 0,
3226 addpath_id, pfx_buf,
3227 sizeof(pfx_buf));
d62a17ae 3228 zlog_debug("%s rcvd %s", peer->host,
3229 pfx_buf);
3230 }
3231
40381db7 3232 if (bgp_damp_update(pi, rn, afi, safi)
d62a17ae 3233 != BGP_DAMP_SUPPRESSED) {
40381db7 3234 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3235 safi);
3236 bgp_process(bgp, rn, afi, safi);
3237 }
3238 } else /* Duplicate - odd */
3239 {
3240 if (bgp_debug_update(peer, p, NULL, 1)) {
3241 if (!peer->rcvd_attr_printed) {
3242 zlog_debug(
3243 "%s rcvd UPDATE w/ attr: %s",
3244 peer->host,
3245 peer->rcvd_attr_str);
3246 peer->rcvd_attr_printed = 1;
3247 }
3248
3249 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3250 afi, safi, prd, p, label,
3251 num_labels, addpath_id ? 1 : 0,
3252 addpath_id, pfx_buf,
3253 sizeof(pfx_buf));
d62a17ae 3254 zlog_debug(
3255 "%s rcvd %s...duplicate ignored",
3256 peer->host, pfx_buf);
3257 }
3258
3259 /* graceful restart STALE flag unset. */
40381db7 3260 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3261 bgp_path_info_unset_flag(
40381db7 3262 rn, pi, BGP_PATH_STALE);
d62a17ae 3263 bgp_process(bgp, rn, afi, safi);
3264 }
3265 }
3266
3267 bgp_unlock_node(rn);
3268 bgp_attr_unintern(&attr_new);
3269
3270 return 0;
3271 }
718e3744 3272
d62a17ae 3273 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3274 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3275 if (bgp_debug_update(peer, p, NULL, 1)) {
3276 bgp_debug_rdpfxpath2str(
a4d82a8a 3277 afi, safi, prd, p, label, num_labels,
d62a17ae 3278 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3279 sizeof(pfx_buf));
3280 zlog_debug(
3281 "%s rcvd %s, flapped quicker than processing",
3282 peer->host, pfx_buf);
3283 }
3284
40381db7 3285 bgp_path_info_restore(rn, pi);
d62a17ae 3286 }
718e3744 3287
d62a17ae 3288 /* Received Logging. */
3289 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3290 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3291 num_labels, addpath_id ? 1 : 0,
3292 addpath_id, pfx_buf,
3293 sizeof(pfx_buf));
d62a17ae 3294 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3295 }
718e3744 3296
d62a17ae 3297 /* graceful restart STALE flag unset. */
40381db7
DS
3298 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
3299 bgp_path_info_unset_flag(rn, pi, BGP_PATH_STALE);
d62a17ae 3300
3301 /* The attribute is changed. */
40381db7 3302 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3303
3304 /* implicit withdraw, decrement aggregate and pcount here.
3305 * only if update is accepted, they'll increment below.
3306 */
40381db7 3307 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3308
3309 /* Update bgp route dampening information. */
3310 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3311 && peer->sort == BGP_PEER_EBGP) {
3312 /* This is implicit withdraw so we should update
3313 dampening
3314 information. */
40381db7
DS
3315 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
3316 bgp_damp_withdraw(pi, rn, afi, safi, 1);
d62a17ae 3317 }
65efcfce 3318#if ENABLE_BGP_VNC
d62a17ae 3319 if (safi == SAFI_MPLS_VPN) {
3320 struct bgp_node *prn = NULL;
3321 struct bgp_table *table = NULL;
3322
3323 prn = bgp_node_get(bgp->rib[afi][safi],
3324 (struct prefix *)prd);
67009e22
DS
3325 if (bgp_node_has_bgp_path_info_data(prn)) {
3326 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3327
3328 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3329 bgp, prd, table, p, pi);
d62a17ae 3330 }
3331 bgp_unlock_node(prn);
3332 }
3333 if ((afi == AFI_IP || afi == AFI_IP6)
3334 && (safi == SAFI_UNICAST)) {
40381db7 3335 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3336 /*
3337 * Implicit withdraw case.
3338 */
3339 ++vnc_implicit_withdraw;
40381db7
DS
3340 vnc_import_bgp_del_route(bgp, p, pi);
3341 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3342 }
3343 }
65efcfce 3344#endif
128ea8ab 3345
d62a17ae 3346 /* Special handling for EVPN update of an existing route. If the
3347 * extended community attribute has changed, we need to
3348 * un-import
3349 * the route using its existing extended community. It will be
3350 * subsequently processed for import with the new extended
3351 * community.
3352 */
3353 if (safi == SAFI_EVPN && !same_attr) {
40381db7 3354 if ((pi->attr->flag
d62a17ae 3355 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3356 && (attr_new->flag
3357 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3358 int cmp;
3359
40381db7 3360 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3361 attr_new->ecommunity);
3362 if (!cmp) {
3363 if (bgp_debug_update(peer, p, NULL, 1))
3364 zlog_debug(
3365 "Change in EXT-COMM, existing %s new %s",
3366 ecommunity_str(
40381db7 3367 pi->attr->ecommunity),
d62a17ae 3368 ecommunity_str(
3369 attr_new->ecommunity));
3370 bgp_evpn_unimport_route(bgp, afi, safi,
40381db7 3371 p, pi);
d62a17ae 3372 }
3373 }
3374 }
718e3744 3375
d62a17ae 3376 /* Update to new attribute. */
40381db7
DS
3377 bgp_attr_unintern(&pi->attr);
3378 pi->attr = attr_new;
d62a17ae 3379
3380 /* Update MPLS label */
3381 if (has_valid_label) {
40381db7 3382 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3383 if (extra->label != label) {
3384 memcpy(&extra->label, label,
dbd587da 3385 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3386 extra->num_labels = num_labels;
3387 }
b57ba6d2
MK
3388 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3389 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3390 }
718e3744 3391
65efcfce 3392#if ENABLE_BGP_VNC
d62a17ae 3393 if ((afi == AFI_IP || afi == AFI_IP6)
3394 && (safi == SAFI_UNICAST)) {
3395 if (vnc_implicit_withdraw) {
3396 /*
3397 * Add back the route with its new attributes
3398 * (e.g., nexthop).
3399 * The route is still selected, until the route
3400 * selection
3401 * queued by bgp_process actually runs. We have
3402 * to make this
3403 * update to the VNC side immediately to avoid
3404 * racing against
3405 * configuration changes (e.g., route-map
3406 * changes) which
3407 * trigger re-importation of the entire RIB.
3408 */
40381db7
DS
3409 vnc_import_bgp_add_route(bgp, p, pi);
3410 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 3411 }
3412 }
65efcfce 3413#endif
d62a17ae 3414 /* Update Overlay Index */
3415 if (afi == AFI_L2VPN) {
3416 overlay_index_update(
40381db7 3417 pi->attr, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3418 evpn == NULL ? NULL : &evpn->gw_ip);
3419 }
65efcfce 3420
d62a17ae 3421 /* Update bgp route dampening information. */
3422 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3423 && peer->sort == BGP_PEER_EBGP) {
3424 /* Now we do normal update dampening. */
40381db7 3425 ret = bgp_damp_update(pi, rn, afi, safi);
d62a17ae 3426 if (ret == BGP_DAMP_SUPPRESSED) {
3427 bgp_unlock_node(rn);
3428 return 0;
3429 }
3430 }
128ea8ab 3431
d62a17ae 3432 /* Nexthop reachability check - for unicast and
3433 * labeled-unicast.. */
3434 if ((afi == AFI_IP || afi == AFI_IP6)
3435 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
3436 if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1
3437 && !CHECK_FLAG(peer->flags,
3438 PEER_FLAG_DISABLE_CONNECTED_CHECK)
3439 && !bgp_flag_check(
3440 bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
3441 connected = 1;
3442 else
3443 connected = 0;
3444
960035b2
PZ
3445 struct bgp *bgp_nexthop = bgp;
3446
40381db7
DS
3447 if (pi->extra && pi->extra->bgp_orig)
3448 bgp_nexthop = pi->extra->bgp_orig;
960035b2 3449
40381db7
DS
3450 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, afi, pi,
3451 NULL, connected)
a4d82a8a 3452 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
40381db7 3453 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 3454 else {
3455 if (BGP_DEBUG(nht, NHT)) {
3456 char buf1[INET6_ADDRSTRLEN];
3457 inet_ntop(AF_INET,
3458 (const void *)&attr_new
3459 ->nexthop,
3460 buf1, INET6_ADDRSTRLEN);
3461 zlog_debug("%s(%s): NH unresolved",
3462 __FUNCTION__, buf1);
3463 }
40381db7 3464 bgp_path_info_unset_flag(rn, pi,
18ee8310 3465 BGP_PATH_VALID);
d62a17ae 3466 }
3467 } else
40381db7 3468 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 3469
3470#if ENABLE_BGP_VNC
3471 if (safi == SAFI_MPLS_VPN) {
3472 struct bgp_node *prn = NULL;
3473 struct bgp_table *table = NULL;
3474
3475 prn = bgp_node_get(bgp->rib[afi][safi],
3476 (struct prefix *)prd);
67009e22
DS
3477 if (bgp_node_has_bgp_path_info_data(prn)) {
3478 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3479
3480 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 3481 bgp, prd, table, p, pi);
d62a17ae 3482 }
3483 bgp_unlock_node(prn);
3484 }
3485#endif
718e3744 3486
d62a17ae 3487 /* If this is an EVPN route and some attribute has changed,
3488 * process
3489 * route for import. If the extended community has changed, we
3490 * would
3491 * have done the un-import earlier and the import would result
3492 * in the
3493 * route getting injected into appropriate L2 VNIs. If it is
3494 * just
3495 * some other attribute change, the import will result in
3496 * updating
3497 * the attributes for the route in the VNI(s).
3498 */
3499 if (safi == SAFI_EVPN && !same_attr)
40381db7 3500 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 3501
3502 /* Process change. */
40381db7 3503 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 3504
3505 bgp_process(bgp, rn, afi, safi);
3506 bgp_unlock_node(rn);
558d1fec 3507
ddb5b488
PZ
3508 if (SAFI_UNICAST == safi
3509 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3510 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3511
40381db7 3512 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3513 }
3514 if ((SAFI_MPLS_VPN == safi)
3515 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3516
40381db7 3517 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
3518 }
3519
28070ee3 3520#if ENABLE_BGP_VNC
d62a17ae 3521 if (SAFI_MPLS_VPN == safi) {
3522 mpls_label_t label_decoded = decode_label(label);
28070ee3 3523
d62a17ae 3524 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3525 type, sub_type, &label_decoded);
3526 }
3527 if (SAFI_ENCAP == safi) {
3528 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3529 type, sub_type, NULL);
3530 }
28070ee3
PZ
3531#endif
3532
d62a17ae 3533 return 0;
3534 } // End of implicit withdraw
718e3744 3535
d62a17ae 3536 /* Received Logging. */
3537 if (bgp_debug_update(peer, p, NULL, 1)) {
3538 if (!peer->rcvd_attr_printed) {
3539 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3540 peer->rcvd_attr_str);
3541 peer->rcvd_attr_printed = 1;
3542 }
718e3744 3543
a4d82a8a 3544 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3545 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3546 sizeof(pfx_buf));
3547 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3548 }
718e3744 3549
d62a17ae 3550 /* Make new BGP info. */
3551 new = info_make(type, sub_type, 0, peer, attr_new, rn);
718e3744 3552
d62a17ae 3553 /* Update MPLS label */
3554 if (has_valid_label) {
18ee8310 3555 extra = bgp_path_info_extra_get(new);
8ba71050 3556 if (extra->label != label) {
dbd587da
QY
3557 memcpy(&extra->label, label,
3558 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3559 extra->num_labels = num_labels;
3560 }
b57ba6d2
MK
3561 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3562 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3563 }
718e3744 3564
d62a17ae 3565 /* Update Overlay Index */
3566 if (afi == AFI_L2VPN) {
3567 overlay_index_update(new->attr,
3568 evpn == NULL ? NULL : &evpn->eth_s_id,
3569 evpn == NULL ? NULL : &evpn->gw_ip);
3570 }
3571 /* Nexthop reachability check. */
3572 if ((afi == AFI_IP || afi == AFI_IP6)
3573 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
3574 if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1
3575 && !CHECK_FLAG(peer->flags,
3576 PEER_FLAG_DISABLE_CONNECTED_CHECK)
3577 && !bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
3578 connected = 1;
3579 else
3580 connected = 0;
3581
960035b2 3582 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, connected)
a4d82a8a 3583 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
18ee8310 3584 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
d62a17ae 3585 else {
3586 if (BGP_DEBUG(nht, NHT)) {
3587 char buf1[INET6_ADDRSTRLEN];
3588 inet_ntop(AF_INET,
3589 (const void *)&attr_new->nexthop,
3590 buf1, INET6_ADDRSTRLEN);
3591 zlog_debug("%s(%s): NH unresolved",
3592 __FUNCTION__, buf1);
3593 }
18ee8310 3594 bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID);
d62a17ae 3595 }
3596 } else
18ee8310 3597 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
a82478b9 3598
d62a17ae 3599 /* Addpath ID */
3600 new->addpath_rx_id = addpath_id;
3601
3602 /* Increment prefix */
3603 bgp_aggregate_increment(bgp, p, new, afi, safi);
3604
3605 /* Register new BGP information. */
18ee8310 3606 bgp_path_info_add(rn, new);
d62a17ae 3607
3608 /* route_node_get lock */
3609 bgp_unlock_node(rn);
558d1fec 3610
65efcfce 3611#if ENABLE_BGP_VNC
d62a17ae 3612 if (safi == SAFI_MPLS_VPN) {
3613 struct bgp_node *prn = NULL;
3614 struct bgp_table *table = NULL;
3615
3616 prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
67009e22
DS
3617 if (bgp_node_has_bgp_path_info_data(prn)) {
3618 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3619
3620 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3621 bgp, prd, table, p, new);
3622 }
3623 bgp_unlock_node(prn);
3624 }
65efcfce
LB
3625#endif
3626
d62a17ae 3627 /* If maximum prefix count is configured and current prefix
3628 count exeed it. */
3629 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3630 return -1;
718e3744 3631
d62a17ae 3632 /* If this is an EVPN route, process for import. */
3633 if (safi == SAFI_EVPN)
3634 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 3635
4a11bf2c
DL
3636 hook_call(bgp_process, bgp, afi, safi, rn, peer, false);
3637
d62a17ae 3638 /* Process change. */
3639 bgp_process(bgp, rn, afi, safi);
718e3744 3640
ddb5b488
PZ
3641 if (SAFI_UNICAST == safi
3642 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3643 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3644 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
3645 }
3646 if ((SAFI_MPLS_VPN == safi)
3647 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3648
3649 vpn_leak_to_vrf_update(bgp, new);
3650 }
28070ee3 3651#if ENABLE_BGP_VNC
d62a17ae 3652 if (SAFI_MPLS_VPN == safi) {
3653 mpls_label_t label_decoded = decode_label(label);
28070ee3 3654
d62a17ae 3655 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3656 sub_type, &label_decoded);
3657 }
3658 if (SAFI_ENCAP == safi) {
3659 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3660 sub_type, NULL);
3661 }
28070ee3
PZ
3662#endif
3663
d62a17ae 3664 return 0;
718e3744 3665
d62a17ae 3666/* This BGP update is filtered. Log the reason then update BGP
3667 entry. */
3668filtered:
4a11bf2c
DL
3669 hook_call(bgp_process, bgp, afi, safi, rn, peer, true);
3670
d62a17ae 3671 if (bgp_debug_update(peer, p, NULL, 1)) {
3672 if (!peer->rcvd_attr_printed) {
3673 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3674 peer->rcvd_attr_str);
3675 peer->rcvd_attr_printed = 1;
3676 }
718e3744 3677
a4d82a8a 3678 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3679 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3680 sizeof(pfx_buf));
3681 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3682 peer->host, pfx_buf, reason);
3683 }
128ea8ab 3684
40381db7 3685 if (pi) {
d62a17ae 3686 /* If this is an EVPN route, un-import it as it is now filtered.
3687 */
3688 if (safi == SAFI_EVPN)
40381db7 3689 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 3690
ddb5b488
PZ
3691 if (SAFI_UNICAST == safi
3692 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3693 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3694
40381db7 3695 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3696 }
3697 if ((SAFI_MPLS_VPN == safi)
3698 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3699
40381db7 3700 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
3701 }
3702
40381db7 3703 bgp_rib_remove(rn, pi, peer, afi, safi);
d62a17ae 3704 }
3705
3706 bgp_unlock_node(rn);
558d1fec 3707
97736e32 3708#if ENABLE_BGP_VNC
d62a17ae 3709 /*
3710 * Filtered update is treated as an implicit withdrawal (see
3711 * bgp_rib_remove()
3712 * a few lines above)
3713 */
3714 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
3715 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
3716 0);
3717 }
97736e32
PZ
3718#endif
3719
d62a17ae 3720 return 0;
718e3744 3721}
3722
d7c0a89a 3723int bgp_withdraw(struct peer *peer, struct prefix *p, uint32_t addpath_id,
d62a17ae 3724 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3725 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3726 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 3727{
d62a17ae 3728 struct bgp *bgp;
3729 char pfx_buf[BGP_PRD_PATH_STRLEN];
3730 struct bgp_node *rn;
40381db7 3731 struct bgp_path_info *pi;
718e3744 3732
28070ee3 3733#if ENABLE_BGP_VNC
d62a17ae 3734 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
3735 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
3736 0);
3737 }
28070ee3
PZ
3738#endif
3739
d62a17ae 3740 bgp = peer->bgp;
3741
3742 /* Lookup node. */
3743 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
3744
3745 /* If peer is soft reconfiguration enabled. Record input packet for
3746 * further calculation.
3747 *
3748 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3749 * routes that are filtered. This tanks out Quagga RS pretty badly due
3750 * to
3751 * the iteration over all RS clients.
3752 * Since we need to remove the entry from adj_in anyway, do that first
3753 * and
3754 * if there was no entry, we don't need to do anything more.
3755 */
3756 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3757 && peer != bgp->peer_self)
3758 if (!bgp_adj_in_unset(rn, peer, addpath_id)) {
b4d46cc9
DL
3759 peer->stat_pfx_dup_withdraw++;
3760
d62a17ae 3761 if (bgp_debug_update(peer, p, NULL, 1)) {
3762 bgp_debug_rdpfxpath2str(
a4d82a8a 3763 afi, safi, prd, p, label, num_labels,
d62a17ae 3764 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3765 sizeof(pfx_buf));
3766 zlog_debug(
3767 "%s withdrawing route %s not in adj-in",
3768 peer->host, pfx_buf);
3769 }
3770 bgp_unlock_node(rn);
3771 return 0;
3772 }
cd808e74 3773
d62a17ae 3774 /* Lookup withdrawn route. */
6f94b685 3775 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
3776 if (pi->peer == peer && pi->type == type
3777 && pi->sub_type == sub_type
3778 && pi->addpath_rx_id == addpath_id)
d62a17ae 3779 break;
3780
3781 /* Logging. */
3782 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 3783 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3784 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3785 sizeof(pfx_buf));
3786 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
3787 pfx_buf);
3788 }
718e3744 3789
d62a17ae 3790 /* Withdraw specified route from routing table. */
40381db7
DS
3791 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
3792 bgp_rib_withdraw(rn, pi, peer, afi, safi, prd);
ddb5b488
PZ
3793 if (SAFI_UNICAST == safi
3794 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3795 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 3796 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3797 }
3798 if ((SAFI_MPLS_VPN == safi)
3799 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3800
40381db7 3801 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
3802 }
3803 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 3804 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3805 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3806 sizeof(pfx_buf));
3807 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
3808 }
718e3744 3809
d62a17ae 3810 /* Unlock bgp_node_get() lock. */
3811 bgp_unlock_node(rn);
3812
3813 return 0;
718e3744 3814}
6b0655a2 3815
d62a17ae 3816void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
3817 int withdraw)
718e3744 3818{
d62a17ae 3819 struct update_subgroup *subgrp;
3820 subgrp = peer_subgroup(peer, afi, safi);
3821 subgroup_default_originate(subgrp, withdraw);
3f9c7369 3822}
6182d65b 3823
718e3744 3824
3f9c7369
DS
3825/*
3826 * bgp_stop_announce_route_timer
3827 */
d62a17ae 3828void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 3829{
d62a17ae 3830 if (!paf->t_announce_route)
3831 return;
3832
3833 THREAD_TIMER_OFF(paf->t_announce_route);
718e3744 3834}
6b0655a2 3835
3f9c7369
DS
3836/*
3837 * bgp_announce_route_timer_expired
3838 *
3839 * Callback that is invoked when the route announcement timer for a
3840 * peer_af expires.
3841 */
d62a17ae 3842static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 3843{
d62a17ae 3844 struct peer_af *paf;
3845 struct peer *peer;
558d1fec 3846
d62a17ae 3847 paf = THREAD_ARG(t);
3848 peer = paf->peer;
718e3744 3849
d62a17ae 3850 if (peer->status != Established)
3851 return 0;
3f9c7369 3852
d62a17ae 3853 if (!peer->afc_nego[paf->afi][paf->safi])
3854 return 0;
3f9c7369 3855
d62a17ae 3856 peer_af_announce_route(paf, 1);
3857 return 0;
718e3744 3858}
3859
3f9c7369
DS
3860/*
3861 * bgp_announce_route
3862 *
3863 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3864 */
d62a17ae 3865void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
3866{
3867 struct peer_af *paf;
3868 struct update_subgroup *subgrp;
3869
3870 paf = peer_af_find(peer, afi, safi);
3871 if (!paf)
3872 return;
3873 subgrp = PAF_SUBGRP(paf);
3874
3875 /*
3876 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3877 * or a refresh has already been triggered.
3878 */
3879 if (!subgrp || paf->t_announce_route)
3880 return;
3881
3882 /*
3883 * Start a timer to stagger/delay the announce. This serves
3884 * two purposes - announcement can potentially be combined for
3885 * multiple peers and the announcement doesn't happen in the
3886 * vty context.
3887 */
3888 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
3889 (subgrp->peer_count == 1)
3890 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3891 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
3892 &paf->t_announce_route);
3f9c7369
DS
3893}
3894
3895/*
3896 * Announce routes from all AF tables to a peer.
3897 *
3898 * This should ONLY be called when there is a need to refresh the
3899 * routes to the peer based on a policy change for this peer alone
3900 * or a route refresh request received from the peer.
3901 * The operation will result in splitting the peer from its existing
3902 * subgroups and putting it in new subgroups.
3903 */
d62a17ae 3904void bgp_announce_route_all(struct peer *peer)
718e3744 3905{
d62a17ae 3906 afi_t afi;
3907 safi_t safi;
3908
05c7a1cc
QY
3909 FOREACH_AFI_SAFI (afi, safi)
3910 bgp_announce_route(peer, afi, safi);
718e3744 3911}
6b0655a2 3912
d62a17ae 3913static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
3914 struct bgp_table *table,
3915 struct prefix_rd *prd)
718e3744 3916{
d62a17ae 3917 int ret;
3918 struct bgp_node *rn;
3919 struct bgp_adj_in *ain;
718e3744 3920
d62a17ae 3921 if (!table)
3922 table = peer->bgp->rib[afi][safi];
718e3744 3923
d62a17ae 3924 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
3925 for (ain = rn->adj_in; ain; ain = ain->next) {
ea47320b
DL
3926 if (ain->peer != peer)
3927 continue;
8692c506 3928
6f94b685
DS
3929 struct bgp_path_info *pi =
3930 bgp_node_get_bgp_path_info(rn);
d7c0a89a 3931 uint32_t num_labels = 0;
b57ba6d2 3932 mpls_label_t *label_pnt = NULL;
8cb687c2 3933 struct bgp_route_evpn evpn;
b57ba6d2 3934
40381db7
DS
3935 if (pi && pi->extra)
3936 num_labels = pi->extra->num_labels;
b57ba6d2 3937 if (num_labels)
40381db7 3938 label_pnt = &pi->extra->label[0];
8cb687c2
DS
3939 if (pi)
3940 memcpy(&evpn, &pi->attr->evpn_overlay,
3941 sizeof(evpn));
3942 else
3943 memset(&evpn, 0, sizeof(evpn));
8692c506 3944
ea47320b
DL
3945 ret = bgp_update(peer, &rn->p, ain->addpath_rx_id,
3946 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
a4d82a8a 3947 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 3948 num_labels, 1, &evpn);
ea47320b
DL
3949
3950 if (ret < 0) {
3951 bgp_unlock_node(rn);
3952 return;
d62a17ae 3953 }
3954 }
718e3744 3955}
3956
d62a17ae 3957void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 3958{
d62a17ae 3959 struct bgp_node *rn;
3960 struct bgp_table *table;
718e3744 3961
d62a17ae 3962 if (peer->status != Established)
3963 return;
718e3744 3964
d62a17ae 3965 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
3966 && (safi != SAFI_EVPN))
3967 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
3968 else
3969 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
67009e22
DS
3970 rn = bgp_route_next(rn)) {
3971 table = bgp_node_get_bgp_table_info(rn);
3972 if (table != NULL) {
d62a17ae 3973 struct prefix_rd prd;
67009e22 3974
d62a17ae 3975 prd.family = AF_UNSPEC;
3976 prd.prefixlen = 64;
3977 memcpy(&prd.val, rn->p.u.val, 8);
8692c506 3978
d62a17ae 3979 bgp_soft_reconfig_table(peer, afi, safi, table,
3980 &prd);
3981 }
67009e22 3982 }
718e3744 3983}
6b0655a2 3984
228da428 3985
d62a17ae 3986struct bgp_clear_node_queue {
3987 struct bgp_node *rn;
228da428
CC
3988};
3989
d62a17ae 3990static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 3991{
d62a17ae 3992 struct bgp_clear_node_queue *cnq = data;
3993 struct bgp_node *rn = cnq->rn;
3994 struct peer *peer = wq->spec.data;
40381db7 3995 struct bgp_path_info *pi;
3103e8d2 3996 struct bgp *bgp;
d62a17ae 3997 afi_t afi = bgp_node_table(rn)->afi;
3998 safi_t safi = bgp_node_table(rn)->safi;
3999
4000 assert(rn && peer);
3103e8d2 4001 bgp = peer->bgp;
d62a17ae 4002
4003 /* It is possible that we have multiple paths for a prefix from a peer
4004 * if that peer is using AddPath.
4005 */
6f94b685 4006 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 4007 if (pi->peer != peer)
ea47320b
DL
4008 continue;
4009
4010 /* graceful restart STALE flag set. */
4011 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4012 && peer->nsf[afi][safi]
40381db7
DS
4013 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4014 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
4015 bgp_path_info_set_flag(rn, pi, BGP_PATH_STALE);
ea47320b
DL
4016 else {
4017 /* If this is an EVPN route, process for
4018 * un-import. */
4019 if (safi == SAFI_EVPN)
40381db7
DS
4020 bgp_evpn_unimport_route(bgp, afi, safi, &rn->p,
4021 pi);
3103e8d2
DS
4022 /* Handle withdraw for VRF route-leaking and L3VPN */
4023 if (SAFI_UNICAST == safi
4024 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4025 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4026 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4027 bgp, pi);
960035b2 4028 }
3103e8d2 4029 if (SAFI_MPLS_VPN == safi &&
960035b2 4030 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4031 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4032 }
3103e8d2 4033
40381db7 4034 bgp_rib_remove(rn, pi, peer, afi, safi);
d62a17ae 4035 }
ea47320b 4036 }
d62a17ae 4037 return WQ_SUCCESS;
200df115 4038}
4039
d62a17ae 4040static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4041{
d62a17ae 4042 struct bgp_clear_node_queue *cnq = data;
4043 struct bgp_node *rn = cnq->rn;
4044 struct bgp_table *table = bgp_node_table(rn);
228da428 4045
d62a17ae 4046 bgp_unlock_node(rn);
4047 bgp_table_unlock(table);
4048 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4049}
4050
d62a17ae 4051static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4052{
d62a17ae 4053 struct peer *peer = wq->spec.data;
64e580a7 4054
d62a17ae 4055 /* Tickle FSM to start moving again */
4056 BGP_EVENT_ADD(peer, Clearing_Completed);
4057
4058 peer_unlock(peer); /* bgp_clear_route */
200df115 4059}
718e3744 4060
d62a17ae 4061static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4062{
d62a17ae 4063 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4064
4065 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4066#undef CLEAR_QUEUE_NAME_LEN
4067
0ce1ca80 4068 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4069 peer->clear_node_queue->spec.hold = 10;
4070 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4071 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4072 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4073 peer->clear_node_queue->spec.max_retries = 0;
4074
4075 /* we only 'lock' this peer reference when the queue is actually active
4076 */
4077 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4078}
4079
d62a17ae 4080static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4081 struct bgp_table *table)
65ca75e0 4082{
d62a17ae 4083 struct bgp_node *rn;
4084 int force = bm->process_main_queue ? 0 : 1;
6cf159b9 4085
d62a17ae 4086 if (!table)
4087 table = peer->bgp->rib[afi][safi];
dc83d712 4088
d62a17ae 4089 /* If still no table => afi/safi isn't configured at all or smth. */
4090 if (!table)
4091 return;
dc83d712 4092
d62a17ae 4093 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
40381db7 4094 struct bgp_path_info *pi, *next;
d62a17ae 4095 struct bgp_adj_in *ain;
4096 struct bgp_adj_in *ain_next;
4097
4098 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4099 * queued for every clearing peer, regardless of whether it is
4100 * relevant to the peer at hand.
4101 *
4102 * Overview: There are 3 different indices which need to be
4103 * scrubbed, potentially, when a peer is removed:
4104 *
4105 * 1 peer's routes visible via the RIB (ie accepted routes)
4106 * 2 peer's routes visible by the (optional) peer's adj-in index
4107 * 3 other routes visible by the peer's adj-out index
4108 *
4109 * 3 there is no hurry in scrubbing, once the struct peer is
4110 * removed from bgp->peer, we could just GC such deleted peer's
4111 * adj-outs at our leisure.
4112 *
4113 * 1 and 2 must be 'scrubbed' in some way, at least made
4114 * invisible via RIB index before peer session is allowed to be
4115 * brought back up. So one needs to know when such a 'search' is
4116 * complete.
4117 *
4118 * Ideally:
4119 *
4120 * - there'd be a single global queue or a single RIB walker
4121 * - rather than tracking which route_nodes still need to be
4122 * examined on a peer basis, we'd track which peers still
4123 * aren't cleared
4124 *
4125 * Given that our per-peer prefix-counts now should be reliable,
4126 * this may actually be achievable. It doesn't seem to be a huge
4127 * problem at this time,
4128 *
4129 * It is possible that we have multiple paths for a prefix from
4130 * a peer
4131 * if that peer is using AddPath.
4132 */
4133 ain = rn->adj_in;
4134 while (ain) {
4135 ain_next = ain->next;
4136
4137 if (ain->peer == peer) {
4138 bgp_adj_in_remove(rn, ain);
4139 bgp_unlock_node(rn);
4140 }
4141
4142 ain = ain_next;
4143 }
4144
6f94b685 4145 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
40381db7
DS
4146 next = pi->next;
4147 if (pi->peer != peer)
d62a17ae 4148 continue;
4149
4150 if (force)
40381db7 4151 bgp_path_info_reap(rn, pi);
d62a17ae 4152 else {
4153 struct bgp_clear_node_queue *cnq;
4154
4155 /* both unlocked in bgp_clear_node_queue_del */
4156 bgp_table_lock(bgp_node_table(rn));
4157 bgp_lock_node(rn);
4158 cnq = XCALLOC(
4159 MTYPE_BGP_CLEAR_NODE_QUEUE,
4160 sizeof(struct bgp_clear_node_queue));
4161 cnq->rn = rn;
4162 work_queue_add(peer->clear_node_queue, cnq);
4163 break;
4164 }
4165 }
4166 }
4167 return;
4168}
4169
4170void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4171{
4172 struct bgp_node *rn;
4173 struct bgp_table *table;
4174
4175 if (peer->clear_node_queue == NULL)
4176 bgp_clear_node_queue_init(peer);
4177
4178 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4179 * Idle until it receives a Clearing_Completed event. This protects
4180 * against peers which flap faster than we can we clear, which could
4181 * lead to:
4182 *
4183 * a) race with routes from the new session being installed before
4184 * clear_route_node visits the node (to delete the route of that
4185 * peer)
4186 * b) resource exhaustion, clear_route_node likely leads to an entry
4187 * on the process_main queue. Fast-flapping could cause that queue
4188 * to grow and grow.
4189 */
4190
4191 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4192 * the unlock will happen upon work-queue completion; other wise, the
4193 * unlock happens at the end of this function.
4194 */
4195 if (!peer->clear_node_queue->thread)
4196 peer_lock(peer);
4197
4198 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4199 bgp_clear_route_table(peer, afi, safi, NULL);
4200 else
4201 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
67009e22
DS
4202 rn = bgp_route_next(rn)) {
4203 table = bgp_node_get_bgp_table_info(rn);
4204 if (!table)
4205 continue;
4206
4207 bgp_clear_route_table(peer, afi, safi, table);
4208 }
d62a17ae 4209
4210 /* unlock if no nodes got added to the clear-node-queue. */
4211 if (!peer->clear_node_queue->thread)
4212 peer_unlock(peer);
718e3744 4213}
d62a17ae 4214
4215void bgp_clear_route_all(struct peer *peer)
718e3744 4216{
d62a17ae 4217 afi_t afi;
4218 safi_t safi;
718e3744 4219
05c7a1cc
QY
4220 FOREACH_AFI_SAFI (afi, safi)
4221 bgp_clear_route(peer, afi, safi);
65efcfce
LB
4222
4223#if ENABLE_BGP_VNC
d62a17ae 4224 rfapiProcessPeerDown(peer);
65efcfce 4225#endif
718e3744 4226}
4227
d62a17ae 4228void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4229{
d62a17ae 4230 struct bgp_table *table;
4231 struct bgp_node *rn;
4232 struct bgp_adj_in *ain;
4233 struct bgp_adj_in *ain_next;
718e3744 4234
d62a17ae 4235 table = peer->bgp->rib[afi][safi];
718e3744 4236
d62a17ae 4237 /* It is possible that we have multiple paths for a prefix from a peer
4238 * if that peer is using AddPath.
4239 */
4240 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
4241 ain = rn->adj_in;
43143c8f 4242
d62a17ae 4243 while (ain) {
4244 ain_next = ain->next;
43143c8f 4245
d62a17ae 4246 if (ain->peer == peer) {
4247 bgp_adj_in_remove(rn, ain);
4248 bgp_unlock_node(rn);
4249 }
43143c8f 4250
d62a17ae 4251 ain = ain_next;
4252 }
4253 }
718e3744 4254}
93406d87 4255
d62a17ae 4256void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4257{
4258 struct bgp_node *rn;
40381db7 4259 struct bgp_path_info *pi;
d62a17ae 4260 struct bgp_table *table;
4261
4262 if (safi == SAFI_MPLS_VPN) {
4263 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4264 rn = bgp_route_next(rn)) {
4265 struct bgp_node *rm;
d62a17ae 4266
4267 /* look for neighbor in tables */
67009e22
DS
4268 table = bgp_node_get_bgp_table_info(rn);
4269 if (!table)
ea47320b
DL
4270 continue;
4271
4272 for (rm = bgp_table_top(table); rm;
4273 rm = bgp_route_next(rm))
6f94b685
DS
4274 for (pi = bgp_node_get_bgp_path_info(rm); pi;
4275 pi = pi->next) {
40381db7 4276 if (pi->peer != peer)
ea47320b 4277 continue;
40381db7 4278 if (!CHECK_FLAG(pi->flags,
1defdda8 4279 BGP_PATH_STALE))
ea47320b
DL
4280 break;
4281
40381db7 4282 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4283 break;
4284 }
d62a17ae 4285 }
4286 } else {
4287 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4288 rn = bgp_route_next(rn))
6f94b685
DS
4289 for (pi = bgp_node_get_bgp_path_info(rn); pi;
4290 pi = pi->next) {
40381db7 4291 if (pi->peer != peer)
ea47320b 4292 continue;
40381db7 4293 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4294 break;
40381db7 4295 bgp_rib_remove(rn, pi, peer, afi, safi);
ea47320b
DL
4296 break;
4297 }
d62a17ae 4298 }
93406d87 4299}
6b0655a2 4300
9dac9fc8
DA
4301int bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
4302{
4303 if (peer->sort == BGP_PEER_EBGP
4304 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
4305 || FILTER_LIST_OUT_NAME(filter)
4306 || DISTRIBUTE_OUT_NAME(filter)))
4307 return 1;
4308 return 0;
4309}
4310
4311int bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
4312{
4313 if (peer->sort == BGP_PEER_EBGP
4314 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
4315 || FILTER_LIST_IN_NAME(filter)
4316 || DISTRIBUTE_IN_NAME(filter)))
4317 return 1;
4318 return 0;
4319}
4320
568e10ca 4321static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
4322 safi_t safi)
bb86c601 4323{
d62a17ae 4324 struct bgp_node *rn;
40381db7 4325 struct bgp_path_info *pi;
4b7e6066 4326 struct bgp_path_info *next;
bb86c601 4327
d62a17ae 4328 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
6f94b685 4329 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
40381db7 4330 next = pi->next;
1b7bb747
CS
4331
4332 /* Unimport EVPN routes from VRFs */
4333 if (safi == SAFI_EVPN)
4334 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
4335 SAFI_EVPN,
4336 &rn->p, pi);
4337
40381db7
DS
4338 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
4339 && pi->type == ZEBRA_ROUTE_BGP
4340 && (pi->sub_type == BGP_ROUTE_NORMAL
4341 || pi->sub_type == BGP_ROUTE_AGGREGATE
4342 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 4343
d62a17ae 4344 if (bgp_fibupd_safi(safi))
40381db7
DS
4345 bgp_zebra_withdraw(&rn->p, pi, bgp,
4346 safi);
4347 bgp_path_info_reap(rn, pi);
d62a17ae 4348 }
4349 }
bb86c601
LB
4350}
4351
718e3744 4352/* Delete all kernel routes. */
d62a17ae 4353void bgp_cleanup_routes(struct bgp *bgp)
4354{
4355 afi_t afi;
4356 struct bgp_node *rn;
67009e22 4357 struct bgp_table *table;
d62a17ae 4358
4359 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
4360 if (afi == AFI_L2VPN)
4361 continue;
568e10ca 4362 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
4363 SAFI_UNICAST);
d62a17ae 4364 /*
4365 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4366 */
4367 if (afi != AFI_L2VPN) {
4368 safi_t safi;
4369 safi = SAFI_MPLS_VPN;
4370 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4371 rn = bgp_route_next(rn)) {
67009e22
DS
4372 table = bgp_node_get_bgp_table_info(rn);
4373 if (table != NULL) {
4374 bgp_cleanup_table(bgp, table, safi);
4375 bgp_table_finish(&table);
4376 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4377 bgp_unlock_node(rn);
4378 }
4379 }
4380 safi = SAFI_ENCAP;
4381 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4382 rn = bgp_route_next(rn)) {
67009e22
DS
4383 table = bgp_node_get_bgp_table_info(rn);
4384 if (table != NULL) {
4385 bgp_cleanup_table(bgp, table, safi);
4386 bgp_table_finish(&table);
4387 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4388 bgp_unlock_node(rn);
4389 }
4390 }
4391 }
4392 }
4393 for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn;
4394 rn = bgp_route_next(rn)) {
67009e22
DS
4395 table = bgp_node_get_bgp_table_info(rn);
4396 if (table != NULL) {
4397 bgp_cleanup_table(bgp, table, SAFI_EVPN);
4398 bgp_table_finish(&table);
4399 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4400 bgp_unlock_node(rn);
4401 }
bb86c601 4402 }
718e3744 4403}
4404
d62a17ae 4405void bgp_reset(void)
718e3744 4406{
d62a17ae 4407 vty_reset();
4408 bgp_zclient_reset();
4409 access_list_reset();
4410 prefix_list_reset();
718e3744 4411}
6b0655a2 4412
d62a17ae 4413static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 4414{
d62a17ae 4415 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
4416 && CHECK_FLAG(peer->af_cap[afi][safi],
4417 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
4418}
4419
718e3744 4420/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4421 value. */
d62a17ae 4422int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
4423 struct bgp_nlri *packet)
4424{
d7c0a89a
QY
4425 uint8_t *pnt;
4426 uint8_t *lim;
d62a17ae 4427 struct prefix p;
4428 int psize;
4429 int ret;
4430 afi_t afi;
4431 safi_t safi;
4432 int addpath_encoded;
d7c0a89a 4433 uint32_t addpath_id;
d62a17ae 4434
d62a17ae 4435 pnt = packet->nlri;
4436 lim = pnt + packet->length;
4437 afi = packet->afi;
4438 safi = packet->safi;
4439 addpath_id = 0;
4440 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
4441
4442 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4443 syntactic validity. If the field is syntactically incorrect,
4444 then the Error Subcode is set to Invalid Network Field. */
4445 for (; pnt < lim; pnt += psize) {
4446 /* Clear prefix structure. */
4447 memset(&p, 0, sizeof(struct prefix));
4448
4449 if (addpath_encoded) {
4450
4451 /* When packet overflow occurs return immediately. */
4452 if (pnt + BGP_ADDPATH_ID_LEN > lim)
513386b5 4453 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4454
4455 addpath_id = ntohl(*((uint32_t *)pnt));
4456 pnt += BGP_ADDPATH_ID_LEN;
4457 }
718e3744 4458
d62a17ae 4459 /* Fetch prefix length. */
4460 p.prefixlen = *pnt++;
4461 /* afi/safi validity already verified by caller,
4462 * bgp_update_receive */
4463 p.family = afi2family(afi);
4464
4465 /* Prefix length check. */
4466 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 4467 flog_err(
e50f7cfd 4468 EC_BGP_UPDATE_RCV,
14454c9f 4469 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 4470 peer->host, p.prefixlen, packet->afi);
513386b5 4471 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 4472 }
6b0655a2 4473
d62a17ae 4474 /* Packet size overflow check. */
4475 psize = PSIZE(p.prefixlen);
4476
4477 /* When packet overflow occur return immediately. */
4478 if (pnt + psize > lim) {
af4c2728 4479 flog_err(
e50f7cfd 4480 EC_BGP_UPDATE_RCV,
d62a17ae 4481 "%s [Error] Update packet error (prefix length %d overflows packet)",
4482 peer->host, p.prefixlen);
513386b5 4483 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4484 }
4485
4486 /* Defensive coding, double-check the psize fits in a struct
4487 * prefix */
4488 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 4489 flog_err(
e50f7cfd 4490 EC_BGP_UPDATE_RCV,
d62a17ae 4491 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4492 peer->host, p.prefixlen, sizeof(p.u));
513386b5 4493 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4494 }
4495
4496 /* Fetch prefix from NLRI packet. */
a85297a7 4497 memcpy(p.u.val, pnt, psize);
d62a17ae 4498
4499 /* Check address. */
4500 if (afi == AFI_IP && safi == SAFI_UNICAST) {
4501 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
4502 /* From RFC4271 Section 6.3:
4503 *
4504 * If a prefix in the NLRI field is semantically
4505 * incorrect
4506 * (e.g., an unexpected multicast IP address),
4507 * an error SHOULD
4508 * be logged locally, and the prefix SHOULD be
4509 * ignored.
a4d82a8a 4510 */
af4c2728 4511 flog_err(
e50f7cfd 4512 EC_BGP_UPDATE_RCV,
d62a17ae 4513 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4514 peer->host, inet_ntoa(p.u.prefix4));
4515 continue;
4516 }
4517 }
4518
4519 /* Check address. */
4520 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
4521 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4522 char buf[BUFSIZ];
4523
af4c2728 4524 flog_err(
e50f7cfd 4525 EC_BGP_UPDATE_RCV,
d62a17ae 4526 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4527 peer->host,
4528 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4529 BUFSIZ));
4530
4531 continue;
4532 }
4533 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
4534 char buf[BUFSIZ];
4535
af4c2728 4536 flog_err(
e50f7cfd 4537 EC_BGP_UPDATE_RCV,
d62a17ae 4538 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4539 peer->host,
4540 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4541 BUFSIZ));
4542
4543 continue;
4544 }
4545 }
4546
4547 /* Normal process. */
4548 if (attr)
4549 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
4550 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 4551 NULL, NULL, 0, 0, NULL);
d62a17ae 4552 else
4553 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
4554 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
4555 BGP_ROUTE_NORMAL, NULL, NULL, 0,
4556 NULL);
d62a17ae 4557
513386b5
DA
4558 /* Do not send BGP notification twice when maximum-prefix count
4559 * overflow. */
4560 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4561 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
4562
4563 /* Address family configuration mismatch. */
d62a17ae 4564 if (ret < 0)
513386b5 4565 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 4566 }
4567
4568 /* Packet length consistency check. */
4569 if (pnt != lim) {
af4c2728 4570 flog_err(
e50f7cfd 4571 EC_BGP_UPDATE_RCV,
d62a17ae 4572 "%s [Error] Update packet error (prefix length mismatch with total length)",
4573 peer->host);
513386b5 4574 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4575 }
6b0655a2 4576
513386b5 4577 return BGP_NLRI_PARSE_OK;
718e3744 4578}
4579
d62a17ae 4580static struct bgp_static *bgp_static_new(void)
718e3744 4581{
d62a17ae 4582 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 4583}
4584
d62a17ae 4585static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 4586{
0a22ddfb 4587 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 4588 route_map_counter_decrement(bgp_static->rmap.map);
4589
0a22ddfb 4590 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 4591 XFREE(MTYPE_BGP_STATIC, bgp_static);
4592}
4593
4594void bgp_static_update(struct bgp *bgp, struct prefix *p,
4595 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
4596{
4597 struct bgp_node *rn;
40381db7 4598 struct bgp_path_info *pi;
4b7e6066 4599 struct bgp_path_info *new;
40381db7 4600 struct bgp_path_info rmap_path;
d62a17ae 4601 struct attr attr;
4602 struct attr *attr_new;
b68885f9 4603 route_map_result_t ret;
65efcfce 4604#if ENABLE_BGP_VNC
d62a17ae 4605 int vnc_implicit_withdraw = 0;
65efcfce 4606#endif
fee0f4c6 4607
d62a17ae 4608 assert(bgp_static);
4609 if (!bgp_static)
4610 return;
dd8103a9 4611
d62a17ae 4612 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4613
d62a17ae 4614 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 4615
d62a17ae 4616 attr.nexthop = bgp_static->igpnexthop;
4617 attr.med = bgp_static->igpmetric;
4618 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 4619
d62a17ae 4620 if (bgp_static->atomic)
4621 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 4622
d62a17ae 4623 /* Store label index, if required. */
4624 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
4625 attr.label_index = bgp_static->label_index;
4626 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
4627 }
718e3744 4628
d62a17ae 4629 /* Apply route-map. */
4630 if (bgp_static->rmap.name) {
4631 struct attr attr_tmp = attr;
80ced710 4632
40381db7
DS
4633 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
4634 rmap_path.peer = bgp->peer_self;
4635 rmap_path.attr = &attr_tmp;
fee0f4c6 4636
d62a17ae 4637 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 4638
40381db7
DS
4639 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
4640 &rmap_path);
fee0f4c6 4641
d62a17ae 4642 bgp->peer_self->rmap_type = 0;
718e3744 4643
d62a17ae 4644 if (ret == RMAP_DENYMATCH) {
4645 /* Free uninterned attribute. */
4646 bgp_attr_flush(&attr_tmp);
718e3744 4647
d62a17ae 4648 /* Unintern original. */
4649 aspath_unintern(&attr.aspath);
4650 bgp_static_withdraw(bgp, p, afi, safi);
4651 return;
4652 }
7f323236
DW
4653
4654 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
4655 bgp_attr_add_gshut_community(&attr_tmp);
4656
d62a17ae 4657 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
4658 } else {
4659
4660 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
4661 bgp_attr_add_gshut_community(&attr);
4662
d62a17ae 4663 attr_new = bgp_attr_intern(&attr);
7f323236 4664 }
718e3744 4665
6f94b685 4666 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4667 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4668 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4669 break;
4670
40381db7
DS
4671 if (pi) {
4672 if (attrhash_cmp(pi->attr, attr_new)
4673 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
d62a17ae 4674 && !bgp_flag_check(bgp, BGP_FLAG_FORCE_STATIC_PROCESS)) {
4675 bgp_unlock_node(rn);
4676 bgp_attr_unintern(&attr_new);
4677 aspath_unintern(&attr.aspath);
4678 return;
4679 } else {
4680 /* The attribute is changed. */
40381db7 4681 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4682
4683 /* Rewrite BGP route information. */
40381db7
DS
4684 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
4685 bgp_path_info_restore(rn, pi);
d62a17ae 4686 else
40381db7 4687 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
65efcfce 4688#if ENABLE_BGP_VNC
d62a17ae 4689 if ((afi == AFI_IP || afi == AFI_IP6)
4690 && (safi == SAFI_UNICAST)) {
40381db7 4691 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4692 /*
4693 * Implicit withdraw case.
40381db7 4694 * We have to do this before pi is
d62a17ae 4695 * changed
4696 */
4697 ++vnc_implicit_withdraw;
40381db7 4698 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 4699 vnc_import_bgp_exterior_del_route(
40381db7 4700 bgp, p, pi);
d62a17ae 4701 }
4702 }
65efcfce 4703#endif
40381db7
DS
4704 bgp_attr_unintern(&pi->attr);
4705 pi->attr = attr_new;
4706 pi->uptime = bgp_clock();
65efcfce 4707#if ENABLE_BGP_VNC
d62a17ae 4708 if ((afi == AFI_IP || afi == AFI_IP6)
4709 && (safi == SAFI_UNICAST)) {
4710 if (vnc_implicit_withdraw) {
40381db7 4711 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 4712 vnc_import_bgp_exterior_add_route(
40381db7 4713 bgp, p, pi);
d62a17ae 4714 }
4715 }
65efcfce 4716#endif
718e3744 4717
d62a17ae 4718 /* Nexthop reachability check. */
4719 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
4720 && (safi == SAFI_UNICAST
4721 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
4722
4723 struct bgp *bgp_nexthop = bgp;
4724
40381db7
DS
4725 if (pi->extra && pi->extra->bgp_orig)
4726 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
4727
4728 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
40381db7
DS
4729 afi, pi, NULL, 0))
4730 bgp_path_info_set_flag(rn, pi,
18ee8310 4731 BGP_PATH_VALID);
d62a17ae 4732 else {
4733 if (BGP_DEBUG(nht, NHT)) {
4734 char buf1[INET6_ADDRSTRLEN];
4735 inet_ntop(p->family,
4736 &p->u.prefix, buf1,
4737 INET6_ADDRSTRLEN);
4738 zlog_debug(
4739 "%s(%s): Route not in table, not advertising",
4740 __FUNCTION__, buf1);
4741 }
18ee8310 4742 bgp_path_info_unset_flag(
40381db7 4743 rn, pi, BGP_PATH_VALID);
d62a17ae 4744 }
4745 } else {
4746 /* Delete the NHT structure if any, if we're
4747 * toggling between
4748 * enabling/disabling import check. We
4749 * deregister the route
4750 * from NHT to avoid overloading NHT and the
4751 * process interaction
4752 */
40381db7
DS
4753 bgp_unlink_nexthop(pi);
4754 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 4755 }
4756 /* Process change. */
40381db7 4757 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4758 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
4759
4760 if (SAFI_UNICAST == safi
4761 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4762 || bgp->inst_type
4763 == BGP_INSTANCE_TYPE_DEFAULT)) {
4764 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 4765 pi);
ddb5b488
PZ
4766 }
4767
d62a17ae 4768 bgp_unlock_node(rn);
4769 aspath_unintern(&attr.aspath);
4770 return;
4771 }
718e3744 4772 }
718e3744 4773
d62a17ae 4774 /* Make new BGP info. */
4775 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
4776 attr_new, rn);
4777 /* Nexthop reachability check. */
4778 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
4779 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 4780 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
18ee8310 4781 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
d62a17ae 4782 else {
4783 if (BGP_DEBUG(nht, NHT)) {
4784 char buf1[INET6_ADDRSTRLEN];
4785 inet_ntop(p->family, &p->u.prefix, buf1,
4786 INET6_ADDRSTRLEN);
4787 zlog_debug(
4788 "%s(%s): Route not in table, not advertising",
4789 __FUNCTION__, buf1);
4790 }
18ee8310 4791 bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID);
d62a17ae 4792 }
4793 } else {
4794 /* Delete the NHT structure if any, if we're toggling between
4795 * enabling/disabling import check. We deregister the route
4796 * from NHT to avoid overloading NHT and the process interaction
4797 */
4798 bgp_unlink_nexthop(new);
4799
18ee8310 4800 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
fc9a856f 4801 }
078430f6 4802
d62a17ae 4803 /* Aggregate address increment. */
4804 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 4805
d62a17ae 4806 /* Register new BGP information. */
18ee8310 4807 bgp_path_info_add(rn, new);
718e3744 4808
d62a17ae 4809 /* route_node_get lock */
4810 bgp_unlock_node(rn);
4811
4812 /* Process change. */
4813 bgp_process(bgp, rn, afi, safi);
4814
ddb5b488
PZ
4815 if (SAFI_UNICAST == safi
4816 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4817 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4818 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4819 }
4820
d62a17ae 4821 /* Unintern original. */
4822 aspath_unintern(&attr.aspath);
718e3744 4823}
4824
d62a17ae 4825void bgp_static_withdraw(struct bgp *bgp, struct prefix *p, afi_t afi,
4826 safi_t safi)
718e3744 4827{
d62a17ae 4828 struct bgp_node *rn;
40381db7 4829 struct bgp_path_info *pi;
718e3744 4830
d62a17ae 4831 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4832
d62a17ae 4833 /* Check selected route and self inserted route. */
6f94b685 4834 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4835 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4836 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4837 break;
4838
4839 /* Withdraw static BGP route from routing table. */
40381db7 4840 if (pi) {
ddb5b488
PZ
4841 if (SAFI_UNICAST == safi
4842 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4843 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4844 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 4845 }
40381db7
DS
4846 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
4847 bgp_unlink_nexthop(pi);
4848 bgp_path_info_delete(rn, pi);
d62a17ae 4849 bgp_process(bgp, rn, afi, safi);
4850 }
718e3744 4851
d62a17ae 4852 /* Unlock bgp_node_lookup. */
4853 bgp_unlock_node(rn);
718e3744 4854}
4855
137446f9
LB
4856/*
4857 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4858 */
d62a17ae 4859static void bgp_static_withdraw_safi(struct bgp *bgp, struct prefix *p,
4860 afi_t afi, safi_t safi,
4861 struct prefix_rd *prd)
718e3744 4862{
d62a17ae 4863 struct bgp_node *rn;
40381db7 4864 struct bgp_path_info *pi;
718e3744 4865
d62a17ae 4866 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 4867
d62a17ae 4868 /* Check selected route and self inserted route. */
6f94b685 4869 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4870 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4871 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4872 break;
718e3744 4873
d62a17ae 4874 /* Withdraw static BGP route from routing table. */
40381db7 4875 if (pi) {
65efcfce 4876#if ENABLE_BGP_VNC
d62a17ae 4877 rfapiProcessWithdraw(
40381db7 4878 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 4879 1); /* Kill, since it is an administrative change */
65efcfce 4880#endif
ddb5b488
PZ
4881 if (SAFI_MPLS_VPN == safi
4882 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4883 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 4884 }
40381db7
DS
4885 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
4886 bgp_path_info_delete(rn, pi);
d62a17ae 4887 bgp_process(bgp, rn, afi, safi);
4888 }
718e3744 4889
d62a17ae 4890 /* Unlock bgp_node_lookup. */
4891 bgp_unlock_node(rn);
718e3744 4892}
4893
d62a17ae 4894static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p,
4895 struct bgp_static *bgp_static, afi_t afi,
4896 safi_t safi)
137446f9 4897{
d62a17ae 4898 struct bgp_node *rn;
4b7e6066 4899 struct bgp_path_info *new;
d62a17ae 4900 struct attr *attr_new;
4901 struct attr attr = {0};
40381db7 4902 struct bgp_path_info *pi;
65efcfce 4903#if ENABLE_BGP_VNC
d62a17ae 4904 mpls_label_t label = 0;
65efcfce 4905#endif
d7c0a89a 4906 uint32_t num_labels = 0;
d62a17ae 4907 union gw_addr add;
137446f9 4908
d62a17ae 4909 assert(bgp_static);
137446f9 4910
b57ba6d2
MK
4911 if (bgp_static->label != MPLS_INVALID_LABEL)
4912 num_labels = 1;
d62a17ae 4913 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
4914 &bgp_static->prd);
137446f9 4915
d62a17ae 4916 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 4917
d62a17ae 4918 attr.nexthop = bgp_static->igpnexthop;
4919 attr.med = bgp_static->igpmetric;
4920 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 4921
d62a17ae 4922 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
4923 || (safi == SAFI_ENCAP)) {
4924 if (afi == AFI_IP) {
4925 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
4926 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
4927 }
4928 }
4929 if (afi == AFI_L2VPN) {
4930 if (bgp_static->gatewayIp.family == AF_INET)
4931 add.ipv4.s_addr =
4932 bgp_static->gatewayIp.u.prefix4.s_addr;
4933 else if (bgp_static->gatewayIp.family == AF_INET6)
4934 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
4935 sizeof(struct in6_addr));
4936 overlay_index_update(&attr, bgp_static->eth_s_id, &add);
4937 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
4938 struct bgp_encap_type_vxlan bet;
4939 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 4940 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 4941 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
4942 }
4943 if (bgp_static->router_mac) {
4944 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
4945 }
4946 }
4947 /* Apply route-map. */
4948 if (bgp_static->rmap.name) {
4949 struct attr attr_tmp = attr;
40381db7 4950 struct bgp_path_info rmap_path;
b68885f9 4951 route_map_result_t ret;
137446f9 4952
40381db7
DS
4953 rmap_path.peer = bgp->peer_self;
4954 rmap_path.attr = &attr_tmp;
137446f9 4955
d62a17ae 4956 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 4957
40381db7
DS
4958 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
4959 &rmap_path);
137446f9 4960
d62a17ae 4961 bgp->peer_self->rmap_type = 0;
137446f9 4962
d62a17ae 4963 if (ret == RMAP_DENYMATCH) {
4964 /* Free uninterned attribute. */
4965 bgp_attr_flush(&attr_tmp);
137446f9 4966
d62a17ae 4967 /* Unintern original. */
4968 aspath_unintern(&attr.aspath);
4969 bgp_static_withdraw_safi(bgp, p, afi, safi,
4970 &bgp_static->prd);
4971 return;
4972 }
137446f9 4973
d62a17ae 4974 attr_new = bgp_attr_intern(&attr_tmp);
4975 } else {
4976 attr_new = bgp_attr_intern(&attr);
4977 }
137446f9 4978
6f94b685 4979 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4980 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4981 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4982 break;
4983
40381db7 4984 if (pi) {
d62a17ae 4985 memset(&add, 0, sizeof(union gw_addr));
40381db7
DS
4986 if (attrhash_cmp(pi->attr, attr_new)
4987 && overlay_index_equal(afi, pi, bgp_static->eth_s_id, &add)
4988 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4989 bgp_unlock_node(rn);
4990 bgp_attr_unintern(&attr_new);
4991 aspath_unintern(&attr.aspath);
4992 return;
4993 } else {
4994 /* The attribute is changed. */
40381db7 4995 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4996
4997 /* Rewrite BGP route information. */
40381db7
DS
4998 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
4999 bgp_path_info_restore(rn, pi);
d62a17ae 5000 else
40381db7
DS
5001 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5002 bgp_attr_unintern(&pi->attr);
5003 pi->attr = attr_new;
5004 pi->uptime = bgp_clock();
65efcfce 5005#if ENABLE_BGP_VNC
40381db7
DS
5006 if (pi->extra)
5007 label = decode_label(&pi->extra->label[0]);
65efcfce 5008#endif
137446f9 5009
d62a17ae 5010 /* Process change. */
40381db7 5011 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 5012 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
5013
5014 if (SAFI_MPLS_VPN == safi
5015 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5016 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5017 }
65efcfce 5018#if ENABLE_BGP_VNC
40381db7
DS
5019 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5020 pi->attr, afi, safi, pi->type,
5021 pi->sub_type, &label);
65efcfce 5022#endif
d62a17ae 5023 bgp_unlock_node(rn);
5024 aspath_unintern(&attr.aspath);
5025 return;
5026 }
5027 }
137446f9
LB
5028
5029
d62a17ae 5030 /* Make new BGP info. */
5031 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
5032 attr_new, rn);
1defdda8 5033 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5034 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5035 if (num_labels) {
5036 new->extra->label[0] = bgp_static->label;
5037 new->extra->num_labels = num_labels;
5038 }
65efcfce 5039#if ENABLE_BGP_VNC
d62a17ae 5040 label = decode_label(&bgp_static->label);
65efcfce 5041#endif
137446f9 5042
d62a17ae 5043 /* Aggregate address increment. */
5044 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5045
d62a17ae 5046 /* Register new BGP information. */
18ee8310 5047 bgp_path_info_add(rn, new);
d62a17ae 5048 /* route_node_get lock */
5049 bgp_unlock_node(rn);
137446f9 5050
d62a17ae 5051 /* Process change. */
5052 bgp_process(bgp, rn, afi, safi);
137446f9 5053
ddb5b488
PZ
5054 if (SAFI_MPLS_VPN == safi
5055 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5056 vpn_leak_to_vrf_update(bgp, new);
5057 }
65efcfce 5058#if ENABLE_BGP_VNC
d62a17ae 5059 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5060 safi, new->type, new->sub_type, &label);
65efcfce
LB
5061#endif
5062
d62a17ae 5063 /* Unintern original. */
5064 aspath_unintern(&attr.aspath);
137446f9
LB
5065}
5066
718e3744 5067/* Configure static BGP network. When user don't run zebra, static
5068 route should be installed as valid. */
e2a86ad9
DS
5069static int bgp_static_set(struct vty *vty, const char *negate,
5070 const char *ip_str, afi_t afi, safi_t safi,
d7c0a89a 5071 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 5072{
5073 VTY_DECLVAR_CONTEXT(bgp, bgp);
5074 int ret;
5075 struct prefix p;
5076 struct bgp_static *bgp_static;
5077 struct bgp_node *rn;
d7c0a89a 5078 uint8_t need_update = 0;
d62a17ae 5079
5080 /* Convert IP prefix string to struct prefix. */
5081 ret = str2prefix(ip_str, &p);
5082 if (!ret) {
5083 vty_out(vty, "%% Malformed prefix\n");
5084 return CMD_WARNING_CONFIG_FAILED;
5085 }
5086 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5087 vty_out(vty, "%% Malformed prefix (link-local address)\n");
5088 return CMD_WARNING_CONFIG_FAILED;
5089 }
718e3744 5090
d62a17ae 5091 apply_mask(&p);
718e3744 5092
e2a86ad9 5093 if (negate) {
718e3744 5094
e2a86ad9
DS
5095 /* Set BGP static route configuration. */
5096 rn = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5097
e2a86ad9 5098 if (!rn) {
a4d82a8a 5099 vty_out(vty, "%% Can't find static route specified\n");
d62a17ae 5100 return CMD_WARNING_CONFIG_FAILED;
5101 }
5102
5a8ba9fc 5103 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 5104
e2a86ad9
DS
5105 if ((label_index != BGP_INVALID_LABEL_INDEX)
5106 && (label_index != bgp_static->label_index)) {
5107 vty_out(vty,
5108 "%% label-index doesn't match static route\n");
5109 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5110 }
d62a17ae 5111
e2a86ad9
DS
5112 if ((rmap && bgp_static->rmap.name)
5113 && strcmp(rmap, bgp_static->rmap.name)) {
5114 vty_out(vty,
5115 "%% route-map name doesn't match static route\n");
5116 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5117 }
718e3744 5118
e2a86ad9
DS
5119 /* Update BGP RIB. */
5120 if (!bgp_static->backdoor)
5121 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5122
e2a86ad9
DS
5123 /* Clear configuration. */
5124 bgp_static_free(bgp_static);
5a8ba9fc 5125 bgp_node_set_bgp_static_info(rn, NULL);
e2a86ad9
DS
5126 bgp_unlock_node(rn);
5127 bgp_unlock_node(rn);
5128 } else {
718e3744 5129
e2a86ad9
DS
5130 /* Set BGP static route configuration. */
5131 rn = bgp_node_get(bgp->route[afi][safi], &p);
718e3744 5132
5a8ba9fc 5133 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 5134 if (bgp_static) {
e2a86ad9 5135 /* Configuration change. */
e2a86ad9
DS
5136 /* Label index cannot be changed. */
5137 if (bgp_static->label_index != label_index) {
5138 vty_out(vty, "%% cannot change label-index\n");
5139 return CMD_WARNING_CONFIG_FAILED;
5140 }
d62a17ae 5141
e2a86ad9 5142 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5143 if (bgp_static->valid
5144 && bgp_static->backdoor != backdoor)
e2a86ad9 5145 need_update = 1;
718e3744 5146
e2a86ad9 5147 bgp_static->backdoor = backdoor;
718e3744 5148
e2a86ad9 5149 if (rmap) {
0a22ddfb
QY
5150 XFREE(MTYPE_ROUTE_MAP_NAME,
5151 bgp_static->rmap.name);
b4897fa5 5152 route_map_counter_decrement(
5153 bgp_static->rmap.map);
e2a86ad9
DS
5154 bgp_static->rmap.name =
5155 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5156 bgp_static->rmap.map =
5157 route_map_lookup_by_name(rmap);
b4897fa5 5158 route_map_counter_increment(
5159 bgp_static->rmap.map);
e2a86ad9 5160 } else {
0a22ddfb
QY
5161 XFREE(MTYPE_ROUTE_MAP_NAME,
5162 bgp_static->rmap.name);
b4897fa5 5163 route_map_counter_decrement(
5164 bgp_static->rmap.map);
e2a86ad9
DS
5165 bgp_static->rmap.name = NULL;
5166 bgp_static->rmap.map = NULL;
5167 bgp_static->valid = 0;
5168 }
5169 bgp_unlock_node(rn);
5170 } else {
5171 /* New configuration. */
5172 bgp_static = bgp_static_new();
5173 bgp_static->backdoor = backdoor;
5174 bgp_static->valid = 0;
5175 bgp_static->igpmetric = 0;
5176 bgp_static->igpnexthop.s_addr = 0;
5177 bgp_static->label_index = label_index;
718e3744 5178
e2a86ad9 5179 if (rmap) {
0a22ddfb
QY
5180 XFREE(MTYPE_ROUTE_MAP_NAME,
5181 bgp_static->rmap.name);
b4897fa5 5182 route_map_counter_decrement(
5183 bgp_static->rmap.map);
e2a86ad9
DS
5184 bgp_static->rmap.name =
5185 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5186 bgp_static->rmap.map =
5187 route_map_lookup_by_name(rmap);
b4897fa5 5188 route_map_counter_increment(
5189 bgp_static->rmap.map);
e2a86ad9 5190 }
5a8ba9fc 5191 bgp_node_set_bgp_static_info(rn, bgp_static);
e2a86ad9 5192 }
d62a17ae 5193
e2a86ad9
DS
5194 bgp_static->valid = 1;
5195 if (need_update)
5196 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5197
e2a86ad9
DS
5198 if (!bgp_static->backdoor)
5199 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5200 }
d62a17ae 5201
5202 return CMD_SUCCESS;
5203}
5204
5205void bgp_static_add(struct bgp *bgp)
5206{
5207 afi_t afi;
5208 safi_t safi;
5209 struct bgp_node *rn;
5210 struct bgp_node *rm;
5211 struct bgp_table *table;
5212 struct bgp_static *bgp_static;
5213
05c7a1cc
QY
5214 FOREACH_AFI_SAFI (afi, safi)
5215 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5216 rn = bgp_route_next(rn)) {
67009e22 5217 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5218 continue;
ea47320b 5219
05c7a1cc
QY
5220 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5221 || (safi == SAFI_EVPN)) {
67009e22 5222 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5223
5224 for (rm = bgp_table_top(table); rm;
5225 rm = bgp_route_next(rm)) {
a78beeb5 5226 bgp_static =
5a8ba9fc
DS
5227 bgp_node_get_bgp_static_info(
5228 rm);
05c7a1cc
QY
5229 bgp_static_update_safi(bgp, &rm->p,
5230 bgp_static, afi,
5231 safi);
d62a17ae 5232 }
05c7a1cc 5233 } else {
5a8ba9fc
DS
5234 bgp_static_update(
5235 bgp, &rn->p,
5236 bgp_node_get_bgp_static_info(rn), afi,
5237 safi);
ea47320b 5238 }
05c7a1cc 5239 }
6aeb9e78
DS
5240}
5241
718e3744 5242/* Called from bgp_delete(). Delete all static routes from the BGP
5243 instance. */
d62a17ae 5244void bgp_static_delete(struct bgp *bgp)
5245{
5246 afi_t afi;
5247 safi_t safi;
5248 struct bgp_node *rn;
5249 struct bgp_node *rm;
5250 struct bgp_table *table;
5251 struct bgp_static *bgp_static;
5252
05c7a1cc
QY
5253 FOREACH_AFI_SAFI (afi, safi)
5254 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5255 rn = bgp_route_next(rn)) {
67009e22 5256 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5257 continue;
ea47320b 5258
05c7a1cc
QY
5259 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5260 || (safi == SAFI_EVPN)) {
67009e22 5261 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5262
5263 for (rm = bgp_table_top(table); rm;
5264 rm = bgp_route_next(rm)) {
a78beeb5 5265 bgp_static =
5a8ba9fc
DS
5266 bgp_node_get_bgp_static_info(
5267 rm);
c7d14ba6
PG
5268 if (!bgp_static)
5269 continue;
5270
05c7a1cc
QY
5271 bgp_static_withdraw_safi(
5272 bgp, &rm->p, AFI_IP, safi,
5273 (struct prefix_rd *)&rn->p);
ea47320b 5274 bgp_static_free(bgp_static);
5a8ba9fc 5275 bgp_node_set_bgp_static_info(rn, NULL);
ea47320b 5276 bgp_unlock_node(rn);
d62a17ae 5277 }
05c7a1cc 5278 } else {
5a8ba9fc 5279 bgp_static = bgp_node_get_bgp_static_info(rn);
05c7a1cc
QY
5280 bgp_static_withdraw(bgp, &rn->p, afi, safi);
5281 bgp_static_free(bgp_static);
5a8ba9fc 5282 bgp_node_set_bgp_static_info(rn, NULL);
05c7a1cc 5283 bgp_unlock_node(rn);
ea47320b 5284 }
05c7a1cc 5285 }
d62a17ae 5286}
5287
5288void bgp_static_redo_import_check(struct bgp *bgp)
5289{
5290 afi_t afi;
5291 safi_t safi;
5292 struct bgp_node *rn;
5293 struct bgp_node *rm;
5294 struct bgp_table *table;
5295 struct bgp_static *bgp_static;
5296
5297 /* Use this flag to force reprocessing of the route */
5298 bgp_flag_set(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc
QY
5299 FOREACH_AFI_SAFI (afi, safi) {
5300 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5301 rn = bgp_route_next(rn)) {
67009e22 5302 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5303 continue;
ea47320b 5304
05c7a1cc
QY
5305 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5306 || (safi == SAFI_EVPN)) {
67009e22 5307 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5308
5309 for (rm = bgp_table_top(table); rm;
5310 rm = bgp_route_next(rm)) {
a78beeb5 5311 bgp_static =
5a8ba9fc
DS
5312 bgp_node_get_bgp_static_info(
5313 rm);
05c7a1cc
QY
5314 bgp_static_update_safi(bgp, &rm->p,
5315 bgp_static, afi,
5316 safi);
d62a17ae 5317 }
05c7a1cc 5318 } else {
5a8ba9fc 5319 bgp_static = bgp_node_get_bgp_static_info(rn);
05c7a1cc
QY
5320 bgp_static_update(bgp, &rn->p, bgp_static, afi,
5321 safi);
ea47320b 5322 }
05c7a1cc
QY
5323 }
5324 }
d62a17ae 5325 bgp_flag_unset(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
5326}
5327
5328static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
5329 safi_t safi)
5330{
5331 struct bgp_table *table;
5332 struct bgp_node *rn;
40381db7 5333 struct bgp_path_info *pi;
d62a17ae 5334
dfb6fd1d
NT
5335 /* Do not install the aggregate route if BGP is in the
5336 * process of termination.
5337 */
5338 if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS) ||
5339 (bgp->peer_self == NULL))
5340 return;
5341
d62a17ae 5342 table = bgp->rib[afi][safi];
5343 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685 5344 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7
DS
5345 if (pi->peer == bgp->peer_self
5346 && ((pi->type == ZEBRA_ROUTE_BGP
5347 && pi->sub_type == BGP_ROUTE_STATIC)
5348 || (pi->type != ZEBRA_ROUTE_BGP
5349 && pi->sub_type
d62a17ae 5350 == BGP_ROUTE_REDISTRIBUTE))) {
40381db7 5351 bgp_aggregate_decrement(bgp, &rn->p, pi, afi,
d62a17ae 5352 safi);
40381db7
DS
5353 bgp_unlink_nexthop(pi);
5354 bgp_path_info_delete(rn, pi);
d62a17ae 5355 bgp_process(bgp, rn, afi, safi);
5356 }
5357 }
5358 }
ad4cbda1 5359}
5360
5361/*
5362 * Purge all networks and redistributed routes from routing table.
5363 * Invoked upon the instance going down.
5364 */
d62a17ae 5365void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 5366{
d62a17ae 5367 afi_t afi;
5368 safi_t safi;
ad4cbda1 5369
05c7a1cc
QY
5370 FOREACH_AFI_SAFI (afi, safi)
5371 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 5372}
5373
137446f9
LB
5374/*
5375 * gpz 110624
5376 * Currently this is used to set static routes for VPN and ENCAP.
5377 * I think it can probably be factored with bgp_static_set.
5378 */
d62a17ae 5379int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
5380 const char *ip_str, const char *rd_str,
5381 const char *label_str, const char *rmap_str,
5382 int evpn_type, const char *esi, const char *gwip,
5383 const char *ethtag, const char *routermac)
5384{
5385 VTY_DECLVAR_CONTEXT(bgp, bgp);
5386 int ret;
5387 struct prefix p;
5388 struct prefix_rd prd;
5389 struct bgp_node *prn;
5390 struct bgp_node *rn;
5391 struct bgp_table *table;
5392 struct bgp_static *bgp_static;
5393 mpls_label_t label = MPLS_INVALID_LABEL;
5394 struct prefix gw_ip;
5395
5396 /* validate ip prefix */
5397 ret = str2prefix(ip_str, &p);
5398 if (!ret) {
5399 vty_out(vty, "%% Malformed prefix\n");
5400 return CMD_WARNING_CONFIG_FAILED;
5401 }
5402 apply_mask(&p);
5403 if ((afi == AFI_L2VPN)
5404 && (bgp_build_evpn_prefix(evpn_type,
5405 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5406 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5407 return CMD_WARNING_CONFIG_FAILED;
5408 }
718e3744 5409
d62a17ae 5410 ret = str2prefix_rd(rd_str, &prd);
5411 if (!ret) {
5412 vty_out(vty, "%% Malformed rd\n");
5413 return CMD_WARNING_CONFIG_FAILED;
5414 }
718e3744 5415
d62a17ae 5416 if (label_str) {
5417 unsigned long label_val;
5418 label_val = strtoul(label_str, NULL, 10);
5419 encode_label(label_val, &label);
5420 }
9bedbb1e 5421
d62a17ae 5422 if (safi == SAFI_EVPN) {
5423 if (esi && str2esi(esi, NULL) == 0) {
5424 vty_out(vty, "%% Malformed ESI\n");
5425 return CMD_WARNING_CONFIG_FAILED;
5426 }
5427 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
5428 vty_out(vty, "%% Malformed Router MAC\n");
5429 return CMD_WARNING_CONFIG_FAILED;
5430 }
5431 if (gwip) {
5432 memset(&gw_ip, 0, sizeof(struct prefix));
5433 ret = str2prefix(gwip, &gw_ip);
5434 if (!ret) {
5435 vty_out(vty, "%% Malformed GatewayIp\n");
5436 return CMD_WARNING_CONFIG_FAILED;
5437 }
5438 if ((gw_ip.family == AF_INET
3714a385 5439 && is_evpn_prefix_ipaddr_v6(
d62a17ae 5440 (struct prefix_evpn *)&p))
5441 || (gw_ip.family == AF_INET6
3714a385 5442 && is_evpn_prefix_ipaddr_v4(
d62a17ae 5443 (struct prefix_evpn *)&p))) {
5444 vty_out(vty,
5445 "%% GatewayIp family differs with IP prefix\n");
5446 return CMD_WARNING_CONFIG_FAILED;
5447 }
5448 }
5449 }
5450 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
67009e22
DS
5451 if (!bgp_node_has_bgp_path_info_data(prn))
5452 bgp_node_set_bgp_table_info(prn,
5453 bgp_table_init(bgp, afi, safi));
67009e22 5454 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 5455
5456 rn = bgp_node_get(table, &p);
5457
67009e22 5458 if (bgp_node_has_bgp_path_info_data(rn)) {
d62a17ae 5459 vty_out(vty, "%% Same network configuration exists\n");
5460 bgp_unlock_node(rn);
5461 } else {
5462 /* New configuration. */
5463 bgp_static = bgp_static_new();
5464 bgp_static->backdoor = 0;
5465 bgp_static->valid = 0;
5466 bgp_static->igpmetric = 0;
5467 bgp_static->igpnexthop.s_addr = 0;
5468 bgp_static->label = label;
5469 bgp_static->prd = prd;
5470
5471 if (rmap_str) {
0a22ddfb 5472 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5473 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 5474 bgp_static->rmap.name =
5475 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
5476 bgp_static->rmap.map =
5477 route_map_lookup_by_name(rmap_str);
b4897fa5 5478 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 5479 }
718e3744 5480
d62a17ae 5481 if (safi == SAFI_EVPN) {
5482 if (esi) {
5483 bgp_static->eth_s_id =
5484 XCALLOC(MTYPE_ATTR,
5485 sizeof(struct eth_segment_id));
5486 str2esi(esi, bgp_static->eth_s_id);
5487 }
5488 if (routermac) {
5489 bgp_static->router_mac =
28328ea9 5490 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
5491 (void)prefix_str2mac(routermac,
5492 bgp_static->router_mac);
d62a17ae 5493 }
5494 if (gwip)
5495 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
5496 }
5a8ba9fc 5497 bgp_node_set_bgp_static_info(rn, bgp_static);
718e3744 5498
d62a17ae 5499 bgp_static->valid = 1;
5500 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
5501 }
718e3744 5502
d62a17ae 5503 return CMD_SUCCESS;
718e3744 5504}
5505
5506/* Configure static BGP network. */
d62a17ae 5507int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
5508 const char *ip_str, const char *rd_str,
5509 const char *label_str, int evpn_type, const char *esi,
5510 const char *gwip, const char *ethtag)
5511{
5512 VTY_DECLVAR_CONTEXT(bgp, bgp);
5513 int ret;
5514 struct prefix p;
5515 struct prefix_rd prd;
5516 struct bgp_node *prn;
5517 struct bgp_node *rn;
5518 struct bgp_table *table;
5519 struct bgp_static *bgp_static;
5520 mpls_label_t label = MPLS_INVALID_LABEL;
5521
5522 /* Convert IP prefix string to struct prefix. */
5523 ret = str2prefix(ip_str, &p);
5524 if (!ret) {
5525 vty_out(vty, "%% Malformed prefix\n");
5526 return CMD_WARNING_CONFIG_FAILED;
5527 }
5528 apply_mask(&p);
5529 if ((afi == AFI_L2VPN)
5530 && (bgp_build_evpn_prefix(evpn_type,
5531 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5532 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5533 return CMD_WARNING_CONFIG_FAILED;
5534 }
5535 ret = str2prefix_rd(rd_str, &prd);
5536 if (!ret) {
5537 vty_out(vty, "%% Malformed rd\n");
5538 return CMD_WARNING_CONFIG_FAILED;
5539 }
718e3744 5540
d62a17ae 5541 if (label_str) {
5542 unsigned long label_val;
5543 label_val = strtoul(label_str, NULL, 10);
5544 encode_label(label_val, &label);
5545 }
718e3744 5546
d62a17ae 5547 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
67009e22
DS
5548 if (!bgp_node_has_bgp_path_info_data(prn))
5549 bgp_node_set_bgp_table_info(prn,
5550 bgp_table_init(bgp, afi, safi));
d62a17ae 5551 else
5552 bgp_unlock_node(prn);
67009e22 5553 table = bgp_node_get_bgp_table_info(prn);
718e3744 5554
d62a17ae 5555 rn = bgp_node_lookup(table, &p);
6b0655a2 5556
d62a17ae 5557 if (rn) {
5558 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 5559
5a8ba9fc 5560 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 5561 bgp_static_free(bgp_static);
5a8ba9fc 5562 bgp_node_set_bgp_static_info(rn, NULL);
d62a17ae 5563 bgp_unlock_node(rn);
5564 bgp_unlock_node(rn);
5565 } else
5566 vty_out(vty, "%% Can't find the route\n");
5567
5568 return CMD_SUCCESS;
5569}
5570
5571static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
5572 const char *rmap_name)
5573{
5574 VTY_DECLVAR_CONTEXT(bgp, bgp);
5575 struct bgp_rmap *rmap;
5576
5577 rmap = &bgp->table_map[afi][safi];
5578 if (rmap_name) {
0a22ddfb 5579 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5580 route_map_counter_decrement(rmap->map);
d62a17ae 5581 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
5582 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 5583 route_map_counter_increment(rmap->map);
d62a17ae 5584 } else {
0a22ddfb 5585 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5586 route_map_counter_decrement(rmap->map);
d62a17ae 5587 rmap->name = NULL;
5588 rmap->map = NULL;
5589 }
73ac8160 5590
d62a17ae 5591 if (bgp_fibupd_safi(safi))
5592 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5593
d62a17ae 5594 return CMD_SUCCESS;
73ac8160
DS
5595}
5596
d62a17ae 5597static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
5598 const char *rmap_name)
73ac8160 5599{
d62a17ae 5600 VTY_DECLVAR_CONTEXT(bgp, bgp);
5601 struct bgp_rmap *rmap;
73ac8160 5602
d62a17ae 5603 rmap = &bgp->table_map[afi][safi];
0a22ddfb 5604 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5605 route_map_counter_decrement(rmap->map);
d62a17ae 5606 rmap->name = NULL;
5607 rmap->map = NULL;
73ac8160 5608
d62a17ae 5609 if (bgp_fibupd_safi(safi))
5610 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5611
d62a17ae 5612 return CMD_SUCCESS;
73ac8160
DS
5613}
5614
2b791107 5615void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 5616 safi_t safi)
73ac8160 5617{
d62a17ae 5618 if (bgp->table_map[afi][safi].name) {
d62a17ae 5619 vty_out(vty, " table-map %s\n",
5620 bgp->table_map[afi][safi].name);
5621 }
73ac8160
DS
5622}
5623
73ac8160
DS
5624DEFUN (bgp_table_map,
5625 bgp_table_map_cmd,
5626 "table-map WORD",
5627 "BGP table to RIB route download filter\n"
5628 "Name of the route map\n")
5629{
d62a17ae 5630 int idx_word = 1;
5631 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5632 argv[idx_word]->arg);
73ac8160
DS
5633}
5634DEFUN (no_bgp_table_map,
5635 no_bgp_table_map_cmd,
5636 "no table-map WORD",
3a2d747c 5637 NO_STR
73ac8160
DS
5638 "BGP table to RIB route download filter\n"
5639 "Name of the route map\n")
5640{
d62a17ae 5641 int idx_word = 2;
5642 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5643 argv[idx_word]->arg);
73ac8160
DS
5644}
5645
e2a86ad9
DS
5646DEFPY(bgp_network,
5647 bgp_network_cmd,
5648 "[no] network \
5649 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5650 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5651 backdoor$backdoor}]",
5652 NO_STR
5653 "Specify a network to announce via BGP\n"
5654 "IPv4 prefix\n"
5655 "Network number\n"
5656 "Network mask\n"
5657 "Network mask\n"
5658 "Route-map to modify the attributes\n"
5659 "Name of the route map\n"
5660 "Label index to associate with the prefix\n"
5661 "Label index value\n"
5662 "Specify a BGP backdoor route\n")
5663{
5664 char addr_prefix_str[BUFSIZ];
5665
5666 if (address_str) {
5667 int ret;
718e3744 5668
e2a86ad9
DS
5669 ret = netmask_str2prefix_str(address_str, netmask_str,
5670 addr_prefix_str);
5671 if (!ret) {
5672 vty_out(vty, "%% Inconsistent address and mask\n");
5673 return CMD_WARNING_CONFIG_FAILED;
5674 }
d62a17ae 5675 }
718e3744 5676
a4d82a8a
PZ
5677 return bgp_static_set(
5678 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
5679 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
5680 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 5681}
5682
e2a86ad9
DS
5683DEFPY(ipv6_bgp_network,
5684 ipv6_bgp_network_cmd,
5685 "[no] network X:X::X:X/M$prefix \
5686 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5687 NO_STR
5688 "Specify a network to announce via BGP\n"
5689 "IPv6 prefix\n"
5690 "Route-map to modify the attributes\n"
5691 "Name of the route map\n"
5692 "Label index to associate with the prefix\n"
5693 "Label index value\n")
718e3744 5694{
a4d82a8a
PZ
5695 return bgp_static_set(
5696 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
5697 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
5698}
5699
d62a17ae 5700static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 5701{
d62a17ae 5702 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 5703}
5704
d62a17ae 5705static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 5706{
20894f50
DA
5707 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
5708 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 5709 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
5710}
718e3744 5711
40381db7 5712static int bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
29f7d023 5713 struct aspath *aspath,
3da2cc32 5714 struct community *comm,
dd18c5a9
DS
5715 struct ecommunity *ecomm,
5716 struct lcommunity *lcomm)
eaaf8adb
DS
5717{
5718 static struct aspath *ae = NULL;
5719
5720 if (!ae)
5721 ae = aspath_empty();
5722
40381db7 5723 if (!pi)
eaaf8adb
DS
5724 return 0;
5725
40381db7 5726 if (origin != pi->attr->origin)
eaaf8adb
DS
5727 return 0;
5728
40381db7 5729 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
29f7d023
DS
5730 return 0;
5731
40381db7 5732 if (!community_cmp(pi->attr->community, comm))
eaaf8adb
DS
5733 return 0;
5734
3da2cc32 5735 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
eaaf8adb
DS
5736 return 0;
5737
dd18c5a9
DS
5738 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
5739 return 0;
5740
40381db7 5741 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
7ce8a8e0
DS
5742 return 0;
5743
eaaf8adb
DS
5744 return 1;
5745}
5746
c701010e
DS
5747static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi,
5748 struct prefix *p, uint8_t origin,
5749 struct aspath *aspath,
5750 struct community *community,
3da2cc32 5751 struct ecommunity *ecommunity,
dd18c5a9 5752 struct lcommunity *lcommunity,
c701010e
DS
5753 uint8_t atomic_aggregate,
5754 struct bgp_aggregate *aggregate)
5755{
5756 struct bgp_node *rn;
5757 struct bgp_table *table;
6f94b685 5758 struct bgp_path_info *pi, *orig, *new;
20894f50 5759 struct attr *attr;
c701010e
DS
5760
5761 table = bgp->rib[afi][safi];
5762
5763 rn = bgp_node_get(table, p);
eaaf8adb 5764
6f94b685 5765 for (orig = pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
5766 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5767 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
5768 break;
5769
c701010e 5770 if (aggregate->count > 0) {
eaaf8adb
DS
5771 /*
5772 * If the aggregate information has not changed
5773 * no need to re-install it again.
5774 */
6f94b685 5775 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 5776 ecommunity, lcommunity)) {
eaaf8adb
DS
5777 bgp_unlock_node(rn);
5778
5779 if (aspath)
5780 aspath_free(aspath);
5781 if (community)
3c1f53de 5782 community_free(&community);
3da2cc32
DS
5783 if (ecommunity)
5784 ecommunity_free(&ecommunity);
dd18c5a9
DS
5785 if (lcommunity)
5786 lcommunity_free(&lcommunity);
eaaf8adb
DS
5787
5788 return;
5789 }
5790
5791 /*
5792 * Mark the old as unusable
5793 */
40381db7
DS
5794 if (pi)
5795 bgp_path_info_delete(rn, pi);
eaaf8adb 5796
20894f50
DA
5797 attr = bgp_attr_aggregate_intern(
5798 bgp, origin, aspath, community, ecommunity, lcommunity,
5799 aggregate, atomic_aggregate, p);
5800
5801 if (!attr) {
5802 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
5803 return;
5804 }
5805
3da2cc32 5806 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
20894f50
DA
5807 bgp->peer_self, attr, rn);
5808
1defdda8 5809 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 5810
18ee8310 5811 bgp_path_info_add(rn, new);
c701010e
DS
5812 bgp_process(bgp, rn, afi, safi);
5813 } else {
6f94b685 5814 for (pi = orig; pi; pi = pi->next)
40381db7
DS
5815 if (pi->peer == bgp->peer_self
5816 && pi->type == ZEBRA_ROUTE_BGP
5817 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
5818 break;
5819
5820 /* Withdraw static BGP route from routing table. */
40381db7
DS
5821 if (pi) {
5822 bgp_path_info_delete(rn, pi);
c701010e
DS
5823 bgp_process(bgp, rn, afi, safi);
5824 }
5825 }
5826
5827 bgp_unlock_node(rn);
5828}
5829
b5d58c32 5830/* Update an aggregate as routes are added/removed from the BGP table */
20894f50 5831void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
fc968841 5832 afi_t afi, safi_t safi,
d62a17ae 5833 struct bgp_aggregate *aggregate)
5834{
5835 struct bgp_table *table;
5836 struct bgp_node *top;
5837 struct bgp_node *rn;
d7c0a89a 5838 uint8_t origin;
d62a17ae 5839 struct aspath *aspath = NULL;
d62a17ae 5840 struct community *community = NULL;
3da2cc32 5841 struct ecommunity *ecommunity = NULL;
dd18c5a9 5842 struct lcommunity *lcommunity = NULL;
40381db7 5843 struct bgp_path_info *pi;
d62a17ae 5844 unsigned long match = 0;
d7c0a89a 5845 uint8_t atomic_aggregate = 0;
d62a17ae 5846
9f822fa2
S
5847 /* If the bgp instance is being deleted or self peer is deleted
5848 * then do not create aggregate route
5849 */
5850 if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS) ||
5851 (bgp->peer_self == NULL))
5852 return;
5853
d62a17ae 5854 /* ORIGIN attribute: If at least one route among routes that are
5855 aggregated has ORIGIN with the value INCOMPLETE, then the
5856 aggregated route must have the ORIGIN attribute with the value
5857 INCOMPLETE. Otherwise, if at least one route among routes that
5858 are aggregated has ORIGIN with the value EGP, then the aggregated
5859 route must have the origin attribute with the value EGP. In all
5860 other case the value of the ORIGIN attribute of the aggregated
5861 route is INTERNAL. */
5862 origin = BGP_ORIGIN_IGP;
718e3744 5863
d62a17ae 5864 table = bgp->rib[afi][safi];
718e3744 5865
d62a17ae 5866 top = bgp_node_get(table, p);
5867 for (rn = bgp_node_get(table, p); rn;
c2ff8b3e
DS
5868 rn = bgp_route_next_until(rn, top)) {
5869 if (rn->p.prefixlen <= p->prefixlen)
5870 continue;
d62a17ae 5871
c2ff8b3e 5872 match = 0;
d62a17ae 5873
6f94b685 5874 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 5875 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 5876 continue;
718e3744 5877
40381db7 5878 if (pi->attr->flag
c2ff8b3e
DS
5879 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
5880 atomic_aggregate = 1;
d62a17ae 5881
40381db7 5882 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 5883 continue;
d62a17ae 5884
f273fef1
DS
5885 /*
5886 * summary-only aggregate route suppress
5887 * aggregated route announcements.
5888 */
c2ff8b3e 5889 if (aggregate->summary_only) {
40381db7
DS
5890 (bgp_path_info_extra_get(pi))->suppress++;
5891 bgp_path_info_set_flag(rn, pi,
18ee8310 5892 BGP_PATH_ATTR_CHANGED);
c2ff8b3e 5893 match++;
d62a17ae 5894 }
c2ff8b3e
DS
5895
5896 aggregate->count++;
5897
f273fef1
DS
5898 /*
5899 * If at least one route among routes that are
5900 * aggregated has ORIGIN with the value INCOMPLETE,
5901 * then the aggregated route MUST have the ORIGIN
5902 * attribute with the value INCOMPLETE. Otherwise, if
5903 * at least one route among routes that are aggregated
5904 * has ORIGIN with the value EGP, then the aggregated
5905 * route MUST have the ORIGIN attribute with the value
5906 * EGP.
5907 */
fc968841
NT
5908 switch (pi->attr->origin) {
5909 case BGP_ORIGIN_INCOMPLETE:
5910 aggregate->incomplete_origin_count++;
5911 break;
5912 case BGP_ORIGIN_EGP:
5913 aggregate->egp_origin_count++;
5914 break;
5915 default:
5916 /*Do nothing.
5917 */
5918 break;
5919 }
c2ff8b3e
DS
5920
5921 if (!aggregate->as_set)
5922 continue;
5923
f273fef1
DS
5924 /*
5925 * as-set aggregate route generate origin, as path,
5926 * and community aggregation.
5927 */
fc968841
NT
5928 /* Compute aggregate route's as-path.
5929 */
ef51a7d8 5930 bgp_compute_aggregate_aspath_hash(aggregate,
5931 pi->attr->aspath);
c2ff8b3e 5932
fc968841
NT
5933 /* Compute aggregate route's community.
5934 */
5935 if (pi->attr->community)
21fec674 5936 bgp_compute_aggregate_community_hash(
fc968841
NT
5937 aggregate,
5938 pi->attr->community);
dd18c5a9 5939
fc968841
NT
5940 /* Compute aggregate route's extended community.
5941 */
5942 if (pi->attr->ecommunity)
4edd83f9 5943 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
5944 aggregate,
5945 pi->attr->ecommunity);
5946
5947 /* Compute aggregate route's large community.
5948 */
5949 if (pi->attr->lcommunity)
f1eb1f05 5950 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
5951 aggregate,
5952 pi->attr->lcommunity);
d62a17ae 5953 }
c2ff8b3e
DS
5954 if (match)
5955 bgp_process(bgp, rn, afi, safi);
5956 }
21fec674 5957 if (aggregate->as_set) {
ef51a7d8 5958 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 5959 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 5960 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 5961 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 5962 }
5963
f1eb1f05 5964
d62a17ae 5965 bgp_unlock_node(top);
718e3744 5966
718e3744 5967
fc968841
NT
5968 if (aggregate->incomplete_origin_count > 0)
5969 origin = BGP_ORIGIN_INCOMPLETE;
5970 else if (aggregate->egp_origin_count > 0)
5971 origin = BGP_ORIGIN_EGP;
d62a17ae 5972
fc968841
NT
5973 if (aggregate->as_set) {
5974 if (aggregate->aspath)
5975 /* Retrieve aggregate route's as-path.
5976 */
5977 aspath = aspath_dup(aggregate->aspath);
d62a17ae 5978
fc968841
NT
5979 if (aggregate->community)
5980 /* Retrieve aggregate route's community.
5981 */
5982 community = community_dup(aggregate->community);
3da2cc32 5983
fc968841
NT
5984 if (aggregate->ecommunity)
5985 /* Retrieve aggregate route's ecommunity.
5986 */
5987 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 5988
fc968841
NT
5989 if (aggregate->lcommunity)
5990 /* Retrieve aggregate route's lcommunity.
5991 */
5992 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 5993 }
718e3744 5994
c701010e 5995 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
5996 ecommunity, lcommunity, atomic_aggregate,
5997 aggregate);
718e3744 5998}
5999
20894f50 6000void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
3b7db173
DS
6001 safi_t safi, struct bgp_aggregate *aggregate)
6002{
6003 struct bgp_table *table;
6004 struct bgp_node *top;
6005 struct bgp_node *rn;
40381db7 6006 struct bgp_path_info *pi;
3b7db173
DS
6007 unsigned long match;
6008
6009 table = bgp->rib[afi][safi];
6010
6011 /* If routes exists below this node, generate aggregate routes. */
6012 top = bgp_node_get(table, p);
6013 for (rn = bgp_node_get(table, p); rn;
6014 rn = bgp_route_next_until(rn, top)) {
6015 if (rn->p.prefixlen <= p->prefixlen)
6016 continue;
6017 match = 0;
6018
6f94b685 6019 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 6020 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
6021 continue;
6022
40381db7 6023 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
6024 continue;
6025
40381db7
DS
6026 if (aggregate->summary_only && pi->extra) {
6027 pi->extra->suppress--;
3b7db173 6028
40381db7 6029 if (pi->extra->suppress == 0) {
18ee8310 6030 bgp_path_info_set_flag(
40381db7 6031 rn, pi, BGP_PATH_ATTR_CHANGED);
3b7db173
DS
6032 match++;
6033 }
6034 }
6035 aggregate->count--;
fc968841
NT
6036
6037 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6038 aggregate->incomplete_origin_count--;
6039 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6040 aggregate->egp_origin_count--;
6041
6042 if (aggregate->as_set) {
6043 /* Remove as-path from aggregate.
6044 */
ef51a7d8 6045 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
6046 aggregate,
6047 pi->attr->aspath);
6048
6049 if (pi->attr->community)
6050 /* Remove community from aggregate.
6051 */
21fec674 6052 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
6053 aggregate,
6054 pi->attr->community);
6055
6056 if (pi->attr->ecommunity)
6057 /* Remove ecommunity from aggregate.
6058 */
4edd83f9 6059 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
6060 aggregate,
6061 pi->attr->ecommunity);
6062
6063 if (pi->attr->lcommunity)
6064 /* Remove lcommunity from aggregate.
6065 */
f1eb1f05 6066 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
6067 aggregate,
6068 pi->attr->lcommunity);
6069 }
6070
3b7db173
DS
6071 }
6072
6073 /* If this node was suppressed, process the change. */
6074 if (match)
6075 bgp_process(bgp, rn, afi, safi);
6076 }
f1eb1f05 6077 if (aggregate->as_set) {
ef51a7d8 6078 aspath_free(aggregate->aspath);
6079 aggregate->aspath = NULL;
21fec674 6080 if (aggregate->community)
6081 community_free(&aggregate->community);
4edd83f9 6082 if (aggregate->ecommunity)
6083 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 6084 if (aggregate->lcommunity)
6085 lcommunity_free(&aggregate->lcommunity);
6086 }
6087
3b7db173
DS
6088 bgp_unlock_node(top);
6089}
718e3744 6090
fc968841
NT
6091static void bgp_add_route_to_aggregate(struct bgp *bgp, struct prefix *aggr_p,
6092 struct bgp_path_info *pinew, afi_t afi,
6093 safi_t safi,
6094 struct bgp_aggregate *aggregate)
6095{
6096 uint8_t origin;
6097 struct aspath *aspath = NULL;
6098 uint8_t atomic_aggregate = 0;
6099 struct community *community = NULL;
6100 struct ecommunity *ecommunity = NULL;
6101 struct lcommunity *lcommunity = NULL;
6102
6103 /* ORIGIN attribute: If at least one route among routes that are
6104 * aggregated has ORIGIN with the value INCOMPLETE, then the
6105 * aggregated route must have the ORIGIN attribute with the value
6106 * INCOMPLETE. Otherwise, if at least one route among routes that
6107 * are aggregated has ORIGIN with the value EGP, then the aggregated
6108 * route must have the origin attribute with the value EGP. In all
6109 * other case the value of the ORIGIN attribute of the aggregated
6110 * route is INTERNAL.
6111 */
6112 origin = BGP_ORIGIN_IGP;
6113
6114 aggregate->count++;
6115
6116 if (aggregate->summary_only)
6117 (bgp_path_info_extra_get(pinew))->suppress++;
6118
6119 switch (pinew->attr->origin) {
6120 case BGP_ORIGIN_INCOMPLETE:
6121 aggregate->incomplete_origin_count++;
6122 break;
6123 case BGP_ORIGIN_EGP:
6124 aggregate->egp_origin_count++;
6125 break;
6126 default:
6127 /* Do nothing.
6128 */
6129 break;
6130 }
6131
6132 if (aggregate->incomplete_origin_count > 0)
6133 origin = BGP_ORIGIN_INCOMPLETE;
6134 else if (aggregate->egp_origin_count > 0)
6135 origin = BGP_ORIGIN_EGP;
6136
6137 if (aggregate->as_set) {
6138 /* Compute aggregate route's as-path.
6139 */
6140 bgp_compute_aggregate_aspath(aggregate,
6141 pinew->attr->aspath);
6142
6143 /* Compute aggregate route's community.
6144 */
6145 if (pinew->attr->community)
6146 bgp_compute_aggregate_community(
6147 aggregate,
6148 pinew->attr->community);
6149
6150 /* Compute aggregate route's extended community.
6151 */
6152 if (pinew->attr->ecommunity)
6153 bgp_compute_aggregate_ecommunity(
6154 aggregate,
6155 pinew->attr->ecommunity);
6156
6157 /* Compute aggregate route's large community.
6158 */
6159 if (pinew->attr->lcommunity)
6160 bgp_compute_aggregate_lcommunity(
6161 aggregate,
6162 pinew->attr->lcommunity);
6163
6164 /* Retrieve aggregate route's as-path.
6165 */
6166 if (aggregate->aspath)
6167 aspath = aspath_dup(aggregate->aspath);
6168
6169 /* Retrieve aggregate route's community.
6170 */
6171 if (aggregate->community)
6172 community = community_dup(aggregate->community);
6173
6174 /* Retrieve aggregate route's ecommunity.
6175 */
6176 if (aggregate->ecommunity)
6177 ecommunity = ecommunity_dup(aggregate->ecommunity);
6178
6179 /* Retrieve aggregate route's lcommunity.
6180 */
6181 if (aggregate->lcommunity)
6182 lcommunity = lcommunity_dup(aggregate->lcommunity);
6183 }
6184
6185 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6186 aspath, community, ecommunity,
6187 lcommunity, atomic_aggregate, aggregate);
6188}
6189
6190static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
6191 safi_t safi,
6192 struct bgp_path_info *pi,
6193 struct bgp_aggregate *aggregate,
6194 struct prefix *aggr_p)
6195{
6196 uint8_t origin;
6197 struct aspath *aspath = NULL;
6198 uint8_t atomic_aggregate = 0;
6199 struct community *community = NULL;
6200 struct ecommunity *ecommunity = NULL;
6201 struct lcommunity *lcommunity = NULL;
6202 unsigned long match = 0;
6203
6204 if (BGP_PATH_HOLDDOWN(pi))
6205 return;
6206
6207 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6208 return;
6209
6210 if (aggregate->summary_only
6211 && pi->extra
6212 && pi->extra->suppress > 0) {
6213 pi->extra->suppress--;
6214
6215 if (pi->extra->suppress == 0) {
6216 bgp_path_info_set_flag(pi->net, pi,
6217 BGP_PATH_ATTR_CHANGED);
6218 match++;
6219 }
6220 }
6221
6222 if (aggregate->count > 0)
6223 aggregate->count--;
6224
6225 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6226 aggregate->incomplete_origin_count--;
6227 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6228 aggregate->egp_origin_count--;
6229
6230 if (aggregate->as_set) {
6231 /* Remove as-path from aggregate.
6232 */
6233 bgp_remove_aspath_from_aggregate(aggregate,
6234 pi->attr->aspath);
6235
6236 if (pi->attr->community)
6237 /* Remove community from aggregate.
6238 */
6239 bgp_remove_community_from_aggregate(
6240 aggregate,
6241 pi->attr->community);
6242
6243 if (pi->attr->ecommunity)
6244 /* Remove ecommunity from aggregate.
6245 */
6246 bgp_remove_ecommunity_from_aggregate(
6247 aggregate,
6248 pi->attr->ecommunity);
6249
6250 if (pi->attr->lcommunity)
6251 /* Remove lcommunity from aggregate.
6252 */
6253 bgp_remove_lcommunity_from_aggregate(
6254 aggregate,
6255 pi->attr->lcommunity);
6256 }
6257
6258 /* If this node was suppressed, process the change. */
6259 if (match)
6260 bgp_process(bgp, pi->net, afi, safi);
6261
6262 origin = BGP_ORIGIN_IGP;
6263 if (aggregate->incomplete_origin_count > 0)
6264 origin = BGP_ORIGIN_INCOMPLETE;
6265 else if (aggregate->egp_origin_count > 0)
6266 origin = BGP_ORIGIN_EGP;
6267
6268 if (aggregate->as_set) {
6269 /* Retrieve aggregate route's as-path.
6270 */
6271 if (aggregate->aspath)
6272 aspath = aspath_dup(aggregate->aspath);
6273
6274 /* Retrieve aggregate route's community.
6275 */
6276 if (aggregate->community)
6277 community = community_dup(aggregate->community);
6278
6279 /* Retrieve aggregate route's ecommunity.
6280 */
6281 if (aggregate->ecommunity)
6282 ecommunity = ecommunity_dup(aggregate->ecommunity);
6283
6284 /* Retrieve aggregate route's lcommunity.
6285 */
6286 if (aggregate->lcommunity)
6287 lcommunity = lcommunity_dup(aggregate->lcommunity);
6288 }
6289
6290 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6291 aspath, community, ecommunity,
6292 lcommunity, atomic_aggregate, aggregate);
6293}
6294
d62a17ae 6295void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p,
40381db7 6296 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 6297{
d62a17ae 6298 struct bgp_node *child;
6299 struct bgp_node *rn;
6300 struct bgp_aggregate *aggregate;
6301 struct bgp_table *table;
718e3744 6302
d62a17ae 6303 table = bgp->aggregate[afi][safi];
f018db83 6304
d62a17ae 6305 /* No aggregates configured. */
6306 if (bgp_table_top_nolock(table) == NULL)
6307 return;
f018db83 6308
d62a17ae 6309 if (p->prefixlen == 0)
6310 return;
718e3744 6311
40381db7 6312 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 6313 return;
718e3744 6314
d62a17ae 6315 child = bgp_node_get(table, p);
718e3744 6316
d62a17ae 6317 /* Aggregate address configuration check. */
b1e62edd 6318 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
b613a918 6319 aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 6320 if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
fc968841
NT
6321 bgp_add_route_to_aggregate(bgp, &rn->p, pi, afi,
6322 safi, aggregate);
d62a17ae 6323 }
b1e62edd 6324 }
d62a17ae 6325 bgp_unlock_node(child);
718e3744 6326}
6327
d62a17ae 6328void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p,
4b7e6066 6329 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 6330{
d62a17ae 6331 struct bgp_node *child;
6332 struct bgp_node *rn;
6333 struct bgp_aggregate *aggregate;
6334 struct bgp_table *table;
718e3744 6335
d62a17ae 6336 table = bgp->aggregate[afi][safi];
718e3744 6337
d62a17ae 6338 /* No aggregates configured. */
6339 if (bgp_table_top_nolock(table) == NULL)
6340 return;
718e3744 6341
d62a17ae 6342 if (p->prefixlen == 0)
6343 return;
718e3744 6344
d62a17ae 6345 child = bgp_node_get(table, p);
718e3744 6346
d62a17ae 6347 /* Aggregate address configuration check. */
b1e62edd 6348 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
b613a918 6349 aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 6350 if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
fc968841
NT
6351 bgp_remove_route_from_aggregate(bgp, afi, safi,
6352 del, aggregate, &rn->p);
d62a17ae 6353 }
b1e62edd 6354 }
d62a17ae 6355 bgp_unlock_node(child);
6356}
718e3744 6357
718e3744 6358/* Aggregate route attribute. */
6359#define AGGREGATE_SUMMARY_ONLY 1
6360#define AGGREGATE_AS_SET 1
6361
d62a17ae 6362static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
6363 afi_t afi, safi_t safi)
718e3744 6364{
d62a17ae 6365 VTY_DECLVAR_CONTEXT(bgp, bgp);
6366 int ret;
6367 struct prefix p;
6368 struct bgp_node *rn;
6369 struct bgp_aggregate *aggregate;
718e3744 6370
d62a17ae 6371 /* Convert string to prefix structure. */
6372 ret = str2prefix(prefix_str, &p);
6373 if (!ret) {
6374 vty_out(vty, "Malformed prefix\n");
6375 return CMD_WARNING_CONFIG_FAILED;
6376 }
6377 apply_mask(&p);
6378
6379 /* Old configuration check. */
6380 rn = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
6381 if (!rn) {
6382 vty_out(vty,
6383 "%% There is no aggregate-address configuration.\n");
6384 return CMD_WARNING_CONFIG_FAILED;
6385 }
f6269b4f 6386
b613a918 6387 aggregate = bgp_node_get_bgp_aggregate_info(rn);
09990cdd 6388 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
dd18c5a9
DS
6389 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
6390 NULL, NULL, 0, aggregate);
d62a17ae 6391
6392 /* Unlock aggregate address configuration. */
b613a918 6393 bgp_node_set_bgp_aggregate_info(rn, NULL);
fc968841
NT
6394
6395 if (aggregate->community)
6396 community_free(&aggregate->community);
6397
6398 if (aggregate->community_hash) {
6399 /* Delete all communities in the hash.
6400 */
6401 hash_clean(aggregate->community_hash,
6402 bgp_aggr_community_remove);
6403 /* Free up the community_hash.
6404 */
6405 hash_free(aggregate->community_hash);
6406 }
6407
6408 if (aggregate->ecommunity)
6409 ecommunity_free(&aggregate->ecommunity);
6410
6411 if (aggregate->ecommunity_hash) {
6412 /* Delete all ecommunities in the hash.
6413 */
6414 hash_clean(aggregate->ecommunity_hash,
6415 bgp_aggr_ecommunity_remove);
6416 /* Free up the ecommunity_hash.
6417 */
6418 hash_free(aggregate->ecommunity_hash);
6419 }
6420
6421 if (aggregate->lcommunity)
6422 lcommunity_free(&aggregate->lcommunity);
6423
6424 if (aggregate->lcommunity_hash) {
6425 /* Delete all lcommunities in the hash.
6426 */
6427 hash_clean(aggregate->lcommunity_hash,
6428 bgp_aggr_lcommunity_remove);
6429 /* Free up the lcommunity_hash.
6430 */
6431 hash_free(aggregate->lcommunity_hash);
6432 }
6433
6434 if (aggregate->aspath)
6435 aspath_free(aggregate->aspath);
6436
6437 if (aggregate->aspath_hash) {
6438 /* Delete all as-paths in the hash.
6439 */
6440 hash_clean(aggregate->aspath_hash,
6441 bgp_aggr_aspath_remove);
6442 /* Free up the aspath_hash.
6443 */
6444 hash_free(aggregate->aspath_hash);
6445 }
6446
d62a17ae 6447 bgp_aggregate_free(aggregate);
6448 bgp_unlock_node(rn);
6449 bgp_unlock_node(rn);
6450
6451 return CMD_SUCCESS;
6452}
6453
6454static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
20894f50
DA
6455 safi_t safi, const char *rmap, uint8_t summary_only,
6456 uint8_t as_set)
d62a17ae 6457{
6458 VTY_DECLVAR_CONTEXT(bgp, bgp);
6459 int ret;
6460 struct prefix p;
6461 struct bgp_node *rn;
6462 struct bgp_aggregate *aggregate;
6463
6464 /* Convert string to prefix structure. */
6465 ret = str2prefix(prefix_str, &p);
6466 if (!ret) {
6467 vty_out(vty, "Malformed prefix\n");
6468 return CMD_WARNING_CONFIG_FAILED;
6469 }
6470 apply_mask(&p);
6471
3624ac81
DS
6472 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
6473 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
6474 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6475 prefix_str);
6476 return CMD_WARNING_CONFIG_FAILED;
6477 }
6478
d62a17ae 6479 /* Old configuration check. */
6480 rn = bgp_node_get(bgp->aggregate[afi][safi], &p);
20894f50 6481 aggregate = bgp_node_get_bgp_aggregate_info(rn);
d62a17ae 6482
20894f50 6483 if (aggregate) {
d62a17ae 6484 vty_out(vty, "There is already same aggregate network.\n");
6485 /* try to remove the old entry */
6486 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
6487 if (ret) {
6488 vty_out(vty, "Error deleting aggregate.\n");
6489 bgp_unlock_node(rn);
6490 return CMD_WARNING_CONFIG_FAILED;
6491 }
6492 }
718e3744 6493
d62a17ae 6494 /* Make aggregate address structure. */
6495 aggregate = bgp_aggregate_new();
6496 aggregate->summary_only = summary_only;
6497 aggregate->as_set = as_set;
6498 aggregate->safi = safi;
20894f50
DA
6499
6500 if (rmap) {
6501 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6502 route_map_counter_decrement(aggregate->rmap.map);
6503 aggregate->rmap.name =
6504 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6505 aggregate->rmap.map = route_map_lookup_by_name(rmap);
6506 route_map_counter_increment(aggregate->rmap.map);
6507 }
b613a918 6508 bgp_node_set_bgp_aggregate_info(rn, aggregate);
718e3744 6509
d62a17ae 6510 /* Aggregate address insert into BGP routing table. */
fc968841 6511 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 6512
d62a17ae 6513 return CMD_SUCCESS;
718e3744 6514}
6515
6516DEFUN (aggregate_address,
6517 aggregate_address_cmd,
20894f50 6518 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6519 "Configure BGP aggregate entries\n"
6520 "Aggregate prefix\n"
6521 "Generate AS set path information\n"
a636c635
DW
6522 "Filter more specific routes from updates\n"
6523 "Filter more specific routes from updates\n"
20894f50
DA
6524 "Generate AS set path information\n"
6525 "Apply route map to aggregate network\n"
6526 "Name of route map\n")
718e3744 6527{
d62a17ae 6528 int idx = 0;
6529 argv_find(argv, argc, "A.B.C.D/M", &idx);
6530 char *prefix = argv[idx]->arg;
20894f50 6531 char *rmap = NULL;
d62a17ae 6532 int as_set =
6533 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
6534 idx = 0;
6535 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6536 ? AGGREGATE_SUMMARY_ONLY
6537 : 0;
e3e6107d 6538
20894f50
DA
6539 idx = 0;
6540 argv_find(argv, argc, "WORD", &idx);
6541 if (idx)
6542 rmap = argv[idx]->arg;
6543
d62a17ae 6544 return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty),
20894f50 6545 rmap, summary_only, as_set);
718e3744 6546}
6547
e3e6107d
QY
6548DEFUN (aggregate_address_mask,
6549 aggregate_address_mask_cmd,
20894f50 6550 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6551 "Configure BGP aggregate entries\n"
6552 "Aggregate address\n"
6553 "Aggregate mask\n"
6554 "Generate AS set path information\n"
a636c635
DW
6555 "Filter more specific routes from updates\n"
6556 "Filter more specific routes from updates\n"
20894f50
DA
6557 "Generate AS set path information\n"
6558 "Apply route map to aggregate network\n"
6559 "Name of route map\n")
718e3744 6560{
d62a17ae 6561 int idx = 0;
6562 argv_find(argv, argc, "A.B.C.D", &idx);
6563 char *prefix = argv[idx]->arg;
6564 char *mask = argv[idx + 1]->arg;
cf40d052 6565 bool rmap_found;
20894f50 6566 char *rmap = NULL;
d62a17ae 6567 int as_set =
6568 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
6569 idx = 0;
6570 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6571 ? AGGREGATE_SUMMARY_ONLY
6572 : 0;
6573
cf40d052
DS
6574 rmap_found = argv_find(argv, argc, "WORD", &idx);
6575 if (rmap_found)
20894f50
DA
6576 rmap = argv[idx]->arg;
6577
d62a17ae 6578 char prefix_str[BUFSIZ];
6579 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
6580
6581 if (!ret) {
6582 vty_out(vty, "%% Inconsistent address and mask\n");
6583 return CMD_WARNING_CONFIG_FAILED;
6584 }
718e3744 6585
d62a17ae 6586 return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
20894f50 6587 rmap, summary_only, as_set);
718e3744 6588}
6589
718e3744 6590DEFUN (no_aggregate_address,
6591 no_aggregate_address_cmd,
b84da0db 6592 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6593 NO_STR
6594 "Configure BGP aggregate entries\n"
a636c635
DW
6595 "Aggregate prefix\n"
6596 "Generate AS set path information\n"
e3e6107d
QY
6597 "Filter more specific routes from updates\n"
6598 "Filter more specific routes from updates\n"
b84da0db
DA
6599 "Generate AS set path information\n"
6600 "Apply route map to aggregate network\n"
6601 "Name of route map\n")
718e3744 6602{
d62a17ae 6603 int idx = 0;
6604 argv_find(argv, argc, "A.B.C.D/M", &idx);
6605 char *prefix = argv[idx]->arg;
6606 return bgp_aggregate_unset(vty, prefix, AFI_IP, bgp_node_safi(vty));
718e3744 6607}
6608
718e3744 6609DEFUN (no_aggregate_address_mask,
6610 no_aggregate_address_mask_cmd,
b84da0db 6611 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6612 NO_STR
6613 "Configure BGP aggregate entries\n"
6614 "Aggregate address\n"
a636c635
DW
6615 "Aggregate mask\n"
6616 "Generate AS set path information\n"
e3e6107d
QY
6617 "Filter more specific routes from updates\n"
6618 "Filter more specific routes from updates\n"
b84da0db
DA
6619 "Generate AS set path information\n"
6620 "Apply route map to aggregate network\n"
6621 "Name of route map\n")
718e3744 6622{
d62a17ae 6623 int idx = 0;
6624 argv_find(argv, argc, "A.B.C.D", &idx);
6625 char *prefix = argv[idx]->arg;
6626 char *mask = argv[idx + 1]->arg;
718e3744 6627
d62a17ae 6628 char prefix_str[BUFSIZ];
6629 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
718e3744 6630
d62a17ae 6631 if (!ret) {
6632 vty_out(vty, "%% Inconsistent address and mask\n");
6633 return CMD_WARNING_CONFIG_FAILED;
6634 }
718e3744 6635
d62a17ae 6636 return bgp_aggregate_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
718e3744 6637}
6638
718e3744 6639DEFUN (ipv6_aggregate_address,
6640 ipv6_aggregate_address_cmd,
20894f50 6641 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6642 "Configure BGP aggregate entries\n"
6643 "Aggregate prefix\n"
5101fece 6644 "Generate AS set path information\n"
6645 "Filter more specific routes from updates\n"
6646 "Filter more specific routes from updates\n"
20894f50
DA
6647 "Generate AS set path information\n"
6648 "Apply route map to aggregate network\n"
6649 "Name of route map\n")
718e3744 6650{
d62a17ae 6651 int idx = 0;
6652 argv_find(argv, argc, "X:X::X:X/M", &idx);
6653 char *prefix = argv[idx]->arg;
20894f50 6654 char *rmap = NULL;
273fae13 6655 bool rmap_found;
5101fece 6656 int as_set =
6657 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
6658
6659 idx = 0;
d62a17ae 6660 int sum_only = argv_find(argv, argc, "summary-only", &idx)
6661 ? AGGREGATE_SUMMARY_ONLY
6662 : 0;
20894f50 6663
273fae13
DA
6664 rmap_found = argv_find(argv, argc, "WORD", &idx);
6665 if (rmap_found)
20894f50
DA
6666 rmap = argv[idx]->arg;
6667
6668 return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, rmap,
6669 sum_only, as_set);
718e3744 6670}
6671
6672DEFUN (no_ipv6_aggregate_address,
6673 no_ipv6_aggregate_address_cmd,
b84da0db 6674 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6675 NO_STR
6676 "Configure BGP aggregate entries\n"
16cedbb0 6677 "Aggregate prefix\n"
5101fece 6678 "Generate AS set path information\n"
6679 "Filter more specific routes from updates\n"
6680 "Filter more specific routes from updates\n"
b84da0db
DA
6681 "Generate AS set path information\n"
6682 "Apply route map to aggregate network\n"
6683 "Name of route map\n")
718e3744 6684{
d62a17ae 6685 int idx = 0;
6686 argv_find(argv, argc, "X:X::X:X/M", &idx);
6687 char *prefix = argv[idx]->arg;
6688 return bgp_aggregate_unset(vty, prefix, AFI_IP6, SAFI_UNICAST);
718e3744 6689}
6690
718e3744 6691/* Redistribute route treatment. */
d62a17ae 6692void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
6693 const union g_addr *nexthop, ifindex_t ifindex,
6694 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
6695 uint8_t type, unsigned short instance,
6696 route_tag_t tag)
d62a17ae 6697{
4b7e6066 6698 struct bgp_path_info *new;
40381db7
DS
6699 struct bgp_path_info *bpi;
6700 struct bgp_path_info rmap_path;
d62a17ae 6701 struct bgp_node *bn;
6702 struct attr attr;
6703 struct attr *new_attr;
6704 afi_t afi;
b68885f9 6705 route_map_result_t ret;
d62a17ae 6706 struct bgp_redist *red;
6707
6708 /* Make default attribute. */
6709 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
9de1f7ff 6710
a4d82a8a 6711 switch (nhtype) {
9de1f7ff
DS
6712 case NEXTHOP_TYPE_IFINDEX:
6713 break;
6714 case NEXTHOP_TYPE_IPV4:
6715 case NEXTHOP_TYPE_IPV4_IFINDEX:
6716 attr.nexthop = nexthop->ipv4;
6717 break;
6718 case NEXTHOP_TYPE_IPV6:
6719 case NEXTHOP_TYPE_IPV6_IFINDEX:
6720 attr.mp_nexthop_global = nexthop->ipv6;
6721 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
6722 break;
6723 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
6724 switch (p->family) {
6725 case AF_INET:
9de1f7ff 6726 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
6727 break;
6728 case AF_INET6:
9de1f7ff
DS
6729 memset(&attr.mp_nexthop_global, 0,
6730 sizeof(attr.mp_nexthop_global));
74489921 6731 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 6732 break;
74489921 6733 }
9de1f7ff 6734 break;
d62a17ae 6735 }
74489921 6736 attr.nh_ifindex = ifindex;
f04a80a5 6737
d62a17ae 6738 attr.med = metric;
6739 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
6740 attr.tag = tag;
718e3744 6741
d62a17ae 6742 afi = family2afi(p->family);
6aeb9e78 6743
d62a17ae 6744 red = bgp_redist_lookup(bgp, afi, type, instance);
6745 if (red) {
6746 struct attr attr_new;
718e3744 6747
d62a17ae 6748 /* Copy attribute for modification. */
6749 bgp_attr_dup(&attr_new, &attr);
718e3744 6750
d62a17ae 6751 if (red->redist_metric_flag)
6752 attr_new.med = red->redist_metric;
718e3744 6753
d62a17ae 6754 /* Apply route-map. */
6755 if (red->rmap.name) {
40381db7
DS
6756 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
6757 rmap_path.peer = bgp->peer_self;
6758 rmap_path.attr = &attr_new;
718e3744 6759
d62a17ae 6760 SET_FLAG(bgp->peer_self->rmap_type,
6761 PEER_RMAP_TYPE_REDISTRIBUTE);
6762
6763 ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
40381db7 6764 &rmap_path);
d62a17ae 6765
6766 bgp->peer_self->rmap_type = 0;
6767
6768 if (ret == RMAP_DENYMATCH) {
6769 /* Free uninterned attribute. */
6770 bgp_attr_flush(&attr_new);
6771
6772 /* Unintern original. */
6773 aspath_unintern(&attr.aspath);
6774 bgp_redistribute_delete(bgp, p, type, instance);
6775 return;
6776 }
6777 }
6778
7f323236
DW
6779 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
6780 bgp_attr_add_gshut_community(&attr_new);
6781
d62a17ae 6782 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
6783 SAFI_UNICAST, p, NULL);
6784
6785 new_attr = bgp_attr_intern(&attr_new);
6786
6f94b685
DS
6787 for (bpi = bgp_node_get_bgp_path_info(bn); bpi;
6788 bpi = bpi->next)
40381db7
DS
6789 if (bpi->peer == bgp->peer_self
6790 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 6791 break;
6792
40381db7 6793 if (bpi) {
d62a17ae 6794 /* Ensure the (source route) type is updated. */
40381db7
DS
6795 bpi->type = type;
6796 if (attrhash_cmp(bpi->attr, new_attr)
6797 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 6798 bgp_attr_unintern(&new_attr);
6799 aspath_unintern(&attr.aspath);
6800 bgp_unlock_node(bn);
6801 return;
6802 } else {
6803 /* The attribute is changed. */
40381db7 6804 bgp_path_info_set_flag(bn, bpi,
18ee8310 6805 BGP_PATH_ATTR_CHANGED);
d62a17ae 6806
6807 /* Rewrite BGP route information. */
40381db7
DS
6808 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
6809 bgp_path_info_restore(bn, bpi);
d62a17ae 6810 else
40381db7
DS
6811 bgp_aggregate_decrement(
6812 bgp, p, bpi, afi, SAFI_UNICAST);
6813 bgp_attr_unintern(&bpi->attr);
6814 bpi->attr = new_attr;
6815 bpi->uptime = bgp_clock();
d62a17ae 6816
6817 /* Process change. */
40381db7 6818 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 6819 SAFI_UNICAST);
6820 bgp_process(bgp, bn, afi, SAFI_UNICAST);
6821 bgp_unlock_node(bn);
6822 aspath_unintern(&attr.aspath);
ddb5b488
PZ
6823
6824 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6825 || (bgp->inst_type
6826 == BGP_INSTANCE_TYPE_DEFAULT)) {
6827
6828 vpn_leak_from_vrf_update(
40381db7 6829 bgp_get_default(), bgp, bpi);
ddb5b488 6830 }
d62a17ae 6831 return;
6832 }
6833 }
6834
6835 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
6836 bgp->peer_self, new_attr, bn);
1defdda8 6837 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 6838
6839 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 6840 bgp_path_info_add(bn, new);
d62a17ae 6841 bgp_unlock_node(bn);
6842 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
6843
6844 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6845 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6846
6847 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6848 }
d62a17ae 6849 }
6850
6851 /* Unintern original. */
6852 aspath_unintern(&attr.aspath);
718e3744 6853}
6854
d7c0a89a
QY
6855void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
6856 unsigned short instance)
718e3744 6857{
d62a17ae 6858 afi_t afi;
6859 struct bgp_node *rn;
40381db7 6860 struct bgp_path_info *pi;
d62a17ae 6861 struct bgp_redist *red;
718e3744 6862
d62a17ae 6863 afi = family2afi(p->family);
718e3744 6864
d62a17ae 6865 red = bgp_redist_lookup(bgp, afi, type, instance);
6866 if (red) {
6867 rn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
6868 SAFI_UNICAST, p, NULL);
6869
6f94b685 6870 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7 6871 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 6872 break;
6873
40381db7 6874 if (pi) {
ddb5b488
PZ
6875 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6876 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6877
6878 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 6879 bgp, pi);
ddb5b488 6880 }
40381db7
DS
6881 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
6882 bgp_path_info_delete(rn, pi);
d62a17ae 6883 bgp_process(bgp, rn, afi, SAFI_UNICAST);
6884 }
6885 bgp_unlock_node(rn);
6886 }
6887}
6888
6889/* Withdraw specified route type's route. */
6890void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 6891 unsigned short instance)
d62a17ae 6892{
6893 struct bgp_node *rn;
40381db7 6894 struct bgp_path_info *pi;
d62a17ae 6895 struct bgp_table *table;
6896
6897 table = bgp->rib[afi][SAFI_UNICAST];
6898
6899 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685 6900 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
6901 if (pi->peer == bgp->peer_self && pi->type == type
6902 && pi->instance == instance)
d62a17ae 6903 break;
6904
40381db7 6905 if (pi) {
ddb5b488
PZ
6906 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6907 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6908
6909 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 6910 bgp, pi);
ddb5b488 6911 }
40381db7 6912 bgp_aggregate_decrement(bgp, &rn->p, pi, afi,
d62a17ae 6913 SAFI_UNICAST);
40381db7 6914 bgp_path_info_delete(rn, pi);
d62a17ae 6915 bgp_process(bgp, rn, afi, SAFI_UNICAST);
6916 }
718e3744 6917 }
718e3744 6918}
6b0655a2 6919
718e3744 6920/* Static function to display route. */
9c92b5f7
MK
6921static void route_vty_out_route(struct prefix *p, struct vty *vty,
6922 json_object *json)
718e3744 6923{
be054588 6924 int len = 0;
d62a17ae 6925 char buf[BUFSIZ];
50e05855 6926 char buf2[BUFSIZ];
718e3744 6927
d62a17ae 6928 if (p->family == AF_INET) {
c6462ff4 6929 if (!json) {
89e5e9f0
PM
6930 len = vty_out(
6931 vty, "%s/%d",
6932 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
6933 p->prefixlen);
c6462ff4
MK
6934 } else {
6935 json_object_string_add(json, "prefix",
6936 inet_ntop(p->family,
6937 &p->u.prefix, buf,
6938 BUFSIZ));
6939 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 6940 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 6941 json_object_string_add(json, "network", buf2);
c6462ff4 6942 }
d62a17ae 6943 } else if (p->family == AF_ETHERNET) {
b03b8898
DS
6944 prefix2str(p, buf, PREFIX_STRLEN);
6945 len = vty_out(vty, "%s", buf);
6946 } else if (p->family == AF_EVPN) {
57f7feb6 6947 if (!json)
60466a63
QY
6948 len = vty_out(
6949 vty, "%s",
6950 bgp_evpn_route2str((struct prefix_evpn *)p, buf,
6951 BUFSIZ));
57f7feb6 6952 else
60466a63 6953 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
6954 } else if (p->family == AF_FLOWSPEC) {
6955 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
6956 json ?
6957 NLRI_STRING_FORMAT_JSON_SIMPLE :
6958 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 6959 } else {
c6462ff4 6960 if (!json)
60466a63
QY
6961 len = vty_out(
6962 vty, "%s/%d",
6963 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
6964 p->prefixlen);
50e05855
AD
6965 else {
6966 json_object_string_add(json, "prefix",
6967 inet_ntop(p->family,
6968 &p->u.prefix, buf,
6969 BUFSIZ));
6970 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
6971 prefix2str(p, buf2, PREFIX_STRLEN);
6972 json_object_string_add(json, "network", buf2);
6973 }
9c92b5f7 6974 }
d62a17ae 6975
9c92b5f7
MK
6976 if (!json) {
6977 len = 17 - len;
6978 if (len < 1)
6979 vty_out(vty, "\n%*s", 20, " ");
6980 else
6981 vty_out(vty, "%*s", len, " ");
6982 }
718e3744 6983}
6984
d62a17ae 6985enum bgp_display_type {
6986 normal_list,
718e3744 6987};
6988
18ee8310 6989/* Print the short form route status for a bgp_path_info */
4b7e6066 6990static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 6991 struct bgp_path_info *path,
d62a17ae 6992 json_object *json_path)
718e3744 6993{
d62a17ae 6994 if (json_path) {
b05a1c8b 6995
d62a17ae 6996 /* Route status display. */
9b6d8fcf 6997 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 6998 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 6999
9b6d8fcf 7000 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7001 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 7002
9b6d8fcf 7003 if (path->extra && path->extra->suppress)
d62a17ae 7004 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 7005
9b6d8fcf
DS
7006 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7007 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7008 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 7009
d62a17ae 7010 /* Selected */
9b6d8fcf 7011 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7012 json_object_boolean_true_add(json_path, "history");
b05a1c8b 7013
9b6d8fcf 7014 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7015 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 7016
9b6d8fcf 7017 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7018 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b 7019
9b6d8fcf 7020 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7021 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 7022
d62a17ae 7023 /* Internal route. */
9b6d8fcf
DS
7024 if ((path->peer->as)
7025 && (path->peer->as == path->peer->local_as))
d62a17ae 7026 json_object_string_add(json_path, "pathFrom",
7027 "internal");
7028 else
7029 json_object_string_add(json_path, "pathFrom",
7030 "external");
b05a1c8b 7031
d62a17ae 7032 return;
7033 }
b05a1c8b 7034
d62a17ae 7035 /* Route status display. */
9b6d8fcf 7036 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7037 vty_out(vty, "R");
9b6d8fcf 7038 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7039 vty_out(vty, "S");
9b6d8fcf 7040 else if (path->extra && path->extra->suppress)
d62a17ae 7041 vty_out(vty, "s");
9b6d8fcf
DS
7042 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7043 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7044 vty_out(vty, "*");
7045 else
7046 vty_out(vty, " ");
7047
7048 /* Selected */
9b6d8fcf 7049 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7050 vty_out(vty, "h");
9b6d8fcf 7051 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7052 vty_out(vty, "d");
9b6d8fcf 7053 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7054 vty_out(vty, ">");
9b6d8fcf 7055 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7056 vty_out(vty, "=");
7057 else
7058 vty_out(vty, " ");
718e3744 7059
d62a17ae 7060 /* Internal route. */
9b6d8fcf
DS
7061 if (path->peer && (path->peer->as)
7062 && (path->peer->as == path->peer->local_as))
d62a17ae 7063 vty_out(vty, "i");
7064 else
7065 vty_out(vty, " ");
b40d939b 7066}
7067
25b5da8d
DA
7068static char *bgp_nexthop_fqdn(struct peer *peer)
7069{
7070 if (peer->hostname && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
7071 return peer->hostname;
7072 return NULL;
7073}
7074
b40d939b 7075/* called from terminal list command */
4b7e6066 7076void route_vty_out(struct vty *vty, struct prefix *p,
9b6d8fcf 7077 struct bgp_path_info *path, int display, safi_t safi,
4b7e6066 7078 json_object *json_paths)
d62a17ae 7079{
7080 struct attr *attr;
7081 json_object *json_path = NULL;
7082 json_object *json_nexthops = NULL;
7083 json_object *json_nexthop_global = NULL;
7084 json_object *json_nexthop_ll = NULL;
6f214dd3 7085 json_object *json_ext_community = NULL;
9df8b37c 7086 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 7087 bool nexthop_self =
9b6d8fcf 7088 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 7089 bool nexthop_othervrf = false;
43089216 7090 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 7091 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
25b5da8d 7092 char *nexthop_fqdn = bgp_nexthop_fqdn(path->peer);
d62a17ae 7093
7094 if (json_paths)
7095 json_path = json_object_new_object();
7096
7097 /* short status lead text */
9b6d8fcf 7098 route_vty_short_status_out(vty, path, json_path);
d62a17ae 7099
7100 if (!json_paths) {
7101 /* print prefix and mask */
7102 if (!display)
9c92b5f7 7103 route_vty_out_route(p, vty, json_path);
d62a17ae 7104 else
7105 vty_out(vty, "%*s", 17, " ");
9c92b5f7 7106 } else {
b682f6de 7107 route_vty_out_route(p, vty, json_path);
d62a17ae 7108 }
47fc97cc 7109
d62a17ae 7110 /* Print attribute */
9b6d8fcf 7111 attr = path->attr;
445c2480
DS
7112 if (!attr) {
7113 if (json_paths)
7114 json_object_array_add(json_paths, json_path);
7115 else
7116 vty_out(vty, "\n");
d62a17ae 7117
445c2480
DS
7118 return;
7119 }
7120
9df8b37c
PZ
7121 /*
7122 * If vrf id of nexthop is different from that of prefix,
7123 * set up printable string to append
7124 */
9b6d8fcf 7125 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
7126 const char *self = "";
7127
7128 if (nexthop_self)
7129 self = "<";
7130
7131 nexthop_othervrf = true;
9b6d8fcf 7132 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 7133
9b6d8fcf 7134 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
7135 snprintf(vrf_id_str, sizeof(vrf_id_str),
7136 "@%s%s", VRFID_NONE_STR, self);
7137 else
7138 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 7139 path->extra->bgp_orig->vrf_id, self);
9df8b37c 7140
9b6d8fcf
DS
7141 if (path->extra->bgp_orig->inst_type
7142 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 7143
9b6d8fcf 7144 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
7145 } else {
7146 const char *self = "";
7147
7148 if (nexthop_self)
7149 self = "<";
7150
7151 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
7152 }
7153
445c2480
DS
7154 /*
7155 * For ENCAP and EVPN routes, nexthop address family is not
7156 * neccessarily the same as the prefix address family.
7157 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7158 * EVPN routes are also exchanged with a MP nexthop. Currently,
7159 * this
7160 * is only IPv4, the value will be present in either
7161 * attr->nexthop or
7162 * attr->mp_nexthop_global_in
7163 */
7164 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
7165 char buf[BUFSIZ];
7166 char nexthop[128];
7167 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
7168
7169 switch (af) {
7170 case AF_INET:
7171 sprintf(nexthop, "%s",
a4d82a8a
PZ
7172 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
7173 BUFSIZ));
445c2480
DS
7174 break;
7175 case AF_INET6:
7176 sprintf(nexthop, "%s",
a4d82a8a
PZ
7177 inet_ntop(af, &attr->mp_nexthop_global, buf,
7178 BUFSIZ));
445c2480
DS
7179 break;
7180 default:
7181 sprintf(nexthop, "?");
7182 break;
d62a17ae 7183 }
d62a17ae 7184
445c2480
DS
7185 if (json_paths) {
7186 json_nexthop_global = json_object_new_object();
7187
25b5da8d
DA
7188 json_object_string_add(
7189 json_nexthop_global, "afi",
7190 nexthop_fqdn ? "fqdn"
7191 : (af == AF_INET) ? "ip" : "ipv6");
7192 json_object_string_add(
7193 json_nexthop_global,
7194 nexthop_fqdn ? "fqdn"
7195 : (af == AF_INET) ? "ip" : "ipv6",
7196 nexthop_fqdn ? nexthop_fqdn : nexthop);
445c2480
DS
7197 json_object_boolean_true_add(json_nexthop_global,
7198 "used");
7199 } else
25b5da8d
DA
7200 vty_out(vty, "%s%s",
7201 nexthop_fqdn ? nexthop_fqdn : nexthop,
7202 vrf_id_str);
445c2480
DS
7203 } else if (safi == SAFI_EVPN) {
7204 if (json_paths) {
7205 json_nexthop_global = json_object_new_object();
7206
25b5da8d
DA
7207 json_object_string_add(
7208 json_nexthop_global,
7209 nexthop_fqdn ? "fqdn" : "ip",
7210 nexthop_fqdn ? nexthop_fqdn
7211 : inet_ntoa(attr->nexthop));
a4d82a8a
PZ
7212 json_object_string_add(json_nexthop_global, "afi",
7213 "ipv4");
445c2480
DS
7214 json_object_boolean_true_add(json_nexthop_global,
7215 "used");
7216 } else
25b5da8d
DA
7217 vty_out(vty, "%-16s%s",
7218 nexthop_fqdn ?: inet_ntoa(attr->nexthop),
9df8b37c 7219 vrf_id_str);
d33fc23b 7220 } else if (safi == SAFI_FLOWSPEC) {
026b914a
PG
7221 if (attr->nexthop.s_addr != 0) {
7222 if (json_paths) {
7223 json_nexthop_global = json_object_new_object();
7224 json_object_string_add(
25b5da8d
DA
7225 json_nexthop_global,
7226 nexthop_fqdn ? "fqdn" : "ip",
7227 nexthop_fqdn
7228 ? nexthop_fqdn
7229 : inet_ntoa(attr->nexthop));
026b914a
PG
7230 json_object_string_add(json_nexthop_global,
7231 "afi", "ipv4");
50e05855
AD
7232 json_object_boolean_true_add(
7233 json_nexthop_global,
026b914a
PG
7234 "used");
7235 } else {
25b5da8d
DA
7236 vty_out(vty, "%-16s",
7237 nexthop_fqdn
7238 ? nexthop_fqdn
7239 : inet_ntoa(attr->nexthop));
026b914a
PG
7240 }
7241 }
d33fc23b 7242 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
7243 if (json_paths) {
7244 json_nexthop_global = json_object_new_object();
d62a17ae 7245
a4d82a8a
PZ
7246 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN))
7247 json_object_string_add(
25b5da8d
DA
7248 json_nexthop_global,
7249 nexthop_fqdn ? "fqdn" : "ip",
7250 nexthop_fqdn
7251 ? nexthop_fqdn
7252 : inet_ntoa(
7253 attr->mp_nexthop_global_in));
445c2480 7254 else
a4d82a8a 7255 json_object_string_add(
25b5da8d
DA
7256 json_nexthop_global,
7257 nexthop_fqdn ? "fqdn" : "ip",
7258 nexthop_fqdn
7259 ? nexthop_fqdn
7260 : inet_ntoa(attr->nexthop));
445c2480 7261
a4d82a8a
PZ
7262 json_object_string_add(json_nexthop_global, "afi",
7263 "ipv4");
445c2480
DS
7264 json_object_boolean_true_add(json_nexthop_global,
7265 "used");
7266 } else {
9df8b37c
PZ
7267 char buf[BUFSIZ];
7268
d87ff2dd 7269 snprintf(buf, sizeof(buf), "%s%s",
25b5da8d
DA
7270 nexthop_fqdn ? nexthop_fqdn
7271 : inet_ntoa(attr->nexthop),
7272 vrf_id_str);
9df8b37c 7273 vty_out(vty, "%-16s", buf);
d62a17ae 7274 }
445c2480 7275 }
b05a1c8b 7276
445c2480 7277 /* IPv6 Next Hop */
a4d82a8a 7278 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
7279 int len;
7280 char buf[BUFSIZ];
d62a17ae 7281
445c2480
DS
7282 if (json_paths) {
7283 json_nexthop_global = json_object_new_object();
a4d82a8a 7284 json_object_string_add(
25b5da8d
DA
7285 json_nexthop_global,
7286 nexthop_fqdn ? "fqdn" : "ip",
7287 nexthop_fqdn
7288 ? nexthop_fqdn
7289 : inet_ntop(AF_INET6,
7290 &attr->mp_nexthop_global,
7291 buf, BUFSIZ));
a4d82a8a
PZ
7292 json_object_string_add(json_nexthop_global, "afi",
7293 "ipv6");
7294 json_object_string_add(json_nexthop_global, "scope",
7295 "global");
445c2480
DS
7296
7297 /* We display both LL & GL if both have been
7298 * received */
0606039c
DA
7299 if ((attr->mp_nexthop_len
7300 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 7301 || (path->peer->conf_if)) {
a4d82a8a 7302 json_nexthop_ll = json_object_new_object();
d62a17ae 7303 json_object_string_add(
25b5da8d
DA
7304 json_nexthop_ll,
7305 nexthop_fqdn ? "fqdn" : "ip",
7306 nexthop_fqdn
7307 ? nexthop_fqdn
7308 : inet_ntop(
7309 AF_INET6,
7310 &attr->mp_nexthop_local,
7311 buf, BUFSIZ));
a4d82a8a
PZ
7312 json_object_string_add(json_nexthop_ll, "afi",
7313 "ipv6");
7314 json_object_string_add(json_nexthop_ll, "scope",
445c2480 7315 "link-local");
d62a17ae 7316
a4d82a8a
PZ
7317 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
7318 &attr->mp_nexthop_local)
445c2480
DS
7319 != 0)
7320 && !attr->mp_nexthop_prefer_global)
d62a17ae 7321 json_object_boolean_true_add(
a4d82a8a 7322 json_nexthop_ll, "used");
445c2480
DS
7323 else
7324 json_object_boolean_true_add(
a4d82a8a 7325 json_nexthop_global, "used");
445c2480
DS
7326 } else
7327 json_object_boolean_true_add(
7328 json_nexthop_global, "used");
7329 } else {
7330 /* Display LL if LL/Global both in table unless
7331 * prefer-global is set */
0606039c
DA
7332 if (((attr->mp_nexthop_len
7333 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 7334 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
7335 || (path->peer->conf_if)) {
7336 if (path->peer->conf_if) {
a4d82a8a 7337 len = vty_out(vty, "%s",
9b6d8fcf 7338 path->peer->conf_if);
445c2480
DS
7339 len = 16 - len; /* len of IPv6
7340 addr + max
7341 len of def
7342 ifname */
7343
7344 if (len < 1)
a4d82a8a 7345 vty_out(vty, "\n%*s", 36, " ");
445c2480 7346 else
a4d82a8a 7347 vty_out(vty, "%*s", len, " ");
d62a17ae 7348 } else {
7349 len = vty_out(
9df8b37c 7350 vty, "%s%s",
25b5da8d
DA
7351 nexthop_fqdn
7352 ? nexthop_fqdn
7353 : inet_ntop(
7354 AF_INET6,
7355 &attr->mp_nexthop_local,
7356 buf, BUFSIZ),
9df8b37c 7357 vrf_id_str);
d62a17ae 7358 len = 16 - len;
7359
7360 if (len < 1)
a4d82a8a 7361 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 7362 else
a4d82a8a 7363 vty_out(vty, "%*s", len, " ");
d62a17ae 7364 }
445c2480 7365 } else {
a4d82a8a 7366 len = vty_out(
9df8b37c 7367 vty, "%s%s",
25b5da8d
DA
7368 nexthop_fqdn
7369 ? nexthop_fqdn
7370 : inet_ntop(
7371 AF_INET6,
7372 &attr->mp_nexthop_global,
7373 buf, BUFSIZ),
7374 vrf_id_str);
445c2480
DS
7375 len = 16 - len;
7376
7377 if (len < 1)
7378 vty_out(vty, "\n%*s", 36, " ");
7379 else
7380 vty_out(vty, "%*s", len, " ");
d62a17ae 7381 }
7382 }
445c2480 7383 }
718e3744 7384
445c2480
DS
7385 /* MED/Metric */
7386 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
50e05855
AD
7387 if (json_paths) {
7388
7389 /*
7390 * Adding "metric" field to match with corresponding
7391 * CLI. "med" will be deprecated in future.
7392 */
a4d82a8a 7393 json_object_int_add(json_path, "med", attr->med);
50e05855
AD
7394 json_object_int_add(json_path, "metric", attr->med);
7395 } else
445c2480
DS
7396 vty_out(vty, "%10u", attr->med);
7397 else if (!json_paths)
7398 vty_out(vty, " ");
d62a17ae 7399
445c2480
DS
7400 /* Local Pref */
7401 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855
AD
7402 if (json_paths) {
7403
7404 /*
7405 * Adding "locPrf" field to match with corresponding
7406 * CLI. "localPref" will be deprecated in future.
7407 */
445c2480
DS
7408 json_object_int_add(json_path, "localpref",
7409 attr->local_pref);
50e05855
AD
7410 json_object_int_add(json_path, "locPrf",
7411 attr->local_pref);
7412 } else
445c2480
DS
7413 vty_out(vty, "%7u", attr->local_pref);
7414 else if (!json_paths)
7415 vty_out(vty, " ");
d62a17ae 7416
445c2480
DS
7417 if (json_paths)
7418 json_object_int_add(json_path, "weight", attr->weight);
7419 else
7420 vty_out(vty, "%7u ", attr->weight);
47fc97cc 7421
445c2480
DS
7422 if (json_paths) {
7423 char buf[BUFSIZ];
a4d82a8a
PZ
7424 json_object_string_add(
7425 json_path, "peerId",
9b6d8fcf 7426 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 7427 }
b05a1c8b 7428
445c2480
DS
7429 /* Print aspath */
7430 if (attr->aspath) {
50e05855
AD
7431 if (json_paths) {
7432
7433 /*
7434 * Adding "path" field to match with corresponding
7435 * CLI. "aspath" will be deprecated in future.
7436 */
445c2480
DS
7437 json_object_string_add(json_path, "aspath",
7438 attr->aspath->str);
50e05855
AD
7439 json_object_string_add(json_path, "path",
7440 attr->aspath->str);
7441 } else
445c2480 7442 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 7443 }
f1aa5d8a 7444
445c2480
DS
7445 /* Print origin */
7446 if (json_paths)
a4d82a8a
PZ
7447 json_object_string_add(json_path, "origin",
7448 bgp_origin_long_str[attr->origin]);
445c2480
DS
7449 else
7450 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7451
9df8b37c 7452 if (json_paths) {
6f214dd3
CS
7453 if (safi == SAFI_EVPN &&
7454 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7455 json_ext_community = json_object_new_object();
7456 json_object_string_add(json_ext_community,
7457 "string",
7458 attr->ecommunity->str);
7459 json_object_object_add(json_path,
7460 "extendedCommunity",
7461 json_ext_community);
7462 }
7463
9df8b37c
PZ
7464 if (nexthop_self)
7465 json_object_boolean_true_add(json_path,
7466 "announceNexthopSelf");
7467 if (nexthop_othervrf) {
7468 json_object_string_add(json_path, "nhVrfName",
7469 nexthop_vrfname);
7470
7471 json_object_int_add(json_path, "nhVrfId",
7472 ((nexthop_vrfid == VRF_UNKNOWN)
7473 ? -1
7474 : (int)nexthop_vrfid));
7475 }
7476 }
7477
d62a17ae 7478 if (json_paths) {
7479 if (json_nexthop_global || json_nexthop_ll) {
7480 json_nexthops = json_object_new_array();
f1aa5d8a 7481
d62a17ae 7482 if (json_nexthop_global)
7483 json_object_array_add(json_nexthops,
7484 json_nexthop_global);
f1aa5d8a 7485
d62a17ae 7486 if (json_nexthop_ll)
7487 json_object_array_add(json_nexthops,
7488 json_nexthop_ll);
f1aa5d8a 7489
d62a17ae 7490 json_object_object_add(json_path, "nexthops",
7491 json_nexthops);
7492 }
7493
7494 json_object_array_add(json_paths, json_path);
7495 } else {
7496 vty_out(vty, "\n");
6f214dd3
CS
7497
7498 if (safi == SAFI_EVPN &&
7499 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7500 vty_out(vty, "%*s", 20, " ");
7501 vty_out(vty, "%s\n", attr->ecommunity->str);
7502 }
7503
65efcfce 7504#if ENABLE_BGP_VNC
d62a17ae 7505 /* prints an additional line, indented, with VNC info, if
7506 * present */
7507 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 7508 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 7509#endif
d62a17ae 7510 }
7511}
718e3744 7512
7513/* called from terminal list command */
d62a17ae 7514void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr,
9f049418 7515 safi_t safi, bool use_json, json_object *json_ar)
d62a17ae 7516{
7517 json_object *json_status = NULL;
7518 json_object *json_net = NULL;
7519 char buff[BUFSIZ];
50e05855 7520 char buf2[BUFSIZ];
d62a17ae 7521 /* Route status display. */
7522 if (use_json) {
7523 json_status = json_object_new_object();
7524 json_net = json_object_new_object();
7525 } else {
7526 vty_out(vty, "*");
7527 vty_out(vty, ">");
7528 vty_out(vty, " ");
7529 }
718e3744 7530
d62a17ae 7531 /* print prefix and mask */
50e05855 7532 if (use_json) {
d62a17ae 7533 json_object_string_add(
7534 json_net, "addrPrefix",
7535 inet_ntop(p->family, &p->u.prefix, buff, BUFSIZ));
50e05855 7536 json_object_int_add(json_net, "prefixLen", p->prefixlen);
37d4e0df 7537 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855
AD
7538 json_object_string_add(json_net, "network", buf2);
7539 } else
9c92b5f7 7540 route_vty_out_route(p, vty, NULL);
d62a17ae 7541
7542 /* Print attribute */
7543 if (attr) {
7544 if (use_json) {
7545 if (p->family == AF_INET
7546 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7547 || safi == SAFI_EVPN
7548 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7549 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7550 || safi == SAFI_EVPN)
7551 json_object_string_add(
7552 json_net, "nextHop",
7553 inet_ntoa(
7554 attr->mp_nexthop_global_in));
7555 else
7556 json_object_string_add(
7557 json_net, "nextHop",
7558 inet_ntoa(attr->nexthop));
7559 } else if (p->family == AF_INET6
7560 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
7561 char buf[BUFSIZ];
7562
7563 json_object_string_add(
aa0a10fc 7564 json_net, "nextHopGlobal",
d62a17ae 7565 inet_ntop(AF_INET6,
7566 &attr->mp_nexthop_global, buf,
7567 BUFSIZ));
7568 }
7569
7570 if (attr->flag
7571 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
7572 json_object_int_add(json_net, "metric",
7573 attr->med);
7574
50e05855
AD
7575 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
7576
7577 /*
7578 * Adding "locPrf" field to match with
7579 * corresponding CLI. "localPref" will be
7580 * deprecated in future.
7581 */
d62a17ae 7582 json_object_int_add(json_net, "localPref",
7583 attr->local_pref);
50e05855
AD
7584 json_object_int_add(json_net, "locPrf",
7585 attr->local_pref);
7586 }
d62a17ae 7587
7588 json_object_int_add(json_net, "weight", attr->weight);
7589
7590 /* Print aspath */
50e05855
AD
7591 if (attr->aspath) {
7592
7593 /*
7594 * Adding "path" field to match with
7595 * corresponding CLI. "localPref" will be
7596 * deprecated in future.
7597 */
d62a17ae 7598 json_object_string_add(json_net, "asPath",
7599 attr->aspath->str);
50e05855
AD
7600 json_object_string_add(json_net, "path",
7601 attr->aspath->str);
7602 }
d62a17ae 7603
7604 /* Print origin */
7605 json_object_string_add(json_net, "bgpOriginCode",
7606 bgp_origin_str[attr->origin]);
7607 } else {
7608 if (p->family == AF_INET
7609 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7610 || safi == SAFI_EVPN
7611 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7612 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7613 || safi == SAFI_EVPN)
7614 vty_out(vty, "%-16s",
7615 inet_ntoa(
7616 attr->mp_nexthop_global_in));
7617 else
7618 vty_out(vty, "%-16s",
7619 inet_ntoa(attr->nexthop));
7620 } else if (p->family == AF_INET6
7621 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
7622 int len;
7623 char buf[BUFSIZ];
7624
7625 len = vty_out(
7626 vty, "%s",
7627 inet_ntop(AF_INET6,
7628 &attr->mp_nexthop_global, buf,
7629 BUFSIZ));
7630 len = 16 - len;
7631 if (len < 1)
7632 vty_out(vty, "\n%*s", 36, " ");
7633 else
7634 vty_out(vty, "%*s", len, " ");
7635 }
7636 if (attr->flag
7637 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
7638 vty_out(vty, "%10u", attr->med);
7639 else
7640 vty_out(vty, " ");
718e3744 7641
d62a17ae 7642 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
7643 vty_out(vty, "%7u", attr->local_pref);
7644 else
7645 vty_out(vty, " ");
7646
7647 vty_out(vty, "%7u ", attr->weight);
7648
7649 /* Print aspath */
7650 if (attr->aspath)
7651 aspath_print_vty(vty, "%s", attr->aspath, " ");
7652
7653 /* Print origin */
7654 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7655 }
7656 }
7657 if (use_json) {
7658 json_object_boolean_true_add(json_status, "*");
7659 json_object_boolean_true_add(json_status, ">");
7660 json_object_object_add(json_net, "appliedStatusSymbols",
7661 json_status);
7662 char buf_cut[BUFSIZ];
1608ff77
SP
7663
7664 prefix2str(p, buf_cut, PREFIX_STRLEN);
7665 json_object_object_add(json_ar, buf_cut, json_net);
d62a17ae 7666 } else
7667 vty_out(vty, "\n");
7668}
7669
7670void route_vty_out_tag(struct vty *vty, struct prefix *p,
9b6d8fcf 7671 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 7672 json_object *json)
7673{
7674 json_object *json_out = NULL;
7675 struct attr *attr;
7676 mpls_label_t label = MPLS_INVALID_LABEL;
7677
9b6d8fcf 7678 if (!path->extra)
d62a17ae 7679 return;
7680
7681 if (json)
7682 json_out = json_object_new_object();
7683
7684 /* short status lead text */
9b6d8fcf 7685 route_vty_short_status_out(vty, path, json_out);
d62a17ae 7686
7687 /* print prefix and mask */
7688 if (json == NULL) {
7689 if (!display)
9c92b5f7 7690 route_vty_out_route(p, vty, NULL);
d62a17ae 7691 else
7692 vty_out(vty, "%*s", 17, " ");
7693 }
7694
7695 /* Print attribute */
9b6d8fcf 7696 attr = path->attr;
d62a17ae 7697 if (attr) {
7698 if (((p->family == AF_INET)
7699 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
a4d82a8a 7700 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
d62a17ae 7701 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7702 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7703 || safi == SAFI_EVPN) {
7704 if (json)
7705 json_object_string_add(
7706 json_out, "mpNexthopGlobalIn",
7707 inet_ntoa(
7708 attr->mp_nexthop_global_in));
7709 else
7710 vty_out(vty, "%-16s",
7711 inet_ntoa(
7712 attr->mp_nexthop_global_in));
7713 } else {
7714 if (json)
7715 json_object_string_add(
7716 json_out, "nexthop",
7717 inet_ntoa(attr->nexthop));
7718 else
7719 vty_out(vty, "%-16s",
7720 inet_ntoa(attr->nexthop));
7721 }
7722 } else if (((p->family == AF_INET6)
7723 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
b03b8898 7724 || (safi == SAFI_EVPN
d62a17ae 7725 && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
7726 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
ff44f570 7727 char buf_a[512];
d62a17ae 7728 if (attr->mp_nexthop_len
7729 == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
7730 if (json)
7731 json_object_string_add(
7732 json_out, "mpNexthopGlobalIn",
7733 inet_ntop(
7734 AF_INET6,
7735 &attr->mp_nexthop_global,
11f9b450 7736 buf_a, sizeof(buf_a)));
d62a17ae 7737 else
7738 vty_out(vty, "%s",
7739 inet_ntop(
7740 AF_INET6,
7741 &attr->mp_nexthop_global,
11f9b450 7742 buf_a, sizeof(buf_a)));
d62a17ae 7743 } else if (attr->mp_nexthop_len
7744 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
899e4095
DL
7745 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
7746 &attr->mp_nexthop_global,
7747 &attr->mp_nexthop_local);
7748 if (json)
d62a17ae 7749 json_object_string_add(
7750 json_out,
899e4095
DL
7751 "mpNexthopGlobalLocal", buf_a);
7752 else
7753 vty_out(vty, "%s", buf_a);
d62a17ae 7754 }
7755 }
7756 }
7757
9b6d8fcf 7758 label = decode_label(&path->extra->label[0]);
d62a17ae 7759
7760 if (bgp_is_valid_label(&label)) {
7761 if (json) {
7762 json_object_int_add(json_out, "notag", label);
7763 json_object_array_add(json, json_out);
7764 } else {
7765 vty_out(vty, "notag/%d", label);
7766 vty_out(vty, "\n");
7767 }
7768 }
7769}
718e3744 7770
d62a17ae 7771void route_vty_out_overlay(struct vty *vty, struct prefix *p,
9b6d8fcf 7772 struct bgp_path_info *path, int display,
d62a17ae 7773 json_object *json_paths)
718e3744 7774{
d62a17ae 7775 struct attr *attr;
14f51eba 7776 char buf[BUFSIZ] = {0};
d62a17ae 7777 json_object *json_path = NULL;
14f51eba
LK
7778 json_object *json_nexthop = NULL;
7779 json_object *json_overlay = NULL;
856ca177 7780
9b6d8fcf 7781 if (!path->extra)
d62a17ae 7782 return;
718e3744 7783
14f51eba
LK
7784 if (json_paths) {
7785 json_path = json_object_new_object();
7786 json_overlay = json_object_new_object();
7787 json_nexthop = json_object_new_object();
7788 }
7789
d62a17ae 7790 /* short status lead text */
9b6d8fcf 7791 route_vty_short_status_out(vty, path, json_path);
856ca177 7792
d62a17ae 7793 /* print prefix and mask */
7794 if (!display)
14f51eba 7795 route_vty_out_route(p, vty, json_path);
d62a17ae 7796 else
7797 vty_out(vty, "%*s", 17, " ");
7798
7799 /* Print attribute */
9b6d8fcf 7800 attr = path->attr;
d62a17ae 7801 if (attr) {
7802 char buf1[BUFSIZ];
7803 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
7804
7805 switch (af) {
7806 case AF_INET:
14f51eba
LK
7807 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
7808 if (!json_path) {
7809 vty_out(vty, "%-16s", buf);
7810 } else {
7811 json_object_string_add(json_nexthop, "ip", buf);
7812
7813 json_object_string_add(json_nexthop, "afi",
7814 "ipv4");
7815
7816 json_object_object_add(json_path, "nexthop",
7817 json_nexthop);
7818 }
d62a17ae 7819 break;
7820 case AF_INET6:
14f51eba
LK
7821 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
7822 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
7823 if (!json_path) {
7824 vty_out(vty, "%s(%s)", buf, buf1);
7825 } else {
7826 json_object_string_add(json_nexthop,
7827 "ipv6Global", buf);
7828
7829 json_object_string_add(json_nexthop,
7830 "ipv6LinkLocal", buf1);
7831
7832 json_object_string_add(json_nexthop, "afi",
7833 "ipv6");
7834
7835 json_object_object_add(json_path, "nexthop",
7836 json_nexthop);
7837 }
d62a17ae 7838 break;
7839 default:
14f51eba
LK
7840 if (!json_path) {
7841 vty_out(vty, "?");
7842 } else {
7843 json_object_string_add(json_nexthop, "Error",
7844 "Unsupported address-family");
7845 }
d62a17ae 7846 }
988258b4
QY
7847
7848 char *str = esi2str(&(attr->evpn_overlay.eth_s_id));
7849
14f51eba
LK
7850 if (!json_path)
7851 vty_out(vty, "%s", str);
7852 else
7853 json_object_string_add(json_overlay, "esi", str);
25b5da8d 7854
988258b4
QY
7855 XFREE(MTYPE_TMP, str);
7856
3714a385 7857 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
14f51eba
LK
7858 inet_ntop(AF_INET, &(attr->evpn_overlay.gw_ip.ipv4),
7859 buf, BUFSIZ);
3714a385 7860 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
14f51eba
LK
7861 inet_ntop(AF_INET6, &(attr->evpn_overlay.gw_ip.ipv6),
7862 buf, BUFSIZ);
988258b4 7863 }
14f51eba
LK
7864
7865 if (!json_path)
7866 vty_out(vty, "/%s", buf);
7867 else
7868 json_object_string_add(json_overlay, "gw", buf);
7869
988258b4
QY
7870 if (attr->ecommunity) {
7871 char *mac = NULL;
7872 struct ecommunity_val *routermac = ecommunity_lookup(
7873 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
7874 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
7875 if (routermac)
7876 mac = ecom_mac2str((char *)routermac->val);
7877 if (mac) {
14f51eba
LK
7878 if (!json_path) {
7879 vty_out(vty, "/%s", (char *)mac);
7880 } else {
7881 json_object_string_add(json_overlay,
7882 "rmac", mac);
7883 }
988258b4
QY
7884 XFREE(MTYPE_TMP, mac);
7885 }
7886 }
718e3744 7887
14f51eba
LK
7888 if (!json_path) {
7889 vty_out(vty, "\n");
7890 } else {
7891 json_object_object_add(json_path, "overlay",
7892 json_overlay);
7893
7894 json_object_array_add(json_paths, json_path);
7895 }
7896 }
d62a17ae 7897}
718e3744 7898
d62a17ae 7899/* dampening route */
7900static void damp_route_vty_out(struct vty *vty, struct prefix *p,
9b6d8fcf 7901 struct bgp_path_info *path, int display,
4b7e6066 7902 safi_t safi, bool use_json, json_object *json)
d62a17ae 7903{
7904 struct attr *attr;
7905 int len;
7906 char timebuf[BGP_UPTIME_LEN];
7907
7908 /* short status lead text */
9b6d8fcf 7909 route_vty_short_status_out(vty, path, json);
d62a17ae 7910
7911 /* print prefix and mask */
7912 if (!use_json) {
7913 if (!display)
9c92b5f7 7914 route_vty_out_route(p, vty, NULL);
d62a17ae 7915 else
7916 vty_out(vty, "%*s", 17, " ");
7917 }
7918
9b6d8fcf 7919 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 7920 len = 17 - len;
7921 if (len < 1) {
7922 if (!use_json)
7923 vty_out(vty, "\n%*s", 34, " ");
7924 } else {
7925 if (use_json)
7926 json_object_int_add(json, "peerHost", len);
7927 else
7928 vty_out(vty, "%*s", len, " ");
7929 }
7930
7931 if (use_json)
9b6d8fcf 7932 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN,
d62a17ae 7933 use_json, json);
7934 else
9b6d8fcf
DS
7935 vty_out(vty, "%s ",
7936 bgp_damp_reuse_time_vty(vty, path, timebuf,
7937 BGP_UPTIME_LEN, use_json,
7938 json));
d62a17ae 7939
7940 /* Print attribute */
9b6d8fcf 7941 attr = path->attr;
d62a17ae 7942 if (attr) {
7943 /* Print aspath */
7944 if (attr->aspath) {
7945 if (use_json)
7946 json_object_string_add(json, "asPath",
7947 attr->aspath->str);
7948 else
7949 aspath_print_vty(vty, "%s", attr->aspath, " ");
7950 }
7951
7952 /* Print origin */
7953 if (use_json)
7954 json_object_string_add(json, "origin",
7955 bgp_origin_str[attr->origin]);
7956 else
7957 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7958 }
7959 if (!use_json)
7960 vty_out(vty, "\n");
7961}
718e3744 7962
d62a17ae 7963/* flap route */
7964static void flap_route_vty_out(struct vty *vty, struct prefix *p,
9b6d8fcf 7965 struct bgp_path_info *path, int display,
4b7e6066 7966 safi_t safi, bool use_json, json_object *json)
784d3a42 7967{
d62a17ae 7968 struct attr *attr;
7969 struct bgp_damp_info *bdi;
7970 char timebuf[BGP_UPTIME_LEN];
7971 int len;
784d3a42 7972
9b6d8fcf 7973 if (!path->extra)
d62a17ae 7974 return;
784d3a42 7975
9b6d8fcf 7976 bdi = path->extra->damp_info;
784d3a42 7977
d62a17ae 7978 /* short status lead text */
9b6d8fcf 7979 route_vty_short_status_out(vty, path, json);
784d3a42 7980
d62a17ae 7981 /* print prefix and mask */
7982 if (!use_json) {
7983 if (!display)
9c92b5f7 7984 route_vty_out_route(p, vty, NULL);
d62a17ae 7985 else
7986 vty_out(vty, "%*s", 17, " ");
7987 }
784d3a42 7988
9b6d8fcf 7989 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 7990 len = 16 - len;
7991 if (len < 1) {
7992 if (!use_json)
7993 vty_out(vty, "\n%*s", 33, " ");
7994 } else {
7995 if (use_json)
7996 json_object_int_add(json, "peerHost", len);
7997 else
7998 vty_out(vty, "%*s", len, " ");
7999 }
784d3a42 8000
d62a17ae 8001 len = vty_out(vty, "%d", bdi->flap);
8002 len = 5 - len;
8003 if (len < 1) {
8004 if (!use_json)
8005 vty_out(vty, " ");
8006 } else {
8007 if (use_json)
8008 json_object_int_add(json, "bdiFlap", len);
8009 else
8010 vty_out(vty, "%*s", len, " ");
8011 }
8012
8013 if (use_json)
8014 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
8015 json);
8016 else
996c9314
LB
8017 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
8018 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 8019
9b6d8fcf
DS
8020 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
8021 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 8022 if (use_json)
9b6d8fcf 8023 bgp_damp_reuse_time_vty(vty, path, timebuf,
d62a17ae 8024 BGP_UPTIME_LEN, use_json, json);
8025 else
8026 vty_out(vty, "%s ",
9b6d8fcf 8027 bgp_damp_reuse_time_vty(vty, path, timebuf,
d62a17ae 8028 BGP_UPTIME_LEN,
8029 use_json, json));
8030 } else {
8031 if (!use_json)
8032 vty_out(vty, "%*s ", 8, " ");
8033 }
8034
8035 /* Print attribute */
9b6d8fcf 8036 attr = path->attr;
d62a17ae 8037 if (attr) {
8038 /* Print aspath */
8039 if (attr->aspath) {
8040 if (use_json)
8041 json_object_string_add(json, "asPath",
8042 attr->aspath->str);
8043 else
8044 aspath_print_vty(vty, "%s", attr->aspath, " ");
8045 }
8046
8047 /* Print origin */
8048 if (use_json)
8049 json_object_string_add(json, "origin",
8050 bgp_origin_str[attr->origin]);
8051 else
8052 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8053 }
8054 if (!use_json)
8055 vty_out(vty, "\n");
8056}
8057
8058static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
8059 int *first, const char *header,
8060 json_object *json_adv_to)
8061{
8062 char buf1[INET6_ADDRSTRLEN];
8063 json_object *json_peer = NULL;
8064
8065 if (json_adv_to) {
8066 /* 'advertised-to' is a dictionary of peers we have advertised
8067 * this
8068 * prefix too. The key is the peer's IP or swpX, the value is
8069 * the
8070 * hostname if we know it and "" if not.
8071 */
8072 json_peer = json_object_new_object();
8073
8074 if (peer->hostname)
8075 json_object_string_add(json_peer, "hostname",
8076 peer->hostname);
8077
8078 if (peer->conf_if)
8079 json_object_object_add(json_adv_to, peer->conf_if,
8080 json_peer);
8081 else
8082 json_object_object_add(
8083 json_adv_to,
8084 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
8085 json_peer);
8086 } else {
8087 if (*first) {
8088 vty_out(vty, "%s", header);
8089 *first = 0;
8090 }
8091
8092 if (peer->hostname
8093 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
8094 if (peer->conf_if)
8095 vty_out(vty, " %s(%s)", peer->hostname,
8096 peer->conf_if);
8097 else
8098 vty_out(vty, " %s(%s)", peer->hostname,
8099 sockunion2str(&peer->su, buf1,
8100 SU_ADDRSTRLEN));
8101 } else {
8102 if (peer->conf_if)
8103 vty_out(vty, " %s", peer->conf_if);
8104 else
8105 vty_out(vty, " %s",
8106 sockunion2str(&peer->su, buf1,
8107 SU_ADDRSTRLEN));
8108 }
8109 }
784d3a42
PG
8110}
8111
dcc68b5e
MS
8112static void route_vty_out_tx_ids(struct vty *vty,
8113 struct bgp_addpath_info_data *d)
8114{
8115 int i;
8116
8117 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
8118 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
8119 d->addpath_tx_id[i],
8120 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
8121 }
8122}
8123
0dc8ee70
DS
8124static const char *bgp_path_selection_reason2str(
8125 enum bgp_path_selection_reason reason)
8126{
8127 switch (reason) {
8128 case bgp_path_selection_none:
8129 return "Nothing to Select";
8130 break;
8131 case bgp_path_selection_first:
8132 return "First path received";
8133 break;
8134 case bgp_path_selection_evpn_sticky_mac:
8135 return "EVPN Sticky Mac";
8136 break;
8137 case bgp_path_selection_evpn_seq:
8138 return "EVPN sequence number";
8139 break;
8140 case bgp_path_selection_evpn_lower_ip:
8141 return "EVPN lower IP";
8142 break;
8143 case bgp_path_selection_weight:
8144 return "Weight";
8145 break;
8146 case bgp_path_selection_local_pref:
8147 return "Local Pref";
8148 break;
8149 case bgp_path_selection_local_route:
8150 return "Local Route";
8151 break;
8152 case bgp_path_selection_confed_as_path:
8153 return "Confederation based AS Path";
8154 break;
8155 case bgp_path_selection_as_path:
8156 return "AS Path";
8157 break;
8158 case bgp_path_selection_origin:
8159 return "Origin";
8160 break;
8161 case bgp_path_selection_med:
8162 return "MED";
8163 break;
8164 case bgp_path_selection_peer:
8165 return "Peer Type";
8166 break;
8167 case bgp_path_selection_confed:
8168 return "Confed Peer Type";
8169 break;
8170 case bgp_path_selection_igp_metric:
8171 return "IGP Metric";
8172 break;
8173 case bgp_path_selection_older:
8174 return "Older Path";
8175 break;
8176 case bgp_path_selection_router_id:
8177 return "Router ID";
8178 break;
8179 case bgp_path_selection_cluster_length:
8180 return "Cluser length";
8181 break;
8182 case bgp_path_selection_stale:
8183 return "Path Staleness";
8184 break;
8185 case bgp_path_selection_local_configured:
8186 return "Locally configured route";
8187 break;
8188 case bgp_path_selection_neighbor_ip:
8189 return "Neighbor IP";
8190 break;
8191 case bgp_path_selection_default:
8192 return "Nothing left to compare";
8193 break;
8194 }
a74879b2 8195 return "Invalid (internal error)";
0dc8ee70
DS
8196}
8197
f08b5ca0
DS
8198void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
8199 struct bgp_node *bn, struct bgp_path_info *path,
8200 afi_t afi, safi_t safi, json_object *json_paths)
d62a17ae 8201{
8202 char buf[INET6_ADDRSTRLEN];
8203 char buf1[BUFSIZ];
d62a17ae 8204 char buf2[EVPN_ROUTE_STRLEN];
d62a17ae 8205 struct attr *attr;
8206 int sockunion_vty_out(struct vty *, union sockunion *);
8207 time_t tbuf;
8208 json_object *json_bestpath = NULL;
8209 json_object *json_cluster_list = NULL;
8210 json_object *json_cluster_list_list = NULL;
8211 json_object *json_ext_community = NULL;
8212 json_object *json_last_update = NULL;
7fd077aa 8213 json_object *json_pmsi = NULL;
d62a17ae 8214 json_object *json_nexthop_global = NULL;
8215 json_object *json_nexthop_ll = NULL;
8216 json_object *json_nexthops = NULL;
8217 json_object *json_path = NULL;
8218 json_object *json_peer = NULL;
8219 json_object *json_string = NULL;
8220 json_object *json_adv_to = NULL;
8221 int first = 0;
8222 struct listnode *node, *nnode;
8223 struct peer *peer;
8224 int addpath_capable;
8225 int has_adj;
8226 unsigned int first_as;
1defdda8 8227 bool nexthop_self =
9b6d8fcf 8228 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 8229 int i;
25b5da8d 8230 char *nexthop_fqdn = bgp_nexthop_fqdn(path->peer);
d62a17ae 8231
8232 if (json_paths) {
8233 json_path = json_object_new_object();
8234 json_peer = json_object_new_object();
8235 json_nexthop_global = json_object_new_object();
8236 }
8237
44c69747 8238 if (path->extra) {
b57ba6d2 8239 char tag_buf[30];
d62a17ae 8240
d7325ee7 8241 buf2[0] = '\0';
d62a17ae 8242 tag_buf[0] = '\0';
9b6d8fcf
DS
8243 if (path->extra && path->extra->num_labels) {
8244 bgp_evpn_label2str(path->extra->label,
8245 path->extra->num_labels, tag_buf,
a4d82a8a 8246 sizeof(tag_buf));
d62a17ae 8247 }
d7325ee7 8248 if (safi == SAFI_EVPN) {
44c69747
LK
8249 if (!json_paths) {
8250 bgp_evpn_route2str((struct prefix_evpn *)&bn->p,
8251 buf2, sizeof(buf2));
8252 vty_out(vty, " Route %s", buf2);
8253 if (tag_buf[0] != '\0')
8254 vty_out(vty, " VNI %s", tag_buf);
8255 vty_out(vty, "\n");
8256 } else {
8257 if (tag_buf[0])
8258 json_object_string_add(json_path, "VNI",
8259 tag_buf);
8260 }
d7325ee7
DD
8261 }
8262
44c69747 8263 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 8264 struct bgp_path_info *parent_ri;
d62a17ae 8265 struct bgp_node *rn, *prn;
8266
9b6d8fcf 8267 parent_ri = (struct bgp_path_info *)path->extra->parent;
d62a17ae 8268 rn = parent_ri->net;
8269 if (rn && rn->prn) {
8270 prn = rn->prn;
d7325ee7
DD
8271 prefix_rd2str((struct prefix_rd *)&prn->p,
8272 buf1, sizeof(buf1));
8273 if (is_pi_family_evpn(parent_ri)) {
8274 bgp_evpn_route2str((struct prefix_evpn *)&rn->p,
8275 buf2, sizeof(buf2));
8276 vty_out(vty, " Imported from %s:%s, VNI %s\n", buf1, buf2, tag_buf);
8277 } else
8278 vty_out(vty, " Imported from %s:%s\n", buf1, buf2);
d62a17ae 8279 }
8280 }
8281 }
d62a17ae 8282
9b6d8fcf 8283 attr = path->attr;
d62a17ae 8284
8285 if (attr) {
8286 /* Line1 display AS-path, Aggregator */
8287 if (attr->aspath) {
8288 if (json_paths) {
68e1a55b
DS
8289 if (!attr->aspath->json)
8290 aspath_str_update(attr->aspath, true);
d62a17ae 8291 json_object_lock(attr->aspath->json);
8292 json_object_object_add(json_path, "aspath",
8293 attr->aspath->json);
8294 } else {
8295 if (attr->aspath->segments)
8296 aspath_print_vty(vty, " %s",
8297 attr->aspath, "");
8298 else
8299 vty_out(vty, " Local");
8300 }
8301 }
8302
9b6d8fcf 8303 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
d62a17ae 8304 if (json_paths)
8305 json_object_boolean_true_add(json_path,
8306 "removed");
8307 else
8308 vty_out(vty, ", (removed)");
8309 }
8310
9b6d8fcf 8311 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
d62a17ae 8312 if (json_paths)
8313 json_object_boolean_true_add(json_path,
8314 "stale");
8315 else
8316 vty_out(vty, ", (stale)");
8317 }
8318
8319 if (CHECK_FLAG(attr->flag,
8320 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
8321 if (json_paths) {
8322 json_object_int_add(json_path, "aggregatorAs",
8323 attr->aggregator_as);
8324 json_object_string_add(
8325 json_path, "aggregatorId",
8326 inet_ntoa(attr->aggregator_addr));
8327 } else {
8328 vty_out(vty, ", (aggregated by %u %s)",
8329 attr->aggregator_as,
8330 inet_ntoa(attr->aggregator_addr));
8331 }
8332 }
8333
9b6d8fcf 8334 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
d62a17ae 8335 PEER_FLAG_REFLECTOR_CLIENT)) {
8336 if (json_paths)
8337 json_object_boolean_true_add(
8338 json_path, "rxedFromRrClient");
8339 else
8340 vty_out(vty, ", (Received from a RR-client)");
8341 }
8342
9b6d8fcf 8343 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
d62a17ae 8344 PEER_FLAG_RSERVER_CLIENT)) {
8345 if (json_paths)
8346 json_object_boolean_true_add(
8347 json_path, "rxedFromRsClient");
8348 else
8349 vty_out(vty, ", (Received from a RS-client)");
8350 }
8351
9b6d8fcf 8352 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 8353 if (json_paths)
8354 json_object_boolean_true_add(
8355 json_path, "dampeningHistoryEntry");
8356 else
8357 vty_out(vty, ", (history entry)");
9b6d8fcf 8358 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
d62a17ae 8359 if (json_paths)
8360 json_object_boolean_true_add(
8361 json_path, "dampeningSuppressed");
8362 else
8363 vty_out(vty, ", (suppressed due to dampening)");
8364 }
8365
8366 if (!json_paths)
8367 vty_out(vty, "\n");
8368
8369 /* Line2 display Next-hop, Neighbor, Router-id */
8370 /* Display the nexthop */
f08b5ca0
DS
8371 if ((bn->p.family == AF_INET || bn->p.family == AF_ETHERNET
8372 || bn->p.family == AF_EVPN)
d62a17ae 8373 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8374 || safi == SAFI_EVPN
8375 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8376 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8377 || safi == SAFI_EVPN) {
8378 if (json_paths)
8379 json_object_string_add(
25b5da8d
DA
8380 json_nexthop_global,
8381 nexthop_fqdn ? "fqdn" : "ip",
8382 nexthop_fqdn
8383 ? nexthop_fqdn
8384 : inet_ntoa(
8385 attr->mp_nexthop_global_in));
d62a17ae 8386 else
8387 vty_out(vty, " %s",
25b5da8d
DA
8388 nexthop_fqdn
8389 ? nexthop_fqdn
8390 : inet_ntoa(
8391 attr->mp_nexthop_global_in));
d62a17ae 8392 } else {
8393 if (json_paths)
8394 json_object_string_add(
25b5da8d
DA
8395 json_nexthop_global,
8396 nexthop_fqdn ? "fqdn" : "ip",
8397 nexthop_fqdn
8398 ? nexthop_fqdn
8399 : inet_ntoa(
8400 attr->nexthop));
d62a17ae 8401 else
8402 vty_out(vty, " %s",
25b5da8d
DA
8403 nexthop_fqdn
8404 ? nexthop_fqdn
8405 : inet_ntoa(
8406 attr->nexthop));
d62a17ae 8407 }
8408
8409 if (json_paths)
8410 json_object_string_add(json_nexthop_global,
8411 "afi", "ipv4");
8412 } else {
8413 if (json_paths) {
8414 json_object_string_add(
25b5da8d
DA
8415 json_nexthop_global,
8416 nexthop_fqdn ? "fqdn" : "ip",
8417 nexthop_fqdn
8418 ? nexthop_fqdn
8419 : inet_ntop(
8420 AF_INET6,
8421 &attr->mp_nexthop_global,
8422 buf,
8423 INET6_ADDRSTRLEN));
d62a17ae 8424 json_object_string_add(json_nexthop_global,
8425 "afi", "ipv6");
8426 json_object_string_add(json_nexthop_global,
8427 "scope", "global");
8428 } else {
8429 vty_out(vty, " %s",
25b5da8d
DA
8430 nexthop_fqdn
8431 ? nexthop_fqdn
8432 : inet_ntop(
8433 AF_INET6,
8434 &attr->mp_nexthop_global,
8435 buf,
8436 INET6_ADDRSTRLEN));
d62a17ae 8437 }
8438 }
8439
8440 /* Display the IGP cost or 'inaccessible' */
9b6d8fcf 8441 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
d62a17ae 8442 if (json_paths)
8443 json_object_boolean_false_add(
8444 json_nexthop_global, "accessible");
8445 else
8446 vty_out(vty, " (inaccessible)");
8447 } else {
9b6d8fcf 8448 if (path->extra && path->extra->igpmetric) {
d62a17ae 8449 if (json_paths)
8450 json_object_int_add(
8451 json_nexthop_global, "metric",
9b6d8fcf 8452 path->extra->igpmetric);
d62a17ae 8453 else
8454 vty_out(vty, " (metric %u)",
9b6d8fcf 8455 path->extra->igpmetric);
d62a17ae 8456 }
8457
8458 /* IGP cost is 0, display this only for json */
8459 else {
8460 if (json_paths)
8461 json_object_int_add(json_nexthop_global,
8462 "metric", 0);
8463 }
8464
8465 if (json_paths)
8466 json_object_boolean_true_add(
8467 json_nexthop_global, "accessible");
8468 }
8469
8470 /* Display peer "from" output */
8471 /* This path was originated locally */
9b6d8fcf 8472 if (path->peer == bgp->peer_self) {
d62a17ae 8473
8474 if (safi == SAFI_EVPN
f08b5ca0 8475 || (bn->p.family == AF_INET
d62a17ae 8476 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8477 if (json_paths)
8478 json_object_string_add(
8479 json_peer, "peerId", "0.0.0.0");
8480 else
8481 vty_out(vty, " from 0.0.0.0 ");
8482 } else {
8483 if (json_paths)
8484 json_object_string_add(json_peer,
8485 "peerId", "::");
8486 else
8487 vty_out(vty, " from :: ");
8488 }
8489
8490 if (json_paths)
8491 json_object_string_add(
8492 json_peer, "routerId",
8493 inet_ntoa(bgp->router_id));
8494 else
8495 vty_out(vty, "(%s)", inet_ntoa(bgp->router_id));
8496 }
8497
8498 /* We RXed this path from one of our peers */
8499 else {
8500
8501 if (json_paths) {
8502 json_object_string_add(
8503 json_peer, "peerId",
9b6d8fcf 8504 sockunion2str(&path->peer->su, buf,
d62a17ae 8505 SU_ADDRSTRLEN));
8506 json_object_string_add(
8507 json_peer, "routerId",
8508 inet_ntop(AF_INET,
9b6d8fcf 8509 &path->peer->remote_id, buf1,
06b9f471 8510 sizeof(buf1)));
d62a17ae 8511
9b6d8fcf 8512 if (path->peer->hostname)
d62a17ae 8513 json_object_string_add(
8514 json_peer, "hostname",
9b6d8fcf 8515 path->peer->hostname);
d62a17ae 8516
9b6d8fcf 8517 if (path->peer->domainname)
d62a17ae 8518 json_object_string_add(
8519 json_peer, "domainname",
9b6d8fcf 8520 path->peer->domainname);
d62a17ae 8521
9b6d8fcf 8522 if (path->peer->conf_if)
d62a17ae 8523 json_object_string_add(
8524 json_peer, "interface",
9b6d8fcf 8525 path->peer->conf_if);
d62a17ae 8526 } else {
9b6d8fcf
DS
8527 if (path->peer->conf_if) {
8528 if (path->peer->hostname
d62a17ae 8529 && bgp_flag_check(
9b6d8fcf 8530 path->peer->bgp,
d62a17ae 8531 BGP_FLAG_SHOW_HOSTNAME))
8532 vty_out(vty, " from %s(%s)",
9b6d8fcf
DS
8533 path->peer->hostname,
8534 path->peer->conf_if);
d62a17ae 8535 else
8536 vty_out(vty, " from %s",
9b6d8fcf 8537 path->peer->conf_if);
d62a17ae 8538 } else {
9b6d8fcf 8539 if (path->peer->hostname
d62a17ae 8540 && bgp_flag_check(
9b6d8fcf 8541 path->peer->bgp,
d62a17ae 8542 BGP_FLAG_SHOW_HOSTNAME))
8543 vty_out(vty, " from %s(%s)",
9b6d8fcf
DS
8544 path->peer->hostname,
8545 path->peer->host);
d62a17ae 8546 else
8547 vty_out(vty, " from %s",
8548 sockunion2str(
9b6d8fcf 8549 &path->peer->su,
d62a17ae 8550 buf,
8551 SU_ADDRSTRLEN));
8552 }
8553
8554 if (attr->flag
8555 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
8556 vty_out(vty, " (%s)",
8557 inet_ntoa(attr->originator_id));
8558 else
8559 vty_out(vty, " (%s)",
8560 inet_ntop(
8561 AF_INET,
9b6d8fcf 8562 &path->peer->remote_id,
06b9f471 8563 buf1, sizeof(buf1)));
d62a17ae 8564 }
8565 }
8566
9df8b37c
PZ
8567 /*
8568 * Note when vrfid of nexthop is different from that of prefix
8569 */
9b6d8fcf
DS
8570 if (path->extra && path->extra->bgp_orig) {
8571 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c
PZ
8572
8573 if (json_paths) {
8574 const char *vn;
8575
9b6d8fcf
DS
8576 if (path->extra->bgp_orig->inst_type
8577 == BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8578
03a6facf 8579 vn = VRF_DEFAULT_NAME;
9df8b37c 8580 else
9b6d8fcf 8581 vn = path->extra->bgp_orig->name;
9df8b37c
PZ
8582
8583 json_object_string_add(json_path, "nhVrfName",
8584 vn);
8585
8586 if (nexthop_vrfid == VRF_UNKNOWN) {
8587 json_object_int_add(json_path,
8588 "nhVrfId", -1);
8589 } else {
8590 json_object_int_add(json_path,
8591 "nhVrfId", (int)nexthop_vrfid);
8592 }
8593 } else {
8594 if (nexthop_vrfid == VRF_UNKNOWN)
8595 vty_out(vty, " vrf ?");
8596 else
8597 vty_out(vty, " vrf %u", nexthop_vrfid);
8598 }
8599 }
8600
8601 if (nexthop_self) {
8602 if (json_paths) {
8603 json_object_boolean_true_add(json_path,
8604 "announceNexthopSelf");
8605 } else {
8606 vty_out(vty, " announce-nh-self");
8607 }
8608 }
8609
d62a17ae 8610 if (!json_paths)
8611 vty_out(vty, "\n");
8612
8613 /* display the link-local nexthop */
8614 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
8615 if (json_paths) {
8616 json_nexthop_ll = json_object_new_object();
8617 json_object_string_add(
25b5da8d
DA
8618 json_nexthop_ll,
8619 nexthop_fqdn ? "fqdn" : "ip",
8620 nexthop_fqdn
8621 ? nexthop_fqdn
8622 : inet_ntop(
8623 AF_INET6,
8624 &attr->mp_nexthop_local,
8625 buf,
8626 INET6_ADDRSTRLEN));
d62a17ae 8627 json_object_string_add(json_nexthop_ll, "afi",
8628 "ipv6");
8629 json_object_string_add(json_nexthop_ll, "scope",
8630 "link-local");
8631
8632 json_object_boolean_true_add(json_nexthop_ll,
8633 "accessible");
8634
8635 if (!attr->mp_nexthop_prefer_global)
8636 json_object_boolean_true_add(
8637 json_nexthop_ll, "used");
8638 else
8639 json_object_boolean_true_add(
8640 json_nexthop_global, "used");
8641 } else {
8642 vty_out(vty, " (%s) %s\n",
8643 inet_ntop(AF_INET6,
8644 &attr->mp_nexthop_local, buf,
8645 INET6_ADDRSTRLEN),
8646 attr->mp_nexthop_prefer_global
8647 ? "(prefer-global)"
8648 : "(used)");
8649 }
8650 }
8651 /* If we do not have a link-local nexthop then we must flag the
8652 global as "used" */
8653 else {
8654 if (json_paths)
8655 json_object_boolean_true_add(
8656 json_nexthop_global, "used");
8657 }
718e3744 8658
d62a17ae 8659 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8660 * Int/Ext/Local, Atomic, best */
8661 if (json_paths)
8662 json_object_string_add(
8663 json_path, "origin",
8664 bgp_origin_long_str[attr->origin]);
8665 else
8666 vty_out(vty, " Origin %s",
8667 bgp_origin_long_str[attr->origin]);
8668
8669 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
50e05855
AD
8670 if (json_paths) {
8671
8672 /*
8673 * Adding "metric" field to match with
8674 * corresponding CLI. "med" will be
8675 * deprecated in future.
8676 */
d62a17ae 8677 json_object_int_add(json_path, "med",
8678 attr->med);
50e05855
AD
8679 json_object_int_add(json_path, "metric",
8680 attr->med);
8681 } else
d62a17ae 8682 vty_out(vty, ", metric %u", attr->med);
8683 }
718e3744 8684
d62a17ae 8685 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
8686 if (json_paths)
8687 json_object_int_add(json_path, "localpref",
8688 attr->local_pref);
8689 else
8690 vty_out(vty, ", localpref %u",
8691 attr->local_pref);
d62a17ae 8692 }
718e3744 8693
d62a17ae 8694 if (attr->weight != 0) {
8695 if (json_paths)
8696 json_object_int_add(json_path, "weight",
8697 attr->weight);
8698 else
8699 vty_out(vty, ", weight %u", attr->weight);
8700 }
718e3744 8701
d62a17ae 8702 if (attr->tag != 0) {
8703 if (json_paths)
8704 json_object_int_add(json_path, "tag",
8705 attr->tag);
8706 else
8707 vty_out(vty, ", tag %" ROUTE_TAG_PRI,
8708 attr->tag);
8709 }
718e3744 8710
9b6d8fcf 8711 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
d62a17ae 8712 if (json_paths)
8713 json_object_boolean_false_add(json_path,
8714 "valid");
8715 else
8716 vty_out(vty, ", invalid");
9b6d8fcf 8717 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 8718 if (json_paths)
8719 json_object_boolean_true_add(json_path,
8720 "valid");
8721 else
8722 vty_out(vty, ", valid");
8723 }
718e3744 8724
9b6d8fcf
DS
8725 if (path->peer != bgp->peer_self) {
8726 if (path->peer->as == path->peer->local_as) {
d62a17ae 8727 if (CHECK_FLAG(bgp->config,
8728 BGP_CONFIG_CONFEDERATION)) {
8729 if (json_paths)
8730 json_object_string_add(
8731 json_peer, "type",
8732 "confed-internal");
8733 else
8734 vty_out(vty,
8735 ", confed-internal");
8736 } else {
8737 if (json_paths)
8738 json_object_string_add(
8739 json_peer, "type",
8740 "internal");
8741 else
8742 vty_out(vty, ", internal");
8743 }
8744 } else {
8745 if (bgp_confederation_peers_check(
9b6d8fcf 8746 bgp, path->peer->as)) {
d62a17ae 8747 if (json_paths)
8748 json_object_string_add(
8749 json_peer, "type",
8750 "confed-external");
8751 else
8752 vty_out(vty,
8753 ", confed-external");
8754 } else {
8755 if (json_paths)
8756 json_object_string_add(
8757 json_peer, "type",
8758 "external");
8759 else
8760 vty_out(vty, ", external");
8761 }
8762 }
9b6d8fcf 8763 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
d62a17ae 8764 if (json_paths) {
8765 json_object_boolean_true_add(json_path,
8766 "aggregated");
8767 json_object_boolean_true_add(json_path,
8768 "local");
8769 } else {
8770 vty_out(vty, ", aggregated, local");
8771 }
9b6d8fcf 8772 } else if (path->type != ZEBRA_ROUTE_BGP) {
d62a17ae 8773 if (json_paths)
8774 json_object_boolean_true_add(json_path,
8775 "sourced");
8776 else
8777 vty_out(vty, ", sourced");
8778 } else {
8779 if (json_paths) {
8780 json_object_boolean_true_add(json_path,
8781 "sourced");
8782 json_object_boolean_true_add(json_path,
8783 "local");
8784 } else {
8785 vty_out(vty, ", sourced, local");
8786 }
8787 }
718e3744 8788
d62a17ae 8789 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
8790 if (json_paths)
8791 json_object_boolean_true_add(json_path,
8792 "atomicAggregate");
8793 else
8794 vty_out(vty, ", atomic-aggregate");
8795 }
718e3744 8796
9b6d8fcf
DS
8797 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
8798 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
8799 && bgp_path_info_mpath_count(path))) {
d62a17ae 8800 if (json_paths)
8801 json_object_boolean_true_add(json_path,
8802 "multipath");
8803 else
8804 vty_out(vty, ", multipath");
8805 }
856ca177 8806
d62a17ae 8807 // Mark the bestpath(s)
9b6d8fcf 8808 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
d62a17ae 8809 first_as = aspath_get_first_as(attr->aspath);
8810
8811 if (json_paths) {
8812 if (!json_bestpath)
8813 json_bestpath =
8814 json_object_new_object();
8815 json_object_int_add(json_bestpath,
8816 "bestpathFromAs", first_as);
8817 } else {
8818 if (first_as)
fb2b0934 8819 vty_out(vty, ", bestpath-from-AS %u",
d62a17ae 8820 first_as);
8821 else
8822 vty_out(vty,
8823 ", bestpath-from-AS Local");
8824 }
8825 }
718e3744 8826
9b6d8fcf 8827 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8828 if (json_paths) {
8829 if (!json_bestpath)
8830 json_bestpath =
8831 json_object_new_object();
8832 json_object_boolean_true_add(json_bestpath,
8833 "overall");
0dc8ee70
DS
8834 json_object_string_add(json_bestpath,
8835 "selectionReason",
8836 bgp_path_selection_reason2str(bn->reason));
8837 } else {
d62a17ae 8838 vty_out(vty, ", best");
0dc8ee70
DS
8839 vty_out(vty, " (%s)",
8840 bgp_path_selection_reason2str(bn->reason));
8841 }
d62a17ae 8842 }
718e3744 8843
d62a17ae 8844 if (json_bestpath)
8845 json_object_object_add(json_path, "bestpath",
8846 json_bestpath);
8847
8848 if (!json_paths)
8849 vty_out(vty, "\n");
8850
8851 /* Line 4 display Community */
8852 if (attr->community) {
8853 if (json_paths) {
a69ea8ae 8854 if (!attr->community->json)
a4d82a8a 8855 community_str(attr->community, true);
d62a17ae 8856 json_object_lock(attr->community->json);
8857 json_object_object_add(json_path, "community",
8858 attr->community->json);
8859 } else {
8860 vty_out(vty, " Community: %s\n",
8861 attr->community->str);
8862 }
8863 }
718e3744 8864
d62a17ae 8865 /* Line 5 display Extended-community */
8866 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8867 if (json_paths) {
8868 json_ext_community = json_object_new_object();
8869 json_object_string_add(json_ext_community,
8870 "string",
8871 attr->ecommunity->str);
8872 json_object_object_add(json_path,
8873 "extendedCommunity",
8874 json_ext_community);
8875 } else {
8876 vty_out(vty, " Extended Community: %s\n",
8877 attr->ecommunity->str);
8878 }
8879 }
adbac85e 8880
d62a17ae 8881 /* Line 6 display Large community */
b96879c0
DS
8882 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
8883 if (json_paths) {
8d9b8ed9
PM
8884 if (!attr->lcommunity->json)
8885 lcommunity_str(attr->lcommunity, true);
8886 json_object_lock(attr->lcommunity->json);
b96879c0
DS
8887 json_object_object_add(json_path,
8888 "largeCommunity",
8d9b8ed9 8889 attr->lcommunity->json);
b96879c0
DS
8890 } else {
8891 vty_out(vty, " Large Community: %s\n",
8892 attr->lcommunity->str);
8893 }
8894 }
d62a17ae 8895
8896 /* Line 7 display Originator, Cluster-id */
8897 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
8898 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
8899 if (attr->flag
8900 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
8901 if (json_paths)
8902 json_object_string_add(
8903 json_path, "originatorId",
8904 inet_ntoa(attr->originator_id));
8905 else
8906 vty_out(vty, " Originator: %s",
8907 inet_ntoa(attr->originator_id));
8908 }
8909
8910 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
8911 int i;
8912
8913 if (json_paths) {
8914 json_cluster_list =
8915 json_object_new_object();
8916 json_cluster_list_list =
8917 json_object_new_array();
8918
8919 for (i = 0;
8920 i < attr->cluster->length / 4;
8921 i++) {
8922 json_string = json_object_new_string(
8923 inet_ntoa(
8924 attr->cluster->list
8925 [i]));
8926 json_object_array_add(
8927 json_cluster_list_list,
8928 json_string);
8929 }
8930
8931 /* struct cluster_list does not have
8932 "str" variable like
8933 * aspath and community do. Add this
8934 someday if someone
8935 * asks for it.
8936 json_object_string_add(json_cluster_list,
8937 "string", attr->cluster->str);
8938 */
8939 json_object_object_add(
8940 json_cluster_list, "list",
8941 json_cluster_list_list);
8942 json_object_object_add(
8943 json_path, "clusterList",
8944 json_cluster_list);
8945 } else {
8946 vty_out(vty, ", Cluster list: ");
8947
8948 for (i = 0;
8949 i < attr->cluster->length / 4;
8950 i++) {
8951 vty_out(vty, "%s ",
8952 inet_ntoa(
8953 attr->cluster->list
8954 [i]));
8955 }
8956 }
8957 }
8958
8959 if (!json_paths)
8960 vty_out(vty, "\n");
8961 }
adbac85e 8962
9b6d8fcf
DS
8963 if (path->extra && path->extra->damp_info)
8964 bgp_damp_info_vty(vty, path, json_path);
d62a17ae 8965
6a527b2f 8966 /* Remote Label */
9b6d8fcf 8967 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
6a527b2f 8968 && safi != SAFI_EVPN) {
9b6d8fcf 8969 mpls_label_t label = label_pton(&path->extra->label[0]);
121e245d 8970
d62a17ae 8971 if (json_paths)
8972 json_object_int_add(json_path, "remoteLabel",
8973 label);
8974 else
8975 vty_out(vty, " Remote label: %d\n", label);
8976 }
b05a1c8b 8977
d62a17ae 8978 /* Label Index */
8979 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
8980 if (json_paths)
8981 json_object_int_add(json_path, "labelIndex",
8982 attr->label_index);
8983 else
8984 vty_out(vty, " Label Index: %d\n",
8985 attr->label_index);
8986 }
520d5d76 8987
d62a17ae 8988 /* Line 8 display Addpath IDs */
dcc68b5e
MS
8989 if (path->addpath_rx_id
8990 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
d62a17ae 8991 if (json_paths) {
8992 json_object_int_add(json_path, "addpathRxId",
9b6d8fcf 8993 path->addpath_rx_id);
dcc68b5e
MS
8994
8995 /* Keep backwards compatibility with the old API
8996 * by putting TX All's ID in the old field
8997 */
8998 json_object_int_add(
8999 json_path, "addpathTxId",
9000 path->tx_addpath.addpath_tx_id
9001 [BGP_ADDPATH_ALL]);
9002
9003 /* ... but create a specific field for each
9004 * strategy
9005 */
9006 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9007 json_object_int_add(
9008 json_path,
9009 bgp_addpath_names(i)
9010 ->id_json_name,
9011 path->tx_addpath
9012 .addpath_tx_id[i]);
9013 }
d62a17ae 9014 } else {
dcc68b5e
MS
9015 vty_out(vty, " AddPath ID: RX %u, ",
9016 path->addpath_rx_id);
9017
9018 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 9019 }
9020 }
718e3744 9021
d62a17ae 9022 /* If we used addpath to TX a non-bestpath we need to display
dcc68b5e
MS
9023 * "Advertised to" on a path-by-path basis
9024 */
9025 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 9026 first = 1;
9027
9028 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9029 addpath_capable =
9030 bgp_addpath_encode_tx(peer, afi, safi);
9031 has_adj = bgp_adj_out_lookup(
dcc68b5e
MS
9032 peer, path->net,
9033 bgp_addpath_id_for_peer(
9034 peer, afi, safi,
9035 &path->tx_addpath));
d62a17ae 9036
9037 if ((addpath_capable && has_adj)
9038 || (!addpath_capable && has_adj
9b6d8fcf 9039 && CHECK_FLAG(path->flags,
1defdda8 9040 BGP_PATH_SELECTED))) {
d62a17ae 9041 if (json_path && !json_adv_to)
9042 json_adv_to =
9043 json_object_new_object();
9044
9045 route_vty_out_advertised_to(
9046 vty, peer, &first,
9047 " Advertised to:",
9048 json_adv_to);
9049 }
9050 }
9051
9052 if (json_path) {
9053 if (json_adv_to) {
9054 json_object_object_add(json_path,
9055 "advertisedTo",
9056 json_adv_to);
9057 }
9058 } else {
9059 if (!first) {
9060 vty_out(vty, "\n");
9061 }
9062 }
9063 }
b05a1c8b 9064
d62a17ae 9065 /* Line 9 display Uptime */
9b6d8fcf 9066 tbuf = time(NULL) - (bgp_clock() - path->uptime);
d62a17ae 9067 if (json_paths) {
9068 json_last_update = json_object_new_object();
9069 json_object_int_add(json_last_update, "epoch", tbuf);
9070 json_object_string_add(json_last_update, "string",
9071 ctime(&tbuf));
9072 json_object_object_add(json_path, "lastUpdate",
9073 json_last_update);
9074 } else
9075 vty_out(vty, " Last update: %s", ctime(&tbuf));
7fd077aa 9076
9077 /* Line 10 display PMSI tunnel attribute, if present */
9078 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
b7d08f5a 9079 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
9080 attr->pmsi_tnl_type,
9081 PMSI_TNLTYPE_STR_DEFAULT);
9082
7fd077aa 9083 if (json_paths) {
9084 json_pmsi = json_object_new_object();
b7d08f5a 9085 json_object_string_add(json_pmsi,
9086 "tunnelType", str);
27f28ccc
AK
9087 json_object_int_add(json_pmsi,
9088 "label",
9089 label2vni(&attr->label));
7fd077aa 9090 json_object_object_add(json_path, "pmsi",
9091 json_pmsi);
9092 } else
27f28ccc
AK
9093 vty_out(vty,
9094 " PMSI Tunnel Type: %s, label: %d\n",
9095 str, label2vni(&attr->label));
7fd077aa 9096 }
9097
d62a17ae 9098 }
f1aa5d8a 9099
d62a17ae 9100 /* We've constructed the json object for this path, add it to the json
9101 * array of paths
9102 */
9103 if (json_paths) {
9104 if (json_nexthop_global || json_nexthop_ll) {
9105 json_nexthops = json_object_new_array();
f1aa5d8a 9106
d62a17ae 9107 if (json_nexthop_global)
9108 json_object_array_add(json_nexthops,
9109 json_nexthop_global);
f1aa5d8a 9110
d62a17ae 9111 if (json_nexthop_ll)
9112 json_object_array_add(json_nexthops,
9113 json_nexthop_ll);
f1aa5d8a 9114
d62a17ae 9115 json_object_object_add(json_path, "nexthops",
9116 json_nexthops);
9117 }
9118
9119 json_object_object_add(json_path, "peer", json_peer);
9120 json_object_array_add(json_paths, json_path);
9121 } else
9122 vty_out(vty, "\n");
b366b518
BB
9123}
9124
96ade3ed 9125#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
9126#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9127#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 9128
d62a17ae 9129static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
9130 const char *prefix_list_str, afi_t afi,
9131 safi_t safi, enum bgp_show_type type);
9132static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
9133 const char *filter, afi_t afi, safi_t safi,
9134 enum bgp_show_type type);
9135static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
9136 const char *rmap_str, afi_t afi, safi_t safi,
9137 enum bgp_show_type type);
9138static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
9139 const char *com, int exact, afi_t afi,
9140 safi_t safi);
9141static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
9142 const char *prefix, afi_t afi, safi_t safi,
9143 enum bgp_show_type type);
a4d82a8a
PZ
9144static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
9145 afi_t afi, safi_t safi, enum bgp_show_type type);
7f323236
DW
9146static int bgp_show_community(struct vty *vty, struct bgp *bgp,
9147 const char *comstr, int exact, afi_t afi,
9f049418 9148 safi_t safi, bool use_json);
d62a17ae 9149
1ae44dfc
LB
9150
9151static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 9152 struct bgp_table *table, enum bgp_show_type type,
9f049418 9153 void *output_arg, bool use_json, char *rd,
a4d82a8a
PZ
9154 int is_last, unsigned long *output_cum,
9155 unsigned long *total_cum,
9386b588 9156 unsigned long *json_header_depth)
d62a17ae 9157{
40381db7 9158 struct bgp_path_info *pi;
d62a17ae 9159 struct bgp_node *rn;
9160 int header = 1;
9161 int display;
1ae44dfc
LB
9162 unsigned long output_count = 0;
9163 unsigned long total_count = 0;
d62a17ae 9164 struct prefix *p;
d62a17ae 9165 char buf2[BUFSIZ];
9166 json_object *json_paths = NULL;
9167 int first = 1;
9168
1ae44dfc
LB
9169 if (output_cum && *output_cum != 0)
9170 header = 0;
9171
9386b588 9172 if (use_json && !*json_header_depth) {
d62a17ae 9173 vty_out(vty,
66f80d74 9174 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
01eced22
AD
9175 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9176 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 9177 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b
DS
9178 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
9179 ? VRF_DEFAULT_NAME
9180 : bgp->name,
01eced22
AD
9181 table->version, inet_ntoa(bgp->router_id),
9182 bgp->default_local_pref, bgp->as);
9386b588
PZ
9183 *json_header_depth = 2;
9184 if (rd) {
445c2480 9185 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
9186 ++*json_header_depth;
9187 }
d62a17ae 9188 }
718e3744 9189
445c2480
DS
9190 if (use_json && rd) {
9191 vty_out(vty, " \"%s\" : { ", rd);
9192 }
9193
d62a17ae 9194 /* Start processing of routes. */
98ce9a06 9195 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685
DS
9196 pi = bgp_node_get_bgp_path_info(rn);
9197 if (pi == NULL)
98ce9a06 9198 continue;
d62a17ae 9199
98ce9a06 9200 display = 0;
98ce9a06
DS
9201 if (use_json)
9202 json_paths = json_object_new_array();
9203 else
9204 json_paths = NULL;
d62a17ae 9205
6f94b685 9206 for (; pi; pi = pi->next) {
98ce9a06
DS
9207 total_count++;
9208 if (type == bgp_show_type_flap_statistics
9209 || type == bgp_show_type_flap_neighbor
9210 || type == bgp_show_type_dampend_paths
9211 || type == bgp_show_type_damp_neighbor) {
40381db7 9212 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
9213 continue;
9214 }
9215 if (type == bgp_show_type_regexp) {
9216 regex_t *regex = output_arg;
d62a17ae 9217
40381db7 9218 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
9219 == REG_NOMATCH)
9220 continue;
9221 }
9222 if (type == bgp_show_type_prefix_list) {
9223 struct prefix_list *plist = output_arg;
d62a17ae 9224
98ce9a06
DS
9225 if (prefix_list_apply(plist, &rn->p)
9226 != PREFIX_PERMIT)
9227 continue;
9228 }
9229 if (type == bgp_show_type_filter_list) {
9230 struct as_list *as_list = output_arg;
d62a17ae 9231
40381db7 9232 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
9233 != AS_FILTER_PERMIT)
9234 continue;
9235 }
9236 if (type == bgp_show_type_route_map) {
9237 struct route_map *rmap = output_arg;
9b6d8fcf 9238 struct bgp_path_info path;
98ce9a06 9239 struct attr dummy_attr;
b68885f9 9240 route_map_result_t ret;
d62a17ae 9241
40381db7 9242 bgp_attr_dup(&dummy_attr, pi->attr);
d62a17ae 9243
40381db7 9244 path.peer = pi->peer;
9b6d8fcf 9245 path.attr = &dummy_attr;
d62a17ae 9246
a4d82a8a 9247 ret = route_map_apply(rmap, &rn->p, RMAP_BGP,
9b6d8fcf 9248 &path);
98ce9a06
DS
9249 if (ret == RMAP_DENYMATCH)
9250 continue;
9251 }
9252 if (type == bgp_show_type_neighbor
9253 || type == bgp_show_type_flap_neighbor
9254 || type == bgp_show_type_damp_neighbor) {
9255 union sockunion *su = output_arg;
9256
40381db7
DS
9257 if (pi->peer == NULL
9258 || pi->peer->su_remote == NULL
9259 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
9260 continue;
9261 }
9262 if (type == bgp_show_type_cidr_only) {
d7c0a89a 9263 uint32_t destination;
d62a17ae 9264
98ce9a06
DS
9265 destination = ntohl(rn->p.u.prefix4.s_addr);
9266 if (IN_CLASSC(destination)
9267 && rn->p.prefixlen == 24)
9268 continue;
9269 if (IN_CLASSB(destination)
9270 && rn->p.prefixlen == 16)
9271 continue;
9272 if (IN_CLASSA(destination)
9273 && rn->p.prefixlen == 8)
9274 continue;
9275 }
9276 if (type == bgp_show_type_prefix_longer) {
f7813c7c 9277 p = output_arg;
98ce9a06
DS
9278 if (!prefix_match(p, &rn->p))
9279 continue;
9280 }
9281 if (type == bgp_show_type_community_all) {
40381db7 9282 if (!pi->attr->community)
98ce9a06
DS
9283 continue;
9284 }
9285 if (type == bgp_show_type_community) {
9286 struct community *com = output_arg;
d62a17ae 9287
40381db7
DS
9288 if (!pi->attr->community
9289 || !community_match(pi->attr->community,
98ce9a06
DS
9290 com))
9291 continue;
9292 }
9293 if (type == bgp_show_type_community_exact) {
9294 struct community *com = output_arg;
d62a17ae 9295
40381db7
DS
9296 if (!pi->attr->community
9297 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
9298 continue;
9299 }
9300 if (type == bgp_show_type_community_list) {
9301 struct community_list *list = output_arg;
d62a17ae 9302
40381db7 9303 if (!community_list_match(pi->attr->community,
a4d82a8a 9304 list))
98ce9a06
DS
9305 continue;
9306 }
a4d82a8a 9307 if (type == bgp_show_type_community_list_exact) {
98ce9a06 9308 struct community_list *list = output_arg;
d62a17ae 9309
98ce9a06 9310 if (!community_list_exact_match(
40381db7 9311 pi->attr->community, list))
98ce9a06
DS
9312 continue;
9313 }
9314 if (type == bgp_show_type_lcommunity) {
9315 struct lcommunity *lcom = output_arg;
d62a17ae 9316
40381db7
DS
9317 if (!pi->attr->lcommunity
9318 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
9319 lcom))
9320 continue;
9321 }
36a206db 9322
9323 if (type == bgp_show_type_lcommunity_exact) {
9324 struct lcommunity *lcom = output_arg;
9325
9326 if (!pi->attr->lcommunity
9327 || !lcommunity_cmp(pi->attr->lcommunity,
9328 lcom))
9329 continue;
9330 }
98ce9a06
DS
9331 if (type == bgp_show_type_lcommunity_list) {
9332 struct community_list *list = output_arg;
d62a17ae 9333
40381db7 9334 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 9335 list))
98ce9a06
DS
9336 continue;
9337 }
36a206db 9338 if (type
9339 == bgp_show_type_lcommunity_list_exact) {
9340 struct community_list *list = output_arg;
9341
9342 if (!lcommunity_list_exact_match(
9343 pi->attr->lcommunity, list))
9344 continue;
9345 }
98ce9a06 9346 if (type == bgp_show_type_lcommunity_all) {
40381db7 9347 if (!pi->attr->lcommunity)
98ce9a06
DS
9348 continue;
9349 }
9350 if (type == bgp_show_type_dampend_paths
9351 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
9352 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
9353 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
9354 continue;
9355 }
9356
9357 if (!use_json && header) {
996c9314 9358 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 9359 ", local router ID is %s, vrf id ",
98ce9a06
DS
9360 table->version,
9361 inet_ntoa(bgp->router_id));
9df8b37c
PZ
9362 if (bgp->vrf_id == VRF_UNKNOWN)
9363 vty_out(vty, "%s", VRFID_NONE_STR);
9364 else
9365 vty_out(vty, "%u", bgp->vrf_id);
9366 vty_out(vty, "\n");
01eced22
AD
9367 vty_out(vty, "Default local pref %u, ",
9368 bgp->default_local_pref);
9369 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 9370 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 9371 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 9372 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 9373 if (type == bgp_show_type_dampend_paths
9374 || type == bgp_show_type_damp_neighbor)
98ce9a06 9375 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
9376 else if (type == bgp_show_type_flap_statistics
9377 || type == bgp_show_type_flap_neighbor)
98ce9a06 9378 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 9379 else
98ce9a06
DS
9380 vty_out(vty, BGP_SHOW_HEADER);
9381 header = 0;
d62a17ae 9382 }
98ce9a06
DS
9383 if (rd != NULL && !display && !output_count) {
9384 if (!use_json)
9385 vty_out(vty,
9386 "Route Distinguisher: %s\n",
9387 rd);
d62a17ae 9388 }
98ce9a06
DS
9389 if (type == bgp_show_type_dampend_paths
9390 || type == bgp_show_type_damp_neighbor)
40381db7 9391 damp_route_vty_out(vty, &rn->p, pi, display,
a4d82a8a 9392 safi, use_json, json_paths);
98ce9a06
DS
9393 else if (type == bgp_show_type_flap_statistics
9394 || type == bgp_show_type_flap_neighbor)
40381db7 9395 flap_route_vty_out(vty, &rn->p, pi, display,
a4d82a8a 9396 safi, use_json, json_paths);
98ce9a06 9397 else
40381db7 9398 route_vty_out(vty, &rn->p, pi, display, safi,
a4d82a8a 9399 json_paths);
98ce9a06 9400 display++;
d62a17ae 9401 }
9402
98ce9a06
DS
9403 if (display) {
9404 output_count++;
9405 if (!use_json)
9406 continue;
9407
9408 p = &rn->p;
625d2931
PG
9409 /* encode prefix */
9410 if (p->family == AF_FLOWSPEC) {
9411 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
9412
9413 bgp_fs_nlri_get_string((unsigned char *)
9414 p->u.prefix_flowspec.ptr,
9415 p->u.prefix_flowspec
9416 .prefixlen,
9417 retstr,
9418 NLRI_STRING_FORMAT_MIN,
9419 NULL);
9420 if (first)
9421 vty_out(vty, "\"%s/%d\": ",
9422 retstr,
9423 p->u.prefix_flowspec.prefixlen);
9424 else
9425 vty_out(vty, ",\"%s/%d\": ",
9426 retstr,
9427 p->u.prefix_flowspec.prefixlen);
9428 } else {
9429 prefix2str(p, buf2, sizeof(buf2));
9430 if (first)
9431 vty_out(vty, "\"%s\": ", buf2);
9432 else
9433 vty_out(vty, ",\"%s\": ", buf2);
9434 }
98ce9a06 9435 vty_out(vty, "%s",
23b2a7ef 9436 json_object_to_json_string(json_paths));
98ce9a06 9437 json_object_free(json_paths);
449feb8e 9438 json_paths = NULL;
98ce9a06
DS
9439 first = 0;
9440 }
9441 }
9442
1ae44dfc
LB
9443 if (output_cum) {
9444 output_count += *output_cum;
9445 *output_cum = output_count;
9446 }
9447 if (total_cum) {
9448 total_count += *total_cum;
9449 *total_cum = total_count;
9450 }
d62a17ae 9451 if (use_json) {
9386b588 9452 if (rd) {
a4d82a8a 9453 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
9454 }
9455 if (is_last) {
a4d82a8a
PZ
9456 unsigned long i;
9457 for (i = 0; i < *json_header_depth; ++i)
9458 vty_out(vty, " } ");
faf6559a 9459 vty_out(vty, "\n");
9386b588 9460 }
d62a17ae 9461 } else {
1ae44dfc
LB
9462 if (is_last) {
9463 /* No route is displayed */
9464 if (output_count == 0) {
9465 if (type == bgp_show_type_normal)
9466 vty_out(vty,
9467 "No BGP prefixes displayed, %ld exist\n",
9468 total_count);
9469 } else
d62a17ae 9470 vty_out(vty,
1ae44dfc
LB
9471 "\nDisplayed %ld routes and %ld total paths\n",
9472 output_count, total_count);
9473 }
d62a17ae 9474 }
718e3744 9475
d62a17ae 9476 return CMD_SUCCESS;
718e3744 9477}
9478
1ae44dfc
LB
9479int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
9480 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 9481 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc
LB
9482{
9483 struct bgp_node *rn, *next;
9484 unsigned long output_cum = 0;
9485 unsigned long total_cum = 0;
9386b588 9486 unsigned long json_header_depth = 0;
67009e22 9487 struct bgp_table *itable;
0136788c
LB
9488 bool show_msg;
9489
9490 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc
LB
9491
9492 for (rn = bgp_table_top(table); rn; rn = next) {
9493 next = bgp_route_next(rn);
9494 if (prd_match && memcmp(rn->p.u.val, prd_match->val, 8) != 0)
9495 continue;
67009e22
DS
9496
9497 itable = bgp_node_get_bgp_table_info(rn);
9498 if (itable != NULL) {
1ae44dfc 9499 struct prefix_rd prd;
06b9f471 9500 char rd[RD_ADDRSTRLEN];
1ae44dfc
LB
9501
9502 memcpy(&prd, &(rn->p), sizeof(struct prefix_rd));
06b9f471 9503 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22
DS
9504 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
9505 use_json, rd, next == NULL, &output_cum,
9506 &total_cum, &json_header_depth);
0136788c
LB
9507 if (next == NULL)
9508 show_msg = false;
1ae44dfc
LB
9509 }
9510 }
0136788c
LB
9511 if (show_msg) {
9512 if (output_cum == 0)
9513 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
9514 total_cum);
9515 else
9516 vty_out(vty,
9517 "\nDisplayed %ld routes and %ld total paths\n",
9518 output_cum, total_cum);
9519 }
1ae44dfc
LB
9520 return CMD_SUCCESS;
9521}
d62a17ae 9522static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
9f049418 9523 enum bgp_show_type type, void *output_arg, bool use_json)
fee0f4c6 9524{
d62a17ae 9525 struct bgp_table *table;
9386b588 9526 unsigned long json_header_depth = 0;
fee0f4c6 9527
d62a17ae 9528 if (bgp == NULL) {
9529 bgp = bgp_get_default();
9530 }
fee0f4c6 9531
d62a17ae 9532 if (bgp == NULL) {
9533 if (!use_json)
9534 vty_out(vty, "No BGP process is configured\n");
16307668
RW
9535 else
9536 vty_out(vty, "{}\n");
d62a17ae 9537 return CMD_WARNING;
9538 }
4dd6177e 9539
1ae44dfc 9540 table = bgp->rib[afi][safi];
d62a17ae 9541 /* use MPLS and ENCAP specific shows until they are merged */
9542 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
9543 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
9544 output_arg, use_json);
d62a17ae 9545 }
dba3c1d3
PG
9546
9547 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
9548 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
9549 output_arg, use_json,
9550 1, NULL, NULL);
9551 }
d62a17ae 9552 /* labeled-unicast routes live in the unicast table */
9553 else if (safi == SAFI_LABELED_UNICAST)
9554 safi = SAFI_UNICAST;
fee0f4c6 9555
1ae44dfc 9556 return bgp_show_table(vty, bgp, safi, table, type, output_arg, use_json,
9386b588 9557 NULL, 1, NULL, NULL, &json_header_depth);
fee0f4c6 9558}
9559
d62a17ae 9560static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
9f049418 9561 safi_t safi, bool use_json)
f186de26 9562{
d62a17ae 9563 struct listnode *node, *nnode;
9564 struct bgp *bgp;
9565 int is_first = 1;
9f049418 9566 bool route_output = false;
f186de26 9567
d62a17ae 9568 if (use_json)
9569 vty_out(vty, "{\n");
9f689658 9570
d62a17ae 9571 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 9572 route_output = true;
d62a17ae 9573 if (use_json) {
9574 if (!is_first)
9575 vty_out(vty, ",\n");
9576 else
9577 is_first = 0;
9578
9579 vty_out(vty, "\"%s\":",
9580 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 9581 ? VRF_DEFAULT_NAME
d62a17ae 9582 : bgp->name);
9583 } else {
9584 vty_out(vty, "\nInstance %s:\n",
9585 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 9586 ? VRF_DEFAULT_NAME
d62a17ae 9587 : bgp->name);
9588 }
9589 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
9590 use_json);
9591 }
9f689658 9592
d62a17ae 9593 if (use_json)
9594 vty_out(vty, "}\n");
9f049418
DS
9595 else if (!route_output)
9596 vty_out(vty, "%% BGP instance not found\n");
f186de26 9597}
9598
718e3744 9599/* Header of detailed BGP route information */
d62a17ae 9600void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9601 struct bgp_node *rn, struct prefix_rd *prd,
9602 afi_t afi, safi_t safi, json_object *json)
9603{
40381db7 9604 struct bgp_path_info *pi;
d62a17ae 9605 struct prefix *p;
9606 struct peer *peer;
9607 struct listnode *node, *nnode;
06b9f471 9608 char buf1[RD_ADDRSTRLEN];
d62a17ae 9609 char buf2[INET6_ADDRSTRLEN];
d62a17ae 9610 char buf3[EVPN_ROUTE_STRLEN];
0291c246 9611 char prefix_str[BUFSIZ];
d62a17ae 9612 int count = 0;
9613 int best = 0;
9614 int suppress = 0;
c5f1e1b2
C
9615 int accept_own = 0;
9616 int route_filter_translated_v4 = 0;
9617 int route_filter_v4 = 0;
9618 int route_filter_translated_v6 = 0;
9619 int route_filter_v6 = 0;
9620 int llgr_stale = 0;
9621 int no_llgr = 0;
9622 int accept_own_nexthop = 0;
9623 int blackhole = 0;
d62a17ae 9624 int no_export = 0;
9625 int no_advertise = 0;
9626 int local_as = 0;
c5f1e1b2 9627 int no_peer = 0;
d62a17ae 9628 int first = 1;
9629 int has_valid_label = 0;
9630 mpls_label_t label = 0;
9631 json_object *json_adv_to = NULL;
9bedbb1e 9632
d62a17ae 9633 p = &rn->p;
9634 has_valid_label = bgp_is_valid_label(&rn->local_label);
9635
9636 if (has_valid_label)
9637 label = label_pton(&rn->local_label);
9638
44c69747 9639 if (safi == SAFI_EVPN) {
d62a17ae 9640
44c69747 9641 if (!json) {
d62a17ae 9642 vty_out(vty, "BGP routing table entry for %s%s%s\n",
06b9f471 9643 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
44c69747 9644 : "", prd ? ":" : "",
d62a17ae 9645 bgp_evpn_route2str((struct prefix_evpn *)p,
44c69747
LK
9646 buf3, sizeof(buf3)));
9647 } else {
9648 json_object_string_add(json, "rd",
9649 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
9650 "");
9651 bgp_evpn_route2json((struct prefix_evpn *)p, json);
9652 }
9653 } else {
9654 if (!json) {
d62a17ae 9655 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
9656 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
44c69747
LK
9657 ? prefix_rd2str(prd, buf1,
9658 sizeof(buf1))
9659 : ""),
d62a17ae 9660 safi == SAFI_MPLS_VPN ? ":" : "",
9661 inet_ntop(p->family, &p->u.prefix, buf2,
44c69747 9662 INET6_ADDRSTRLEN),
d62a17ae 9663 p->prefixlen);
cd1964ff 9664
44c69747
LK
9665 } else
9666 json_object_string_add(json, "prefix",
9667 prefix2str(p, prefix_str, sizeof(prefix_str)));
9668 }
9669
9670 if (has_valid_label) {
9671 if (json)
9672 json_object_int_add(json, "localLabel", label);
9673 else
d62a17ae 9674 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
9675 }
9676
9677 if (!json)
d62a17ae 9678 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 9679 vty_out(vty, "not allocated\n");
718e3744 9680
6f94b685 9681 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
d62a17ae 9682 count++;
40381db7 9683 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 9684 best = count;
40381db7 9685 if (pi->extra && pi->extra->suppress)
d62a17ae 9686 suppress = 1;
cee9c031 9687
40381db7 9688 if (pi->attr->community == NULL)
cee9c031
QY
9689 continue;
9690
9691 no_advertise += community_include(
40381db7
DS
9692 pi->attr->community, COMMUNITY_NO_ADVERTISE);
9693 no_export += community_include(pi->attr->community,
cee9c031 9694 COMMUNITY_NO_EXPORT);
40381db7 9695 local_as += community_include(pi->attr->community,
cee9c031 9696 COMMUNITY_LOCAL_AS);
40381db7 9697 accept_own += community_include(pi->attr->community,
cee9c031
QY
9698 COMMUNITY_ACCEPT_OWN);
9699 route_filter_translated_v4 += community_include(
40381db7 9700 pi->attr->community,
cee9c031
QY
9701 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
9702 route_filter_translated_v6 += community_include(
40381db7 9703 pi->attr->community,
cee9c031
QY
9704 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
9705 route_filter_v4 += community_include(
40381db7 9706 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 9707 route_filter_v6 += community_include(
40381db7
DS
9708 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
9709 llgr_stale += community_include(pi->attr->community,
cee9c031 9710 COMMUNITY_LLGR_STALE);
40381db7 9711 no_llgr += community_include(pi->attr->community,
cee9c031
QY
9712 COMMUNITY_NO_LLGR);
9713 accept_own_nexthop +=
40381db7 9714 community_include(pi->attr->community,
cee9c031 9715 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 9716 blackhole += community_include(pi->attr->community,
cee9c031 9717 COMMUNITY_BLACKHOLE);
40381db7 9718 no_peer += community_include(pi->attr->community,
cee9c031 9719 COMMUNITY_NO_PEER);
d62a17ae 9720 }
718e3744 9721 }
718e3744 9722
d62a17ae 9723 if (!json) {
9724 vty_out(vty, "Paths: (%d available", count);
9725 if (best) {
9726 vty_out(vty, ", best #%d", best);
b84060bb
PG
9727 if (safi == SAFI_UNICAST) {
9728 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
9729 vty_out(vty, ", table %s",
9730 VRF_DEFAULT_NAME);
9731 else
9732 vty_out(vty, ", vrf %s",
9733 bgp->name);
9734 }
d62a17ae 9735 } else
9736 vty_out(vty, ", no best path");
9737
c5f1e1b2
C
9738 if (accept_own)
9739 vty_out(vty,
9740 ", accept own local route exported and imported in different VRF");
9741 else if (route_filter_translated_v4)
9742 vty_out(vty,
9743 ", mark translated RTs for VPNv4 route filtering");
9744 else if (route_filter_v4)
9745 vty_out(vty,
9746 ", attach RT as-is for VPNv4 route filtering");
9747 else if (route_filter_translated_v6)
9748 vty_out(vty,
9749 ", mark translated RTs for VPNv6 route filtering");
9750 else if (route_filter_v6)
9751 vty_out(vty,
9752 ", attach RT as-is for VPNv6 route filtering");
9753 else if (llgr_stale)
9754 vty_out(vty,
9755 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9756 else if (no_llgr)
9757 vty_out(vty,
9758 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9759 else if (accept_own_nexthop)
9760 vty_out(vty,
9761 ", accept local nexthop");
9762 else if (blackhole)
9763 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 9764 else if (no_export)
9765 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
9766 else if (no_advertise)
9767 vty_out(vty, ", not advertised to any peer");
d62a17ae 9768 else if (local_as)
9769 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
9770 else if (no_peer)
9771 vty_out(vty,
9772 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 9773
9774 if (suppress)
9775 vty_out(vty,
9776 ", Advertisements suppressed by an aggregate.");
9777 vty_out(vty, ")\n");
9778 }
718e3744 9779
d62a17ae 9780 /* If we are not using addpath then we can display Advertised to and
9781 * that will
9782 * show what peers we advertised the bestpath to. If we are using
9783 * addpath
9784 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 9785 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 9786 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9787 if (bgp_adj_out_lookup(peer, rn, 0)) {
9788 if (json && !json_adv_to)
9789 json_adv_to = json_object_new_object();
9790
9791 route_vty_out_advertised_to(
9792 vty, peer, &first,
9793 " Advertised to non peer-group peers:\n ",
9794 json_adv_to);
9795 }
9796 }
9797
9798 if (json) {
9799 if (json_adv_to) {
9800 json_object_object_add(json, "advertisedTo",
9801 json_adv_to);
9802 }
9803 } else {
9804 if (first)
9805 vty_out(vty, " Not advertised to any peer");
9806 vty_out(vty, "\n");
9807 }
9808 }
718e3744 9809}
9810
44c69747
LK
9811static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9812 struct bgp_node *bgp_node, struct vty *vty,
9813 struct bgp *bgp, afi_t afi,
9814 safi_t safi, json_object *json,
9815 enum bgp_path_type pathtype, int *display)
9816{
9817 struct bgp_path_info *pi;
9818 int header = 1;
9819 char rdbuf[RD_ADDRSTRLEN];
9820 json_object *json_header = NULL;
9821 json_object *json_paths = NULL;
9822
9823 for (pi = bgp_node_get_bgp_path_info(bgp_node); pi;
9824 pi = pi->next) {
9825
9826 if (json && !json_paths) {
9827 /* Instantiate json_paths only if path is valid */
9828 json_paths = json_object_new_array();
9829 if (pfx_rd) {
9830 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
9831 json_header = json_object_new_object();
9832 } else
9833 json_header = json;
9834 }
9835
9836 if (header) {
9837 route_vty_out_detail_header(
9838 vty, bgp, bgp_node, pfx_rd,
9839 AFI_IP, safi, json_header);
9840 header = 0;
9841 }
9842 (*display)++;
9843
9844 if (pathtype == BGP_PATH_SHOW_ALL
9845 || (pathtype == BGP_PATH_SHOW_BESTPATH
9846 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
9847 || (pathtype == BGP_PATH_SHOW_MULTIPATH
9848 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
9849 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
9850 route_vty_out_detail(vty, bgp, bgp_node,
9851 pi, AFI_IP, safi,
9852 json_paths);
9853 }
9854
9855 if (json && json_paths) {
9856 json_object_object_add(json_header, "paths", json_paths);
9857
9858 if (pfx_rd)
9859 json_object_object_add(json, rdbuf, json_header);
9860 }
9861}
9862
718e3744 9863/* Display specified route of BGP table. */
d62a17ae 9864static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
9865 struct bgp_table *rib, const char *ip_str,
9866 afi_t afi, safi_t safi,
9867 struct prefix_rd *prd, int prefix_check,
9f049418 9868 enum bgp_path_type pathtype, bool use_json)
d62a17ae 9869{
9870 int ret;
d62a17ae 9871 int display = 0;
9872 struct prefix match;
9873 struct bgp_node *rn;
9874 struct bgp_node *rm;
d62a17ae 9875 struct bgp_table *table;
9876 json_object *json = NULL;
9877 json_object *json_paths = NULL;
9878
9879 /* Check IP address argument. */
9880 ret = str2prefix(ip_str, &match);
9881 if (!ret) {
9882 vty_out(vty, "address is malformed\n");
9883 return CMD_WARNING;
9884 }
718e3744 9885
d62a17ae 9886 match.family = afi2family(afi);
b05a1c8b 9887
44c69747 9888 if (use_json)
d62a17ae 9889 json = json_object_new_object();
718e3744 9890
44c69747 9891 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
d62a17ae 9892 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
9893 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
9894 continue;
67009e22
DS
9895 table = bgp_node_get_bgp_table_info(rn);
9896 if (!table)
ea47320b 9897 continue;
d62a17ae 9898
ea47320b
DL
9899 if ((rm = bgp_node_match(table, &match)) == NULL)
9900 continue;
d62a17ae 9901
ea47320b
DL
9902 if (prefix_check
9903 && rm->p.prefixlen != match.prefixlen) {
9904 bgp_unlock_node(rm);
9905 continue;
9906 }
d62a17ae 9907
44c69747
LK
9908 bgp_show_path_info((struct prefix_rd *)&rn->p, rm,
9909 vty, bgp, afi, safi, json,
9910 pathtype, &display);
9911
9912 bgp_unlock_node(rm);
9913 }
9914 } else if (safi == SAFI_EVPN) {
9915 struct bgp_node *longest_pfx;
9916 bool is_exact_pfxlen_match = FALSE;
9917
9918 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
9919 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
9920 continue;
9921 table = bgp_node_get_bgp_table_info(rn);
9922 if (!table)
9923 continue;
9924
9925 longest_pfx = NULL;
9926 is_exact_pfxlen_match = FALSE;
9927 /*
9928 * Search through all the prefixes for a match. The
9929 * pfx's are enumerated in ascending order of pfxlens.
9930 * So, the last pfx match is the longest match. Set
9931 * is_exact_pfxlen_match when we get exact pfxlen match
9932 */
9933 for (rm = bgp_table_top(table); rm;
9934 rm = bgp_route_next(rm)) {
9935 /*
9936 * Get prefixlen of the ip-prefix within type5
9937 * evpn route
9938 */
9939 if (evpn_type5_prefix_match(&rm->p,
9940 &match) && rm->info) {
9941 longest_pfx = rm;
9942 int type5_pfxlen =
9943 bgp_evpn_get_type5_prefixlen(&rm->p);
9944 if (type5_pfxlen == match.prefixlen) {
9945 is_exact_pfxlen_match = TRUE;
9946 bgp_unlock_node(rm);
9947 break;
9948 }
d62a17ae 9949 }
9950 }
ea47320b 9951
44c69747
LK
9952 if (!longest_pfx)
9953 continue;
9954
9955 if (prefix_check && !is_exact_pfxlen_match)
9956 continue;
9957
9958 rm = longest_pfx;
9959 bgp_lock_node(rm);
9960
9961 bgp_show_path_info((struct prefix_rd *)&rn->p, rm,
9962 vty, bgp, afi, safi, json,
9963 pathtype, &display);
9964
ea47320b 9965 bgp_unlock_node(rm);
d62a17ae 9966 }
98a9dbc7 9967 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
9968 if (use_json)
9969 json_paths = json_object_new_array();
9970
63a0b7a9
PG
9971 display = bgp_flowspec_display_match_per_ip(afi, rib,
9972 &match, prefix_check,
9973 vty,
9974 use_json,
9975 json_paths);
44c69747
LK
9976 if (use_json && display)
9977 json_object_object_add(json, "paths", json_paths);
d62a17ae 9978 } else {
d62a17ae 9979 if ((rn = bgp_node_match(rib, &match)) != NULL) {
9980 if (!prefix_check
9981 || rn->p.prefixlen == match.prefixlen) {
44c69747
LK
9982 bgp_show_path_info(NULL, rn, vty, bgp, afi,
9983 safi, json,
9984 pathtype, &display);
d62a17ae 9985 }
9986
9987 bgp_unlock_node(rn);
9988 }
9989 }
e5eee9af 9990
d62a17ae 9991 if (use_json) {
996c9314 9992 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
9993 json, JSON_C_TO_STRING_PRETTY |
9994 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 9995 json_object_free(json);
9996 } else {
9997 if (!display) {
9998 vty_out(vty, "%% Network not in table\n");
9999 return CMD_WARNING;
10000 }
10001 }
b05a1c8b 10002
d62a17ae 10003 return CMD_SUCCESS;
718e3744 10004}
10005
fee0f4c6 10006/* Display specified route of Main RIB */
d62a17ae 10007static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
10008 afi_t afi, safi_t safi, struct prefix_rd *prd,
10009 int prefix_check, enum bgp_path_type pathtype,
9f049418 10010 bool use_json)
d62a17ae 10011{
9b86009a 10012 if (!bgp) {
d62a17ae 10013 bgp = bgp_get_default();
9b86009a
RW
10014 if (!bgp) {
10015 if (!use_json)
10016 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10017 else
10018 vty_out(vty, "{}\n");
9b86009a
RW
10019 return CMD_WARNING;
10020 }
10021 }
d62a17ae 10022
10023 /* labeled-unicast routes live in the unicast table */
10024 if (safi == SAFI_LABELED_UNICAST)
10025 safi = SAFI_UNICAST;
10026
10027 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
10028 afi, safi, prd, prefix_check, pathtype,
10029 use_json);
10030}
10031
10032static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 10033 struct cmd_token **argv, bool exact, afi_t afi,
10034 safi_t safi, bool uj)
d62a17ae 10035{
10036 struct lcommunity *lcom;
10037 struct buffer *b;
10038 int i;
10039 char *str;
10040 int first = 0;
10041
10042 b = buffer_new(1024);
10043 for (i = 0; i < argc; i++) {
10044 if (first)
10045 buffer_putc(b, ' ');
10046 else {
10047 if (strmatch(argv[i]->text, "AA:BB:CC")) {
10048 first = 1;
10049 buffer_putstr(b, argv[i]->arg);
10050 }
10051 }
10052 }
10053 buffer_putc(b, '\0');
57d187bc 10054
d62a17ae 10055 str = buffer_getstr(b);
10056 buffer_free(b);
57d187bc 10057
d62a17ae 10058 lcom = lcommunity_str2com(str);
10059 XFREE(MTYPE_TMP, str);
10060 if (!lcom) {
10061 vty_out(vty, "%% Large-community malformed\n");
10062 return CMD_WARNING;
10063 }
57d187bc 10064
36a206db 10065 return bgp_show(vty, bgp, afi, safi,
10066 (exact ? bgp_show_type_lcommunity_exact
10067 : bgp_show_type_lcommunity),
10068 lcom, uj);
57d187bc
JS
10069}
10070
d62a17ae 10071static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 10072 const char *lcom, bool exact, afi_t afi,
10073 safi_t safi, bool uj)
57d187bc 10074{
d62a17ae 10075 struct community_list *list;
57d187bc 10076
e237b0d2 10077 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 10078 LARGE_COMMUNITY_LIST_MASTER);
10079 if (list == NULL) {
10080 vty_out(vty, "%% %s is not a valid large-community-list name\n",
10081 lcom);
10082 return CMD_WARNING;
10083 }
57d187bc 10084
36a206db 10085 return bgp_show(vty, bgp, afi, safi,
10086 (exact ? bgp_show_type_lcommunity_list_exact
10087 : bgp_show_type_lcommunity_list),
d62a17ae 10088 list, uj);
fee0f4c6 10089}
10090
52951b63
DS
10091DEFUN (show_ip_bgp_large_community_list,
10092 show_ip_bgp_large_community_list_cmd,
36a206db 10093 "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
10094 SHOW_STR
10095 IP_STR
10096 BGP_STR
10097 BGP_INSTANCE_HELP_STR
9bedbb1e 10098 BGP_AFI_HELP_STR
4dd6177e 10099 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10100 "Display routes matching the large-community-list\n"
10101 "large-community-list number\n"
10102 "large-community-list name\n"
36a206db 10103 "Exact match of the large-communities\n"
52951b63
DS
10104 JSON_STR)
10105{
d62a17ae 10106 char *vrf = NULL;
10107 afi_t afi = AFI_IP6;
10108 safi_t safi = SAFI_UNICAST;
10109 int idx = 0;
36a206db 10110 bool exact_match = 0;
d62a17ae 10111
10112 if (argv_find(argv, argc, "ip", &idx))
10113 afi = AFI_IP;
10114 if (argv_find(argv, argc, "view", &idx)
10115 || argv_find(argv, argc, "vrf", &idx))
10116 vrf = argv[++idx]->arg;
10117 if (argv_find(argv, argc, "ipv4", &idx)
10118 || argv_find(argv, argc, "ipv6", &idx)) {
10119 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
10120 if (argv_find(argv, argc, "unicast", &idx)
10121 || argv_find(argv, argc, "multicast", &idx))
10122 safi = bgp_vty_safi_from_str(argv[idx]->text);
10123 }
10124
9f049418 10125 bool uj = use_json(argc, argv);
d62a17ae 10126
10127 struct bgp *bgp = bgp_lookup_by_name(vrf);
10128 if (bgp == NULL) {
10129 vty_out(vty, "Can't find BGP instance %s\n", vrf);
10130 return CMD_WARNING;
10131 }
10132
10133 argv_find(argv, argc, "large-community-list", &idx);
36a206db 10134
10135 const char *clist_number_or_name = argv[++idx]->arg;
10136
10137 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10138 exact_match = 1;
10139
10140 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
10141 exact_match, afi, safi, uj);
52951b63
DS
10142}
10143DEFUN (show_ip_bgp_large_community,
10144 show_ip_bgp_large_community_cmd,
36a206db 10145 "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
10146 SHOW_STR
10147 IP_STR
10148 BGP_STR
10149 BGP_INSTANCE_HELP_STR
9bedbb1e 10150 BGP_AFI_HELP_STR
4dd6177e 10151 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10152 "Display routes matching the large-communities\n"
10153 "List of large-community numbers\n"
36a206db 10154 "Exact match of the large-communities\n"
52951b63
DS
10155 JSON_STR)
10156{
d62a17ae 10157 char *vrf = NULL;
10158 afi_t afi = AFI_IP6;
10159 safi_t safi = SAFI_UNICAST;
10160 int idx = 0;
36a206db 10161 bool exact_match = 0;
d62a17ae 10162
10163 if (argv_find(argv, argc, "ip", &idx))
10164 afi = AFI_IP;
10165 if (argv_find(argv, argc, "view", &idx)
10166 || argv_find(argv, argc, "vrf", &idx))
10167 vrf = argv[++idx]->arg;
10168 if (argv_find(argv, argc, "ipv4", &idx)
10169 || argv_find(argv, argc, "ipv6", &idx)) {
10170 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
10171 if (argv_find(argv, argc, "unicast", &idx)
10172 || argv_find(argv, argc, "multicast", &idx))
10173 safi = bgp_vty_safi_from_str(argv[idx]->text);
10174 }
10175
9f049418 10176 bool uj = use_json(argc, argv);
d62a17ae 10177
10178 struct bgp *bgp = bgp_lookup_by_name(vrf);
10179 if (bgp == NULL) {
10180 vty_out(vty, "Can't find BGP instance %s\n", vrf);
10181 return CMD_WARNING;
10182 }
10183
36a206db 10184 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
10185 if (argv_find(argv, argc, "exact-match", &idx))
10186 exact_match = 1;
10187 return bgp_show_lcommunity(vty, bgp, argc, argv,
10188 exact_match, afi, safi, uj);
10189 } else
d62a17ae 10190 return bgp_show(vty, bgp, afi, safi,
10191 bgp_show_type_lcommunity_all, NULL, uj);
52951b63
DS
10192}
10193
d62a17ae 10194static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
10195 safi_t safi);
e01ca200 10196
7b2ff250
DW
10197
10198/* BGP route print out function without JSON */
af462945
DS
10199DEFUN (show_ip_bgp,
10200 show_ip_bgp_cmd,
4dd6177e 10201 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
7b2ff250
DW
10202 <dampening <parameters>\
10203 |route-map WORD\
10204 |prefix-list WORD\
10205 |filter-list WORD\
10206 |statistics\
7b2ff250
DW
10207 |community-list <(1-500)|WORD> [exact-match]\
10208 |A.B.C.D/M longer-prefixes\
10209 |X:X::X:X/M longer-prefixes\
10210 >",
718e3744 10211 SHOW_STR
10212 IP_STR
10213 BGP_STR
a636c635 10214 BGP_INSTANCE_HELP_STR
4f280b15 10215 BGP_AFI_HELP_STR
4dd6177e 10216 BGP_SAFI_WITH_LABEL_HELP_STR
a636c635 10217 "Display detailed information about dampening\n"
af462945 10218 "Display detail of configured dampening parameters\n"
a636c635
DW
10219 "Display routes matching the route-map\n"
10220 "A route-map to match on\n"
10221 "Display routes conforming to the prefix-list\n"
8c3deaae 10222 "Prefix-list name\n"
a636c635
DW
10223 "Display routes conforming to the filter-list\n"
10224 "Regular expression access list name\n"
e01ca200 10225 "BGP RIB advertisement statistics\n"
a636c635
DW
10226 "Display routes matching the community-list\n"
10227 "community-list number\n"
10228 "community-list name\n"
10229 "Exact match of the communities\n"
0c7b1b01 10230 "IPv4 prefix\n"
8c3deaae 10231 "Display route and more specific routes\n"
0c7b1b01 10232 "IPv6 prefix\n"
7b2ff250 10233 "Display route and more specific routes\n")
718e3744 10234{
d62a17ae 10235 afi_t afi = AFI_IP6;
10236 safi_t safi = SAFI_UNICAST;
10237 int exact_match = 0;
d62a17ae 10238 struct bgp *bgp = NULL;
10239 int idx = 0;
10240
10241 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10242 &bgp, false);
d62a17ae 10243 if (!idx)
10244 return CMD_WARNING;
10245
d62a17ae 10246 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 10247 if (argv_find(argv, argc, "parameters", &idx))
d62a17ae 10248 return bgp_show_dampening_parameters(vty, afi, safi);
10249 }
c016b6c7 10250
d62a17ae 10251 if (argv_find(argv, argc, "prefix-list", &idx))
10252 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
10253 safi, bgp_show_type_prefix_list);
10254
10255 if (argv_find(argv, argc, "filter-list", &idx))
10256 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
10257 safi, bgp_show_type_filter_list);
10258
10259 if (argv_find(argv, argc, "statistics", &idx))
10260 return bgp_table_stats(vty, bgp, afi, safi);
10261
10262 if (argv_find(argv, argc, "route-map", &idx))
10263 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
10264 safi, bgp_show_type_route_map);
10265
d62a17ae 10266 if (argv_find(argv, argc, "community-list", &idx)) {
10267 const char *clist_number_or_name = argv[++idx]->arg;
10268 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10269 exact_match = 1;
10270 return bgp_show_community_list(vty, bgp, clist_number_or_name,
10271 exact_match, afi, safi);
10272 }
10273 /* prefix-longer */
10274 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10275 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10276 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
10277 safi,
10278 bgp_show_type_prefix_longer);
10279
7b2ff250
DW
10280 return CMD_WARNING;
10281}
10282
10283/* BGP route print out function with JSON */
10284DEFUN (show_ip_bgp_json,
10285 show_ip_bgp_json_cmd,
10286 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
cf4898bc
QY
10287 [cidr-only\
10288 |dampening <flap-statistics|dampened-paths>\
10289 |community [AA:NN|local-AS|no-advertise|no-export\
10290 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10291 |accept-own|accept-own-nexthop|route-filter-v6\
10292 |route-filter-v4|route-filter-translated-v6\
10293 |route-filter-translated-v4] [exact-match]\
10294 ] [json]",
7b2ff250
DW
10295 SHOW_STR
10296 IP_STR
10297 BGP_STR
10298 BGP_INSTANCE_HELP_STR
10299 BGP_AFI_HELP_STR
10300 BGP_SAFI_WITH_LABEL_HELP_STR
10301 "Display only routes with non-natural netmasks\n"
10302 "Display detailed information about dampening\n"
10303 "Display flap statistics of routes\n"
10304 "Display paths suppressed due to dampening\n"
10305 "Display routes matching the communities\n"
d0086e8e
AD
10306 COMMUNITY_AANN_STR
10307 "Do not send outside local AS (well-known community)\n"
10308 "Do not advertise to any peer (well-known community)\n"
10309 "Do not export to next AS (well-known community)\n"
10310 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
10311 "Do not export to any peer (well-known community)\n"
10312 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10313 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10314 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10315 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10316 "Should accept VPN route with local nexthop (well-known community)\n"
10317 "RT VPNv6 route filtering (well-known community)\n"
10318 "RT VPNv4 route filtering (well-known community)\n"
10319 "RT translated VPNv6 route filtering (well-known community)\n"
10320 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 10321 "Exact match of the communities\n"
7b2ff250
DW
10322 JSON_STR)
10323{
10324 afi_t afi = AFI_IP6;
10325 safi_t safi = SAFI_UNICAST;
10326 enum bgp_show_type sh_type = bgp_show_type_normal;
10327 struct bgp *bgp = NULL;
10328 int idx = 0;
d0086e8e 10329 int exact_match = 0;
9f049418
DS
10330 bool uj = use_json(argc, argv);
10331
10332 if (uj)
10333 argc--;
7b2ff250
DW
10334
10335 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10336 &bgp, uj);
7b2ff250
DW
10337 if (!idx)
10338 return CMD_WARNING;
10339
7b2ff250
DW
10340 if (argv_find(argv, argc, "cidr-only", &idx))
10341 return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
10342 NULL, uj);
10343
10344 if (argv_find(argv, argc, "dampening", &idx)) {
10345 if (argv_find(argv, argc, "dampened-paths", &idx))
10346 return bgp_show(vty, bgp, afi, safi,
10347 bgp_show_type_dampend_paths, NULL, uj);
10348 else if (argv_find(argv, argc, "flap-statistics", &idx))
10349 return bgp_show(vty, bgp, afi, safi,
10350 bgp_show_type_flap_statistics, NULL,
10351 uj);
10352 }
10353
10354 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 10355 char *maybecomm = NULL;
cf4898bc 10356 char *community = NULL;
d0086e8e 10357
79bc257a
RW
10358 if (idx + 1 < argc) {
10359 if (argv[idx + 1]->type == VARIABLE_TKN)
10360 maybecomm = argv[idx + 1]->arg;
10361 else
10362 maybecomm = argv[idx + 1]->text;
10363 }
10364
cf4898bc
QY
10365 if (maybecomm && !strmatch(maybecomm, "json")
10366 && !strmatch(maybecomm, "exact-match"))
10367 community = maybecomm;
d0086e8e 10368
cf4898bc
QY
10369 if (argv_find(argv, argc, "exact-match", &idx))
10370 exact_match = 1;
d0086e8e 10371
cf4898bc
QY
10372 if (community)
10373 return bgp_show_community(vty, bgp, community,
10374 exact_match, afi, safi, uj);
10375 else
d0086e8e 10376 return (bgp_show(vty, bgp, afi, safi,
cf4898bc
QY
10377 bgp_show_type_community_all, NULL,
10378 uj));
7b2ff250 10379 }
d0086e8e 10380
1ae44dfc 10381 return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj);
a636c635 10382}
47fc97cc 10383
718e3744 10384DEFUN (show_ip_bgp_route,
10385 show_ip_bgp_route_cmd,
4dd6177e 10386 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]"
ae19d7dd 10387 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
718e3744 10388 SHOW_STR
10389 IP_STR
10390 BGP_STR
a636c635 10391 BGP_INSTANCE_HELP_STR
4f280b15 10392 BGP_AFI_HELP_STR
4dd6177e 10393 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 10394 "Network in the BGP routing table to display\n"
0c7b1b01 10395 "IPv4 prefix\n"
8c3deaae 10396 "Network in the BGP routing table to display\n"
0c7b1b01 10397 "IPv6 prefix\n"
4092b06c 10398 "Display only the bestpath\n"
b05a1c8b 10399 "Display only multipaths\n"
9973d184 10400 JSON_STR)
4092b06c 10401{
d62a17ae 10402 int prefix_check = 0;
ae19d7dd 10403
d62a17ae 10404 afi_t afi = AFI_IP6;
10405 safi_t safi = SAFI_UNICAST;
10406 char *prefix = NULL;
10407 struct bgp *bgp = NULL;
10408 enum bgp_path_type path_type;
9f049418 10409 bool uj = use_json(argc, argv);
b05a1c8b 10410
d62a17ae 10411 int idx = 0;
ae19d7dd 10412
d62a17ae 10413 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10414 &bgp, uj);
d62a17ae 10415 if (!idx)
10416 return CMD_WARNING;
c41247f5 10417
d62a17ae 10418 if (!bgp) {
10419 vty_out(vty,
10420 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10421 return CMD_WARNING;
10422 }
a636c635 10423
d62a17ae 10424 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10425 if (argv_find(argv, argc, "A.B.C.D", &idx)
10426 || argv_find(argv, argc, "X:X::X:X", &idx))
10427 prefix_check = 0;
10428 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10429 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10430 prefix_check = 1;
10431
10432 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
10433 && afi != AFI_IP6) {
10434 vty_out(vty,
10435 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10436 return CMD_WARNING;
10437 }
10438 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
10439 && afi != AFI_IP) {
10440 vty_out(vty,
10441 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10442 return CMD_WARNING;
10443 }
10444
10445 prefix = argv[idx]->arg;
10446
10447 /* [<bestpath|multipath>] */
10448 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 10449 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 10450 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 10451 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 10452 else
360660c6 10453 path_type = BGP_PATH_SHOW_ALL;
a636c635 10454
d62a17ae 10455 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
10456 path_type, uj);
4092b06c
DS
10457}
10458
8c3deaae
QY
10459DEFUN (show_ip_bgp_regexp,
10460 show_ip_bgp_regexp_cmd,
4dd6177e 10461 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX...",
8c3deaae
QY
10462 SHOW_STR
10463 IP_STR
10464 BGP_STR
b00b230a 10465 BGP_INSTANCE_HELP_STR
4f280b15 10466 BGP_AFI_HELP_STR
4dd6177e 10467 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 10468 "Display routes matching the AS path regular expression\n"
a818ea74 10469 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n")
8c3deaae 10470{
d62a17ae 10471 afi_t afi = AFI_IP6;
10472 safi_t safi = SAFI_UNICAST;
10473 struct bgp *bgp = NULL;
8c3deaae 10474
d62a17ae 10475 int idx = 0;
10476 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10477 &bgp, false);
d62a17ae 10478 if (!idx)
10479 return CMD_WARNING;
8c3deaae 10480
d62a17ae 10481 // get index of regex
10482 argv_find(argv, argc, "regexp", &idx);
10483 idx++;
8c3deaae 10484
d62a17ae 10485 char *regstr = argv_concat(argv, argc, idx);
e889891d 10486 int rc = bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
d62a17ae 10487 bgp_show_type_regexp);
10488 XFREE(MTYPE_TMP, regstr);
10489 return rc;
8c3deaae
QY
10490}
10491
a636c635
DW
10492DEFUN (show_ip_bgp_instance_all,
10493 show_ip_bgp_instance_all_cmd,
4dd6177e 10494 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json]",
4092b06c 10495 SHOW_STR
a636c635 10496 IP_STR
4092b06c 10497 BGP_STR
a636c635 10498 BGP_INSTANCE_ALL_HELP_STR
4f280b15 10499 BGP_AFI_HELP_STR
4dd6177e 10500 BGP_SAFI_WITH_LABEL_HELP_STR
9973d184 10501 JSON_STR)
4092b06c 10502{
d62a17ae 10503 afi_t afi = AFI_IP;
10504 safi_t safi = SAFI_UNICAST;
10505 struct bgp *bgp = NULL;
d62a17ae 10506 int idx = 0;
9f049418 10507 bool uj = use_json(argc, argv);
ae19d7dd 10508
d62a17ae 10509 if (uj)
10510 argc--;
e3e29b32 10511
9f049418
DS
10512 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10513 &bgp, uj);
10514 if (!idx)
10515 return CMD_WARNING;
10516
d62a17ae 10517 bgp_show_all_instances_routes_vty(vty, afi, safi, uj);
10518 return CMD_SUCCESS;
e3e29b32
LB
10519}
10520
a4d82a8a
PZ
10521static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
10522 afi_t afi, safi_t safi, enum bgp_show_type type)
718e3744 10523{
d62a17ae 10524 regex_t *regex;
10525 int rc;
e3e29b32 10526
c3900853
DA
10527 if (!config_bgp_aspath_validate(regstr)) {
10528 vty_out(vty, "Invalid character in as-path access-list %s\n",
10529 regstr);
10530 return CMD_WARNING_CONFIG_FAILED;
10531 }
10532
d62a17ae 10533 regex = bgp_regcomp(regstr);
10534 if (!regex) {
10535 vty_out(vty, "Can't compile regexp %s\n", regstr);
10536 return CMD_WARNING;
10537 }
a636c635 10538
e889891d 10539 rc = bgp_show(vty, bgp, afi, safi, type, regex, 0);
d62a17ae 10540 bgp_regex_free(regex);
10541 return rc;
e3e29b32
LB
10542}
10543
d62a17ae 10544static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10545 const char *prefix_list_str, afi_t afi,
10546 safi_t safi, enum bgp_show_type type)
e3e29b32 10547{
d62a17ae 10548 struct prefix_list *plist;
718e3744 10549
d62a17ae 10550 plist = prefix_list_lookup(afi, prefix_list_str);
10551 if (plist == NULL) {
10552 vty_out(vty, "%% %s is not a valid prefix-list name\n",
10553 prefix_list_str);
10554 return CMD_WARNING;
10555 }
718e3744 10556
d62a17ae 10557 return bgp_show(vty, bgp, afi, safi, type, plist, 0);
4092b06c
DS
10558}
10559
d62a17ae 10560static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10561 const char *filter, afi_t afi, safi_t safi,
10562 enum bgp_show_type type)
4092b06c 10563{
d62a17ae 10564 struct as_list *as_list;
718e3744 10565
d62a17ae 10566 as_list = as_list_lookup(filter);
10567 if (as_list == NULL) {
10568 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
10569 filter);
10570 return CMD_WARNING;
10571 }
a636c635 10572
d62a17ae 10573 return bgp_show(vty, bgp, afi, safi, type, as_list, 0);
718e3744 10574}
10575
d62a17ae 10576static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10577 const char *rmap_str, afi_t afi, safi_t safi,
10578 enum bgp_show_type type)
718e3744 10579{
d62a17ae 10580 struct route_map *rmap;
bb46e94f 10581
d62a17ae 10582 rmap = route_map_lookup_by_name(rmap_str);
10583 if (!rmap) {
10584 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
10585 return CMD_WARNING;
10586 }
10587
10588 return bgp_show(vty, bgp, afi, safi, type, rmap, 0);
10589}
10590
7f323236
DW
10591static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10592 const char *comstr, int exact, afi_t afi,
9f049418 10593 safi_t safi, bool use_json)
d62a17ae 10594{
10595 struct community *com;
d62a17ae 10596 int ret = 0;
10597
7f323236 10598 com = community_str2com(comstr);
d62a17ae 10599 if (!com) {
7f323236 10600 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 10601 return CMD_WARNING;
10602 }
10603
10604 ret = bgp_show(vty, bgp, afi, safi,
10605 (exact ? bgp_show_type_community_exact
10606 : bgp_show_type_community),
d0086e8e 10607 com, use_json);
3c1f53de 10608 community_free(&com);
46c3ce83 10609
d62a17ae 10610 return ret;
718e3744 10611}
10612
d62a17ae 10613static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10614 const char *com, int exact, afi_t afi,
10615 safi_t safi)
50ef26d4 10616{
d62a17ae 10617 struct community_list *list;
50ef26d4 10618
e237b0d2 10619 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 10620 if (list == NULL) {
10621 vty_out(vty, "%% %s is not a valid community-list name\n", com);
10622 return CMD_WARNING;
10623 }
718e3744 10624
d62a17ae 10625 return bgp_show(vty, bgp, afi, safi,
10626 (exact ? bgp_show_type_community_list_exact
10627 : bgp_show_type_community_list),
10628 list, 0);
50ef26d4 10629}
10630
d62a17ae 10631static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10632 const char *prefix, afi_t afi, safi_t safi,
10633 enum bgp_show_type type)
718e3744 10634{
d62a17ae 10635 int ret;
10636 struct prefix *p;
47fc97cc 10637
d62a17ae 10638 p = prefix_new();
95cbbd2a 10639
d62a17ae 10640 ret = str2prefix(prefix, p);
10641 if (!ret) {
10642 vty_out(vty, "%% Malformed Prefix\n");
10643 return CMD_WARNING;
10644 }
47e9b292 10645
d62a17ae 10646 ret = bgp_show(vty, bgp, afi, safi, type, p, 0);
10647 prefix_free(p);
10648 return ret;
10649}
10650
d62a17ae 10651enum bgp_stats {
10652 BGP_STATS_MAXBITLEN = 0,
10653 BGP_STATS_RIB,
10654 BGP_STATS_PREFIXES,
10655 BGP_STATS_TOTPLEN,
10656 BGP_STATS_UNAGGREGATEABLE,
10657 BGP_STATS_MAX_AGGREGATEABLE,
10658 BGP_STATS_AGGREGATES,
10659 BGP_STATS_SPACE,
10660 BGP_STATS_ASPATH_COUNT,
10661 BGP_STATS_ASPATH_MAXHOPS,
10662 BGP_STATS_ASPATH_TOTHOPS,
10663 BGP_STATS_ASPATH_MAXSIZE,
10664 BGP_STATS_ASPATH_TOTSIZE,
10665 BGP_STATS_ASN_HIGHEST,
10666 BGP_STATS_MAX,
a636c635 10667};
2815e61f 10668
d62a17ae 10669static const char *table_stats_strs[] = {
9d303b37
DL
10670 [BGP_STATS_PREFIXES] = "Total Prefixes",
10671 [BGP_STATS_TOTPLEN] = "Average prefix length",
10672 [BGP_STATS_RIB] = "Total Advertisements",
10673 [BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes",
10674 [BGP_STATS_MAX_AGGREGATEABLE] =
10675 "Maximum aggregateable prefixes",
10676 [BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements",
10677 [BGP_STATS_SPACE] = "Address space advertised",
10678 [BGP_STATS_ASPATH_COUNT] = "Advertisements with paths",
10679 [BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)",
10680 [BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)",
10681 [BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)",
10682 [BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)",
10683 [BGP_STATS_ASN_HIGHEST] = "Highest public ASN",
10684 [BGP_STATS_MAX] = NULL,
a636c635 10685};
2815e61f 10686
d62a17ae 10687struct bgp_table_stats {
10688 struct bgp_table *table;
10689 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 10690 double total_space;
ff7924f6
PJ
10691};
10692
a636c635
DW
10693#if 0
10694#define TALLY_SIGFIG 100000
10695static unsigned long
10696ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 10697{
a636c635
DW
10698 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
10699 unsigned long res = (newtot * TALLY_SIGFIG) / count;
10700 unsigned long ret = newtot / count;
07d0c4ed 10701
a636c635
DW
10702 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
10703 return ret + 1;
10704 else
10705 return ret;
10706}
10707#endif
ff7924f6 10708
9c14ec72
RW
10709static void bgp_table_stats_rn(struct bgp_node *rn, struct bgp_node *top,
10710 struct bgp_table_stats *ts, unsigned int space)
2815e61f 10711{
9c14ec72
RW
10712 struct bgp_node *prn = bgp_node_parent_nolock(rn);
10713 struct bgp_path_info *pi;
d62a17ae 10714
9c14ec72
RW
10715 if (rn == top)
10716 return;
d62a17ae 10717
9c14ec72
RW
10718 if (!bgp_node_has_bgp_path_info_data(rn))
10719 return;
d62a17ae 10720
9c14ec72
RW
10721 ts->counts[BGP_STATS_PREFIXES]++;
10722 ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
ff7924f6 10723
a636c635
DW
10724#if 0
10725 ts->counts[BGP_STATS_AVGPLEN]
10726 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
10727 ts->counts[BGP_STATS_AVGPLEN],
10728 rn->p.prefixlen);
10729#endif
d62a17ae 10730
9c14ec72
RW
10731 /* check if the prefix is included by any other announcements */
10732 while (prn && !bgp_node_has_bgp_path_info_data(prn))
10733 prn = bgp_node_parent_nolock(prn);
d62a17ae 10734
9c14ec72
RW
10735 if (prn == NULL || prn == top) {
10736 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
10737 /* announced address space */
10738 if (space)
10739 ts->total_space += pow(2.0, space - rn->p.prefixlen);
10740 } else if (bgp_node_has_bgp_path_info_data(prn))
10741 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 10742
9c14ec72
RW
10743
10744 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
10745 ts->counts[BGP_STATS_RIB]++;
10746
10747 if (pi->attr
10748 && (CHECK_FLAG(pi->attr->flag,
10749 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))))
10750 ts->counts[BGP_STATS_AGGREGATES]++;
10751
10752 /* as-path stats */
10753 if (pi->attr && pi->attr->aspath) {
10754 unsigned int hops = aspath_count_hops(pi->attr->aspath);
10755 unsigned int size = aspath_size(pi->attr->aspath);
10756 as_t highest = aspath_highest(pi->attr->aspath);
10757
10758 ts->counts[BGP_STATS_ASPATH_COUNT]++;
10759
10760 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
10761 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
10762
10763 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
10764 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
10765
10766 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
10767 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 10768#if 0
07d0c4ed 10769 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
10770 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
10771 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
10772 hops);
10773 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
10774 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
10775 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
10776 size);
10777#endif
9c14ec72
RW
10778 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
10779 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
10780 }
10781 }
10782}
10783
10784static int bgp_table_stats_walker(struct thread *t)
10785{
10786 struct bgp_node *rn, *nrn;
10787 struct bgp_node *top;
10788 struct bgp_table_stats *ts = THREAD_ARG(t);
10789 unsigned int space = 0;
10790
10791 if (!(top = bgp_table_top(ts->table)))
10792 return 0;
10793
10794 switch (ts->table->afi) {
10795 case AFI_IP:
10796 space = IPV4_MAX_BITLEN;
10797 break;
10798 case AFI_IP6:
10799 space = IPV6_MAX_BITLEN;
10800 break;
10801 default:
10802 return 0;
10803 }
10804
10805 ts->counts[BGP_STATS_MAXBITLEN] = space;
10806
10807 for (rn = top; rn; rn = bgp_route_next(rn)) {
10808 if (ts->table->safi == SAFI_MPLS_VPN) {
10809 struct bgp_table *table;
10810
10811 table = bgp_node_get_bgp_table_info(rn);
10812 if (!table)
10813 continue;
10814
10815 top = bgp_table_top(table);
10816 for (nrn = bgp_table_top(table); nrn;
10817 nrn = bgp_route_next(nrn))
10818 bgp_table_stats_rn(nrn, top, ts, space);
10819 } else {
10820 bgp_table_stats_rn(rn, top, ts, space);
d62a17ae 10821 }
10822 }
9c14ec72 10823
d62a17ae 10824 return 0;
2815e61f 10825}
ff7924f6 10826
d62a17ae 10827static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
10828 safi_t safi)
2815e61f 10829{
d62a17ae 10830 struct bgp_table_stats ts;
10831 unsigned int i;
019386c2 10832
d62a17ae 10833 if (!bgp->rib[afi][safi]) {
10834 vty_out(vty, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10835 afi, safi);
10836 return CMD_WARNING;
10837 }
019386c2 10838
5cb5f4d0 10839 vty_out(vty, "BGP %s RIB statistics\n", get_afi_safi_str(afi, safi, false));
019386c2 10840
d62a17ae 10841 /* labeled-unicast routes live in the unicast table */
10842 if (safi == SAFI_LABELED_UNICAST)
10843 safi = SAFI_UNICAST;
019386c2 10844
d62a17ae 10845 memset(&ts, 0, sizeof(ts));
10846 ts.table = bgp->rib[afi][safi];
10847 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 10848
d62a17ae 10849 for (i = 0; i < BGP_STATS_MAX; i++) {
10850 if (!table_stats_strs[i])
10851 continue;
10852
10853 switch (i) {
a636c635
DW
10854#if 0
10855 case BGP_STATS_ASPATH_AVGHOPS:
10856 case BGP_STATS_ASPATH_AVGSIZE:
10857 case BGP_STATS_AVGPLEN:
10858 vty_out (vty, "%-30s: ", table_stats_strs[i]);
10859 vty_out (vty, "%12.2f",
10860 (float)ts.counts[i] / (float)TALLY_SIGFIG);
10861 break;
10862#endif
d62a17ae 10863 case BGP_STATS_ASPATH_TOTHOPS:
10864 case BGP_STATS_ASPATH_TOTSIZE:
10865 vty_out(vty, "%-30s: ", table_stats_strs[i]);
10866 vty_out(vty, "%12.2f",
10867 ts.counts[i]
10868 ? (float)ts.counts[i]
10869 / (float)ts.counts
10870 [BGP_STATS_ASPATH_COUNT]
10871 : 0);
10872 break;
10873 case BGP_STATS_TOTPLEN:
10874 vty_out(vty, "%-30s: ", table_stats_strs[i]);
10875 vty_out(vty, "%12.2f",
10876 ts.counts[i]
10877 ? (float)ts.counts[i]
10878 / (float)ts.counts
10879 [BGP_STATS_PREFIXES]
10880 : 0);
10881 break;
10882 case BGP_STATS_SPACE:
10883 vty_out(vty, "%-30s: ", table_stats_strs[i]);
8d0ab76d
DL
10884 vty_out(vty, "%12g\n", ts.total_space);
10885
10886 if (afi == AFI_IP6) {
10887 vty_out(vty, "%30s: ", "/32 equivalent ");
10888 vty_out(vty, "%12g\n",
a4d82a8a 10889 ts.total_space * pow(2.0, -128 + 32));
8d0ab76d
DL
10890 vty_out(vty, "%30s: ", "/48 equivalent ");
10891 vty_out(vty, "%12g\n",
a4d82a8a 10892 ts.total_space * pow(2.0, -128 + 48));
8d0ab76d
DL
10893 } else {
10894 vty_out(vty, "%30s: ", "% announced ");
10895 vty_out(vty, "%12.2f\n",
10896 ts.total_space * 100. * pow(2.0, -32));
10897 vty_out(vty, "%30s: ", "/8 equivalent ");
10898 vty_out(vty, "%12.2f\n",
a4d82a8a 10899 ts.total_space * pow(2.0, -32 + 8));
8d0ab76d
DL
10900 vty_out(vty, "%30s: ", "/24 equivalent ");
10901 vty_out(vty, "%12.2f\n",
a4d82a8a 10902 ts.total_space * pow(2.0, -32 + 24));
8d0ab76d 10903 }
d62a17ae 10904 break;
10905 default:
10906 vty_out(vty, "%-30s: ", table_stats_strs[i]);
10907 vty_out(vty, "%12llu", ts.counts[i]);
10908 }
ff7924f6 10909
d62a17ae 10910 vty_out(vty, "\n");
10911 }
10912 return CMD_SUCCESS;
10913}
10914
10915enum bgp_pcounts {
10916 PCOUNT_ADJ_IN = 0,
10917 PCOUNT_DAMPED,
10918 PCOUNT_REMOVED,
10919 PCOUNT_HISTORY,
10920 PCOUNT_STALE,
10921 PCOUNT_VALID,
10922 PCOUNT_ALL,
10923 PCOUNT_COUNTED,
10924 PCOUNT_PFCNT, /* the figure we display to users */
10925 PCOUNT_MAX,
a636c635 10926};
718e3744 10927
d62a17ae 10928static const char *pcount_strs[] = {
9d303b37
DL
10929 [PCOUNT_ADJ_IN] = "Adj-in",
10930 [PCOUNT_DAMPED] = "Damped",
10931 [PCOUNT_REMOVED] = "Removed",
10932 [PCOUNT_HISTORY] = "History",
10933 [PCOUNT_STALE] = "Stale",
10934 [PCOUNT_VALID] = "Valid",
10935 [PCOUNT_ALL] = "All RIB",
10936 [PCOUNT_COUNTED] = "PfxCt counted",
10937 [PCOUNT_PFCNT] = "Useable",
10938 [PCOUNT_MAX] = NULL,
a636c635 10939};
718e3744 10940
d62a17ae 10941struct peer_pcounts {
10942 unsigned int count[PCOUNT_MAX];
10943 const struct peer *peer;
10944 const struct bgp_table *table;
a636c635 10945};
47fc97cc 10946
d62a17ae 10947static int bgp_peer_count_walker(struct thread *t)
10948{
10949 struct bgp_node *rn;
10950 struct peer_pcounts *pc = THREAD_ARG(t);
10951 const struct peer *peer = pc->peer;
10952
10953 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn)) {
10954 struct bgp_adj_in *ain;
40381db7 10955 struct bgp_path_info *pi;
d62a17ae 10956
10957 for (ain = rn->adj_in; ain; ain = ain->next)
10958 if (ain->peer == peer)
10959 pc->count[PCOUNT_ADJ_IN]++;
10960
6f94b685
DS
10961 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
10962
40381db7 10963 if (pi->peer != peer)
d62a17ae 10964 continue;
10965
10966 pc->count[PCOUNT_ALL]++;
10967
40381db7 10968 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
d62a17ae 10969 pc->count[PCOUNT_DAMPED]++;
40381db7 10970 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
d62a17ae 10971 pc->count[PCOUNT_HISTORY]++;
40381db7 10972 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
d62a17ae 10973 pc->count[PCOUNT_REMOVED]++;
40381db7 10974 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 10975 pc->count[PCOUNT_STALE]++;
40381db7 10976 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
d62a17ae 10977 pc->count[PCOUNT_VALID]++;
40381db7 10978 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
d62a17ae 10979 pc->count[PCOUNT_PFCNT]++;
10980
40381db7 10981 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 10982 pc->count[PCOUNT_COUNTED]++;
40381db7 10983 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
1c50c1c0
QY
10984 flog_err(
10985 EC_LIB_DEVELOPMENT,
10986 "Attempting to count but flags say it is unusable");
d62a17ae 10987 } else {
40381db7 10988 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
1c50c1c0
QY
10989 flog_err(
10990 EC_LIB_DEVELOPMENT,
10991 "Not counted but flags say we should");
d62a17ae 10992 }
10993 }
10994 }
10995 return 0;
718e3744 10996}
10997
d62a17ae 10998static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 10999 safi_t safi, bool use_json)
856ca177 11000{
d62a17ae 11001 struct peer_pcounts pcounts = {.peer = peer};
11002 unsigned int i;
11003 json_object *json = NULL;
11004 json_object *json_loop = NULL;
856ca177 11005
d62a17ae 11006 if (use_json) {
11007 json = json_object_new_object();
11008 json_loop = json_object_new_object();
11009 }
718e3744 11010
d62a17ae 11011 if (!peer || !peer->bgp || !peer->afc[afi][safi]
11012 || !peer->bgp->rib[afi][safi]) {
11013 if (use_json) {
11014 json_object_string_add(
11015 json, "warning",
11016 "No such neighbor or address family");
11017 vty_out(vty, "%s\n", json_object_to_json_string(json));
11018 json_object_free(json);
11019 } else
11020 vty_out(vty, "%% No such neighbor or address family\n");
11021
11022 return CMD_WARNING;
11023 }
2a71e9ce 11024
d62a17ae 11025 memset(&pcounts, 0, sizeof(pcounts));
11026 pcounts.peer = peer;
11027 pcounts.table = peer->bgp->rib[afi][safi];
11028
11029 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
11030 * stats for the thread-walk (i.e. ensure this can't be blamed on
11031 * on just vty_read()).
11032 */
d62a17ae 11033 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
11034
11035 if (use_json) {
11036 json_object_string_add(json, "prefixCountsFor", peer->host);
11037 json_object_string_add(json, "multiProtocol",
5cb5f4d0 11038 get_afi_safi_str(afi, safi, true));
d62a17ae 11039 json_object_int_add(json, "pfxCounter",
11040 peer->pcount[afi][safi]);
11041
11042 for (i = 0; i < PCOUNT_MAX; i++)
11043 json_object_int_add(json_loop, pcount_strs[i],
11044 pcounts.count[i]);
11045
11046 json_object_object_add(json, "ribTableWalkCounters", json_loop);
11047
11048 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
11049 json_object_string_add(json, "pfxctDriftFor",
11050 peer->host);
11051 json_object_string_add(
11052 json, "recommended",
11053 "Please report this bug, with the above command output");
11054 }
996c9314
LB
11055 vty_out(vty, "%s\n", json_object_to_json_string_ext(
11056 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 11057 json_object_free(json);
11058 } else {
11059
11060 if (peer->hostname
11061 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
11062 vty_out(vty, "Prefix counts for %s/%s, %s\n",
11063 peer->hostname, peer->host,
5cb5f4d0 11064 get_afi_safi_str(afi, safi, false));
d62a17ae 11065 } else {
11066 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 11067 get_afi_safi_str(afi, safi, false));
d62a17ae 11068 }
11069
11070 vty_out(vty, "PfxCt: %ld\n", peer->pcount[afi][safi]);
11071 vty_out(vty, "\nCounts from RIB table walk:\n\n");
11072
11073 for (i = 0; i < PCOUNT_MAX; i++)
11074 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
11075 pcounts.count[i]);
11076
11077 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
11078 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
11079 vty_out(vty,
11080 "Please report this bug, with the above command output\n");
11081 }
11082 }
11083
11084 return CMD_SUCCESS;
718e3744 11085}
11086
a636c635
DW
11087DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
11088 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
c1a44e43 11089 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] "
30a6a167 11090 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
718e3744 11091 SHOW_STR
11092 IP_STR
11093 BGP_STR
8386ac43 11094 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
11095 BGP_AFI_HELP_STR
11096 BGP_SAFI_HELP_STR
0b16f239
DS
11097 "Detailed information on TCP and BGP neighbor connections\n"
11098 "Neighbor to display information about\n"
11099 "Neighbor to display information about\n"
91d37724 11100 "Neighbor on BGP configured interface\n"
a636c635 11101 "Display detailed prefix count information\n"
9973d184 11102 JSON_STR)
0b16f239 11103{
d62a17ae 11104 afi_t afi = AFI_IP6;
11105 safi_t safi = SAFI_UNICAST;
11106 struct peer *peer;
11107 int idx = 0;
11108 struct bgp *bgp = NULL;
9f049418
DS
11109 bool uj = use_json(argc, argv);
11110
11111 if (uj)
11112 argc--;
856ca177 11113
d62a17ae 11114 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11115 &bgp, uj);
d62a17ae 11116 if (!idx)
11117 return CMD_WARNING;
0b16f239 11118
d62a17ae 11119 argv_find(argv, argc, "neighbors", &idx);
11120 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
11121 if (!peer)
11122 return CMD_WARNING;
bb46e94f 11123
29c8d9da 11124 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 11125}
0b16f239 11126
d6902373
PG
11127#ifdef KEEP_OLD_VPN_COMMANDS
11128DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
11129 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
11130 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
11131 SHOW_STR
11132 IP_STR
11133 BGP_STR
d6902373 11134 BGP_VPNVX_HELP_STR
91d37724 11135 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
11136 "Detailed information on TCP and BGP neighbor connections\n"
11137 "Neighbor to display information about\n"
11138 "Neighbor to display information about\n"
91d37724 11139 "Neighbor on BGP configured interface\n"
a636c635 11140 "Display detailed prefix count information\n"
9973d184 11141 JSON_STR)
a636c635 11142{
d62a17ae 11143 int idx_peer = 6;
11144 struct peer *peer;
9f049418 11145 bool uj = use_json(argc, argv);
a636c635 11146
d62a17ae 11147 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
11148 if (!peer)
11149 return CMD_WARNING;
11150
11151 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
11152}
11153
d6902373
PG
11154DEFUN (show_ip_bgp_vpn_all_route_prefix,
11155 show_ip_bgp_vpn_all_route_prefix_cmd,
11156 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
11157 SHOW_STR
11158 IP_STR
11159 BGP_STR
d6902373 11160 BGP_VPNVX_HELP_STR
91d37724
QY
11161 "Display information about all VPNv4 NLRIs\n"
11162 "Network in the BGP routing table to display\n"
3a2d747c 11163 "Network in the BGP routing table to display\n"
9973d184 11164 JSON_STR)
91d37724 11165{
d62a17ae 11166 int idx = 0;
11167 char *network = NULL;
11168 struct bgp *bgp = bgp_get_default();
11169 if (!bgp) {
11170 vty_out(vty, "Can't find default instance\n");
11171 return CMD_WARNING;
11172 }
87e34b58 11173
d62a17ae 11174 if (argv_find(argv, argc, "A.B.C.D", &idx))
11175 network = argv[idx]->arg;
11176 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
11177 network = argv[idx]->arg;
11178 else {
11179 vty_out(vty, "Unable to figure out Network\n");
11180 return CMD_WARNING;
11181 }
87e34b58 11182
d62a17ae 11183 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 11184 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 11185}
d6902373 11186#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 11187
44c69747
LK
11188DEFUN (show_bgp_l2vpn_evpn_route_prefix,
11189 show_bgp_l2vpn_evpn_route_prefix_cmd,
11190 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 11191 SHOW_STR
4c63a661
PG
11192 BGP_STR
11193 L2VPN_HELP_STR
11194 EVPN_HELP_STR
44c69747
LK
11195 "Network in the BGP routing table to display\n"
11196 "Network in the BGP routing table to display\n"
4c63a661
PG
11197 "Network in the BGP routing table to display\n"
11198 "Network in the BGP routing table to display\n"
11199 JSON_STR)
11200{
d62a17ae 11201 int idx = 0;
11202 char *network = NULL;
44c69747 11203 int prefix_check = 0;
a636c635 11204
44c69747
LK
11205 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
11206 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 11207 network = argv[idx]->arg;
44c69747
LK
11208 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
11209 argv_find(argv, argc, "A.B.C.D/M", &idx)) {
d62a17ae 11210 network = argv[idx]->arg;
44c69747
LK
11211 prefix_check = 1;
11212 } else {
d62a17ae 11213 vty_out(vty, "Unable to figure out Network\n");
11214 return CMD_WARNING;
11215 }
44c69747
LK
11216 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
11217 prefix_check, BGP_PATH_SHOW_ALL,
11218 use_json(argc, argv));
d62a17ae 11219}
11220
11221static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 11222 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 11223 const char *rmap_name, bool use_json,
6392aaa6 11224 json_object *json)
d62a17ae 11225{
11226 struct bgp_table *table;
11227 struct bgp_adj_in *ain;
11228 struct bgp_adj_out *adj;
11229 unsigned long output_count;
11230 unsigned long filtered_count;
11231 struct bgp_node *rn;
11232 int header1 = 1;
11233 struct bgp *bgp;
11234 int header2 = 1;
11235 struct attr attr;
11236 int ret;
11237 struct update_subgroup *subgrp;
11238 json_object *json_scode = NULL;
11239 json_object *json_ocode = NULL;
11240 json_object *json_ar = NULL;
11241 struct peer_af *paf;
f99def61 11242 bool route_filtered;
d62a17ae 11243
11244 if (use_json) {
11245 json_scode = json_object_new_object();
11246 json_ocode = json_object_new_object();
11247 json_ar = json_object_new_object();
11248
11249 json_object_string_add(json_scode, "suppressed", "s");
11250 json_object_string_add(json_scode, "damped", "d");
11251 json_object_string_add(json_scode, "history", "h");
11252 json_object_string_add(json_scode, "valid", "*");
11253 json_object_string_add(json_scode, "best", ">");
11254 json_object_string_add(json_scode, "multipath", "=");
11255 json_object_string_add(json_scode, "internal", "i");
11256 json_object_string_add(json_scode, "ribFailure", "r");
11257 json_object_string_add(json_scode, "stale", "S");
11258 json_object_string_add(json_scode, "removed", "R");
11259
11260 json_object_string_add(json_ocode, "igp", "i");
11261 json_object_string_add(json_ocode, "egp", "e");
11262 json_object_string_add(json_ocode, "incomplete", "?");
11263 }
a636c635 11264
d62a17ae 11265 bgp = peer->bgp;
a636c635 11266
d62a17ae 11267 if (!bgp) {
11268 if (use_json) {
11269 json_object_string_add(json, "alert", "no BGP");
11270 vty_out(vty, "%s\n", json_object_to_json_string(json));
11271 json_object_free(json);
11272 } else
11273 vty_out(vty, "%% No bgp\n");
11274 return;
11275 }
a636c635 11276
c512a642
EDP
11277 /* labeled-unicast routes live in the unicast table */
11278 if (safi == SAFI_LABELED_UNICAST)
11279 table = bgp->rib[afi][SAFI_UNICAST];
11280 else
11281 table = bgp->rib[afi][safi];
d62a17ae 11282
11283 output_count = filtered_count = 0;
11284 subgrp = peer_subgroup(peer, afi, safi);
11285
6392aaa6 11286 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 11287 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
11288 if (use_json) {
11289 json_object_int_add(json, "bgpTableVersion",
11290 table->version);
11291 json_object_string_add(json, "bgpLocalRouterId",
11292 inet_ntoa(bgp->router_id));
01eced22
AD
11293 json_object_int_add(json, "defaultLocPrf",
11294 bgp->default_local_pref);
11295 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 11296 json_object_object_add(json, "bgpStatusCodes",
11297 json_scode);
11298 json_object_object_add(json, "bgpOriginCodes",
11299 json_ocode);
07d0c4ed
DA
11300 json_object_string_add(
11301 json, "bgpOriginatingDefaultNetwork",
11302 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 11303 } else {
996c9314 11304 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 11305 ", local router ID is %s, vrf id ",
d62a17ae 11306 table->version, inet_ntoa(bgp->router_id));
9df8b37c
PZ
11307 if (bgp->vrf_id == VRF_UNKNOWN)
11308 vty_out(vty, "%s", VRFID_NONE_STR);
11309 else
11310 vty_out(vty, "%u", bgp->vrf_id);
11311 vty_out(vty, "\n");
01eced22
AD
11312 vty_out(vty, "Default local pref %u, ",
11313 bgp->default_local_pref);
11314 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 11315 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11316 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 11317 vty_out(vty, BGP_SHOW_OCODE_HEADER);
11318
07d0c4ed
DA
11319 vty_out(vty, "Originating default network %s\n\n",
11320 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 11321 }
11322 header1 = 0;
11323 }
a636c635 11324
d62a17ae 11325 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6392aaa6
PM
11326 if (type == bgp_show_adj_route_received
11327 || type == bgp_show_adj_route_filtered) {
d62a17ae 11328 for (ain = rn->adj_in; ain; ain = ain->next) {
6392aaa6 11329 if (ain->peer != peer || !ain->attr)
ea47320b 11330 continue;
6392aaa6 11331
ea47320b
DL
11332 if (header1) {
11333 if (use_json) {
11334 json_object_int_add(
60466a63 11335 json, "bgpTableVersion",
ea47320b
DL
11336 0);
11337 json_object_string_add(
11338 json,
11339 "bgpLocalRouterId",
11340 inet_ntoa(
11341 bgp->router_id));
01eced22
AD
11342 json_object_int_add(json,
11343 "defaultLocPrf",
11344 bgp->default_local_pref);
11345 json_object_int_add(json,
11346 "localAS", bgp->as);
ea47320b 11347 json_object_object_add(
60466a63 11348 json, "bgpStatusCodes",
ea47320b
DL
11349 json_scode);
11350 json_object_object_add(
60466a63 11351 json, "bgpOriginCodes",
ea47320b
DL
11352 json_ocode);
11353 } else {
11354 vty_out(vty,
9df8b37c 11355 "BGP table version is 0, local router ID is %s, vrf id ",
ea47320b 11356 inet_ntoa(
9df8b37c
PZ
11357 bgp->router_id));
11358 if (bgp->vrf_id == VRF_UNKNOWN)
11359 vty_out(vty, "%s",
11360 VRFID_NONE_STR);
11361 else
11362 vty_out(vty, "%u",
11363 bgp->vrf_id);
11364 vty_out(vty, "\n");
01eced22
AD
11365 vty_out(vty,
11366 "Default local pref %u, ",
11367 bgp->default_local_pref);
11368 vty_out(vty, "local AS %u\n",
11369 bgp->as);
ea47320b
DL
11370 vty_out(vty,
11371 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
11372 vty_out(vty,
11373 BGP_SHOW_NCODE_HEADER);
ea47320b
DL
11374 vty_out(vty,
11375 BGP_SHOW_OCODE_HEADER);
d62a17ae 11376 }
ea47320b
DL
11377 header1 = 0;
11378 }
11379 if (header2) {
11380 if (!use_json)
11381 vty_out(vty, BGP_SHOW_HEADER);
11382 header2 = 0;
11383 }
6392aaa6
PM
11384
11385 bgp_attr_dup(&attr, ain->attr);
f99def61
AD
11386 route_filtered = false;
11387
11388 /* Filter prefix using distribute list,
11389 * filter list or prefix list
11390 */
11391 if ((bgp_input_filter(peer, &rn->p, &attr, afi,
11392 safi)) == FILTER_DENY)
11393 route_filtered = true;
11394
11395 /* Filter prefix using route-map */
6392aaa6 11396 ret = bgp_input_modifier(peer, &rn->p, &attr,
82b692c0 11397 afi, safi, rmap_name, NULL, 0);
6392aaa6 11398
13c8e163
AD
11399 if (type == bgp_show_adj_route_filtered &&
11400 !route_filtered && ret != RMAP_DENY) {
b755861b 11401 bgp_attr_undup(&attr, ain->attr);
6392aaa6 11402 continue;
d62a17ae 11403 }
6392aaa6 11404
13c8e163
AD
11405 if (type == bgp_show_adj_route_received &&
11406 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
11407 filtered_count++;
11408
11409 route_vty_out_tmp(vty, &rn->p, &attr, safi,
11410 use_json, json_ar);
b755861b 11411 bgp_attr_undup(&attr, ain->attr);
6392aaa6 11412 output_count++;
d62a17ae 11413 }
6392aaa6 11414 } else if (type == bgp_show_adj_route_advertised) {
a79c04e7 11415 RB_FOREACH (adj, bgp_adj_out_rb, &rn->adj_out)
924c3f6a 11416 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 11417 if (paf->peer != peer || !adj->attr)
924c3f6a 11418 continue;
d62a17ae 11419
924c3f6a
DS
11420 if (header1) {
11421 if (use_json) {
11422 json_object_int_add(
11423 json,
11424 "bgpTableVersion",
11425 table->version);
11426 json_object_string_add(
11427 json,
11428 "bgpLocalRouterId",
11429 inet_ntoa(
11430 bgp->router_id));
01eced22
AD
11431 json_object_int_add(
11432 json, "defaultLocPrf",
11433 bgp->default_local_pref
11434 );
11435 json_object_int_add(
11436 json, "localAS",
11437 bgp->as);
924c3f6a
DS
11438 json_object_object_add(
11439 json,
11440 "bgpStatusCodes",
11441 json_scode);
11442 json_object_object_add(
11443 json,
11444 "bgpOriginCodes",
11445 json_ocode);
11446 } else {
11447 vty_out(vty,
11448 "BGP table version is %" PRIu64
9df8b37c 11449 ", local router ID is %s, vrf id ",
924c3f6a
DS
11450 table->version,
11451 inet_ntoa(
11452 bgp->router_id));
9df8b37c
PZ
11453 if (bgp->vrf_id ==
11454 VRF_UNKNOWN)
11455 vty_out(vty,
11456 "%s",
11457 VRFID_NONE_STR);
11458 else
11459 vty_out(vty,
11460 "%u",
11461 bgp->vrf_id);
11462 vty_out(vty, "\n");
01eced22
AD
11463 vty_out(vty,
11464 "Default local pref %u, ",
11465 bgp->default_local_pref
11466 );
11467 vty_out(vty,
11468 "local AS %u\n",
11469 bgp->as);
924c3f6a
DS
11470 vty_out(vty,
11471 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
11472 vty_out(vty,
11473 BGP_SHOW_NCODE_HEADER);
924c3f6a
DS
11474 vty_out(vty,
11475 BGP_SHOW_OCODE_HEADER);
a2addae8 11476 }
924c3f6a
DS
11477 header1 = 0;
11478 }
924c3f6a
DS
11479 if (header2) {
11480 if (!use_json)
11481 vty_out(vty,
11482 BGP_SHOW_HEADER);
11483 header2 = 0;
11484 }
d62a17ae 11485
b755861b
PM
11486 bgp_attr_dup(&attr, adj->attr);
11487 ret = bgp_output_modifier(
11488 peer, &rn->p, &attr, afi, safi,
11489 rmap_name);
f46d8e1e 11490
b755861b
PM
11491 if (ret != RMAP_DENY) {
11492 route_vty_out_tmp(vty, &rn->p,
11493 &attr, safi,
11494 use_json,
11495 json_ar);
11496 output_count++;
11497 } else {
11498 filtered_count++;
a2addae8 11499 }
b755861b
PM
11500
11501 bgp_attr_undup(&attr, adj->attr);
924c3f6a 11502 }
d62a17ae 11503 }
11504 }
d62a17ae 11505
d62a17ae 11506 if (use_json) {
6392aaa6
PM
11507 json_object_object_add(json, "advertisedRoutes", json_ar);
11508 json_object_int_add(json, "totalPrefixCounter", output_count);
11509 json_object_int_add(json, "filteredPrefixCounter",
11510 filtered_count);
11511
996c9314
LB
11512 vty_out(vty, "%s\n", json_object_to_json_string_ext(
11513 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 11514 json_object_free(json);
6392aaa6
PM
11515 } else if (output_count > 0) {
11516 if (filtered_count > 0)
11517 vty_out(vty,
11518 "\nTotal number of prefixes %ld (%ld filtered)\n",
11519 output_count, filtered_count);
11520 else
11521 vty_out(vty, "\nTotal number of prefixes %ld\n",
11522 output_count);
d62a17ae 11523 }
a636c635 11524}
2a71e9ce 11525
d62a17ae 11526static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 11527 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 11528 const char *rmap_name, bool use_json)
0b16f239 11529{
d62a17ae 11530 json_object *json = NULL;
0b16f239 11531
d62a17ae 11532 if (use_json)
11533 json = json_object_new_object();
0b16f239 11534
d62a17ae 11535 if (!peer || !peer->afc[afi][safi]) {
11536 if (use_json) {
11537 json_object_string_add(
11538 json, "warning",
11539 "No such neighbor or address family");
11540 vty_out(vty, "%s\n", json_object_to_json_string(json));
11541 json_object_free(json);
11542 } else
11543 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 11544
d62a17ae 11545 return CMD_WARNING;
11546 }
11547
6392aaa6
PM
11548 if ((type == bgp_show_adj_route_received
11549 || type == bgp_show_adj_route_filtered)
d62a17ae 11550 && !CHECK_FLAG(peer->af_flags[afi][safi],
11551 PEER_FLAG_SOFT_RECONFIG)) {
11552 if (use_json) {
11553 json_object_string_add(
11554 json, "warning",
11555 "Inbound soft reconfiguration not enabled");
11556 vty_out(vty, "%s\n", json_object_to_json_string(json));
11557 json_object_free(json);
11558 } else
11559 vty_out(vty,
11560 "%% Inbound soft reconfiguration not enabled\n");
11561
11562 return CMD_WARNING;
11563 }
0b16f239 11564
6392aaa6 11565 show_adj_route(vty, peer, afi, safi, type, rmap_name, use_json, json);
0b16f239 11566
d62a17ae 11567 return CMD_SUCCESS;
a636c635 11568}
50ef26d4 11569
a636c635
DW
11570DEFUN (show_ip_bgp_instance_neighbor_advertised_route,
11571 show_ip_bgp_instance_neighbor_advertised_route_cmd,
4dd6177e 11572 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
6392aaa6 11573 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
718e3744 11574 SHOW_STR
11575 IP_STR
11576 BGP_STR
a636c635 11577 BGP_INSTANCE_HELP_STR
7395a2c9 11578 BGP_AFI_HELP_STR
4dd6177e 11579 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 11580 "Detailed information on TCP and BGP neighbor connections\n"
11581 "Neighbor to display information about\n"
11582 "Neighbor to display information about\n"
91d37724 11583 "Neighbor on BGP configured interface\n"
a636c635 11584 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
11585 "Display the received routes from neighbor\n"
11586 "Display the filtered routes received from neighbor\n"
a636c635
DW
11587 "Route-map to modify the attributes\n"
11588 "Name of the route map\n"
9973d184 11589 JSON_STR)
718e3744 11590{
d62a17ae 11591 afi_t afi = AFI_IP6;
11592 safi_t safi = SAFI_UNICAST;
11593 char *rmap_name = NULL;
11594 char *peerstr = NULL;
d62a17ae 11595 struct bgp *bgp = NULL;
11596 struct peer *peer;
6392aaa6 11597 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 11598 int idx = 0;
9f049418 11599 bool uj = use_json(argc, argv);
6392aaa6 11600
d62a17ae 11601 if (uj)
11602 argc--;
30a6a167 11603
9f049418
DS
11604 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11605 &bgp, uj);
11606 if (!idx)
11607 return CMD_WARNING;
11608
d62a17ae 11609 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11610 argv_find(argv, argc, "neighbors", &idx);
11611 peerstr = argv[++idx]->arg;
8c3deaae 11612
d62a17ae 11613 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
11614 if (!peer)
11615 return CMD_WARNING;
856ca177 11616
d62a17ae 11617 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
11618 type = bgp_show_adj_route_advertised;
11619 else if (argv_find(argv, argc, "received-routes", &idx))
11620 type = bgp_show_adj_route_received;
11621 else if (argv_find(argv, argc, "filtered-routes", &idx))
11622 type = bgp_show_adj_route_filtered;
11623
d62a17ae 11624 if (argv_find(argv, argc, "route-map", &idx))
11625 rmap_name = argv[++idx]->arg;
95cbbd2a 11626
6392aaa6 11627 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj);
95cbbd2a
ML
11628}
11629
718e3744 11630DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
11631 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 11632 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 11633 SHOW_STR
11634 IP_STR
11635 BGP_STR
8c3deaae
QY
11636 "Address Family\n"
11637 "Address Family\n"
718e3744 11638 "Address Family modifier\n"
11639 "Detailed information on TCP and BGP neighbor connections\n"
11640 "Neighbor to display information about\n"
11641 "Neighbor to display information about\n"
91d37724 11642 "Neighbor on BGP configured interface\n"
718e3744 11643 "Display information received from a BGP neighbor\n"
856ca177 11644 "Display the prefixlist filter\n"
9973d184 11645 JSON_STR)
718e3744 11646{
d62a17ae 11647 afi_t afi = AFI_IP6;
11648 safi_t safi = SAFI_UNICAST;
11649 char *peerstr = NULL;
11650
11651 char name[BUFSIZ];
11652 union sockunion su;
11653 struct peer *peer;
11654 int count, ret;
11655
11656 int idx = 0;
11657
11658 /* show [ip] bgp */
11659 if (argv_find(argv, argc, "ip", &idx))
11660 afi = AFI_IP;
11661 /* [<ipv4|ipv6> [unicast]] */
11662 if (argv_find(argv, argc, "ipv4", &idx))
11663 afi = AFI_IP;
11664 if (argv_find(argv, argc, "ipv6", &idx))
11665 afi = AFI_IP6;
11666 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11667 argv_find(argv, argc, "neighbors", &idx);
11668 peerstr = argv[++idx]->arg;
11669
9f049418 11670 bool uj = use_json(argc, argv);
d62a17ae 11671
11672 ret = str2sockunion(peerstr, &su);
11673 if (ret < 0) {
11674 peer = peer_lookup_by_conf_if(NULL, peerstr);
11675 if (!peer) {
11676 if (uj)
11677 vty_out(vty, "{}\n");
11678 else
11679 vty_out(vty,
11680 "%% Malformed address or name: %s\n",
11681 peerstr);
11682 return CMD_WARNING;
11683 }
11684 } else {
11685 peer = peer_lookup(NULL, &su);
11686 if (!peer) {
11687 if (uj)
11688 vty_out(vty, "{}\n");
11689 else
11690 vty_out(vty, "No peer\n");
11691 return CMD_WARNING;
11692 }
11693 }
718e3744 11694
d62a17ae 11695 sprintf(name, "%s.%d.%d", peer->host, afi, safi);
11696 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
11697 if (count) {
11698 if (!uj)
11699 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 11700 get_afi_safi_str(afi, safi, false));
d62a17ae 11701 prefix_bgp_show_prefix_list(vty, afi, name, uj);
11702 } else {
11703 if (uj)
11704 vty_out(vty, "{}\n");
11705 else
11706 vty_out(vty, "No functional output\n");
11707 }
718e3744 11708
d62a17ae 11709 return CMD_SUCCESS;
11710}
11711
11712static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
11713 afi_t afi, safi_t safi,
9f049418 11714 enum bgp_show_type type, bool use_json)
d62a17ae 11715{
8a893163
DW
11716 /* labeled-unicast routes live in the unicast table */
11717 if (safi == SAFI_LABELED_UNICAST)
11718 safi = SAFI_UNICAST;
11719
d62a17ae 11720 if (!peer || !peer->afc[afi][safi]) {
11721 if (use_json) {
11722 json_object *json_no = NULL;
11723 json_no = json_object_new_object();
11724 json_object_string_add(
11725 json_no, "warning",
11726 "No such neighbor or address family");
11727 vty_out(vty, "%s\n",
11728 json_object_to_json_string(json_no));
11729 json_object_free(json_no);
11730 } else
11731 vty_out(vty, "%% No such neighbor or address family\n");
11732 return CMD_WARNING;
11733 }
47fc97cc 11734
d62a17ae 11735 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json);
718e3744 11736}
11737
dba3c1d3
PG
11738DEFUN (show_ip_bgp_flowspec_routes_detailed,
11739 show_ip_bgp_flowspec_routes_detailed_cmd,
11740 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
11741 SHOW_STR
11742 IP_STR
11743 BGP_STR
11744 BGP_INSTANCE_HELP_STR
11745 BGP_AFI_HELP_STR
11746 "SAFI Flowspec\n"
11747 "Detailed information on flowspec entries\n"
11748 JSON_STR)
11749{
11750 afi_t afi = AFI_IP;
11751 safi_t safi = SAFI_UNICAST;
11752 struct bgp *bgp = NULL;
11753 int idx = 0;
9f049418
DS
11754 bool uj = use_json(argc, argv);
11755
11756 if (uj)
11757 argc--;
dba3c1d3
PG
11758
11759 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11760 &bgp, uj);
dba3c1d3
PG
11761 if (!idx)
11762 return CMD_WARNING;
11763
9f049418 11764 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL, uj);
dba3c1d3
PG
11765}
11766
718e3744 11767DEFUN (show_ip_bgp_neighbor_routes,
11768 show_ip_bgp_neighbor_routes_cmd,
4dd6177e 11769 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
30a6a167 11770 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
50ef26d4 11771 SHOW_STR
11772 IP_STR
11773 BGP_STR
8386ac43 11774 BGP_INSTANCE_HELP_STR
4f280b15 11775 BGP_AFI_HELP_STR
4dd6177e 11776 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 11777 "Detailed information on TCP and BGP neighbor connections\n"
11778 "Neighbor to display information about\n"
11779 "Neighbor to display information about\n"
91d37724 11780 "Neighbor on BGP configured interface\n"
2525cf39 11781 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
11782 "Display the dampened routes received from neighbor\n"
11783 "Display routes learned from neighbor\n"
9973d184 11784 JSON_STR)
718e3744 11785{
d62a17ae 11786 char *peerstr = NULL;
11787 struct bgp *bgp = NULL;
11788 afi_t afi = AFI_IP6;
11789 safi_t safi = SAFI_UNICAST;
11790 struct peer *peer;
11791 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 11792 int idx = 0;
9f049418
DS
11793 bool uj = use_json(argc, argv);
11794
11795 if (uj)
11796 argc--;
bb46e94f 11797
d62a17ae 11798 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11799 &bgp, uj);
d62a17ae 11800 if (!idx)
11801 return CMD_WARNING;
c493f2d8 11802
d62a17ae 11803 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11804 argv_find(argv, argc, "neighbors", &idx);
11805 peerstr = argv[++idx]->arg;
8c3deaae 11806
d62a17ae 11807 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 11808 if (!peer)
d62a17ae 11809 return CMD_WARNING;
bb46e94f 11810
d62a17ae 11811 if (argv_find(argv, argc, "flap-statistics", &idx))
11812 sh_type = bgp_show_type_flap_neighbor;
11813 else if (argv_find(argv, argc, "dampened-routes", &idx))
11814 sh_type = bgp_show_type_damp_neighbor;
11815 else if (argv_find(argv, argc, "routes", &idx))
11816 sh_type = bgp_show_type_neighbor;
2525cf39 11817
d62a17ae 11818 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 11819}
6b0655a2 11820
734b349e 11821struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 11822
d62a17ae 11823struct bgp_distance {
11824 /* Distance value for the IP source prefix. */
d7c0a89a 11825 uint8_t distance;
718e3744 11826
d62a17ae 11827 /* Name of the access-list to be matched. */
11828 char *access_list;
718e3744 11829};
11830
4f280b15
LB
11831DEFUN (show_bgp_afi_vpn_rd_route,
11832 show_bgp_afi_vpn_rd_route_cmd,
d114b977 11833 "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
11834 SHOW_STR
11835 BGP_STR
11836 BGP_AFI_HELP_STR
11837 "Address Family modifier\n"
11838 "Display information for a route distinguisher\n"
11839 "Route Distinguisher\n"
7395a2c9
DS
11840 "Network in the BGP routing table to display\n"
11841 "Network in the BGP routing table to display\n"
11842 JSON_STR)
4f280b15 11843{
d62a17ae 11844 int ret;
11845 struct prefix_rd prd;
11846 afi_t afi = AFI_MAX;
11847 int idx = 0;
4f280b15 11848
ff6566f3
DS
11849 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
11850 vty_out(vty, "%% Malformed Address Family\n");
11851 return CMD_WARNING;
11852 }
11853
d62a17ae 11854 ret = str2prefix_rd(argv[5]->arg, &prd);
11855 if (!ret) {
11856 vty_out(vty, "%% Malformed Route Distinguisher\n");
11857 return CMD_WARNING;
11858 }
ff6566f3 11859
d62a17ae 11860 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 11861 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
11862}
11863
d62a17ae 11864static struct bgp_distance *bgp_distance_new(void)
718e3744 11865{
d62a17ae 11866 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 11867}
11868
d62a17ae 11869static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 11870{
d62a17ae 11871 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 11872}
11873
d62a17ae 11874static int bgp_distance_set(struct vty *vty, const char *distance_str,
11875 const char *ip_str, const char *access_list_str)
718e3744 11876{
d62a17ae 11877 int ret;
11878 afi_t afi;
11879 safi_t safi;
11880 struct prefix p;
d7c0a89a 11881 uint8_t distance;
d62a17ae 11882 struct bgp_node *rn;
11883 struct bgp_distance *bdistance;
718e3744 11884
d62a17ae 11885 afi = bgp_node_afi(vty);
11886 safi = bgp_node_safi(vty);
734b349e 11887
d62a17ae 11888 ret = str2prefix(ip_str, &p);
11889 if (ret == 0) {
11890 vty_out(vty, "Malformed prefix\n");
11891 return CMD_WARNING_CONFIG_FAILED;
11892 }
718e3744 11893
d62a17ae 11894 distance = atoi(distance_str);
718e3744 11895
d62a17ae 11896 /* Get BGP distance node. */
11897 rn = bgp_node_get(bgp_distance_table[afi][safi], (struct prefix *)&p);
5b00b40e 11898 bdistance = bgp_node_get_bgp_distance_info(rn);
ca2e160d 11899 if (bdistance)
d62a17ae 11900 bgp_unlock_node(rn);
ca2e160d 11901 else {
d62a17ae 11902 bdistance = bgp_distance_new();
5b00b40e 11903 bgp_node_set_bgp_distance_info(rn, bdistance);
d62a17ae 11904 }
718e3744 11905
d62a17ae 11906 /* Set distance value. */
11907 bdistance->distance = distance;
718e3744 11908
d62a17ae 11909 /* Reset access-list configuration. */
11910 if (bdistance->access_list) {
11911 XFREE(MTYPE_AS_LIST, bdistance->access_list);
11912 bdistance->access_list = NULL;
11913 }
11914 if (access_list_str)
11915 bdistance->access_list =
11916 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 11917
d62a17ae 11918 return CMD_SUCCESS;
718e3744 11919}
11920
d62a17ae 11921static int bgp_distance_unset(struct vty *vty, const char *distance_str,
11922 const char *ip_str, const char *access_list_str)
718e3744 11923{
d62a17ae 11924 int ret;
11925 afi_t afi;
11926 safi_t safi;
11927 struct prefix p;
11928 int distance;
11929 struct bgp_node *rn;
11930 struct bgp_distance *bdistance;
718e3744 11931
d62a17ae 11932 afi = bgp_node_afi(vty);
11933 safi = bgp_node_safi(vty);
734b349e 11934
d62a17ae 11935 ret = str2prefix(ip_str, &p);
11936 if (ret == 0) {
11937 vty_out(vty, "Malformed prefix\n");
11938 return CMD_WARNING_CONFIG_FAILED;
11939 }
718e3744 11940
d62a17ae 11941 rn = bgp_node_lookup(bgp_distance_table[afi][safi],
11942 (struct prefix *)&p);
11943 if (!rn) {
11944 vty_out(vty, "Can't find specified prefix\n");
11945 return CMD_WARNING_CONFIG_FAILED;
11946 }
718e3744 11947
5b00b40e 11948 bdistance = bgp_node_get_bgp_distance_info(rn);
d62a17ae 11949 distance = atoi(distance_str);
1f9a9fff 11950
d62a17ae 11951 if (bdistance->distance != distance) {
11952 vty_out(vty, "Distance does not match configured\n");
11953 return CMD_WARNING_CONFIG_FAILED;
11954 }
718e3744 11955
0a22ddfb 11956 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 11957 bgp_distance_free(bdistance);
718e3744 11958
6f94b685 11959 bgp_node_set_bgp_path_info(rn, NULL);
d62a17ae 11960 bgp_unlock_node(rn);
11961 bgp_unlock_node(rn);
718e3744 11962
d62a17ae 11963 return CMD_SUCCESS;
718e3744 11964}
11965
718e3744 11966/* Apply BGP information to distance method. */
40381db7 11967uint8_t bgp_distance_apply(struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 11968 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 11969{
11970 struct bgp_node *rn;
11971 struct prefix q;
11972 struct peer *peer;
11973 struct bgp_distance *bdistance;
11974 struct access_list *alist;
11975 struct bgp_static *bgp_static;
11976
11977 if (!bgp)
11978 return 0;
11979
40381db7 11980 peer = pinfo->peer;
d62a17ae 11981
7b7d48e5
DS
11982 if (pinfo->attr->distance)
11983 return pinfo->attr->distance;
11984
d62a17ae 11985 /* Check source address. */
11986 sockunion2hostprefix(&peer->su, &q);
11987 rn = bgp_node_match(bgp_distance_table[afi][safi], &q);
11988 if (rn) {
5b00b40e 11989 bdistance = bgp_node_get_bgp_distance_info(rn);
d62a17ae 11990 bgp_unlock_node(rn);
11991
11992 if (bdistance->access_list) {
11993 alist = access_list_lookup(afi, bdistance->access_list);
11994 if (alist
11995 && access_list_apply(alist, p) == FILTER_PERMIT)
11996 return bdistance->distance;
11997 } else
11998 return bdistance->distance;
718e3744 11999 }
718e3744 12000
d62a17ae 12001 /* Backdoor check. */
12002 rn = bgp_node_lookup(bgp->route[afi][safi], p);
12003 if (rn) {
5a8ba9fc 12004 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 12005 bgp_unlock_node(rn);
718e3744 12006
d62a17ae 12007 if (bgp_static->backdoor) {
12008 if (bgp->distance_local[afi][safi])
12009 return bgp->distance_local[afi][safi];
12010 else
12011 return ZEBRA_IBGP_DISTANCE_DEFAULT;
12012 }
718e3744 12013 }
718e3744 12014
d62a17ae 12015 if (peer->sort == BGP_PEER_EBGP) {
12016 if (bgp->distance_ebgp[afi][safi])
12017 return bgp->distance_ebgp[afi][safi];
12018 return ZEBRA_EBGP_DISTANCE_DEFAULT;
12019 } else {
12020 if (bgp->distance_ibgp[afi][safi])
12021 return bgp->distance_ibgp[afi][safi];
12022 return ZEBRA_IBGP_DISTANCE_DEFAULT;
12023 }
718e3744 12024}
12025
12026DEFUN (bgp_distance,
12027 bgp_distance_cmd,
6147e2c6 12028 "distance bgp (1-255) (1-255) (1-255)",
718e3744 12029 "Define an administrative distance\n"
12030 "BGP distance\n"
12031 "Distance for routes external to the AS\n"
12032 "Distance for routes internal to the AS\n"
12033 "Distance for local routes\n")
12034{
d62a17ae 12035 VTY_DECLVAR_CONTEXT(bgp, bgp);
12036 int idx_number = 2;
12037 int idx_number_2 = 3;
12038 int idx_number_3 = 4;
12039 afi_t afi;
12040 safi_t safi;
718e3744 12041
d62a17ae 12042 afi = bgp_node_afi(vty);
12043 safi = bgp_node_safi(vty);
718e3744 12044
d62a17ae 12045 bgp->distance_ebgp[afi][safi] = atoi(argv[idx_number]->arg);
12046 bgp->distance_ibgp[afi][safi] = atoi(argv[idx_number_2]->arg);
12047 bgp->distance_local[afi][safi] = atoi(argv[idx_number_3]->arg);
12048 return CMD_SUCCESS;
718e3744 12049}
12050
12051DEFUN (no_bgp_distance,
12052 no_bgp_distance_cmd,
a636c635 12053 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 12054 NO_STR
12055 "Define an administrative distance\n"
12056 "BGP distance\n"
12057 "Distance for routes external to the AS\n"
12058 "Distance for routes internal to the AS\n"
12059 "Distance for local routes\n")
12060{
d62a17ae 12061 VTY_DECLVAR_CONTEXT(bgp, bgp);
12062 afi_t afi;
12063 safi_t safi;
718e3744 12064
d62a17ae 12065 afi = bgp_node_afi(vty);
12066 safi = bgp_node_safi(vty);
718e3744 12067
d62a17ae 12068 bgp->distance_ebgp[afi][safi] = 0;
12069 bgp->distance_ibgp[afi][safi] = 0;
12070 bgp->distance_local[afi][safi] = 0;
12071 return CMD_SUCCESS;
718e3744 12072}
12073
718e3744 12074
12075DEFUN (bgp_distance_source,
12076 bgp_distance_source_cmd,
6147e2c6 12077 "distance (1-255) A.B.C.D/M",
718e3744 12078 "Define an administrative distance\n"
12079 "Administrative distance\n"
12080 "IP source prefix\n")
12081{
d62a17ae 12082 int idx_number = 1;
12083 int idx_ipv4_prefixlen = 2;
12084 bgp_distance_set(vty, argv[idx_number]->arg,
12085 argv[idx_ipv4_prefixlen]->arg, NULL);
12086 return CMD_SUCCESS;
718e3744 12087}
12088
12089DEFUN (no_bgp_distance_source,
12090 no_bgp_distance_source_cmd,
6147e2c6 12091 "no distance (1-255) A.B.C.D/M",
718e3744 12092 NO_STR
12093 "Define an administrative distance\n"
12094 "Administrative distance\n"
12095 "IP source prefix\n")
12096{
d62a17ae 12097 int idx_number = 2;
12098 int idx_ipv4_prefixlen = 3;
12099 bgp_distance_unset(vty, argv[idx_number]->arg,
12100 argv[idx_ipv4_prefixlen]->arg, NULL);
12101 return CMD_SUCCESS;
718e3744 12102}
12103
12104DEFUN (bgp_distance_source_access_list,
12105 bgp_distance_source_access_list_cmd,
6147e2c6 12106 "distance (1-255) A.B.C.D/M WORD",
718e3744 12107 "Define an administrative distance\n"
12108 "Administrative distance\n"
12109 "IP source prefix\n"
12110 "Access list name\n")
12111{
d62a17ae 12112 int idx_number = 1;
12113 int idx_ipv4_prefixlen = 2;
12114 int idx_word = 3;
12115 bgp_distance_set(vty, argv[idx_number]->arg,
12116 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12117 return CMD_SUCCESS;
718e3744 12118}
12119
12120DEFUN (no_bgp_distance_source_access_list,
12121 no_bgp_distance_source_access_list_cmd,
6147e2c6 12122 "no distance (1-255) A.B.C.D/M WORD",
718e3744 12123 NO_STR
12124 "Define an administrative distance\n"
12125 "Administrative distance\n"
12126 "IP source prefix\n"
12127 "Access list name\n")
12128{
d62a17ae 12129 int idx_number = 2;
12130 int idx_ipv4_prefixlen = 3;
12131 int idx_word = 4;
12132 bgp_distance_unset(vty, argv[idx_number]->arg,
12133 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12134 return CMD_SUCCESS;
718e3744 12135}
6b0655a2 12136
734b349e
MZ
12137DEFUN (ipv6_bgp_distance_source,
12138 ipv6_bgp_distance_source_cmd,
39e92c06 12139 "distance (1-255) X:X::X:X/M",
734b349e
MZ
12140 "Define an administrative distance\n"
12141 "Administrative distance\n"
12142 "IP source prefix\n")
12143{
d62a17ae 12144 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
12145 return CMD_SUCCESS;
734b349e
MZ
12146}
12147
12148DEFUN (no_ipv6_bgp_distance_source,
12149 no_ipv6_bgp_distance_source_cmd,
39e92c06 12150 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
12151 NO_STR
12152 "Define an administrative distance\n"
12153 "Administrative distance\n"
12154 "IP source prefix\n")
12155{
d62a17ae 12156 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
12157 return CMD_SUCCESS;
734b349e
MZ
12158}
12159
12160DEFUN (ipv6_bgp_distance_source_access_list,
12161 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12162 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12163 "Define an administrative distance\n"
12164 "Administrative distance\n"
12165 "IP source prefix\n"
12166 "Access list name\n")
12167{
d62a17ae 12168 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
12169 return CMD_SUCCESS;
734b349e
MZ
12170}
12171
12172DEFUN (no_ipv6_bgp_distance_source_access_list,
12173 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12174 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12175 NO_STR
12176 "Define an administrative distance\n"
12177 "Administrative distance\n"
12178 "IP source prefix\n"
12179 "Access list name\n")
12180{
d62a17ae 12181 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
12182 return CMD_SUCCESS;
734b349e
MZ
12183}
12184
718e3744 12185DEFUN (bgp_damp_set,
12186 bgp_damp_set_cmd,
31500417 12187 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 12188 "BGP Specific commands\n"
12189 "Enable route-flap dampening\n"
12190 "Half-life time for the penalty\n"
12191 "Value to start reusing a route\n"
12192 "Value to start suppressing a route\n"
12193 "Maximum duration to suppress a stable route\n")
12194{
d62a17ae 12195 VTY_DECLVAR_CONTEXT(bgp, bgp);
12196 int idx_half_life = 2;
12197 int idx_reuse = 3;
12198 int idx_suppress = 4;
12199 int idx_max_suppress = 5;
12200 int half = DEFAULT_HALF_LIFE * 60;
12201 int reuse = DEFAULT_REUSE;
12202 int suppress = DEFAULT_SUPPRESS;
12203 int max = 4 * half;
12204
12205 if (argc == 6) {
12206 half = atoi(argv[idx_half_life]->arg) * 60;
12207 reuse = atoi(argv[idx_reuse]->arg);
12208 suppress = atoi(argv[idx_suppress]->arg);
12209 max = atoi(argv[idx_max_suppress]->arg) * 60;
12210 } else if (argc == 3) {
12211 half = atoi(argv[idx_half_life]->arg) * 60;
12212 max = 4 * half;
12213 }
718e3744 12214
d62a17ae 12215 if (suppress < reuse) {
12216 vty_out(vty,
12217 "Suppress value cannot be less than reuse value \n");
12218 return 0;
12219 }
7ebe9748 12220
d62a17ae 12221 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
12222 reuse, suppress, max);
718e3744 12223}
12224
718e3744 12225DEFUN (bgp_damp_unset,
12226 bgp_damp_unset_cmd,
d04c479d 12227 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 12228 NO_STR
12229 "BGP Specific commands\n"
16cedbb0
QY
12230 "Enable route-flap dampening\n"
12231 "Half-life time for the penalty\n"
12232 "Value to start reusing a route\n"
12233 "Value to start suppressing a route\n"
12234 "Maximum duration to suppress a stable route\n")
718e3744 12235{
d62a17ae 12236 VTY_DECLVAR_CONTEXT(bgp, bgp);
12237 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 12238}
12239
718e3744 12240/* Display specified route of BGP table. */
d62a17ae 12241static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
12242 const char *ip_str, afi_t afi, safi_t safi,
12243 struct prefix_rd *prd, int prefix_check)
12244{
12245 int ret;
12246 struct prefix match;
12247 struct bgp_node *rn;
12248 struct bgp_node *rm;
40381db7
DS
12249 struct bgp_path_info *pi;
12250 struct bgp_path_info *pi_temp;
d62a17ae 12251 struct bgp *bgp;
12252 struct bgp_table *table;
12253
12254 /* BGP structure lookup. */
12255 if (view_name) {
12256 bgp = bgp_lookup_by_name(view_name);
12257 if (bgp == NULL) {
12258 vty_out(vty, "%% Can't find BGP instance %s\n",
12259 view_name);
12260 return CMD_WARNING;
12261 }
12262 } else {
12263 bgp = bgp_get_default();
12264 if (bgp == NULL) {
12265 vty_out(vty, "%% No BGP process is configured\n");
12266 return CMD_WARNING;
12267 }
718e3744 12268 }
718e3744 12269
d62a17ae 12270 /* Check IP address argument. */
12271 ret = str2prefix(ip_str, &match);
12272 if (!ret) {
12273 vty_out(vty, "%% address is malformed\n");
12274 return CMD_WARNING;
12275 }
718e3744 12276
d62a17ae 12277 match.family = afi2family(afi);
12278
12279 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
12280 || (safi == SAFI_EVPN)) {
12281 for (rn = bgp_table_top(bgp->rib[AFI_IP][safi]); rn;
12282 rn = bgp_route_next(rn)) {
12283 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
12284 continue;
67009e22
DS
12285 table = bgp_node_get_bgp_table_info(rn);
12286 if (!table)
ea47320b
DL
12287 continue;
12288 if ((rm = bgp_node_match(table, &match)) == NULL)
12289 continue;
d62a17ae 12290
ea47320b
DL
12291 if (!prefix_check
12292 || rm->p.prefixlen == match.prefixlen) {
6f94b685 12293 pi = bgp_node_get_bgp_path_info(rm);
40381db7
DS
12294 while (pi) {
12295 if (pi->extra && pi->extra->damp_info) {
12296 pi_temp = pi->next;
ea47320b 12297 bgp_damp_info_free(
40381db7 12298 pi->extra->damp_info,
60466a63 12299 1);
40381db7 12300 pi = pi_temp;
ea47320b 12301 } else
40381db7 12302 pi = pi->next;
d62a17ae 12303 }
ea47320b
DL
12304 }
12305
12306 bgp_unlock_node(rm);
d62a17ae 12307 }
12308 } else {
12309 if ((rn = bgp_node_match(bgp->rib[afi][safi], &match))
12310 != NULL) {
12311 if (!prefix_check
12312 || rn->p.prefixlen == match.prefixlen) {
6f94b685 12313 pi = bgp_node_get_bgp_path_info(rn);
40381db7
DS
12314 while (pi) {
12315 if (pi->extra && pi->extra->damp_info) {
12316 pi_temp = pi->next;
d62a17ae 12317 bgp_damp_info_free(
40381db7 12318 pi->extra->damp_info,
d62a17ae 12319 1);
40381db7 12320 pi = pi_temp;
d62a17ae 12321 } else
40381db7 12322 pi = pi->next;
d62a17ae 12323 }
12324 }
12325
12326 bgp_unlock_node(rn);
12327 }
12328 }
718e3744 12329
d62a17ae 12330 return CMD_SUCCESS;
718e3744 12331}
12332
12333DEFUN (clear_ip_bgp_dampening,
12334 clear_ip_bgp_dampening_cmd,
12335 "clear ip bgp dampening",
12336 CLEAR_STR
12337 IP_STR
12338 BGP_STR
12339 "Clear route flap dampening information\n")
12340{
d62a17ae 12341 bgp_damp_info_clean();
12342 return CMD_SUCCESS;
718e3744 12343}
12344
12345DEFUN (clear_ip_bgp_dampening_prefix,
12346 clear_ip_bgp_dampening_prefix_cmd,
12347 "clear ip bgp dampening A.B.C.D/M",
12348 CLEAR_STR
12349 IP_STR
12350 BGP_STR
12351 "Clear route flap dampening information\n"
0c7b1b01 12352 "IPv4 prefix\n")
718e3744 12353{
d62a17ae 12354 int idx_ipv4_prefixlen = 4;
12355 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
12356 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 12357}
12358
12359DEFUN (clear_ip_bgp_dampening_address,
12360 clear_ip_bgp_dampening_address_cmd,
12361 "clear ip bgp dampening A.B.C.D",
12362 CLEAR_STR
12363 IP_STR
12364 BGP_STR
12365 "Clear route flap dampening information\n"
12366 "Network to clear damping information\n")
12367{
d62a17ae 12368 int idx_ipv4 = 4;
12369 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
12370 SAFI_UNICAST, NULL, 0);
718e3744 12371}
12372
12373DEFUN (clear_ip_bgp_dampening_address_mask,
12374 clear_ip_bgp_dampening_address_mask_cmd,
12375 "clear ip bgp dampening A.B.C.D A.B.C.D",
12376 CLEAR_STR
12377 IP_STR
12378 BGP_STR
12379 "Clear route flap dampening information\n"
12380 "Network to clear damping information\n"
12381 "Network mask\n")
12382{
d62a17ae 12383 int idx_ipv4 = 4;
12384 int idx_ipv4_2 = 5;
12385 int ret;
12386 char prefix_str[BUFSIZ];
718e3744 12387
d62a17ae 12388 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
12389 prefix_str);
12390 if (!ret) {
12391 vty_out(vty, "%% Inconsistent address and mask\n");
12392 return CMD_WARNING;
12393 }
718e3744 12394
d62a17ae 12395 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
12396 NULL, 0);
718e3744 12397}
6b0655a2 12398
e3b78da8 12399static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
12400{
12401 struct vty *vty = arg;
e3b78da8 12402 struct peer *peer = bucket->data;
825d9834
DS
12403 char buf[SU_ADDRSTRLEN];
12404
12405 vty_out(vty, "\tPeer: %s %s\n", peer->host,
12406 sockunion2str(&peer->su, buf, sizeof(buf)));
12407}
12408
12409DEFUN (show_bgp_peerhash,
12410 show_bgp_peerhash_cmd,
12411 "show bgp peerhash",
12412 SHOW_STR
12413 BGP_STR
12414 "Display information about the BGP peerhash\n")
12415{
12416 struct list *instances = bm->bgp;
12417 struct listnode *node;
12418 struct bgp *bgp;
12419
12420 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
12421 vty_out(vty, "BGP: %s\n", bgp->name);
12422 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
12423 vty);
12424 }
12425
12426 return CMD_SUCCESS;
12427}
12428
587ff0fd 12429/* also used for encap safi */
2b791107
DL
12430static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
12431 afi_t afi, safi_t safi)
d62a17ae 12432{
12433 struct bgp_node *prn;
12434 struct bgp_node *rn;
12435 struct bgp_table *table;
12436 struct prefix *p;
12437 struct prefix_rd *prd;
12438 struct bgp_static *bgp_static;
12439 mpls_label_t label;
12440 char buf[SU_ADDRSTRLEN];
12441 char rdbuf[RD_ADDRSTRLEN];
12442
12443 /* Network configuration. */
12444 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b 12445 prn = bgp_route_next(prn)) {
67009e22
DS
12446 table = bgp_node_get_bgp_table_info(prn);
12447 if (!table)
ea47320b 12448 continue;
d62a17ae 12449
60466a63 12450 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5a8ba9fc 12451 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12452 if (bgp_static == NULL)
ea47320b 12453 continue;
d62a17ae 12454
ea47320b
DL
12455 p = &rn->p;
12456 prd = (struct prefix_rd *)&prn->p;
d62a17ae 12457
ea47320b 12458 /* "network" configuration display. */
06b9f471 12459 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
12460 label = decode_label(&bgp_static->label);
12461
12462 vty_out(vty, " network %s/%d rd %s",
12463 inet_ntop(p->family, &p->u.prefix, buf,
12464 SU_ADDRSTRLEN),
12465 p->prefixlen, rdbuf);
12466 if (safi == SAFI_MPLS_VPN)
12467 vty_out(vty, " label %u", label);
12468
12469 if (bgp_static->rmap.name)
12470 vty_out(vty, " route-map %s",
12471 bgp_static->rmap.name);
e2a86ad9
DS
12472
12473 if (bgp_static->backdoor)
12474 vty_out(vty, " backdoor");
12475
ea47320b
DL
12476 vty_out(vty, "\n");
12477 }
12478 }
d62a17ae 12479}
12480
2b791107
DL
12481static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
12482 afi_t afi, safi_t safi)
d62a17ae 12483{
12484 struct bgp_node *prn;
12485 struct bgp_node *rn;
12486 struct bgp_table *table;
12487 struct prefix *p;
12488 struct prefix_rd *prd;
12489 struct bgp_static *bgp_static;
ff44f570 12490 char buf[PREFIX_STRLEN * 2];
d62a17ae 12491 char buf2[SU_ADDRSTRLEN];
12492 char rdbuf[RD_ADDRSTRLEN];
12493
12494 /* Network configuration. */
12495 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b 12496 prn = bgp_route_next(prn)) {
67009e22
DS
12497 table = bgp_node_get_bgp_table_info(prn);
12498 if (!table)
ea47320b 12499 continue;
d62a17ae 12500
60466a63 12501 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5a8ba9fc 12502 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12503 if (bgp_static == NULL)
ea47320b 12504 continue;
d62a17ae 12505
ea47320b
DL
12506 char *macrouter = NULL;
12507 char *esi = NULL;
d62a17ae 12508
ea47320b
DL
12509 if (bgp_static->router_mac)
12510 macrouter = prefix_mac2str(
12511 bgp_static->router_mac, NULL, 0);
12512 if (bgp_static->eth_s_id)
12513 esi = esi2str(bgp_static->eth_s_id);
12514 p = &rn->p;
12515 prd = (struct prefix_rd *)&prn->p;
d62a17ae 12516
ea47320b 12517 /* "network" configuration display. */
06b9f471 12518 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
12519 if (p->u.prefix_evpn.route_type == 5) {
12520 char local_buf[PREFIX_STRLEN];
3714a385 12521 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
12522 struct prefix_evpn *)p)
12523 ? AF_INET
12524 : AF_INET6;
3714a385 12525 inet_ntop(family,
12526 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a
PZ
12527 local_buf, PREFIX_STRLEN);
12528 sprintf(buf, "%s/%u", local_buf,
3714a385 12529 p->u.prefix_evpn.prefix_addr.ip_prefix_length);
197cb530
PG
12530 } else {
12531 prefix2str(p, buf, sizeof(buf));
12532 }
ea47320b 12533
a4d82a8a
PZ
12534 if (bgp_static->gatewayIp.family == AF_INET
12535 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
12536 inet_ntop(bgp_static->gatewayIp.family,
12537 &bgp_static->gatewayIp.u.prefix, buf2,
12538 sizeof(buf2));
ea47320b 12539 vty_out(vty,
7bcc8dac 12540 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 12541 buf, rdbuf,
12542 p->u.prefix_evpn.prefix_addr.eth_tag,
60466a63 12543 decode_label(&bgp_static->label), esi, buf2,
ea47320b
DL
12544 macrouter);
12545
0a22ddfb
QY
12546 XFREE(MTYPE_TMP, macrouter);
12547 XFREE(MTYPE_TMP, esi);
ea47320b
DL
12548 }
12549 }
3da6fcd5
PG
12550}
12551
718e3744 12552/* Configuration of static route announcement and aggregate
12553 information. */
2b791107
DL
12554void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
12555 safi_t safi)
d62a17ae 12556{
12557 struct bgp_node *rn;
12558 struct prefix *p;
12559 struct bgp_static *bgp_static;
12560 struct bgp_aggregate *bgp_aggregate;
12561 char buf[SU_ADDRSTRLEN];
12562
2b791107
DL
12563 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
12564 bgp_config_write_network_vpn(vty, bgp, afi, safi);
12565 return;
12566 }
d62a17ae 12567
2b791107
DL
12568 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
12569 bgp_config_write_network_evpn(vty, bgp, afi, safi);
12570 return;
12571 }
d62a17ae 12572
12573 /* Network configuration. */
12574 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
ea47320b 12575 rn = bgp_route_next(rn)) {
5a8ba9fc 12576 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12577 if (bgp_static == NULL)
ea47320b 12578 continue;
d62a17ae 12579
ea47320b 12580 p = &rn->p;
d62a17ae 12581
d8a9922d
DS
12582 vty_out(vty, " network %s/%d",
12583 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
12584 p->prefixlen);
d62a17ae 12585
ea47320b
DL
12586 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
12587 vty_out(vty, " label-index %u",
12588 bgp_static->label_index);
d62a17ae 12589
ea47320b
DL
12590 if (bgp_static->rmap.name)
12591 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
12592
12593 if (bgp_static->backdoor)
12594 vty_out(vty, " backdoor");
718e3744 12595
ea47320b
DL
12596 vty_out(vty, "\n");
12597 }
12598
d62a17ae 12599 /* Aggregate-address configuration. */
12600 for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn;
ea47320b 12601 rn = bgp_route_next(rn)) {
b613a918 12602 bgp_aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 12603 if (bgp_aggregate == NULL)
ea47320b 12604 continue;
d62a17ae 12605
ea47320b 12606 p = &rn->p;
d62a17ae 12607
d8a9922d
DS
12608 vty_out(vty, " aggregate-address %s/%d",
12609 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
12610 p->prefixlen);
d62a17ae 12611
ea47320b
DL
12612 if (bgp_aggregate->as_set)
12613 vty_out(vty, " as-set");
d62a17ae 12614
ea47320b
DL
12615 if (bgp_aggregate->summary_only)
12616 vty_out(vty, " summary-only");
718e3744 12617
20894f50
DA
12618 if (bgp_aggregate->rmap.name)
12619 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
12620
ea47320b
DL
12621 vty_out(vty, "\n");
12622 }
d62a17ae 12623}
734b349e 12624
2b791107 12625void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 12626 safi_t safi)
d62a17ae 12627{
12628 struct bgp_node *rn;
12629 struct bgp_distance *bdistance;
12630
12631 /* Distance configuration. */
12632 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
12633 && bgp->distance_local[afi][safi]
12634 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
12635 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
12636 || bgp->distance_local[afi][safi]
12637 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 12638 vty_out(vty, " distance bgp %d %d %d\n",
12639 bgp->distance_ebgp[afi][safi],
12640 bgp->distance_ibgp[afi][safi],
12641 bgp->distance_local[afi][safi]);
12642 }
734b349e 12643
d62a17ae 12644 for (rn = bgp_table_top(bgp_distance_table[afi][safi]); rn;
ca2e160d 12645 rn = bgp_route_next(rn)) {
5b00b40e 12646 bdistance = bgp_node_get_bgp_distance_info(rn);
ca2e160d 12647 if (bdistance != NULL) {
d62a17ae 12648 char buf[PREFIX_STRLEN];
12649
d62a17ae 12650 vty_out(vty, " distance %d %s %s\n",
12651 bdistance->distance,
12652 prefix2str(&rn->p, buf, sizeof(buf)),
12653 bdistance->access_list ? bdistance->access_list
12654 : "");
12655 }
ca2e160d 12656 }
718e3744 12657}
12658
12659/* Allocate routing table structure and install commands. */
d62a17ae 12660void bgp_route_init(void)
12661{
12662 afi_t afi;
12663 safi_t safi;
12664
12665 /* Init BGP distance table. */
05c7a1cc 12666 FOREACH_AFI_SAFI (afi, safi)
960035b2 12667 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 12668
12669 /* IPv4 BGP commands. */
12670 install_element(BGP_NODE, &bgp_table_map_cmd);
12671 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 12672 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 12673
12674 install_element(BGP_NODE, &aggregate_address_cmd);
12675 install_element(BGP_NODE, &aggregate_address_mask_cmd);
12676 install_element(BGP_NODE, &no_aggregate_address_cmd);
12677 install_element(BGP_NODE, &no_aggregate_address_mask_cmd);
12678
12679 /* IPv4 unicast configuration. */
12680 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
12681 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 12682 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 12683
12684 install_element(BGP_IPV4_NODE, &aggregate_address_cmd);
12685 install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd);
12686 install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd);
12687 install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
12688
12689 /* IPv4 multicast configuration. */
12690 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
12691 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 12692 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
d62a17ae 12693 install_element(BGP_IPV4M_NODE, &aggregate_address_cmd);
12694 install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
12695 install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd);
12696 install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
12697
12698 /* IPv4 labeled-unicast configuration. */
12699 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
12700 install_element(VIEW_NODE, &show_ip_bgp_cmd);
7b2ff250 12701 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 12702 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
12703 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
12704
12705 install_element(VIEW_NODE,
12706 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
12707 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
12708 install_element(VIEW_NODE,
12709 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 12710#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 12711 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 12712#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 12713 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
12714 install_element(VIEW_NODE,
44c69747 12715 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 12716
d62a17ae 12717 /* BGP dampening clear commands */
12718 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
12719 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 12720
d62a17ae 12721 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
12722 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
12723
12724 /* prefix count */
12725 install_element(ENABLE_NODE,
12726 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 12727#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 12728 install_element(ENABLE_NODE,
12729 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 12730#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 12731
d62a17ae 12732 /* New config IPv6 BGP commands. */
12733 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
12734 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 12735 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 12736
12737 install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
12738 install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
12739
12740 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 12741
d62a17ae 12742 install_element(BGP_NODE, &bgp_distance_cmd);
12743 install_element(BGP_NODE, &no_bgp_distance_cmd);
12744 install_element(BGP_NODE, &bgp_distance_source_cmd);
12745 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
12746 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
12747 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
12748 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
12749 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
12750 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
12751 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
12752 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
12753 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
12754 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
12755 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
12756 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
12757 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
12758 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
12759 install_element(BGP_IPV4M_NODE,
12760 &no_bgp_distance_source_access_list_cmd);
12761 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
12762 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
12763 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
12764 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
12765 install_element(BGP_IPV6_NODE,
12766 &ipv6_bgp_distance_source_access_list_cmd);
12767 install_element(BGP_IPV6_NODE,
12768 &no_ipv6_bgp_distance_source_access_list_cmd);
12769 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
12770 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
12771 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
12772 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
12773 install_element(BGP_IPV6M_NODE,
12774 &ipv6_bgp_distance_source_access_list_cmd);
12775 install_element(BGP_IPV6M_NODE,
12776 &no_ipv6_bgp_distance_source_access_list_cmd);
12777
12778 install_element(BGP_NODE, &bgp_damp_set_cmd);
12779 install_element(BGP_NODE, &bgp_damp_unset_cmd);
12780 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
12781 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
12782
12783 /* IPv4 Multicast Mode */
12784 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
12785 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
12786
12787 /* Large Communities */
12788 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
12789 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
12790
12791 /* show bgp ipv4 flowspec detailed */
12792 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
12793
825d9834 12794 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 12795}
12796
12797void bgp_route_finish(void)
12798{
12799 afi_t afi;
12800 safi_t safi;
12801
05c7a1cc
QY
12802 FOREACH_AFI_SAFI (afi, safi) {
12803 bgp_table_unlock(bgp_distance_table[afi][safi]);
12804 bgp_distance_table[afi][safi] = NULL;
12805 }
228da428 12806}