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