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