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