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