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