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