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