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