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