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