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