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