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