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