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