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