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