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