]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
lib: Implement an allocator for 32 bit ID numbers
[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;
d62a17ae 1931
121e245d
DS
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)
eaaf8adb
DS
5521 return 0;
5522
40381db7 5523 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
29f7d023
DS
5524 return 0;
5525
40381db7 5526 if (!community_cmp(pi->attr->community, comm))
eaaf8adb
DS
5527 return 0;
5528
3da2cc32 5529 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
eaaf8adb
DS
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);
d62a17ae 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];
50e05855 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 6420 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 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);
50e05855
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);
37d4e0df
AD
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");
50e05855
AD
6690 json_object_boolean_true_add(
6691 json_nexthop_global,
026b914a
PG
6692 "used");
6693 } else {
6694 vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
6695 }
6696 }
d33fc23b 6697 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
6698 if (json_paths) {
6699 json_nexthop_global = json_object_new_object();
d62a17ae 6700
a4d82a8a
PZ
6701 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN))
6702 json_object_string_add(
6703 json_nexthop_global, "ip",
6704 inet_ntoa(attr->mp_nexthop_global_in));
445c2480 6705 else
a4d82a8a
PZ
6706 json_object_string_add(
6707 json_nexthop_global, "ip",
6708 inet_ntoa(attr->nexthop));
445c2480 6709
a4d82a8a
PZ
6710 json_object_string_add(json_nexthop_global, "afi",
6711 "ipv4");
445c2480
DS
6712 json_object_boolean_true_add(json_nexthop_global,
6713 "used");
6714 } else {
9df8b37c
PZ
6715 char buf[BUFSIZ];
6716
d87ff2dd 6717 snprintf(buf, sizeof(buf), "%s%s",
6718 inet_ntoa(attr->nexthop), vrf_id_str);
9df8b37c 6719 vty_out(vty, "%-16s", buf);
d62a17ae 6720 }
445c2480 6721 }
b05a1c8b 6722
445c2480 6723 /* IPv6 Next Hop */
a4d82a8a 6724 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
6725 int len;
6726 char buf[BUFSIZ];
d62a17ae 6727
445c2480
DS
6728 if (json_paths) {
6729 json_nexthop_global = json_object_new_object();
a4d82a8a
PZ
6730 json_object_string_add(
6731 json_nexthop_global, "ip",
6732 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
6733 buf, BUFSIZ));
6734 json_object_string_add(json_nexthop_global, "afi",
6735 "ipv6");
6736 json_object_string_add(json_nexthop_global, "scope",
6737 "global");
445c2480
DS
6738
6739 /* We display both LL & GL if both have been
6740 * received */
6741 if ((attr->mp_nexthop_len == 32)
9b6d8fcf 6742 || (path->peer->conf_if)) {
a4d82a8a 6743 json_nexthop_ll = json_object_new_object();
d62a17ae 6744 json_object_string_add(
445c2480 6745 json_nexthop_ll, "ip",
a4d82a8a
PZ
6746 inet_ntop(AF_INET6,
6747 &attr->mp_nexthop_local, buf,
6748 BUFSIZ));
6749 json_object_string_add(json_nexthop_ll, "afi",
6750 "ipv6");
6751 json_object_string_add(json_nexthop_ll, "scope",
445c2480 6752 "link-local");
d62a17ae 6753
a4d82a8a
PZ
6754 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
6755 &attr->mp_nexthop_local)
445c2480
DS
6756 != 0)
6757 && !attr->mp_nexthop_prefer_global)
d62a17ae 6758 json_object_boolean_true_add(
a4d82a8a 6759 json_nexthop_ll, "used");
445c2480
DS
6760 else
6761 json_object_boolean_true_add(
a4d82a8a 6762 json_nexthop_global, "used");
445c2480
DS
6763 } else
6764 json_object_boolean_true_add(
6765 json_nexthop_global, "used");
6766 } else {
6767 /* Display LL if LL/Global both in table unless
6768 * prefer-global is set */
6769 if (((attr->mp_nexthop_len == 32)
6770 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
6771 || (path->peer->conf_if)) {
6772 if (path->peer->conf_if) {
a4d82a8a 6773 len = vty_out(vty, "%s",
9b6d8fcf 6774 path->peer->conf_if);
445c2480
DS
6775 len = 16 - len; /* len of IPv6
6776 addr + max
6777 len of def
6778 ifname */
6779
6780 if (len < 1)
a4d82a8a 6781 vty_out(vty, "\n%*s", 36, " ");
445c2480 6782 else
a4d82a8a 6783 vty_out(vty, "%*s", len, " ");
d62a17ae 6784 } else {
6785 len = vty_out(
9df8b37c 6786 vty, "%s%s",
d62a17ae 6787 inet_ntop(
6788 AF_INET6,
445c2480 6789 &attr->mp_nexthop_local,
9df8b37c
PZ
6790 buf, BUFSIZ),
6791 vrf_id_str);
d62a17ae 6792 len = 16 - len;
6793
6794 if (len < 1)
a4d82a8a 6795 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 6796 else
a4d82a8a 6797 vty_out(vty, "%*s", len, " ");
d62a17ae 6798 }
445c2480 6799 } else {
a4d82a8a 6800 len = vty_out(
9df8b37c 6801 vty, "%s%s",
a4d82a8a
PZ
6802 inet_ntop(AF_INET6,
6803 &attr->mp_nexthop_global, buf,
9df8b37c
PZ
6804 BUFSIZ),
6805 vrf_id_str);
445c2480
DS
6806 len = 16 - len;
6807
6808 if (len < 1)
6809 vty_out(vty, "\n%*s", 36, " ");
6810 else
6811 vty_out(vty, "%*s", len, " ");
d62a17ae 6812 }
6813 }
445c2480 6814 }
718e3744 6815
445c2480
DS
6816 /* MED/Metric */
6817 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
50e05855
AD
6818 if (json_paths) {
6819
6820 /*
6821 * Adding "metric" field to match with corresponding
6822 * CLI. "med" will be deprecated in future.
6823 */
a4d82a8a 6824 json_object_int_add(json_path, "med", attr->med);
50e05855
AD
6825 json_object_int_add(json_path, "metric", attr->med);
6826 } else
445c2480
DS
6827 vty_out(vty, "%10u", attr->med);
6828 else if (!json_paths)
6829 vty_out(vty, " ");
d62a17ae 6830
445c2480
DS
6831 /* Local Pref */
6832 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855
AD
6833 if (json_paths) {
6834
6835 /*
6836 * Adding "locPrf" field to match with corresponding
6837 * CLI. "localPref" will be deprecated in future.
6838 */
445c2480
DS
6839 json_object_int_add(json_path, "localpref",
6840 attr->local_pref);
50e05855
AD
6841 json_object_int_add(json_path, "locPrf",
6842 attr->local_pref);
6843 } else
445c2480
DS
6844 vty_out(vty, "%7u", attr->local_pref);
6845 else if (!json_paths)
6846 vty_out(vty, " ");
d62a17ae 6847
445c2480
DS
6848 if (json_paths)
6849 json_object_int_add(json_path, "weight", attr->weight);
6850 else
6851 vty_out(vty, "%7u ", attr->weight);
47fc97cc 6852
445c2480
DS
6853 if (json_paths) {
6854 char buf[BUFSIZ];
a4d82a8a
PZ
6855 json_object_string_add(
6856 json_path, "peerId",
9b6d8fcf 6857 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 6858 }
b05a1c8b 6859
445c2480
DS
6860 /* Print aspath */
6861 if (attr->aspath) {
50e05855
AD
6862 if (json_paths) {
6863
6864 /*
6865 * Adding "path" field to match with corresponding
6866 * CLI. "aspath" will be deprecated in future.
6867 */
445c2480
DS
6868 json_object_string_add(json_path, "aspath",
6869 attr->aspath->str);
50e05855
AD
6870 json_object_string_add(json_path, "path",
6871 attr->aspath->str);
6872 } else
445c2480 6873 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 6874 }
f1aa5d8a 6875
445c2480
DS
6876 /* Print origin */
6877 if (json_paths)
a4d82a8a
PZ
6878 json_object_string_add(json_path, "origin",
6879 bgp_origin_long_str[attr->origin]);
445c2480
DS
6880 else
6881 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
6882
9df8b37c
PZ
6883 if (json_paths) {
6884 if (nexthop_self)
6885 json_object_boolean_true_add(json_path,
6886 "announceNexthopSelf");
6887 if (nexthop_othervrf) {
6888 json_object_string_add(json_path, "nhVrfName",
6889 nexthop_vrfname);
6890
6891 json_object_int_add(json_path, "nhVrfId",
6892 ((nexthop_vrfid == VRF_UNKNOWN)
6893 ? -1
6894 : (int)nexthop_vrfid));
6895 }
6896 }
6897
d62a17ae 6898 if (json_paths) {
6899 if (json_nexthop_global || json_nexthop_ll) {
6900 json_nexthops = json_object_new_array();
f1aa5d8a 6901
d62a17ae 6902 if (json_nexthop_global)
6903 json_object_array_add(json_nexthops,
6904 json_nexthop_global);
f1aa5d8a 6905
d62a17ae 6906 if (json_nexthop_ll)
6907 json_object_array_add(json_nexthops,
6908 json_nexthop_ll);
f1aa5d8a 6909
d62a17ae 6910 json_object_object_add(json_path, "nexthops",
6911 json_nexthops);
6912 }
6913
6914 json_object_array_add(json_paths, json_path);
6915 } else {
6916 vty_out(vty, "\n");
65efcfce 6917#if ENABLE_BGP_VNC
d62a17ae 6918 /* prints an additional line, indented, with VNC info, if
6919 * present */
6920 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 6921 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 6922#endif
d62a17ae 6923 }
6924}
718e3744 6925
6926/* called from terminal list command */
d62a17ae 6927void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr,
9f049418 6928 safi_t safi, bool use_json, json_object *json_ar)
d62a17ae 6929{
6930 json_object *json_status = NULL;
6931 json_object *json_net = NULL;
6932 char buff[BUFSIZ];
50e05855 6933 char buf2[BUFSIZ];
d62a17ae 6934 /* Route status display. */
6935 if (use_json) {
6936 json_status = json_object_new_object();
6937 json_net = json_object_new_object();
6938 } else {
6939 vty_out(vty, "*");
6940 vty_out(vty, ">");
6941 vty_out(vty, " ");
6942 }
718e3744 6943
d62a17ae 6944 /* print prefix and mask */
50e05855 6945 if (use_json) {
d62a17ae 6946 json_object_string_add(
6947 json_net, "addrPrefix",
6948 inet_ntop(p->family, &p->u.prefix, buff, BUFSIZ));
50e05855 6949 json_object_int_add(json_net, "prefixLen", p->prefixlen);
37d4e0df 6950 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855
AD
6951 json_object_string_add(json_net, "network", buf2);
6952 } else
9c92b5f7 6953 route_vty_out_route(p, vty, NULL);
d62a17ae 6954
6955 /* Print attribute */
6956 if (attr) {
6957 if (use_json) {
6958 if (p->family == AF_INET
6959 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6960 || safi == SAFI_EVPN
6961 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
6962 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6963 || safi == SAFI_EVPN)
6964 json_object_string_add(
6965 json_net, "nextHop",
6966 inet_ntoa(
6967 attr->mp_nexthop_global_in));
6968 else
6969 json_object_string_add(
6970 json_net, "nextHop",
6971 inet_ntoa(attr->nexthop));
6972 } else if (p->family == AF_INET6
6973 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
6974 char buf[BUFSIZ];
6975
6976 json_object_string_add(
aa0a10fc 6977 json_net, "nextHopGlobal",
d62a17ae 6978 inet_ntop(AF_INET6,
6979 &attr->mp_nexthop_global, buf,
6980 BUFSIZ));
6981 }
6982
6983 if (attr->flag
6984 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
6985 json_object_int_add(json_net, "metric",
6986 attr->med);
6987
50e05855
AD
6988 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
6989
6990 /*
6991 * Adding "locPrf" field to match with
6992 * corresponding CLI. "localPref" will be
6993 * deprecated in future.
6994 */
d62a17ae 6995 json_object_int_add(json_net, "localPref",
6996 attr->local_pref);
50e05855
AD
6997 json_object_int_add(json_net, "locPrf",
6998 attr->local_pref);
6999 }
d62a17ae 7000
7001 json_object_int_add(json_net, "weight", attr->weight);
7002
7003 /* Print aspath */
50e05855
AD
7004 if (attr->aspath) {
7005
7006 /*
7007 * Adding "path" field to match with
7008 * corresponding CLI. "localPref" will be
7009 * deprecated in future.
7010 */
d62a17ae 7011 json_object_string_add(json_net, "asPath",
7012 attr->aspath->str);
50e05855
AD
7013 json_object_string_add(json_net, "path",
7014 attr->aspath->str);
7015 }
d62a17ae 7016
7017 /* Print origin */
7018 json_object_string_add(json_net, "bgpOriginCode",
7019 bgp_origin_str[attr->origin]);
7020 } else {
7021 if (p->family == AF_INET
7022 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7023 || safi == SAFI_EVPN
7024 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7025 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7026 || safi == SAFI_EVPN)
7027 vty_out(vty, "%-16s",
7028 inet_ntoa(
7029 attr->mp_nexthop_global_in));
7030 else
7031 vty_out(vty, "%-16s",
7032 inet_ntoa(attr->nexthop));
7033 } else if (p->family == AF_INET6
7034 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
7035 int len;
7036 char buf[BUFSIZ];
7037
7038 len = vty_out(
7039 vty, "%s",
7040 inet_ntop(AF_INET6,
7041 &attr->mp_nexthop_global, buf,
7042 BUFSIZ));
7043 len = 16 - len;
7044 if (len < 1)
7045 vty_out(vty, "\n%*s", 36, " ");
7046 else
7047 vty_out(vty, "%*s", len, " ");
7048 }
7049 if (attr->flag
7050 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
7051 vty_out(vty, "%10u", attr->med);
7052 else
7053 vty_out(vty, " ");
718e3744 7054
d62a17ae 7055 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
7056 vty_out(vty, "%7u", attr->local_pref);
7057 else
7058 vty_out(vty, " ");
7059
7060 vty_out(vty, "%7u ", attr->weight);
7061
7062 /* Print aspath */
7063 if (attr->aspath)
7064 aspath_print_vty(vty, "%s", attr->aspath, " ");
7065
7066 /* Print origin */
7067 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7068 }
7069 }
7070 if (use_json) {
7071 json_object_boolean_true_add(json_status, "*");
7072 json_object_boolean_true_add(json_status, ">");
7073 json_object_object_add(json_net, "appliedStatusSymbols",
7074 json_status);
7075 char buf_cut[BUFSIZ];
7076 json_object_object_add(
7077 json_ar,
7078 inet_ntop(p->family, &p->u.prefix, buf_cut, BUFSIZ),
7079 json_net);
7080 } else
7081 vty_out(vty, "\n");
7082}
7083
7084void route_vty_out_tag(struct vty *vty, struct prefix *p,
9b6d8fcf 7085 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 7086 json_object *json)
7087{
7088 json_object *json_out = NULL;
7089 struct attr *attr;
7090 mpls_label_t label = MPLS_INVALID_LABEL;
7091
9b6d8fcf 7092 if (!path->extra)
d62a17ae 7093 return;
7094
7095 if (json)
7096 json_out = json_object_new_object();
7097
7098 /* short status lead text */
9b6d8fcf 7099 route_vty_short_status_out(vty, path, json_out);
d62a17ae 7100
7101 /* print prefix and mask */
7102 if (json == NULL) {
7103 if (!display)
9c92b5f7 7104 route_vty_out_route(p, vty, NULL);
d62a17ae 7105 else
7106 vty_out(vty, "%*s", 17, " ");
7107 }
7108
7109 /* Print attribute */
9b6d8fcf 7110 attr = path->attr;
d62a17ae 7111 if (attr) {
7112 if (((p->family == AF_INET)
7113 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
a4d82a8a 7114 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
d62a17ae 7115 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7116 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7117 || safi == SAFI_EVPN) {
7118 if (json)
7119 json_object_string_add(
7120 json_out, "mpNexthopGlobalIn",
7121 inet_ntoa(
7122 attr->mp_nexthop_global_in));
7123 else
7124 vty_out(vty, "%-16s",
7125 inet_ntoa(
7126 attr->mp_nexthop_global_in));
7127 } else {
7128 if (json)
7129 json_object_string_add(
7130 json_out, "nexthop",
7131 inet_ntoa(attr->nexthop));
7132 else
7133 vty_out(vty, "%-16s",
7134 inet_ntoa(attr->nexthop));
7135 }
7136 } else if (((p->family == AF_INET6)
7137 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
b03b8898 7138 || (safi == SAFI_EVPN
d62a17ae 7139 && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
7140 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
ff44f570
DS
7141 char buf_a[512];
7142 char buf_b[512];
d62a17ae 7143 char buf_c[BUFSIZ];
7144 if (attr->mp_nexthop_len
7145 == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
7146 if (json)
7147 json_object_string_add(
7148 json_out, "mpNexthopGlobalIn",
7149 inet_ntop(
7150 AF_INET6,
7151 &attr->mp_nexthop_global,
11f9b450 7152 buf_a, sizeof(buf_a)));
d62a17ae 7153 else
7154 vty_out(vty, "%s",
7155 inet_ntop(
7156 AF_INET6,
7157 &attr->mp_nexthop_global,
11f9b450 7158 buf_a, sizeof(buf_a)));
d62a17ae 7159 } else if (attr->mp_nexthop_len
7160 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
7161 if (json) {
7162 inet_ntop(AF_INET6,
7163 &attr->mp_nexthop_global,
11f9b450 7164 buf_a, sizeof(buf_a));
d62a17ae 7165 inet_ntop(AF_INET6,
7166 &attr->mp_nexthop_local,
11f9b450 7167 buf_b, sizeof(buf_b));
d62a17ae 7168 sprintf(buf_c, "%s(%s)", buf_a, buf_b);
7169 json_object_string_add(
7170 json_out,
7171 "mpNexthopGlobalLocal", buf_c);
7172 } else
7173 vty_out(vty, "%s(%s)",
7174 inet_ntop(
7175 AF_INET6,
7176 &attr->mp_nexthop_global,
11f9b450 7177 buf_a, sizeof(buf_a)),
d62a17ae 7178 inet_ntop(
7179 AF_INET6,
7180 &attr->mp_nexthop_local,
11f9b450 7181 buf_b, sizeof(buf_b)));
d62a17ae 7182 }
7183 }
7184 }
7185
9b6d8fcf 7186 label = decode_label(&path->extra->label[0]);
d62a17ae 7187
7188 if (bgp_is_valid_label(&label)) {
7189 if (json) {
7190 json_object_int_add(json_out, "notag", label);
7191 json_object_array_add(json, json_out);
7192 } else {
7193 vty_out(vty, "notag/%d", label);
7194 vty_out(vty, "\n");
7195 }
7196 }
7197}
718e3744 7198
d62a17ae 7199void route_vty_out_overlay(struct vty *vty, struct prefix *p,
9b6d8fcf 7200 struct bgp_path_info *path, int display,
d62a17ae 7201 json_object *json_paths)
718e3744 7202{
d62a17ae 7203 struct attr *attr;
7204 char buf[BUFSIZ];
7205 json_object *json_path = NULL;
784d3a42 7206
d62a17ae 7207 if (json_paths)
7208 json_path = json_object_new_object();
856ca177 7209
9b6d8fcf 7210 if (!path->extra)
d62a17ae 7211 return;
718e3744 7212
d62a17ae 7213 /* short status lead text */
9b6d8fcf 7214 route_vty_short_status_out(vty, path, json_path);
856ca177 7215
d62a17ae 7216 /* print prefix and mask */
7217 if (!display)
9c92b5f7 7218 route_vty_out_route(p, vty, NULL);
d62a17ae 7219 else
7220 vty_out(vty, "%*s", 17, " ");
7221
7222 /* Print attribute */
9b6d8fcf 7223 attr = path->attr;
d62a17ae 7224 if (attr) {
7225 char buf1[BUFSIZ];
7226 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
7227
7228 switch (af) {
7229 case AF_INET:
7230 vty_out(vty, "%-16s",
7231 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
7232 BUFSIZ));
7233 break;
7234 case AF_INET6:
7235 vty_out(vty, "%s(%s)",
7236 inet_ntop(af, &attr->mp_nexthop_global, buf,
7237 BUFSIZ),
7238 inet_ntop(af, &attr->mp_nexthop_local, buf1,
7239 BUFSIZ));
7240 break;
7241 default:
7242 vty_out(vty, "?");
7243 }
988258b4
QY
7244
7245 char *str = esi2str(&(attr->evpn_overlay.eth_s_id));
7246
7247 vty_out(vty, "%s", str);
7248 XFREE(MTYPE_TMP, str);
7249
3714a385 7250 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
988258b4
QY
7251 vty_out(vty, "/%s",
7252 inet_ntoa(attr->evpn_overlay.gw_ip.ipv4));
3714a385 7253 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
988258b4
QY
7254 vty_out(vty, "/%s",
7255 inet_ntop(AF_INET6,
7256 &(attr->evpn_overlay.gw_ip.ipv6), buf,
7257 BUFSIZ));
7258 }
7259 if (attr->ecommunity) {
7260 char *mac = NULL;
7261 struct ecommunity_val *routermac = ecommunity_lookup(
7262 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
7263 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
7264 if (routermac)
7265 mac = ecom_mac2str((char *)routermac->val);
7266 if (mac) {
7267 vty_out(vty, "/%s", (char *)mac);
7268 XFREE(MTYPE_TMP, mac);
7269 }
7270 }
7271 vty_out(vty, "\n");
718e3744 7272 }
718e3744 7273
d62a17ae 7274}
718e3744 7275
d62a17ae 7276/* dampening route */
7277static void damp_route_vty_out(struct vty *vty, struct prefix *p,
9b6d8fcf 7278 struct bgp_path_info *path, int display,
4b7e6066 7279 safi_t safi, bool use_json, json_object *json)
d62a17ae 7280{
7281 struct attr *attr;
7282 int len;
7283 char timebuf[BGP_UPTIME_LEN];
7284
7285 /* short status lead text */
9b6d8fcf 7286 route_vty_short_status_out(vty, path, json);
d62a17ae 7287
7288 /* print prefix and mask */
7289 if (!use_json) {
7290 if (!display)
9c92b5f7 7291 route_vty_out_route(p, vty, NULL);
d62a17ae 7292 else
7293 vty_out(vty, "%*s", 17, " ");
7294 }
7295
9b6d8fcf 7296 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 7297 len = 17 - len;
7298 if (len < 1) {
7299 if (!use_json)
7300 vty_out(vty, "\n%*s", 34, " ");
7301 } else {
7302 if (use_json)
7303 json_object_int_add(json, "peerHost", len);
7304 else
7305 vty_out(vty, "%*s", len, " ");
7306 }
7307
7308 if (use_json)
9b6d8fcf 7309 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN,
d62a17ae 7310 use_json, json);
7311 else
9b6d8fcf
DS
7312 vty_out(vty, "%s ",
7313 bgp_damp_reuse_time_vty(vty, path, timebuf,
7314 BGP_UPTIME_LEN, use_json,
7315 json));
d62a17ae 7316
7317 /* Print attribute */
9b6d8fcf 7318 attr = path->attr;
d62a17ae 7319 if (attr) {
7320 /* Print aspath */
7321 if (attr->aspath) {
7322 if (use_json)
7323 json_object_string_add(json, "asPath",
7324 attr->aspath->str);
7325 else
7326 aspath_print_vty(vty, "%s", attr->aspath, " ");
7327 }
7328
7329 /* Print origin */
7330 if (use_json)
7331 json_object_string_add(json, "origin",
7332 bgp_origin_str[attr->origin]);
7333 else
7334 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7335 }
7336 if (!use_json)
7337 vty_out(vty, "\n");
7338}
718e3744 7339
d62a17ae 7340/* flap route */
7341static void flap_route_vty_out(struct vty *vty, struct prefix *p,
9b6d8fcf 7342 struct bgp_path_info *path, int display,
4b7e6066 7343 safi_t safi, bool use_json, json_object *json)
784d3a42 7344{
d62a17ae 7345 struct attr *attr;
7346 struct bgp_damp_info *bdi;
7347 char timebuf[BGP_UPTIME_LEN];
7348 int len;
784d3a42 7349
9b6d8fcf 7350 if (!path->extra)
d62a17ae 7351 return;
784d3a42 7352
9b6d8fcf 7353 bdi = path->extra->damp_info;
784d3a42 7354
d62a17ae 7355 /* short status lead text */
9b6d8fcf 7356 route_vty_short_status_out(vty, path, json);
784d3a42 7357
d62a17ae 7358 /* print prefix and mask */
7359 if (!use_json) {
7360 if (!display)
9c92b5f7 7361 route_vty_out_route(p, vty, NULL);
d62a17ae 7362 else
7363 vty_out(vty, "%*s", 17, " ");
7364 }
784d3a42 7365
9b6d8fcf 7366 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 7367 len = 16 - len;
7368 if (len < 1) {
7369 if (!use_json)
7370 vty_out(vty, "\n%*s", 33, " ");
7371 } else {
7372 if (use_json)
7373 json_object_int_add(json, "peerHost", len);
7374 else
7375 vty_out(vty, "%*s", len, " ");
7376 }
784d3a42 7377
d62a17ae 7378 len = vty_out(vty, "%d", bdi->flap);
7379 len = 5 - len;
7380 if (len < 1) {
7381 if (!use_json)
7382 vty_out(vty, " ");
7383 } else {
7384 if (use_json)
7385 json_object_int_add(json, "bdiFlap", len);
7386 else
7387 vty_out(vty, "%*s", len, " ");
7388 }
7389
7390 if (use_json)
7391 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
7392 json);
7393 else
996c9314
LB
7394 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
7395 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 7396
9b6d8fcf
DS
7397 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
7398 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 7399 if (use_json)
9b6d8fcf 7400 bgp_damp_reuse_time_vty(vty, path, timebuf,
d62a17ae 7401 BGP_UPTIME_LEN, use_json, json);
7402 else
7403 vty_out(vty, "%s ",
9b6d8fcf 7404 bgp_damp_reuse_time_vty(vty, path, timebuf,
d62a17ae 7405 BGP_UPTIME_LEN,
7406 use_json, json));
7407 } else {
7408 if (!use_json)
7409 vty_out(vty, "%*s ", 8, " ");
7410 }
7411
7412 /* Print attribute */
9b6d8fcf 7413 attr = path->attr;
d62a17ae 7414 if (attr) {
7415 /* Print aspath */
7416 if (attr->aspath) {
7417 if (use_json)
7418 json_object_string_add(json, "asPath",
7419 attr->aspath->str);
7420 else
7421 aspath_print_vty(vty, "%s", attr->aspath, " ");
7422 }
7423
7424 /* Print origin */
7425 if (use_json)
7426 json_object_string_add(json, "origin",
7427 bgp_origin_str[attr->origin]);
7428 else
7429 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7430 }
7431 if (!use_json)
7432 vty_out(vty, "\n");
7433}
7434
7435static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
7436 int *first, const char *header,
7437 json_object *json_adv_to)
7438{
7439 char buf1[INET6_ADDRSTRLEN];
7440 json_object *json_peer = NULL;
7441
7442 if (json_adv_to) {
7443 /* 'advertised-to' is a dictionary of peers we have advertised
7444 * this
7445 * prefix too. The key is the peer's IP or swpX, the value is
7446 * the
7447 * hostname if we know it and "" if not.
7448 */
7449 json_peer = json_object_new_object();
7450
7451 if (peer->hostname)
7452 json_object_string_add(json_peer, "hostname",
7453 peer->hostname);
7454
7455 if (peer->conf_if)
7456 json_object_object_add(json_adv_to, peer->conf_if,
7457 json_peer);
7458 else
7459 json_object_object_add(
7460 json_adv_to,
7461 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
7462 json_peer);
7463 } else {
7464 if (*first) {
7465 vty_out(vty, "%s", header);
7466 *first = 0;
7467 }
7468
7469 if (peer->hostname
7470 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
7471 if (peer->conf_if)
7472 vty_out(vty, " %s(%s)", peer->hostname,
7473 peer->conf_if);
7474 else
7475 vty_out(vty, " %s(%s)", peer->hostname,
7476 sockunion2str(&peer->su, buf1,
7477 SU_ADDRSTRLEN));
7478 } else {
7479 if (peer->conf_if)
7480 vty_out(vty, " %s", peer->conf_if);
7481 else
7482 vty_out(vty, " %s",
7483 sockunion2str(&peer->su, buf1,
7484 SU_ADDRSTRLEN));
7485 }
7486 }
784d3a42
PG
7487}
7488
d62a17ae 7489void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
9b6d8fcf 7490 struct bgp_path_info *path, afi_t afi, safi_t safi,
d62a17ae 7491 json_object *json_paths)
7492{
7493 char buf[INET6_ADDRSTRLEN];
7494 char buf1[BUFSIZ];
d62a17ae 7495 char buf2[EVPN_ROUTE_STRLEN];
d62a17ae 7496 struct attr *attr;
7497 int sockunion_vty_out(struct vty *, union sockunion *);
7498 time_t tbuf;
7499 json_object *json_bestpath = NULL;
7500 json_object *json_cluster_list = NULL;
7501 json_object *json_cluster_list_list = NULL;
7502 json_object *json_ext_community = NULL;
7503 json_object *json_last_update = NULL;
7fd077aa 7504 json_object *json_pmsi = NULL;
d62a17ae 7505 json_object *json_nexthop_global = NULL;
7506 json_object *json_nexthop_ll = NULL;
7507 json_object *json_nexthops = NULL;
7508 json_object *json_path = NULL;
7509 json_object *json_peer = NULL;
7510 json_object *json_string = NULL;
7511 json_object *json_adv_to = NULL;
7512 int first = 0;
7513 struct listnode *node, *nnode;
7514 struct peer *peer;
7515 int addpath_capable;
7516 int has_adj;
7517 unsigned int first_as;
1defdda8 7518 bool nexthop_self =
9b6d8fcf 7519 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
d62a17ae 7520
7521 if (json_paths) {
7522 json_path = json_object_new_object();
7523 json_peer = json_object_new_object();
7524 json_nexthop_global = json_object_new_object();
7525 }
7526
d62a17ae 7527 if (!json_paths && safi == SAFI_EVPN) {
b57ba6d2 7528 char tag_buf[30];
d62a17ae 7529
7530 bgp_evpn_route2str((struct prefix_evpn *)p, buf2, sizeof(buf2));
7531 vty_out(vty, " Route %s", buf2);
7532 tag_buf[0] = '\0';
9b6d8fcf
DS
7533 if (path->extra && path->extra->num_labels) {
7534 bgp_evpn_label2str(path->extra->label,
7535 path->extra->num_labels, tag_buf,
a4d82a8a 7536 sizeof(tag_buf));
d62a17ae 7537 vty_out(vty, " VNI %s", tag_buf);
7538 }
7539 vty_out(vty, "\n");
9b6d8fcf 7540 if (path->extra && path->extra->parent) {
4b7e6066 7541 struct bgp_path_info *parent_ri;
d62a17ae 7542 struct bgp_node *rn, *prn;
7543
9b6d8fcf 7544 parent_ri = (struct bgp_path_info *)path->extra->parent;
d62a17ae 7545 rn = parent_ri->net;
7546 if (rn && rn->prn) {
7547 prn = rn->prn;
7548 vty_out(vty, " Imported from %s:%s\n",
7549 prefix_rd2str(
7550 (struct prefix_rd *)&prn->p,
06b9f471 7551 buf1, sizeof(buf1)),
d62a17ae 7552 buf2);
7553 }
7554 }
7555 }
d62a17ae 7556
9b6d8fcf 7557 attr = path->attr;
d62a17ae 7558
7559 if (attr) {
7560 /* Line1 display AS-path, Aggregator */
7561 if (attr->aspath) {
7562 if (json_paths) {
68e1a55b
DS
7563 if (!attr->aspath->json)
7564 aspath_str_update(attr->aspath, true);
d62a17ae 7565 json_object_lock(attr->aspath->json);
7566 json_object_object_add(json_path, "aspath",
7567 attr->aspath->json);
7568 } else {
7569 if (attr->aspath->segments)
7570 aspath_print_vty(vty, " %s",
7571 attr->aspath, "");
7572 else
7573 vty_out(vty, " Local");
7574 }
7575 }
7576
9b6d8fcf 7577 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
d62a17ae 7578 if (json_paths)
7579 json_object_boolean_true_add(json_path,
7580 "removed");
7581 else
7582 vty_out(vty, ", (removed)");
7583 }
7584
9b6d8fcf 7585 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
d62a17ae 7586 if (json_paths)
7587 json_object_boolean_true_add(json_path,
7588 "stale");
7589 else
7590 vty_out(vty, ", (stale)");
7591 }
7592
7593 if (CHECK_FLAG(attr->flag,
7594 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
7595 if (json_paths) {
7596 json_object_int_add(json_path, "aggregatorAs",
7597 attr->aggregator_as);
7598 json_object_string_add(
7599 json_path, "aggregatorId",
7600 inet_ntoa(attr->aggregator_addr));
7601 } else {
7602 vty_out(vty, ", (aggregated by %u %s)",
7603 attr->aggregator_as,
7604 inet_ntoa(attr->aggregator_addr));
7605 }
7606 }
7607
9b6d8fcf 7608 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
d62a17ae 7609 PEER_FLAG_REFLECTOR_CLIENT)) {
7610 if (json_paths)
7611 json_object_boolean_true_add(
7612 json_path, "rxedFromRrClient");
7613 else
7614 vty_out(vty, ", (Received from a RR-client)");
7615 }
7616
9b6d8fcf 7617 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
d62a17ae 7618 PEER_FLAG_RSERVER_CLIENT)) {
7619 if (json_paths)
7620 json_object_boolean_true_add(
7621 json_path, "rxedFromRsClient");
7622 else
7623 vty_out(vty, ", (Received from a RS-client)");
7624 }
7625
9b6d8fcf 7626 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 7627 if (json_paths)
7628 json_object_boolean_true_add(
7629 json_path, "dampeningHistoryEntry");
7630 else
7631 vty_out(vty, ", (history entry)");
9b6d8fcf 7632 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
d62a17ae 7633 if (json_paths)
7634 json_object_boolean_true_add(
7635 json_path, "dampeningSuppressed");
7636 else
7637 vty_out(vty, ", (suppressed due to dampening)");
7638 }
7639
7640 if (!json_paths)
7641 vty_out(vty, "\n");
7642
7643 /* Line2 display Next-hop, Neighbor, Router-id */
7644 /* Display the nexthop */
a4d82a8a
PZ
7645 if ((p->family == AF_INET || p->family == AF_ETHERNET
7646 || p->family == AF_EVPN)
d62a17ae 7647 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7648 || safi == SAFI_EVPN
7649 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7650 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7651 || safi == SAFI_EVPN) {
7652 if (json_paths)
7653 json_object_string_add(
7654 json_nexthop_global, "ip",
7655 inet_ntoa(
7656 attr->mp_nexthop_global_in));
7657 else
7658 vty_out(vty, " %s",
7659 inet_ntoa(
7660 attr->mp_nexthop_global_in));
7661 } else {
7662 if (json_paths)
7663 json_object_string_add(
7664 json_nexthop_global, "ip",
7665 inet_ntoa(attr->nexthop));
7666 else
7667 vty_out(vty, " %s",
7668 inet_ntoa(attr->nexthop));
7669 }
7670
7671 if (json_paths)
7672 json_object_string_add(json_nexthop_global,
7673 "afi", "ipv4");
7674 } else {
7675 if (json_paths) {
7676 json_object_string_add(
7677 json_nexthop_global, "ip",
7678 inet_ntop(AF_INET6,
7679 &attr->mp_nexthop_global, buf,
7680 INET6_ADDRSTRLEN));
7681 json_object_string_add(json_nexthop_global,
7682 "afi", "ipv6");
7683 json_object_string_add(json_nexthop_global,
7684 "scope", "global");
7685 } else {
7686 vty_out(vty, " %s",
7687 inet_ntop(AF_INET6,
7688 &attr->mp_nexthop_global, buf,
7689 INET6_ADDRSTRLEN));
7690 }
7691 }
7692
7693 /* Display the IGP cost or 'inaccessible' */
9b6d8fcf 7694 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
d62a17ae 7695 if (json_paths)
7696 json_object_boolean_false_add(
7697 json_nexthop_global, "accessible");
7698 else
7699 vty_out(vty, " (inaccessible)");
7700 } else {
9b6d8fcf 7701 if (path->extra && path->extra->igpmetric) {
d62a17ae 7702 if (json_paths)
7703 json_object_int_add(
7704 json_nexthop_global, "metric",
9b6d8fcf 7705 path->extra->igpmetric);
d62a17ae 7706 else
7707 vty_out(vty, " (metric %u)",
9b6d8fcf 7708 path->extra->igpmetric);
d62a17ae 7709 }
7710
7711 /* IGP cost is 0, display this only for json */
7712 else {
7713 if (json_paths)
7714 json_object_int_add(json_nexthop_global,
7715 "metric", 0);
7716 }
7717
7718 if (json_paths)
7719 json_object_boolean_true_add(
7720 json_nexthop_global, "accessible");
7721 }
7722
7723 /* Display peer "from" output */
7724 /* This path was originated locally */
9b6d8fcf 7725 if (path->peer == bgp->peer_self) {
d62a17ae 7726
7727 if (safi == SAFI_EVPN
7728 || (p->family == AF_INET
7729 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7730 if (json_paths)
7731 json_object_string_add(
7732 json_peer, "peerId", "0.0.0.0");
7733 else
7734 vty_out(vty, " from 0.0.0.0 ");
7735 } else {
7736 if (json_paths)
7737 json_object_string_add(json_peer,
7738 "peerId", "::");
7739 else
7740 vty_out(vty, " from :: ");
7741 }
7742
7743 if (json_paths)
7744 json_object_string_add(
7745 json_peer, "routerId",
7746 inet_ntoa(bgp->router_id));
7747 else
7748 vty_out(vty, "(%s)", inet_ntoa(bgp->router_id));
7749 }
7750
7751 /* We RXed this path from one of our peers */
7752 else {
7753
7754 if (json_paths) {
7755 json_object_string_add(
7756 json_peer, "peerId",
9b6d8fcf 7757 sockunion2str(&path->peer->su, buf,
d62a17ae 7758 SU_ADDRSTRLEN));
7759 json_object_string_add(
7760 json_peer, "routerId",
7761 inet_ntop(AF_INET,
9b6d8fcf 7762 &path->peer->remote_id, buf1,
06b9f471 7763 sizeof(buf1)));
d62a17ae 7764
9b6d8fcf 7765 if (path->peer->hostname)
d62a17ae 7766 json_object_string_add(
7767 json_peer, "hostname",
9b6d8fcf 7768 path->peer->hostname);
d62a17ae 7769
9b6d8fcf 7770 if (path->peer->domainname)
d62a17ae 7771 json_object_string_add(
7772 json_peer, "domainname",
9b6d8fcf 7773 path->peer->domainname);
d62a17ae 7774
9b6d8fcf 7775 if (path->peer->conf_if)
d62a17ae 7776 json_object_string_add(
7777 json_peer, "interface",
9b6d8fcf 7778 path->peer->conf_if);
d62a17ae 7779 } else {
9b6d8fcf
DS
7780 if (path->peer->conf_if) {
7781 if (path->peer->hostname
d62a17ae 7782 && bgp_flag_check(
9b6d8fcf 7783 path->peer->bgp,
d62a17ae 7784 BGP_FLAG_SHOW_HOSTNAME))
7785 vty_out(vty, " from %s(%s)",
9b6d8fcf
DS
7786 path->peer->hostname,
7787 path->peer->conf_if);
d62a17ae 7788 else
7789 vty_out(vty, " from %s",
9b6d8fcf 7790 path->peer->conf_if);
d62a17ae 7791 } else {
9b6d8fcf 7792 if (path->peer->hostname
d62a17ae 7793 && bgp_flag_check(
9b6d8fcf 7794 path->peer->bgp,
d62a17ae 7795 BGP_FLAG_SHOW_HOSTNAME))
7796 vty_out(vty, " from %s(%s)",
9b6d8fcf
DS
7797 path->peer->hostname,
7798 path->peer->host);
d62a17ae 7799 else
7800 vty_out(vty, " from %s",
7801 sockunion2str(
9b6d8fcf 7802 &path->peer->su,
d62a17ae 7803 buf,
7804 SU_ADDRSTRLEN));
7805 }
7806
7807 if (attr->flag
7808 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
7809 vty_out(vty, " (%s)",
7810 inet_ntoa(attr->originator_id));
7811 else
7812 vty_out(vty, " (%s)",
7813 inet_ntop(
7814 AF_INET,
9b6d8fcf 7815 &path->peer->remote_id,
06b9f471 7816 buf1, sizeof(buf1)));
d62a17ae 7817 }
7818 }
7819
9df8b37c
PZ
7820 /*
7821 * Note when vrfid of nexthop is different from that of prefix
7822 */
9b6d8fcf
DS
7823 if (path->extra && path->extra->bgp_orig) {
7824 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c
PZ
7825
7826 if (json_paths) {
7827 const char *vn;
7828
9b6d8fcf
DS
7829 if (path->extra->bgp_orig->inst_type
7830 == BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c
PZ
7831
7832 vn = "Default";
7833 else
9b6d8fcf 7834 vn = path->extra->bgp_orig->name;
9df8b37c
PZ
7835
7836 json_object_string_add(json_path, "nhVrfName",
7837 vn);
7838
7839 if (nexthop_vrfid == VRF_UNKNOWN) {
7840 json_object_int_add(json_path,
7841 "nhVrfId", -1);
7842 } else {
7843 json_object_int_add(json_path,
7844 "nhVrfId", (int)nexthop_vrfid);
7845 }
7846 } else {
7847 if (nexthop_vrfid == VRF_UNKNOWN)
7848 vty_out(vty, " vrf ?");
7849 else
7850 vty_out(vty, " vrf %u", nexthop_vrfid);
7851 }
7852 }
7853
7854 if (nexthop_self) {
7855 if (json_paths) {
7856 json_object_boolean_true_add(json_path,
7857 "announceNexthopSelf");
7858 } else {
7859 vty_out(vty, " announce-nh-self");
7860 }
7861 }
7862
d62a17ae 7863 if (!json_paths)
7864 vty_out(vty, "\n");
7865
7866 /* display the link-local nexthop */
7867 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
7868 if (json_paths) {
7869 json_nexthop_ll = json_object_new_object();
7870 json_object_string_add(
7871 json_nexthop_ll, "ip",
7872 inet_ntop(AF_INET6,
7873 &attr->mp_nexthop_local, buf,
7874 INET6_ADDRSTRLEN));
7875 json_object_string_add(json_nexthop_ll, "afi",
7876 "ipv6");
7877 json_object_string_add(json_nexthop_ll, "scope",
7878 "link-local");
7879
7880 json_object_boolean_true_add(json_nexthop_ll,
7881 "accessible");
7882
7883 if (!attr->mp_nexthop_prefer_global)
7884 json_object_boolean_true_add(
7885 json_nexthop_ll, "used");
7886 else
7887 json_object_boolean_true_add(
7888 json_nexthop_global, "used");
7889 } else {
7890 vty_out(vty, " (%s) %s\n",
7891 inet_ntop(AF_INET6,
7892 &attr->mp_nexthop_local, buf,
7893 INET6_ADDRSTRLEN),
7894 attr->mp_nexthop_prefer_global
7895 ? "(prefer-global)"
7896 : "(used)");
7897 }
7898 }
7899 /* If we do not have a link-local nexthop then we must flag the
7900 global as "used" */
7901 else {
7902 if (json_paths)
7903 json_object_boolean_true_add(
7904 json_nexthop_global, "used");
7905 }
718e3744 7906
d62a17ae 7907 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7908 * Int/Ext/Local, Atomic, best */
7909 if (json_paths)
7910 json_object_string_add(
7911 json_path, "origin",
7912 bgp_origin_long_str[attr->origin]);
7913 else
7914 vty_out(vty, " Origin %s",
7915 bgp_origin_long_str[attr->origin]);
7916
7917 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
50e05855
AD
7918 if (json_paths) {
7919
7920 /*
7921 * Adding "metric" field to match with
7922 * corresponding CLI. "med" will be
7923 * deprecated in future.
7924 */
d62a17ae 7925 json_object_int_add(json_path, "med",
7926 attr->med);
50e05855
AD
7927 json_object_int_add(json_path, "metric",
7928 attr->med);
7929 } else
d62a17ae 7930 vty_out(vty, ", metric %u", attr->med);
7931 }
718e3744 7932
d62a17ae 7933 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
7934 if (json_paths)
7935 json_object_int_add(json_path, "localpref",
7936 attr->local_pref);
7937 else
7938 vty_out(vty, ", localpref %u",
7939 attr->local_pref);
d62a17ae 7940 }
718e3744 7941
d62a17ae 7942 if (attr->weight != 0) {
7943 if (json_paths)
7944 json_object_int_add(json_path, "weight",
7945 attr->weight);
7946 else
7947 vty_out(vty, ", weight %u", attr->weight);
7948 }
718e3744 7949
d62a17ae 7950 if (attr->tag != 0) {
7951 if (json_paths)
7952 json_object_int_add(json_path, "tag",
7953 attr->tag);
7954 else
7955 vty_out(vty, ", tag %" ROUTE_TAG_PRI,
7956 attr->tag);
7957 }
718e3744 7958
9b6d8fcf 7959 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
d62a17ae 7960 if (json_paths)
7961 json_object_boolean_false_add(json_path,
7962 "valid");
7963 else
7964 vty_out(vty, ", invalid");
9b6d8fcf 7965 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 7966 if (json_paths)
7967 json_object_boolean_true_add(json_path,
7968 "valid");
7969 else
7970 vty_out(vty, ", valid");
7971 }
718e3744 7972
9b6d8fcf
DS
7973 if (path->peer != bgp->peer_self) {
7974 if (path->peer->as == path->peer->local_as) {
d62a17ae 7975 if (CHECK_FLAG(bgp->config,
7976 BGP_CONFIG_CONFEDERATION)) {
7977 if (json_paths)
7978 json_object_string_add(
7979 json_peer, "type",
7980 "confed-internal");
7981 else
7982 vty_out(vty,
7983 ", confed-internal");
7984 } else {
7985 if (json_paths)
7986 json_object_string_add(
7987 json_peer, "type",
7988 "internal");
7989 else
7990 vty_out(vty, ", internal");
7991 }
7992 } else {
7993 if (bgp_confederation_peers_check(
9b6d8fcf 7994 bgp, path->peer->as)) {
d62a17ae 7995 if (json_paths)
7996 json_object_string_add(
7997 json_peer, "type",
7998 "confed-external");
7999 else
8000 vty_out(vty,
8001 ", confed-external");
8002 } else {
8003 if (json_paths)
8004 json_object_string_add(
8005 json_peer, "type",
8006 "external");
8007 else
8008 vty_out(vty, ", external");
8009 }
8010 }
9b6d8fcf 8011 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
d62a17ae 8012 if (json_paths) {
8013 json_object_boolean_true_add(json_path,
8014 "aggregated");
8015 json_object_boolean_true_add(json_path,
8016 "local");
8017 } else {
8018 vty_out(vty, ", aggregated, local");
8019 }
9b6d8fcf 8020 } else if (path->type != ZEBRA_ROUTE_BGP) {
d62a17ae 8021 if (json_paths)
8022 json_object_boolean_true_add(json_path,
8023 "sourced");
8024 else
8025 vty_out(vty, ", sourced");
8026 } else {
8027 if (json_paths) {
8028 json_object_boolean_true_add(json_path,
8029 "sourced");
8030 json_object_boolean_true_add(json_path,
8031 "local");
8032 } else {
8033 vty_out(vty, ", sourced, local");
8034 }
8035 }
718e3744 8036
d62a17ae 8037 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
8038 if (json_paths)
8039 json_object_boolean_true_add(json_path,
8040 "atomicAggregate");
8041 else
8042 vty_out(vty, ", atomic-aggregate");
8043 }
718e3744 8044
9b6d8fcf
DS
8045 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
8046 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
8047 && bgp_path_info_mpath_count(path))) {
d62a17ae 8048 if (json_paths)
8049 json_object_boolean_true_add(json_path,
8050 "multipath");
8051 else
8052 vty_out(vty, ", multipath");
8053 }
856ca177 8054
d62a17ae 8055 // Mark the bestpath(s)
9b6d8fcf 8056 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
d62a17ae 8057 first_as = aspath_get_first_as(attr->aspath);
8058
8059 if (json_paths) {
8060 if (!json_bestpath)
8061 json_bestpath =
8062 json_object_new_object();
8063 json_object_int_add(json_bestpath,
8064 "bestpathFromAs", first_as);
8065 } else {
8066 if (first_as)
fb2b0934 8067 vty_out(vty, ", bestpath-from-AS %u",
d62a17ae 8068 first_as);
8069 else
8070 vty_out(vty,
8071 ", bestpath-from-AS Local");
8072 }
8073 }
718e3744 8074
9b6d8fcf 8075 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8076 if (json_paths) {
8077 if (!json_bestpath)
8078 json_bestpath =
8079 json_object_new_object();
8080 json_object_boolean_true_add(json_bestpath,
8081 "overall");
8082 } else
8083 vty_out(vty, ", best");
8084 }
718e3744 8085
d62a17ae 8086 if (json_bestpath)
8087 json_object_object_add(json_path, "bestpath",
8088 json_bestpath);
8089
8090 if (!json_paths)
8091 vty_out(vty, "\n");
8092
8093 /* Line 4 display Community */
8094 if (attr->community) {
8095 if (json_paths) {
a69ea8ae 8096 if (!attr->community->json)
a4d82a8a 8097 community_str(attr->community, true);
d62a17ae 8098 json_object_lock(attr->community->json);
8099 json_object_object_add(json_path, "community",
8100 attr->community->json);
8101 } else {
8102 vty_out(vty, " Community: %s\n",
8103 attr->community->str);
8104 }
8105 }
718e3744 8106
d62a17ae 8107 /* Line 5 display Extended-community */
8108 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8109 if (json_paths) {
8110 json_ext_community = json_object_new_object();
8111 json_object_string_add(json_ext_community,
8112 "string",
8113 attr->ecommunity->str);
8114 json_object_object_add(json_path,
8115 "extendedCommunity",
8116 json_ext_community);
8117 } else {
8118 vty_out(vty, " Extended Community: %s\n",
8119 attr->ecommunity->str);
8120 }
8121 }
adbac85e 8122
d62a17ae 8123 /* Line 6 display Large community */
b96879c0
DS
8124 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
8125 if (json_paths) {
8d9b8ed9
PM
8126 if (!attr->lcommunity->json)
8127 lcommunity_str(attr->lcommunity, true);
8128 json_object_lock(attr->lcommunity->json);
b96879c0
DS
8129 json_object_object_add(json_path,
8130 "largeCommunity",
8d9b8ed9 8131 attr->lcommunity->json);
b96879c0
DS
8132 } else {
8133 vty_out(vty, " Large Community: %s\n",
8134 attr->lcommunity->str);
8135 }
8136 }
d62a17ae 8137
8138 /* Line 7 display Originator, Cluster-id */
8139 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
8140 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
8141 if (attr->flag
8142 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
8143 if (json_paths)
8144 json_object_string_add(
8145 json_path, "originatorId",
8146 inet_ntoa(attr->originator_id));
8147 else
8148 vty_out(vty, " Originator: %s",
8149 inet_ntoa(attr->originator_id));
8150 }
8151
8152 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
8153 int i;
8154
8155 if (json_paths) {
8156 json_cluster_list =
8157 json_object_new_object();
8158 json_cluster_list_list =
8159 json_object_new_array();
8160
8161 for (i = 0;
8162 i < attr->cluster->length / 4;
8163 i++) {
8164 json_string = json_object_new_string(
8165 inet_ntoa(
8166 attr->cluster->list
8167 [i]));
8168 json_object_array_add(
8169 json_cluster_list_list,
8170 json_string);
8171 }
8172
8173 /* struct cluster_list does not have
8174 "str" variable like
8175 * aspath and community do. Add this
8176 someday if someone
8177 * asks for it.
8178 json_object_string_add(json_cluster_list,
8179 "string", attr->cluster->str);
8180 */
8181 json_object_object_add(
8182 json_cluster_list, "list",
8183 json_cluster_list_list);
8184 json_object_object_add(
8185 json_path, "clusterList",
8186 json_cluster_list);
8187 } else {
8188 vty_out(vty, ", Cluster list: ");
8189
8190 for (i = 0;
8191 i < attr->cluster->length / 4;
8192 i++) {
8193 vty_out(vty, "%s ",
8194 inet_ntoa(
8195 attr->cluster->list
8196 [i]));
8197 }
8198 }
8199 }
8200
8201 if (!json_paths)
8202 vty_out(vty, "\n");
8203 }
adbac85e 8204
9b6d8fcf
DS
8205 if (path->extra && path->extra->damp_info)
8206 bgp_damp_info_vty(vty, path, json_path);
d62a17ae 8207
6a527b2f 8208 /* Remote Label */
9b6d8fcf 8209 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
6a527b2f 8210 && safi != SAFI_EVPN) {
9b6d8fcf 8211 mpls_label_t label = label_pton(&path->extra->label[0]);
121e245d 8212
d62a17ae 8213 if (json_paths)
8214 json_object_int_add(json_path, "remoteLabel",
8215 label);
8216 else
8217 vty_out(vty, " Remote label: %d\n", label);
8218 }
b05a1c8b 8219
d62a17ae 8220 /* Label Index */
8221 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
8222 if (json_paths)
8223 json_object_int_add(json_path, "labelIndex",
8224 attr->label_index);
8225 else
8226 vty_out(vty, " Label Index: %d\n",
8227 attr->label_index);
8228 }
520d5d76 8229
d62a17ae 8230 /* Line 8 display Addpath IDs */
9b6d8fcf 8231 if (path->addpath_rx_id || path->addpath_tx_id) {
d62a17ae 8232 if (json_paths) {
8233 json_object_int_add(json_path, "addpathRxId",
9b6d8fcf 8234 path->addpath_rx_id);
d62a17ae 8235 json_object_int_add(json_path, "addpathTxId",
9b6d8fcf 8236 path->addpath_tx_id);
d62a17ae 8237 } else {
8238 vty_out(vty, " AddPath ID: RX %u, TX %u\n",
9b6d8fcf
DS
8239 path->addpath_rx_id,
8240 path->addpath_tx_id);
d62a17ae 8241 }
8242 }
718e3744 8243
d62a17ae 8244 /* If we used addpath to TX a non-bestpath we need to display
8245 * "Advertised to" on a path-by-path basis */
8246 if (bgp->addpath_tx_used[afi][safi]) {
8247 first = 1;
8248
8249 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
8250 addpath_capable =
8251 bgp_addpath_encode_tx(peer, afi, safi);
8252 has_adj = bgp_adj_out_lookup(
9b6d8fcf 8253 peer, path->net, path->addpath_tx_id);
d62a17ae 8254
8255 if ((addpath_capable && has_adj)
8256 || (!addpath_capable && has_adj
9b6d8fcf 8257 && CHECK_FLAG(path->flags,
1defdda8 8258 BGP_PATH_SELECTED))) {
d62a17ae 8259 if (json_path && !json_adv_to)
8260 json_adv_to =
8261 json_object_new_object();
8262
8263 route_vty_out_advertised_to(
8264 vty, peer, &first,
8265 " Advertised to:",
8266 json_adv_to);
8267 }
8268 }
8269
8270 if (json_path) {
8271 if (json_adv_to) {
8272 json_object_object_add(json_path,
8273 "advertisedTo",
8274 json_adv_to);
8275 }
8276 } else {
8277 if (!first) {
8278 vty_out(vty, "\n");
8279 }
8280 }
8281 }
b05a1c8b 8282
d62a17ae 8283 /* Line 9 display Uptime */
9b6d8fcf 8284 tbuf = time(NULL) - (bgp_clock() - path->uptime);
d62a17ae 8285 if (json_paths) {
8286 json_last_update = json_object_new_object();
8287 json_object_int_add(json_last_update, "epoch", tbuf);
8288 json_object_string_add(json_last_update, "string",
8289 ctime(&tbuf));
8290 json_object_object_add(json_path, "lastUpdate",
8291 json_last_update);
8292 } else
8293 vty_out(vty, " Last update: %s", ctime(&tbuf));
7fd077aa 8294
8295 /* Line 10 display PMSI tunnel attribute, if present */
8296 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
b7d08f5a 8297 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
8298 attr->pmsi_tnl_type,
8299 PMSI_TNLTYPE_STR_DEFAULT);
8300
7fd077aa 8301 if (json_paths) {
8302 json_pmsi = json_object_new_object();
b7d08f5a 8303 json_object_string_add(json_pmsi,
8304 "tunnelType", str);
7fd077aa 8305 json_object_object_add(json_path, "pmsi",
8306 json_pmsi);
8307 } else
8308 vty_out(vty, " PMSI Tunnel Type: %s\n",
b7d08f5a 8309 str);
7fd077aa 8310 }
8311
d62a17ae 8312 }
f1aa5d8a 8313
d62a17ae 8314 /* We've constructed the json object for this path, add it to the json
8315 * array of paths
8316 */
8317 if (json_paths) {
8318 if (json_nexthop_global || json_nexthop_ll) {
8319 json_nexthops = json_object_new_array();
f1aa5d8a 8320
d62a17ae 8321 if (json_nexthop_global)
8322 json_object_array_add(json_nexthops,
8323 json_nexthop_global);
f1aa5d8a 8324
d62a17ae 8325 if (json_nexthop_ll)
8326 json_object_array_add(json_nexthops,
8327 json_nexthop_ll);
f1aa5d8a 8328
d62a17ae 8329 json_object_object_add(json_path, "nexthops",
8330 json_nexthops);
8331 }
8332
8333 json_object_object_add(json_path, "peer", json_peer);
8334 json_object_array_add(json_paths, json_path);
8335 } else
8336 vty_out(vty, "\n");
b366b518
BB
8337}
8338
96ade3ed 8339#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
8340#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8341#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 8342
d62a17ae 8343static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
8344 const char *prefix_list_str, afi_t afi,
8345 safi_t safi, enum bgp_show_type type);
8346static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
8347 const char *filter, afi_t afi, safi_t safi,
8348 enum bgp_show_type type);
8349static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
8350 const char *rmap_str, afi_t afi, safi_t safi,
8351 enum bgp_show_type type);
8352static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
8353 const char *com, int exact, afi_t afi,
8354 safi_t safi);
8355static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
8356 const char *prefix, afi_t afi, safi_t safi,
8357 enum bgp_show_type type);
a4d82a8a
PZ
8358static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
8359 afi_t afi, safi_t safi, enum bgp_show_type type);
7f323236
DW
8360static int bgp_show_community(struct vty *vty, struct bgp *bgp,
8361 const char *comstr, int exact, afi_t afi,
9f049418 8362 safi_t safi, bool use_json);
d62a17ae 8363
1ae44dfc
LB
8364
8365static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 8366 struct bgp_table *table, enum bgp_show_type type,
9f049418 8367 void *output_arg, bool use_json, char *rd,
a4d82a8a
PZ
8368 int is_last, unsigned long *output_cum,
8369 unsigned long *total_cum,
9386b588 8370 unsigned long *json_header_depth)
d62a17ae 8371{
40381db7 8372 struct bgp_path_info *pi;
d62a17ae 8373 struct bgp_node *rn;
8374 int header = 1;
8375 int display;
1ae44dfc
LB
8376 unsigned long output_count = 0;
8377 unsigned long total_count = 0;
d62a17ae 8378 struct prefix *p;
d62a17ae 8379 char buf2[BUFSIZ];
8380 json_object *json_paths = NULL;
8381 int first = 1;
8382
1ae44dfc
LB
8383 if (output_cum && *output_cum != 0)
8384 header = 0;
8385
9386b588 8386 if (use_json && !*json_header_depth) {
d62a17ae 8387 vty_out(vty,
66f80d74
DS
8388 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8389 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
a8bf7d9c 8390 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b
DS
8391 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
8392 ? VRF_DEFAULT_NAME
8393 : bgp->name,
d62a17ae 8394 table->version, inet_ntoa(bgp->router_id));
9386b588
PZ
8395 *json_header_depth = 2;
8396 if (rd) {
445c2480 8397 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
8398 ++*json_header_depth;
8399 }
d62a17ae 8400 }
718e3744 8401
445c2480
DS
8402 if (use_json && rd) {
8403 vty_out(vty, " \"%s\" : { ", rd);
8404 }
8405
d62a17ae 8406 /* Start processing of routes. */
98ce9a06
DS
8407 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
8408 if (rn->info == NULL)
8409 continue;
d62a17ae 8410
98ce9a06 8411 display = 0;
98ce9a06
DS
8412 if (use_json)
8413 json_paths = json_object_new_array();
8414 else
8415 json_paths = NULL;
d62a17ae 8416
40381db7 8417 for (pi = rn->info; pi; pi = pi->next) {
98ce9a06
DS
8418 total_count++;
8419 if (type == bgp_show_type_flap_statistics
8420 || type == bgp_show_type_flap_neighbor
8421 || type == bgp_show_type_dampend_paths
8422 || type == bgp_show_type_damp_neighbor) {
40381db7 8423 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
8424 continue;
8425 }
8426 if (type == bgp_show_type_regexp) {
8427 regex_t *regex = output_arg;
d62a17ae 8428
40381db7 8429 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
8430 == REG_NOMATCH)
8431 continue;
8432 }
8433 if (type == bgp_show_type_prefix_list) {
8434 struct prefix_list *plist = output_arg;
d62a17ae 8435
98ce9a06
DS
8436 if (prefix_list_apply(plist, &rn->p)
8437 != PREFIX_PERMIT)
8438 continue;
8439 }
8440 if (type == bgp_show_type_filter_list) {
8441 struct as_list *as_list = output_arg;
d62a17ae 8442
40381db7 8443 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
8444 != AS_FILTER_PERMIT)
8445 continue;
8446 }
8447 if (type == bgp_show_type_route_map) {
8448 struct route_map *rmap = output_arg;
9b6d8fcf 8449 struct bgp_path_info path;
98ce9a06
DS
8450 struct attr dummy_attr;
8451 int ret;
d62a17ae 8452
40381db7 8453 bgp_attr_dup(&dummy_attr, pi->attr);
d62a17ae 8454
40381db7 8455 path.peer = pi->peer;
9b6d8fcf 8456 path.attr = &dummy_attr;
d62a17ae 8457
a4d82a8a 8458 ret = route_map_apply(rmap, &rn->p, RMAP_BGP,
9b6d8fcf 8459 &path);
98ce9a06
DS
8460 if (ret == RMAP_DENYMATCH)
8461 continue;
8462 }
8463 if (type == bgp_show_type_neighbor
8464 || type == bgp_show_type_flap_neighbor
8465 || type == bgp_show_type_damp_neighbor) {
8466 union sockunion *su = output_arg;
8467
40381db7
DS
8468 if (pi->peer == NULL
8469 || pi->peer->su_remote == NULL
8470 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
8471 continue;
8472 }
8473 if (type == bgp_show_type_cidr_only) {
d7c0a89a 8474 uint32_t destination;
d62a17ae 8475
98ce9a06
DS
8476 destination = ntohl(rn->p.u.prefix4.s_addr);
8477 if (IN_CLASSC(destination)
8478 && rn->p.prefixlen == 24)
8479 continue;
8480 if (IN_CLASSB(destination)
8481 && rn->p.prefixlen == 16)
8482 continue;
8483 if (IN_CLASSA(destination)
8484 && rn->p.prefixlen == 8)
8485 continue;
8486 }
8487 if (type == bgp_show_type_prefix_longer) {
f7813c7c 8488 p = output_arg;
98ce9a06
DS
8489 if (!prefix_match(p, &rn->p))
8490 continue;
8491 }
8492 if (type == bgp_show_type_community_all) {
40381db7 8493 if (!pi->attr->community)
98ce9a06
DS
8494 continue;
8495 }
8496 if (type == bgp_show_type_community) {
8497 struct community *com = output_arg;
d62a17ae 8498
40381db7
DS
8499 if (!pi->attr->community
8500 || !community_match(pi->attr->community,
98ce9a06
DS
8501 com))
8502 continue;
8503 }
8504 if (type == bgp_show_type_community_exact) {
8505 struct community *com = output_arg;
d62a17ae 8506
40381db7
DS
8507 if (!pi->attr->community
8508 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
8509 continue;
8510 }
8511 if (type == bgp_show_type_community_list) {
8512 struct community_list *list = output_arg;
d62a17ae 8513
40381db7 8514 if (!community_list_match(pi->attr->community,
a4d82a8a 8515 list))
98ce9a06
DS
8516 continue;
8517 }
a4d82a8a 8518 if (type == bgp_show_type_community_list_exact) {
98ce9a06 8519 struct community_list *list = output_arg;
d62a17ae 8520
98ce9a06 8521 if (!community_list_exact_match(
40381db7 8522 pi->attr->community, list))
98ce9a06
DS
8523 continue;
8524 }
8525 if (type == bgp_show_type_lcommunity) {
8526 struct lcommunity *lcom = output_arg;
d62a17ae 8527
40381db7
DS
8528 if (!pi->attr->lcommunity
8529 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
8530 lcom))
8531 continue;
8532 }
8533 if (type == bgp_show_type_lcommunity_list) {
8534 struct community_list *list = output_arg;
d62a17ae 8535
40381db7 8536 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 8537 list))
98ce9a06
DS
8538 continue;
8539 }
8540 if (type == bgp_show_type_lcommunity_all) {
40381db7 8541 if (!pi->attr->lcommunity)
98ce9a06
DS
8542 continue;
8543 }
8544 if (type == bgp_show_type_dampend_paths
8545 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
8546 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
8547 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
8548 continue;
8549 }
8550
8551 if (!use_json && header) {
996c9314 8552 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 8553 ", local router ID is %s, vrf id ",
98ce9a06
DS
8554 table->version,
8555 inet_ntoa(bgp->router_id));
9df8b37c
PZ
8556 if (bgp->vrf_id == VRF_UNKNOWN)
8557 vty_out(vty, "%s", VRFID_NONE_STR);
8558 else
8559 vty_out(vty, "%u", bgp->vrf_id);
8560 vty_out(vty, "\n");
98ce9a06 8561 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 8562 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 8563 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 8564 if (type == bgp_show_type_dampend_paths
8565 || type == bgp_show_type_damp_neighbor)
98ce9a06 8566 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
8567 else if (type == bgp_show_type_flap_statistics
8568 || type == bgp_show_type_flap_neighbor)
98ce9a06 8569 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 8570 else
98ce9a06
DS
8571 vty_out(vty, BGP_SHOW_HEADER);
8572 header = 0;
d62a17ae 8573 }
98ce9a06
DS
8574 if (rd != NULL && !display && !output_count) {
8575 if (!use_json)
8576 vty_out(vty,
8577 "Route Distinguisher: %s\n",
8578 rd);
d62a17ae 8579 }
98ce9a06
DS
8580 if (type == bgp_show_type_dampend_paths
8581 || type == bgp_show_type_damp_neighbor)
40381db7 8582 damp_route_vty_out(vty, &rn->p, pi, display,
a4d82a8a 8583 safi, use_json, json_paths);
98ce9a06
DS
8584 else if (type == bgp_show_type_flap_statistics
8585 || type == bgp_show_type_flap_neighbor)
40381db7 8586 flap_route_vty_out(vty, &rn->p, pi, display,
a4d82a8a 8587 safi, use_json, json_paths);
98ce9a06 8588 else
40381db7 8589 route_vty_out(vty, &rn->p, pi, display, safi,
a4d82a8a 8590 json_paths);
98ce9a06 8591 display++;
d62a17ae 8592 }
8593
98ce9a06
DS
8594 if (display) {
8595 output_count++;
8596 if (!use_json)
8597 continue;
8598
8599 p = &rn->p;
625d2931
PG
8600 /* encode prefix */
8601 if (p->family == AF_FLOWSPEC) {
8602 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
8603
8604 bgp_fs_nlri_get_string((unsigned char *)
8605 p->u.prefix_flowspec.ptr,
8606 p->u.prefix_flowspec
8607 .prefixlen,
8608 retstr,
8609 NLRI_STRING_FORMAT_MIN,
8610 NULL);
8611 if (first)
8612 vty_out(vty, "\"%s/%d\": ",
8613 retstr,
8614 p->u.prefix_flowspec.prefixlen);
8615 else
8616 vty_out(vty, ",\"%s/%d\": ",
8617 retstr,
8618 p->u.prefix_flowspec.prefixlen);
8619 } else {
8620 prefix2str(p, buf2, sizeof(buf2));
8621 if (first)
8622 vty_out(vty, "\"%s\": ", buf2);
8623 else
8624 vty_out(vty, ",\"%s\": ", buf2);
8625 }
98ce9a06 8626 vty_out(vty, "%s",
23b2a7ef 8627 json_object_to_json_string(json_paths));
98ce9a06 8628 json_object_free(json_paths);
449feb8e 8629 json_paths = NULL;
98ce9a06
DS
8630 first = 0;
8631 }
8632 }
8633
1ae44dfc
LB
8634 if (output_cum) {
8635 output_count += *output_cum;
8636 *output_cum = output_count;
8637 }
8638 if (total_cum) {
8639 total_count += *total_cum;
8640 *total_cum = total_count;
8641 }
d62a17ae 8642 if (use_json) {
9386b588 8643 if (rd) {
a4d82a8a 8644 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
8645 }
8646 if (is_last) {
a4d82a8a
PZ
8647 unsigned long i;
8648 for (i = 0; i < *json_header_depth; ++i)
8649 vty_out(vty, " } ");
9386b588 8650 }
d62a17ae 8651 } else {
1ae44dfc
LB
8652 if (is_last) {
8653 /* No route is displayed */
8654 if (output_count == 0) {
8655 if (type == bgp_show_type_normal)
8656 vty_out(vty,
8657 "No BGP prefixes displayed, %ld exist\n",
8658 total_count);
8659 } else
d62a17ae 8660 vty_out(vty,
1ae44dfc
LB
8661 "\nDisplayed %ld routes and %ld total paths\n",
8662 output_count, total_count);
8663 }
d62a17ae 8664 }
718e3744 8665
d62a17ae 8666 return CMD_SUCCESS;
718e3744 8667}
8668
1ae44dfc
LB
8669int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
8670 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 8671 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc
LB
8672{
8673 struct bgp_node *rn, *next;
8674 unsigned long output_cum = 0;
8675 unsigned long total_cum = 0;
9386b588 8676 unsigned long json_header_depth = 0;
0136788c
LB
8677 bool show_msg;
8678
8679 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc
LB
8680
8681 for (rn = bgp_table_top(table); rn; rn = next) {
8682 next = bgp_route_next(rn);
8683 if (prd_match && memcmp(rn->p.u.val, prd_match->val, 8) != 0)
8684 continue;
8685 if (rn->info != NULL) {
8686 struct prefix_rd prd;
06b9f471 8687 char rd[RD_ADDRSTRLEN];
1ae44dfc
LB
8688
8689 memcpy(&prd, &(rn->p), sizeof(struct prefix_rd));
06b9f471 8690 prefix_rd2str(&prd, rd, sizeof(rd));
1ae44dfc 8691 bgp_show_table(vty, bgp, safi, rn->info, type,
a4d82a8a 8692 output_arg, use_json, rd, next == NULL,
9386b588
PZ
8693 &output_cum, &total_cum,
8694 &json_header_depth);
0136788c
LB
8695 if (next == NULL)
8696 show_msg = false;
1ae44dfc
LB
8697 }
8698 }
0136788c
LB
8699 if (show_msg) {
8700 if (output_cum == 0)
8701 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
8702 total_cum);
8703 else
8704 vty_out(vty,
8705 "\nDisplayed %ld routes and %ld total paths\n",
8706 output_cum, total_cum);
8707 }
1ae44dfc
LB
8708 return CMD_SUCCESS;
8709}
d62a17ae 8710static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
9f049418 8711 enum bgp_show_type type, void *output_arg, bool use_json)
fee0f4c6 8712{
d62a17ae 8713 struct bgp_table *table;
9386b588 8714 unsigned long json_header_depth = 0;
fee0f4c6 8715
d62a17ae 8716 if (bgp == NULL) {
8717 bgp = bgp_get_default();
8718 }
fee0f4c6 8719
d62a17ae 8720 if (bgp == NULL) {
8721 if (!use_json)
8722 vty_out(vty, "No BGP process is configured\n");
16307668
RW
8723 else
8724 vty_out(vty, "{}\n");
d62a17ae 8725 return CMD_WARNING;
8726 }
4dd6177e 8727
1ae44dfc 8728 table = bgp->rib[afi][safi];
d62a17ae 8729 /* use MPLS and ENCAP specific shows until they are merged */
8730 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
8731 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
8732 output_arg, use_json);
d62a17ae 8733 }
dba3c1d3
PG
8734
8735 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
8736 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
8737 output_arg, use_json,
8738 1, NULL, NULL);
8739 }
d62a17ae 8740 /* labeled-unicast routes live in the unicast table */
8741 else if (safi == SAFI_LABELED_UNICAST)
8742 safi = SAFI_UNICAST;
fee0f4c6 8743
1ae44dfc 8744 return bgp_show_table(vty, bgp, safi, table, type, output_arg, use_json,
9386b588 8745 NULL, 1, NULL, NULL, &json_header_depth);
fee0f4c6 8746}
8747
d62a17ae 8748static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
9f049418 8749 safi_t safi, bool use_json)
f186de26 8750{
d62a17ae 8751 struct listnode *node, *nnode;
8752 struct bgp *bgp;
8753 int is_first = 1;
9f049418 8754 bool route_output = false;
f186de26 8755
d62a17ae 8756 if (use_json)
8757 vty_out(vty, "{\n");
9f689658 8758
d62a17ae 8759 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 8760 route_output = true;
d62a17ae 8761 if (use_json) {
8762 if (!is_first)
8763 vty_out(vty, ",\n");
8764 else
8765 is_first = 0;
8766
8767 vty_out(vty, "\"%s\":",
8768 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 8769 ? VRF_DEFAULT_NAME
d62a17ae 8770 : bgp->name);
8771 } else {
8772 vty_out(vty, "\nInstance %s:\n",
8773 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 8774 ? VRF_DEFAULT_NAME
d62a17ae 8775 : bgp->name);
8776 }
8777 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
8778 use_json);
8779 }
9f689658 8780
d62a17ae 8781 if (use_json)
8782 vty_out(vty, "}\n");
9f049418
DS
8783 else if (!route_output)
8784 vty_out(vty, "%% BGP instance not found\n");
f186de26 8785}
8786
718e3744 8787/* Header of detailed BGP route information */
d62a17ae 8788void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
8789 struct bgp_node *rn, struct prefix_rd *prd,
8790 afi_t afi, safi_t safi, json_object *json)
8791{
40381db7 8792 struct bgp_path_info *pi;
d62a17ae 8793 struct prefix *p;
8794 struct peer *peer;
8795 struct listnode *node, *nnode;
06b9f471 8796 char buf1[RD_ADDRSTRLEN];
d62a17ae 8797 char buf2[INET6_ADDRSTRLEN];
d62a17ae 8798 char buf3[EVPN_ROUTE_STRLEN];
0291c246 8799 char prefix_str[BUFSIZ];
d62a17ae 8800 int count = 0;
8801 int best = 0;
8802 int suppress = 0;
c5f1e1b2
C
8803 int accept_own = 0;
8804 int route_filter_translated_v4 = 0;
8805 int route_filter_v4 = 0;
8806 int route_filter_translated_v6 = 0;
8807 int route_filter_v6 = 0;
8808 int llgr_stale = 0;
8809 int no_llgr = 0;
8810 int accept_own_nexthop = 0;
8811 int blackhole = 0;
d62a17ae 8812 int no_export = 0;
8813 int no_advertise = 0;
8814 int local_as = 0;
c5f1e1b2 8815 int no_peer = 0;
d62a17ae 8816 int first = 1;
8817 int has_valid_label = 0;
8818 mpls_label_t label = 0;
8819 json_object *json_adv_to = NULL;
9bedbb1e 8820
d62a17ae 8821 p = &rn->p;
8822 has_valid_label = bgp_is_valid_label(&rn->local_label);
8823
8824 if (has_valid_label)
8825 label = label_pton(&rn->local_label);
8826
8827 if (json) {
8828 if (has_valid_label)
8829 json_object_int_add(json, "localLabel", label);
8830
60466a63
QY
8831 json_object_string_add(
8832 json, "prefix",
8833 prefix2str(p, prefix_str, sizeof(prefix_str)));
d62a17ae 8834 } else {
d62a17ae 8835 if (safi == SAFI_EVPN)
8836 vty_out(vty, "BGP routing table entry for %s%s%s\n",
06b9f471 8837 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
d62a17ae 8838 : "",
8839 prd ? ":" : "",
8840 bgp_evpn_route2str((struct prefix_evpn *)p,
8841 buf3, sizeof(buf3)));
8842 else
8843 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
8844 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8845 ? prefix_rd2str(prd, buf1,
06b9f471 8846 sizeof(buf1))
d62a17ae 8847 : ""),
8848 safi == SAFI_MPLS_VPN ? ":" : "",
8849 inet_ntop(p->family, &p->u.prefix, buf2,
8850 INET6_ADDRSTRLEN),
8851 p->prefixlen);
cd1964ff 8852
d62a17ae 8853 if (has_valid_label)
8854 vty_out(vty, "Local label: %d\n", label);
d62a17ae 8855 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 8856 vty_out(vty, "not allocated\n");
8857 }
718e3744 8858
40381db7 8859 for (pi = rn->info; pi; pi = pi->next) {
d62a17ae 8860 count++;
40381db7 8861 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 8862 best = count;
40381db7 8863 if (pi->extra && pi->extra->suppress)
d62a17ae 8864 suppress = 1;
cee9c031 8865
40381db7 8866 if (pi->attr->community == NULL)
cee9c031
QY
8867 continue;
8868
8869 no_advertise += community_include(
40381db7
DS
8870 pi->attr->community, COMMUNITY_NO_ADVERTISE);
8871 no_export += community_include(pi->attr->community,
cee9c031 8872 COMMUNITY_NO_EXPORT);
40381db7 8873 local_as += community_include(pi->attr->community,
cee9c031 8874 COMMUNITY_LOCAL_AS);
40381db7 8875 accept_own += community_include(pi->attr->community,
cee9c031
QY
8876 COMMUNITY_ACCEPT_OWN);
8877 route_filter_translated_v4 += community_include(
40381db7 8878 pi->attr->community,
cee9c031
QY
8879 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
8880 route_filter_translated_v6 += community_include(
40381db7 8881 pi->attr->community,
cee9c031
QY
8882 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
8883 route_filter_v4 += community_include(
40381db7 8884 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 8885 route_filter_v6 += community_include(
40381db7
DS
8886 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
8887 llgr_stale += community_include(pi->attr->community,
cee9c031 8888 COMMUNITY_LLGR_STALE);
40381db7 8889 no_llgr += community_include(pi->attr->community,
cee9c031
QY
8890 COMMUNITY_NO_LLGR);
8891 accept_own_nexthop +=
40381db7 8892 community_include(pi->attr->community,
cee9c031 8893 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 8894 blackhole += community_include(pi->attr->community,
cee9c031 8895 COMMUNITY_BLACKHOLE);
40381db7 8896 no_peer += community_include(pi->attr->community,
cee9c031 8897 COMMUNITY_NO_PEER);
d62a17ae 8898 }
718e3744 8899 }
718e3744 8900
d62a17ae 8901 if (!json) {
8902 vty_out(vty, "Paths: (%d available", count);
8903 if (best) {
8904 vty_out(vty, ", best #%d", best);
8905 if (safi == SAFI_UNICAST)
8906 vty_out(vty, ", table %s",
8907 (bgp->inst_type
8908 == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 8909 ? VRF_DEFAULT_NAME
d62a17ae 8910 : bgp->name);
8911 } else
8912 vty_out(vty, ", no best path");
8913
c5f1e1b2
C
8914 if (accept_own)
8915 vty_out(vty,
8916 ", accept own local route exported and imported in different VRF");
8917 else if (route_filter_translated_v4)
8918 vty_out(vty,
8919 ", mark translated RTs for VPNv4 route filtering");
8920 else if (route_filter_v4)
8921 vty_out(vty,
8922 ", attach RT as-is for VPNv4 route filtering");
8923 else if (route_filter_translated_v6)
8924 vty_out(vty,
8925 ", mark translated RTs for VPNv6 route filtering");
8926 else if (route_filter_v6)
8927 vty_out(vty,
8928 ", attach RT as-is for VPNv6 route filtering");
8929 else if (llgr_stale)
8930 vty_out(vty,
8931 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
8932 else if (no_llgr)
8933 vty_out(vty,
8934 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
8935 else if (accept_own_nexthop)
8936 vty_out(vty,
8937 ", accept local nexthop");
8938 else if (blackhole)
8939 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 8940 else if (no_export)
8941 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
8942 else if (no_advertise)
8943 vty_out(vty, ", not advertised to any peer");
d62a17ae 8944 else if (local_as)
8945 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
8946 else if (no_peer)
8947 vty_out(vty,
8948 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 8949
8950 if (suppress)
8951 vty_out(vty,
8952 ", Advertisements suppressed by an aggregate.");
8953 vty_out(vty, ")\n");
8954 }
718e3744 8955
d62a17ae 8956 /* If we are not using addpath then we can display Advertised to and
8957 * that will
8958 * show what peers we advertised the bestpath to. If we are using
8959 * addpath
8960 * though then we must display Advertised to on a path-by-path basis. */
8961 if (!bgp->addpath_tx_used[afi][safi]) {
8962 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
8963 if (bgp_adj_out_lookup(peer, rn, 0)) {
8964 if (json && !json_adv_to)
8965 json_adv_to = json_object_new_object();
8966
8967 route_vty_out_advertised_to(
8968 vty, peer, &first,
8969 " Advertised to non peer-group peers:\n ",
8970 json_adv_to);
8971 }
8972 }
8973
8974 if (json) {
8975 if (json_adv_to) {
8976 json_object_object_add(json, "advertisedTo",
8977 json_adv_to);
8978 }
8979 } else {
8980 if (first)
8981 vty_out(vty, " Not advertised to any peer");
8982 vty_out(vty, "\n");
8983 }
8984 }
718e3744 8985}
8986
8987/* Display specified route of BGP table. */
d62a17ae 8988static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
8989 struct bgp_table *rib, const char *ip_str,
8990 afi_t afi, safi_t safi,
8991 struct prefix_rd *prd, int prefix_check,
9f049418 8992 enum bgp_path_type pathtype, bool use_json)
d62a17ae 8993{
8994 int ret;
8995 int header;
8996 int display = 0;
8997 struct prefix match;
8998 struct bgp_node *rn;
8999 struct bgp_node *rm;
40381db7 9000 struct bgp_path_info *pi;
d62a17ae 9001 struct bgp_table *table;
9002 json_object *json = NULL;
9003 json_object *json_paths = NULL;
9004
9005 /* Check IP address argument. */
9006 ret = str2prefix(ip_str, &match);
9007 if (!ret) {
9008 vty_out(vty, "address is malformed\n");
9009 return CMD_WARNING;
9010 }
718e3744 9011
d62a17ae 9012 match.family = afi2family(afi);
b05a1c8b 9013
d62a17ae 9014 if (use_json) {
9015 json = json_object_new_object();
9016 json_paths = json_object_new_array();
9017 }
718e3744 9018
d62a17ae 9019 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9020 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
9021 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
9022 continue;
9023
ea47320b
DL
9024 if ((table = rn->info) == NULL)
9025 continue;
d62a17ae 9026
ea47320b
DL
9027 header = 1;
9028
9029 if ((rm = bgp_node_match(table, &match)) == NULL)
9030 continue;
d62a17ae 9031
ea47320b
DL
9032 if (prefix_check
9033 && rm->p.prefixlen != match.prefixlen) {
9034 bgp_unlock_node(rm);
9035 continue;
9036 }
d62a17ae 9037
40381db7 9038 for (pi = rm->info; pi; pi = pi->next) {
ea47320b 9039 if (header) {
60466a63
QY
9040 route_vty_out_detail_header(
9041 vty, bgp, rm,
9042 (struct prefix_rd *)&rn->p,
ea47320b
DL
9043 AFI_IP, safi, json);
9044 header = 0;
d62a17ae 9045 }
ea47320b
DL
9046 display++;
9047
360660c6
DS
9048 if (pathtype == BGP_PATH_SHOW_ALL
9049 || (pathtype == BGP_PATH_SHOW_BESTPATH
40381db7 9050 && CHECK_FLAG(pi->flags,
1defdda8 9051 BGP_PATH_SELECTED))
360660c6 9052 || (pathtype == BGP_PATH_SHOW_MULTIPATH
40381db7 9053 && (CHECK_FLAG(pi->flags,
1defdda8 9054 BGP_PATH_MULTIPATH)
40381db7 9055 || CHECK_FLAG(pi->flags,
1defdda8 9056 BGP_PATH_SELECTED))))
ea47320b 9057 route_vty_out_detail(vty, bgp, &rm->p,
40381db7 9058 pi, AFI_IP, safi,
ea47320b 9059 json_paths);
d62a17ae 9060 }
ea47320b
DL
9061
9062 bgp_unlock_node(rm);
d62a17ae 9063 }
98a9dbc7 9064 } else if (safi == SAFI_FLOWSPEC) {
63a0b7a9
PG
9065 display = bgp_flowspec_display_match_per_ip(afi, rib,
9066 &match, prefix_check,
9067 vty,
9068 use_json,
9069 json_paths);
d62a17ae 9070 } else {
9071 header = 1;
9072
9073 if ((rn = bgp_node_match(rib, &match)) != NULL) {
9074 if (!prefix_check
9075 || rn->p.prefixlen == match.prefixlen) {
40381db7 9076 for (pi = rn->info; pi; pi = pi->next) {
d62a17ae 9077 if (header) {
9078 route_vty_out_detail_header(
9079 vty, bgp, rn, NULL, afi,
9080 safi, json);
9081 header = 0;
9082 }
9083 display++;
9084
360660c6
DS
9085 if (pathtype == BGP_PATH_SHOW_ALL
9086 || (pathtype
9087 == BGP_PATH_SHOW_BESTPATH
d62a17ae 9088 && CHECK_FLAG(
40381db7 9089 pi->flags,
1defdda8 9090 BGP_PATH_SELECTED))
360660c6
DS
9091 || (pathtype
9092 == BGP_PATH_SHOW_MULTIPATH
d62a17ae 9093 && (CHECK_FLAG(
40381db7 9094 pi->flags,
1defdda8 9095 BGP_PATH_MULTIPATH)
d62a17ae 9096 || CHECK_FLAG(
40381db7 9097 pi->flags,
1defdda8 9098 BGP_PATH_SELECTED))))
d62a17ae 9099 route_vty_out_detail(
40381db7 9100 vty, bgp, &rn->p, pi,
d62a17ae 9101 afi, safi, json_paths);
9102 }
9103 }
9104
9105 bgp_unlock_node(rn);
9106 }
9107 }
e5eee9af 9108
d62a17ae 9109 if (use_json) {
9110 if (display)
9111 json_object_object_add(json, "paths", json_paths);
9112
996c9314
LB
9113 vty_out(vty, "%s\n", json_object_to_json_string_ext(
9114 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 9115 json_object_free(json);
9116 } else {
9117 if (!display) {
9118 vty_out(vty, "%% Network not in table\n");
9119 return CMD_WARNING;
9120 }
9121 }
b05a1c8b 9122
d62a17ae 9123 return CMD_SUCCESS;
718e3744 9124}
9125
fee0f4c6 9126/* Display specified route of Main RIB */
d62a17ae 9127static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
9128 afi_t afi, safi_t safi, struct prefix_rd *prd,
9129 int prefix_check, enum bgp_path_type pathtype,
9f049418 9130 bool use_json)
d62a17ae 9131{
9b86009a 9132 if (!bgp) {
d62a17ae 9133 bgp = bgp_get_default();
9b86009a
RW
9134 if (!bgp) {
9135 if (!use_json)
9136 vty_out(vty, "No BGP process is configured\n");
16307668
RW
9137 else
9138 vty_out(vty, "{}\n");
9b86009a
RW
9139 return CMD_WARNING;
9140 }
9141 }
d62a17ae 9142
9143 /* labeled-unicast routes live in the unicast table */
9144 if (safi == SAFI_LABELED_UNICAST)
9145 safi = SAFI_UNICAST;
9146
9147 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
9148 afi, safi, prd, prefix_check, pathtype,
9149 use_json);
9150}
9151
9152static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
9153 struct cmd_token **argv, afi_t afi, safi_t safi,
088f1098 9154 bool uj)
d62a17ae 9155{
9156 struct lcommunity *lcom;
9157 struct buffer *b;
9158 int i;
9159 char *str;
9160 int first = 0;
9161
9162 b = buffer_new(1024);
9163 for (i = 0; i < argc; i++) {
9164 if (first)
9165 buffer_putc(b, ' ');
9166 else {
9167 if (strmatch(argv[i]->text, "AA:BB:CC")) {
9168 first = 1;
9169 buffer_putstr(b, argv[i]->arg);
9170 }
9171 }
9172 }
9173 buffer_putc(b, '\0');
57d187bc 9174
d62a17ae 9175 str = buffer_getstr(b);
9176 buffer_free(b);
57d187bc 9177
d62a17ae 9178 lcom = lcommunity_str2com(str);
9179 XFREE(MTYPE_TMP, str);
9180 if (!lcom) {
9181 vty_out(vty, "%% Large-community malformed\n");
9182 return CMD_WARNING;
9183 }
57d187bc 9184
d62a17ae 9185 return bgp_show(vty, bgp, afi, safi, bgp_show_type_lcommunity, lcom,
9186 uj);
57d187bc
JS
9187}
9188
d62a17ae 9189static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
9190 const char *lcom, afi_t afi, safi_t safi,
088f1098 9191 bool uj)
57d187bc 9192{
d62a17ae 9193 struct community_list *list;
57d187bc 9194
d62a17ae 9195 list = community_list_lookup(bgp_clist, lcom,
9196 LARGE_COMMUNITY_LIST_MASTER);
9197 if (list == NULL) {
9198 vty_out(vty, "%% %s is not a valid large-community-list name\n",
9199 lcom);
9200 return CMD_WARNING;
9201 }
57d187bc 9202
d62a17ae 9203 return bgp_show(vty, bgp, afi, safi, bgp_show_type_lcommunity_list,
9204 list, uj);
fee0f4c6 9205}
9206
52951b63
DS
9207DEFUN (show_ip_bgp_large_community_list,
9208 show_ip_bgp_large_community_list_cmd,
4dd6177e 9209 "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
9210 SHOW_STR
9211 IP_STR
9212 BGP_STR
9213 BGP_INSTANCE_HELP_STR
9bedbb1e 9214 BGP_AFI_HELP_STR
4dd6177e 9215 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
9216 "Display routes matching the large-community-list\n"
9217 "large-community-list number\n"
9218 "large-community-list name\n"
9219 JSON_STR)
9220{
d62a17ae 9221 char *vrf = NULL;
9222 afi_t afi = AFI_IP6;
9223 safi_t safi = SAFI_UNICAST;
9224 int idx = 0;
9225
9226 if (argv_find(argv, argc, "ip", &idx))
9227 afi = AFI_IP;
9228 if (argv_find(argv, argc, "view", &idx)
9229 || argv_find(argv, argc, "vrf", &idx))
9230 vrf = argv[++idx]->arg;
9231 if (argv_find(argv, argc, "ipv4", &idx)
9232 || argv_find(argv, argc, "ipv6", &idx)) {
9233 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
9234 if (argv_find(argv, argc, "unicast", &idx)
9235 || argv_find(argv, argc, "multicast", &idx))
9236 safi = bgp_vty_safi_from_str(argv[idx]->text);
9237 }
9238
9f049418 9239 bool uj = use_json(argc, argv);
d62a17ae 9240
9241 struct bgp *bgp = bgp_lookup_by_name(vrf);
9242 if (bgp == NULL) {
9243 vty_out(vty, "Can't find BGP instance %s\n", vrf);
9244 return CMD_WARNING;
9245 }
9246
9247 argv_find(argv, argc, "large-community-list", &idx);
9248 return bgp_show_lcommunity_list(vty, bgp, argv[idx + 1]->arg, afi, safi,
9249 uj);
52951b63
DS
9250}
9251DEFUN (show_ip_bgp_large_community,
9252 show_ip_bgp_large_community_cmd,
4dd6177e 9253 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community [AA:BB:CC] [json]",
52951b63
DS
9254 SHOW_STR
9255 IP_STR
9256 BGP_STR
9257 BGP_INSTANCE_HELP_STR
9bedbb1e 9258 BGP_AFI_HELP_STR
4dd6177e 9259 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
9260 "Display routes matching the large-communities\n"
9261 "List of large-community numbers\n"
9262 JSON_STR)
9263{
d62a17ae 9264 char *vrf = NULL;
9265 afi_t afi = AFI_IP6;
9266 safi_t safi = SAFI_UNICAST;
9267 int idx = 0;
9268
9269 if (argv_find(argv, argc, "ip", &idx))
9270 afi = AFI_IP;
9271 if (argv_find(argv, argc, "view", &idx)
9272 || argv_find(argv, argc, "vrf", &idx))
9273 vrf = argv[++idx]->arg;
9274 if (argv_find(argv, argc, "ipv4", &idx)
9275 || argv_find(argv, argc, "ipv6", &idx)) {
9276 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
9277 if (argv_find(argv, argc, "unicast", &idx)
9278 || argv_find(argv, argc, "multicast", &idx))
9279 safi = bgp_vty_safi_from_str(argv[idx]->text);
9280 }
9281
9f049418 9282 bool uj = use_json(argc, argv);
d62a17ae 9283
9284 struct bgp *bgp = bgp_lookup_by_name(vrf);
9285 if (bgp == NULL) {
9286 vty_out(vty, "Can't find BGP instance %s\n", vrf);
9287 return CMD_WARNING;
9288 }
9289
9290 if (argv_find(argv, argc, "AA:BB:CC", &idx))
9291 return bgp_show_lcommunity(vty, bgp, argc, argv, afi, safi, uj);
9292 else
9293 return bgp_show(vty, bgp, afi, safi,
9294 bgp_show_type_lcommunity_all, NULL, uj);
52951b63
DS
9295}
9296
d62a17ae 9297static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
9298 safi_t safi);
e01ca200 9299
7b2ff250
DW
9300
9301/* BGP route print out function without JSON */
af462945
DS
9302DEFUN (show_ip_bgp,
9303 show_ip_bgp_cmd,
4dd6177e 9304 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
7b2ff250
DW
9305 <dampening <parameters>\
9306 |route-map WORD\
9307 |prefix-list WORD\
9308 |filter-list WORD\
9309 |statistics\
7b2ff250
DW
9310 |community-list <(1-500)|WORD> [exact-match]\
9311 |A.B.C.D/M longer-prefixes\
9312 |X:X::X:X/M longer-prefixes\
9313 >",
718e3744 9314 SHOW_STR
9315 IP_STR
9316 BGP_STR
a636c635 9317 BGP_INSTANCE_HELP_STR
4f280b15 9318 BGP_AFI_HELP_STR
4dd6177e 9319 BGP_SAFI_WITH_LABEL_HELP_STR
a636c635 9320 "Display detailed information about dampening\n"
af462945 9321 "Display detail of configured dampening parameters\n"
a636c635
DW
9322 "Display routes matching the route-map\n"
9323 "A route-map to match on\n"
9324 "Display routes conforming to the prefix-list\n"
8c3deaae 9325 "Prefix-list name\n"
a636c635
DW
9326 "Display routes conforming to the filter-list\n"
9327 "Regular expression access list name\n"
e01ca200 9328 "BGP RIB advertisement statistics\n"
a636c635
DW
9329 "Display routes matching the community-list\n"
9330 "community-list number\n"
9331 "community-list name\n"
9332 "Exact match of the communities\n"
0c7b1b01 9333 "IPv4 prefix\n"
8c3deaae 9334 "Display route and more specific routes\n"
0c7b1b01 9335 "IPv6 prefix\n"
7b2ff250 9336 "Display route and more specific routes\n")
718e3744 9337{
d62a17ae 9338 afi_t afi = AFI_IP6;
9339 safi_t safi = SAFI_UNICAST;
9340 int exact_match = 0;
d62a17ae 9341 struct bgp *bgp = NULL;
9342 int idx = 0;
9343
9344 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 9345 &bgp, false);
d62a17ae 9346 if (!idx)
9347 return CMD_WARNING;
9348
d62a17ae 9349 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 9350 if (argv_find(argv, argc, "parameters", &idx))
d62a17ae 9351 return bgp_show_dampening_parameters(vty, afi, safi);
9352 }
c016b6c7 9353
d62a17ae 9354 if (argv_find(argv, argc, "prefix-list", &idx))
9355 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
9356 safi, bgp_show_type_prefix_list);
9357
9358 if (argv_find(argv, argc, "filter-list", &idx))
9359 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
9360 safi, bgp_show_type_filter_list);
9361
9362 if (argv_find(argv, argc, "statistics", &idx))
9363 return bgp_table_stats(vty, bgp, afi, safi);
9364
9365 if (argv_find(argv, argc, "route-map", &idx))
9366 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
9367 safi, bgp_show_type_route_map);
9368
d62a17ae 9369 if (argv_find(argv, argc, "community-list", &idx)) {
9370 const char *clist_number_or_name = argv[++idx]->arg;
9371 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
9372 exact_match = 1;
9373 return bgp_show_community_list(vty, bgp, clist_number_or_name,
9374 exact_match, afi, safi);
9375 }
9376 /* prefix-longer */
9377 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
9378 || argv_find(argv, argc, "X:X::X:X/M", &idx))
9379 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
9380 safi,
9381 bgp_show_type_prefix_longer);
9382
7b2ff250
DW
9383 return CMD_WARNING;
9384}
9385
9386/* BGP route print out function with JSON */
9387DEFUN (show_ip_bgp_json,
9388 show_ip_bgp_json_cmd,
9389 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
cf4898bc
QY
9390 [cidr-only\
9391 |dampening <flap-statistics|dampened-paths>\
9392 |community [AA:NN|local-AS|no-advertise|no-export\
9393 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
9394 |accept-own|accept-own-nexthop|route-filter-v6\
9395 |route-filter-v4|route-filter-translated-v6\
9396 |route-filter-translated-v4] [exact-match]\
9397 ] [json]",
7b2ff250
DW
9398 SHOW_STR
9399 IP_STR
9400 BGP_STR
9401 BGP_INSTANCE_HELP_STR
9402 BGP_AFI_HELP_STR
9403 BGP_SAFI_WITH_LABEL_HELP_STR
9404 "Display only routes with non-natural netmasks\n"
9405 "Display detailed information about dampening\n"
9406 "Display flap statistics of routes\n"
9407 "Display paths suppressed due to dampening\n"
9408 "Display routes matching the communities\n"
d0086e8e
AD
9409 COMMUNITY_AANN_STR
9410 "Do not send outside local AS (well-known community)\n"
9411 "Do not advertise to any peer (well-known community)\n"
9412 "Do not export to next AS (well-known community)\n"
9413 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
9414 "Do not export to any peer (well-known community)\n"
9415 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
9416 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
9417 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
9418 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
9419 "Should accept VPN route with local nexthop (well-known community)\n"
9420 "RT VPNv6 route filtering (well-known community)\n"
9421 "RT VPNv4 route filtering (well-known community)\n"
9422 "RT translated VPNv6 route filtering (well-known community)\n"
9423 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 9424 "Exact match of the communities\n"
7b2ff250
DW
9425 JSON_STR)
9426{
9427 afi_t afi = AFI_IP6;
9428 safi_t safi = SAFI_UNICAST;
9429 enum bgp_show_type sh_type = bgp_show_type_normal;
9430 struct bgp *bgp = NULL;
9431 int idx = 0;
d0086e8e 9432 int exact_match = 0;
9f049418
DS
9433 bool uj = use_json(argc, argv);
9434
9435 if (uj)
9436 argc--;
7b2ff250
DW
9437
9438 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 9439 &bgp, uj);
7b2ff250
DW
9440 if (!idx)
9441 return CMD_WARNING;
9442
7b2ff250
DW
9443 if (argv_find(argv, argc, "cidr-only", &idx))
9444 return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
9445 NULL, uj);
9446
9447 if (argv_find(argv, argc, "dampening", &idx)) {
9448 if (argv_find(argv, argc, "dampened-paths", &idx))
9449 return bgp_show(vty, bgp, afi, safi,
9450 bgp_show_type_dampend_paths, NULL, uj);
9451 else if (argv_find(argv, argc, "flap-statistics", &idx))
9452 return bgp_show(vty, bgp, afi, safi,
9453 bgp_show_type_flap_statistics, NULL,
9454 uj);
9455 }
9456
9457 if (argv_find(argv, argc, "community", &idx)) {
cf4898bc
QY
9458 char *maybecomm = idx + 1 < argc ? argv[idx + 1]->text : NULL;
9459 char *community = NULL;
d0086e8e 9460
cf4898bc
QY
9461 if (maybecomm && !strmatch(maybecomm, "json")
9462 && !strmatch(maybecomm, "exact-match"))
9463 community = maybecomm;
d0086e8e 9464
cf4898bc
QY
9465 if (argv_find(argv, argc, "exact-match", &idx))
9466 exact_match = 1;
d0086e8e 9467
cf4898bc
QY
9468 if (community)
9469 return bgp_show_community(vty, bgp, community,
9470 exact_match, afi, safi, uj);
9471 else
d0086e8e 9472 return (bgp_show(vty, bgp, afi, safi,
cf4898bc
QY
9473 bgp_show_type_community_all, NULL,
9474 uj));
7b2ff250 9475 }
d0086e8e 9476
1ae44dfc 9477 return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj);
a636c635 9478}
47fc97cc 9479
718e3744 9480DEFUN (show_ip_bgp_route,
9481 show_ip_bgp_route_cmd,
4dd6177e 9482 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]"
ae19d7dd 9483 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
718e3744 9484 SHOW_STR
9485 IP_STR
9486 BGP_STR
a636c635 9487 BGP_INSTANCE_HELP_STR
4f280b15 9488 BGP_AFI_HELP_STR
4dd6177e 9489 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 9490 "Network in the BGP routing table to display\n"
0c7b1b01 9491 "IPv4 prefix\n"
8c3deaae 9492 "Network in the BGP routing table to display\n"
0c7b1b01 9493 "IPv6 prefix\n"
4092b06c 9494 "Display only the bestpath\n"
b05a1c8b 9495 "Display only multipaths\n"
9973d184 9496 JSON_STR)
4092b06c 9497{
d62a17ae 9498 int prefix_check = 0;
ae19d7dd 9499
d62a17ae 9500 afi_t afi = AFI_IP6;
9501 safi_t safi = SAFI_UNICAST;
9502 char *prefix = NULL;
9503 struct bgp *bgp = NULL;
9504 enum bgp_path_type path_type;
9f049418 9505 bool uj = use_json(argc, argv);
b05a1c8b 9506
d62a17ae 9507 int idx = 0;
ae19d7dd 9508
d62a17ae 9509 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 9510 &bgp, uj);
d62a17ae 9511 if (!idx)
9512 return CMD_WARNING;
c41247f5 9513
d62a17ae 9514 if (!bgp) {
9515 vty_out(vty,
9516 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9517 return CMD_WARNING;
9518 }
a636c635 9519
d62a17ae 9520 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9521 if (argv_find(argv, argc, "A.B.C.D", &idx)
9522 || argv_find(argv, argc, "X:X::X:X", &idx))
9523 prefix_check = 0;
9524 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
9525 || argv_find(argv, argc, "X:X::X:X/M", &idx))
9526 prefix_check = 1;
9527
9528 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
9529 && afi != AFI_IP6) {
9530 vty_out(vty,
9531 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9532 return CMD_WARNING;
9533 }
9534 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
9535 && afi != AFI_IP) {
9536 vty_out(vty,
9537 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9538 return CMD_WARNING;
9539 }
9540
9541 prefix = argv[idx]->arg;
9542
9543 /* [<bestpath|multipath>] */
9544 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 9545 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 9546 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 9547 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 9548 else
360660c6 9549 path_type = BGP_PATH_SHOW_ALL;
a636c635 9550
d62a17ae 9551 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
9552 path_type, uj);
4092b06c
DS
9553}
9554
8c3deaae
QY
9555DEFUN (show_ip_bgp_regexp,
9556 show_ip_bgp_regexp_cmd,
4dd6177e 9557 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX...",
8c3deaae
QY
9558 SHOW_STR
9559 IP_STR
9560 BGP_STR
b00b230a 9561 BGP_INSTANCE_HELP_STR
4f280b15 9562 BGP_AFI_HELP_STR
4dd6177e 9563 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae
QY
9564 "Display routes matching the AS path regular expression\n"
9565 "A regular-expression to match the BGP AS paths\n")
9566{
d62a17ae 9567 afi_t afi = AFI_IP6;
9568 safi_t safi = SAFI_UNICAST;
9569 struct bgp *bgp = NULL;
8c3deaae 9570
d62a17ae 9571 int idx = 0;
9572 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 9573 &bgp, false);
d62a17ae 9574 if (!idx)
9575 return CMD_WARNING;
8c3deaae 9576
d62a17ae 9577 // get index of regex
9578 argv_find(argv, argc, "regexp", &idx);
9579 idx++;
8c3deaae 9580
d62a17ae 9581 char *regstr = argv_concat(argv, argc, idx);
e889891d 9582 int rc = bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
d62a17ae 9583 bgp_show_type_regexp);
9584 XFREE(MTYPE_TMP, regstr);
9585 return rc;
8c3deaae
QY
9586}
9587
a636c635
DW
9588DEFUN (show_ip_bgp_instance_all,
9589 show_ip_bgp_instance_all_cmd,
4dd6177e 9590 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json]",
4092b06c 9591 SHOW_STR
a636c635 9592 IP_STR
4092b06c 9593 BGP_STR
a636c635 9594 BGP_INSTANCE_ALL_HELP_STR
4f280b15 9595 BGP_AFI_HELP_STR
4dd6177e 9596 BGP_SAFI_WITH_LABEL_HELP_STR
9973d184 9597 JSON_STR)
4092b06c 9598{
d62a17ae 9599 afi_t afi = AFI_IP;
9600 safi_t safi = SAFI_UNICAST;
9601 struct bgp *bgp = NULL;
d62a17ae 9602 int idx = 0;
9f049418 9603 bool uj = use_json(argc, argv);
ae19d7dd 9604
d62a17ae 9605 if (uj)
9606 argc--;
e3e29b32 9607
9f049418
DS
9608 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9609 &bgp, uj);
9610 if (!idx)
9611 return CMD_WARNING;
9612
d62a17ae 9613 bgp_show_all_instances_routes_vty(vty, afi, safi, uj);
9614 return CMD_SUCCESS;
e3e29b32
LB
9615}
9616
a4d82a8a
PZ
9617static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
9618 afi_t afi, safi_t safi, enum bgp_show_type type)
718e3744 9619{
d62a17ae 9620 regex_t *regex;
9621 int rc;
e3e29b32 9622
d62a17ae 9623 regex = bgp_regcomp(regstr);
9624 if (!regex) {
9625 vty_out(vty, "Can't compile regexp %s\n", regstr);
9626 return CMD_WARNING;
9627 }
a636c635 9628
e889891d 9629 rc = bgp_show(vty, bgp, afi, safi, type, regex, 0);
d62a17ae 9630 bgp_regex_free(regex);
9631 return rc;
e3e29b32
LB
9632}
9633
d62a17ae 9634static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
9635 const char *prefix_list_str, afi_t afi,
9636 safi_t safi, enum bgp_show_type type)
e3e29b32 9637{
d62a17ae 9638 struct prefix_list *plist;
718e3744 9639
d62a17ae 9640 plist = prefix_list_lookup(afi, prefix_list_str);
9641 if (plist == NULL) {
9642 vty_out(vty, "%% %s is not a valid prefix-list name\n",
9643 prefix_list_str);
9644 return CMD_WARNING;
9645 }
718e3744 9646
d62a17ae 9647 return bgp_show(vty, bgp, afi, safi, type, plist, 0);
4092b06c
DS
9648}
9649
d62a17ae 9650static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
9651 const char *filter, afi_t afi, safi_t safi,
9652 enum bgp_show_type type)
4092b06c 9653{
d62a17ae 9654 struct as_list *as_list;
718e3744 9655
d62a17ae 9656 as_list = as_list_lookup(filter);
9657 if (as_list == NULL) {
9658 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
9659 filter);
9660 return CMD_WARNING;
9661 }
a636c635 9662
d62a17ae 9663 return bgp_show(vty, bgp, afi, safi, type, as_list, 0);
718e3744 9664}
9665
d62a17ae 9666static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
9667 const char *rmap_str, afi_t afi, safi_t safi,
9668 enum bgp_show_type type)
718e3744 9669{
d62a17ae 9670 struct route_map *rmap;
bb46e94f 9671
d62a17ae 9672 rmap = route_map_lookup_by_name(rmap_str);
9673 if (!rmap) {
9674 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
9675 return CMD_WARNING;
9676 }
9677
9678 return bgp_show(vty, bgp, afi, safi, type, rmap, 0);
9679}
9680
7f323236
DW
9681static int bgp_show_community(struct vty *vty, struct bgp *bgp,
9682 const char *comstr, int exact, afi_t afi,
9f049418 9683 safi_t safi, bool use_json)
d62a17ae 9684{
9685 struct community *com;
d62a17ae 9686 int ret = 0;
9687
7f323236 9688 com = community_str2com(comstr);
d62a17ae 9689 if (!com) {
7f323236 9690 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 9691 return CMD_WARNING;
9692 }
9693
9694 ret = bgp_show(vty, bgp, afi, safi,
9695 (exact ? bgp_show_type_community_exact
9696 : bgp_show_type_community),
d0086e8e 9697 com, use_json);
3c1f53de 9698 community_free(&com);
46c3ce83 9699
d62a17ae 9700 return ret;
718e3744 9701}
9702
d62a17ae 9703static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
9704 const char *com, int exact, afi_t afi,
9705 safi_t safi)
50ef26d4 9706{
d62a17ae 9707 struct community_list *list;
50ef26d4 9708
d62a17ae 9709 list = community_list_lookup(bgp_clist, com, COMMUNITY_LIST_MASTER);
9710 if (list == NULL) {
9711 vty_out(vty, "%% %s is not a valid community-list name\n", com);
9712 return CMD_WARNING;
9713 }
718e3744 9714
d62a17ae 9715 return bgp_show(vty, bgp, afi, safi,
9716 (exact ? bgp_show_type_community_list_exact
9717 : bgp_show_type_community_list),
9718 list, 0);
50ef26d4 9719}
9720
d62a17ae 9721static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
9722 const char *prefix, afi_t afi, safi_t safi,
9723 enum bgp_show_type type)
718e3744 9724{
d62a17ae 9725 int ret;
9726 struct prefix *p;
47fc97cc 9727
d62a17ae 9728 p = prefix_new();
95cbbd2a 9729
d62a17ae 9730 ret = str2prefix(prefix, p);
9731 if (!ret) {
9732 vty_out(vty, "%% Malformed Prefix\n");
9733 return CMD_WARNING;
9734 }
47e9b292 9735
d62a17ae 9736 ret = bgp_show(vty, bgp, afi, safi, type, p, 0);
9737 prefix_free(p);
9738 return ret;
9739}
9740
9741static struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp,
9f049418 9742 const char *ip_str, bool use_json)
d62a17ae 9743{
9744 int ret;
9745 struct peer *peer;
9746 union sockunion su;
9747
9748 /* Get peer sockunion. */
9749 ret = str2sockunion(ip_str, &su);
9750 if (ret < 0) {
9751 peer = peer_lookup_by_conf_if(bgp, ip_str);
9752 if (!peer) {
9753 peer = peer_lookup_by_hostname(bgp, ip_str);
9754
9755 if (!peer) {
9756 if (use_json) {
9757 json_object *json_no = NULL;
9758 json_no = json_object_new_object();
9759 json_object_string_add(
9760 json_no,
9761 "malformedAddressOrName",
9762 ip_str);
9763 vty_out(vty, "%s\n",
66f80d74 9764 json_object_to_json_string_ext(
a4d82a8a
PZ
9765 json_no,
9766 JSON_C_TO_STRING_PRETTY));
d62a17ae 9767 json_object_free(json_no);
9768 } else
9769 vty_out(vty,
9770 "%% Malformed address or name: %s\n",
9771 ip_str);
9772 return NULL;
9773 }
9774 }
9775 return peer;
9776 }
718e3744 9777
d62a17ae 9778 /* Peer structure lookup. */
9779 peer = peer_lookup(bgp, &su);
9780 if (!peer) {
9781 if (use_json) {
9782 json_object *json_no = NULL;
9783 json_no = json_object_new_object();
9784 json_object_string_add(json_no, "warning",
9e6e6f46 9785 "No such neighbor in this view/vrf");
d62a17ae 9786 vty_out(vty, "%s\n",
a4d82a8a
PZ
9787 json_object_to_json_string_ext(
9788 json_no, JSON_C_TO_STRING_PRETTY));
d62a17ae 9789 json_object_free(json_no);
9790 } else
9e6e6f46 9791 vty_out(vty, "No such neighbor in this view/vrf\n");
d62a17ae 9792 return NULL;
9793 }
2815e61f 9794
d62a17ae 9795 return peer;
9796}
9797
9798enum bgp_stats {
9799 BGP_STATS_MAXBITLEN = 0,
9800 BGP_STATS_RIB,
9801 BGP_STATS_PREFIXES,
9802 BGP_STATS_TOTPLEN,
9803 BGP_STATS_UNAGGREGATEABLE,
9804 BGP_STATS_MAX_AGGREGATEABLE,
9805 BGP_STATS_AGGREGATES,
9806 BGP_STATS_SPACE,
9807 BGP_STATS_ASPATH_COUNT,
9808 BGP_STATS_ASPATH_MAXHOPS,
9809 BGP_STATS_ASPATH_TOTHOPS,
9810 BGP_STATS_ASPATH_MAXSIZE,
9811 BGP_STATS_ASPATH_TOTSIZE,
9812 BGP_STATS_ASN_HIGHEST,
9813 BGP_STATS_MAX,
a636c635 9814};
2815e61f 9815
d62a17ae 9816static const char *table_stats_strs[] = {
9d303b37
DL
9817 [BGP_STATS_PREFIXES] = "Total Prefixes",
9818 [BGP_STATS_TOTPLEN] = "Average prefix length",
9819 [BGP_STATS_RIB] = "Total Advertisements",
9820 [BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes",
9821 [BGP_STATS_MAX_AGGREGATEABLE] =
9822 "Maximum aggregateable prefixes",
9823 [BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements",
9824 [BGP_STATS_SPACE] = "Address space advertised",
9825 [BGP_STATS_ASPATH_COUNT] = "Advertisements with paths",
9826 [BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)",
9827 [BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)",
9828 [BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)",
9829 [BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)",
9830 [BGP_STATS_ASN_HIGHEST] = "Highest public ASN",
9831 [BGP_STATS_MAX] = NULL,
a636c635 9832};
2815e61f 9833
d62a17ae 9834struct bgp_table_stats {
9835 struct bgp_table *table;
9836 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 9837 double total_space;
ff7924f6
PJ
9838};
9839
a636c635
DW
9840#if 0
9841#define TALLY_SIGFIG 100000
9842static unsigned long
9843ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 9844{
a636c635
DW
9845 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
9846 unsigned long res = (newtot * TALLY_SIGFIG) / count;
9847 unsigned long ret = newtot / count;
07d0c4ed 9848
a636c635
DW
9849 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
9850 return ret + 1;
9851 else
9852 return ret;
9853}
9854#endif
ff7924f6 9855
d62a17ae 9856static int bgp_table_stats_walker(struct thread *t)
2815e61f 9857{
d62a17ae 9858 struct bgp_node *rn;
9859 struct bgp_node *top;
9860 struct bgp_table_stats *ts = THREAD_ARG(t);
9861 unsigned int space = 0;
a636c635 9862
d62a17ae 9863 if (!(top = bgp_table_top(ts->table)))
9864 return 0;
2815e61f 9865
d62a17ae 9866 switch (top->p.family) {
9867 case AF_INET:
9868 space = IPV4_MAX_BITLEN;
9869 break;
9870 case AF_INET6:
9871 space = IPV6_MAX_BITLEN;
9872 break;
9873 }
9874
9875 ts->counts[BGP_STATS_MAXBITLEN] = space;
9876
9877 for (rn = top; rn; rn = bgp_route_next(rn)) {
40381db7 9878 struct bgp_path_info *pi;
d62a17ae 9879 struct bgp_node *prn = bgp_node_parent_nolock(rn);
40381db7 9880 unsigned int pinum = 0;
d62a17ae 9881
9882 if (rn == top)
9883 continue;
9884
9885 if (!rn->info)
9886 continue;
9887
9888 ts->counts[BGP_STATS_PREFIXES]++;
9889 ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
ff7924f6 9890
a636c635
DW
9891#if 0
9892 ts->counts[BGP_STATS_AVGPLEN]
9893 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
9894 ts->counts[BGP_STATS_AVGPLEN],
9895 rn->p.prefixlen);
9896#endif
d62a17ae 9897
9898 /* check if the prefix is included by any other announcements */
9899 while (prn && !prn->info)
9900 prn = bgp_node_parent_nolock(prn);
9901
9902 if (prn == NULL || prn == top) {
9903 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
9904 /* announced address space */
9905 if (space)
a4d82a8a
PZ
9906 ts->total_space +=
9907 pow(2.0, space - rn->p.prefixlen);
d62a17ae 9908 } else if (prn->info)
9909 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
9910
40381db7
DS
9911 for (pi = rn->info; pi; pi = pi->next) {
9912 pinum++;
d62a17ae 9913 ts->counts[BGP_STATS_RIB]++;
9914
40381db7
DS
9915 if (pi->attr
9916 && (CHECK_FLAG(pi->attr->flag,
d62a17ae 9917 ATTR_FLAG_BIT(
9918 BGP_ATTR_ATOMIC_AGGREGATE))))
9919 ts->counts[BGP_STATS_AGGREGATES]++;
9920
9921 /* as-path stats */
40381db7 9922 if (pi->attr && pi->attr->aspath) {
d62a17ae 9923 unsigned int hops =
40381db7 9924 aspath_count_hops(pi->attr->aspath);
d62a17ae 9925 unsigned int size =
40381db7
DS
9926 aspath_size(pi->attr->aspath);
9927 as_t highest = aspath_highest(pi->attr->aspath);
d62a17ae 9928
9929 ts->counts[BGP_STATS_ASPATH_COUNT]++;
9930
9931 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
9932 ts->counts[BGP_STATS_ASPATH_MAXHOPS] =
9933 hops;
9934
9935 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
9936 ts->counts[BGP_STATS_ASPATH_MAXSIZE] =
9937 size;
9938
9939 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
9940 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 9941#if 0
07d0c4ed 9942 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
9943 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
9944 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
9945 hops);
9946 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
9947 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
9948 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
9949 size);
9950#endif
d62a17ae 9951 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
9952 ts->counts[BGP_STATS_ASN_HIGHEST] =
9953 highest;
9954 }
9955 }
9956 }
9957 return 0;
2815e61f 9958}
ff7924f6 9959
d62a17ae 9960static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
9961 safi_t safi)
2815e61f 9962{
d62a17ae 9963 struct bgp_table_stats ts;
9964 unsigned int i;
019386c2 9965
d62a17ae 9966 if (!bgp->rib[afi][safi]) {
9967 vty_out(vty, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9968 afi, safi);
9969 return CMD_WARNING;
9970 }
019386c2 9971
d62a17ae 9972 vty_out(vty, "BGP %s RIB statistics\n", afi_safi_print(afi, safi));
019386c2 9973
d62a17ae 9974 /* labeled-unicast routes live in the unicast table */
9975 if (safi == SAFI_LABELED_UNICAST)
9976 safi = SAFI_UNICAST;
019386c2 9977
d62a17ae 9978 memset(&ts, 0, sizeof(ts));
9979 ts.table = bgp->rib[afi][safi];
9980 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 9981
d62a17ae 9982 for (i = 0; i < BGP_STATS_MAX; i++) {
9983 if (!table_stats_strs[i])
9984 continue;
9985
9986 switch (i) {
a636c635
DW
9987#if 0
9988 case BGP_STATS_ASPATH_AVGHOPS:
9989 case BGP_STATS_ASPATH_AVGSIZE:
9990 case BGP_STATS_AVGPLEN:
9991 vty_out (vty, "%-30s: ", table_stats_strs[i]);
9992 vty_out (vty, "%12.2f",
9993 (float)ts.counts[i] / (float)TALLY_SIGFIG);
9994 break;
9995#endif
d62a17ae 9996 case BGP_STATS_ASPATH_TOTHOPS:
9997 case BGP_STATS_ASPATH_TOTSIZE:
9998 vty_out(vty, "%-30s: ", table_stats_strs[i]);
9999 vty_out(vty, "%12.2f",
10000 ts.counts[i]
10001 ? (float)ts.counts[i]
10002 / (float)ts.counts
10003 [BGP_STATS_ASPATH_COUNT]
10004 : 0);
10005 break;
10006 case BGP_STATS_TOTPLEN:
10007 vty_out(vty, "%-30s: ", table_stats_strs[i]);
10008 vty_out(vty, "%12.2f",
10009 ts.counts[i]
10010 ? (float)ts.counts[i]
10011 / (float)ts.counts
10012 [BGP_STATS_PREFIXES]
10013 : 0);
10014 break;
10015 case BGP_STATS_SPACE:
10016 vty_out(vty, "%-30s: ", table_stats_strs[i]);
8d0ab76d
DL
10017 vty_out(vty, "%12g\n", ts.total_space);
10018
10019 if (afi == AFI_IP6) {
10020 vty_out(vty, "%30s: ", "/32 equivalent ");
10021 vty_out(vty, "%12g\n",
a4d82a8a 10022 ts.total_space * pow(2.0, -128 + 32));
8d0ab76d
DL
10023 vty_out(vty, "%30s: ", "/48 equivalent ");
10024 vty_out(vty, "%12g\n",
a4d82a8a 10025 ts.total_space * pow(2.0, -128 + 48));
8d0ab76d
DL
10026 } else {
10027 vty_out(vty, "%30s: ", "% announced ");
10028 vty_out(vty, "%12.2f\n",
10029 ts.total_space * 100. * pow(2.0, -32));
10030 vty_out(vty, "%30s: ", "/8 equivalent ");
10031 vty_out(vty, "%12.2f\n",
a4d82a8a 10032 ts.total_space * pow(2.0, -32 + 8));
8d0ab76d
DL
10033 vty_out(vty, "%30s: ", "/24 equivalent ");
10034 vty_out(vty, "%12.2f\n",
a4d82a8a 10035 ts.total_space * pow(2.0, -32 + 24));
8d0ab76d 10036 }
d62a17ae 10037 break;
10038 default:
10039 vty_out(vty, "%-30s: ", table_stats_strs[i]);
10040 vty_out(vty, "%12llu", ts.counts[i]);
10041 }
ff7924f6 10042
d62a17ae 10043 vty_out(vty, "\n");
10044 }
10045 return CMD_SUCCESS;
10046}
10047
10048enum bgp_pcounts {
10049 PCOUNT_ADJ_IN = 0,
10050 PCOUNT_DAMPED,
10051 PCOUNT_REMOVED,
10052 PCOUNT_HISTORY,
10053 PCOUNT_STALE,
10054 PCOUNT_VALID,
10055 PCOUNT_ALL,
10056 PCOUNT_COUNTED,
10057 PCOUNT_PFCNT, /* the figure we display to users */
10058 PCOUNT_MAX,
a636c635 10059};
718e3744 10060
d62a17ae 10061static const char *pcount_strs[] = {
9d303b37
DL
10062 [PCOUNT_ADJ_IN] = "Adj-in",
10063 [PCOUNT_DAMPED] = "Damped",
10064 [PCOUNT_REMOVED] = "Removed",
10065 [PCOUNT_HISTORY] = "History",
10066 [PCOUNT_STALE] = "Stale",
10067 [PCOUNT_VALID] = "Valid",
10068 [PCOUNT_ALL] = "All RIB",
10069 [PCOUNT_COUNTED] = "PfxCt counted",
10070 [PCOUNT_PFCNT] = "Useable",
10071 [PCOUNT_MAX] = NULL,
a636c635 10072};
718e3744 10073
d62a17ae 10074struct peer_pcounts {
10075 unsigned int count[PCOUNT_MAX];
10076 const struct peer *peer;
10077 const struct bgp_table *table;
a636c635 10078};
47fc97cc 10079
d62a17ae 10080static int bgp_peer_count_walker(struct thread *t)
10081{
10082 struct bgp_node *rn;
10083 struct peer_pcounts *pc = THREAD_ARG(t);
10084 const struct peer *peer = pc->peer;
10085
10086 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn)) {
10087 struct bgp_adj_in *ain;
40381db7 10088 struct bgp_path_info *pi;
d62a17ae 10089
10090 for (ain = rn->adj_in; ain; ain = ain->next)
10091 if (ain->peer == peer)
10092 pc->count[PCOUNT_ADJ_IN]++;
10093
40381db7
DS
10094 for (pi = rn->info; pi; pi = pi->next) {
10095 if (pi->peer != peer)
d62a17ae 10096 continue;
10097
10098 pc->count[PCOUNT_ALL]++;
10099
40381db7 10100 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
d62a17ae 10101 pc->count[PCOUNT_DAMPED]++;
40381db7 10102 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
d62a17ae 10103 pc->count[PCOUNT_HISTORY]++;
40381db7 10104 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
d62a17ae 10105 pc->count[PCOUNT_REMOVED]++;
40381db7 10106 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 10107 pc->count[PCOUNT_STALE]++;
40381db7 10108 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
d62a17ae 10109 pc->count[PCOUNT_VALID]++;
40381db7 10110 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
d62a17ae 10111 pc->count[PCOUNT_PFCNT]++;
10112
40381db7 10113 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 10114 pc->count[PCOUNT_COUNTED]++;
40381db7 10115 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
1c50c1c0
QY
10116 flog_err(
10117 EC_LIB_DEVELOPMENT,
10118 "Attempting to count but flags say it is unusable");
d62a17ae 10119 } else {
40381db7 10120 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
1c50c1c0
QY
10121 flog_err(
10122 EC_LIB_DEVELOPMENT,
10123 "Not counted but flags say we should");
d62a17ae 10124 }
10125 }
10126 }
10127 return 0;
718e3744 10128}
10129
d62a17ae 10130static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 10131 safi_t safi, bool use_json)
856ca177 10132{
d62a17ae 10133 struct peer_pcounts pcounts = {.peer = peer};
10134 unsigned int i;
10135 json_object *json = NULL;
10136 json_object *json_loop = NULL;
856ca177 10137
d62a17ae 10138 if (use_json) {
10139 json = json_object_new_object();
10140 json_loop = json_object_new_object();
10141 }
718e3744 10142
d62a17ae 10143 if (!peer || !peer->bgp || !peer->afc[afi][safi]
10144 || !peer->bgp->rib[afi][safi]) {
10145 if (use_json) {
10146 json_object_string_add(
10147 json, "warning",
10148 "No such neighbor or address family");
10149 vty_out(vty, "%s\n", json_object_to_json_string(json));
10150 json_object_free(json);
10151 } else
10152 vty_out(vty, "%% No such neighbor or address family\n");
10153
10154 return CMD_WARNING;
10155 }
2a71e9ce 10156
d62a17ae 10157 memset(&pcounts, 0, sizeof(pcounts));
10158 pcounts.peer = peer;
10159 pcounts.table = peer->bgp->rib[afi][safi];
10160
10161 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
10162 * stats for the thread-walk (i.e. ensure this can't be blamed on
10163 * on just vty_read()).
10164 */
d62a17ae 10165 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
10166
10167 if (use_json) {
10168 json_object_string_add(json, "prefixCountsFor", peer->host);
10169 json_object_string_add(json, "multiProtocol",
10170 afi_safi_print(afi, safi));
10171 json_object_int_add(json, "pfxCounter",
10172 peer->pcount[afi][safi]);
10173
10174 for (i = 0; i < PCOUNT_MAX; i++)
10175 json_object_int_add(json_loop, pcount_strs[i],
10176 pcounts.count[i]);
10177
10178 json_object_object_add(json, "ribTableWalkCounters", json_loop);
10179
10180 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
10181 json_object_string_add(json, "pfxctDriftFor",
10182 peer->host);
10183 json_object_string_add(
10184 json, "recommended",
10185 "Please report this bug, with the above command output");
10186 }
996c9314
LB
10187 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10188 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 10189 json_object_free(json);
10190 } else {
10191
10192 if (peer->hostname
10193 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
10194 vty_out(vty, "Prefix counts for %s/%s, %s\n",
10195 peer->hostname, peer->host,
10196 afi_safi_print(afi, safi));
10197 } else {
10198 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
10199 afi_safi_print(afi, safi));
10200 }
10201
10202 vty_out(vty, "PfxCt: %ld\n", peer->pcount[afi][safi]);
10203 vty_out(vty, "\nCounts from RIB table walk:\n\n");
10204
10205 for (i = 0; i < PCOUNT_MAX; i++)
10206 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
10207 pcounts.count[i]);
10208
10209 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
10210 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
10211 vty_out(vty,
10212 "Please report this bug, with the above command output\n");
10213 }
10214 }
10215
10216 return CMD_SUCCESS;
718e3744 10217}
10218
a636c635
DW
10219DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
10220 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
c1a44e43 10221 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] "
30a6a167 10222 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
718e3744 10223 SHOW_STR
10224 IP_STR
10225 BGP_STR
8386ac43 10226 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
10227 BGP_AFI_HELP_STR
10228 BGP_SAFI_HELP_STR
0b16f239
DS
10229 "Detailed information on TCP and BGP neighbor connections\n"
10230 "Neighbor to display information about\n"
10231 "Neighbor to display information about\n"
91d37724 10232 "Neighbor on BGP configured interface\n"
a636c635 10233 "Display detailed prefix count information\n"
9973d184 10234 JSON_STR)
0b16f239 10235{
d62a17ae 10236 afi_t afi = AFI_IP6;
10237 safi_t safi = SAFI_UNICAST;
10238 struct peer *peer;
10239 int idx = 0;
10240 struct bgp *bgp = NULL;
9f049418
DS
10241 bool uj = use_json(argc, argv);
10242
10243 if (uj)
10244 argc--;
856ca177 10245
d62a17ae 10246 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10247 &bgp, uj);
d62a17ae 10248 if (!idx)
10249 return CMD_WARNING;
0b16f239 10250
d62a17ae 10251 argv_find(argv, argc, "neighbors", &idx);
10252 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
10253 if (!peer)
10254 return CMD_WARNING;
bb46e94f 10255
d62a17ae 10256 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_UNICAST, uj);
a636c635 10257}
0b16f239 10258
d6902373
PG
10259#ifdef KEEP_OLD_VPN_COMMANDS
10260DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
10261 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
10262 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
10263 SHOW_STR
10264 IP_STR
10265 BGP_STR
d6902373 10266 BGP_VPNVX_HELP_STR
91d37724 10267 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
10268 "Detailed information on TCP and BGP neighbor connections\n"
10269 "Neighbor to display information about\n"
10270 "Neighbor to display information about\n"
91d37724 10271 "Neighbor on BGP configured interface\n"
a636c635 10272 "Display detailed prefix count information\n"
9973d184 10273 JSON_STR)
a636c635 10274{
d62a17ae 10275 int idx_peer = 6;
10276 struct peer *peer;
9f049418 10277 bool uj = use_json(argc, argv);
a636c635 10278
d62a17ae 10279 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
10280 if (!peer)
10281 return CMD_WARNING;
10282
10283 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
10284}
10285
d6902373
PG
10286DEFUN (show_ip_bgp_vpn_all_route_prefix,
10287 show_ip_bgp_vpn_all_route_prefix_cmd,
10288 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
10289 SHOW_STR
10290 IP_STR
10291 BGP_STR
d6902373 10292 BGP_VPNVX_HELP_STR
91d37724
QY
10293 "Display information about all VPNv4 NLRIs\n"
10294 "Network in the BGP routing table to display\n"
3a2d747c 10295 "Network in the BGP routing table to display\n"
9973d184 10296 JSON_STR)
91d37724 10297{
d62a17ae 10298 int idx = 0;
10299 char *network = NULL;
10300 struct bgp *bgp = bgp_get_default();
10301 if (!bgp) {
10302 vty_out(vty, "Can't find default instance\n");
10303 return CMD_WARNING;
10304 }
87e34b58 10305
d62a17ae 10306 if (argv_find(argv, argc, "A.B.C.D", &idx))
10307 network = argv[idx]->arg;
10308 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
10309 network = argv[idx]->arg;
10310 else {
10311 vty_out(vty, "Unable to figure out Network\n");
10312 return CMD_WARNING;
10313 }
87e34b58 10314
d62a17ae 10315 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 10316 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 10317}
d6902373 10318#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 10319
4c63a661
PG
10320DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix,
10321 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd,
10322 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10323 SHOW_STR
10324 IP_STR
10325 BGP_STR
10326 L2VPN_HELP_STR
10327 EVPN_HELP_STR
10328 "Display information about all EVPN NLRIs\n"
10329 "Network in the BGP routing table to display\n"
10330 "Network in the BGP routing table to display\n"
10331 JSON_STR)
10332{
d62a17ae 10333 int idx = 0;
10334 char *network = NULL;
a636c635 10335
d62a17ae 10336 if (argv_find(argv, argc, "A.B.C.D", &idx))
10337 network = argv[idx]->arg;
10338 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
10339 network = argv[idx]->arg;
10340 else {
10341 vty_out(vty, "Unable to figure out Network\n");
10342 return CMD_WARNING;
10343 }
10344 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL, 0,
360660c6 10345 BGP_PATH_SHOW_ALL, use_json(argc, argv));
d62a17ae 10346}
10347
10348static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 10349 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 10350 const char *rmap_name, bool use_json,
6392aaa6 10351 json_object *json)
d62a17ae 10352{
10353 struct bgp_table *table;
10354 struct bgp_adj_in *ain;
10355 struct bgp_adj_out *adj;
10356 unsigned long output_count;
10357 unsigned long filtered_count;
10358 struct bgp_node *rn;
10359 int header1 = 1;
10360 struct bgp *bgp;
10361 int header2 = 1;
10362 struct attr attr;
10363 int ret;
10364 struct update_subgroup *subgrp;
10365 json_object *json_scode = NULL;
10366 json_object *json_ocode = NULL;
10367 json_object *json_ar = NULL;
10368 struct peer_af *paf;
f99def61 10369 bool route_filtered;
d62a17ae 10370
10371 if (use_json) {
10372 json_scode = json_object_new_object();
10373 json_ocode = json_object_new_object();
10374 json_ar = json_object_new_object();
10375
10376 json_object_string_add(json_scode, "suppressed", "s");
10377 json_object_string_add(json_scode, "damped", "d");
10378 json_object_string_add(json_scode, "history", "h");
10379 json_object_string_add(json_scode, "valid", "*");
10380 json_object_string_add(json_scode, "best", ">");
10381 json_object_string_add(json_scode, "multipath", "=");
10382 json_object_string_add(json_scode, "internal", "i");
10383 json_object_string_add(json_scode, "ribFailure", "r");
10384 json_object_string_add(json_scode, "stale", "S");
10385 json_object_string_add(json_scode, "removed", "R");
10386
10387 json_object_string_add(json_ocode, "igp", "i");
10388 json_object_string_add(json_ocode, "egp", "e");
10389 json_object_string_add(json_ocode, "incomplete", "?");
10390 }
a636c635 10391
d62a17ae 10392 bgp = peer->bgp;
a636c635 10393
d62a17ae 10394 if (!bgp) {
10395 if (use_json) {
10396 json_object_string_add(json, "alert", "no BGP");
10397 vty_out(vty, "%s\n", json_object_to_json_string(json));
10398 json_object_free(json);
10399 } else
10400 vty_out(vty, "%% No bgp\n");
10401 return;
10402 }
a636c635 10403
d62a17ae 10404 table = bgp->rib[afi][safi];
10405
10406 output_count = filtered_count = 0;
10407 subgrp = peer_subgroup(peer, afi, safi);
10408
6392aaa6 10409 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 10410 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
10411 if (use_json) {
10412 json_object_int_add(json, "bgpTableVersion",
10413 table->version);
10414 json_object_string_add(json, "bgpLocalRouterId",
10415 inet_ntoa(bgp->router_id));
10416 json_object_object_add(json, "bgpStatusCodes",
10417 json_scode);
10418 json_object_object_add(json, "bgpOriginCodes",
10419 json_ocode);
07d0c4ed
DA
10420 json_object_string_add(
10421 json, "bgpOriginatingDefaultNetwork",
10422 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 10423 } else {
996c9314 10424 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 10425 ", local router ID is %s, vrf id ",
d62a17ae 10426 table->version, inet_ntoa(bgp->router_id));
9df8b37c
PZ
10427 if (bgp->vrf_id == VRF_UNKNOWN)
10428 vty_out(vty, "%s", VRFID_NONE_STR);
10429 else
10430 vty_out(vty, "%u", bgp->vrf_id);
10431 vty_out(vty, "\n");
d62a17ae 10432 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10433 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 10434 vty_out(vty, BGP_SHOW_OCODE_HEADER);
10435
07d0c4ed
DA
10436 vty_out(vty, "Originating default network %s\n\n",
10437 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 10438 }
10439 header1 = 0;
10440 }
a636c635 10441
d62a17ae 10442 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6392aaa6
PM
10443 if (type == bgp_show_adj_route_received
10444 || type == bgp_show_adj_route_filtered) {
d62a17ae 10445 for (ain = rn->adj_in; ain; ain = ain->next) {
6392aaa6 10446 if (ain->peer != peer || !ain->attr)
ea47320b 10447 continue;
6392aaa6 10448
ea47320b
DL
10449 if (header1) {
10450 if (use_json) {
10451 json_object_int_add(
60466a63 10452 json, "bgpTableVersion",
ea47320b
DL
10453 0);
10454 json_object_string_add(
10455 json,
10456 "bgpLocalRouterId",
10457 inet_ntoa(
10458 bgp->router_id));
10459 json_object_object_add(
60466a63 10460 json, "bgpStatusCodes",
ea47320b
DL
10461 json_scode);
10462 json_object_object_add(
60466a63 10463 json, "bgpOriginCodes",
ea47320b
DL
10464 json_ocode);
10465 } else {
10466 vty_out(vty,
9df8b37c 10467 "BGP table version is 0, local router ID is %s, vrf id ",
ea47320b 10468 inet_ntoa(
9df8b37c
PZ
10469 bgp->router_id));
10470 if (bgp->vrf_id == VRF_UNKNOWN)
10471 vty_out(vty, "%s",
10472 VRFID_NONE_STR);
10473 else
10474 vty_out(vty, "%u",
10475 bgp->vrf_id);
10476 vty_out(vty, "\n");
ea47320b
DL
10477 vty_out(vty,
10478 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
10479 vty_out(vty,
10480 BGP_SHOW_NCODE_HEADER);
ea47320b
DL
10481 vty_out(vty,
10482 BGP_SHOW_OCODE_HEADER);
d62a17ae 10483 }
ea47320b
DL
10484 header1 = 0;
10485 }
10486 if (header2) {
10487 if (!use_json)
10488 vty_out(vty, BGP_SHOW_HEADER);
10489 header2 = 0;
10490 }
6392aaa6
PM
10491
10492 bgp_attr_dup(&attr, ain->attr);
f99def61
AD
10493 route_filtered = false;
10494
10495 /* Filter prefix using distribute list,
10496 * filter list or prefix list
10497 */
10498 if ((bgp_input_filter(peer, &rn->p, &attr, afi,
10499 safi)) == FILTER_DENY)
10500 route_filtered = true;
10501
10502 /* Filter prefix using route-map */
6392aaa6 10503 ret = bgp_input_modifier(peer, &rn->p, &attr,
13c8e163 10504 afi, safi, rmap_name);
6392aaa6 10505
13c8e163
AD
10506 if (type == bgp_show_adj_route_filtered &&
10507 !route_filtered && ret != RMAP_DENY) {
b755861b 10508 bgp_attr_undup(&attr, ain->attr);
6392aaa6 10509 continue;
d62a17ae 10510 }
6392aaa6 10511
13c8e163
AD
10512 if (type == bgp_show_adj_route_received &&
10513 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
10514 filtered_count++;
10515
10516 route_vty_out_tmp(vty, &rn->p, &attr, safi,
10517 use_json, json_ar);
b755861b 10518 bgp_attr_undup(&attr, ain->attr);
6392aaa6 10519 output_count++;
d62a17ae 10520 }
6392aaa6 10521 } else if (type == bgp_show_adj_route_advertised) {
d62a17ae 10522 for (adj = rn->adj_out; adj; adj = adj->next)
924c3f6a 10523 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 10524 if (paf->peer != peer || !adj->attr)
924c3f6a 10525 continue;
d62a17ae 10526
924c3f6a
DS
10527 if (header1) {
10528 if (use_json) {
10529 json_object_int_add(
10530 json,
10531 "bgpTableVersion",
10532 table->version);
10533 json_object_string_add(
10534 json,
10535 "bgpLocalRouterId",
10536 inet_ntoa(
10537 bgp->router_id));
10538 json_object_object_add(
10539 json,
10540 "bgpStatusCodes",
10541 json_scode);
10542 json_object_object_add(
10543 json,
10544 "bgpOriginCodes",
10545 json_ocode);
10546 } else {
10547 vty_out(vty,
10548 "BGP table version is %" PRIu64
9df8b37c 10549 ", local router ID is %s, vrf id ",
924c3f6a
DS
10550 table->version,
10551 inet_ntoa(
10552 bgp->router_id));
9df8b37c
PZ
10553 if (bgp->vrf_id ==
10554 VRF_UNKNOWN)
10555 vty_out(vty,
10556 "%s",
10557 VRFID_NONE_STR);
10558 else
10559 vty_out(vty,
10560 "%u",
10561 bgp->vrf_id);
10562 vty_out(vty, "\n");
924c3f6a
DS
10563 vty_out(vty,
10564 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
10565 vty_out(vty,
10566 BGP_SHOW_NCODE_HEADER);
924c3f6a
DS
10567 vty_out(vty,
10568 BGP_SHOW_OCODE_HEADER);
a2addae8 10569 }
924c3f6a
DS
10570 header1 = 0;
10571 }
924c3f6a
DS
10572 if (header2) {
10573 if (!use_json)
10574 vty_out(vty,
10575 BGP_SHOW_HEADER);
10576 header2 = 0;
10577 }
d62a17ae 10578
b755861b
PM
10579 bgp_attr_dup(&attr, adj->attr);
10580 ret = bgp_output_modifier(
10581 peer, &rn->p, &attr, afi, safi,
10582 rmap_name);
f46d8e1e 10583
b755861b
PM
10584 if (ret != RMAP_DENY) {
10585 route_vty_out_tmp(vty, &rn->p,
10586 &attr, safi,
10587 use_json,
10588 json_ar);
10589 output_count++;
10590 } else {
10591 filtered_count++;
a2addae8 10592 }
b755861b
PM
10593
10594 bgp_attr_undup(&attr, adj->attr);
924c3f6a 10595 }
d62a17ae 10596 }
10597 }
d62a17ae 10598
d62a17ae 10599 if (use_json) {
6392aaa6
PM
10600 json_object_object_add(json, "advertisedRoutes", json_ar);
10601 json_object_int_add(json, "totalPrefixCounter", output_count);
10602 json_object_int_add(json, "filteredPrefixCounter",
10603 filtered_count);
10604
996c9314
LB
10605 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10606 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 10607 json_object_free(json);
6392aaa6
PM
10608 } else if (output_count > 0) {
10609 if (filtered_count > 0)
10610 vty_out(vty,
10611 "\nTotal number of prefixes %ld (%ld filtered)\n",
10612 output_count, filtered_count);
10613 else
10614 vty_out(vty, "\nTotal number of prefixes %ld\n",
10615 output_count);
d62a17ae 10616 }
a636c635 10617}
2a71e9ce 10618
d62a17ae 10619static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 10620 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 10621 const char *rmap_name, bool use_json)
0b16f239 10622{
d62a17ae 10623 json_object *json = NULL;
0b16f239 10624
d62a17ae 10625 if (use_json)
10626 json = json_object_new_object();
0b16f239 10627
d62a17ae 10628 /* labeled-unicast routes live in the unicast table */
10629 if (safi == SAFI_LABELED_UNICAST)
10630 safi = SAFI_UNICAST;
4dd6177e 10631
d62a17ae 10632 if (!peer || !peer->afc[afi][safi]) {
10633 if (use_json) {
10634 json_object_string_add(
10635 json, "warning",
10636 "No such neighbor or address family");
10637 vty_out(vty, "%s\n", json_object_to_json_string(json));
10638 json_object_free(json);
10639 } else
10640 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 10641
d62a17ae 10642 return CMD_WARNING;
10643 }
10644
6392aaa6
PM
10645 if ((type == bgp_show_adj_route_received
10646 || type == bgp_show_adj_route_filtered)
d62a17ae 10647 && !CHECK_FLAG(peer->af_flags[afi][safi],
10648 PEER_FLAG_SOFT_RECONFIG)) {
10649 if (use_json) {
10650 json_object_string_add(
10651 json, "warning",
10652 "Inbound soft reconfiguration not enabled");
10653 vty_out(vty, "%s\n", json_object_to_json_string(json));
10654 json_object_free(json);
10655 } else
10656 vty_out(vty,
10657 "%% Inbound soft reconfiguration not enabled\n");
10658
10659 return CMD_WARNING;
10660 }
0b16f239 10661
6392aaa6 10662 show_adj_route(vty, peer, afi, safi, type, rmap_name, use_json, json);
0b16f239 10663
d62a17ae 10664 return CMD_SUCCESS;
a636c635 10665}
50ef26d4 10666
a636c635
DW
10667DEFUN (show_ip_bgp_instance_neighbor_advertised_route,
10668 show_ip_bgp_instance_neighbor_advertised_route_cmd,
4dd6177e 10669 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
6392aaa6 10670 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
718e3744 10671 SHOW_STR
10672 IP_STR
10673 BGP_STR
a636c635 10674 BGP_INSTANCE_HELP_STR
7395a2c9 10675 BGP_AFI_HELP_STR
4dd6177e 10676 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 10677 "Detailed information on TCP and BGP neighbor connections\n"
10678 "Neighbor to display information about\n"
10679 "Neighbor to display information about\n"
91d37724 10680 "Neighbor on BGP configured interface\n"
a636c635 10681 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
10682 "Display the received routes from neighbor\n"
10683 "Display the filtered routes received from neighbor\n"
a636c635
DW
10684 "Route-map to modify the attributes\n"
10685 "Name of the route map\n"
9973d184 10686 JSON_STR)
718e3744 10687{
d62a17ae 10688 afi_t afi = AFI_IP6;
10689 safi_t safi = SAFI_UNICAST;
10690 char *rmap_name = NULL;
10691 char *peerstr = NULL;
d62a17ae 10692 struct bgp *bgp = NULL;
10693 struct peer *peer;
6392aaa6 10694 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 10695 int idx = 0;
9f049418 10696 bool uj = use_json(argc, argv);
6392aaa6 10697
d62a17ae 10698 if (uj)
10699 argc--;
30a6a167 10700
9f049418
DS
10701 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10702 &bgp, uj);
10703 if (!idx)
10704 return CMD_WARNING;
10705
d62a17ae 10706 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10707 argv_find(argv, argc, "neighbors", &idx);
10708 peerstr = argv[++idx]->arg;
8c3deaae 10709
d62a17ae 10710 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
10711 if (!peer)
10712 return CMD_WARNING;
856ca177 10713
d62a17ae 10714 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
10715 type = bgp_show_adj_route_advertised;
10716 else if (argv_find(argv, argc, "received-routes", &idx))
10717 type = bgp_show_adj_route_received;
10718 else if (argv_find(argv, argc, "filtered-routes", &idx))
10719 type = bgp_show_adj_route_filtered;
10720
d62a17ae 10721 if (argv_find(argv, argc, "route-map", &idx))
10722 rmap_name = argv[++idx]->arg;
95cbbd2a 10723
6392aaa6 10724 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj);
95cbbd2a
ML
10725}
10726
718e3744 10727DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
10728 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 10729 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 10730 SHOW_STR
10731 IP_STR
10732 BGP_STR
8c3deaae
QY
10733 "Address Family\n"
10734 "Address Family\n"
718e3744 10735 "Address Family modifier\n"
10736 "Detailed information on TCP and BGP neighbor connections\n"
10737 "Neighbor to display information about\n"
10738 "Neighbor to display information about\n"
91d37724 10739 "Neighbor on BGP configured interface\n"
718e3744 10740 "Display information received from a BGP neighbor\n"
856ca177 10741 "Display the prefixlist filter\n"
9973d184 10742 JSON_STR)
718e3744 10743{
d62a17ae 10744 afi_t afi = AFI_IP6;
10745 safi_t safi = SAFI_UNICAST;
10746 char *peerstr = NULL;
10747
10748 char name[BUFSIZ];
10749 union sockunion su;
10750 struct peer *peer;
10751 int count, ret;
10752
10753 int idx = 0;
10754
10755 /* show [ip] bgp */
10756 if (argv_find(argv, argc, "ip", &idx))
10757 afi = AFI_IP;
10758 /* [<ipv4|ipv6> [unicast]] */
10759 if (argv_find(argv, argc, "ipv4", &idx))
10760 afi = AFI_IP;
10761 if (argv_find(argv, argc, "ipv6", &idx))
10762 afi = AFI_IP6;
10763 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10764 argv_find(argv, argc, "neighbors", &idx);
10765 peerstr = argv[++idx]->arg;
10766
9f049418 10767 bool uj = use_json(argc, argv);
d62a17ae 10768
10769 ret = str2sockunion(peerstr, &su);
10770 if (ret < 0) {
10771 peer = peer_lookup_by_conf_if(NULL, peerstr);
10772 if (!peer) {
10773 if (uj)
10774 vty_out(vty, "{}\n");
10775 else
10776 vty_out(vty,
10777 "%% Malformed address or name: %s\n",
10778 peerstr);
10779 return CMD_WARNING;
10780 }
10781 } else {
10782 peer = peer_lookup(NULL, &su);
10783 if (!peer) {
10784 if (uj)
10785 vty_out(vty, "{}\n");
10786 else
10787 vty_out(vty, "No peer\n");
10788 return CMD_WARNING;
10789 }
10790 }
718e3744 10791
d62a17ae 10792 sprintf(name, "%s.%d.%d", peer->host, afi, safi);
10793 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
10794 if (count) {
10795 if (!uj)
10796 vty_out(vty, "Address Family: %s\n",
10797 afi_safi_print(afi, safi));
10798 prefix_bgp_show_prefix_list(vty, afi, name, uj);
10799 } else {
10800 if (uj)
10801 vty_out(vty, "{}\n");
10802 else
10803 vty_out(vty, "No functional output\n");
10804 }
718e3744 10805
d62a17ae 10806 return CMD_SUCCESS;
10807}
10808
10809static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
10810 afi_t afi, safi_t safi,
9f049418 10811 enum bgp_show_type type, bool use_json)
d62a17ae 10812{
8a893163
DW
10813 /* labeled-unicast routes live in the unicast table */
10814 if (safi == SAFI_LABELED_UNICAST)
10815 safi = SAFI_UNICAST;
10816
d62a17ae 10817 if (!peer || !peer->afc[afi][safi]) {
10818 if (use_json) {
10819 json_object *json_no = NULL;
10820 json_no = json_object_new_object();
10821 json_object_string_add(
10822 json_no, "warning",
10823 "No such neighbor or address family");
10824 vty_out(vty, "%s\n",
10825 json_object_to_json_string(json_no));
10826 json_object_free(json_no);
10827 } else
10828 vty_out(vty, "%% No such neighbor or address family\n");
10829 return CMD_WARNING;
10830 }
47fc97cc 10831
d62a17ae 10832 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json);
718e3744 10833}
10834
dba3c1d3
PG
10835DEFUN (show_ip_bgp_flowspec_routes_detailed,
10836 show_ip_bgp_flowspec_routes_detailed_cmd,
10837 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
10838 SHOW_STR
10839 IP_STR
10840 BGP_STR
10841 BGP_INSTANCE_HELP_STR
10842 BGP_AFI_HELP_STR
10843 "SAFI Flowspec\n"
10844 "Detailed information on flowspec entries\n"
10845 JSON_STR)
10846{
10847 afi_t afi = AFI_IP;
10848 safi_t safi = SAFI_UNICAST;
10849 struct bgp *bgp = NULL;
10850 int idx = 0;
9f049418
DS
10851 bool uj = use_json(argc, argv);
10852
10853 if (uj)
10854 argc--;
dba3c1d3
PG
10855
10856 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10857 &bgp, uj);
dba3c1d3
PG
10858 if (!idx)
10859 return CMD_WARNING;
10860
9f049418 10861 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL, uj);
dba3c1d3
PG
10862}
10863
718e3744 10864DEFUN (show_ip_bgp_neighbor_routes,
10865 show_ip_bgp_neighbor_routes_cmd,
4dd6177e 10866 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
30a6a167 10867 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
50ef26d4 10868 SHOW_STR
10869 IP_STR
10870 BGP_STR
8386ac43 10871 BGP_INSTANCE_HELP_STR
4f280b15 10872 BGP_AFI_HELP_STR
4dd6177e 10873 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 10874 "Detailed information on TCP and BGP neighbor connections\n"
10875 "Neighbor to display information about\n"
10876 "Neighbor to display information about\n"
91d37724 10877 "Neighbor on BGP configured interface\n"
2525cf39 10878 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
10879 "Display the dampened routes received from neighbor\n"
10880 "Display routes learned from neighbor\n"
9973d184 10881 JSON_STR)
718e3744 10882{
d62a17ae 10883 char *peerstr = NULL;
10884 struct bgp *bgp = NULL;
10885 afi_t afi = AFI_IP6;
10886 safi_t safi = SAFI_UNICAST;
10887 struct peer *peer;
10888 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 10889 int idx = 0;
9f049418
DS
10890 bool uj = use_json(argc, argv);
10891
10892 if (uj)
10893 argc--;
bb46e94f 10894
d62a17ae 10895 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10896 &bgp, uj);
d62a17ae 10897 if (!idx)
10898 return CMD_WARNING;
c493f2d8 10899
d62a17ae 10900 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10901 argv_find(argv, argc, "neighbors", &idx);
10902 peerstr = argv[++idx]->arg;
8c3deaae 10903
d62a17ae 10904 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 10905 if (!peer)
d62a17ae 10906 return CMD_WARNING;
bb46e94f 10907
d62a17ae 10908 if (argv_find(argv, argc, "flap-statistics", &idx))
10909 sh_type = bgp_show_type_flap_neighbor;
10910 else if (argv_find(argv, argc, "dampened-routes", &idx))
10911 sh_type = bgp_show_type_damp_neighbor;
10912 else if (argv_find(argv, argc, "routes", &idx))
10913 sh_type = bgp_show_type_neighbor;
2525cf39 10914
d62a17ae 10915 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 10916}
6b0655a2 10917
734b349e 10918struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 10919
d62a17ae 10920struct bgp_distance {
10921 /* Distance value for the IP source prefix. */
d7c0a89a 10922 uint8_t distance;
718e3744 10923
d62a17ae 10924 /* Name of the access-list to be matched. */
10925 char *access_list;
718e3744 10926};
10927
4f280b15
LB
10928DEFUN (show_bgp_afi_vpn_rd_route,
10929 show_bgp_afi_vpn_rd_route_cmd,
d114b977 10930 "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
10931 SHOW_STR
10932 BGP_STR
10933 BGP_AFI_HELP_STR
10934 "Address Family modifier\n"
10935 "Display information for a route distinguisher\n"
10936 "Route Distinguisher\n"
7395a2c9
DS
10937 "Network in the BGP routing table to display\n"
10938 "Network in the BGP routing table to display\n"
10939 JSON_STR)
4f280b15 10940{
d62a17ae 10941 int ret;
10942 struct prefix_rd prd;
10943 afi_t afi = AFI_MAX;
10944 int idx = 0;
4f280b15 10945
ff6566f3
DS
10946 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
10947 vty_out(vty, "%% Malformed Address Family\n");
10948 return CMD_WARNING;
10949 }
10950
d62a17ae 10951 ret = str2prefix_rd(argv[5]->arg, &prd);
10952 if (!ret) {
10953 vty_out(vty, "%% Malformed Route Distinguisher\n");
10954 return CMD_WARNING;
10955 }
ff6566f3 10956
d62a17ae 10957 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 10958 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
10959}
10960
d62a17ae 10961static struct bgp_distance *bgp_distance_new(void)
718e3744 10962{
d62a17ae 10963 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 10964}
10965
d62a17ae 10966static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 10967{
d62a17ae 10968 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 10969}
10970
d62a17ae 10971static int bgp_distance_set(struct vty *vty, const char *distance_str,
10972 const char *ip_str, const char *access_list_str)
718e3744 10973{
d62a17ae 10974 int ret;
10975 afi_t afi;
10976 safi_t safi;
10977 struct prefix p;
d7c0a89a 10978 uint8_t distance;
d62a17ae 10979 struct bgp_node *rn;
10980 struct bgp_distance *bdistance;
718e3744 10981
d62a17ae 10982 afi = bgp_node_afi(vty);
10983 safi = bgp_node_safi(vty);
734b349e 10984
d62a17ae 10985 ret = str2prefix(ip_str, &p);
10986 if (ret == 0) {
10987 vty_out(vty, "Malformed prefix\n");
10988 return CMD_WARNING_CONFIG_FAILED;
10989 }
718e3744 10990
d62a17ae 10991 distance = atoi(distance_str);
718e3744 10992
d62a17ae 10993 /* Get BGP distance node. */
10994 rn = bgp_node_get(bgp_distance_table[afi][safi], (struct prefix *)&p);
ca2e160d
DS
10995 bdistance = bgp_distance_get_node(rn);
10996 if (bdistance)
d62a17ae 10997 bgp_unlock_node(rn);
ca2e160d 10998 else {
d62a17ae 10999 bdistance = bgp_distance_new();
a78beeb5 11000 bgp_distance_set_node_info(rn, bdistance);
d62a17ae 11001 }
718e3744 11002
d62a17ae 11003 /* Set distance value. */
11004 bdistance->distance = distance;
718e3744 11005
d62a17ae 11006 /* Reset access-list configuration. */
11007 if (bdistance->access_list) {
11008 XFREE(MTYPE_AS_LIST, bdistance->access_list);
11009 bdistance->access_list = NULL;
11010 }
11011 if (access_list_str)
11012 bdistance->access_list =
11013 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 11014
d62a17ae 11015 return CMD_SUCCESS;
718e3744 11016}
11017
d62a17ae 11018static int bgp_distance_unset(struct vty *vty, const char *distance_str,
11019 const char *ip_str, const char *access_list_str)
718e3744 11020{
d62a17ae 11021 int ret;
11022 afi_t afi;
11023 safi_t safi;
11024 struct prefix p;
11025 int distance;
11026 struct bgp_node *rn;
11027 struct bgp_distance *bdistance;
718e3744 11028
d62a17ae 11029 afi = bgp_node_afi(vty);
11030 safi = bgp_node_safi(vty);
734b349e 11031
d62a17ae 11032 ret = str2prefix(ip_str, &p);
11033 if (ret == 0) {
11034 vty_out(vty, "Malformed prefix\n");
11035 return CMD_WARNING_CONFIG_FAILED;
11036 }
718e3744 11037
d62a17ae 11038 rn = bgp_node_lookup(bgp_distance_table[afi][safi],
11039 (struct prefix *)&p);
11040 if (!rn) {
11041 vty_out(vty, "Can't find specified prefix\n");
11042 return CMD_WARNING_CONFIG_FAILED;
11043 }
718e3744 11044
ca2e160d 11045 bdistance = bgp_distance_get_node(rn);
d62a17ae 11046 distance = atoi(distance_str);
1f9a9fff 11047
d62a17ae 11048 if (bdistance->distance != distance) {
11049 vty_out(vty, "Distance does not match configured\n");
11050 return CMD_WARNING_CONFIG_FAILED;
11051 }
718e3744 11052
d62a17ae 11053 if (bdistance->access_list)
11054 XFREE(MTYPE_AS_LIST, bdistance->access_list);
11055 bgp_distance_free(bdistance);
718e3744 11056
d62a17ae 11057 rn->info = NULL;
11058 bgp_unlock_node(rn);
11059 bgp_unlock_node(rn);
718e3744 11060
d62a17ae 11061 return CMD_SUCCESS;
718e3744 11062}
11063
718e3744 11064/* Apply BGP information to distance method. */
40381db7 11065uint8_t bgp_distance_apply(struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 11066 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 11067{
11068 struct bgp_node *rn;
11069 struct prefix q;
11070 struct peer *peer;
11071 struct bgp_distance *bdistance;
11072 struct access_list *alist;
11073 struct bgp_static *bgp_static;
11074
11075 if (!bgp)
11076 return 0;
11077
40381db7 11078 peer = pinfo->peer;
d62a17ae 11079
11080 /* Check source address. */
11081 sockunion2hostprefix(&peer->su, &q);
11082 rn = bgp_node_match(bgp_distance_table[afi][safi], &q);
11083 if (rn) {
ca2e160d 11084 bdistance = bgp_distance_get_node(rn);
d62a17ae 11085 bgp_unlock_node(rn);
11086
11087 if (bdistance->access_list) {
11088 alist = access_list_lookup(afi, bdistance->access_list);
11089 if (alist
11090 && access_list_apply(alist, p) == FILTER_PERMIT)
11091 return bdistance->distance;
11092 } else
11093 return bdistance->distance;
718e3744 11094 }
718e3744 11095
d62a17ae 11096 /* Backdoor check. */
11097 rn = bgp_node_lookup(bgp->route[afi][safi], p);
11098 if (rn) {
a78beeb5 11099 bgp_static = bgp_static_get_node_info(rn);
d62a17ae 11100 bgp_unlock_node(rn);
718e3744 11101
d62a17ae 11102 if (bgp_static->backdoor) {
11103 if (bgp->distance_local[afi][safi])
11104 return bgp->distance_local[afi][safi];
11105 else
11106 return ZEBRA_IBGP_DISTANCE_DEFAULT;
11107 }
718e3744 11108 }
718e3744 11109
d62a17ae 11110 if (peer->sort == BGP_PEER_EBGP) {
11111 if (bgp->distance_ebgp[afi][safi])
11112 return bgp->distance_ebgp[afi][safi];
11113 return ZEBRA_EBGP_DISTANCE_DEFAULT;
11114 } else {
11115 if (bgp->distance_ibgp[afi][safi])
11116 return bgp->distance_ibgp[afi][safi];
11117 return ZEBRA_IBGP_DISTANCE_DEFAULT;
11118 }
718e3744 11119}
11120
11121DEFUN (bgp_distance,
11122 bgp_distance_cmd,
6147e2c6 11123 "distance bgp (1-255) (1-255) (1-255)",
718e3744 11124 "Define an administrative distance\n"
11125 "BGP distance\n"
11126 "Distance for routes external to the AS\n"
11127 "Distance for routes internal to the AS\n"
11128 "Distance for local routes\n")
11129{
d62a17ae 11130 VTY_DECLVAR_CONTEXT(bgp, bgp);
11131 int idx_number = 2;
11132 int idx_number_2 = 3;
11133 int idx_number_3 = 4;
11134 afi_t afi;
11135 safi_t safi;
718e3744 11136
d62a17ae 11137 afi = bgp_node_afi(vty);
11138 safi = bgp_node_safi(vty);
718e3744 11139
d62a17ae 11140 bgp->distance_ebgp[afi][safi] = atoi(argv[idx_number]->arg);
11141 bgp->distance_ibgp[afi][safi] = atoi(argv[idx_number_2]->arg);
11142 bgp->distance_local[afi][safi] = atoi(argv[idx_number_3]->arg);
11143 return CMD_SUCCESS;
718e3744 11144}
11145
11146DEFUN (no_bgp_distance,
11147 no_bgp_distance_cmd,
a636c635 11148 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 11149 NO_STR
11150 "Define an administrative distance\n"
11151 "BGP distance\n"
11152 "Distance for routes external to the AS\n"
11153 "Distance for routes internal to the AS\n"
11154 "Distance for local routes\n")
11155{
d62a17ae 11156 VTY_DECLVAR_CONTEXT(bgp, bgp);
11157 afi_t afi;
11158 safi_t safi;
718e3744 11159
d62a17ae 11160 afi = bgp_node_afi(vty);
11161 safi = bgp_node_safi(vty);
718e3744 11162
d62a17ae 11163 bgp->distance_ebgp[afi][safi] = 0;
11164 bgp->distance_ibgp[afi][safi] = 0;
11165 bgp->distance_local[afi][safi] = 0;
11166 return CMD_SUCCESS;
718e3744 11167}
11168
718e3744 11169
11170DEFUN (bgp_distance_source,
11171 bgp_distance_source_cmd,
6147e2c6 11172 "distance (1-255) A.B.C.D/M",
718e3744 11173 "Define an administrative distance\n"
11174 "Administrative distance\n"
11175 "IP source prefix\n")
11176{
d62a17ae 11177 int idx_number = 1;
11178 int idx_ipv4_prefixlen = 2;
11179 bgp_distance_set(vty, argv[idx_number]->arg,
11180 argv[idx_ipv4_prefixlen]->arg, NULL);
11181 return CMD_SUCCESS;
718e3744 11182}
11183
11184DEFUN (no_bgp_distance_source,
11185 no_bgp_distance_source_cmd,
6147e2c6 11186 "no distance (1-255) A.B.C.D/M",
718e3744 11187 NO_STR
11188 "Define an administrative distance\n"
11189 "Administrative distance\n"
11190 "IP source prefix\n")
11191{
d62a17ae 11192 int idx_number = 2;
11193 int idx_ipv4_prefixlen = 3;
11194 bgp_distance_unset(vty, argv[idx_number]->arg,
11195 argv[idx_ipv4_prefixlen]->arg, NULL);
11196 return CMD_SUCCESS;
718e3744 11197}
11198
11199DEFUN (bgp_distance_source_access_list,
11200 bgp_distance_source_access_list_cmd,
6147e2c6 11201 "distance (1-255) A.B.C.D/M WORD",
718e3744 11202 "Define an administrative distance\n"
11203 "Administrative distance\n"
11204 "IP source prefix\n"
11205 "Access list name\n")
11206{
d62a17ae 11207 int idx_number = 1;
11208 int idx_ipv4_prefixlen = 2;
11209 int idx_word = 3;
11210 bgp_distance_set(vty, argv[idx_number]->arg,
11211 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
11212 return CMD_SUCCESS;
718e3744 11213}
11214
11215DEFUN (no_bgp_distance_source_access_list,
11216 no_bgp_distance_source_access_list_cmd,
6147e2c6 11217 "no distance (1-255) A.B.C.D/M WORD",
718e3744 11218 NO_STR
11219 "Define an administrative distance\n"
11220 "Administrative distance\n"
11221 "IP source prefix\n"
11222 "Access list name\n")
11223{
d62a17ae 11224 int idx_number = 2;
11225 int idx_ipv4_prefixlen = 3;
11226 int idx_word = 4;
11227 bgp_distance_unset(vty, argv[idx_number]->arg,
11228 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
11229 return CMD_SUCCESS;
718e3744 11230}
6b0655a2 11231
734b349e
MZ
11232DEFUN (ipv6_bgp_distance_source,
11233 ipv6_bgp_distance_source_cmd,
39e92c06 11234 "distance (1-255) X:X::X:X/M",
734b349e
MZ
11235 "Define an administrative distance\n"
11236 "Administrative distance\n"
11237 "IP source prefix\n")
11238{
d62a17ae 11239 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
11240 return CMD_SUCCESS;
734b349e
MZ
11241}
11242
11243DEFUN (no_ipv6_bgp_distance_source,
11244 no_ipv6_bgp_distance_source_cmd,
39e92c06 11245 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
11246 NO_STR
11247 "Define an administrative distance\n"
11248 "Administrative distance\n"
11249 "IP source prefix\n")
11250{
d62a17ae 11251 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
11252 return CMD_SUCCESS;
734b349e
MZ
11253}
11254
11255DEFUN (ipv6_bgp_distance_source_access_list,
11256 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 11257 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
11258 "Define an administrative distance\n"
11259 "Administrative distance\n"
11260 "IP source prefix\n"
11261 "Access list name\n")
11262{
d62a17ae 11263 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
11264 return CMD_SUCCESS;
734b349e
MZ
11265}
11266
11267DEFUN (no_ipv6_bgp_distance_source_access_list,
11268 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 11269 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
11270 NO_STR
11271 "Define an administrative distance\n"
11272 "Administrative distance\n"
11273 "IP source prefix\n"
11274 "Access list name\n")
11275{
d62a17ae 11276 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
11277 return CMD_SUCCESS;
734b349e
MZ
11278}
11279
718e3744 11280DEFUN (bgp_damp_set,
11281 bgp_damp_set_cmd,
31500417 11282 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 11283 "BGP Specific commands\n"
11284 "Enable route-flap dampening\n"
11285 "Half-life time for the penalty\n"
11286 "Value to start reusing a route\n"
11287 "Value to start suppressing a route\n"
11288 "Maximum duration to suppress a stable route\n")
11289{
d62a17ae 11290 VTY_DECLVAR_CONTEXT(bgp, bgp);
11291 int idx_half_life = 2;
11292 int idx_reuse = 3;
11293 int idx_suppress = 4;
11294 int idx_max_suppress = 5;
11295 int half = DEFAULT_HALF_LIFE * 60;
11296 int reuse = DEFAULT_REUSE;
11297 int suppress = DEFAULT_SUPPRESS;
11298 int max = 4 * half;
11299
11300 if (argc == 6) {
11301 half = atoi(argv[idx_half_life]->arg) * 60;
11302 reuse = atoi(argv[idx_reuse]->arg);
11303 suppress = atoi(argv[idx_suppress]->arg);
11304 max = atoi(argv[idx_max_suppress]->arg) * 60;
11305 } else if (argc == 3) {
11306 half = atoi(argv[idx_half_life]->arg) * 60;
11307 max = 4 * half;
11308 }
718e3744 11309
d62a17ae 11310 if (suppress < reuse) {
11311 vty_out(vty,
11312 "Suppress value cannot be less than reuse value \n");
11313 return 0;
11314 }
7ebe9748 11315
d62a17ae 11316 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
11317 reuse, suppress, max);
718e3744 11318}
11319
718e3744 11320DEFUN (bgp_damp_unset,
11321 bgp_damp_unset_cmd,
d04c479d 11322 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 11323 NO_STR
11324 "BGP Specific commands\n"
16cedbb0
QY
11325 "Enable route-flap dampening\n"
11326 "Half-life time for the penalty\n"
11327 "Value to start reusing a route\n"
11328 "Value to start suppressing a route\n"
11329 "Maximum duration to suppress a stable route\n")
718e3744 11330{
d62a17ae 11331 VTY_DECLVAR_CONTEXT(bgp, bgp);
11332 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 11333}
11334
718e3744 11335/* Display specified route of BGP table. */
d62a17ae 11336static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
11337 const char *ip_str, afi_t afi, safi_t safi,
11338 struct prefix_rd *prd, int prefix_check)
11339{
11340 int ret;
11341 struct prefix match;
11342 struct bgp_node *rn;
11343 struct bgp_node *rm;
40381db7
DS
11344 struct bgp_path_info *pi;
11345 struct bgp_path_info *pi_temp;
d62a17ae 11346 struct bgp *bgp;
11347 struct bgp_table *table;
11348
11349 /* BGP structure lookup. */
11350 if (view_name) {
11351 bgp = bgp_lookup_by_name(view_name);
11352 if (bgp == NULL) {
11353 vty_out(vty, "%% Can't find BGP instance %s\n",
11354 view_name);
11355 return CMD_WARNING;
11356 }
11357 } else {
11358 bgp = bgp_get_default();
11359 if (bgp == NULL) {
11360 vty_out(vty, "%% No BGP process is configured\n");
11361 return CMD_WARNING;
11362 }
718e3744 11363 }
718e3744 11364
d62a17ae 11365 /* Check IP address argument. */
11366 ret = str2prefix(ip_str, &match);
11367 if (!ret) {
11368 vty_out(vty, "%% address is malformed\n");
11369 return CMD_WARNING;
11370 }
718e3744 11371
d62a17ae 11372 match.family = afi2family(afi);
11373
11374 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
11375 || (safi == SAFI_EVPN)) {
11376 for (rn = bgp_table_top(bgp->rib[AFI_IP][safi]); rn;
11377 rn = bgp_route_next(rn)) {
11378 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
11379 continue;
ea47320b
DL
11380 if ((table = rn->info) == NULL)
11381 continue;
11382 if ((rm = bgp_node_match(table, &match)) == NULL)
11383 continue;
d62a17ae 11384
ea47320b
DL
11385 if (!prefix_check
11386 || rm->p.prefixlen == match.prefixlen) {
40381db7
DS
11387 pi = rm->info;
11388 while (pi) {
11389 if (pi->extra && pi->extra->damp_info) {
11390 pi_temp = pi->next;
ea47320b 11391 bgp_damp_info_free(
40381db7 11392 pi->extra->damp_info,
60466a63 11393 1);
40381db7 11394 pi = pi_temp;
ea47320b 11395 } else
40381db7 11396 pi = pi->next;
d62a17ae 11397 }
ea47320b
DL
11398 }
11399
11400 bgp_unlock_node(rm);
d62a17ae 11401 }
11402 } else {
11403 if ((rn = bgp_node_match(bgp->rib[afi][safi], &match))
11404 != NULL) {
11405 if (!prefix_check
11406 || rn->p.prefixlen == match.prefixlen) {
40381db7
DS
11407 pi = rn->info;
11408 while (pi) {
11409 if (pi->extra && pi->extra->damp_info) {
11410 pi_temp = pi->next;
d62a17ae 11411 bgp_damp_info_free(
40381db7 11412 pi->extra->damp_info,
d62a17ae 11413 1);
40381db7 11414 pi = pi_temp;
d62a17ae 11415 } else
40381db7 11416 pi = pi->next;
d62a17ae 11417 }
11418 }
11419
11420 bgp_unlock_node(rn);
11421 }
11422 }
718e3744 11423
d62a17ae 11424 return CMD_SUCCESS;
718e3744 11425}
11426
11427DEFUN (clear_ip_bgp_dampening,
11428 clear_ip_bgp_dampening_cmd,
11429 "clear ip bgp dampening",
11430 CLEAR_STR
11431 IP_STR
11432 BGP_STR
11433 "Clear route flap dampening information\n")
11434{
d62a17ae 11435 bgp_damp_info_clean();
11436 return CMD_SUCCESS;
718e3744 11437}
11438
11439DEFUN (clear_ip_bgp_dampening_prefix,
11440 clear_ip_bgp_dampening_prefix_cmd,
11441 "clear ip bgp dampening A.B.C.D/M",
11442 CLEAR_STR
11443 IP_STR
11444 BGP_STR
11445 "Clear route flap dampening information\n"
0c7b1b01 11446 "IPv4 prefix\n")
718e3744 11447{
d62a17ae 11448 int idx_ipv4_prefixlen = 4;
11449 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
11450 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 11451}
11452
11453DEFUN (clear_ip_bgp_dampening_address,
11454 clear_ip_bgp_dampening_address_cmd,
11455 "clear ip bgp dampening A.B.C.D",
11456 CLEAR_STR
11457 IP_STR
11458 BGP_STR
11459 "Clear route flap dampening information\n"
11460 "Network to clear damping information\n")
11461{
d62a17ae 11462 int idx_ipv4 = 4;
11463 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
11464 SAFI_UNICAST, NULL, 0);
718e3744 11465}
11466
11467DEFUN (clear_ip_bgp_dampening_address_mask,
11468 clear_ip_bgp_dampening_address_mask_cmd,
11469 "clear ip bgp dampening A.B.C.D A.B.C.D",
11470 CLEAR_STR
11471 IP_STR
11472 BGP_STR
11473 "Clear route flap dampening information\n"
11474 "Network to clear damping information\n"
11475 "Network mask\n")
11476{
d62a17ae 11477 int idx_ipv4 = 4;
11478 int idx_ipv4_2 = 5;
11479 int ret;
11480 char prefix_str[BUFSIZ];
718e3744 11481
d62a17ae 11482 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
11483 prefix_str);
11484 if (!ret) {
11485 vty_out(vty, "%% Inconsistent address and mask\n");
11486 return CMD_WARNING;
11487 }
718e3744 11488
d62a17ae 11489 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
11490 NULL, 0);
718e3744 11491}
6b0655a2 11492
825d9834
DS
11493static void show_bgp_peerhash_entry(struct hash_backet *backet, void *arg)
11494{
11495 struct vty *vty = arg;
11496 struct peer *peer = backet->data;
11497 char buf[SU_ADDRSTRLEN];
11498
11499 vty_out(vty, "\tPeer: %s %s\n", peer->host,
11500 sockunion2str(&peer->su, buf, sizeof(buf)));
11501}
11502
11503DEFUN (show_bgp_peerhash,
11504 show_bgp_peerhash_cmd,
11505 "show bgp peerhash",
11506 SHOW_STR
11507 BGP_STR
11508 "Display information about the BGP peerhash\n")
11509{
11510 struct list *instances = bm->bgp;
11511 struct listnode *node;
11512 struct bgp *bgp;
11513
11514 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
11515 vty_out(vty, "BGP: %s\n", bgp->name);
11516 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
11517 vty);
11518 }
11519
11520 return CMD_SUCCESS;
11521}
11522
587ff0fd 11523/* also used for encap safi */
2b791107
DL
11524static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
11525 afi_t afi, safi_t safi)
d62a17ae 11526{
11527 struct bgp_node *prn;
11528 struct bgp_node *rn;
11529 struct bgp_table *table;
11530 struct prefix *p;
11531 struct prefix_rd *prd;
11532 struct bgp_static *bgp_static;
11533 mpls_label_t label;
11534 char buf[SU_ADDRSTRLEN];
11535 char rdbuf[RD_ADDRSTRLEN];
11536
11537 /* Network configuration. */
11538 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b
DL
11539 prn = bgp_route_next(prn)) {
11540 if ((table = prn->info) == NULL)
11541 continue;
d62a17ae 11542
60466a63 11543 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
a78beeb5
DS
11544 bgp_static = bgp_static_get_node_info(rn);
11545 if (bgp_static == NULL)
ea47320b 11546 continue;
d62a17ae 11547
ea47320b
DL
11548 p = &rn->p;
11549 prd = (struct prefix_rd *)&prn->p;
d62a17ae 11550
ea47320b 11551 /* "network" configuration display. */
06b9f471 11552 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
11553 label = decode_label(&bgp_static->label);
11554
11555 vty_out(vty, " network %s/%d rd %s",
11556 inet_ntop(p->family, &p->u.prefix, buf,
11557 SU_ADDRSTRLEN),
11558 p->prefixlen, rdbuf);
11559 if (safi == SAFI_MPLS_VPN)
11560 vty_out(vty, " label %u", label);
11561
11562 if (bgp_static->rmap.name)
11563 vty_out(vty, " route-map %s",
11564 bgp_static->rmap.name);
e2a86ad9
DS
11565
11566 if (bgp_static->backdoor)
11567 vty_out(vty, " backdoor");
11568
ea47320b
DL
11569 vty_out(vty, "\n");
11570 }
11571 }
d62a17ae 11572}
11573
2b791107
DL
11574static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
11575 afi_t afi, safi_t safi)
d62a17ae 11576{
11577 struct bgp_node *prn;
11578 struct bgp_node *rn;
11579 struct bgp_table *table;
11580 struct prefix *p;
11581 struct prefix_rd *prd;
11582 struct bgp_static *bgp_static;
ff44f570 11583 char buf[PREFIX_STRLEN * 2];
d62a17ae 11584 char buf2[SU_ADDRSTRLEN];
11585 char rdbuf[RD_ADDRSTRLEN];
11586
11587 /* Network configuration. */
11588 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b
DL
11589 prn = bgp_route_next(prn)) {
11590 if ((table = prn->info) == NULL)
11591 continue;
d62a17ae 11592
60466a63 11593 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
a78beeb5
DS
11594 bgp_static = bgp_static_get_node_info(rn);
11595 if (bgp_static == NULL)
ea47320b 11596 continue;
d62a17ae 11597
ea47320b
DL
11598 char *macrouter = NULL;
11599 char *esi = NULL;
d62a17ae 11600
ea47320b
DL
11601 if (bgp_static->router_mac)
11602 macrouter = prefix_mac2str(
11603 bgp_static->router_mac, NULL, 0);
11604 if (bgp_static->eth_s_id)
11605 esi = esi2str(bgp_static->eth_s_id);
11606 p = &rn->p;
11607 prd = (struct prefix_rd *)&prn->p;
d62a17ae 11608
ea47320b 11609 /* "network" configuration display. */
06b9f471 11610 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
11611 if (p->u.prefix_evpn.route_type == 5) {
11612 char local_buf[PREFIX_STRLEN];
3714a385 11613 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
11614 struct prefix_evpn *)p)
11615 ? AF_INET
11616 : AF_INET6;
3714a385 11617 inet_ntop(family,
11618 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a
PZ
11619 local_buf, PREFIX_STRLEN);
11620 sprintf(buf, "%s/%u", local_buf,
3714a385 11621 p->u.prefix_evpn.prefix_addr.ip_prefix_length);
197cb530
PG
11622 } else {
11623 prefix2str(p, buf, sizeof(buf));
11624 }
ea47320b 11625
a4d82a8a
PZ
11626 if (bgp_static->gatewayIp.family == AF_INET
11627 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
11628 inet_ntop(bgp_static->gatewayIp.family,
11629 &bgp_static->gatewayIp.u.prefix, buf2,
11630 sizeof(buf2));
ea47320b 11631 vty_out(vty,
7bcc8dac 11632 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 11633 buf, rdbuf,
11634 p->u.prefix_evpn.prefix_addr.eth_tag,
60466a63 11635 decode_label(&bgp_static->label), esi, buf2,
ea47320b
DL
11636 macrouter);
11637
11638 if (macrouter)
11639 XFREE(MTYPE_TMP, macrouter);
11640 if (esi)
11641 XFREE(MTYPE_TMP, esi);
11642 }
11643 }
3da6fcd5
PG
11644}
11645
718e3744 11646/* Configuration of static route announcement and aggregate
11647 information. */
2b791107
DL
11648void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
11649 safi_t safi)
d62a17ae 11650{
11651 struct bgp_node *rn;
11652 struct prefix *p;
11653 struct bgp_static *bgp_static;
11654 struct bgp_aggregate *bgp_aggregate;
11655 char buf[SU_ADDRSTRLEN];
11656
2b791107
DL
11657 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
11658 bgp_config_write_network_vpn(vty, bgp, afi, safi);
11659 return;
11660 }
d62a17ae 11661
2b791107
DL
11662 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
11663 bgp_config_write_network_evpn(vty, bgp, afi, safi);
11664 return;
11665 }
d62a17ae 11666
11667 /* Network configuration. */
11668 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
ea47320b 11669 rn = bgp_route_next(rn)) {
a78beeb5
DS
11670 bgp_static = bgp_static_get_node_info(rn);
11671 if (bgp_static == NULL)
ea47320b 11672 continue;
d62a17ae 11673
ea47320b 11674 p = &rn->p;
d62a17ae 11675
ea47320b 11676 /* "network" configuration display. */
60466a63 11677 if (bgp_option_check(BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) {
d7c0a89a 11678 uint32_t destination;
ea47320b 11679 struct in_addr netmask;
d62a17ae 11680
ea47320b
DL
11681 destination = ntohl(p->u.prefix4.s_addr);
11682 masklen2ip(p->prefixlen, &netmask);
11683 vty_out(vty, " network %s",
11684 inet_ntop(p->family, &p->u.prefix, buf,
11685 SU_ADDRSTRLEN));
d62a17ae 11686
ea47320b
DL
11687 if ((IN_CLASSC(destination) && p->prefixlen == 24)
11688 || (IN_CLASSB(destination) && p->prefixlen == 16)
11689 || (IN_CLASSA(destination) && p->prefixlen == 8)
11690 || p->u.prefix4.s_addr == 0) {
11691 /* Natural mask is not display. */
11692 } else
11693 vty_out(vty, " mask %s", inet_ntoa(netmask));
11694 } else {
11695 vty_out(vty, " network %s/%d",
11696 inet_ntop(p->family, &p->u.prefix, buf,
11697 SU_ADDRSTRLEN),
11698 p->prefixlen);
11699 }
d62a17ae 11700
ea47320b
DL
11701 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
11702 vty_out(vty, " label-index %u",
11703 bgp_static->label_index);
d62a17ae 11704
ea47320b
DL
11705 if (bgp_static->rmap.name)
11706 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
11707
11708 if (bgp_static->backdoor)
11709 vty_out(vty, " backdoor");
718e3744 11710
ea47320b
DL
11711 vty_out(vty, "\n");
11712 }
11713
d62a17ae 11714 /* Aggregate-address configuration. */
11715 for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn;
ea47320b 11716 rn = bgp_route_next(rn)) {
b1e62edd
DS
11717 bgp_aggregate = bgp_aggregate_get_node_info(rn);
11718 if (bgp_aggregate == NULL)
ea47320b 11719 continue;
d62a17ae 11720
ea47320b 11721 p = &rn->p;
d62a17ae 11722
ea47320b
DL
11723 if (bgp_option_check(BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) {
11724 struct in_addr netmask;
d62a17ae 11725
ea47320b
DL
11726 masklen2ip(p->prefixlen, &netmask);
11727 vty_out(vty, " aggregate-address %s %s",
11728 inet_ntop(p->family, &p->u.prefix, buf,
11729 SU_ADDRSTRLEN),
11730 inet_ntoa(netmask));
11731 } else {
11732 vty_out(vty, " aggregate-address %s/%d",
11733 inet_ntop(p->family, &p->u.prefix, buf,
11734 SU_ADDRSTRLEN),
11735 p->prefixlen);
11736 }
d62a17ae 11737
ea47320b
DL
11738 if (bgp_aggregate->as_set)
11739 vty_out(vty, " as-set");
d62a17ae 11740
ea47320b
DL
11741 if (bgp_aggregate->summary_only)
11742 vty_out(vty, " summary-only");
718e3744 11743
ea47320b
DL
11744 vty_out(vty, "\n");
11745 }
d62a17ae 11746}
734b349e 11747
2b791107 11748void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 11749 safi_t safi)
d62a17ae 11750{
11751 struct bgp_node *rn;
11752 struct bgp_distance *bdistance;
11753
11754 /* Distance configuration. */
11755 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
11756 && bgp->distance_local[afi][safi]
11757 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
11758 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
11759 || bgp->distance_local[afi][safi]
11760 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 11761 vty_out(vty, " distance bgp %d %d %d\n",
11762 bgp->distance_ebgp[afi][safi],
11763 bgp->distance_ibgp[afi][safi],
11764 bgp->distance_local[afi][safi]);
11765 }
734b349e 11766
d62a17ae 11767 for (rn = bgp_table_top(bgp_distance_table[afi][safi]); rn;
ca2e160d
DS
11768 rn = bgp_route_next(rn)) {
11769 bdistance = bgp_distance_get_node(rn);
11770 if (bdistance != NULL) {
d62a17ae 11771 char buf[PREFIX_STRLEN];
11772
d62a17ae 11773 vty_out(vty, " distance %d %s %s\n",
11774 bdistance->distance,
11775 prefix2str(&rn->p, buf, sizeof(buf)),
11776 bdistance->access_list ? bdistance->access_list
11777 : "");
11778 }
ca2e160d 11779 }
718e3744 11780}
11781
11782/* Allocate routing table structure and install commands. */
d62a17ae 11783void bgp_route_init(void)
11784{
11785 afi_t afi;
11786 safi_t safi;
11787
11788 /* Init BGP distance table. */
05c7a1cc 11789 FOREACH_AFI_SAFI (afi, safi)
960035b2 11790 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 11791
11792 /* IPv4 BGP commands. */
11793 install_element(BGP_NODE, &bgp_table_map_cmd);
11794 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 11795 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 11796
11797 install_element(BGP_NODE, &aggregate_address_cmd);
11798 install_element(BGP_NODE, &aggregate_address_mask_cmd);
11799 install_element(BGP_NODE, &no_aggregate_address_cmd);
11800 install_element(BGP_NODE, &no_aggregate_address_mask_cmd);
11801
11802 /* IPv4 unicast configuration. */
11803 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
11804 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 11805 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 11806
11807 install_element(BGP_IPV4_NODE, &aggregate_address_cmd);
11808 install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd);
11809 install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd);
11810 install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
11811
11812 /* IPv4 multicast configuration. */
11813 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
11814 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 11815 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
d62a17ae 11816 install_element(BGP_IPV4M_NODE, &aggregate_address_cmd);
11817 install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
11818 install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd);
11819 install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
11820
11821 /* IPv4 labeled-unicast configuration. */
11822 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
11823 install_element(VIEW_NODE, &show_ip_bgp_cmd);
7b2ff250 11824 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 11825 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
11826 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
11827
11828 install_element(VIEW_NODE,
11829 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
11830 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
11831 install_element(VIEW_NODE,
11832 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 11833#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 11834 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 11835#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 11836 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
11837 install_element(VIEW_NODE,
11838 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd);
57d187bc 11839
d62a17ae 11840 /* BGP dampening clear commands */
11841 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
11842 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 11843
d62a17ae 11844 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
11845 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
11846
11847 /* prefix count */
11848 install_element(ENABLE_NODE,
11849 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 11850#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 11851 install_element(ENABLE_NODE,
11852 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 11853#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 11854
d62a17ae 11855 /* New config IPv6 BGP commands. */
11856 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
11857 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 11858 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 11859
11860 install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
11861 install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
11862
11863 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 11864
d62a17ae 11865 install_element(BGP_NODE, &bgp_distance_cmd);
11866 install_element(BGP_NODE, &no_bgp_distance_cmd);
11867 install_element(BGP_NODE, &bgp_distance_source_cmd);
11868 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
11869 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
11870 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
11871 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
11872 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
11873 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
11874 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
11875 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
11876 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
11877 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
11878 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
11879 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
11880 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
11881 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
11882 install_element(BGP_IPV4M_NODE,
11883 &no_bgp_distance_source_access_list_cmd);
11884 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
11885 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
11886 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
11887 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
11888 install_element(BGP_IPV6_NODE,
11889 &ipv6_bgp_distance_source_access_list_cmd);
11890 install_element(BGP_IPV6_NODE,
11891 &no_ipv6_bgp_distance_source_access_list_cmd);
11892 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
11893 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
11894 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
11895 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
11896 install_element(BGP_IPV6M_NODE,
11897 &ipv6_bgp_distance_source_access_list_cmd);
11898 install_element(BGP_IPV6M_NODE,
11899 &no_ipv6_bgp_distance_source_access_list_cmd);
11900
11901 install_element(BGP_NODE, &bgp_damp_set_cmd);
11902 install_element(BGP_NODE, &bgp_damp_unset_cmd);
11903 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
11904 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
11905
11906 /* IPv4 Multicast Mode */
11907 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
11908 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
11909
11910 /* Large Communities */
11911 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
11912 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
11913
11914 /* show bgp ipv4 flowspec detailed */
11915 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
11916
825d9834 11917 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 11918}
11919
11920void bgp_route_finish(void)
11921{
11922 afi_t afi;
11923 safi_t safi;
11924
05c7a1cc
QY
11925 FOREACH_AFI_SAFI (afi, safi) {
11926 bgp_table_unlock(bgp_distance_table[afi][safi]);
11927 bgp_distance_table[afi][safi] = NULL;
11928 }
228da428 11929}