1 /* BGP routing information
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
5 * This file is part of GNU Zebra.
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
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.
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
35 #include "sockunion.h"
38 #include "workqueue.h"
42 #include "lib_errors.h"
44 #include "bgpd/bgpd.h"
45 #include "bgpd/bgp_table.h"
46 #include "bgpd/bgp_route.h"
47 #include "bgpd/bgp_attr.h"
48 #include "bgpd/bgp_debug.h"
49 #include "bgpd/bgp_errors.h"
50 #include "bgpd/bgp_aspath.h"
51 #include "bgpd/bgp_regex.h"
52 #include "bgpd/bgp_community.h"
53 #include "bgpd/bgp_ecommunity.h"
54 #include "bgpd/bgp_lcommunity.h"
55 #include "bgpd/bgp_clist.h"
56 #include "bgpd/bgp_packet.h"
57 #include "bgpd/bgp_filter.h"
58 #include "bgpd/bgp_fsm.h"
59 #include "bgpd/bgp_mplsvpn.h"
60 #include "bgpd/bgp_nexthop.h"
61 #include "bgpd/bgp_damp.h"
62 #include "bgpd/bgp_advertise.h"
63 #include "bgpd/bgp_zebra.h"
64 #include "bgpd/bgp_vty.h"
65 #include "bgpd/bgp_mpath.h"
66 #include "bgpd/bgp_nht.h"
67 #include "bgpd/bgp_updgrp.h"
68 #include "bgpd/bgp_label.h"
69 #include "bgpd/bgp_addpath.h"
70 #include "bgpd/bgp_mac.h"
73 #include "bgpd/rfapi/rfapi_backend.h"
74 #include "bgpd/rfapi/vnc_import_bgp.h"
75 #include "bgpd/rfapi/vnc_export_bgp.h"
77 #include "bgpd/bgp_encap_types.h"
78 #include "bgpd/bgp_encap_tlv.h"
79 #include "bgpd/bgp_evpn.h"
80 #include "bgpd/bgp_evpn_vty.h"
81 #include "bgpd/bgp_flowspec.h"
82 #include "bgpd/bgp_flowspec_util.h"
83 #include "bgpd/bgp_pbr.h"
85 #ifndef VTYSH_EXTRACT_PL
86 #include "bgpd/bgp_route_clippy.c"
89 /* Extern from bgp_dump.c */
90 extern const char *bgp_origin_str
[];
91 extern const char *bgp_origin_long_str
[];
94 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
95 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
96 static const struct message bgp_pmsi_tnltype_str
[] = {
97 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
98 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
99 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
100 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
101 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
102 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
103 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
104 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
108 #define VRFID_NONE_STR "-"
110 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
111 safi_t safi
, struct prefix
*p
,
112 struct prefix_rd
*prd
)
115 struct bgp_node
*prn
= NULL
;
121 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
122 || (safi
== SAFI_EVPN
)) {
123 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
125 if (!bgp_node_has_bgp_path_info_data(prn
))
126 bgp_node_set_bgp_table_info(
127 prn
, bgp_table_init(table
->bgp
, afi
, safi
));
129 bgp_unlock_node(prn
);
130 table
= bgp_node_get_bgp_table_info(prn
);
133 rn
= bgp_node_get(table
, p
);
135 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
136 || (safi
== SAFI_EVPN
))
142 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
143 safi_t safi
, struct prefix
*p
,
144 struct prefix_rd
*prd
)
147 struct bgp_node
*prn
= NULL
;
152 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
153 || (safi
== SAFI_EVPN
)) {
154 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
158 if (!bgp_node_has_bgp_path_info_data(prn
)) {
159 bgp_unlock_node(prn
);
163 table
= bgp_node_get_bgp_table_info(prn
);
166 rn
= bgp_node_lookup(table
, p
);
171 /* Allocate bgp_path_info_extra */
172 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
174 struct bgp_path_info_extra
*new;
175 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
176 sizeof(struct bgp_path_info_extra
));
177 new->label
[0] = MPLS_INVALID_LABEL
;
179 new->bgp_fs_pbr
= NULL
;
180 new->bgp_fs_iprule
= NULL
;
184 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
186 struct bgp_path_info_extra
*e
;
188 if (!extra
|| !*extra
)
193 bgp_damp_info_free(e
->damp_info
, 0);
197 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
200 /* FIXME: since multiple e may have the same e->parent
201 * and e->parent->net is holding a refcount for each
202 * of them, we need to do some fudging here.
204 * WARNING: if bpi->net->lock drops to 0, bpi may be
205 * freed as well (because bpi->net was holding the
206 * last reference to bpi) => write after free!
210 bpi
= bgp_path_info_lock(bpi
);
211 refcount
= bpi
->net
->lock
- 1;
212 bgp_unlock_node((struct bgp_node
*)bpi
->net
);
215 bgp_path_info_unlock(bpi
);
217 bgp_path_info_unlock(e
->parent
);
222 bgp_unlock(e
->bgp_orig
);
224 if ((*extra
)->bgp_fs_iprule
)
225 list_delete(&((*extra
)->bgp_fs_iprule
));
226 if ((*extra
)->bgp_fs_pbr
)
227 list_delete(&((*extra
)->bgp_fs_pbr
));
228 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
233 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
234 * allocated if required.
236 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
239 pi
->extra
= bgp_path_info_extra_new();
243 /* Free bgp route information. */
244 static void bgp_path_info_free(struct bgp_path_info
*path
)
247 bgp_attr_unintern(&path
->attr
);
249 bgp_unlink_nexthop(path
);
250 bgp_path_info_extra_free(&path
->extra
);
251 bgp_path_info_mpath_free(&path
->mpath
);
253 bgp_addpath_free_info_data(&path
->tx_addpath
,
254 &path
->net
->tx_addpath
);
256 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
258 XFREE(MTYPE_BGP_ROUTE
, path
);
261 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
267 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
269 assert(path
&& path
->lock
> 0);
272 if (path
->lock
== 0) {
274 zlog_debug ("%s: unlocked and freeing", __func__
);
275 zlog_backtrace (LOG_DEBUG
);
277 bgp_path_info_free(path
);
284 zlog_debug ("%s: unlocked to 1", __func__
);
285 zlog_backtrace (LOG_DEBUG
);
292 void bgp_path_info_add(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
294 struct bgp_path_info
*top
;
296 top
= bgp_node_get_bgp_path_info(rn
);
302 bgp_node_set_bgp_path_info(rn
, pi
);
304 bgp_path_info_lock(pi
);
306 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
309 /* Do the actual removal of info from RIB, for use by bgp_process
310 completion callback *only* */
311 void bgp_path_info_reap(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
314 pi
->next
->prev
= pi
->prev
;
316 pi
->prev
->next
= pi
->next
;
318 bgp_node_set_bgp_path_info(rn
, pi
->next
);
320 bgp_path_info_mpath_dequeue(pi
);
321 bgp_path_info_unlock(pi
);
325 void bgp_path_info_delete(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
327 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_REMOVED
);
328 /* set of previous already took care of pcount */
329 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
332 /* undo the effects of a previous call to bgp_path_info_delete; typically
333 called when a route is deleted and then quickly re-added before the
334 deletion has been processed */
335 void bgp_path_info_restore(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
337 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_REMOVED
);
338 /* unset of previous already took care of pcount */
339 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
342 /* Adjust pcount as required */
343 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
345 struct bgp_table
*table
;
347 assert(rn
&& bgp_node_table(rn
));
348 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
350 table
= bgp_node_table(rn
);
352 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
355 if (!BGP_PATH_COUNTABLE(pi
)
356 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
358 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
360 /* slight hack, but more robust against errors. */
361 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
362 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
364 flog_err(EC_LIB_DEVELOPMENT
,
365 "Asked to decrement 0 prefix count for peer");
366 } else if (BGP_PATH_COUNTABLE(pi
)
367 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
368 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
369 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
373 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
374 struct bgp_path_info
*pi2
)
376 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
379 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
380 * This is here primarily to keep prefix-count in check.
382 void bgp_path_info_set_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
385 SET_FLAG(pi
->flags
, flag
);
387 /* early bath if we know it's not a flag that changes countability state
389 if (!CHECK_FLAG(flag
,
390 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
393 bgp_pcount_adjust(rn
, pi
);
396 void bgp_path_info_unset_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
399 UNSET_FLAG(pi
->flags
, flag
);
401 /* early bath if we know it's not a flag that changes countability state
403 if (!CHECK_FLAG(flag
,
404 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
407 bgp_pcount_adjust(rn
, pi
);
410 /* Get MED value. If MED value is missing and "bgp bestpath
411 missing-as-worst" is specified, treat it as the worst value. */
412 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
414 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
417 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
424 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
)
426 if (pi
->addpath_rx_id
)
427 sprintf(buf
, "path %s (addpath rxid %d)", pi
->peer
->host
,
430 sprintf(buf
, "path %s", pi
->peer
->host
);
433 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
435 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
436 struct bgp_path_info
*exist
, int *paths_eq
,
437 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
438 char *pfx_buf
, afi_t afi
, safi_t safi
,
439 enum bgp_path_selection_reason
*reason
)
441 struct attr
*newattr
, *existattr
;
442 bgp_peer_sort_t new_sort
;
443 bgp_peer_sort_t exist_sort
;
449 uint32_t exist_weight
;
450 uint32_t newm
, existm
;
451 struct in_addr new_id
;
452 struct in_addr exist_id
;
455 int internal_as_route
;
458 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
459 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
461 uint32_t exist_mm_seq
;
468 *reason
= bgp_path_selection_none
;
470 zlog_debug("%s: new is NULL", pfx_buf
);
475 bgp_path_info_path_with_addpath_rx_str(new, new_buf
);
478 *reason
= bgp_path_selection_first
;
480 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
486 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
);
487 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
488 pfx_buf
, new_buf
, new->flags
, exist_buf
,
493 existattr
= exist
->attr
;
495 /* For EVPN routes, we cannot just go by local vs remote, we have to
496 * look at the MAC mobility sequence number, if present.
498 if (safi
== SAFI_EVPN
) {
499 /* This is an error condition described in RFC 7432 Section
501 * states that in this scenario "the PE MUST alert the operator"
503 * does not state what other action to take. In order to provide
505 * consistency in this scenario we are going to prefer the path
509 if (newattr
->sticky
!= existattr
->sticky
) {
511 prefix2str(&new->net
->p
, pfx_buf
,
513 * PREFIX2STR_BUFFER
);
514 bgp_path_info_path_with_addpath_rx_str(new,
516 bgp_path_info_path_with_addpath_rx_str(
520 if (newattr
->sticky
&& !existattr
->sticky
) {
521 *reason
= bgp_path_selection_evpn_sticky_mac
;
524 "%s: %s wins over %s due to sticky MAC flag",
525 pfx_buf
, new_buf
, exist_buf
);
529 if (!newattr
->sticky
&& existattr
->sticky
) {
530 *reason
= bgp_path_selection_evpn_sticky_mac
;
533 "%s: %s loses to %s due to sticky MAC flag",
534 pfx_buf
, new_buf
, exist_buf
);
539 new_mm_seq
= mac_mobility_seqnum(newattr
);
540 exist_mm_seq
= mac_mobility_seqnum(existattr
);
542 if (new_mm_seq
> exist_mm_seq
) {
543 *reason
= bgp_path_selection_evpn_seq
;
546 "%s: %s wins over %s due to MM seq %u > %u",
547 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
552 if (new_mm_seq
< exist_mm_seq
) {
553 *reason
= bgp_path_selection_evpn_seq
;
556 "%s: %s loses to %s due to MM seq %u < %u",
557 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
563 * if sequence numbers are the same path with the lowest IP
566 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
568 *reason
= bgp_path_selection_evpn_lower_ip
;
571 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
572 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
573 inet_ntoa(new->attr
->nexthop
));
577 *reason
= bgp_path_selection_evpn_lower_ip
;
580 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
581 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
582 inet_ntoa(new->attr
->nexthop
));
587 /* 1. Weight check. */
588 new_weight
= newattr
->weight
;
589 exist_weight
= existattr
->weight
;
591 if (new_weight
> exist_weight
) {
592 *reason
= bgp_path_selection_weight
;
594 zlog_debug("%s: %s wins over %s due to weight %d > %d",
595 pfx_buf
, new_buf
, exist_buf
, new_weight
,
600 if (new_weight
< exist_weight
) {
601 *reason
= bgp_path_selection_weight
;
603 zlog_debug("%s: %s loses to %s due to weight %d < %d",
604 pfx_buf
, new_buf
, exist_buf
, new_weight
,
609 /* 2. Local preference check. */
610 new_pref
= exist_pref
= bgp
->default_local_pref
;
612 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
613 new_pref
= newattr
->local_pref
;
614 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
615 exist_pref
= existattr
->local_pref
;
617 if (new_pref
> exist_pref
) {
618 *reason
= bgp_path_selection_local_pref
;
621 "%s: %s wins over %s due to localpref %d > %d",
622 pfx_buf
, new_buf
, exist_buf
, new_pref
,
627 if (new_pref
< exist_pref
) {
628 *reason
= bgp_path_selection_local_pref
;
631 "%s: %s loses to %s due to localpref %d < %d",
632 pfx_buf
, new_buf
, exist_buf
, new_pref
,
637 /* 3. Local route check. We prefer:
639 * - BGP_ROUTE_AGGREGATE
640 * - BGP_ROUTE_REDISTRIBUTE
642 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
643 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
644 *reason
= bgp_path_selection_local_route
;
647 "%s: %s wins over %s due to preferred BGP_ROUTE type",
648 pfx_buf
, new_buf
, exist_buf
);
652 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
653 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
654 *reason
= bgp_path_selection_local_route
;
657 "%s: %s loses to %s due to preferred BGP_ROUTE type",
658 pfx_buf
, new_buf
, exist_buf
);
662 /* 4. AS path length check. */
663 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
664 int exist_hops
= aspath_count_hops(existattr
->aspath
);
665 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
667 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
670 aspath_hops
= aspath_count_hops(newattr
->aspath
);
671 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
673 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
674 *reason
= bgp_path_selection_confed_as_path
;
677 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
678 pfx_buf
, new_buf
, exist_buf
,
680 (exist_hops
+ exist_confeds
));
684 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
685 *reason
= bgp_path_selection_confed_as_path
;
688 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
689 pfx_buf
, new_buf
, exist_buf
,
691 (exist_hops
+ exist_confeds
));
695 int newhops
= aspath_count_hops(newattr
->aspath
);
697 if (newhops
< exist_hops
) {
698 *reason
= bgp_path_selection_as_path
;
701 "%s: %s wins over %s due to aspath hopcount %d < %d",
702 pfx_buf
, new_buf
, exist_buf
,
703 newhops
, exist_hops
);
707 if (newhops
> exist_hops
) {
708 *reason
= bgp_path_selection_as_path
;
711 "%s: %s loses to %s due to aspath hopcount %d > %d",
712 pfx_buf
, new_buf
, exist_buf
,
713 newhops
, exist_hops
);
719 /* 5. Origin check. */
720 if (newattr
->origin
< existattr
->origin
) {
721 *reason
= bgp_path_selection_origin
;
723 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
724 pfx_buf
, new_buf
, exist_buf
,
725 bgp_origin_long_str
[newattr
->origin
],
726 bgp_origin_long_str
[existattr
->origin
]);
730 if (newattr
->origin
> existattr
->origin
) {
731 *reason
= bgp_path_selection_origin
;
733 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
734 pfx_buf
, new_buf
, exist_buf
,
735 bgp_origin_long_str
[newattr
->origin
],
736 bgp_origin_long_str
[existattr
->origin
]);
741 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
742 && aspath_count_hops(existattr
->aspath
) == 0);
743 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
744 && aspath_count_confeds(existattr
->aspath
) > 0
745 && aspath_count_hops(newattr
->aspath
) == 0
746 && aspath_count_hops(existattr
->aspath
) == 0);
748 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
749 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
750 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
751 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
752 || internal_as_route
) {
753 new_med
= bgp_med_value(new->attr
, bgp
);
754 exist_med
= bgp_med_value(exist
->attr
, bgp
);
756 if (new_med
< exist_med
) {
757 *reason
= bgp_path_selection_med
;
760 "%s: %s wins over %s due to MED %d < %d",
761 pfx_buf
, new_buf
, exist_buf
, new_med
,
766 if (new_med
> exist_med
) {
767 *reason
= bgp_path_selection_med
;
770 "%s: %s loses to %s due to MED %d > %d",
771 pfx_buf
, new_buf
, exist_buf
, new_med
,
777 /* 7. Peer type check. */
778 new_sort
= new->peer
->sort
;
779 exist_sort
= exist
->peer
->sort
;
781 if (new_sort
== BGP_PEER_EBGP
782 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
783 *reason
= bgp_path_selection_peer
;
786 "%s: %s wins over %s due to eBGP peer > iBGP peer",
787 pfx_buf
, new_buf
, exist_buf
);
791 if (exist_sort
== BGP_PEER_EBGP
792 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
793 *reason
= bgp_path_selection_peer
;
796 "%s: %s loses to %s due to iBGP peer < eBGP peer",
797 pfx_buf
, new_buf
, exist_buf
);
801 /* 8. IGP metric check. */
805 newm
= new->extra
->igpmetric
;
807 existm
= exist
->extra
->igpmetric
;
812 "%s: %s wins over %s due to IGP metric %d < %d",
813 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
820 "%s: %s loses to %s due to IGP metric %d > %d",
821 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
825 /* 9. Same IGP metric. Compare the cluster list length as
826 representative of IGP hops metric. Rewrite the metric value
827 pair (newm, existm) with the cluster list length. Prefer the
828 path with smaller cluster list length. */
829 if (newm
== existm
) {
830 if (peer_sort(new->peer
) == BGP_PEER_IBGP
831 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
832 && (mpath_cfg
== NULL
834 mpath_cfg
->ibgp_flags
,
835 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
836 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
837 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
842 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
843 pfx_buf
, new_buf
, exist_buf
,
851 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
852 pfx_buf
, new_buf
, exist_buf
,
859 /* 10. confed-external vs. confed-internal */
860 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
861 if (new_sort
== BGP_PEER_CONFED
862 && exist_sort
== BGP_PEER_IBGP
) {
863 *reason
= bgp_path_selection_confed
;
866 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
867 pfx_buf
, new_buf
, exist_buf
);
871 if (exist_sort
== BGP_PEER_CONFED
872 && new_sort
== BGP_PEER_IBGP
) {
873 *reason
= bgp_path_selection_confed
;
876 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
877 pfx_buf
, new_buf
, exist_buf
);
882 /* 11. Maximum path check. */
883 if (newm
== existm
) {
884 /* If one path has a label but the other does not, do not treat
885 * them as equals for multipath
887 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
889 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
892 "%s: %s and %s cannot be multipath, one has a label while the other does not",
893 pfx_buf
, new_buf
, exist_buf
);
894 } else if (bgp_flag_check(bgp
,
895 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
898 * For the two paths, all comparison steps till IGP
900 * have succeeded - including AS_PATH hop count. Since
902 * bestpath as-path multipath-relax' knob is on, we
904 * an exact match of AS_PATH. Thus, mark the paths are
906 * That will trigger both these paths to get into the
914 "%s: %s and %s are equal via multipath-relax",
915 pfx_buf
, new_buf
, exist_buf
);
916 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
917 if (aspath_cmp(new->attr
->aspath
,
918 exist
->attr
->aspath
)) {
923 "%s: %s and %s are equal via matching aspaths",
924 pfx_buf
, new_buf
, exist_buf
);
926 } else if (new->peer
->as
== exist
->peer
->as
) {
931 "%s: %s and %s are equal via same remote-as",
932 pfx_buf
, new_buf
, exist_buf
);
936 * TODO: If unequal cost ibgp multipath is enabled we can
937 * mark the paths as equal here instead of returning
942 "%s: %s wins over %s after IGP metric comparison",
943 pfx_buf
, new_buf
, exist_buf
);
946 "%s: %s loses to %s after IGP metric comparison",
947 pfx_buf
, new_buf
, exist_buf
);
949 *reason
= bgp_path_selection_igp_metric
;
953 /* 12. If both paths are external, prefer the path that was received
954 first (the oldest one). This step minimizes route-flap, since a
955 newer path won't displace an older one, even if it was the
956 preferred route based on the additional decision criteria below. */
957 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
958 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
959 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
960 *reason
= bgp_path_selection_older
;
963 "%s: %s wins over %s due to oldest external",
964 pfx_buf
, new_buf
, exist_buf
);
968 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
969 *reason
= bgp_path_selection_older
;
972 "%s: %s loses to %s due to oldest external",
973 pfx_buf
, new_buf
, exist_buf
);
978 /* 13. Router-ID comparision. */
979 /* If one of the paths is "stale", the corresponding peer router-id will
980 * be 0 and would always win over the other path. If originator id is
981 * used for the comparision, it will decide which path is better.
983 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
984 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
986 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
987 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
988 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
990 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
992 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
993 *reason
= bgp_path_selection_router_id
;
996 "%s: %s wins over %s due to Router-ID comparison",
997 pfx_buf
, new_buf
, exist_buf
);
1001 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1002 *reason
= bgp_path_selection_router_id
;
1005 "%s: %s loses to %s due to Router-ID comparison",
1006 pfx_buf
, new_buf
, exist_buf
);
1010 /* 14. Cluster length comparision. */
1011 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1012 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1014 if (new_cluster
< exist_cluster
) {
1015 *reason
= bgp_path_selection_cluster_length
;
1018 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1019 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1024 if (new_cluster
> exist_cluster
) {
1025 *reason
= bgp_path_selection_cluster_length
;
1028 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1029 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1034 /* 15. Neighbor address comparision. */
1035 /* Do this only if neither path is "stale" as stale paths do not have
1036 * valid peer information (as the connection may or may not be up).
1038 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1039 *reason
= bgp_path_selection_stale
;
1042 "%s: %s wins over %s due to latter path being STALE",
1043 pfx_buf
, new_buf
, exist_buf
);
1047 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1048 *reason
= bgp_path_selection_stale
;
1051 "%s: %s loses to %s due to former path being STALE",
1052 pfx_buf
, new_buf
, exist_buf
);
1056 /* locally configured routes to advertise do not have su_remote */
1057 if (new->peer
->su_remote
== NULL
) {
1058 *reason
= bgp_path_selection_local_configured
;
1061 if (exist
->peer
->su_remote
== NULL
) {
1062 *reason
= bgp_path_selection_local_configured
;
1066 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1069 *reason
= bgp_path_selection_neighbor_ip
;
1072 "%s: %s loses to %s due to Neighor IP comparison",
1073 pfx_buf
, new_buf
, exist_buf
);
1078 *reason
= bgp_path_selection_neighbor_ip
;
1081 "%s: %s wins over %s due to Neighor IP comparison",
1082 pfx_buf
, new_buf
, exist_buf
);
1086 *reason
= bgp_path_selection_default
;
1088 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1089 pfx_buf
, new_buf
, exist_buf
);
1094 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1095 * is preferred, or 0 if they are the same (usually will only occur if
1096 * multipath is enabled
1097 * This version is compatible with */
1098 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1099 struct bgp_path_info
*exist
, char *pfx_buf
,
1100 afi_t afi
, safi_t safi
,
1101 enum bgp_path_selection_reason
*reason
)
1105 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1119 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1120 struct attr
*attr
, afi_t afi
,
1123 struct bgp_filter
*filter
;
1125 filter
= &peer
->filter
[afi
][safi
];
1127 #define FILTER_EXIST_WARN(F, f, filter) \
1128 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1129 zlog_debug("%s: Could not find configured input %s-list %s!", \
1130 peer->host, #f, F##_IN_NAME(filter));
1132 if (DISTRIBUTE_IN_NAME(filter
)) {
1133 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1135 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1139 if (PREFIX_LIST_IN_NAME(filter
)) {
1140 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1142 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1146 if (FILTER_LIST_IN_NAME(filter
)) {
1147 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1149 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1154 return FILTER_PERMIT
;
1155 #undef FILTER_EXIST_WARN
1158 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1159 struct attr
*attr
, afi_t afi
,
1162 struct bgp_filter
*filter
;
1164 filter
= &peer
->filter
[afi
][safi
];
1166 #define FILTER_EXIST_WARN(F, f, filter) \
1167 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1168 zlog_debug("%s: Could not find configured output %s-list %s!", \
1169 peer->host, #f, F##_OUT_NAME(filter));
1171 if (DISTRIBUTE_OUT_NAME(filter
)) {
1172 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1174 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1178 if (PREFIX_LIST_OUT_NAME(filter
)) {
1179 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1181 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1186 if (FILTER_LIST_OUT_NAME(filter
)) {
1187 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1189 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1194 return FILTER_PERMIT
;
1195 #undef FILTER_EXIST_WARN
1198 /* If community attribute includes no_export then return 1. */
1199 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1201 if (attr
->community
) {
1202 /* NO_ADVERTISE check. */
1203 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1206 /* NO_EXPORT check. */
1207 if (peer
->sort
== BGP_PEER_EBGP
1208 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1211 /* NO_EXPORT_SUBCONFED check. */
1212 if (peer
->sort
== BGP_PEER_EBGP
1213 || peer
->sort
== BGP_PEER_CONFED
)
1214 if (community_include(attr
->community
,
1215 COMMUNITY_NO_EXPORT_SUBCONFED
))
1221 /* Route reflection loop check. */
1222 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1224 struct in_addr cluster_id
;
1226 if (attr
->cluster
) {
1227 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1228 cluster_id
= peer
->bgp
->cluster_id
;
1230 cluster_id
= peer
->bgp
->router_id
;
1232 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1238 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1239 struct attr
*attr
, afi_t afi
, safi_t safi
,
1240 const char *rmap_name
)
1242 struct bgp_filter
*filter
;
1243 struct bgp_path_info rmap_path
;
1244 route_map_result_t ret
;
1245 struct route_map
*rmap
= NULL
;
1247 filter
= &peer
->filter
[afi
][safi
];
1249 /* Apply default weight value. */
1250 if (peer
->weight
[afi
][safi
])
1251 attr
->weight
= peer
->weight
[afi
][safi
];
1254 rmap
= route_map_lookup_by_name(rmap_name
);
1259 if (ROUTE_MAP_IN_NAME(filter
)) {
1260 rmap
= ROUTE_MAP_IN(filter
);
1267 /* Route map apply. */
1269 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1270 /* Duplicate current value to new strucutre for modification. */
1271 rmap_path
.peer
= peer
;
1272 rmap_path
.attr
= attr
;
1274 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1276 /* Apply BGP route map to the attribute. */
1277 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1279 peer
->rmap_type
= 0;
1281 if (ret
== RMAP_DENYMATCH
)
1287 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1288 struct attr
*attr
, afi_t afi
, safi_t safi
,
1289 const char *rmap_name
)
1291 struct bgp_path_info rmap_path
;
1292 route_map_result_t ret
;
1293 struct route_map
*rmap
= NULL
;
1297 * So if we get to this point and have no rmap_name
1298 * we want to just show the output as it currently
1304 /* Apply default weight value. */
1305 if (peer
->weight
[afi
][safi
])
1306 attr
->weight
= peer
->weight
[afi
][safi
];
1308 rmap
= route_map_lookup_by_name(rmap_name
);
1311 * If we have a route map name and we do not find
1312 * the routemap that means we have an implicit
1318 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1319 /* Route map apply. */
1320 /* Duplicate current value to new strucutre for modification. */
1321 rmap_path
.peer
= peer
;
1322 rmap_path
.attr
= attr
;
1324 rmap_type
= peer
->rmap_type
;
1325 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1327 /* Apply BGP route map to the attribute. */
1328 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1330 peer
->rmap_type
= rmap_type
;
1332 if (ret
== RMAP_DENYMATCH
)
1334 * caller has multiple error paths with bgp_attr_flush()
1341 /* If this is an EBGP peer with remove-private-AS */
1342 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1343 struct peer
*peer
, struct attr
*attr
)
1345 if (peer
->sort
== BGP_PEER_EBGP
1346 && (peer_af_flag_check(peer
, afi
, safi
,
1347 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1348 || peer_af_flag_check(peer
, afi
, safi
,
1349 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1350 || peer_af_flag_check(peer
, afi
, safi
,
1351 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1352 || peer_af_flag_check(peer
, afi
, safi
,
1353 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1354 // Take action on the entire aspath
1355 if (peer_af_flag_check(peer
, afi
, safi
,
1356 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1357 || peer_af_flag_check(peer
, afi
, safi
,
1358 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1359 if (peer_af_flag_check(
1361 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1362 attr
->aspath
= aspath_replace_private_asns(
1363 attr
->aspath
, bgp
->as
);
1365 // The entire aspath consists of private ASNs so create
1367 else if (aspath_private_as_check(attr
->aspath
))
1368 attr
->aspath
= aspath_empty_get();
1370 // There are some public and some private ASNs, remove
1373 attr
->aspath
= aspath_remove_private_asns(
1377 // 'all' was not specified so the entire aspath must be private
1379 // for us to do anything
1380 else if (aspath_private_as_check(attr
->aspath
)) {
1381 if (peer_af_flag_check(
1383 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1384 attr
->aspath
= aspath_replace_private_asns(
1385 attr
->aspath
, bgp
->as
);
1387 attr
->aspath
= aspath_empty_get();
1392 /* If this is an EBGP peer with as-override */
1393 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1394 struct peer
*peer
, struct attr
*attr
)
1396 if (peer
->sort
== BGP_PEER_EBGP
1397 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1398 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1399 attr
->aspath
= aspath_replace_specific_asn(
1400 attr
->aspath
, peer
->as
, bgp
->as
);
1404 void bgp_attr_add_gshut_community(struct attr
*attr
)
1406 struct community
*old
;
1407 struct community
*new;
1408 struct community
*merge
;
1409 struct community
*gshut
;
1411 old
= attr
->community
;
1412 gshut
= community_str2com("graceful-shutdown");
1417 merge
= community_merge(community_dup(old
), gshut
);
1419 if (old
->refcnt
== 0)
1420 community_free(&old
);
1422 new = community_uniq_sort(merge
);
1423 community_free(&merge
);
1425 new = community_dup(gshut
);
1428 community_free(&gshut
);
1429 attr
->community
= new;
1430 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1432 /* When we add the graceful-shutdown community we must also
1433 * lower the local-preference */
1434 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1435 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1439 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1441 if (family
== AF_INET
) {
1442 attr
->nexthop
.s_addr
= 0;
1443 attr
->mp_nexthop_global_in
.s_addr
= 0;
1445 if (family
== AF_INET6
)
1446 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1447 if (family
== AF_EVPN
)
1448 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1451 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
1452 struct update_subgroup
*subgrp
, struct prefix
*p
,
1455 struct bgp_filter
*filter
;
1458 struct peer
*onlypeer
;
1460 struct attr
*piattr
;
1461 char buf
[PREFIX_STRLEN
];
1467 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1469 if (DISABLE_BGP_ANNOUNCE
)
1472 afi
= SUBGRP_AFI(subgrp
);
1473 safi
= SUBGRP_SAFI(subgrp
);
1474 peer
= SUBGRP_PEER(subgrp
);
1476 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1477 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1480 filter
= &peer
->filter
[afi
][safi
];
1481 bgp
= SUBGRP_INST(subgrp
);
1482 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1486 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1487 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1488 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1491 * direct and direct_ext type routes originate internally even
1492 * though they can have peer pointers that reference other
1495 prefix2str(p
, buf
, PREFIX_STRLEN
);
1496 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1502 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1503 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1504 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1505 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1507 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1512 /* With addpath we may be asked to TX all kinds of paths so make sure
1514 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1515 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1516 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1520 /* If this is not the bestpath then check to see if there is an enabled
1522 * feature that requires us to advertise it */
1523 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1524 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1529 /* Aggregate-address suppress check. */
1530 if (pi
->extra
&& pi
->extra
->suppress
)
1531 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1536 * If we are doing VRF 2 VRF leaking via the import
1537 * statement, we want to prevent the route going
1538 * off box as that the RT and RD created are localy
1539 * significant and globaly useless.
1541 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1542 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1545 /* If it's labeled safi, make sure the route has a valid label. */
1546 if (safi
== SAFI_LABELED_UNICAST
) {
1547 mpls_label_t label
= bgp_adv_label(rn
, pi
, peer
, afi
, safi
);
1548 if (!bgp_is_valid_label(&label
)) {
1549 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1550 zlog_debug("u%" PRIu64
":s%" PRIu64
1551 " %s/%d is filtered - no label (%p)",
1552 subgrp
->update_group
->id
, subgrp
->id
,
1553 inet_ntop(p
->family
, &p
->u
.prefix
,
1554 buf
, SU_ADDRSTRLEN
),
1555 p
->prefixlen
, &label
);
1560 /* Do not send back route to sender. */
1561 if (onlypeer
&& from
== onlypeer
) {
1565 /* Do not send the default route in the BGP table if the neighbor is
1566 * configured for default-originate */
1567 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1568 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1569 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1571 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1575 /* Transparency check. */
1576 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1577 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1582 /* If community is not disabled check the no-export and local. */
1583 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1584 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1586 "subgrpannouncecheck: community filter check fail");
1590 /* If the attribute has originator-id and it is same as remote
1592 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1593 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1594 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1596 "%s [Update:SEND] %s originator-id is same as "
1599 prefix2str(p
, buf
, sizeof(buf
)));
1603 /* ORF prefix-list filter check */
1604 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1605 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1606 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1607 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1608 if (peer
->orf_plist
[afi
][safi
]) {
1609 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1611 if (bgp_debug_update(NULL
, p
,
1612 subgrp
->update_group
, 0))
1614 "%s [Update:SEND] %s is filtered via ORF",
1622 /* Output filter check. */
1623 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1624 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1625 zlog_debug("%s [Update:SEND] %s is filtered",
1626 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1630 #ifdef BGP_SEND_ASPATH_CHECK
1631 /* AS path loop check. */
1632 if (onlypeer
&& aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1633 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1635 "%s [Update:SEND] suppress announcement to peer AS %u "
1636 "that is part of AS path.",
1637 onlypeer
->host
, onlypeer
->as
);
1640 #endif /* BGP_SEND_ASPATH_CHECK */
1642 /* If we're a CONFED we need to loop check the CONFED ID too */
1643 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1644 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1645 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1647 "%s [Update:SEND] suppress announcement to peer AS %u"
1649 peer
->host
, bgp
->confed_id
);
1654 /* Route-Reflect check. */
1655 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1660 /* IBGP reflection check. */
1661 if (reflect
&& !samepeer_safe
) {
1662 /* A route from a Client peer. */
1663 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1664 PEER_FLAG_REFLECTOR_CLIENT
)) {
1665 /* Reflect to all the Non-Client peers and also to the
1666 Client peers other than the originator. Originator
1668 is already done. So there is noting to do. */
1669 /* no bgp client-to-client reflection check. */
1670 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1671 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1672 PEER_FLAG_REFLECTOR_CLIENT
))
1675 /* A route from a Non-client peer. Reflect to all other
1677 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1678 PEER_FLAG_REFLECTOR_CLIENT
))
1683 /* For modify attribute, copy it to temporary structure. */
1684 bgp_attr_dup(attr
, piattr
);
1686 /* If local-preference is not set. */
1687 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1688 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1689 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1690 attr
->local_pref
= bgp
->default_local_pref
;
1693 /* If originator-id is not set and the route is to be reflected,
1694 set the originator id */
1696 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1697 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1698 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1701 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1703 if (peer
->sort
== BGP_PEER_EBGP
1704 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1705 if (from
!= bgp
->peer_self
&& !transparent
1706 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1707 PEER_FLAG_MED_UNCHANGED
))
1709 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1712 /* Since the nexthop attribute can vary per peer, it is not explicitly
1714 * in announce check, only certain flags and length (or number of
1716 * -- for IPv6/MP_REACH) are set here in order to guide the update
1718 * code in setting the nexthop(s) on a per peer basis in
1720 * Typically, the source nexthop in the attribute is preserved but in
1722 * scenarios where we know it will always be overwritten, we reset the
1723 * nexthop to "0" in an attempt to achieve better Update packing. An
1724 * example of this is when a prefix from each of 2 IBGP peers needs to
1726 * announced to an EBGP peer (and they have the same attributes barring
1730 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1732 #define NEXTHOP_IS_V6 \
1733 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1734 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1735 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1736 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1738 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1740 * the peer (group) is configured to receive link-local nexthop
1742 * and it is available in the prefix OR we're not reflecting the route
1744 * the peer (group) to whom we're going to announce is on a shared
1746 * and this is either a self-originated route or the peer is EBGP.
1748 if (NEXTHOP_IS_V6
) {
1749 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1750 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1751 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1752 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1753 || (!reflect
&& peer
->shared_network
1754 && (from
== bgp
->peer_self
1755 || peer
->sort
== BGP_PEER_EBGP
))) {
1756 attr
->mp_nexthop_len
=
1757 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1760 /* Clear off link-local nexthop in source, whenever it is not
1762 * ensure more prefixes share the same attribute for
1765 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1766 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1767 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1770 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1771 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1773 /* Route map & unsuppress-map apply. */
1774 if (ROUTE_MAP_OUT_NAME(filter
) || (pi
->extra
&& pi
->extra
->suppress
)) {
1775 struct bgp_path_info rmap_path
;
1776 struct bgp_path_info_extra dummy_rmap_path_extra
;
1777 struct attr dummy_attr
;
1779 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1780 rmap_path
.peer
= peer
;
1781 rmap_path
.attr
= attr
;
1784 memcpy(&dummy_rmap_path_extra
, pi
->extra
,
1785 sizeof(struct bgp_path_info_extra
));
1786 rmap_path
.extra
= &dummy_rmap_path_extra
;
1789 /* don't confuse inbound and outbound setting */
1790 RESET_FLAG(attr
->rmap_change_flags
);
1793 * The route reflector is not allowed to modify the attributes
1794 * of the reflected IBGP routes unless explicitly allowed.
1796 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1797 && !bgp_flag_check(bgp
,
1798 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1799 bgp_attr_dup(&dummy_attr
, attr
);
1800 rmap_path
.attr
= &dummy_attr
;
1803 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1805 if (pi
->extra
&& pi
->extra
->suppress
)
1806 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1807 RMAP_BGP
, &rmap_path
);
1809 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1810 RMAP_BGP
, &rmap_path
);
1812 peer
->rmap_type
= 0;
1814 if (ret
== RMAP_DENYMATCH
) {
1815 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1816 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1817 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1819 bgp_attr_flush(attr
);
1824 /* RFC 8212 to prevent route leaks.
1825 * This specification intends to improve this situation by requiring the
1826 * explicit configuration of both BGP Import and Export Policies for any
1827 * External BGP (EBGP) session such as customers, peers, or
1828 * confederation boundaries for all enabled address families. Through
1829 * codification of the aforementioned requirement, operators will
1830 * benefit from consistent behavior across different BGP
1833 if (peer
->bgp
->ebgp_requires_policy
1834 == DEFAULT_EBGP_POLICY_ENABLED
)
1835 if (!bgp_outbound_policy_exists(peer
, filter
))
1838 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1839 if (peer
->sort
== BGP_PEER_IBGP
1840 || peer
->sort
== BGP_PEER_CONFED
) {
1841 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1842 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1844 bgp_attr_add_gshut_community(attr
);
1848 /* After route-map has been applied, we check to see if the nexthop to
1849 * be carried in the attribute (that is used for the announcement) can
1850 * be cleared off or not. We do this in all cases where we would be
1851 * setting the nexthop to "ourselves". For IPv6, we only need to
1853 * the global nexthop here; the link-local nexthop would have been
1855 * already, and if not, it is required by the update formation code.
1856 * Also see earlier comments in this function.
1859 * If route-map has performed some operation on the nexthop or the peer
1860 * configuration says to pass it unchanged, we cannot reset the nexthop
1861 * here, so only attempt to do it if these aren't true. Note that the
1862 * route-map handler itself might have cleared the nexthop, if for
1864 * it is configured as 'peer-address'.
1866 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1867 piattr
->rmap_change_flags
)
1869 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1870 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1871 /* We can reset the nexthop, if setting (or forcing) it to
1873 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1874 PEER_FLAG_NEXTHOP_SELF
)
1875 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1876 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1878 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1879 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1880 subgroup_announce_reset_nhop(
1881 (peer_cap_enhe(peer
, afi
, safi
)
1885 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1886 /* Can also reset the nexthop if announcing to EBGP, but
1888 * no peer in the subgroup is on a shared subnet.
1889 * Note: 3rd party nexthop currently implemented for
1892 if ((p
->family
== AF_INET
) &&
1893 (!bgp_subgrp_multiaccess_check_v4(
1896 subgroup_announce_reset_nhop(
1897 (peer_cap_enhe(peer
, afi
, safi
)
1902 if ((p
->family
== AF_INET6
) &&
1903 (!bgp_subgrp_multiaccess_check_v6(
1904 piattr
->mp_nexthop_global
,
1906 subgroup_announce_reset_nhop(
1907 (peer_cap_enhe(peer
, afi
, safi
)
1914 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
1916 * This flag is used for leaked vpn-vrf routes
1918 int family
= p
->family
;
1920 if (peer_cap_enhe(peer
, afi
, safi
))
1923 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1925 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
1926 __func__
, family2str(family
));
1927 subgroup_announce_reset_nhop(family
, attr
);
1930 /* If IPv6/MP and nexthop does not have any override and happens
1932 * be a link-local address, reset it so that we don't pass along
1934 * source's link-local IPv6 address to recipients who may not be
1936 * the same interface.
1938 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1939 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1940 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1947 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1948 struct bgp_maxpaths_cfg
*mpath_cfg
,
1949 struct bgp_path_info_pair
*result
, afi_t afi
,
1952 struct bgp_path_info
*new_select
;
1953 struct bgp_path_info
*old_select
;
1954 struct bgp_path_info
*pi
;
1955 struct bgp_path_info
*pi1
;
1956 struct bgp_path_info
*pi2
;
1957 struct bgp_path_info
*nextpi
= NULL
;
1958 int paths_eq
, do_mpath
, debug
;
1959 struct list mp_list
;
1960 char pfx_buf
[PREFIX2STR_BUFFER
];
1961 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1963 bgp_mp_list_init(&mp_list
);
1965 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1967 debug
= bgp_debug_bestpath(&rn
->p
);
1970 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1972 /* bgp deterministic-med */
1974 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1976 /* Clear BGP_PATH_DMED_SELECTED for all paths */
1977 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1979 bgp_path_info_unset_flag(rn
, pi1
,
1980 BGP_PATH_DMED_SELECTED
);
1982 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1984 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
1986 if (BGP_PATH_HOLDDOWN(pi1
))
1988 if (pi1
->peer
!= bgp
->peer_self
)
1989 if (pi1
->peer
->status
!= Established
)
1994 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
1995 if (CHECK_FLAG(pi2
->flags
,
1996 BGP_PATH_DMED_CHECK
))
1998 if (BGP_PATH_HOLDDOWN(pi2
))
2000 if (pi2
->peer
!= bgp
->peer_self
2003 PEER_STATUS_NSF_WAIT
))
2004 if (pi2
->peer
->status
2008 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2010 && !aspath_cmp_left_confed(
2015 if (bgp_path_info_cmp(
2016 bgp
, pi2
, new_select
,
2017 &paths_eq
, mpath_cfg
, debug
,
2020 bgp_path_info_unset_flag(
2022 BGP_PATH_DMED_SELECTED
);
2026 bgp_path_info_set_flag(
2027 rn
, pi2
, BGP_PATH_DMED_CHECK
);
2030 bgp_path_info_set_flag(rn
, new_select
,
2031 BGP_PATH_DMED_CHECK
);
2032 bgp_path_info_set_flag(rn
, new_select
,
2033 BGP_PATH_DMED_SELECTED
);
2036 bgp_path_info_path_with_addpath_rx_str(
2037 new_select
, path_buf
);
2038 zlog_debug("%s: %s is the bestpath from AS %u",
2040 aspath_get_first_as(
2041 new_select
->attr
->aspath
));
2046 /* Check old selected route and new selected route. */
2049 for (pi
= bgp_node_get_bgp_path_info(rn
);
2050 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2051 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2054 if (BGP_PATH_HOLDDOWN(pi
)) {
2055 /* reap REMOVED routes, if needs be
2056 * selected route must stay for a while longer though
2058 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2059 && (pi
!= old_select
))
2060 bgp_path_info_reap(rn
, pi
);
2063 zlog_debug("%s: pi %p in holddown", __func__
,
2069 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2070 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2071 if (pi
->peer
->status
!= Established
) {
2075 "%s: pi %p non self peer %s not estab state",
2076 __func__
, pi
, pi
->peer
->host
);
2081 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
2082 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2083 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2085 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2089 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2091 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2092 debug
, pfx_buf
, afi
, safi
, &rn
->reason
)) {
2097 /* Now that we know which path is the bestpath see if any of the other
2099 * qualify as multipaths
2103 bgp_path_info_path_with_addpath_rx_str(new_select
,
2106 sprintf(path_buf
, "NONE");
2108 "%s: After path selection, newbest is %s oldbest was %s",
2110 old_select
? old_select
->peer
->host
: "NONE");
2113 if (do_mpath
&& new_select
) {
2114 for (pi
= bgp_node_get_bgp_path_info(rn
);
2115 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2118 bgp_path_info_path_with_addpath_rx_str(
2121 if (pi
== new_select
) {
2124 "%s: %s is the bestpath, add to the multipath list",
2126 bgp_mp_list_add(&mp_list
, pi
);
2130 if (BGP_PATH_HOLDDOWN(pi
))
2133 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2134 && !CHECK_FLAG(pi
->peer
->sflags
,
2135 PEER_STATUS_NSF_WAIT
))
2136 if (pi
->peer
->status
!= Established
)
2139 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2142 "%s: %s has the same nexthop as the bestpath, skip it",
2147 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2148 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2154 "%s: %s is equivalent to the bestpath, add to the multipath list",
2156 bgp_mp_list_add(&mp_list
, pi
);
2161 bgp_path_info_mpath_update(rn
, new_select
, old_select
, &mp_list
,
2163 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2164 bgp_mp_list_clear(&mp_list
);
2166 bgp_addpath_update_ids(bgp
, rn
, afi
, safi
);
2168 result
->old
= old_select
;
2169 result
->new = new_select
;
2175 * A new route/change in bestpath of an existing route. Evaluate the path
2176 * for advertisement to the subgroup.
2178 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2179 struct bgp_path_info
*selected
,
2180 struct bgp_node
*rn
,
2181 uint32_t addpath_tx_id
)
2184 struct peer
*onlypeer
;
2190 afi
= SUBGRP_AFI(subgrp
);
2191 safi
= SUBGRP_SAFI(subgrp
);
2192 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2195 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2196 char buf_prefix
[PREFIX_STRLEN
];
2197 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2198 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2202 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2203 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2204 PEER_STATUS_ORF_WAIT_REFRESH
))
2207 memset(&attr
, 0, sizeof(struct attr
));
2208 /* It's initialized in bgp_announce_check() */
2210 /* Announcement to the subgroup. If the route is filtered withdraw it.
2213 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2214 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2216 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2220 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2222 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2229 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2230 * This is called at the end of route processing.
2232 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2234 struct bgp_path_info
*pi
;
2236 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2237 if (BGP_PATH_HOLDDOWN(pi
))
2239 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2240 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2245 * Has the route changed from the RIB's perspective? This is invoked only
2246 * if the route selection returns the same best route as earlier - to
2247 * determine if we need to update zebra or not.
2249 int bgp_zebra_has_route_changed(struct bgp_node
*rn
,
2250 struct bgp_path_info
*selected
)
2252 struct bgp_path_info
*mpinfo
;
2254 /* If this is multipath, check all selected paths for any nexthop
2255 * change or attribute change. Some attribute changes (e.g., community)
2256 * aren't of relevance to the RIB, but we'll update zebra to ensure
2257 * we handle the case of BGP nexthop change. This is the behavior
2258 * when the best path has an attribute change anyway.
2260 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2261 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
))
2265 * If this is multipath, check all selected paths for any nexthop change
2267 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2268 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2269 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2270 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2274 /* Nothing has changed from the RIB's perspective. */
2278 struct bgp_process_queue
{
2280 STAILQ_HEAD(, bgp_node
) pqueue
;
2281 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2283 unsigned int queued
;
2287 * old_select = The old best path
2288 * new_select = the new best path
2290 * if (!old_select && new_select)
2291 * We are sending new information on.
2293 * if (old_select && new_select) {
2294 * if (new_select != old_select)
2295 * We have a new best path send a change
2297 * We've received a update with new attributes that needs
2301 * if (old_select && !new_select)
2302 * We have no eligible route that we can announce or the rn
2305 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2306 afi_t afi
, safi_t safi
)
2308 struct bgp_path_info
*new_select
;
2309 struct bgp_path_info
*old_select
;
2310 struct bgp_path_info_pair old_and_new
;
2311 char pfx_buf
[PREFIX2STR_BUFFER
];
2314 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
2316 debug
= bgp_debug_bestpath(&rn
->p
);
2318 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2320 "%s: bgp delete in progress, ignoring event, p=%s",
2325 /* Is it end of initial update? (after startup) */
2327 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2328 sizeof(bgp
->update_delay_zebra_resume_time
));
2330 bgp
->main_zebra_update_hold
= 0;
2331 FOREACH_AFI_SAFI (afi
, safi
) {
2332 if (bgp_fibupd_safi(safi
))
2333 bgp_zebra_announce_table(bgp
, afi
, safi
);
2335 bgp
->main_peers_update_hold
= 0;
2337 bgp_start_routeadv(bgp
);
2341 struct prefix
*p
= &rn
->p
;
2343 debug
= bgp_debug_bestpath(&rn
->p
);
2345 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2346 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2347 afi2str(afi
), safi2str(safi
));
2350 /* Best path selection. */
2351 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2353 old_select
= old_and_new
.old
;
2354 new_select
= old_and_new
.new;
2356 /* Do we need to allocate or free labels?
2357 * Right now, since we only deal with per-prefix labels, it is not
2358 * necessary to do this upon changes to best path. Exceptions:
2359 * - label index has changed -> recalculate resulting label
2360 * - path_info sub_type changed -> switch to/from implicit-null
2361 * - no valid label (due to removed static label binding) -> get new one
2363 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2366 || bgp_label_index_differs(new_select
, old_select
)
2367 || new_select
->sub_type
!= old_select
->sub_type
2368 || !bgp_is_valid_label(&rn
->local_label
)) {
2369 /* Enforced penultimate hop popping:
2370 * implicit-null for local routes, aggregate
2371 * and redistributed routes
2373 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2374 || new_select
->sub_type
2375 == BGP_ROUTE_AGGREGATE
2376 || new_select
->sub_type
2377 == BGP_ROUTE_REDISTRIBUTE
) {
2380 BGP_NODE_REGISTERED_FOR_LABEL
))
2381 bgp_unregister_for_label(rn
);
2382 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2384 bgp_set_valid_label(&rn
->local_label
);
2386 bgp_register_for_label(rn
, new_select
);
2388 } else if (CHECK_FLAG(rn
->flags
,
2389 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2390 bgp_unregister_for_label(rn
);
2392 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2393 bgp_unregister_for_label(rn
);
2397 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2399 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2400 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2401 old_select
, new_select
);
2404 /* If best route remains the same and this is not due to user-initiated
2405 * clear, see exactly what needs to be done.
2407 if (old_select
&& old_select
== new_select
2408 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2409 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2410 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2411 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2413 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2414 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2416 if (bgp_fibupd_safi(safi
)
2417 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2419 if (new_select
->type
== ZEBRA_ROUTE_BGP
2420 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2421 || new_select
->sub_type
2422 == BGP_ROUTE_IMPORTED
))
2424 bgp_zebra_announce(rn
, p
, old_select
,
2428 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2429 bgp_zebra_clear_route_change_flags(rn
);
2431 /* If there is a change of interest to peers, reannounce the
2433 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2434 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2435 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2437 /* unicast routes must also be annouced to
2438 * labeled-unicast update-groups */
2439 if (safi
== SAFI_UNICAST
)
2440 group_announce_route(bgp
, afi
,
2441 SAFI_LABELED_UNICAST
, rn
,
2444 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2445 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2448 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2452 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2454 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2456 /* bestpath has changed; bump version */
2457 if (old_select
|| new_select
) {
2458 bgp_bump_version(rn
);
2460 if (!bgp
->t_rmap_def_originate_eval
) {
2464 update_group_refresh_default_originate_route_map
,
2465 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2466 &bgp
->t_rmap_def_originate_eval
);
2471 bgp_path_info_unset_flag(rn
, old_select
, BGP_PATH_SELECTED
);
2474 zlog_debug("%s: setting SELECTED flag", __func__
);
2475 bgp_path_info_set_flag(rn
, new_select
, BGP_PATH_SELECTED
);
2476 bgp_path_info_unset_flag(rn
, new_select
, BGP_PATH_ATTR_CHANGED
);
2477 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2481 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2482 if (old_select
!= new_select
) {
2484 vnc_import_bgp_exterior_del_route(bgp
, p
,
2486 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2489 vnc_import_bgp_exterior_add_route(bgp
, p
,
2491 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2497 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2499 /* unicast routes must also be annouced to labeled-unicast update-groups
2501 if (safi
== SAFI_UNICAST
)
2502 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2506 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2507 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2508 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2509 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2510 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2511 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2513 /* if this is an evpn imported type-5 prefix,
2514 * we need to withdraw the route first to clear
2515 * the nh neigh and the RMAC entry.
2518 is_route_parent_evpn(old_select
))
2519 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2521 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2523 /* Withdraw the route from the kernel. */
2524 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2525 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2526 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2527 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2529 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2533 /* advertise/withdraw type-5 routes */
2534 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2535 if (advertise_type5_routes(bgp
, afi
) &&
2537 is_route_injectable_into_evpn(new_select
)) {
2539 /* apply the route-map */
2540 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2543 ret
= route_map_apply(
2544 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2545 &rn
->p
, RMAP_BGP
, new_select
);
2546 if (ret
== RMAP_MATCH
)
2547 bgp_evpn_advertise_type5_route(
2548 bgp
, &rn
->p
, new_select
->attr
,
2551 bgp_evpn_withdraw_type5_route(
2552 bgp
, &rn
->p
, afi
, safi
);
2554 bgp_evpn_advertise_type5_route(bgp
,
2560 } else if (advertise_type5_routes(bgp
, afi
) &&
2562 is_route_injectable_into_evpn(old_select
))
2563 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2566 /* Clear any route change flags. */
2567 bgp_zebra_clear_route_change_flags(rn
);
2569 /* Reap old select bgp_path_info, if it has been removed */
2570 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2571 bgp_path_info_reap(rn
, old_select
);
2573 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2577 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2579 struct bgp_process_queue
*pqnode
= data
;
2580 struct bgp
*bgp
= pqnode
->bgp
;
2581 struct bgp_table
*table
;
2582 struct bgp_node
*rn
;
2585 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2586 bgp_process_main_one(bgp
, NULL
, 0, 0);
2587 /* should always have dedicated wq call */
2588 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2592 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2593 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2594 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2595 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2596 table
= bgp_node_table(rn
);
2597 /* note, new RNs may be added as part of processing */
2598 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2600 bgp_unlock_node(rn
);
2601 bgp_table_unlock(table
);
2607 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2609 struct bgp_process_queue
*pqnode
= data
;
2611 bgp_unlock(pqnode
->bgp
);
2613 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2616 void bgp_process_queue_init(void)
2618 if (!bm
->process_main_queue
)
2619 bm
->process_main_queue
=
2620 work_queue_new(bm
->master
, "process_main_queue");
2622 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2623 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2624 bm
->process_main_queue
->spec
.max_retries
= 0;
2625 bm
->process_main_queue
->spec
.hold
= 50;
2626 /* Use a higher yield value of 50ms for main queue processing */
2627 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2630 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2632 struct bgp_process_queue
*pqnode
;
2634 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2635 sizeof(struct bgp_process_queue
));
2637 /* unlocked in bgp_processq_del */
2638 pqnode
->bgp
= bgp_lock(bgp
);
2639 STAILQ_INIT(&pqnode
->pqueue
);
2644 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2646 #define ARBITRARY_PROCESS_QLEN 10000
2647 struct work_queue
*wq
= bm
->process_main_queue
;
2648 struct bgp_process_queue
*pqnode
;
2649 int pqnode_reuse
= 0;
2651 /* already scheduled for processing? */
2652 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2658 /* Add route nodes to an existing work queue item until reaching the
2659 limit only if is from the same BGP view and it's not an EOIU marker
2661 if (work_queue_item_count(wq
)) {
2662 struct work_queue_item
*item
= work_queue_last_item(wq
);
2663 pqnode
= item
->data
;
2665 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2666 || pqnode
->bgp
!= bgp
2667 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2668 pqnode
= bgp_processq_alloc(bgp
);
2672 pqnode
= bgp_processq_alloc(bgp
);
2673 /* all unlocked in bgp_process_wq */
2674 bgp_table_lock(bgp_node_table(rn
));
2676 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2679 /* can't be enqueued twice */
2680 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2681 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2685 work_queue_add(wq
, pqnode
);
2690 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2692 struct bgp_process_queue
*pqnode
;
2694 if (bm
->process_main_queue
== NULL
)
2697 pqnode
= bgp_processq_alloc(bgp
);
2699 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2700 work_queue_add(bm
->process_main_queue
, pqnode
);
2703 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2707 peer
= THREAD_ARG(thread
);
2708 peer
->t_pmax_restart
= NULL
;
2710 if (bgp_debug_neighbor_events(peer
))
2712 "%s Maximum-prefix restart timer expired, restore peering",
2715 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2716 zlog_debug("%s: %s peer_clear failed",
2717 __PRETTY_FUNCTION__
, peer
->host
);
2722 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2726 iana_safi_t pkt_safi
;
2728 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2731 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2732 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2733 PEER_STATUS_PREFIX_LIMIT
)
2738 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2740 afi_safi_print(afi
, safi
), peer
->host
,
2741 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2742 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2744 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2745 PEER_FLAG_MAX_PREFIX_WARNING
))
2748 /* Convert AFI, SAFI to values for packet. */
2749 pkt_afi
= afi_int2iana(afi
);
2750 pkt_safi
= safi_int2iana(safi
);
2754 ndata
[0] = (pkt_afi
>> 8);
2756 ndata
[2] = pkt_safi
;
2757 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2758 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2759 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2760 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2762 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2763 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2764 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2768 /* Dynamic peers will just close their connection. */
2769 if (peer_dynamic_neighbor(peer
))
2772 /* restart timer start */
2773 if (peer
->pmax_restart
[afi
][safi
]) {
2774 peer
->v_pmax_restart
=
2775 peer
->pmax_restart
[afi
][safi
] * 60;
2777 if (bgp_debug_neighbor_events(peer
))
2779 "%s Maximum-prefix restart timer started for %d secs",
2780 peer
->host
, peer
->v_pmax_restart
);
2782 BGP_TIMER_ON(peer
->t_pmax_restart
,
2783 bgp_maximum_prefix_restart_timer
,
2784 peer
->v_pmax_restart
);
2789 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2790 PEER_STATUS_PREFIX_LIMIT
);
2792 if (peer
->pcount
[afi
][safi
]
2793 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2794 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2795 PEER_STATUS_PREFIX_THRESHOLD
)
2800 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2801 afi_safi_print(afi
, safi
), peer
->host
,
2802 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2803 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2804 PEER_STATUS_PREFIX_THRESHOLD
);
2806 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2807 PEER_STATUS_PREFIX_THRESHOLD
);
2811 /* Unconditionally remove the route from the RIB, without taking
2812 * damping into consideration (eg, because the session went down)
2814 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2815 struct peer
*peer
, afi_t afi
, safi_t safi
)
2817 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
2819 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
2820 bgp_path_info_delete(rn
, pi
); /* keep historical info */
2822 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2825 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2826 struct peer
*peer
, afi_t afi
, safi_t safi
,
2827 struct prefix_rd
*prd
)
2829 /* apply dampening, if result is suppressed, we'll be retaining
2830 * the bgp_path_info in the RIB for historical reference.
2832 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2833 && peer
->sort
== BGP_PEER_EBGP
)
2834 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
2835 == BGP_DAMP_SUPPRESSED
) {
2836 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
2842 if (safi
== SAFI_MPLS_VPN
) {
2843 struct bgp_node
*prn
= NULL
;
2844 struct bgp_table
*table
= NULL
;
2846 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2847 (struct prefix
*)prd
);
2848 if (bgp_node_has_bgp_path_info_data(prn
)) {
2849 table
= bgp_node_get_bgp_table_info(prn
);
2851 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2852 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
2854 bgp_unlock_node(prn
);
2856 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2857 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
2859 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
2860 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2866 /* If this is an EVPN route, process for un-import. */
2867 if (safi
== SAFI_EVPN
)
2868 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
2870 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
2873 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2874 struct peer
*peer
, struct attr
*attr
,
2875 struct bgp_node
*rn
)
2877 struct bgp_path_info
*new;
2879 /* Make new BGP info. */
2880 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
2882 new->instance
= instance
;
2883 new->sub_type
= sub_type
;
2886 new->uptime
= bgp_clock();
2891 static void overlay_index_update(struct attr
*attr
,
2892 struct eth_segment_id
*eth_s_id
,
2893 union gw_addr
*gw_ip
)
2898 if (eth_s_id
== NULL
) {
2899 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2900 sizeof(struct eth_segment_id
));
2902 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2903 sizeof(struct eth_segment_id
));
2905 if (gw_ip
== NULL
) {
2906 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2908 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2909 sizeof(union gw_addr
));
2913 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
2914 struct eth_segment_id
*eth_s_id
,
2915 union gw_addr
*gw_ip
)
2917 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
2918 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
2920 struct eth_segment_id esi
;
2924 if (afi
!= AFI_L2VPN
)
2927 memset(&temp
, 0, sizeof(temp
));
2928 path_eth_s_id
= &temp
.esi
;
2929 path_gw_ip
= &temp
.ip
;
2931 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2934 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
2935 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
2938 if (gw_ip
== NULL
) {
2939 memset(&temp
, 0, sizeof(temp
));
2940 path_gw_ip_remote
= &temp
.ip
;
2942 path_gw_ip_remote
= gw_ip
;
2944 if (eth_s_id
== NULL
) {
2945 memset(&temp
, 0, sizeof(temp
));
2946 path_eth_s_id_remote
= &temp
.esi
;
2948 path_eth_s_id_remote
= eth_s_id
;
2950 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
2953 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
2954 sizeof(struct eth_segment_id
));
2957 /* Check if received nexthop is valid or not. */
2958 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2963 /* Only validated for unicast and multicast currently. */
2964 /* Also valid for EVPN where the nexthop is an IP address. */
2965 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2968 /* If NEXT_HOP is present, validate it. */
2969 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2970 if (attr
->nexthop
.s_addr
== 0
2971 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2972 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2976 /* If MP_NEXTHOP is present, validate it. */
2977 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2978 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2979 * it is not an IPv6 link-local address.
2981 if (attr
->mp_nexthop_len
) {
2982 switch (attr
->mp_nexthop_len
) {
2983 case BGP_ATTR_NHLEN_IPV4
:
2984 case BGP_ATTR_NHLEN_VPNV4
:
2985 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2986 || IPV4_CLASS_DE(ntohl(
2987 attr
->mp_nexthop_global_in
.s_addr
))
2988 || bgp_nexthop_self(bgp
,
2989 attr
->mp_nexthop_global_in
));
2992 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2993 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2994 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2995 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2996 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2997 || IN6_IS_ADDR_MULTICAST(
2998 &attr
->mp_nexthop_global
));
3010 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3011 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3012 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3013 uint32_t num_labels
, int soft_reconfig
,
3014 struct bgp_route_evpn
*evpn
)
3017 int aspath_loop_count
= 0;
3018 struct bgp_node
*rn
;
3020 struct attr new_attr
;
3021 struct attr
*attr_new
;
3022 struct bgp_path_info
*pi
;
3023 struct bgp_path_info
*new;
3024 struct bgp_path_info_extra
*extra
;
3026 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3028 int do_loop_check
= 1;
3029 int has_valid_label
= 0;
3031 int vnc_implicit_withdraw
= 0;
3035 memset(&new_attr
, 0, sizeof(struct attr
));
3036 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3037 new_attr
.label
= MPLS_INVALID_LABEL
;
3040 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3041 /* TODO: Check to see if we can get rid of "is_valid_label" */
3042 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3043 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3045 has_valid_label
= bgp_is_valid_label(label
);
3047 /* When peer's soft reconfiguration enabled. Record input packet in
3050 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3051 && peer
!= bgp
->peer_self
)
3052 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
3054 /* Check previously received route. */
3055 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3056 if (pi
->peer
== peer
&& pi
->type
== type
3057 && pi
->sub_type
== sub_type
3058 && pi
->addpath_rx_id
== addpath_id
)
3061 /* AS path local-as loop check. */
3062 if (peer
->change_local_as
) {
3063 if (peer
->allowas_in
[afi
][safi
])
3064 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3065 else if (!CHECK_FLAG(peer
->flags
,
3066 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3067 aspath_loop_count
= 1;
3069 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3070 > aspath_loop_count
) {
3071 reason
= "as-path contains our own AS;";
3076 /* If the peer is configured for "allowas-in origin" and the last ASN in
3078 * as-path is our ASN then we do not need to call aspath_loop_check
3080 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3081 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3084 /* AS path loop check. */
3085 if (do_loop_check
) {
3086 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3087 > peer
->allowas_in
[afi
][safi
]
3088 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3089 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3090 > peer
->allowas_in
[afi
][safi
])) {
3091 reason
= "as-path contains our own AS;";
3096 /* Route reflector originator ID check. */
3097 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3098 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3099 reason
= "originator is us;";
3103 /* Route reflector cluster ID check. */
3104 if (bgp_cluster_filter(peer
, attr
)) {
3105 reason
= "reflected from the same cluster;";
3109 /* Apply incoming filter. */
3110 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3115 /* RFC 8212 to prevent route leaks.
3116 * This specification intends to improve this situation by requiring the
3117 * explicit configuration of both BGP Import and Export Policies for any
3118 * External BGP (EBGP) session such as customers, peers, or
3119 * confederation boundaries for all enabled address families. Through
3120 * codification of the aforementioned requirement, operators will
3121 * benefit from consistent behavior across different BGP
3124 if (peer
->bgp
->ebgp_requires_policy
== DEFAULT_EBGP_POLICY_ENABLED
)
3125 if (!bgp_inbound_policy_exists(peer
,
3126 &peer
->filter
[afi
][safi
])) {
3127 reason
= "inbound policy missing";
3131 bgp_attr_dup(&new_attr
, attr
);
3133 /* Apply incoming route-map.
3134 * NB: new_attr may now contain newly allocated values from route-map
3136 * commands, so we need bgp_attr_flush in the error paths, until we
3138 * the attr (which takes over the memory references) */
3139 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
3141 reason
= "route-map;";
3142 bgp_attr_flush(&new_attr
);
3146 if (peer
->sort
== BGP_PEER_EBGP
) {
3148 /* If we receive the graceful-shutdown community from an eBGP
3149 * peer we must lower local-preference */
3150 if (new_attr
.community
3151 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3152 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3153 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3155 /* If graceful-shutdown is configured then add the GSHUT
3156 * community to all paths received from eBGP peers */
3157 } else if (bgp_flag_check(peer
->bgp
,
3158 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3159 bgp_attr_add_gshut_community(&new_attr
);
3163 /* next hop check. */
3164 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3165 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
3166 reason
= "martian or self next-hop;";
3167 bgp_attr_flush(&new_attr
);
3171 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3172 reason
= "self mac;";
3176 attr_new
= bgp_attr_intern(&new_attr
);
3178 /* If the update is implicit withdraw. */
3180 pi
->uptime
= bgp_clock();
3181 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3183 /* Same attribute comes in. */
3184 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3185 && attrhash_cmp(pi
->attr
, attr_new
)
3186 && (!has_valid_label
3187 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3188 num_labels
* sizeof(mpls_label_t
))
3190 && (overlay_index_equal(
3191 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3192 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3193 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3194 BGP_CONFIG_DAMPENING
)
3195 && peer
->sort
== BGP_PEER_EBGP
3196 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3197 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3198 bgp_debug_rdpfxpath2str(
3199 afi
, safi
, prd
, p
, label
,
3200 num_labels
, addpath_id
? 1 : 0,
3201 addpath_id
, pfx_buf
,
3203 zlog_debug("%s rcvd %s", peer
->host
,
3207 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3208 != BGP_DAMP_SUPPRESSED
) {
3209 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3211 bgp_process(bgp
, rn
, afi
, safi
);
3213 } else /* Duplicate - odd */
3215 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3216 if (!peer
->rcvd_attr_printed
) {
3218 "%s rcvd UPDATE w/ attr: %s",
3220 peer
->rcvd_attr_str
);
3221 peer
->rcvd_attr_printed
= 1;
3224 bgp_debug_rdpfxpath2str(
3225 afi
, safi
, prd
, p
, label
,
3226 num_labels
, addpath_id
? 1 : 0,
3227 addpath_id
, pfx_buf
,
3230 "%s rcvd %s...duplicate ignored",
3231 peer
->host
, pfx_buf
);
3234 /* graceful restart STALE flag unset. */
3235 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3236 bgp_path_info_unset_flag(
3237 rn
, pi
, BGP_PATH_STALE
);
3238 bgp_process(bgp
, rn
, afi
, safi
);
3242 bgp_unlock_node(rn
);
3243 bgp_attr_unintern(&attr_new
);
3248 /* Withdraw/Announce before we fully processed the withdraw */
3249 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3250 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3251 bgp_debug_rdpfxpath2str(
3252 afi
, safi
, prd
, p
, label
, num_labels
,
3253 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3256 "%s rcvd %s, flapped quicker than processing",
3257 peer
->host
, pfx_buf
);
3260 bgp_path_info_restore(rn
, pi
);
3263 /* Received Logging. */
3264 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3265 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3266 num_labels
, addpath_id
? 1 : 0,
3267 addpath_id
, pfx_buf
,
3269 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3272 /* graceful restart STALE flag unset. */
3273 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
3274 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3276 /* The attribute is changed. */
3277 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3279 /* implicit withdraw, decrement aggregate and pcount here.
3280 * only if update is accepted, they'll increment below.
3282 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3284 /* Update bgp route dampening information. */
3285 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3286 && peer
->sort
== BGP_PEER_EBGP
) {
3287 /* This is implicit withdraw so we should update
3290 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3291 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3294 if (safi
== SAFI_MPLS_VPN
) {
3295 struct bgp_node
*prn
= NULL
;
3296 struct bgp_table
*table
= NULL
;
3298 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3299 (struct prefix
*)prd
);
3300 if (bgp_node_has_bgp_path_info_data(prn
)) {
3301 table
= bgp_node_get_bgp_table_info(prn
);
3303 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3304 bgp
, prd
, table
, p
, pi
);
3306 bgp_unlock_node(prn
);
3308 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3309 && (safi
== SAFI_UNICAST
)) {
3310 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3312 * Implicit withdraw case.
3314 ++vnc_implicit_withdraw
;
3315 vnc_import_bgp_del_route(bgp
, p
, pi
);
3316 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3321 /* Special handling for EVPN update of an existing route. If the
3322 * extended community attribute has changed, we need to
3324 * the route using its existing extended community. It will be
3325 * subsequently processed for import with the new extended
3328 if (safi
== SAFI_EVPN
&& !same_attr
) {
3330 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3332 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3335 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3336 attr_new
->ecommunity
);
3338 if (bgp_debug_update(peer
, p
, NULL
, 1))
3340 "Change in EXT-COMM, existing %s new %s",
3342 pi
->attr
->ecommunity
),
3344 attr_new
->ecommunity
));
3345 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3351 /* Update to new attribute. */
3352 bgp_attr_unintern(&pi
->attr
);
3353 pi
->attr
= attr_new
;
3355 /* Update MPLS label */
3356 if (has_valid_label
) {
3357 extra
= bgp_path_info_extra_get(pi
);
3358 if (extra
->label
!= label
) {
3359 memcpy(&extra
->label
, label
,
3360 num_labels
* sizeof(mpls_label_t
));
3361 extra
->num_labels
= num_labels
;
3363 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3364 bgp_set_valid_label(&extra
->label
[0]);
3368 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3369 && (safi
== SAFI_UNICAST
)) {
3370 if (vnc_implicit_withdraw
) {
3372 * Add back the route with its new attributes
3374 * The route is still selected, until the route
3376 * queued by bgp_process actually runs. We have
3378 * update to the VNC side immediately to avoid
3380 * configuration changes (e.g., route-map
3382 * trigger re-importation of the entire RIB.
3384 vnc_import_bgp_add_route(bgp
, p
, pi
);
3385 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3389 /* Update Overlay Index */
3390 if (afi
== AFI_L2VPN
) {
3391 overlay_index_update(
3392 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3393 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3396 /* Update bgp route dampening information. */
3397 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3398 && peer
->sort
== BGP_PEER_EBGP
) {
3399 /* Now we do normal update dampening. */
3400 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3401 if (ret
== BGP_DAMP_SUPPRESSED
) {
3402 bgp_unlock_node(rn
);
3407 /* Nexthop reachability check - for unicast and
3408 * labeled-unicast.. */
3409 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3410 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3411 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3412 && !CHECK_FLAG(peer
->flags
,
3413 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3415 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3420 struct bgp
*bgp_nexthop
= bgp
;
3422 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3423 bgp_nexthop
= pi
->extra
->bgp_orig
;
3425 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
, pi
,
3427 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3428 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3430 if (BGP_DEBUG(nht
, NHT
)) {
3431 char buf1
[INET6_ADDRSTRLEN
];
3433 (const void *)&attr_new
3435 buf1
, INET6_ADDRSTRLEN
);
3436 zlog_debug("%s(%s): NH unresolved",
3437 __FUNCTION__
, buf1
);
3439 bgp_path_info_unset_flag(rn
, pi
,
3443 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3446 if (safi
== SAFI_MPLS_VPN
) {
3447 struct bgp_node
*prn
= NULL
;
3448 struct bgp_table
*table
= NULL
;
3450 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3451 (struct prefix
*)prd
);
3452 if (bgp_node_has_bgp_path_info_data(prn
)) {
3453 table
= bgp_node_get_bgp_table_info(prn
);
3455 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3456 bgp
, prd
, table
, p
, pi
);
3458 bgp_unlock_node(prn
);
3462 /* If this is an EVPN route and some attribute has changed,
3464 * route for import. If the extended community has changed, we
3466 * have done the un-import earlier and the import would result
3468 * route getting injected into appropriate L2 VNIs. If it is
3470 * some other attribute change, the import will result in
3472 * the attributes for the route in the VNI(s).
3474 if (safi
== SAFI_EVPN
&& !same_attr
)
3475 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3477 /* Process change. */
3478 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3480 bgp_process(bgp
, rn
, afi
, safi
);
3481 bgp_unlock_node(rn
);
3483 if (SAFI_UNICAST
== safi
3484 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3485 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3487 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3489 if ((SAFI_MPLS_VPN
== safi
)
3490 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3492 vpn_leak_to_vrf_update(bgp
, pi
);
3496 if (SAFI_MPLS_VPN
== safi
) {
3497 mpls_label_t label_decoded
= decode_label(label
);
3499 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3500 type
, sub_type
, &label_decoded
);
3502 if (SAFI_ENCAP
== safi
) {
3503 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3504 type
, sub_type
, NULL
);
3509 } // End of implicit withdraw
3511 /* Received Logging. */
3512 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3513 if (!peer
->rcvd_attr_printed
) {
3514 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3515 peer
->rcvd_attr_str
);
3516 peer
->rcvd_attr_printed
= 1;
3519 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3520 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3522 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3525 /* Make new BGP info. */
3526 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3528 /* Update MPLS label */
3529 if (has_valid_label
) {
3530 extra
= bgp_path_info_extra_get(new);
3531 if (extra
->label
!= label
) {
3532 memcpy(&extra
->label
, label
,
3533 num_labels
* sizeof(mpls_label_t
));
3534 extra
->num_labels
= num_labels
;
3536 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3537 bgp_set_valid_label(&extra
->label
[0]);
3540 /* Update Overlay Index */
3541 if (afi
== AFI_L2VPN
) {
3542 overlay_index_update(new->attr
,
3543 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3544 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3546 /* Nexthop reachability check. */
3547 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3548 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3549 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3550 && !CHECK_FLAG(peer
->flags
,
3551 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3552 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3557 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3558 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3559 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3561 if (BGP_DEBUG(nht
, NHT
)) {
3562 char buf1
[INET6_ADDRSTRLEN
];
3564 (const void *)&attr_new
->nexthop
,
3565 buf1
, INET6_ADDRSTRLEN
);
3566 zlog_debug("%s(%s): NH unresolved",
3567 __FUNCTION__
, buf1
);
3569 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3572 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3575 new->addpath_rx_id
= addpath_id
;
3577 /* Increment prefix */
3578 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3580 /* Register new BGP information. */
3581 bgp_path_info_add(rn
, new);
3583 /* route_node_get lock */
3584 bgp_unlock_node(rn
);
3587 if (safi
== SAFI_MPLS_VPN
) {
3588 struct bgp_node
*prn
= NULL
;
3589 struct bgp_table
*table
= NULL
;
3591 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3592 if (bgp_node_has_bgp_path_info_data(prn
)) {
3593 table
= bgp_node_get_bgp_table_info(prn
);
3595 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3596 bgp
, prd
, table
, p
, new);
3598 bgp_unlock_node(prn
);
3602 /* If maximum prefix count is configured and current prefix
3604 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3607 /* If this is an EVPN route, process for import. */
3608 if (safi
== SAFI_EVPN
)
3609 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3611 /* Process change. */
3612 bgp_process(bgp
, rn
, afi
, safi
);
3614 if (SAFI_UNICAST
== safi
3615 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3616 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3617 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3619 if ((SAFI_MPLS_VPN
== safi
)
3620 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3622 vpn_leak_to_vrf_update(bgp
, new);
3625 if (SAFI_MPLS_VPN
== safi
) {
3626 mpls_label_t label_decoded
= decode_label(label
);
3628 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3629 sub_type
, &label_decoded
);
3631 if (SAFI_ENCAP
== safi
) {
3632 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3639 /* This BGP update is filtered. Log the reason then update BGP
3642 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3643 if (!peer
->rcvd_attr_printed
) {
3644 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3645 peer
->rcvd_attr_str
);
3646 peer
->rcvd_attr_printed
= 1;
3649 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3650 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3652 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3653 peer
->host
, pfx_buf
, reason
);
3657 /* If this is an EVPN route, un-import it as it is now filtered.
3659 if (safi
== SAFI_EVPN
)
3660 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3662 if (SAFI_UNICAST
== safi
3663 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3664 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3666 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3668 if ((SAFI_MPLS_VPN
== safi
)
3669 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3671 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3674 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3677 bgp_unlock_node(rn
);
3681 * Filtered update is treated as an implicit withdrawal (see
3683 * a few lines above)
3685 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3686 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3694 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3695 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3696 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3697 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3700 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3701 struct bgp_node
*rn
;
3702 struct bgp_path_info
*pi
;
3705 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3706 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3714 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3716 /* If peer is soft reconfiguration enabled. Record input packet for
3717 * further calculation.
3719 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3720 * routes that are filtered. This tanks out Quagga RS pretty badly due
3722 * the iteration over all RS clients.
3723 * Since we need to remove the entry from adj_in anyway, do that first
3725 * if there was no entry, we don't need to do anything more.
3727 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3728 && peer
!= bgp
->peer_self
)
3729 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3730 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3731 bgp_debug_rdpfxpath2str(
3732 afi
, safi
, prd
, p
, label
, num_labels
,
3733 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3736 "%s withdrawing route %s not in adj-in",
3737 peer
->host
, pfx_buf
);
3739 bgp_unlock_node(rn
);
3743 /* Lookup withdrawn route. */
3744 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3745 if (pi
->peer
== peer
&& pi
->type
== type
3746 && pi
->sub_type
== sub_type
3747 && pi
->addpath_rx_id
== addpath_id
)
3751 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3752 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3753 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3755 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3759 /* Withdraw specified route from routing table. */
3760 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3761 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
3762 if (SAFI_UNICAST
== safi
3763 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3764 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3765 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3767 if ((SAFI_MPLS_VPN
== safi
)
3768 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3770 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3772 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3773 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3774 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3776 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3779 /* Unlock bgp_node_get() lock. */
3780 bgp_unlock_node(rn
);
3785 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3788 struct update_subgroup
*subgrp
;
3789 subgrp
= peer_subgroup(peer
, afi
, safi
);
3790 subgroup_default_originate(subgrp
, withdraw
);
3795 * bgp_stop_announce_route_timer
3797 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3799 if (!paf
->t_announce_route
)
3802 THREAD_TIMER_OFF(paf
->t_announce_route
);
3806 * bgp_announce_route_timer_expired
3808 * Callback that is invoked when the route announcement timer for a
3811 static int bgp_announce_route_timer_expired(struct thread
*t
)
3813 struct peer_af
*paf
;
3816 paf
= THREAD_ARG(t
);
3819 if (peer
->status
!= Established
)
3822 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3825 peer_af_announce_route(paf
, 1);
3830 * bgp_announce_route
3832 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3834 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3836 struct peer_af
*paf
;
3837 struct update_subgroup
*subgrp
;
3839 paf
= peer_af_find(peer
, afi
, safi
);
3842 subgrp
= PAF_SUBGRP(paf
);
3845 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3846 * or a refresh has already been triggered.
3848 if (!subgrp
|| paf
->t_announce_route
)
3852 * Start a timer to stagger/delay the announce. This serves
3853 * two purposes - announcement can potentially be combined for
3854 * multiple peers and the announcement doesn't happen in the
3857 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3858 (subgrp
->peer_count
== 1)
3859 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3860 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3861 &paf
->t_announce_route
);
3865 * Announce routes from all AF tables to a peer.
3867 * This should ONLY be called when there is a need to refresh the
3868 * routes to the peer based on a policy change for this peer alone
3869 * or a route refresh request received from the peer.
3870 * The operation will result in splitting the peer from its existing
3871 * subgroups and putting it in new subgroups.
3873 void bgp_announce_route_all(struct peer
*peer
)
3878 FOREACH_AFI_SAFI (afi
, safi
)
3879 bgp_announce_route(peer
, afi
, safi
);
3882 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3883 struct bgp_table
*table
,
3884 struct prefix_rd
*prd
)
3887 struct bgp_node
*rn
;
3888 struct bgp_adj_in
*ain
;
3891 table
= peer
->bgp
->rib
[afi
][safi
];
3893 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3894 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3895 if (ain
->peer
!= peer
)
3898 struct bgp_path_info
*pi
=
3899 bgp_node_get_bgp_path_info(rn
);
3900 uint32_t num_labels
= 0;
3901 mpls_label_t
*label_pnt
= NULL
;
3902 struct bgp_route_evpn evpn
;
3904 if (pi
&& pi
->extra
)
3905 num_labels
= pi
->extra
->num_labels
;
3907 label_pnt
= &pi
->extra
->label
[0];
3909 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
3912 memset(&evpn
, 0, sizeof(evpn
));
3914 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3915 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3916 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3917 num_labels
, 1, &evpn
);
3920 bgp_unlock_node(rn
);
3926 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3928 struct bgp_node
*rn
;
3929 struct bgp_table
*table
;
3931 if (peer
->status
!= Established
)
3934 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3935 && (safi
!= SAFI_EVPN
))
3936 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3938 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3939 rn
= bgp_route_next(rn
)) {
3940 table
= bgp_node_get_bgp_table_info(rn
);
3941 if (table
!= NULL
) {
3942 struct prefix_rd prd
;
3944 prd
.family
= AF_UNSPEC
;
3946 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3948 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3955 struct bgp_clear_node_queue
{
3956 struct bgp_node
*rn
;
3959 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3961 struct bgp_clear_node_queue
*cnq
= data
;
3962 struct bgp_node
*rn
= cnq
->rn
;
3963 struct peer
*peer
= wq
->spec
.data
;
3964 struct bgp_path_info
*pi
;
3966 afi_t afi
= bgp_node_table(rn
)->afi
;
3967 safi_t safi
= bgp_node_table(rn
)->safi
;
3972 /* It is possible that we have multiple paths for a prefix from a peer
3973 * if that peer is using AddPath.
3975 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
3976 if (pi
->peer
!= peer
)
3979 /* graceful restart STALE flag set. */
3980 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3981 && peer
->nsf
[afi
][safi
]
3982 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
3983 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
3984 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
3986 /* If this is an EVPN route, process for
3988 if (safi
== SAFI_EVPN
)
3989 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
3991 /* Handle withdraw for VRF route-leaking and L3VPN */
3992 if (SAFI_UNICAST
== safi
3993 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3994 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3995 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3998 if (SAFI_MPLS_VPN
== safi
&&
3999 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4000 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4003 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4009 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4011 struct bgp_clear_node_queue
*cnq
= data
;
4012 struct bgp_node
*rn
= cnq
->rn
;
4013 struct bgp_table
*table
= bgp_node_table(rn
);
4015 bgp_unlock_node(rn
);
4016 bgp_table_unlock(table
);
4017 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4020 static void bgp_clear_node_complete(struct work_queue
*wq
)
4022 struct peer
*peer
= wq
->spec
.data
;
4024 /* Tickle FSM to start moving again */
4025 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4027 peer_unlock(peer
); /* bgp_clear_route */
4030 static void bgp_clear_node_queue_init(struct peer
*peer
)
4032 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4034 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4035 #undef CLEAR_QUEUE_NAME_LEN
4037 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4038 peer
->clear_node_queue
->spec
.hold
= 10;
4039 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4040 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4041 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4042 peer
->clear_node_queue
->spec
.max_retries
= 0;
4044 /* we only 'lock' this peer reference when the queue is actually active
4046 peer
->clear_node_queue
->spec
.data
= peer
;
4049 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4050 struct bgp_table
*table
)
4052 struct bgp_node
*rn
;
4053 int force
= bm
->process_main_queue
? 0 : 1;
4056 table
= peer
->bgp
->rib
[afi
][safi
];
4058 /* If still no table => afi/safi isn't configured at all or smth. */
4062 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4063 struct bgp_path_info
*pi
, *next
;
4064 struct bgp_adj_in
*ain
;
4065 struct bgp_adj_in
*ain_next
;
4067 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4068 * queued for every clearing peer, regardless of whether it is
4069 * relevant to the peer at hand.
4071 * Overview: There are 3 different indices which need to be
4072 * scrubbed, potentially, when a peer is removed:
4074 * 1 peer's routes visible via the RIB (ie accepted routes)
4075 * 2 peer's routes visible by the (optional) peer's adj-in index
4076 * 3 other routes visible by the peer's adj-out index
4078 * 3 there is no hurry in scrubbing, once the struct peer is
4079 * removed from bgp->peer, we could just GC such deleted peer's
4080 * adj-outs at our leisure.
4082 * 1 and 2 must be 'scrubbed' in some way, at least made
4083 * invisible via RIB index before peer session is allowed to be
4084 * brought back up. So one needs to know when such a 'search' is
4089 * - there'd be a single global queue or a single RIB walker
4090 * - rather than tracking which route_nodes still need to be
4091 * examined on a peer basis, we'd track which peers still
4094 * Given that our per-peer prefix-counts now should be reliable,
4095 * this may actually be achievable. It doesn't seem to be a huge
4096 * problem at this time,
4098 * It is possible that we have multiple paths for a prefix from
4100 * if that peer is using AddPath.
4104 ain_next
= ain
->next
;
4106 if (ain
->peer
== peer
) {
4107 bgp_adj_in_remove(rn
, ain
);
4108 bgp_unlock_node(rn
);
4114 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4116 if (pi
->peer
!= peer
)
4120 bgp_path_info_reap(rn
, pi
);
4122 struct bgp_clear_node_queue
*cnq
;
4124 /* both unlocked in bgp_clear_node_queue_del */
4125 bgp_table_lock(bgp_node_table(rn
));
4128 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4129 sizeof(struct bgp_clear_node_queue
));
4131 work_queue_add(peer
->clear_node_queue
, cnq
);
4139 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4141 struct bgp_node
*rn
;
4142 struct bgp_table
*table
;
4144 if (peer
->clear_node_queue
== NULL
)
4145 bgp_clear_node_queue_init(peer
);
4147 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4148 * Idle until it receives a Clearing_Completed event. This protects
4149 * against peers which flap faster than we can we clear, which could
4152 * a) race with routes from the new session being installed before
4153 * clear_route_node visits the node (to delete the route of that
4155 * b) resource exhaustion, clear_route_node likely leads to an entry
4156 * on the process_main queue. Fast-flapping could cause that queue
4160 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4161 * the unlock will happen upon work-queue completion; other wise, the
4162 * unlock happens at the end of this function.
4164 if (!peer
->clear_node_queue
->thread
)
4167 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4168 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4170 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4171 rn
= bgp_route_next(rn
)) {
4172 table
= bgp_node_get_bgp_table_info(rn
);
4176 bgp_clear_route_table(peer
, afi
, safi
, table
);
4179 /* unlock if no nodes got added to the clear-node-queue. */
4180 if (!peer
->clear_node_queue
->thread
)
4184 void bgp_clear_route_all(struct peer
*peer
)
4189 FOREACH_AFI_SAFI (afi
, safi
)
4190 bgp_clear_route(peer
, afi
, safi
);
4193 rfapiProcessPeerDown(peer
);
4197 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4199 struct bgp_table
*table
;
4200 struct bgp_node
*rn
;
4201 struct bgp_adj_in
*ain
;
4202 struct bgp_adj_in
*ain_next
;
4204 table
= peer
->bgp
->rib
[afi
][safi
];
4206 /* It is possible that we have multiple paths for a prefix from a peer
4207 * if that peer is using AddPath.
4209 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4213 ain_next
= ain
->next
;
4215 if (ain
->peer
== peer
) {
4216 bgp_adj_in_remove(rn
, ain
);
4217 bgp_unlock_node(rn
);
4225 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4227 struct bgp_node
*rn
;
4228 struct bgp_path_info
*pi
;
4229 struct bgp_table
*table
;
4231 if (safi
== SAFI_MPLS_VPN
) {
4232 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4233 rn
= bgp_route_next(rn
)) {
4234 struct bgp_node
*rm
;
4236 /* look for neighbor in tables */
4237 table
= bgp_node_get_bgp_table_info(rn
);
4241 for (rm
= bgp_table_top(table
); rm
;
4242 rm
= bgp_route_next(rm
))
4243 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4245 if (pi
->peer
!= peer
)
4247 if (!CHECK_FLAG(pi
->flags
,
4251 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4256 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4257 rn
= bgp_route_next(rn
))
4258 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4260 if (pi
->peer
!= peer
)
4262 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4264 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4270 int bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4272 if (peer
->sort
== BGP_PEER_EBGP
4273 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4274 || FILTER_LIST_OUT_NAME(filter
)
4275 || DISTRIBUTE_OUT_NAME(filter
)))
4280 int bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4282 if (peer
->sort
== BGP_PEER_EBGP
4283 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4284 || FILTER_LIST_IN_NAME(filter
)
4285 || DISTRIBUTE_IN_NAME(filter
)))
4290 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4293 struct bgp_node
*rn
;
4294 struct bgp_path_info
*pi
;
4295 struct bgp_path_info
*next
;
4297 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4298 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4301 /* Unimport EVPN routes from VRFs */
4302 if (safi
== SAFI_EVPN
)
4303 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
4307 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4308 && pi
->type
== ZEBRA_ROUTE_BGP
4309 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4310 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4311 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4313 if (bgp_fibupd_safi(safi
))
4314 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4316 bgp_path_info_reap(rn
, pi
);
4321 /* Delete all kernel routes. */
4322 void bgp_cleanup_routes(struct bgp
*bgp
)
4325 struct bgp_node
*rn
;
4326 struct bgp_table
*table
;
4328 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4329 if (afi
== AFI_L2VPN
)
4331 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4334 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4336 if (afi
!= AFI_L2VPN
) {
4338 safi
= SAFI_MPLS_VPN
;
4339 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4340 rn
= bgp_route_next(rn
)) {
4341 table
= bgp_node_get_bgp_table_info(rn
);
4342 if (table
!= NULL
) {
4343 bgp_cleanup_table(bgp
, table
, safi
);
4344 bgp_table_finish(&table
);
4345 bgp_node_set_bgp_table_info(rn
, NULL
);
4346 bgp_unlock_node(rn
);
4350 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4351 rn
= bgp_route_next(rn
)) {
4352 table
= bgp_node_get_bgp_table_info(rn
);
4353 if (table
!= NULL
) {
4354 bgp_cleanup_table(bgp
, table
, safi
);
4355 bgp_table_finish(&table
);
4356 bgp_node_set_bgp_table_info(rn
, NULL
);
4357 bgp_unlock_node(rn
);
4362 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4363 rn
= bgp_route_next(rn
)) {
4364 table
= bgp_node_get_bgp_table_info(rn
);
4365 if (table
!= NULL
) {
4366 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4367 bgp_table_finish(&table
);
4368 bgp_node_set_bgp_table_info(rn
, NULL
);
4369 bgp_unlock_node(rn
);
4374 void bgp_reset(void)
4377 bgp_zclient_reset();
4378 access_list_reset();
4379 prefix_list_reset();
4382 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4384 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4385 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4386 PEER_CAP_ADDPATH_AF_TX_RCV
));
4389 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4391 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4392 struct bgp_nlri
*packet
)
4401 int addpath_encoded
;
4402 uint32_t addpath_id
;
4405 lim
= pnt
+ packet
->length
;
4407 safi
= packet
->safi
;
4409 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4411 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4412 syntactic validity. If the field is syntactically incorrect,
4413 then the Error Subcode is set to Invalid Network Field. */
4414 for (; pnt
< lim
; pnt
+= psize
) {
4415 /* Clear prefix structure. */
4416 memset(&p
, 0, sizeof(struct prefix
));
4418 if (addpath_encoded
) {
4420 /* When packet overflow occurs return immediately. */
4421 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4422 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4424 addpath_id
= ntohl(*((uint32_t *)pnt
));
4425 pnt
+= BGP_ADDPATH_ID_LEN
;
4428 /* Fetch prefix length. */
4429 p
.prefixlen
= *pnt
++;
4430 /* afi/safi validity already verified by caller,
4431 * bgp_update_receive */
4432 p
.family
= afi2family(afi
);
4434 /* Prefix length check. */
4435 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4438 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4439 peer
->host
, p
.prefixlen
, packet
->afi
);
4440 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4443 /* Packet size overflow check. */
4444 psize
= PSIZE(p
.prefixlen
);
4446 /* When packet overflow occur return immediately. */
4447 if (pnt
+ psize
> lim
) {
4450 "%s [Error] Update packet error (prefix length %d overflows packet)",
4451 peer
->host
, p
.prefixlen
);
4452 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4455 /* Defensive coding, double-check the psize fits in a struct
4457 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4460 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4461 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4462 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4465 /* Fetch prefix from NLRI packet. */
4466 memcpy(p
.u
.val
, pnt
, psize
);
4468 /* Check address. */
4469 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4470 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4471 /* From RFC4271 Section 6.3:
4473 * If a prefix in the NLRI field is semantically
4475 * (e.g., an unexpected multicast IP address),
4477 * be logged locally, and the prefix SHOULD be
4482 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4483 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4488 /* Check address. */
4489 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4490 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4495 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4497 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4502 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4507 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4509 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4516 /* Normal process. */
4518 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4519 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4520 NULL
, NULL
, 0, 0, NULL
);
4522 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4523 safi
, ZEBRA_ROUTE_BGP
,
4524 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4527 /* Do not send BGP notification twice when maximum-prefix count
4529 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
4530 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
4532 /* Address family configuration mismatch. */
4534 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
4537 /* Packet length consistency check. */
4541 "%s [Error] Update packet error (prefix length mismatch with total length)",
4543 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4546 return BGP_NLRI_PARSE_OK
;
4549 static struct bgp_static
*bgp_static_new(void)
4551 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4554 static void bgp_static_free(struct bgp_static
*bgp_static
)
4556 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4557 route_map_counter_decrement(bgp_static
->rmap
.map
);
4559 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4560 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4563 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4564 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4566 struct bgp_node
*rn
;
4567 struct bgp_path_info
*pi
;
4568 struct bgp_path_info
*new;
4569 struct bgp_path_info rmap_path
;
4571 struct attr
*attr_new
;
4574 int vnc_implicit_withdraw
= 0;
4581 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4583 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4585 attr
.nexthop
= bgp_static
->igpnexthop
;
4586 attr
.med
= bgp_static
->igpmetric
;
4587 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4589 if (bgp_static
->atomic
)
4590 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4592 /* Store label index, if required. */
4593 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4594 attr
.label_index
= bgp_static
->label_index
;
4595 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4598 /* Apply route-map. */
4599 if (bgp_static
->rmap
.name
) {
4600 struct attr attr_tmp
= attr
;
4602 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4603 rmap_path
.peer
= bgp
->peer_self
;
4604 rmap_path
.attr
= &attr_tmp
;
4606 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4608 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4611 bgp
->peer_self
->rmap_type
= 0;
4613 if (ret
== RMAP_DENYMATCH
) {
4614 /* Free uninterned attribute. */
4615 bgp_attr_flush(&attr_tmp
);
4617 /* Unintern original. */
4618 aspath_unintern(&attr
.aspath
);
4619 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4623 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4624 bgp_attr_add_gshut_community(&attr_tmp
);
4626 attr_new
= bgp_attr_intern(&attr_tmp
);
4629 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4630 bgp_attr_add_gshut_community(&attr
);
4632 attr_new
= bgp_attr_intern(&attr
);
4635 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4636 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4637 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4641 if (attrhash_cmp(pi
->attr
, attr_new
)
4642 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4643 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4644 bgp_unlock_node(rn
);
4645 bgp_attr_unintern(&attr_new
);
4646 aspath_unintern(&attr
.aspath
);
4649 /* The attribute is changed. */
4650 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4652 /* Rewrite BGP route information. */
4653 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4654 bgp_path_info_restore(rn
, pi
);
4656 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4658 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4659 && (safi
== SAFI_UNICAST
)) {
4660 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4662 * Implicit withdraw case.
4663 * We have to do this before pi is
4666 ++vnc_implicit_withdraw
;
4667 vnc_import_bgp_del_route(bgp
, p
, pi
);
4668 vnc_import_bgp_exterior_del_route(
4673 bgp_attr_unintern(&pi
->attr
);
4674 pi
->attr
= attr_new
;
4675 pi
->uptime
= bgp_clock();
4677 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4678 && (safi
== SAFI_UNICAST
)) {
4679 if (vnc_implicit_withdraw
) {
4680 vnc_import_bgp_add_route(bgp
, p
, pi
);
4681 vnc_import_bgp_exterior_add_route(
4687 /* Nexthop reachability check. */
4688 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4689 && (safi
== SAFI_UNICAST
4690 || safi
== SAFI_LABELED_UNICAST
)) {
4692 struct bgp
*bgp_nexthop
= bgp
;
4694 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4695 bgp_nexthop
= pi
->extra
->bgp_orig
;
4697 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4699 bgp_path_info_set_flag(rn
, pi
,
4702 if (BGP_DEBUG(nht
, NHT
)) {
4703 char buf1
[INET6_ADDRSTRLEN
];
4704 inet_ntop(p
->family
,
4708 "%s(%s): Route not in table, not advertising",
4709 __FUNCTION__
, buf1
);
4711 bgp_path_info_unset_flag(
4712 rn
, pi
, BGP_PATH_VALID
);
4715 /* Delete the NHT structure if any, if we're
4717 * enabling/disabling import check. We
4718 * deregister the route
4719 * from NHT to avoid overloading NHT and the
4720 * process interaction
4722 bgp_unlink_nexthop(pi
);
4723 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
4725 /* Process change. */
4726 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4727 bgp_process(bgp
, rn
, afi
, safi
);
4729 if (SAFI_UNICAST
== safi
4730 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4732 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4733 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4737 bgp_unlock_node(rn
);
4738 aspath_unintern(&attr
.aspath
);
4743 /* Make new BGP info. */
4744 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4746 /* Nexthop reachability check. */
4747 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4748 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4749 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4750 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4752 if (BGP_DEBUG(nht
, NHT
)) {
4753 char buf1
[INET6_ADDRSTRLEN
];
4754 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4757 "%s(%s): Route not in table, not advertising",
4758 __FUNCTION__
, buf1
);
4760 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4763 /* Delete the NHT structure if any, if we're toggling between
4764 * enabling/disabling import check. We deregister the route
4765 * from NHT to avoid overloading NHT and the process interaction
4767 bgp_unlink_nexthop(new);
4769 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4772 /* Aggregate address increment. */
4773 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4775 /* Register new BGP information. */
4776 bgp_path_info_add(rn
, new);
4778 /* route_node_get lock */
4779 bgp_unlock_node(rn
);
4781 /* Process change. */
4782 bgp_process(bgp
, rn
, afi
, safi
);
4784 if (SAFI_UNICAST
== safi
4785 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4786 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4787 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4790 /* Unintern original. */
4791 aspath_unintern(&attr
.aspath
);
4794 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4797 struct bgp_node
*rn
;
4798 struct bgp_path_info
*pi
;
4800 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4802 /* Check selected route and self inserted route. */
4803 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4804 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4805 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4808 /* Withdraw static BGP route from routing table. */
4810 if (SAFI_UNICAST
== safi
4811 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4812 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4813 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4815 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4816 bgp_unlink_nexthop(pi
);
4817 bgp_path_info_delete(rn
, pi
);
4818 bgp_process(bgp
, rn
, afi
, safi
);
4821 /* Unlock bgp_node_lookup. */
4822 bgp_unlock_node(rn
);
4826 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4828 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4829 afi_t afi
, safi_t safi
,
4830 struct prefix_rd
*prd
)
4832 struct bgp_node
*rn
;
4833 struct bgp_path_info
*pi
;
4835 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4837 /* Check selected route and self inserted route. */
4838 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4839 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4840 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4843 /* Withdraw static BGP route from routing table. */
4846 rfapiProcessWithdraw(
4847 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
4848 1); /* Kill, since it is an administrative change */
4850 if (SAFI_MPLS_VPN
== safi
4851 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4852 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4854 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4855 bgp_path_info_delete(rn
, pi
);
4856 bgp_process(bgp
, rn
, afi
, safi
);
4859 /* Unlock bgp_node_lookup. */
4860 bgp_unlock_node(rn
);
4863 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4864 struct bgp_static
*bgp_static
, afi_t afi
,
4867 struct bgp_node
*rn
;
4868 struct bgp_path_info
*new;
4869 struct attr
*attr_new
;
4870 struct attr attr
= {0};
4871 struct bgp_path_info
*pi
;
4873 mpls_label_t label
= 0;
4875 uint32_t num_labels
= 0;
4880 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4882 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4885 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4887 attr
.nexthop
= bgp_static
->igpnexthop
;
4888 attr
.med
= bgp_static
->igpmetric
;
4889 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4891 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4892 || (safi
== SAFI_ENCAP
)) {
4893 if (afi
== AFI_IP
) {
4894 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4895 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4898 if (afi
== AFI_L2VPN
) {
4899 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4901 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4902 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4903 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4904 sizeof(struct in6_addr
));
4905 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4906 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4907 struct bgp_encap_type_vxlan bet
;
4908 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4909 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4910 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4912 if (bgp_static
->router_mac
) {
4913 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4916 /* Apply route-map. */
4917 if (bgp_static
->rmap
.name
) {
4918 struct attr attr_tmp
= attr
;
4919 struct bgp_path_info rmap_path
;
4922 rmap_path
.peer
= bgp
->peer_self
;
4923 rmap_path
.attr
= &attr_tmp
;
4925 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4927 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4930 bgp
->peer_self
->rmap_type
= 0;
4932 if (ret
== RMAP_DENYMATCH
) {
4933 /* Free uninterned attribute. */
4934 bgp_attr_flush(&attr_tmp
);
4936 /* Unintern original. */
4937 aspath_unintern(&attr
.aspath
);
4938 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4943 attr_new
= bgp_attr_intern(&attr_tmp
);
4945 attr_new
= bgp_attr_intern(&attr
);
4948 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4949 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4950 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4954 memset(&add
, 0, sizeof(union gw_addr
));
4955 if (attrhash_cmp(pi
->attr
, attr_new
)
4956 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
4957 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4958 bgp_unlock_node(rn
);
4959 bgp_attr_unintern(&attr_new
);
4960 aspath_unintern(&attr
.aspath
);
4963 /* The attribute is changed. */
4964 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4966 /* Rewrite BGP route information. */
4967 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4968 bgp_path_info_restore(rn
, pi
);
4970 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4971 bgp_attr_unintern(&pi
->attr
);
4972 pi
->attr
= attr_new
;
4973 pi
->uptime
= bgp_clock();
4976 label
= decode_label(&pi
->extra
->label
[0]);
4979 /* Process change. */
4980 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4981 bgp_process(bgp
, rn
, afi
, safi
);
4983 if (SAFI_MPLS_VPN
== safi
4984 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4985 vpn_leak_to_vrf_update(bgp
, pi
);
4988 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
4989 pi
->attr
, afi
, safi
, pi
->type
,
4990 pi
->sub_type
, &label
);
4992 bgp_unlock_node(rn
);
4993 aspath_unintern(&attr
.aspath
);
4999 /* Make new BGP info. */
5000 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5002 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5003 new->extra
= bgp_path_info_extra_new();
5005 new->extra
->label
[0] = bgp_static
->label
;
5006 new->extra
->num_labels
= num_labels
;
5009 label
= decode_label(&bgp_static
->label
);
5012 /* Aggregate address increment. */
5013 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5015 /* Register new BGP information. */
5016 bgp_path_info_add(rn
, new);
5017 /* route_node_get lock */
5018 bgp_unlock_node(rn
);
5020 /* Process change. */
5021 bgp_process(bgp
, rn
, afi
, safi
);
5023 if (SAFI_MPLS_VPN
== safi
5024 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5025 vpn_leak_to_vrf_update(bgp
, new);
5028 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5029 safi
, new->type
, new->sub_type
, &label
);
5032 /* Unintern original. */
5033 aspath_unintern(&attr
.aspath
);
5036 /* Configure static BGP network. When user don't run zebra, static
5037 route should be installed as valid. */
5038 static int bgp_static_set(struct vty
*vty
, const char *negate
,
5039 const char *ip_str
, afi_t afi
, safi_t safi
,
5040 const char *rmap
, int backdoor
, uint32_t label_index
)
5042 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5045 struct bgp_static
*bgp_static
;
5046 struct bgp_node
*rn
;
5047 uint8_t need_update
= 0;
5049 /* Convert IP prefix string to struct prefix. */
5050 ret
= str2prefix(ip_str
, &p
);
5052 vty_out(vty
, "%% Malformed prefix\n");
5053 return CMD_WARNING_CONFIG_FAILED
;
5055 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5056 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
5057 return CMD_WARNING_CONFIG_FAILED
;
5064 /* Set BGP static route configuration. */
5065 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5068 vty_out(vty
, "%% Can't find static route specified\n");
5069 return CMD_WARNING_CONFIG_FAILED
;
5072 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5074 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5075 && (label_index
!= bgp_static
->label_index
)) {
5077 "%% label-index doesn't match static route\n");
5078 return CMD_WARNING_CONFIG_FAILED
;
5081 if ((rmap
&& bgp_static
->rmap
.name
)
5082 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5084 "%% route-map name doesn't match static route\n");
5085 return CMD_WARNING_CONFIG_FAILED
;
5088 /* Update BGP RIB. */
5089 if (!bgp_static
->backdoor
)
5090 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5092 /* Clear configuration. */
5093 bgp_static_free(bgp_static
);
5094 bgp_node_set_bgp_static_info(rn
, NULL
);
5095 bgp_unlock_node(rn
);
5096 bgp_unlock_node(rn
);
5099 /* Set BGP static route configuration. */
5100 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5102 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5104 /* Configuration change. */
5105 /* Label index cannot be changed. */
5106 if (bgp_static
->label_index
!= label_index
) {
5107 vty_out(vty
, "%% cannot change label-index\n");
5108 return CMD_WARNING_CONFIG_FAILED
;
5111 /* Check previous routes are installed into BGP. */
5112 if (bgp_static
->valid
5113 && bgp_static
->backdoor
!= backdoor
)
5116 bgp_static
->backdoor
= backdoor
;
5119 XFREE(MTYPE_ROUTE_MAP_NAME
,
5120 bgp_static
->rmap
.name
);
5121 route_map_counter_decrement(
5122 bgp_static
->rmap
.map
);
5123 bgp_static
->rmap
.name
=
5124 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5125 bgp_static
->rmap
.map
=
5126 route_map_lookup_by_name(rmap
);
5127 route_map_counter_increment(
5128 bgp_static
->rmap
.map
);
5130 XFREE(MTYPE_ROUTE_MAP_NAME
,
5131 bgp_static
->rmap
.name
);
5132 route_map_counter_decrement(
5133 bgp_static
->rmap
.map
);
5134 bgp_static
->rmap
.name
= NULL
;
5135 bgp_static
->rmap
.map
= NULL
;
5136 bgp_static
->valid
= 0;
5138 bgp_unlock_node(rn
);
5140 /* New configuration. */
5141 bgp_static
= bgp_static_new();
5142 bgp_static
->backdoor
= backdoor
;
5143 bgp_static
->valid
= 0;
5144 bgp_static
->igpmetric
= 0;
5145 bgp_static
->igpnexthop
.s_addr
= 0;
5146 bgp_static
->label_index
= label_index
;
5149 XFREE(MTYPE_ROUTE_MAP_NAME
,
5150 bgp_static
->rmap
.name
);
5151 route_map_counter_decrement(
5152 bgp_static
->rmap
.map
);
5153 bgp_static
->rmap
.name
=
5154 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5155 bgp_static
->rmap
.map
=
5156 route_map_lookup_by_name(rmap
);
5157 route_map_counter_increment(
5158 bgp_static
->rmap
.map
);
5160 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5163 bgp_static
->valid
= 1;
5165 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5167 if (!bgp_static
->backdoor
)
5168 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5174 void bgp_static_add(struct bgp
*bgp
)
5178 struct bgp_node
*rn
;
5179 struct bgp_node
*rm
;
5180 struct bgp_table
*table
;
5181 struct bgp_static
*bgp_static
;
5183 FOREACH_AFI_SAFI (afi
, safi
)
5184 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5185 rn
= bgp_route_next(rn
)) {
5186 if (!bgp_node_has_bgp_path_info_data(rn
))
5189 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5190 || (safi
== SAFI_EVPN
)) {
5191 table
= bgp_node_get_bgp_table_info(rn
);
5193 for (rm
= bgp_table_top(table
); rm
;
5194 rm
= bgp_route_next(rm
)) {
5196 bgp_node_get_bgp_static_info(
5198 bgp_static_update_safi(bgp
, &rm
->p
,
5205 bgp_node_get_bgp_static_info(rn
), afi
,
5211 /* Called from bgp_delete(). Delete all static routes from the BGP
5213 void bgp_static_delete(struct bgp
*bgp
)
5217 struct bgp_node
*rn
;
5218 struct bgp_node
*rm
;
5219 struct bgp_table
*table
;
5220 struct bgp_static
*bgp_static
;
5222 FOREACH_AFI_SAFI (afi
, safi
)
5223 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5224 rn
= bgp_route_next(rn
)) {
5225 if (!bgp_node_has_bgp_path_info_data(rn
))
5228 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5229 || (safi
== SAFI_EVPN
)) {
5230 table
= bgp_node_get_bgp_table_info(rn
);
5232 for (rm
= bgp_table_top(table
); rm
;
5233 rm
= bgp_route_next(rm
)) {
5235 bgp_node_get_bgp_static_info(
5240 bgp_static_withdraw_safi(
5241 bgp
, &rm
->p
, AFI_IP
, safi
,
5242 (struct prefix_rd
*)&rn
->p
);
5243 bgp_static_free(bgp_static
);
5244 bgp_node_set_bgp_static_info(rn
, NULL
);
5245 bgp_unlock_node(rn
);
5248 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5249 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5250 bgp_static_free(bgp_static
);
5251 bgp_node_set_bgp_static_info(rn
, NULL
);
5252 bgp_unlock_node(rn
);
5257 void bgp_static_redo_import_check(struct bgp
*bgp
)
5261 struct bgp_node
*rn
;
5262 struct bgp_node
*rm
;
5263 struct bgp_table
*table
;
5264 struct bgp_static
*bgp_static
;
5266 /* Use this flag to force reprocessing of the route */
5267 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5268 FOREACH_AFI_SAFI (afi
, safi
) {
5269 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5270 rn
= bgp_route_next(rn
)) {
5271 if (!bgp_node_has_bgp_path_info_data(rn
))
5274 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5275 || (safi
== SAFI_EVPN
)) {
5276 table
= bgp_node_get_bgp_table_info(rn
);
5278 for (rm
= bgp_table_top(table
); rm
;
5279 rm
= bgp_route_next(rm
)) {
5281 bgp_node_get_bgp_static_info(
5283 bgp_static_update_safi(bgp
, &rm
->p
,
5288 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5289 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5294 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5297 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5300 struct bgp_table
*table
;
5301 struct bgp_node
*rn
;
5302 struct bgp_path_info
*pi
;
5304 table
= bgp
->rib
[afi
][safi
];
5305 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5306 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5307 if (pi
->peer
== bgp
->peer_self
5308 && ((pi
->type
== ZEBRA_ROUTE_BGP
5309 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5310 || (pi
->type
!= ZEBRA_ROUTE_BGP
5312 == BGP_ROUTE_REDISTRIBUTE
))) {
5313 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5315 bgp_unlink_nexthop(pi
);
5316 bgp_path_info_delete(rn
, pi
);
5317 bgp_process(bgp
, rn
, afi
, safi
);
5324 * Purge all networks and redistributed routes from routing table.
5325 * Invoked upon the instance going down.
5327 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5332 FOREACH_AFI_SAFI (afi
, safi
)
5333 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5338 * Currently this is used to set static routes for VPN and ENCAP.
5339 * I think it can probably be factored with bgp_static_set.
5341 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5342 const char *ip_str
, const char *rd_str
,
5343 const char *label_str
, const char *rmap_str
,
5344 int evpn_type
, const char *esi
, const char *gwip
,
5345 const char *ethtag
, const char *routermac
)
5347 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5350 struct prefix_rd prd
;
5351 struct bgp_node
*prn
;
5352 struct bgp_node
*rn
;
5353 struct bgp_table
*table
;
5354 struct bgp_static
*bgp_static
;
5355 mpls_label_t label
= MPLS_INVALID_LABEL
;
5356 struct prefix gw_ip
;
5358 /* validate ip prefix */
5359 ret
= str2prefix(ip_str
, &p
);
5361 vty_out(vty
, "%% Malformed prefix\n");
5362 return CMD_WARNING_CONFIG_FAILED
;
5365 if ((afi
== AFI_L2VPN
)
5366 && (bgp_build_evpn_prefix(evpn_type
,
5367 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5368 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5369 return CMD_WARNING_CONFIG_FAILED
;
5372 ret
= str2prefix_rd(rd_str
, &prd
);
5374 vty_out(vty
, "%% Malformed rd\n");
5375 return CMD_WARNING_CONFIG_FAILED
;
5379 unsigned long label_val
;
5380 label_val
= strtoul(label_str
, NULL
, 10);
5381 encode_label(label_val
, &label
);
5384 if (safi
== SAFI_EVPN
) {
5385 if (esi
&& str2esi(esi
, NULL
) == 0) {
5386 vty_out(vty
, "%% Malformed ESI\n");
5387 return CMD_WARNING_CONFIG_FAILED
;
5389 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5390 vty_out(vty
, "%% Malformed Router MAC\n");
5391 return CMD_WARNING_CONFIG_FAILED
;
5394 memset(&gw_ip
, 0, sizeof(struct prefix
));
5395 ret
= str2prefix(gwip
, &gw_ip
);
5397 vty_out(vty
, "%% Malformed GatewayIp\n");
5398 return CMD_WARNING_CONFIG_FAILED
;
5400 if ((gw_ip
.family
== AF_INET
5401 && is_evpn_prefix_ipaddr_v6(
5402 (struct prefix_evpn
*)&p
))
5403 || (gw_ip
.family
== AF_INET6
5404 && is_evpn_prefix_ipaddr_v4(
5405 (struct prefix_evpn
*)&p
))) {
5407 "%% GatewayIp family differs with IP prefix\n");
5408 return CMD_WARNING_CONFIG_FAILED
;
5412 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5413 if (!bgp_node_has_bgp_path_info_data(prn
))
5414 bgp_node_set_bgp_table_info(prn
,
5415 bgp_table_init(bgp
, afi
, safi
));
5416 table
= bgp_node_get_bgp_table_info(prn
);
5418 rn
= bgp_node_get(table
, &p
);
5420 if (bgp_node_has_bgp_path_info_data(rn
)) {
5421 vty_out(vty
, "%% Same network configuration exists\n");
5422 bgp_unlock_node(rn
);
5424 /* New configuration. */
5425 bgp_static
= bgp_static_new();
5426 bgp_static
->backdoor
= 0;
5427 bgp_static
->valid
= 0;
5428 bgp_static
->igpmetric
= 0;
5429 bgp_static
->igpnexthop
.s_addr
= 0;
5430 bgp_static
->label
= label
;
5431 bgp_static
->prd
= prd
;
5434 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5435 route_map_counter_decrement(bgp_static
->rmap
.map
);
5436 bgp_static
->rmap
.name
=
5437 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5438 bgp_static
->rmap
.map
=
5439 route_map_lookup_by_name(rmap_str
);
5440 route_map_counter_increment(bgp_static
->rmap
.map
);
5443 if (safi
== SAFI_EVPN
) {
5445 bgp_static
->eth_s_id
=
5447 sizeof(struct eth_segment_id
));
5448 str2esi(esi
, bgp_static
->eth_s_id
);
5451 bgp_static
->router_mac
=
5452 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5453 (void)prefix_str2mac(routermac
,
5454 bgp_static
->router_mac
);
5457 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5459 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5461 bgp_static
->valid
= 1;
5462 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5468 /* Configure static BGP network. */
5469 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5470 const char *ip_str
, const char *rd_str
,
5471 const char *label_str
, int evpn_type
, const char *esi
,
5472 const char *gwip
, const char *ethtag
)
5474 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5477 struct prefix_rd prd
;
5478 struct bgp_node
*prn
;
5479 struct bgp_node
*rn
;
5480 struct bgp_table
*table
;
5481 struct bgp_static
*bgp_static
;
5482 mpls_label_t label
= MPLS_INVALID_LABEL
;
5484 /* Convert IP prefix string to struct prefix. */
5485 ret
= str2prefix(ip_str
, &p
);
5487 vty_out(vty
, "%% Malformed prefix\n");
5488 return CMD_WARNING_CONFIG_FAILED
;
5491 if ((afi
== AFI_L2VPN
)
5492 && (bgp_build_evpn_prefix(evpn_type
,
5493 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5494 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5495 return CMD_WARNING_CONFIG_FAILED
;
5497 ret
= str2prefix_rd(rd_str
, &prd
);
5499 vty_out(vty
, "%% Malformed rd\n");
5500 return CMD_WARNING_CONFIG_FAILED
;
5504 unsigned long label_val
;
5505 label_val
= strtoul(label_str
, NULL
, 10);
5506 encode_label(label_val
, &label
);
5509 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5510 if (!bgp_node_has_bgp_path_info_data(prn
))
5511 bgp_node_set_bgp_table_info(prn
,
5512 bgp_table_init(bgp
, afi
, safi
));
5514 bgp_unlock_node(prn
);
5515 table
= bgp_node_get_bgp_table_info(prn
);
5517 rn
= bgp_node_lookup(table
, &p
);
5520 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5522 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5523 bgp_static_free(bgp_static
);
5524 bgp_node_set_bgp_static_info(rn
, NULL
);
5525 bgp_unlock_node(rn
);
5526 bgp_unlock_node(rn
);
5528 vty_out(vty
, "%% Can't find the route\n");
5533 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5534 const char *rmap_name
)
5536 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5537 struct bgp_rmap
*rmap
;
5539 rmap
= &bgp
->table_map
[afi
][safi
];
5541 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5542 route_map_counter_decrement(rmap
->map
);
5543 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5544 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5545 route_map_counter_increment(rmap
->map
);
5547 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5548 route_map_counter_decrement(rmap
->map
);
5553 if (bgp_fibupd_safi(safi
))
5554 bgp_zebra_announce_table(bgp
, afi
, safi
);
5559 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5560 const char *rmap_name
)
5562 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5563 struct bgp_rmap
*rmap
;
5565 rmap
= &bgp
->table_map
[afi
][safi
];
5566 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5567 route_map_counter_decrement(rmap
->map
);
5571 if (bgp_fibupd_safi(safi
))
5572 bgp_zebra_announce_table(bgp
, afi
, safi
);
5577 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5580 if (bgp
->table_map
[afi
][safi
].name
) {
5581 vty_out(vty
, " table-map %s\n",
5582 bgp
->table_map
[afi
][safi
].name
);
5586 DEFUN (bgp_table_map
,
5589 "BGP table to RIB route download filter\n"
5590 "Name of the route map\n")
5593 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5594 argv
[idx_word
]->arg
);
5596 DEFUN (no_bgp_table_map
,
5597 no_bgp_table_map_cmd
,
5598 "no table-map WORD",
5600 "BGP table to RIB route download filter\n"
5601 "Name of the route map\n")
5604 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5605 argv
[idx_word
]->arg
);
5611 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5612 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5613 backdoor$backdoor}]",
5615 "Specify a network to announce via BGP\n"
5620 "Route-map to modify the attributes\n"
5621 "Name of the route map\n"
5622 "Label index to associate with the prefix\n"
5623 "Label index value\n"
5624 "Specify a BGP backdoor route\n")
5626 char addr_prefix_str
[BUFSIZ
];
5631 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5634 vty_out(vty
, "%% Inconsistent address and mask\n");
5635 return CMD_WARNING_CONFIG_FAILED
;
5639 return bgp_static_set(
5640 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5641 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5642 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5645 DEFPY(ipv6_bgp_network
,
5646 ipv6_bgp_network_cmd
,
5647 "[no] network X:X::X:X/M$prefix \
5648 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5650 "Specify a network to announce via BGP\n"
5652 "Route-map to modify the attributes\n"
5653 "Name of the route map\n"
5654 "Label index to associate with the prefix\n"
5655 "Label index value\n")
5657 return bgp_static_set(
5658 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5659 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5662 static struct bgp_aggregate
*bgp_aggregate_new(void)
5664 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5667 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5669 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5672 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5673 struct aspath
*aspath
,
5674 struct community
*comm
,
5675 struct ecommunity
*ecomm
,
5676 struct lcommunity
*lcomm
)
5678 static struct aspath
*ae
= NULL
;
5681 ae
= aspath_empty();
5686 if (origin
!= pi
->attr
->origin
)
5689 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5692 if (!community_cmp(pi
->attr
->community
, comm
))
5695 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5698 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5701 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5707 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5708 struct prefix
*p
, uint8_t origin
,
5709 struct aspath
*aspath
,
5710 struct community
*community
,
5711 struct ecommunity
*ecommunity
,
5712 struct lcommunity
*lcommunity
,
5713 uint8_t atomic_aggregate
,
5714 struct bgp_aggregate
*aggregate
)
5716 struct bgp_node
*rn
;
5717 struct bgp_table
*table
;
5718 struct bgp_path_info
*pi
, *orig
, *new;
5720 table
= bgp
->rib
[afi
][safi
];
5722 rn
= bgp_node_get(table
, p
);
5724 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5725 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5726 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5729 if (aggregate
->count
> 0) {
5731 * If the aggregate information has not changed
5732 * no need to re-install it again.
5734 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
5735 ecommunity
, lcommunity
)) {
5736 bgp_unlock_node(rn
);
5739 aspath_free(aspath
);
5741 community_free(&community
);
5743 ecommunity_free(&ecommunity
);
5745 lcommunity_free(&lcommunity
);
5751 * Mark the old as unusable
5754 bgp_path_info_delete(rn
, pi
);
5756 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5758 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5759 community
, ecommunity
,
5764 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5766 bgp_path_info_add(rn
, new);
5767 bgp_process(bgp
, rn
, afi
, safi
);
5769 for (pi
= orig
; pi
; pi
= pi
->next
)
5770 if (pi
->peer
== bgp
->peer_self
5771 && pi
->type
== ZEBRA_ROUTE_BGP
5772 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5775 /* Withdraw static BGP route from routing table. */
5777 bgp_path_info_delete(rn
, pi
);
5778 bgp_process(bgp
, rn
, afi
, safi
);
5782 bgp_unlock_node(rn
);
5785 /* Update an aggregate as routes are added/removed from the BGP table */
5786 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5787 afi_t afi
, safi_t safi
,
5788 struct bgp_aggregate
*aggregate
)
5790 struct bgp_table
*table
;
5791 struct bgp_node
*top
;
5792 struct bgp_node
*rn
;
5794 struct aspath
*aspath
= NULL
;
5795 struct community
*community
= NULL
;
5796 struct ecommunity
*ecommunity
= NULL
;
5797 struct lcommunity
*lcommunity
= NULL
;
5798 struct bgp_path_info
*pi
;
5799 unsigned long match
= 0;
5800 uint8_t atomic_aggregate
= 0;
5802 /* If the bgp instance is being deleted or self peer is deleted
5803 * then do not create aggregate route
5805 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
5806 (bgp
->peer_self
== NULL
))
5809 /* ORIGIN attribute: If at least one route among routes that are
5810 aggregated has ORIGIN with the value INCOMPLETE, then the
5811 aggregated route must have the ORIGIN attribute with the value
5812 INCOMPLETE. Otherwise, if at least one route among routes that
5813 are aggregated has ORIGIN with the value EGP, then the aggregated
5814 route must have the origin attribute with the value EGP. In all
5815 other case the value of the ORIGIN attribute of the aggregated
5816 route is INTERNAL. */
5817 origin
= BGP_ORIGIN_IGP
;
5819 table
= bgp
->rib
[afi
][safi
];
5821 top
= bgp_node_get(table
, p
);
5822 for (rn
= bgp_node_get(table
, p
); rn
;
5823 rn
= bgp_route_next_until(rn
, top
)) {
5824 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5829 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5830 if (BGP_PATH_HOLDDOWN(pi
))
5834 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5835 atomic_aggregate
= 1;
5837 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5841 * summary-only aggregate route suppress
5842 * aggregated route announcements.
5844 if (aggregate
->summary_only
) {
5845 (bgp_path_info_extra_get(pi
))->suppress
++;
5846 bgp_path_info_set_flag(rn
, pi
,
5847 BGP_PATH_ATTR_CHANGED
);
5854 * If at least one route among routes that are
5855 * aggregated has ORIGIN with the value INCOMPLETE,
5856 * then the aggregated route MUST have the ORIGIN
5857 * attribute with the value INCOMPLETE. Otherwise, if
5858 * at least one route among routes that are aggregated
5859 * has ORIGIN with the value EGP, then the aggregated
5860 * route MUST have the ORIGIN attribute with the value
5863 switch (pi
->attr
->origin
) {
5864 case BGP_ORIGIN_INCOMPLETE
:
5865 aggregate
->incomplete_origin_count
++;
5867 case BGP_ORIGIN_EGP
:
5868 aggregate
->egp_origin_count
++;
5876 if (!aggregate
->as_set
)
5880 * as-set aggregate route generate origin, as path,
5881 * and community aggregation.
5883 /* Compute aggregate route's as-path.
5885 bgp_compute_aggregate_aspath(aggregate
,
5888 /* Compute aggregate route's community.
5890 if (pi
->attr
->community
)
5891 bgp_compute_aggregate_community(
5893 pi
->attr
->community
);
5895 /* Compute aggregate route's extended community.
5897 if (pi
->attr
->ecommunity
)
5898 bgp_compute_aggregate_ecommunity(
5900 pi
->attr
->ecommunity
);
5902 /* Compute aggregate route's large community.
5904 if (pi
->attr
->lcommunity
)
5905 bgp_compute_aggregate_lcommunity(
5907 pi
->attr
->lcommunity
);
5910 bgp_process(bgp
, rn
, afi
, safi
);
5912 bgp_unlock_node(top
);
5915 if (aggregate
->incomplete_origin_count
> 0)
5916 origin
= BGP_ORIGIN_INCOMPLETE
;
5917 else if (aggregate
->egp_origin_count
> 0)
5918 origin
= BGP_ORIGIN_EGP
;
5920 if (aggregate
->as_set
) {
5921 if (aggregate
->aspath
)
5922 /* Retrieve aggregate route's as-path.
5924 aspath
= aspath_dup(aggregate
->aspath
);
5926 if (aggregate
->community
)
5927 /* Retrieve aggregate route's community.
5929 community
= community_dup(aggregate
->community
);
5931 if (aggregate
->ecommunity
)
5932 /* Retrieve aggregate route's ecommunity.
5934 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
5936 if (aggregate
->lcommunity
)
5937 /* Retrieve aggregate route's lcommunity.
5939 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
5942 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5943 ecommunity
, lcommunity
, atomic_aggregate
,
5947 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5948 safi_t safi
, struct bgp_aggregate
*aggregate
)
5950 struct bgp_table
*table
;
5951 struct bgp_node
*top
;
5952 struct bgp_node
*rn
;
5953 struct bgp_path_info
*pi
;
5954 unsigned long match
;
5956 table
= bgp
->rib
[afi
][safi
];
5958 /* If routes exists below this node, generate aggregate routes. */
5959 top
= bgp_node_get(table
, p
);
5960 for (rn
= bgp_node_get(table
, p
); rn
;
5961 rn
= bgp_route_next_until(rn
, top
)) {
5962 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5966 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5967 if (BGP_PATH_HOLDDOWN(pi
))
5970 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5973 if (aggregate
->summary_only
&& pi
->extra
) {
5974 pi
->extra
->suppress
--;
5976 if (pi
->extra
->suppress
== 0) {
5977 bgp_path_info_set_flag(
5978 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5984 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
5985 aggregate
->incomplete_origin_count
--;
5986 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
5987 aggregate
->egp_origin_count
--;
5989 if (aggregate
->as_set
) {
5990 /* Remove as-path from aggregate.
5992 bgp_remove_aspath_from_aggregate(
5996 if (pi
->attr
->community
)
5997 /* Remove community from aggregate.
5999 bgp_remove_community_from_aggregate(
6001 pi
->attr
->community
);
6003 if (pi
->attr
->ecommunity
)
6004 /* Remove ecommunity from aggregate.
6006 bgp_remove_ecommunity_from_aggregate(
6008 pi
->attr
->ecommunity
);
6010 if (pi
->attr
->lcommunity
)
6011 /* Remove lcommunity from aggregate.
6013 bgp_remove_lcommunity_from_aggregate(
6015 pi
->attr
->lcommunity
);
6020 /* If this node was suppressed, process the change. */
6022 bgp_process(bgp
, rn
, afi
, safi
);
6024 bgp_unlock_node(top
);
6027 static void bgp_add_route_to_aggregate(struct bgp
*bgp
, struct prefix
*aggr_p
,
6028 struct bgp_path_info
*pinew
, afi_t afi
,
6030 struct bgp_aggregate
*aggregate
)
6033 struct aspath
*aspath
= NULL
;
6034 uint8_t atomic_aggregate
= 0;
6035 struct community
*community
= NULL
;
6036 struct ecommunity
*ecommunity
= NULL
;
6037 struct lcommunity
*lcommunity
= NULL
;
6039 /* ORIGIN attribute: If at least one route among routes that are
6040 * aggregated has ORIGIN with the value INCOMPLETE, then the
6041 * aggregated route must have the ORIGIN attribute with the value
6042 * INCOMPLETE. Otherwise, if at least one route among routes that
6043 * are aggregated has ORIGIN with the value EGP, then the aggregated
6044 * route must have the origin attribute with the value EGP. In all
6045 * other case the value of the ORIGIN attribute of the aggregated
6046 * route is INTERNAL.
6048 origin
= BGP_ORIGIN_IGP
;
6052 if (aggregate
->summary_only
)
6053 (bgp_path_info_extra_get(pinew
))->suppress
++;
6055 switch (pinew
->attr
->origin
) {
6056 case BGP_ORIGIN_INCOMPLETE
:
6057 aggregate
->incomplete_origin_count
++;
6059 case BGP_ORIGIN_EGP
:
6060 aggregate
->egp_origin_count
++;
6068 if (aggregate
->incomplete_origin_count
> 0)
6069 origin
= BGP_ORIGIN_INCOMPLETE
;
6070 else if (aggregate
->egp_origin_count
> 0)
6071 origin
= BGP_ORIGIN_EGP
;
6073 if (aggregate
->as_set
) {
6074 /* Compute aggregate route's as-path.
6076 bgp_compute_aggregate_aspath(aggregate
,
6077 pinew
->attr
->aspath
);
6079 /* Compute aggregate route's community.
6081 if (pinew
->attr
->community
)
6082 bgp_compute_aggregate_community(
6084 pinew
->attr
->community
);
6086 /* Compute aggregate route's extended community.
6088 if (pinew
->attr
->ecommunity
)
6089 bgp_compute_aggregate_ecommunity(
6091 pinew
->attr
->ecommunity
);
6093 /* Compute aggregate route's large community.
6095 if (pinew
->attr
->lcommunity
)
6096 bgp_compute_aggregate_lcommunity(
6098 pinew
->attr
->lcommunity
);
6100 /* Retrieve aggregate route's as-path.
6102 if (aggregate
->aspath
)
6103 aspath
= aspath_dup(aggregate
->aspath
);
6105 /* Retrieve aggregate route's community.
6107 if (aggregate
->community
)
6108 community
= community_dup(aggregate
->community
);
6110 /* Retrieve aggregate route's ecommunity.
6112 if (aggregate
->ecommunity
)
6113 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6115 /* Retrieve aggregate route's lcommunity.
6117 if (aggregate
->lcommunity
)
6118 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6121 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6122 aspath
, community
, ecommunity
,
6123 lcommunity
, atomic_aggregate
, aggregate
);
6126 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6128 struct bgp_path_info
*pi
,
6129 struct bgp_aggregate
*aggregate
,
6130 struct prefix
*aggr_p
)
6133 struct aspath
*aspath
= NULL
;
6134 uint8_t atomic_aggregate
= 0;
6135 struct community
*community
= NULL
;
6136 struct ecommunity
*ecommunity
= NULL
;
6137 struct lcommunity
*lcommunity
= NULL
;
6138 unsigned long match
= 0;
6140 if (BGP_PATH_HOLDDOWN(pi
))
6143 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6146 if (aggregate
->summary_only
6148 && pi
->extra
->suppress
> 0) {
6149 pi
->extra
->suppress
--;
6151 if (pi
->extra
->suppress
== 0) {
6152 bgp_path_info_set_flag(pi
->net
, pi
,
6153 BGP_PATH_ATTR_CHANGED
);
6158 if (aggregate
->count
> 0)
6161 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6162 aggregate
->incomplete_origin_count
--;
6163 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6164 aggregate
->egp_origin_count
--;
6166 if (aggregate
->as_set
) {
6167 /* Remove as-path from aggregate.
6169 bgp_remove_aspath_from_aggregate(aggregate
,
6172 if (pi
->attr
->community
)
6173 /* Remove community from aggregate.
6175 bgp_remove_community_from_aggregate(
6177 pi
->attr
->community
);
6179 if (pi
->attr
->ecommunity
)
6180 /* Remove ecommunity from aggregate.
6182 bgp_remove_ecommunity_from_aggregate(
6184 pi
->attr
->ecommunity
);
6186 if (pi
->attr
->lcommunity
)
6187 /* Remove lcommunity from aggregate.
6189 bgp_remove_lcommunity_from_aggregate(
6191 pi
->attr
->lcommunity
);
6194 /* If this node was suppressed, process the change. */
6196 bgp_process(bgp
, pi
->net
, afi
, safi
);
6198 origin
= BGP_ORIGIN_IGP
;
6199 if (aggregate
->incomplete_origin_count
> 0)
6200 origin
= BGP_ORIGIN_INCOMPLETE
;
6201 else if (aggregate
->egp_origin_count
> 0)
6202 origin
= BGP_ORIGIN_EGP
;
6204 if (aggregate
->as_set
) {
6205 /* Retrieve aggregate route's as-path.
6207 if (aggregate
->aspath
)
6208 aspath
= aspath_dup(aggregate
->aspath
);
6210 /* Retrieve aggregate route's community.
6212 if (aggregate
->community
)
6213 community
= community_dup(aggregate
->community
);
6215 /* Retrieve aggregate route's ecommunity.
6217 if (aggregate
->ecommunity
)
6218 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6220 /* Retrieve aggregate route's lcommunity.
6222 if (aggregate
->lcommunity
)
6223 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6226 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6227 aspath
, community
, ecommunity
,
6228 lcommunity
, atomic_aggregate
, aggregate
);
6231 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
6232 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6234 struct bgp_node
*child
;
6235 struct bgp_node
*rn
;
6236 struct bgp_aggregate
*aggregate
;
6237 struct bgp_table
*table
;
6239 table
= bgp
->aggregate
[afi
][safi
];
6241 /* No aggregates configured. */
6242 if (bgp_table_top_nolock(table
) == NULL
)
6245 if (p
->prefixlen
== 0)
6248 if (BGP_PATH_HOLDDOWN(pi
))
6251 child
= bgp_node_get(table
, p
);
6253 /* Aggregate address configuration check. */
6254 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6255 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6256 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6257 bgp_add_route_to_aggregate(bgp
, &rn
->p
, pi
, afi
,
6261 bgp_unlock_node(child
);
6264 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6265 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6267 struct bgp_node
*child
;
6268 struct bgp_node
*rn
;
6269 struct bgp_aggregate
*aggregate
;
6270 struct bgp_table
*table
;
6272 table
= bgp
->aggregate
[afi
][safi
];
6274 /* No aggregates configured. */
6275 if (bgp_table_top_nolock(table
) == NULL
)
6278 if (p
->prefixlen
== 0)
6281 child
= bgp_node_get(table
, p
);
6283 /* Aggregate address configuration check. */
6284 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6285 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6286 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6287 bgp_remove_route_from_aggregate(bgp
, afi
, safi
,
6288 del
, aggregate
, &rn
->p
);
6291 bgp_unlock_node(child
);
6294 /* Aggregate route attribute. */
6295 #define AGGREGATE_SUMMARY_ONLY 1
6296 #define AGGREGATE_AS_SET 1
6298 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6299 afi_t afi
, safi_t safi
)
6301 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6304 struct bgp_node
*rn
;
6305 struct bgp_aggregate
*aggregate
;
6307 /* Convert string to prefix structure. */
6308 ret
= str2prefix(prefix_str
, &p
);
6310 vty_out(vty
, "Malformed prefix\n");
6311 return CMD_WARNING_CONFIG_FAILED
;
6315 /* Old configuration check. */
6316 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6319 "%% There is no aggregate-address configuration.\n");
6320 return CMD_WARNING_CONFIG_FAILED
;
6323 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6324 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6325 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6326 NULL
, NULL
, 0, aggregate
);
6328 /* Unlock aggregate address configuration. */
6329 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6331 if (aggregate
->community
)
6332 community_free(&aggregate
->community
);
6334 if (aggregate
->community_hash
) {
6335 /* Delete all communities in the hash.
6337 hash_clean(aggregate
->community_hash
,
6338 bgp_aggr_community_remove
);
6339 /* Free up the community_hash.
6341 hash_free(aggregate
->community_hash
);
6344 if (aggregate
->ecommunity
)
6345 ecommunity_free(&aggregate
->ecommunity
);
6347 if (aggregate
->ecommunity_hash
) {
6348 /* Delete all ecommunities in the hash.
6350 hash_clean(aggregate
->ecommunity_hash
,
6351 bgp_aggr_ecommunity_remove
);
6352 /* Free up the ecommunity_hash.
6354 hash_free(aggregate
->ecommunity_hash
);
6357 if (aggregate
->lcommunity
)
6358 lcommunity_free(&aggregate
->lcommunity
);
6360 if (aggregate
->lcommunity_hash
) {
6361 /* Delete all lcommunities in the hash.
6363 hash_clean(aggregate
->lcommunity_hash
,
6364 bgp_aggr_lcommunity_remove
);
6365 /* Free up the lcommunity_hash.
6367 hash_free(aggregate
->lcommunity_hash
);
6370 if (aggregate
->aspath
)
6371 aspath_free(aggregate
->aspath
);
6373 if (aggregate
->aspath_hash
) {
6374 /* Delete all as-paths in the hash.
6376 hash_clean(aggregate
->aspath_hash
,
6377 bgp_aggr_aspath_remove
);
6378 /* Free up the aspath_hash.
6380 hash_free(aggregate
->aspath_hash
);
6383 bgp_aggregate_free(aggregate
);
6384 bgp_unlock_node(rn
);
6385 bgp_unlock_node(rn
);
6390 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6391 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
6393 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6396 struct bgp_node
*rn
;
6397 struct bgp_aggregate
*aggregate
;
6399 /* Convert string to prefix structure. */
6400 ret
= str2prefix(prefix_str
, &p
);
6402 vty_out(vty
, "Malformed prefix\n");
6403 return CMD_WARNING_CONFIG_FAILED
;
6407 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6408 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6409 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6411 return CMD_WARNING_CONFIG_FAILED
;
6414 /* Old configuration check. */
6415 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6417 if (bgp_node_has_bgp_path_info_data(rn
)) {
6418 vty_out(vty
, "There is already same aggregate network.\n");
6419 /* try to remove the old entry */
6420 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6422 vty_out(vty
, "Error deleting aggregate.\n");
6423 bgp_unlock_node(rn
);
6424 return CMD_WARNING_CONFIG_FAILED
;
6428 /* Make aggregate address structure. */
6429 aggregate
= bgp_aggregate_new();
6430 aggregate
->summary_only
= summary_only
;
6431 aggregate
->as_set
= as_set
;
6432 aggregate
->safi
= safi
;
6433 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6435 /* Aggregate address insert into BGP routing table. */
6436 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
6441 DEFUN (aggregate_address
,
6442 aggregate_address_cmd
,
6443 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6444 "Configure BGP aggregate entries\n"
6445 "Aggregate prefix\n"
6446 "Generate AS set path information\n"
6447 "Filter more specific routes from updates\n"
6448 "Filter more specific routes from updates\n"
6449 "Generate AS set path information\n")
6452 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6453 char *prefix
= argv
[idx
]->arg
;
6455 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6457 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6458 ? AGGREGATE_SUMMARY_ONLY
6461 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6462 summary_only
, as_set
);
6465 DEFUN (aggregate_address_mask
,
6466 aggregate_address_mask_cmd
,
6467 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6468 "Configure BGP aggregate entries\n"
6469 "Aggregate address\n"
6471 "Generate AS set path information\n"
6472 "Filter more specific routes from updates\n"
6473 "Filter more specific routes from updates\n"
6474 "Generate AS set path information\n")
6477 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6478 char *prefix
= argv
[idx
]->arg
;
6479 char *mask
= argv
[idx
+ 1]->arg
;
6481 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6483 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6484 ? AGGREGATE_SUMMARY_ONLY
6487 char prefix_str
[BUFSIZ
];
6488 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6491 vty_out(vty
, "%% Inconsistent address and mask\n");
6492 return CMD_WARNING_CONFIG_FAILED
;
6495 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6496 summary_only
, as_set
);
6499 DEFUN (no_aggregate_address
,
6500 no_aggregate_address_cmd
,
6501 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6503 "Configure BGP aggregate entries\n"
6504 "Aggregate prefix\n"
6505 "Generate AS set path information\n"
6506 "Filter more specific routes from updates\n"
6507 "Filter more specific routes from updates\n"
6508 "Generate AS set path information\n")
6511 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6512 char *prefix
= argv
[idx
]->arg
;
6513 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6516 DEFUN (no_aggregate_address_mask
,
6517 no_aggregate_address_mask_cmd
,
6518 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6520 "Configure BGP aggregate entries\n"
6521 "Aggregate address\n"
6523 "Generate AS set path information\n"
6524 "Filter more specific routes from updates\n"
6525 "Filter more specific routes from updates\n"
6526 "Generate AS set path information\n")
6529 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6530 char *prefix
= argv
[idx
]->arg
;
6531 char *mask
= argv
[idx
+ 1]->arg
;
6533 char prefix_str
[BUFSIZ
];
6534 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6537 vty_out(vty
, "%% Inconsistent address and mask\n");
6538 return CMD_WARNING_CONFIG_FAILED
;
6541 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6544 DEFUN (ipv6_aggregate_address
,
6545 ipv6_aggregate_address_cmd
,
6546 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>]",
6547 "Configure BGP aggregate entries\n"
6548 "Aggregate prefix\n"
6549 "Generate AS set path information\n"
6550 "Filter more specific routes from updates\n"
6551 "Filter more specific routes from updates\n"
6552 "Generate AS set path information\n")
6555 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6556 char *prefix
= argv
[idx
]->arg
;
6558 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6561 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6562 ? AGGREGATE_SUMMARY_ONLY
6564 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6568 DEFUN (no_ipv6_aggregate_address
,
6569 no_ipv6_aggregate_address_cmd
,
6570 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>]",
6572 "Configure BGP aggregate entries\n"
6573 "Aggregate prefix\n"
6574 "Generate AS set path information\n"
6575 "Filter more specific routes from updates\n"
6576 "Filter more specific routes from updates\n"
6577 "Generate AS set path information\n")
6580 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6581 char *prefix
= argv
[idx
]->arg
;
6582 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6585 /* Redistribute route treatment. */
6586 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6587 const union g_addr
*nexthop
, ifindex_t ifindex
,
6588 enum nexthop_types_t nhtype
, uint32_t metric
,
6589 uint8_t type
, unsigned short instance
,
6592 struct bgp_path_info
*new;
6593 struct bgp_path_info
*bpi
;
6594 struct bgp_path_info rmap_path
;
6595 struct bgp_node
*bn
;
6597 struct attr
*new_attr
;
6600 struct bgp_redist
*red
;
6602 /* Make default attribute. */
6603 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6606 case NEXTHOP_TYPE_IFINDEX
:
6608 case NEXTHOP_TYPE_IPV4
:
6609 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6610 attr
.nexthop
= nexthop
->ipv4
;
6612 case NEXTHOP_TYPE_IPV6
:
6613 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6614 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6615 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6617 case NEXTHOP_TYPE_BLACKHOLE
:
6618 switch (p
->family
) {
6620 attr
.nexthop
.s_addr
= INADDR_ANY
;
6623 memset(&attr
.mp_nexthop_global
, 0,
6624 sizeof(attr
.mp_nexthop_global
));
6625 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6630 attr
.nh_ifindex
= ifindex
;
6633 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6636 afi
= family2afi(p
->family
);
6638 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6640 struct attr attr_new
;
6642 /* Copy attribute for modification. */
6643 bgp_attr_dup(&attr_new
, &attr
);
6645 if (red
->redist_metric_flag
)
6646 attr_new
.med
= red
->redist_metric
;
6648 /* Apply route-map. */
6649 if (red
->rmap
.name
) {
6650 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6651 rmap_path
.peer
= bgp
->peer_self
;
6652 rmap_path
.attr
= &attr_new
;
6654 SET_FLAG(bgp
->peer_self
->rmap_type
,
6655 PEER_RMAP_TYPE_REDISTRIBUTE
);
6657 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6660 bgp
->peer_self
->rmap_type
= 0;
6662 if (ret
== RMAP_DENYMATCH
) {
6663 /* Free uninterned attribute. */
6664 bgp_attr_flush(&attr_new
);
6666 /* Unintern original. */
6667 aspath_unintern(&attr
.aspath
);
6668 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6673 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6674 bgp_attr_add_gshut_community(&attr_new
);
6676 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6677 SAFI_UNICAST
, p
, NULL
);
6679 new_attr
= bgp_attr_intern(&attr_new
);
6681 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
6683 if (bpi
->peer
== bgp
->peer_self
6684 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6688 /* Ensure the (source route) type is updated. */
6690 if (attrhash_cmp(bpi
->attr
, new_attr
)
6691 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6692 bgp_attr_unintern(&new_attr
);
6693 aspath_unintern(&attr
.aspath
);
6694 bgp_unlock_node(bn
);
6697 /* The attribute is changed. */
6698 bgp_path_info_set_flag(bn
, bpi
,
6699 BGP_PATH_ATTR_CHANGED
);
6701 /* Rewrite BGP route information. */
6702 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6703 bgp_path_info_restore(bn
, bpi
);
6705 bgp_aggregate_decrement(
6706 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6707 bgp_attr_unintern(&bpi
->attr
);
6708 bpi
->attr
= new_attr
;
6709 bpi
->uptime
= bgp_clock();
6711 /* Process change. */
6712 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6714 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6715 bgp_unlock_node(bn
);
6716 aspath_unintern(&attr
.aspath
);
6718 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6720 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6722 vpn_leak_from_vrf_update(
6723 bgp_get_default(), bgp
, bpi
);
6729 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6730 bgp
->peer_self
, new_attr
, bn
);
6731 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6733 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6734 bgp_path_info_add(bn
, new);
6735 bgp_unlock_node(bn
);
6736 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6738 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6739 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6741 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6745 /* Unintern original. */
6746 aspath_unintern(&attr
.aspath
);
6749 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6750 unsigned short instance
)
6753 struct bgp_node
*rn
;
6754 struct bgp_path_info
*pi
;
6755 struct bgp_redist
*red
;
6757 afi
= family2afi(p
->family
);
6759 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6761 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6762 SAFI_UNICAST
, p
, NULL
);
6764 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6765 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6769 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6770 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6772 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6775 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6776 bgp_path_info_delete(rn
, pi
);
6777 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6779 bgp_unlock_node(rn
);
6783 /* Withdraw specified route type's route. */
6784 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6785 unsigned short instance
)
6787 struct bgp_node
*rn
;
6788 struct bgp_path_info
*pi
;
6789 struct bgp_table
*table
;
6791 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6793 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6794 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6795 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6796 && pi
->instance
== instance
)
6800 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6801 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6803 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6806 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
6808 bgp_path_info_delete(rn
, pi
);
6809 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6814 /* Static function to display route. */
6815 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6822 if (p
->family
== AF_INET
) {
6826 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6829 json_object_string_add(json
, "prefix",
6830 inet_ntop(p
->family
,
6833 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6834 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6835 json_object_string_add(json
, "network", buf2
);
6837 } else if (p
->family
== AF_ETHERNET
) {
6838 prefix2str(p
, buf
, PREFIX_STRLEN
);
6839 len
= vty_out(vty
, "%s", buf
);
6840 } else if (p
->family
== AF_EVPN
) {
6844 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6847 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6848 } else if (p
->family
== AF_FLOWSPEC
) {
6849 route_vty_out_flowspec(vty
, p
, NULL
,
6851 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6852 NLRI_STRING_FORMAT_MIN
, json
);
6857 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6860 json_object_string_add(json
, "prefix",
6861 inet_ntop(p
->family
,
6864 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6865 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6866 json_object_string_add(json
, "network", buf2
);
6873 vty_out(vty
, "\n%*s", 20, " ");
6875 vty_out(vty
, "%*s", len
, " ");
6879 enum bgp_display_type
{
6883 /* Print the short form route status for a bgp_path_info */
6884 static void route_vty_short_status_out(struct vty
*vty
,
6885 struct bgp_path_info
*path
,
6886 json_object
*json_path
)
6890 /* Route status display. */
6891 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6892 json_object_boolean_true_add(json_path
, "removed");
6894 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6895 json_object_boolean_true_add(json_path
, "stale");
6897 if (path
->extra
&& path
->extra
->suppress
)
6898 json_object_boolean_true_add(json_path
, "suppressed");
6900 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6901 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6902 json_object_boolean_true_add(json_path
, "valid");
6905 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6906 json_object_boolean_true_add(json_path
, "history");
6908 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6909 json_object_boolean_true_add(json_path
, "damped");
6911 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6912 json_object_boolean_true_add(json_path
, "bestpath");
6914 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6915 json_object_boolean_true_add(json_path
, "multipath");
6917 /* Internal route. */
6918 if ((path
->peer
->as
)
6919 && (path
->peer
->as
== path
->peer
->local_as
))
6920 json_object_string_add(json_path
, "pathFrom",
6923 json_object_string_add(json_path
, "pathFrom",
6929 /* Route status display. */
6930 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6932 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6934 else if (path
->extra
&& path
->extra
->suppress
)
6936 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6937 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6943 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6945 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6947 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6949 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6954 /* Internal route. */
6955 if (path
->peer
&& (path
->peer
->as
)
6956 && (path
->peer
->as
== path
->peer
->local_as
))
6962 static char *bgp_nexthop_fqdn(struct peer
*peer
)
6964 if (peer
->hostname
&& bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
))
6965 return peer
->hostname
;
6969 /* called from terminal list command */
6970 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
6971 struct bgp_path_info
*path
, int display
, safi_t safi
,
6972 json_object
*json_paths
)
6975 json_object
*json_path
= NULL
;
6976 json_object
*json_nexthops
= NULL
;
6977 json_object
*json_nexthop_global
= NULL
;
6978 json_object
*json_nexthop_ll
= NULL
;
6979 json_object
*json_ext_community
= NULL
;
6980 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6982 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
6983 bool nexthop_othervrf
= false;
6984 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6985 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
6986 char *nexthop_fqdn
= bgp_nexthop_fqdn(path
->peer
);
6989 json_path
= json_object_new_object();
6991 /* short status lead text */
6992 route_vty_short_status_out(vty
, path
, json_path
);
6995 /* print prefix and mask */
6997 route_vty_out_route(p
, vty
, json_path
);
6999 vty_out(vty
, "%*s", 17, " ");
7001 route_vty_out_route(p
, vty
, json_path
);
7004 /* Print attribute */
7008 json_object_array_add(json_paths
, json_path
);
7016 * If vrf id of nexthop is different from that of prefix,
7017 * set up printable string to append
7019 if (path
->extra
&& path
->extra
->bgp_orig
) {
7020 const char *self
= "";
7025 nexthop_othervrf
= true;
7026 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7028 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
7029 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
7030 "@%s%s", VRFID_NONE_STR
, self
);
7032 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
7033 path
->extra
->bgp_orig
->vrf_id
, self
);
7035 if (path
->extra
->bgp_orig
->inst_type
7036 != BGP_INSTANCE_TYPE_DEFAULT
)
7038 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
7040 const char *self
= "";
7045 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
7049 * For ENCAP and EVPN routes, nexthop address family is not
7050 * neccessarily the same as the prefix address family.
7051 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7052 * EVPN routes are also exchanged with a MP nexthop. Currently,
7054 * is only IPv4, the value will be present in either
7056 * attr->mp_nexthop_global_in
7058 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
7061 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7065 sprintf(nexthop
, "%s",
7066 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7070 sprintf(nexthop
, "%s",
7071 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7075 sprintf(nexthop
, "?");
7080 json_nexthop_global
= json_object_new_object();
7082 json_object_string_add(
7083 json_nexthop_global
, "afi",
7084 nexthop_fqdn
? "fqdn"
7085 : (af
== AF_INET
) ? "ip" : "ipv6");
7086 json_object_string_add(
7087 json_nexthop_global
,
7088 nexthop_fqdn
? "fqdn"
7089 : (af
== AF_INET
) ? "ip" : "ipv6",
7090 nexthop_fqdn
? nexthop_fqdn
: nexthop
);
7091 json_object_boolean_true_add(json_nexthop_global
,
7094 vty_out(vty
, "%s%s",
7095 nexthop_fqdn
? nexthop_fqdn
: nexthop
,
7097 } else if (safi
== SAFI_EVPN
) {
7099 json_nexthop_global
= json_object_new_object();
7101 json_object_string_add(
7102 json_nexthop_global
,
7103 nexthop_fqdn
? "fqdn" : "ip",
7104 nexthop_fqdn
? nexthop_fqdn
7105 : inet_ntoa(attr
->nexthop
));
7106 json_object_string_add(json_nexthop_global
, "afi",
7108 json_object_boolean_true_add(json_nexthop_global
,
7111 vty_out(vty
, "%-16s%s",
7112 nexthop_fqdn
?: inet_ntoa(attr
->nexthop
),
7114 } else if (safi
== SAFI_FLOWSPEC
) {
7115 if (attr
->nexthop
.s_addr
!= 0) {
7117 json_nexthop_global
= json_object_new_object();
7118 json_object_string_add(
7119 json_nexthop_global
,
7120 nexthop_fqdn
? "fqdn" : "ip",
7123 : inet_ntoa(attr
->nexthop
));
7124 json_object_string_add(json_nexthop_global
,
7126 json_object_boolean_true_add(
7127 json_nexthop_global
,
7130 vty_out(vty
, "%-16s",
7133 : inet_ntoa(attr
->nexthop
));
7136 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7138 json_nexthop_global
= json_object_new_object();
7140 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
7141 json_object_string_add(
7142 json_nexthop_global
,
7143 nexthop_fqdn
? "fqdn" : "ip",
7147 attr
->mp_nexthop_global_in
));
7149 json_object_string_add(
7150 json_nexthop_global
,
7151 nexthop_fqdn
? "fqdn" : "ip",
7154 : inet_ntoa(attr
->nexthop
));
7156 json_object_string_add(json_nexthop_global
, "afi",
7158 json_object_boolean_true_add(json_nexthop_global
,
7163 snprintf(buf
, sizeof(buf
), "%s%s",
7164 nexthop_fqdn
? nexthop_fqdn
7165 : inet_ntoa(attr
->nexthop
),
7167 vty_out(vty
, "%-16s", buf
);
7172 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7177 json_nexthop_global
= json_object_new_object();
7178 json_object_string_add(
7179 json_nexthop_global
,
7180 nexthop_fqdn
? "fqdn" : "ip",
7183 : inet_ntop(AF_INET6
,
7184 &attr
->mp_nexthop_global
,
7186 json_object_string_add(json_nexthop_global
, "afi",
7188 json_object_string_add(json_nexthop_global
, "scope",
7191 /* We display both LL & GL if both have been
7193 if ((attr
->mp_nexthop_len
== 32)
7194 || (path
->peer
->conf_if
)) {
7195 json_nexthop_ll
= json_object_new_object();
7196 json_object_string_add(
7198 nexthop_fqdn
? "fqdn" : "ip",
7203 &attr
->mp_nexthop_local
,
7205 json_object_string_add(json_nexthop_ll
, "afi",
7207 json_object_string_add(json_nexthop_ll
, "scope",
7210 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7211 &attr
->mp_nexthop_local
)
7213 && !attr
->mp_nexthop_prefer_global
)
7214 json_object_boolean_true_add(
7215 json_nexthop_ll
, "used");
7217 json_object_boolean_true_add(
7218 json_nexthop_global
, "used");
7220 json_object_boolean_true_add(
7221 json_nexthop_global
, "used");
7223 /* Display LL if LL/Global both in table unless
7224 * prefer-global is set */
7225 if (((attr
->mp_nexthop_len
== 32)
7226 && !attr
->mp_nexthop_prefer_global
)
7227 || (path
->peer
->conf_if
)) {
7228 if (path
->peer
->conf_if
) {
7229 len
= vty_out(vty
, "%s",
7230 path
->peer
->conf_if
);
7231 len
= 16 - len
; /* len of IPv6
7237 vty_out(vty
, "\n%*s", 36, " ");
7239 vty_out(vty
, "%*s", len
, " ");
7247 &attr
->mp_nexthop_local
,
7253 vty_out(vty
, "\n%*s", 36, " ");
7255 vty_out(vty
, "%*s", len
, " ");
7264 &attr
->mp_nexthop_global
,
7270 vty_out(vty
, "\n%*s", 36, " ");
7272 vty_out(vty
, "%*s", len
, " ");
7278 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7282 * Adding "metric" field to match with corresponding
7283 * CLI. "med" will be deprecated in future.
7285 json_object_int_add(json_path
, "med", attr
->med
);
7286 json_object_int_add(json_path
, "metric", attr
->med
);
7288 vty_out(vty
, "%10u", attr
->med
);
7289 else if (!json_paths
)
7293 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7297 * Adding "locPrf" field to match with corresponding
7298 * CLI. "localPref" will be deprecated in future.
7300 json_object_int_add(json_path
, "localpref",
7302 json_object_int_add(json_path
, "locPrf",
7305 vty_out(vty
, "%7u", attr
->local_pref
);
7306 else if (!json_paths
)
7310 json_object_int_add(json_path
, "weight", attr
->weight
);
7312 vty_out(vty
, "%7u ", attr
->weight
);
7316 json_object_string_add(
7317 json_path
, "peerId",
7318 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7326 * Adding "path" field to match with corresponding
7327 * CLI. "aspath" will be deprecated in future.
7329 json_object_string_add(json_path
, "aspath",
7331 json_object_string_add(json_path
, "path",
7334 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7339 json_object_string_add(json_path
, "origin",
7340 bgp_origin_long_str
[attr
->origin
]);
7342 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7345 if (safi
== SAFI_EVPN
&&
7346 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7347 json_ext_community
= json_object_new_object();
7348 json_object_string_add(json_ext_community
,
7350 attr
->ecommunity
->str
);
7351 json_object_object_add(json_path
,
7352 "extendedCommunity",
7353 json_ext_community
);
7357 json_object_boolean_true_add(json_path
,
7358 "announceNexthopSelf");
7359 if (nexthop_othervrf
) {
7360 json_object_string_add(json_path
, "nhVrfName",
7363 json_object_int_add(json_path
, "nhVrfId",
7364 ((nexthop_vrfid
== VRF_UNKNOWN
)
7366 : (int)nexthop_vrfid
));
7371 if (json_nexthop_global
|| json_nexthop_ll
) {
7372 json_nexthops
= json_object_new_array();
7374 if (json_nexthop_global
)
7375 json_object_array_add(json_nexthops
,
7376 json_nexthop_global
);
7378 if (json_nexthop_ll
)
7379 json_object_array_add(json_nexthops
,
7382 json_object_object_add(json_path
, "nexthops",
7386 json_object_array_add(json_paths
, json_path
);
7390 if (safi
== SAFI_EVPN
&&
7391 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7392 vty_out(vty
, "%*s", 20, " ");
7393 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
7397 /* prints an additional line, indented, with VNC info, if
7399 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7400 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7405 /* called from terminal list command */
7406 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7407 safi_t safi
, bool use_json
, json_object
*json_ar
)
7409 json_object
*json_status
= NULL
;
7410 json_object
*json_net
= NULL
;
7413 /* Route status display. */
7415 json_status
= json_object_new_object();
7416 json_net
= json_object_new_object();
7423 /* print prefix and mask */
7425 json_object_string_add(
7426 json_net
, "addrPrefix",
7427 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
7428 json_object_int_add(json_net
, "prefixLen", p
->prefixlen
);
7429 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7430 json_object_string_add(json_net
, "network", buf2
);
7432 route_vty_out_route(p
, vty
, NULL
);
7434 /* Print attribute */
7437 if (p
->family
== AF_INET
7438 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7439 || safi
== SAFI_EVPN
7440 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7441 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7442 || safi
== SAFI_EVPN
)
7443 json_object_string_add(
7444 json_net
, "nextHop",
7446 attr
->mp_nexthop_global_in
));
7448 json_object_string_add(
7449 json_net
, "nextHop",
7450 inet_ntoa(attr
->nexthop
));
7451 } else if (p
->family
== AF_INET6
7452 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7455 json_object_string_add(
7456 json_net
, "nextHopGlobal",
7458 &attr
->mp_nexthop_global
, buf
,
7463 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7464 json_object_int_add(json_net
, "metric",
7467 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7470 * Adding "locPrf" field to match with
7471 * corresponding CLI. "localPref" will be
7472 * deprecated in future.
7474 json_object_int_add(json_net
, "localPref",
7476 json_object_int_add(json_net
, "locPrf",
7480 json_object_int_add(json_net
, "weight", attr
->weight
);
7486 * Adding "path" field to match with
7487 * corresponding CLI. "localPref" will be
7488 * deprecated in future.
7490 json_object_string_add(json_net
, "asPath",
7492 json_object_string_add(json_net
, "path",
7497 json_object_string_add(json_net
, "bgpOriginCode",
7498 bgp_origin_str
[attr
->origin
]);
7500 if (p
->family
== AF_INET
7501 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7502 || safi
== SAFI_EVPN
7503 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7504 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7505 || safi
== SAFI_EVPN
)
7506 vty_out(vty
, "%-16s",
7508 attr
->mp_nexthop_global_in
));
7510 vty_out(vty
, "%-16s",
7511 inet_ntoa(attr
->nexthop
));
7512 } else if (p
->family
== AF_INET6
7513 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7520 &attr
->mp_nexthop_global
, buf
,
7524 vty_out(vty
, "\n%*s", 36, " ");
7526 vty_out(vty
, "%*s", len
, " ");
7529 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7530 vty_out(vty
, "%10u", attr
->med
);
7534 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7535 vty_out(vty
, "%7u", attr
->local_pref
);
7539 vty_out(vty
, "%7u ", attr
->weight
);
7543 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7546 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7550 json_object_boolean_true_add(json_status
, "*");
7551 json_object_boolean_true_add(json_status
, ">");
7552 json_object_object_add(json_net
, "appliedStatusSymbols",
7554 char buf_cut
[BUFSIZ
];
7556 prefix2str(p
, buf_cut
, PREFIX_STRLEN
);
7557 json_object_object_add(json_ar
, buf_cut
, json_net
);
7562 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7563 struct bgp_path_info
*path
, int display
, safi_t safi
,
7566 json_object
*json_out
= NULL
;
7568 mpls_label_t label
= MPLS_INVALID_LABEL
;
7574 json_out
= json_object_new_object();
7576 /* short status lead text */
7577 route_vty_short_status_out(vty
, path
, json_out
);
7579 /* print prefix and mask */
7582 route_vty_out_route(p
, vty
, NULL
);
7584 vty_out(vty
, "%*s", 17, " ");
7587 /* Print attribute */
7590 if (((p
->family
== AF_INET
)
7591 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7592 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7593 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7594 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7595 || safi
== SAFI_EVPN
) {
7597 json_object_string_add(
7598 json_out
, "mpNexthopGlobalIn",
7600 attr
->mp_nexthop_global_in
));
7602 vty_out(vty
, "%-16s",
7604 attr
->mp_nexthop_global_in
));
7607 json_object_string_add(
7608 json_out
, "nexthop",
7609 inet_ntoa(attr
->nexthop
));
7611 vty_out(vty
, "%-16s",
7612 inet_ntoa(attr
->nexthop
));
7614 } else if (((p
->family
== AF_INET6
)
7615 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7616 || (safi
== SAFI_EVPN
7617 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7618 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7620 if (attr
->mp_nexthop_len
7621 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7623 json_object_string_add(
7624 json_out
, "mpNexthopGlobalIn",
7627 &attr
->mp_nexthop_global
,
7628 buf_a
, sizeof(buf_a
)));
7633 &attr
->mp_nexthop_global
,
7634 buf_a
, sizeof(buf_a
)));
7635 } else if (attr
->mp_nexthop_len
7636 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7637 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
7638 &attr
->mp_nexthop_global
,
7639 &attr
->mp_nexthop_local
);
7641 json_object_string_add(
7643 "mpNexthopGlobalLocal", buf_a
);
7645 vty_out(vty
, "%s", buf_a
);
7650 label
= decode_label(&path
->extra
->label
[0]);
7652 if (bgp_is_valid_label(&label
)) {
7654 json_object_int_add(json_out
, "notag", label
);
7655 json_object_array_add(json
, json_out
);
7657 vty_out(vty
, "notag/%d", label
);
7663 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7664 struct bgp_path_info
*path
, int display
,
7665 json_object
*json_paths
)
7668 char buf
[BUFSIZ
] = {0};
7669 json_object
*json_path
= NULL
;
7670 json_object
*json_nexthop
= NULL
;
7671 json_object
*json_overlay
= NULL
;
7677 json_path
= json_object_new_object();
7678 json_overlay
= json_object_new_object();
7679 json_nexthop
= json_object_new_object();
7682 /* short status lead text */
7683 route_vty_short_status_out(vty
, path
, json_path
);
7685 /* print prefix and mask */
7687 route_vty_out_route(p
, vty
, json_path
);
7689 vty_out(vty
, "%*s", 17, " ");
7691 /* Print attribute */
7695 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7699 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
7701 vty_out(vty
, "%-16s", buf
);
7703 json_object_string_add(json_nexthop
, "ip", buf
);
7705 json_object_string_add(json_nexthop
, "afi",
7708 json_object_object_add(json_path
, "nexthop",
7713 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
7714 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
7716 vty_out(vty
, "%s(%s)", buf
, buf1
);
7718 json_object_string_add(json_nexthop
,
7721 json_object_string_add(json_nexthop
,
7722 "ipv6LinkLocal", buf1
);
7724 json_object_string_add(json_nexthop
, "afi",
7727 json_object_object_add(json_path
, "nexthop",
7735 json_object_string_add(json_nexthop
, "Error",
7736 "Unsupported address-family");
7740 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7743 vty_out(vty
, "%s", str
);
7745 json_object_string_add(json_overlay
, "esi", str
);
7747 XFREE(MTYPE_TMP
, str
);
7749 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7750 inet_ntop(AF_INET
, &(attr
->evpn_overlay
.gw_ip
.ipv4
),
7752 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7753 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
),
7758 vty_out(vty
, "/%s", buf
);
7760 json_object_string_add(json_overlay
, "gw", buf
);
7762 if (attr
->ecommunity
) {
7764 struct ecommunity_val
*routermac
= ecommunity_lookup(
7765 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7766 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7768 mac
= ecom_mac2str((char *)routermac
->val
);
7771 vty_out(vty
, "/%s", (char *)mac
);
7773 json_object_string_add(json_overlay
,
7776 XFREE(MTYPE_TMP
, mac
);
7783 json_object_object_add(json_path
, "overlay",
7786 json_object_array_add(json_paths
, json_path
);
7791 /* dampening route */
7792 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7793 struct bgp_path_info
*path
, int display
,
7794 safi_t safi
, bool use_json
, json_object
*json
)
7798 char timebuf
[BGP_UPTIME_LEN
];
7800 /* short status lead text */
7801 route_vty_short_status_out(vty
, path
, json
);
7803 /* print prefix and mask */
7806 route_vty_out_route(p
, vty
, NULL
);
7808 vty_out(vty
, "%*s", 17, " ");
7811 len
= vty_out(vty
, "%s", path
->peer
->host
);
7815 vty_out(vty
, "\n%*s", 34, " ");
7818 json_object_int_add(json
, "peerHost", len
);
7820 vty_out(vty
, "%*s", len
, " ");
7824 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
,
7828 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7829 BGP_UPTIME_LEN
, use_json
,
7832 /* Print attribute */
7838 json_object_string_add(json
, "asPath",
7841 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7846 json_object_string_add(json
, "origin",
7847 bgp_origin_str
[attr
->origin
]);
7849 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7856 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7857 struct bgp_path_info
*path
, int display
,
7858 safi_t safi
, bool use_json
, json_object
*json
)
7861 struct bgp_damp_info
*bdi
;
7862 char timebuf
[BGP_UPTIME_LEN
];
7868 bdi
= path
->extra
->damp_info
;
7870 /* short status lead text */
7871 route_vty_short_status_out(vty
, path
, json
);
7873 /* print prefix and mask */
7876 route_vty_out_route(p
, vty
, NULL
);
7878 vty_out(vty
, "%*s", 17, " ");
7881 len
= vty_out(vty
, "%s", path
->peer
->host
);
7885 vty_out(vty
, "\n%*s", 33, " ");
7888 json_object_int_add(json
, "peerHost", len
);
7890 vty_out(vty
, "%*s", len
, " ");
7893 len
= vty_out(vty
, "%d", bdi
->flap
);
7900 json_object_int_add(json
, "bdiFlap", len
);
7902 vty_out(vty
, "%*s", len
, " ");
7906 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7909 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7910 BGP_UPTIME_LEN
, 0, NULL
));
7912 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
7913 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7915 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7916 BGP_UPTIME_LEN
, use_json
, json
);
7919 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7924 vty_out(vty
, "%*s ", 8, " ");
7927 /* Print attribute */
7933 json_object_string_add(json
, "asPath",
7936 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7941 json_object_string_add(json
, "origin",
7942 bgp_origin_str
[attr
->origin
]);
7944 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7950 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7951 int *first
, const char *header
,
7952 json_object
*json_adv_to
)
7954 char buf1
[INET6_ADDRSTRLEN
];
7955 json_object
*json_peer
= NULL
;
7958 /* 'advertised-to' is a dictionary of peers we have advertised
7960 * prefix too. The key is the peer's IP or swpX, the value is
7962 * hostname if we know it and "" if not.
7964 json_peer
= json_object_new_object();
7967 json_object_string_add(json_peer
, "hostname",
7971 json_object_object_add(json_adv_to
, peer
->conf_if
,
7974 json_object_object_add(
7976 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7980 vty_out(vty
, "%s", header
);
7985 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7987 vty_out(vty
, " %s(%s)", peer
->hostname
,
7990 vty_out(vty
, " %s(%s)", peer
->hostname
,
7991 sockunion2str(&peer
->su
, buf1
,
7995 vty_out(vty
, " %s", peer
->conf_if
);
7998 sockunion2str(&peer
->su
, buf1
,
8004 static void route_vty_out_tx_ids(struct vty
*vty
,
8005 struct bgp_addpath_info_data
*d
)
8009 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8010 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
8011 d
->addpath_tx_id
[i
],
8012 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
8016 static const char *bgp_path_selection_reason2str(
8017 enum bgp_path_selection_reason reason
)
8020 case bgp_path_selection_none
:
8021 return "Nothing to Select";
8023 case bgp_path_selection_first
:
8024 return "First path received";
8026 case bgp_path_selection_evpn_sticky_mac
:
8027 return "EVPN Sticky Mac";
8029 case bgp_path_selection_evpn_seq
:
8030 return "EVPN sequence number";
8032 case bgp_path_selection_evpn_lower_ip
:
8033 return "EVPN lower IP";
8035 case bgp_path_selection_weight
:
8038 case bgp_path_selection_local_pref
:
8039 return "Local Pref";
8041 case bgp_path_selection_local_route
:
8042 return "Local Route";
8044 case bgp_path_selection_confed_as_path
:
8045 return "Confederation based AS Path";
8047 case bgp_path_selection_as_path
:
8050 case bgp_path_selection_origin
:
8053 case bgp_path_selection_med
:
8056 case bgp_path_selection_peer
:
8059 case bgp_path_selection_confed
:
8060 return "Confed Peer Type";
8062 case bgp_path_selection_igp_metric
:
8063 return "IGP Metric";
8065 case bgp_path_selection_older
:
8066 return "Older Path";
8068 case bgp_path_selection_router_id
:
8071 case bgp_path_selection_cluster_length
:
8072 return "Cluser length";
8074 case bgp_path_selection_stale
:
8075 return "Path Staleness";
8077 case bgp_path_selection_local_configured
:
8078 return "Locally configured route";
8080 case bgp_path_selection_neighbor_ip
:
8081 return "Neighbor IP";
8083 case bgp_path_selection_default
:
8084 return "Nothing left to compare";
8087 return "Invalid (internal error)";
8090 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
8091 struct bgp_node
*bn
, struct bgp_path_info
*path
,
8092 afi_t afi
, safi_t safi
, json_object
*json_paths
)
8094 char buf
[INET6_ADDRSTRLEN
];
8096 char buf2
[EVPN_ROUTE_STRLEN
];
8098 int sockunion_vty_out(struct vty
*, union sockunion
*);
8100 json_object
*json_bestpath
= NULL
;
8101 json_object
*json_cluster_list
= NULL
;
8102 json_object
*json_cluster_list_list
= NULL
;
8103 json_object
*json_ext_community
= NULL
;
8104 json_object
*json_last_update
= NULL
;
8105 json_object
*json_pmsi
= NULL
;
8106 json_object
*json_nexthop_global
= NULL
;
8107 json_object
*json_nexthop_ll
= NULL
;
8108 json_object
*json_nexthops
= NULL
;
8109 json_object
*json_path
= NULL
;
8110 json_object
*json_peer
= NULL
;
8111 json_object
*json_string
= NULL
;
8112 json_object
*json_adv_to
= NULL
;
8114 struct listnode
*node
, *nnode
;
8116 int addpath_capable
;
8118 unsigned int first_as
;
8120 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8122 char *nexthop_fqdn
= bgp_nexthop_fqdn(path
->peer
);
8125 json_path
= json_object_new_object();
8126 json_peer
= json_object_new_object();
8127 json_nexthop_global
= json_object_new_object();
8130 if (!json_paths
&& safi
== SAFI_EVPN
) {
8133 bgp_evpn_route2str((struct prefix_evpn
*)&bn
->p
,
8134 buf2
, sizeof(buf2
));
8135 vty_out(vty
, " Route %s", buf2
);
8137 if (path
->extra
&& path
->extra
->num_labels
) {
8138 bgp_evpn_label2str(path
->extra
->label
,
8139 path
->extra
->num_labels
, tag_buf
,
8141 vty_out(vty
, " VNI %s", tag_buf
);
8144 if (path
->extra
&& path
->extra
->parent
) {
8145 struct bgp_path_info
*parent_ri
;
8146 struct bgp_node
*rn
, *prn
;
8148 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
8149 rn
= parent_ri
->net
;
8150 if (rn
&& rn
->prn
) {
8152 vty_out(vty
, " Imported from %s:%s\n",
8154 (struct prefix_rd
*)&prn
->p
,
8155 buf1
, sizeof(buf1
)),
8164 /* Line1 display AS-path, Aggregator */
8167 if (!attr
->aspath
->json
)
8168 aspath_str_update(attr
->aspath
, true);
8169 json_object_lock(attr
->aspath
->json
);
8170 json_object_object_add(json_path
, "aspath",
8171 attr
->aspath
->json
);
8173 if (attr
->aspath
->segments
)
8174 aspath_print_vty(vty
, " %s",
8177 vty_out(vty
, " Local");
8181 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
8183 json_object_boolean_true_add(json_path
,
8186 vty_out(vty
, ", (removed)");
8189 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
8191 json_object_boolean_true_add(json_path
,
8194 vty_out(vty
, ", (stale)");
8197 if (CHECK_FLAG(attr
->flag
,
8198 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
8200 json_object_int_add(json_path
, "aggregatorAs",
8201 attr
->aggregator_as
);
8202 json_object_string_add(
8203 json_path
, "aggregatorId",
8204 inet_ntoa(attr
->aggregator_addr
));
8206 vty_out(vty
, ", (aggregated by %u %s)",
8207 attr
->aggregator_as
,
8208 inet_ntoa(attr
->aggregator_addr
));
8212 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8213 PEER_FLAG_REFLECTOR_CLIENT
)) {
8215 json_object_boolean_true_add(
8216 json_path
, "rxedFromRrClient");
8218 vty_out(vty
, ", (Received from a RR-client)");
8221 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8222 PEER_FLAG_RSERVER_CLIENT
)) {
8224 json_object_boolean_true_add(
8225 json_path
, "rxedFromRsClient");
8227 vty_out(vty
, ", (Received from a RS-client)");
8230 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8232 json_object_boolean_true_add(
8233 json_path
, "dampeningHistoryEntry");
8235 vty_out(vty
, ", (history entry)");
8236 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
8238 json_object_boolean_true_add(
8239 json_path
, "dampeningSuppressed");
8241 vty_out(vty
, ", (suppressed due to dampening)");
8247 /* Line2 display Next-hop, Neighbor, Router-id */
8248 /* Display the nexthop */
8249 if ((bn
->p
.family
== AF_INET
|| bn
->p
.family
== AF_ETHERNET
8250 || bn
->p
.family
== AF_EVPN
)
8251 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8252 || safi
== SAFI_EVPN
8253 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8254 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8255 || safi
== SAFI_EVPN
) {
8257 json_object_string_add(
8258 json_nexthop_global
,
8259 nexthop_fqdn
? "fqdn" : "ip",
8263 attr
->mp_nexthop_global_in
));
8269 attr
->mp_nexthop_global_in
));
8272 json_object_string_add(
8273 json_nexthop_global
,
8274 nexthop_fqdn
? "fqdn" : "ip",
8288 json_object_string_add(json_nexthop_global
,
8292 json_object_string_add(
8293 json_nexthop_global
,
8294 nexthop_fqdn
? "fqdn" : "ip",
8299 &attr
->mp_nexthop_global
,
8302 json_object_string_add(json_nexthop_global
,
8304 json_object_string_add(json_nexthop_global
,
8312 &attr
->mp_nexthop_global
,
8318 /* Display the IGP cost or 'inaccessible' */
8319 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8321 json_object_boolean_false_add(
8322 json_nexthop_global
, "accessible");
8324 vty_out(vty
, " (inaccessible)");
8326 if (path
->extra
&& path
->extra
->igpmetric
) {
8328 json_object_int_add(
8329 json_nexthop_global
, "metric",
8330 path
->extra
->igpmetric
);
8332 vty_out(vty
, " (metric %u)",
8333 path
->extra
->igpmetric
);
8336 /* IGP cost is 0, display this only for json */
8339 json_object_int_add(json_nexthop_global
,
8344 json_object_boolean_true_add(
8345 json_nexthop_global
, "accessible");
8348 /* Display peer "from" output */
8349 /* This path was originated locally */
8350 if (path
->peer
== bgp
->peer_self
) {
8352 if (safi
== SAFI_EVPN
8353 || (bn
->p
.family
== AF_INET
8354 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8356 json_object_string_add(
8357 json_peer
, "peerId", "0.0.0.0");
8359 vty_out(vty
, " from 0.0.0.0 ");
8362 json_object_string_add(json_peer
,
8365 vty_out(vty
, " from :: ");
8369 json_object_string_add(
8370 json_peer
, "routerId",
8371 inet_ntoa(bgp
->router_id
));
8373 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
8376 /* We RXed this path from one of our peers */
8380 json_object_string_add(
8381 json_peer
, "peerId",
8382 sockunion2str(&path
->peer
->su
, buf
,
8384 json_object_string_add(
8385 json_peer
, "routerId",
8387 &path
->peer
->remote_id
, buf1
,
8390 if (path
->peer
->hostname
)
8391 json_object_string_add(
8392 json_peer
, "hostname",
8393 path
->peer
->hostname
);
8395 if (path
->peer
->domainname
)
8396 json_object_string_add(
8397 json_peer
, "domainname",
8398 path
->peer
->domainname
);
8400 if (path
->peer
->conf_if
)
8401 json_object_string_add(
8402 json_peer
, "interface",
8403 path
->peer
->conf_if
);
8405 if (path
->peer
->conf_if
) {
8406 if (path
->peer
->hostname
8409 BGP_FLAG_SHOW_HOSTNAME
))
8410 vty_out(vty
, " from %s(%s)",
8411 path
->peer
->hostname
,
8412 path
->peer
->conf_if
);
8414 vty_out(vty
, " from %s",
8415 path
->peer
->conf_if
);
8417 if (path
->peer
->hostname
8420 BGP_FLAG_SHOW_HOSTNAME
))
8421 vty_out(vty
, " from %s(%s)",
8422 path
->peer
->hostname
,
8425 vty_out(vty
, " from %s",
8433 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8434 vty_out(vty
, " (%s)",
8435 inet_ntoa(attr
->originator_id
));
8437 vty_out(vty
, " (%s)",
8440 &path
->peer
->remote_id
,
8441 buf1
, sizeof(buf1
)));
8446 * Note when vrfid of nexthop is different from that of prefix
8448 if (path
->extra
&& path
->extra
->bgp_orig
) {
8449 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8454 if (path
->extra
->bgp_orig
->inst_type
8455 == BGP_INSTANCE_TYPE_DEFAULT
)
8457 vn
= VRF_DEFAULT_NAME
;
8459 vn
= path
->extra
->bgp_orig
->name
;
8461 json_object_string_add(json_path
, "nhVrfName",
8464 if (nexthop_vrfid
== VRF_UNKNOWN
) {
8465 json_object_int_add(json_path
,
8468 json_object_int_add(json_path
,
8469 "nhVrfId", (int)nexthop_vrfid
);
8472 if (nexthop_vrfid
== VRF_UNKNOWN
)
8473 vty_out(vty
, " vrf ?");
8475 vty_out(vty
, " vrf %u", nexthop_vrfid
);
8481 json_object_boolean_true_add(json_path
,
8482 "announceNexthopSelf");
8484 vty_out(vty
, " announce-nh-self");
8491 /* display the link-local nexthop */
8492 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8494 json_nexthop_ll
= json_object_new_object();
8495 json_object_string_add(
8497 nexthop_fqdn
? "fqdn" : "ip",
8502 &attr
->mp_nexthop_local
,
8505 json_object_string_add(json_nexthop_ll
, "afi",
8507 json_object_string_add(json_nexthop_ll
, "scope",
8510 json_object_boolean_true_add(json_nexthop_ll
,
8513 if (!attr
->mp_nexthop_prefer_global
)
8514 json_object_boolean_true_add(
8515 json_nexthop_ll
, "used");
8517 json_object_boolean_true_add(
8518 json_nexthop_global
, "used");
8520 vty_out(vty
, " (%s) %s\n",
8522 &attr
->mp_nexthop_local
, buf
,
8524 attr
->mp_nexthop_prefer_global
8529 /* If we do not have a link-local nexthop then we must flag the
8533 json_object_boolean_true_add(
8534 json_nexthop_global
, "used");
8537 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8538 * Int/Ext/Local, Atomic, best */
8540 json_object_string_add(
8541 json_path
, "origin",
8542 bgp_origin_long_str
[attr
->origin
]);
8544 vty_out(vty
, " Origin %s",
8545 bgp_origin_long_str
[attr
->origin
]);
8547 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8551 * Adding "metric" field to match with
8552 * corresponding CLI. "med" will be
8553 * deprecated in future.
8555 json_object_int_add(json_path
, "med",
8557 json_object_int_add(json_path
, "metric",
8560 vty_out(vty
, ", metric %u", attr
->med
);
8563 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8565 json_object_int_add(json_path
, "localpref",
8568 vty_out(vty
, ", localpref %u",
8572 if (attr
->weight
!= 0) {
8574 json_object_int_add(json_path
, "weight",
8577 vty_out(vty
, ", weight %u", attr
->weight
);
8580 if (attr
->tag
!= 0) {
8582 json_object_int_add(json_path
, "tag",
8585 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
8589 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8591 json_object_boolean_false_add(json_path
,
8594 vty_out(vty
, ", invalid");
8595 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8597 json_object_boolean_true_add(json_path
,
8600 vty_out(vty
, ", valid");
8603 if (path
->peer
!= bgp
->peer_self
) {
8604 if (path
->peer
->as
== path
->peer
->local_as
) {
8605 if (CHECK_FLAG(bgp
->config
,
8606 BGP_CONFIG_CONFEDERATION
)) {
8608 json_object_string_add(
8613 ", confed-internal");
8616 json_object_string_add(
8620 vty_out(vty
, ", internal");
8623 if (bgp_confederation_peers_check(
8624 bgp
, path
->peer
->as
)) {
8626 json_object_string_add(
8631 ", confed-external");
8634 json_object_string_add(
8638 vty_out(vty
, ", external");
8641 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8643 json_object_boolean_true_add(json_path
,
8645 json_object_boolean_true_add(json_path
,
8648 vty_out(vty
, ", aggregated, local");
8650 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8652 json_object_boolean_true_add(json_path
,
8655 vty_out(vty
, ", sourced");
8658 json_object_boolean_true_add(json_path
,
8660 json_object_boolean_true_add(json_path
,
8663 vty_out(vty
, ", sourced, local");
8667 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8669 json_object_boolean_true_add(json_path
,
8672 vty_out(vty
, ", atomic-aggregate");
8675 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8676 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8677 && bgp_path_info_mpath_count(path
))) {
8679 json_object_boolean_true_add(json_path
,
8682 vty_out(vty
, ", multipath");
8685 // Mark the bestpath(s)
8686 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8687 first_as
= aspath_get_first_as(attr
->aspath
);
8692 json_object_new_object();
8693 json_object_int_add(json_bestpath
,
8694 "bestpathFromAs", first_as
);
8697 vty_out(vty
, ", bestpath-from-AS %u",
8701 ", bestpath-from-AS Local");
8705 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8709 json_object_new_object();
8710 json_object_boolean_true_add(json_bestpath
,
8712 json_object_string_add(json_bestpath
,
8714 bgp_path_selection_reason2str(bn
->reason
));
8716 vty_out(vty
, ", best");
8717 vty_out(vty
, " (%s)",
8718 bgp_path_selection_reason2str(bn
->reason
));
8723 json_object_object_add(json_path
, "bestpath",
8729 /* Line 4 display Community */
8730 if (attr
->community
) {
8732 if (!attr
->community
->json
)
8733 community_str(attr
->community
, true);
8734 json_object_lock(attr
->community
->json
);
8735 json_object_object_add(json_path
, "community",
8736 attr
->community
->json
);
8738 vty_out(vty
, " Community: %s\n",
8739 attr
->community
->str
);
8743 /* Line 5 display Extended-community */
8744 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8746 json_ext_community
= json_object_new_object();
8747 json_object_string_add(json_ext_community
,
8749 attr
->ecommunity
->str
);
8750 json_object_object_add(json_path
,
8751 "extendedCommunity",
8752 json_ext_community
);
8754 vty_out(vty
, " Extended Community: %s\n",
8755 attr
->ecommunity
->str
);
8759 /* Line 6 display Large community */
8760 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8762 if (!attr
->lcommunity
->json
)
8763 lcommunity_str(attr
->lcommunity
, true);
8764 json_object_lock(attr
->lcommunity
->json
);
8765 json_object_object_add(json_path
,
8767 attr
->lcommunity
->json
);
8769 vty_out(vty
, " Large Community: %s\n",
8770 attr
->lcommunity
->str
);
8774 /* Line 7 display Originator, Cluster-id */
8775 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8776 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8778 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8780 json_object_string_add(
8781 json_path
, "originatorId",
8782 inet_ntoa(attr
->originator_id
));
8784 vty_out(vty
, " Originator: %s",
8785 inet_ntoa(attr
->originator_id
));
8788 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8793 json_object_new_object();
8794 json_cluster_list_list
=
8795 json_object_new_array();
8798 i
< attr
->cluster
->length
/ 4;
8800 json_string
= json_object_new_string(
8804 json_object_array_add(
8805 json_cluster_list_list
,
8809 /* struct cluster_list does not have
8811 * aspath and community do. Add this
8814 json_object_string_add(json_cluster_list,
8815 "string", attr->cluster->str);
8817 json_object_object_add(
8818 json_cluster_list
, "list",
8819 json_cluster_list_list
);
8820 json_object_object_add(
8821 json_path
, "clusterList",
8824 vty_out(vty
, ", Cluster list: ");
8827 i
< attr
->cluster
->length
/ 4;
8841 if (path
->extra
&& path
->extra
->damp_info
)
8842 bgp_damp_info_vty(vty
, path
, json_path
);
8845 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8846 && safi
!= SAFI_EVPN
) {
8847 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8850 json_object_int_add(json_path
, "remoteLabel",
8853 vty_out(vty
, " Remote label: %d\n", label
);
8857 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8859 json_object_int_add(json_path
, "labelIndex",
8862 vty_out(vty
, " Label Index: %d\n",
8866 /* Line 8 display Addpath IDs */
8867 if (path
->addpath_rx_id
8868 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
8870 json_object_int_add(json_path
, "addpathRxId",
8871 path
->addpath_rx_id
);
8873 /* Keep backwards compatibility with the old API
8874 * by putting TX All's ID in the old field
8876 json_object_int_add(
8877 json_path
, "addpathTxId",
8878 path
->tx_addpath
.addpath_tx_id
8881 /* ... but create a specific field for each
8884 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8885 json_object_int_add(
8887 bgp_addpath_names(i
)
8893 vty_out(vty
, " AddPath ID: RX %u, ",
8894 path
->addpath_rx_id
);
8896 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
8900 /* If we used addpath to TX a non-bestpath we need to display
8901 * "Advertised to" on a path-by-path basis
8903 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
8906 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8908 bgp_addpath_encode_tx(peer
, afi
, safi
);
8909 has_adj
= bgp_adj_out_lookup(
8911 bgp_addpath_id_for_peer(
8913 &path
->tx_addpath
));
8915 if ((addpath_capable
&& has_adj
)
8916 || (!addpath_capable
&& has_adj
8917 && CHECK_FLAG(path
->flags
,
8918 BGP_PATH_SELECTED
))) {
8919 if (json_path
&& !json_adv_to
)
8921 json_object_new_object();
8923 route_vty_out_advertised_to(
8932 json_object_object_add(json_path
,
8943 /* Line 9 display Uptime */
8944 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
8946 json_last_update
= json_object_new_object();
8947 json_object_int_add(json_last_update
, "epoch", tbuf
);
8948 json_object_string_add(json_last_update
, "string",
8950 json_object_object_add(json_path
, "lastUpdate",
8953 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8955 /* Line 10 display PMSI tunnel attribute, if present */
8956 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8957 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8958 attr
->pmsi_tnl_type
,
8959 PMSI_TNLTYPE_STR_DEFAULT
);
8962 json_pmsi
= json_object_new_object();
8963 json_object_string_add(json_pmsi
,
8965 json_object_int_add(json_pmsi
,
8967 label2vni(&attr
->label
));
8968 json_object_object_add(json_path
, "pmsi",
8972 " PMSI Tunnel Type: %s, label: %d\n",
8973 str
, label2vni(&attr
->label
));
8978 /* We've constructed the json object for this path, add it to the json
8982 if (json_nexthop_global
|| json_nexthop_ll
) {
8983 json_nexthops
= json_object_new_array();
8985 if (json_nexthop_global
)
8986 json_object_array_add(json_nexthops
,
8987 json_nexthop_global
);
8989 if (json_nexthop_ll
)
8990 json_object_array_add(json_nexthops
,
8993 json_object_object_add(json_path
, "nexthops",
8997 json_object_object_add(json_path
, "peer", json_peer
);
8998 json_object_array_add(json_paths
, json_path
);
9003 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
9004 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9005 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
9007 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9008 const char *prefix_list_str
, afi_t afi
,
9009 safi_t safi
, enum bgp_show_type type
);
9010 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9011 const char *filter
, afi_t afi
, safi_t safi
,
9012 enum bgp_show_type type
);
9013 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9014 const char *rmap_str
, afi_t afi
, safi_t safi
,
9015 enum bgp_show_type type
);
9016 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9017 const char *com
, int exact
, afi_t afi
,
9019 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9020 const char *prefix
, afi_t afi
, safi_t safi
,
9021 enum bgp_show_type type
);
9022 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9023 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
9024 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9025 const char *comstr
, int exact
, afi_t afi
,
9026 safi_t safi
, bool use_json
);
9029 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9030 struct bgp_table
*table
, enum bgp_show_type type
,
9031 void *output_arg
, bool use_json
, char *rd
,
9032 int is_last
, unsigned long *output_cum
,
9033 unsigned long *total_cum
,
9034 unsigned long *json_header_depth
)
9036 struct bgp_path_info
*pi
;
9037 struct bgp_node
*rn
;
9040 unsigned long output_count
= 0;
9041 unsigned long total_count
= 0;
9044 json_object
*json_paths
= NULL
;
9047 if (output_cum
&& *output_cum
!= 0)
9050 if (use_json
&& !*json_header_depth
) {
9052 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
9053 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9054 " \"localAS\": %u,\n \"routes\": { ",
9055 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
9056 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
9059 table
->version
, inet_ntoa(bgp
->router_id
),
9060 bgp
->default_local_pref
, bgp
->as
);
9061 *json_header_depth
= 2;
9063 vty_out(vty
, " \"routeDistinguishers\" : {");
9064 ++*json_header_depth
;
9068 if (use_json
&& rd
) {
9069 vty_out(vty
, " \"%s\" : { ", rd
);
9072 /* Start processing of routes. */
9073 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
9074 pi
= bgp_node_get_bgp_path_info(rn
);
9080 json_paths
= json_object_new_array();
9084 for (; pi
; pi
= pi
->next
) {
9086 if (type
== bgp_show_type_flap_statistics
9087 || type
== bgp_show_type_flap_neighbor
9088 || type
== bgp_show_type_dampend_paths
9089 || type
== bgp_show_type_damp_neighbor
) {
9090 if (!(pi
->extra
&& pi
->extra
->damp_info
))
9093 if (type
== bgp_show_type_regexp
) {
9094 regex_t
*regex
= output_arg
;
9096 if (bgp_regexec(regex
, pi
->attr
->aspath
)
9100 if (type
== bgp_show_type_prefix_list
) {
9101 struct prefix_list
*plist
= output_arg
;
9103 if (prefix_list_apply(plist
, &rn
->p
)
9107 if (type
== bgp_show_type_filter_list
) {
9108 struct as_list
*as_list
= output_arg
;
9110 if (as_list_apply(as_list
, pi
->attr
->aspath
)
9111 != AS_FILTER_PERMIT
)
9114 if (type
== bgp_show_type_route_map
) {
9115 struct route_map
*rmap
= output_arg
;
9116 struct bgp_path_info path
;
9117 struct attr dummy_attr
;
9120 bgp_attr_dup(&dummy_attr
, pi
->attr
);
9122 path
.peer
= pi
->peer
;
9123 path
.attr
= &dummy_attr
;
9125 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
9127 if (ret
== RMAP_DENYMATCH
)
9130 if (type
== bgp_show_type_neighbor
9131 || type
== bgp_show_type_flap_neighbor
9132 || type
== bgp_show_type_damp_neighbor
) {
9133 union sockunion
*su
= output_arg
;
9135 if (pi
->peer
== NULL
9136 || pi
->peer
->su_remote
== NULL
9137 || !sockunion_same(pi
->peer
->su_remote
, su
))
9140 if (type
== bgp_show_type_cidr_only
) {
9141 uint32_t destination
;
9143 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
9144 if (IN_CLASSC(destination
)
9145 && rn
->p
.prefixlen
== 24)
9147 if (IN_CLASSB(destination
)
9148 && rn
->p
.prefixlen
== 16)
9150 if (IN_CLASSA(destination
)
9151 && rn
->p
.prefixlen
== 8)
9154 if (type
== bgp_show_type_prefix_longer
) {
9156 if (!prefix_match(p
, &rn
->p
))
9159 if (type
== bgp_show_type_community_all
) {
9160 if (!pi
->attr
->community
)
9163 if (type
== bgp_show_type_community
) {
9164 struct community
*com
= output_arg
;
9166 if (!pi
->attr
->community
9167 || !community_match(pi
->attr
->community
,
9171 if (type
== bgp_show_type_community_exact
) {
9172 struct community
*com
= output_arg
;
9174 if (!pi
->attr
->community
9175 || !community_cmp(pi
->attr
->community
, com
))
9178 if (type
== bgp_show_type_community_list
) {
9179 struct community_list
*list
= output_arg
;
9181 if (!community_list_match(pi
->attr
->community
,
9185 if (type
== bgp_show_type_community_list_exact
) {
9186 struct community_list
*list
= output_arg
;
9188 if (!community_list_exact_match(
9189 pi
->attr
->community
, list
))
9192 if (type
== bgp_show_type_lcommunity
) {
9193 struct lcommunity
*lcom
= output_arg
;
9195 if (!pi
->attr
->lcommunity
9196 || !lcommunity_match(pi
->attr
->lcommunity
,
9201 if (type
== bgp_show_type_lcommunity_exact
) {
9202 struct lcommunity
*lcom
= output_arg
;
9204 if (!pi
->attr
->lcommunity
9205 || !lcommunity_cmp(pi
->attr
->lcommunity
,
9209 if (type
== bgp_show_type_lcommunity_list
) {
9210 struct community_list
*list
= output_arg
;
9212 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
9217 == bgp_show_type_lcommunity_list_exact
) {
9218 struct community_list
*list
= output_arg
;
9220 if (!lcommunity_list_exact_match(
9221 pi
->attr
->lcommunity
, list
))
9224 if (type
== bgp_show_type_lcommunity_all
) {
9225 if (!pi
->attr
->lcommunity
)
9228 if (type
== bgp_show_type_dampend_paths
9229 || type
== bgp_show_type_damp_neighbor
) {
9230 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
9231 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
9235 if (!use_json
&& header
) {
9236 vty_out(vty
, "BGP table version is %" PRIu64
9237 ", local router ID is %s, vrf id ",
9239 inet_ntoa(bgp
->router_id
));
9240 if (bgp
->vrf_id
== VRF_UNKNOWN
)
9241 vty_out(vty
, "%s", VRFID_NONE_STR
);
9243 vty_out(vty
, "%u", bgp
->vrf_id
);
9245 vty_out(vty
, "Default local pref %u, ",
9246 bgp
->default_local_pref
);
9247 vty_out(vty
, "local AS %u\n", bgp
->as
);
9248 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9249 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
9250 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9251 if (type
== bgp_show_type_dampend_paths
9252 || type
== bgp_show_type_damp_neighbor
)
9253 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
9254 else if (type
== bgp_show_type_flap_statistics
9255 || type
== bgp_show_type_flap_neighbor
)
9256 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
9258 vty_out(vty
, BGP_SHOW_HEADER
);
9261 if (rd
!= NULL
&& !display
&& !output_count
) {
9264 "Route Distinguisher: %s\n",
9267 if (type
== bgp_show_type_dampend_paths
9268 || type
== bgp_show_type_damp_neighbor
)
9269 damp_route_vty_out(vty
, &rn
->p
, pi
, display
,
9270 safi
, use_json
, json_paths
);
9271 else if (type
== bgp_show_type_flap_statistics
9272 || type
== bgp_show_type_flap_neighbor
)
9273 flap_route_vty_out(vty
, &rn
->p
, pi
, display
,
9274 safi
, use_json
, json_paths
);
9276 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
9288 if (p
->family
== AF_FLOWSPEC
) {
9289 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
9291 bgp_fs_nlri_get_string((unsigned char *)
9292 p
->u
.prefix_flowspec
.ptr
,
9293 p
->u
.prefix_flowspec
9296 NLRI_STRING_FORMAT_MIN
,
9299 vty_out(vty
, "\"%s/%d\": ",
9301 p
->u
.prefix_flowspec
.prefixlen
);
9303 vty_out(vty
, ",\"%s/%d\": ",
9305 p
->u
.prefix_flowspec
.prefixlen
);
9307 prefix2str(p
, buf2
, sizeof(buf2
));
9309 vty_out(vty
, "\"%s\": ", buf2
);
9311 vty_out(vty
, ",\"%s\": ", buf2
);
9314 json_object_to_json_string(json_paths
));
9315 json_object_free(json_paths
);
9322 output_count
+= *output_cum
;
9323 *output_cum
= output_count
;
9326 total_count
+= *total_cum
;
9327 *total_cum
= total_count
;
9331 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9335 for (i
= 0; i
< *json_header_depth
; ++i
)
9336 vty_out(vty
, " } ");
9341 /* No route is displayed */
9342 if (output_count
== 0) {
9343 if (type
== bgp_show_type_normal
)
9345 "No BGP prefixes displayed, %ld exist\n",
9349 "\nDisplayed %ld routes and %ld total paths\n",
9350 output_count
, total_count
);
9357 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9358 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9359 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9361 struct bgp_node
*rn
, *next
;
9362 unsigned long output_cum
= 0;
9363 unsigned long total_cum
= 0;
9364 unsigned long json_header_depth
= 0;
9365 struct bgp_table
*itable
;
9368 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9370 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
9371 next
= bgp_route_next(rn
);
9372 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
9375 itable
= bgp_node_get_bgp_table_info(rn
);
9376 if (itable
!= NULL
) {
9377 struct prefix_rd prd
;
9378 char rd
[RD_ADDRSTRLEN
];
9380 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
9381 prefix_rd2str(&prd
, rd
, sizeof(rd
));
9382 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
9383 use_json
, rd
, next
== NULL
, &output_cum
,
9384 &total_cum
, &json_header_depth
);
9390 if (output_cum
== 0)
9391 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
9395 "\nDisplayed %ld routes and %ld total paths\n",
9396 output_cum
, total_cum
);
9400 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
9401 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9403 struct bgp_table
*table
;
9404 unsigned long json_header_depth
= 0;
9407 bgp
= bgp_get_default();
9412 vty_out(vty
, "No BGP process is configured\n");
9414 vty_out(vty
, "{}\n");
9418 table
= bgp
->rib
[afi
][safi
];
9419 /* use MPLS and ENCAP specific shows until they are merged */
9420 if (safi
== SAFI_MPLS_VPN
) {
9421 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
9422 output_arg
, use_json
);
9425 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
9426 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
9427 output_arg
, use_json
,
9430 /* labeled-unicast routes live in the unicast table */
9431 else if (safi
== SAFI_LABELED_UNICAST
)
9432 safi
= SAFI_UNICAST
;
9434 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
9435 NULL
, 1, NULL
, NULL
, &json_header_depth
);
9438 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
9439 safi_t safi
, bool use_json
)
9441 struct listnode
*node
, *nnode
;
9444 bool route_output
= false;
9447 vty_out(vty
, "{\n");
9449 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
9450 route_output
= true;
9453 vty_out(vty
, ",\n");
9457 vty_out(vty
, "\"%s\":",
9458 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9462 vty_out(vty
, "\nInstance %s:\n",
9463 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9467 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
9472 vty_out(vty
, "}\n");
9473 else if (!route_output
)
9474 vty_out(vty
, "%% BGP instance not found\n");
9477 /* Header of detailed BGP route information */
9478 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
9479 struct bgp_node
*rn
, struct prefix_rd
*prd
,
9480 afi_t afi
, safi_t safi
, json_object
*json
)
9482 struct bgp_path_info
*pi
;
9485 struct listnode
*node
, *nnode
;
9486 char buf1
[RD_ADDRSTRLEN
];
9487 char buf2
[INET6_ADDRSTRLEN
];
9488 char buf3
[EVPN_ROUTE_STRLEN
];
9489 char prefix_str
[BUFSIZ
];
9494 int route_filter_translated_v4
= 0;
9495 int route_filter_v4
= 0;
9496 int route_filter_translated_v6
= 0;
9497 int route_filter_v6
= 0;
9500 int accept_own_nexthop
= 0;
9503 int no_advertise
= 0;
9507 int has_valid_label
= 0;
9508 mpls_label_t label
= 0;
9509 json_object
*json_adv_to
= NULL
;
9512 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
9514 if (has_valid_label
)
9515 label
= label_pton(&rn
->local_label
);
9518 if (has_valid_label
)
9519 json_object_int_add(json
, "localLabel", label
);
9521 json_object_string_add(
9523 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
9525 if (safi
== SAFI_EVPN
)
9526 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9527 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9530 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9531 buf3
, sizeof(buf3
)));
9533 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9534 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9535 ? prefix_rd2str(prd
, buf1
,
9538 safi
== SAFI_MPLS_VPN
? ":" : "",
9539 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9543 if (has_valid_label
)
9544 vty_out(vty
, "Local label: %d\n", label
);
9545 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9546 vty_out(vty
, "not allocated\n");
9549 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9551 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9553 if (pi
->extra
&& pi
->extra
->suppress
)
9556 if (pi
->attr
->community
== NULL
)
9559 no_advertise
+= community_include(
9560 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9561 no_export
+= community_include(pi
->attr
->community
,
9562 COMMUNITY_NO_EXPORT
);
9563 local_as
+= community_include(pi
->attr
->community
,
9564 COMMUNITY_LOCAL_AS
);
9565 accept_own
+= community_include(pi
->attr
->community
,
9566 COMMUNITY_ACCEPT_OWN
);
9567 route_filter_translated_v4
+= community_include(
9568 pi
->attr
->community
,
9569 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9570 route_filter_translated_v6
+= community_include(
9571 pi
->attr
->community
,
9572 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9573 route_filter_v4
+= community_include(
9574 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9575 route_filter_v6
+= community_include(
9576 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9577 llgr_stale
+= community_include(pi
->attr
->community
,
9578 COMMUNITY_LLGR_STALE
);
9579 no_llgr
+= community_include(pi
->attr
->community
,
9581 accept_own_nexthop
+=
9582 community_include(pi
->attr
->community
,
9583 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9584 blackhole
+= community_include(pi
->attr
->community
,
9585 COMMUNITY_BLACKHOLE
);
9586 no_peer
+= community_include(pi
->attr
->community
,
9592 vty_out(vty
, "Paths: (%d available", count
);
9594 vty_out(vty
, ", best #%d", best
);
9595 if (safi
== SAFI_UNICAST
) {
9596 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9597 vty_out(vty
, ", table %s",
9600 vty_out(vty
, ", vrf %s",
9604 vty_out(vty
, ", no best path");
9608 ", accept own local route exported and imported in different VRF");
9609 else if (route_filter_translated_v4
)
9611 ", mark translated RTs for VPNv4 route filtering");
9612 else if (route_filter_v4
)
9614 ", attach RT as-is for VPNv4 route filtering");
9615 else if (route_filter_translated_v6
)
9617 ", mark translated RTs for VPNv6 route filtering");
9618 else if (route_filter_v6
)
9620 ", attach RT as-is for VPNv6 route filtering");
9621 else if (llgr_stale
)
9623 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9626 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9627 else if (accept_own_nexthop
)
9629 ", accept local nexthop");
9631 vty_out(vty
, ", inform peer to blackhole prefix");
9633 vty_out(vty
, ", not advertised to EBGP peer");
9634 else if (no_advertise
)
9635 vty_out(vty
, ", not advertised to any peer");
9637 vty_out(vty
, ", not advertised outside local AS");
9640 ", inform EBGP peer not to advertise to their EBGP peers");
9644 ", Advertisements suppressed by an aggregate.");
9645 vty_out(vty
, ")\n");
9648 /* If we are not using addpath then we can display Advertised to and
9650 * show what peers we advertised the bestpath to. If we are using
9652 * though then we must display Advertised to on a path-by-path basis. */
9653 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9654 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9655 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
9656 if (json
&& !json_adv_to
)
9657 json_adv_to
= json_object_new_object();
9659 route_vty_out_advertised_to(
9661 " Advertised to non peer-group peers:\n ",
9668 json_object_object_add(json
, "advertisedTo",
9673 vty_out(vty
, " Not advertised to any peer");
9679 /* Display specified route of BGP table. */
9680 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
9681 struct bgp_table
*rib
, const char *ip_str
,
9682 afi_t afi
, safi_t safi
,
9683 struct prefix_rd
*prd
, int prefix_check
,
9684 enum bgp_path_type pathtype
, bool use_json
)
9689 struct prefix match
;
9690 struct bgp_node
*rn
;
9691 struct bgp_node
*rm
;
9692 struct bgp_path_info
*pi
;
9693 struct bgp_table
*table
;
9694 json_object
*json
= NULL
;
9695 json_object
*json_paths
= NULL
;
9697 /* Check IP address argument. */
9698 ret
= str2prefix(ip_str
, &match
);
9700 vty_out(vty
, "address is malformed\n");
9704 match
.family
= afi2family(afi
);
9707 json
= json_object_new_object();
9708 json_paths
= json_object_new_array();
9711 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
9712 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9713 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9715 table
= bgp_node_get_bgp_table_info(rn
);
9721 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9725 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9726 bgp_unlock_node(rm
);
9730 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
9733 route_vty_out_detail_header(
9735 (struct prefix_rd
*)&rn
->p
,
9736 AFI_IP
, safi
, json
);
9741 if (pathtype
== BGP_PATH_SHOW_ALL
9742 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9743 && CHECK_FLAG(pi
->flags
,
9745 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9746 && (CHECK_FLAG(pi
->flags
,
9748 || CHECK_FLAG(pi
->flags
,
9749 BGP_PATH_SELECTED
))))
9750 route_vty_out_detail(vty
, bgp
, rm
,
9755 bgp_unlock_node(rm
);
9757 } else if (safi
== SAFI_FLOWSPEC
) {
9758 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9759 &match
, prefix_check
,
9766 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9768 || rn
->p
.prefixlen
== match
.prefixlen
) {
9769 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
9772 route_vty_out_detail_header(
9773 vty
, bgp
, rn
, NULL
, afi
,
9779 if (pathtype
== BGP_PATH_SHOW_ALL
9781 == BGP_PATH_SHOW_BESTPATH
9786 == BGP_PATH_SHOW_MULTIPATH
9792 BGP_PATH_SELECTED
))))
9793 route_vty_out_detail(
9795 afi
, safi
, json_paths
);
9799 bgp_unlock_node(rn
);
9805 json_object_object_add(json
, "paths", json_paths
);
9807 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9808 json
, JSON_C_TO_STRING_PRETTY
));
9809 json_object_free(json
);
9812 vty_out(vty
, "%% Network not in table\n");
9820 /* Display specified route of Main RIB */
9821 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
9822 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
9823 int prefix_check
, enum bgp_path_type pathtype
,
9827 bgp
= bgp_get_default();
9830 vty_out(vty
, "No BGP process is configured\n");
9832 vty_out(vty
, "{}\n");
9837 /* labeled-unicast routes live in the unicast table */
9838 if (safi
== SAFI_LABELED_UNICAST
)
9839 safi
= SAFI_UNICAST
;
9841 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
9842 afi
, safi
, prd
, prefix_check
, pathtype
,
9846 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9847 struct cmd_token
**argv
, bool exact
, afi_t afi
,
9848 safi_t safi
, bool uj
)
9850 struct lcommunity
*lcom
;
9856 b
= buffer_new(1024);
9857 for (i
= 0; i
< argc
; i
++) {
9859 buffer_putc(b
, ' ');
9861 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9863 buffer_putstr(b
, argv
[i
]->arg
);
9867 buffer_putc(b
, '\0');
9869 str
= buffer_getstr(b
);
9872 lcom
= lcommunity_str2com(str
);
9873 XFREE(MTYPE_TMP
, str
);
9875 vty_out(vty
, "%% Large-community malformed\n");
9879 return bgp_show(vty
, bgp
, afi
, safi
,
9880 (exact
? bgp_show_type_lcommunity_exact
9881 : bgp_show_type_lcommunity
),
9885 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
9886 const char *lcom
, bool exact
, afi_t afi
,
9887 safi_t safi
, bool uj
)
9889 struct community_list
*list
;
9891 list
= community_list_lookup(bgp_clist
, lcom
, 0,
9892 LARGE_COMMUNITY_LIST_MASTER
);
9894 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
9899 return bgp_show(vty
, bgp
, afi
, safi
,
9900 (exact
? bgp_show_type_lcommunity_list_exact
9901 : bgp_show_type_lcommunity_list
),
9905 DEFUN (show_ip_bgp_large_community_list
,
9906 show_ip_bgp_large_community_list_cmd
,
9907 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [exact-match] [json]",
9911 BGP_INSTANCE_HELP_STR
9913 BGP_SAFI_WITH_LABEL_HELP_STR
9914 "Display routes matching the large-community-list\n"
9915 "large-community-list number\n"
9916 "large-community-list name\n"
9917 "Exact match of the large-communities\n"
9921 afi_t afi
= AFI_IP6
;
9922 safi_t safi
= SAFI_UNICAST
;
9924 bool exact_match
= 0;
9926 if (argv_find(argv
, argc
, "ip", &idx
))
9928 if (argv_find(argv
, argc
, "view", &idx
)
9929 || argv_find(argv
, argc
, "vrf", &idx
))
9930 vrf
= argv
[++idx
]->arg
;
9931 if (argv_find(argv
, argc
, "ipv4", &idx
)
9932 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9933 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9934 if (argv_find(argv
, argc
, "unicast", &idx
)
9935 || argv_find(argv
, argc
, "multicast", &idx
))
9936 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9939 bool uj
= use_json(argc
, argv
);
9941 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9943 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9947 argv_find(argv
, argc
, "large-community-list", &idx
);
9949 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9951 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9954 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
9955 exact_match
, afi
, safi
, uj
);
9957 DEFUN (show_ip_bgp_large_community
,
9958 show_ip_bgp_large_community_cmd
,
9959 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
9963 BGP_INSTANCE_HELP_STR
9965 BGP_SAFI_WITH_LABEL_HELP_STR
9966 "Display routes matching the large-communities\n"
9967 "List of large-community numbers\n"
9968 "Exact match of the large-communities\n"
9972 afi_t afi
= AFI_IP6
;
9973 safi_t safi
= SAFI_UNICAST
;
9975 bool exact_match
= 0;
9977 if (argv_find(argv
, argc
, "ip", &idx
))
9979 if (argv_find(argv
, argc
, "view", &idx
)
9980 || argv_find(argv
, argc
, "vrf", &idx
))
9981 vrf
= argv
[++idx
]->arg
;
9982 if (argv_find(argv
, argc
, "ipv4", &idx
)
9983 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9984 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9985 if (argv_find(argv
, argc
, "unicast", &idx
)
9986 || argv_find(argv
, argc
, "multicast", &idx
))
9987 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9990 bool uj
= use_json(argc
, argv
);
9992 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9994 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9998 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
9999 if (argv_find(argv
, argc
, "exact-match", &idx
))
10001 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
10002 exact_match
, afi
, safi
, uj
);
10004 return bgp_show(vty
, bgp
, afi
, safi
,
10005 bgp_show_type_lcommunity_all
, NULL
, uj
);
10008 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10012 /* BGP route print out function without JSON */
10013 DEFUN (show_ip_bgp
,
10015 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10016 <dampening <parameters>\
10021 |community-list <(1-500)|WORD> [exact-match]\
10022 |A.B.C.D/M longer-prefixes\
10023 |X:X::X:X/M longer-prefixes\
10028 BGP_INSTANCE_HELP_STR
10030 BGP_SAFI_WITH_LABEL_HELP_STR
10031 "Display detailed information about dampening\n"
10032 "Display detail of configured dampening parameters\n"
10033 "Display routes matching the route-map\n"
10034 "A route-map to match on\n"
10035 "Display routes conforming to the prefix-list\n"
10036 "Prefix-list name\n"
10037 "Display routes conforming to the filter-list\n"
10038 "Regular expression access list name\n"
10039 "BGP RIB advertisement statistics\n"
10040 "Display routes matching the community-list\n"
10041 "community-list number\n"
10042 "community-list name\n"
10043 "Exact match of the communities\n"
10045 "Display route and more specific routes\n"
10047 "Display route and more specific routes\n")
10049 afi_t afi
= AFI_IP6
;
10050 safi_t safi
= SAFI_UNICAST
;
10051 int exact_match
= 0;
10052 struct bgp
*bgp
= NULL
;
10055 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10058 return CMD_WARNING
;
10060 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10061 if (argv_find(argv
, argc
, "parameters", &idx
))
10062 return bgp_show_dampening_parameters(vty
, afi
, safi
);
10065 if (argv_find(argv
, argc
, "prefix-list", &idx
))
10066 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10067 safi
, bgp_show_type_prefix_list
);
10069 if (argv_find(argv
, argc
, "filter-list", &idx
))
10070 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10071 safi
, bgp_show_type_filter_list
);
10073 if (argv_find(argv
, argc
, "statistics", &idx
))
10074 return bgp_table_stats(vty
, bgp
, afi
, safi
);
10076 if (argv_find(argv
, argc
, "route-map", &idx
))
10077 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10078 safi
, bgp_show_type_route_map
);
10080 if (argv_find(argv
, argc
, "community-list", &idx
)) {
10081 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10082 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10084 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
10085 exact_match
, afi
, safi
);
10087 /* prefix-longer */
10088 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10089 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10090 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
10092 bgp_show_type_prefix_longer
);
10094 return CMD_WARNING
;
10097 /* BGP route print out function with JSON */
10098 DEFUN (show_ip_bgp_json
,
10099 show_ip_bgp_json_cmd
,
10100 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10102 |dampening <flap-statistics|dampened-paths>\
10103 |community [AA:NN|local-AS|no-advertise|no-export\
10104 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10105 |accept-own|accept-own-nexthop|route-filter-v6\
10106 |route-filter-v4|route-filter-translated-v6\
10107 |route-filter-translated-v4] [exact-match]\
10112 BGP_INSTANCE_HELP_STR
10114 BGP_SAFI_WITH_LABEL_HELP_STR
10115 "Display only routes with non-natural netmasks\n"
10116 "Display detailed information about dampening\n"
10117 "Display flap statistics of routes\n"
10118 "Display paths suppressed due to dampening\n"
10119 "Display routes matching the communities\n"
10121 "Do not send outside local AS (well-known community)\n"
10122 "Do not advertise to any peer (well-known community)\n"
10123 "Do not export to next AS (well-known community)\n"
10124 "Graceful shutdown (well-known community)\n"
10125 "Do not export to any peer (well-known community)\n"
10126 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10127 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10128 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10129 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10130 "Should accept VPN route with local nexthop (well-known community)\n"
10131 "RT VPNv6 route filtering (well-known community)\n"
10132 "RT VPNv4 route filtering (well-known community)\n"
10133 "RT translated VPNv6 route filtering (well-known community)\n"
10134 "RT translated VPNv4 route filtering (well-known community)\n"
10135 "Exact match of the communities\n"
10138 afi_t afi
= AFI_IP6
;
10139 safi_t safi
= SAFI_UNICAST
;
10140 enum bgp_show_type sh_type
= bgp_show_type_normal
;
10141 struct bgp
*bgp
= NULL
;
10143 int exact_match
= 0;
10144 bool uj
= use_json(argc
, argv
);
10149 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10152 return CMD_WARNING
;
10154 if (argv_find(argv
, argc
, "cidr-only", &idx
))
10155 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
10158 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10159 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
10160 return bgp_show(vty
, bgp
, afi
, safi
,
10161 bgp_show_type_dampend_paths
, NULL
, uj
);
10162 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10163 return bgp_show(vty
, bgp
, afi
, safi
,
10164 bgp_show_type_flap_statistics
, NULL
,
10168 if (argv_find(argv
, argc
, "community", &idx
)) {
10169 char *maybecomm
= NULL
;
10170 char *community
= NULL
;
10172 if (idx
+ 1 < argc
) {
10173 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
10174 maybecomm
= argv
[idx
+ 1]->arg
;
10176 maybecomm
= argv
[idx
+ 1]->text
;
10179 if (maybecomm
&& !strmatch(maybecomm
, "json")
10180 && !strmatch(maybecomm
, "exact-match"))
10181 community
= maybecomm
;
10183 if (argv_find(argv
, argc
, "exact-match", &idx
))
10187 return bgp_show_community(vty
, bgp
, community
,
10188 exact_match
, afi
, safi
, uj
);
10190 return (bgp_show(vty
, bgp
, afi
, safi
,
10191 bgp_show_type_community_all
, NULL
,
10195 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
10198 DEFUN (show_ip_bgp_route
,
10199 show_ip_bgp_route_cmd
,
10200 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
10201 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
10205 BGP_INSTANCE_HELP_STR
10207 BGP_SAFI_WITH_LABEL_HELP_STR
10208 "Network in the BGP routing table to display\n"
10210 "Network in the BGP routing table to display\n"
10212 "Display only the bestpath\n"
10213 "Display only multipaths\n"
10216 int prefix_check
= 0;
10218 afi_t afi
= AFI_IP6
;
10219 safi_t safi
= SAFI_UNICAST
;
10220 char *prefix
= NULL
;
10221 struct bgp
*bgp
= NULL
;
10222 enum bgp_path_type path_type
;
10223 bool uj
= use_json(argc
, argv
);
10227 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10230 return CMD_WARNING
;
10234 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10235 return CMD_WARNING
;
10238 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10239 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
10240 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
10242 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10243 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10246 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
10247 && afi
!= AFI_IP6
) {
10249 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10250 return CMD_WARNING
;
10252 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
10253 && afi
!= AFI_IP
) {
10255 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10256 return CMD_WARNING
;
10259 prefix
= argv
[idx
]->arg
;
10261 /* [<bestpath|multipath>] */
10262 if (argv_find(argv
, argc
, "bestpath", &idx
))
10263 path_type
= BGP_PATH_SHOW_BESTPATH
;
10264 else if (argv_find(argv
, argc
, "multipath", &idx
))
10265 path_type
= BGP_PATH_SHOW_MULTIPATH
;
10267 path_type
= BGP_PATH_SHOW_ALL
;
10269 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
10273 DEFUN (show_ip_bgp_regexp
,
10274 show_ip_bgp_regexp_cmd
,
10275 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
10279 BGP_INSTANCE_HELP_STR
10281 BGP_SAFI_WITH_LABEL_HELP_STR
10282 "Display routes matching the AS path regular expression\n"
10283 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n")
10285 afi_t afi
= AFI_IP6
;
10286 safi_t safi
= SAFI_UNICAST
;
10287 struct bgp
*bgp
= NULL
;
10290 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10293 return CMD_WARNING
;
10295 // get index of regex
10296 argv_find(argv
, argc
, "regexp", &idx
);
10299 char *regstr
= argv_concat(argv
, argc
, idx
);
10300 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
10301 bgp_show_type_regexp
);
10302 XFREE(MTYPE_TMP
, regstr
);
10306 DEFUN (show_ip_bgp_instance_all
,
10307 show_ip_bgp_instance_all_cmd
,
10308 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
10312 BGP_INSTANCE_ALL_HELP_STR
10314 BGP_SAFI_WITH_LABEL_HELP_STR
10317 afi_t afi
= AFI_IP
;
10318 safi_t safi
= SAFI_UNICAST
;
10319 struct bgp
*bgp
= NULL
;
10321 bool uj
= use_json(argc
, argv
);
10326 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10329 return CMD_WARNING
;
10331 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
10332 return CMD_SUCCESS
;
10335 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10336 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
10341 if (!config_bgp_aspath_validate(regstr
)) {
10342 vty_out(vty
, "Invalid character in as-path access-list %s\n",
10344 return CMD_WARNING_CONFIG_FAILED
;
10347 regex
= bgp_regcomp(regstr
);
10349 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
10350 return CMD_WARNING
;
10353 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
10354 bgp_regex_free(regex
);
10358 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10359 const char *prefix_list_str
, afi_t afi
,
10360 safi_t safi
, enum bgp_show_type type
)
10362 struct prefix_list
*plist
;
10364 plist
= prefix_list_lookup(afi
, prefix_list_str
);
10365 if (plist
== NULL
) {
10366 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
10368 return CMD_WARNING
;
10371 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
10374 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10375 const char *filter
, afi_t afi
, safi_t safi
,
10376 enum bgp_show_type type
)
10378 struct as_list
*as_list
;
10380 as_list
= as_list_lookup(filter
);
10381 if (as_list
== NULL
) {
10382 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
10384 return CMD_WARNING
;
10387 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
10390 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10391 const char *rmap_str
, afi_t afi
, safi_t safi
,
10392 enum bgp_show_type type
)
10394 struct route_map
*rmap
;
10396 rmap
= route_map_lookup_by_name(rmap_str
);
10398 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
10399 return CMD_WARNING
;
10402 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
10405 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10406 const char *comstr
, int exact
, afi_t afi
,
10407 safi_t safi
, bool use_json
)
10409 struct community
*com
;
10412 com
= community_str2com(comstr
);
10414 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
10415 return CMD_WARNING
;
10418 ret
= bgp_show(vty
, bgp
, afi
, safi
,
10419 (exact
? bgp_show_type_community_exact
10420 : bgp_show_type_community
),
10422 community_free(&com
);
10427 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10428 const char *com
, int exact
, afi_t afi
,
10431 struct community_list
*list
;
10433 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
10434 if (list
== NULL
) {
10435 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
10436 return CMD_WARNING
;
10439 return bgp_show(vty
, bgp
, afi
, safi
,
10440 (exact
? bgp_show_type_community_list_exact
10441 : bgp_show_type_community_list
),
10445 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10446 const char *prefix
, afi_t afi
, safi_t safi
,
10447 enum bgp_show_type type
)
10454 ret
= str2prefix(prefix
, p
);
10456 vty_out(vty
, "%% Malformed Prefix\n");
10457 return CMD_WARNING
;
10460 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
10465 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
10466 const char *ip_str
, bool use_json
)
10470 union sockunion su
;
10472 /* Get peer sockunion. */
10473 ret
= str2sockunion(ip_str
, &su
);
10475 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
10477 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
10481 json_object
*json_no
= NULL
;
10482 json_no
= json_object_new_object();
10483 json_object_string_add(
10485 "malformedAddressOrName",
10487 vty_out(vty
, "%s\n",
10488 json_object_to_json_string_ext(
10490 JSON_C_TO_STRING_PRETTY
));
10491 json_object_free(json_no
);
10494 "%% Malformed address or name: %s\n",
10502 /* Peer structure lookup. */
10503 peer
= peer_lookup(bgp
, &su
);
10506 json_object
*json_no
= NULL
;
10507 json_no
= json_object_new_object();
10508 json_object_string_add(json_no
, "warning",
10509 "No such neighbor in this view/vrf");
10510 vty_out(vty
, "%s\n",
10511 json_object_to_json_string_ext(
10512 json_no
, JSON_C_TO_STRING_PRETTY
));
10513 json_object_free(json_no
);
10515 vty_out(vty
, "No such neighbor in this view/vrf\n");
10523 BGP_STATS_MAXBITLEN
= 0,
10525 BGP_STATS_PREFIXES
,
10527 BGP_STATS_UNAGGREGATEABLE
,
10528 BGP_STATS_MAX_AGGREGATEABLE
,
10529 BGP_STATS_AGGREGATES
,
10531 BGP_STATS_ASPATH_COUNT
,
10532 BGP_STATS_ASPATH_MAXHOPS
,
10533 BGP_STATS_ASPATH_TOTHOPS
,
10534 BGP_STATS_ASPATH_MAXSIZE
,
10535 BGP_STATS_ASPATH_TOTSIZE
,
10536 BGP_STATS_ASN_HIGHEST
,
10540 static const char *table_stats_strs
[] = {
10541 [BGP_STATS_PREFIXES
] = "Total Prefixes",
10542 [BGP_STATS_TOTPLEN
] = "Average prefix length",
10543 [BGP_STATS_RIB
] = "Total Advertisements",
10544 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
10545 [BGP_STATS_MAX_AGGREGATEABLE
] =
10546 "Maximum aggregateable prefixes",
10547 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
10548 [BGP_STATS_SPACE
] = "Address space advertised",
10549 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
10550 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10551 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10552 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10553 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10554 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10555 [BGP_STATS_MAX
] = NULL
,
10558 struct bgp_table_stats
{
10559 struct bgp_table
*table
;
10560 unsigned long long counts
[BGP_STATS_MAX
];
10561 double total_space
;
10565 #define TALLY_SIGFIG 100000
10566 static unsigned long
10567 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10569 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10570 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10571 unsigned long ret
= newtot
/ count
;
10573 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10580 static void bgp_table_stats_rn(struct bgp_node
*rn
, struct bgp_node
*top
,
10581 struct bgp_table_stats
*ts
, unsigned int space
)
10583 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10584 struct bgp_path_info
*pi
;
10589 if (!bgp_node_has_bgp_path_info_data(rn
))
10592 ts
->counts
[BGP_STATS_PREFIXES
]++;
10593 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10596 ts
->counts
[BGP_STATS_AVGPLEN
]
10597 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10598 ts
->counts
[BGP_STATS_AVGPLEN
],
10602 /* check if the prefix is included by any other announcements */
10603 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10604 prn
= bgp_node_parent_nolock(prn
);
10606 if (prn
== NULL
|| prn
== top
) {
10607 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10608 /* announced address space */
10610 ts
->total_space
+= pow(2.0, space
- rn
->p
.prefixlen
);
10611 } else if (bgp_node_has_bgp_path_info_data(prn
))
10612 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10615 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10616 ts
->counts
[BGP_STATS_RIB
]++;
10619 && (CHECK_FLAG(pi
->attr
->flag
,
10620 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))))
10621 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10623 /* as-path stats */
10624 if (pi
->attr
&& pi
->attr
->aspath
) {
10625 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
10626 unsigned int size
= aspath_size(pi
->attr
->aspath
);
10627 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10629 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10631 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10632 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
10634 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10635 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
10637 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10638 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10640 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10641 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10642 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10644 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10645 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10646 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
10649 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
10650 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
10655 static int bgp_table_stats_walker(struct thread
*t
)
10657 struct bgp_node
*rn
, *nrn
;
10658 struct bgp_node
*top
;
10659 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
10660 unsigned int space
= 0;
10662 if (!(top
= bgp_table_top(ts
->table
)))
10665 switch (ts
->table
->afi
) {
10667 space
= IPV4_MAX_BITLEN
;
10670 space
= IPV6_MAX_BITLEN
;
10676 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
10678 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
10679 if (ts
->table
->safi
== SAFI_MPLS_VPN
) {
10680 struct bgp_table
*table
;
10682 table
= bgp_node_get_bgp_table_info(rn
);
10686 top
= bgp_table_top(table
);
10687 for (nrn
= bgp_table_top(table
); nrn
;
10688 nrn
= bgp_route_next(nrn
))
10689 bgp_table_stats_rn(nrn
, top
, ts
, space
);
10691 bgp_table_stats_rn(rn
, top
, ts
, space
);
10698 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10701 struct bgp_table_stats ts
;
10704 if (!bgp
->rib
[afi
][safi
]) {
10705 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10707 return CMD_WARNING
;
10710 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
10712 /* labeled-unicast routes live in the unicast table */
10713 if (safi
== SAFI_LABELED_UNICAST
)
10714 safi
= SAFI_UNICAST
;
10716 memset(&ts
, 0, sizeof(ts
));
10717 ts
.table
= bgp
->rib
[afi
][safi
];
10718 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
10720 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
10721 if (!table_stats_strs
[i
])
10726 case BGP_STATS_ASPATH_AVGHOPS
:
10727 case BGP_STATS_ASPATH_AVGSIZE
:
10728 case BGP_STATS_AVGPLEN
:
10729 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
10730 vty_out (vty
, "%12.2f",
10731 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
10734 case BGP_STATS_ASPATH_TOTHOPS
:
10735 case BGP_STATS_ASPATH_TOTSIZE
:
10736 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10737 vty_out(vty
, "%12.2f",
10739 ? (float)ts
.counts
[i
]
10741 [BGP_STATS_ASPATH_COUNT
]
10744 case BGP_STATS_TOTPLEN
:
10745 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10746 vty_out(vty
, "%12.2f",
10748 ? (float)ts
.counts
[i
]
10750 [BGP_STATS_PREFIXES
]
10753 case BGP_STATS_SPACE
:
10754 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10755 vty_out(vty
, "%12g\n", ts
.total_space
);
10757 if (afi
== AFI_IP6
) {
10758 vty_out(vty
, "%30s: ", "/32 equivalent ");
10759 vty_out(vty
, "%12g\n",
10760 ts
.total_space
* pow(2.0, -128 + 32));
10761 vty_out(vty
, "%30s: ", "/48 equivalent ");
10762 vty_out(vty
, "%12g\n",
10763 ts
.total_space
* pow(2.0, -128 + 48));
10765 vty_out(vty
, "%30s: ", "% announced ");
10766 vty_out(vty
, "%12.2f\n",
10767 ts
.total_space
* 100. * pow(2.0, -32));
10768 vty_out(vty
, "%30s: ", "/8 equivalent ");
10769 vty_out(vty
, "%12.2f\n",
10770 ts
.total_space
* pow(2.0, -32 + 8));
10771 vty_out(vty
, "%30s: ", "/24 equivalent ");
10772 vty_out(vty
, "%12.2f\n",
10773 ts
.total_space
* pow(2.0, -32 + 24));
10777 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10778 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10781 vty_out(vty
, "\n");
10783 return CMD_SUCCESS
;
10795 PCOUNT_PFCNT
, /* the figure we display to users */
10799 static const char *pcount_strs
[] = {
10800 [PCOUNT_ADJ_IN
] = "Adj-in",
10801 [PCOUNT_DAMPED
] = "Damped",
10802 [PCOUNT_REMOVED
] = "Removed",
10803 [PCOUNT_HISTORY
] = "History",
10804 [PCOUNT_STALE
] = "Stale",
10805 [PCOUNT_VALID
] = "Valid",
10806 [PCOUNT_ALL
] = "All RIB",
10807 [PCOUNT_COUNTED
] = "PfxCt counted",
10808 [PCOUNT_PFCNT
] = "Useable",
10809 [PCOUNT_MAX
] = NULL
,
10812 struct peer_pcounts
{
10813 unsigned int count
[PCOUNT_MAX
];
10814 const struct peer
*peer
;
10815 const struct bgp_table
*table
;
10818 static int bgp_peer_count_walker(struct thread
*t
)
10820 struct bgp_node
*rn
;
10821 struct peer_pcounts
*pc
= THREAD_ARG(t
);
10822 const struct peer
*peer
= pc
->peer
;
10824 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
10825 struct bgp_adj_in
*ain
;
10826 struct bgp_path_info
*pi
;
10828 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10829 if (ain
->peer
== peer
)
10830 pc
->count
[PCOUNT_ADJ_IN
]++;
10832 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10834 if (pi
->peer
!= peer
)
10837 pc
->count
[PCOUNT_ALL
]++;
10839 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10840 pc
->count
[PCOUNT_DAMPED
]++;
10841 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10842 pc
->count
[PCOUNT_HISTORY
]++;
10843 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10844 pc
->count
[PCOUNT_REMOVED
]++;
10845 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10846 pc
->count
[PCOUNT_STALE
]++;
10847 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10848 pc
->count
[PCOUNT_VALID
]++;
10849 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10850 pc
->count
[PCOUNT_PFCNT
]++;
10852 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10853 pc
->count
[PCOUNT_COUNTED
]++;
10854 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10856 EC_LIB_DEVELOPMENT
,
10857 "Attempting to count but flags say it is unusable");
10859 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10861 EC_LIB_DEVELOPMENT
,
10862 "Not counted but flags say we should");
10869 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10870 safi_t safi
, bool use_json
)
10872 struct peer_pcounts pcounts
= {.peer
= peer
};
10874 json_object
*json
= NULL
;
10875 json_object
*json_loop
= NULL
;
10878 json
= json_object_new_object();
10879 json_loop
= json_object_new_object();
10882 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10883 || !peer
->bgp
->rib
[afi
][safi
]) {
10885 json_object_string_add(
10887 "No such neighbor or address family");
10888 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10889 json_object_free(json
);
10891 vty_out(vty
, "%% No such neighbor or address family\n");
10893 return CMD_WARNING
;
10896 memset(&pcounts
, 0, sizeof(pcounts
));
10897 pcounts
.peer
= peer
;
10898 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10900 /* in-place call via thread subsystem so as to record execution time
10901 * stats for the thread-walk (i.e. ensure this can't be blamed on
10902 * on just vty_read()).
10904 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10907 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10908 json_object_string_add(json
, "multiProtocol",
10909 afi_safi_print(afi
, safi
));
10910 json_object_int_add(json
, "pfxCounter",
10911 peer
->pcount
[afi
][safi
]);
10913 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10914 json_object_int_add(json_loop
, pcount_strs
[i
],
10917 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10919 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10920 json_object_string_add(json
, "pfxctDriftFor",
10922 json_object_string_add(
10923 json
, "recommended",
10924 "Please report this bug, with the above command output");
10926 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10927 json
, JSON_C_TO_STRING_PRETTY
));
10928 json_object_free(json
);
10932 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10933 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10934 peer
->hostname
, peer
->host
,
10935 afi_safi_print(afi
, safi
));
10937 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10938 afi_safi_print(afi
, safi
));
10941 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
10942 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10944 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10945 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10948 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10949 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10951 "Please report this bug, with the above command output\n");
10955 return CMD_SUCCESS
;
10958 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10959 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10960 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
10961 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10965 BGP_INSTANCE_HELP_STR
10968 "Detailed information on TCP and BGP neighbor connections\n"
10969 "Neighbor to display information about\n"
10970 "Neighbor to display information about\n"
10971 "Neighbor on BGP configured interface\n"
10972 "Display detailed prefix count information\n"
10975 afi_t afi
= AFI_IP6
;
10976 safi_t safi
= SAFI_UNICAST
;
10979 struct bgp
*bgp
= NULL
;
10980 bool uj
= use_json(argc
, argv
);
10985 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10988 return CMD_WARNING
;
10990 argv_find(argv
, argc
, "neighbors", &idx
);
10991 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
10993 return CMD_WARNING
;
10995 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
10998 #ifdef KEEP_OLD_VPN_COMMANDS
10999 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
11000 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
11001 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11006 "Display information about all VPNv4 NLRIs\n"
11007 "Detailed information on TCP and BGP neighbor connections\n"
11008 "Neighbor to display information about\n"
11009 "Neighbor to display information about\n"
11010 "Neighbor on BGP configured interface\n"
11011 "Display detailed prefix count information\n"
11016 bool uj
= use_json(argc
, argv
);
11018 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
11020 return CMD_WARNING
;
11022 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
11025 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
11026 show_ip_bgp_vpn_all_route_prefix_cmd
,
11027 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
11032 "Display information about all VPNv4 NLRIs\n"
11033 "Network in the BGP routing table to display\n"
11034 "Network in the BGP routing table to display\n"
11038 char *network
= NULL
;
11039 struct bgp
*bgp
= bgp_get_default();
11041 vty_out(vty
, "Can't find default instance\n");
11042 return CMD_WARNING
;
11045 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
11046 network
= argv
[idx
]->arg
;
11047 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
11048 network
= argv
[idx
]->arg
;
11050 vty_out(vty
, "Unable to figure out Network\n");
11051 return CMD_WARNING
;
11054 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
11055 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11057 #endif /* KEEP_OLD_VPN_COMMANDS */
11059 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
11060 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
11061 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
11067 "Display information about all EVPN NLRIs\n"
11068 "Network in the BGP routing table to display\n"
11069 "Network in the BGP routing table to display\n"
11073 char *network
= NULL
;
11075 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
11076 network
= argv
[idx
]->arg
;
11077 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
11078 network
= argv
[idx
]->arg
;
11080 vty_out(vty
, "Unable to figure out Network\n");
11081 return CMD_WARNING
;
11083 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
11084 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11087 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11088 safi_t safi
, enum bgp_show_adj_route_type type
,
11089 const char *rmap_name
, bool use_json
,
11092 struct bgp_table
*table
;
11093 struct bgp_adj_in
*ain
;
11094 struct bgp_adj_out
*adj
;
11095 unsigned long output_count
;
11096 unsigned long filtered_count
;
11097 struct bgp_node
*rn
;
11103 struct update_subgroup
*subgrp
;
11104 json_object
*json_scode
= NULL
;
11105 json_object
*json_ocode
= NULL
;
11106 json_object
*json_ar
= NULL
;
11107 struct peer_af
*paf
;
11108 bool route_filtered
;
11111 json_scode
= json_object_new_object();
11112 json_ocode
= json_object_new_object();
11113 json_ar
= json_object_new_object();
11115 json_object_string_add(json_scode
, "suppressed", "s");
11116 json_object_string_add(json_scode
, "damped", "d");
11117 json_object_string_add(json_scode
, "history", "h");
11118 json_object_string_add(json_scode
, "valid", "*");
11119 json_object_string_add(json_scode
, "best", ">");
11120 json_object_string_add(json_scode
, "multipath", "=");
11121 json_object_string_add(json_scode
, "internal", "i");
11122 json_object_string_add(json_scode
, "ribFailure", "r");
11123 json_object_string_add(json_scode
, "stale", "S");
11124 json_object_string_add(json_scode
, "removed", "R");
11126 json_object_string_add(json_ocode
, "igp", "i");
11127 json_object_string_add(json_ocode
, "egp", "e");
11128 json_object_string_add(json_ocode
, "incomplete", "?");
11135 json_object_string_add(json
, "alert", "no BGP");
11136 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11137 json_object_free(json
);
11139 vty_out(vty
, "%% No bgp\n");
11143 /* labeled-unicast routes live in the unicast table */
11144 if (safi
== SAFI_LABELED_UNICAST
)
11145 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
11147 table
= bgp
->rib
[afi
][safi
];
11149 output_count
= filtered_count
= 0;
11150 subgrp
= peer_subgroup(peer
, afi
, safi
);
11152 if (type
== bgp_show_adj_route_advertised
&& subgrp
11153 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
11155 json_object_int_add(json
, "bgpTableVersion",
11157 json_object_string_add(json
, "bgpLocalRouterId",
11158 inet_ntoa(bgp
->router_id
));
11159 json_object_int_add(json
, "defaultLocPrf",
11160 bgp
->default_local_pref
);
11161 json_object_int_add(json
, "localAS", bgp
->as
);
11162 json_object_object_add(json
, "bgpStatusCodes",
11164 json_object_object_add(json
, "bgpOriginCodes",
11166 json_object_string_add(
11167 json
, "bgpOriginatingDefaultNetwork",
11168 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11170 vty_out(vty
, "BGP table version is %" PRIu64
11171 ", local router ID is %s, vrf id ",
11172 table
->version
, inet_ntoa(bgp
->router_id
));
11173 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11174 vty_out(vty
, "%s", VRFID_NONE_STR
);
11176 vty_out(vty
, "%u", bgp
->vrf_id
);
11177 vty_out(vty
, "\n");
11178 vty_out(vty
, "Default local pref %u, ",
11179 bgp
->default_local_pref
);
11180 vty_out(vty
, "local AS %u\n", bgp
->as
);
11181 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11182 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11183 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11185 vty_out(vty
, "Originating default network %s\n\n",
11186 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11191 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11192 if (type
== bgp_show_adj_route_received
11193 || type
== bgp_show_adj_route_filtered
) {
11194 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
11195 if (ain
->peer
!= peer
|| !ain
->attr
)
11200 json_object_int_add(
11201 json
, "bgpTableVersion",
11203 json_object_string_add(
11205 "bgpLocalRouterId",
11208 json_object_int_add(json
,
11210 bgp
->default_local_pref
);
11211 json_object_int_add(json
,
11212 "localAS", bgp
->as
);
11213 json_object_object_add(
11214 json
, "bgpStatusCodes",
11216 json_object_object_add(
11217 json
, "bgpOriginCodes",
11221 "BGP table version is 0, local router ID is %s, vrf id ",
11224 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11230 vty_out(vty
, "\n");
11232 "Default local pref %u, ",
11233 bgp
->default_local_pref
);
11234 vty_out(vty
, "local AS %u\n",
11237 BGP_SHOW_SCODE_HEADER
);
11239 BGP_SHOW_NCODE_HEADER
);
11241 BGP_SHOW_OCODE_HEADER
);
11247 vty_out(vty
, BGP_SHOW_HEADER
);
11251 bgp_attr_dup(&attr
, ain
->attr
);
11252 route_filtered
= false;
11254 /* Filter prefix using distribute list,
11255 * filter list or prefix list
11257 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
11258 safi
)) == FILTER_DENY
)
11259 route_filtered
= true;
11261 /* Filter prefix using route-map */
11262 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
11263 afi
, safi
, rmap_name
);
11265 if (type
== bgp_show_adj_route_filtered
&&
11266 !route_filtered
&& ret
!= RMAP_DENY
) {
11267 bgp_attr_undup(&attr
, ain
->attr
);
11271 if (type
== bgp_show_adj_route_received
&&
11272 (route_filtered
|| ret
== RMAP_DENY
))
11275 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
11276 use_json
, json_ar
);
11277 bgp_attr_undup(&attr
, ain
->attr
);
11280 } else if (type
== bgp_show_adj_route_advertised
) {
11281 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
11282 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
11283 if (paf
->peer
!= peer
|| !adj
->attr
)
11288 json_object_int_add(
11292 json_object_string_add(
11294 "bgpLocalRouterId",
11297 json_object_int_add(
11298 json
, "defaultLocPrf",
11299 bgp
->default_local_pref
11301 json_object_int_add(
11304 json_object_object_add(
11308 json_object_object_add(
11314 "BGP table version is %" PRIu64
11315 ", local router ID is %s, vrf id ",
11328 vty_out(vty
, "\n");
11330 "Default local pref %u, ",
11331 bgp
->default_local_pref
11337 BGP_SHOW_SCODE_HEADER
);
11339 BGP_SHOW_NCODE_HEADER
);
11341 BGP_SHOW_OCODE_HEADER
);
11352 bgp_attr_dup(&attr
, adj
->attr
);
11353 ret
= bgp_output_modifier(
11354 peer
, &rn
->p
, &attr
, afi
, safi
,
11357 if (ret
!= RMAP_DENY
) {
11358 route_vty_out_tmp(vty
, &rn
->p
,
11367 bgp_attr_undup(&attr
, adj
->attr
);
11373 json_object_object_add(json
, "advertisedRoutes", json_ar
);
11374 json_object_int_add(json
, "totalPrefixCounter", output_count
);
11375 json_object_int_add(json
, "filteredPrefixCounter",
11378 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11379 json
, JSON_C_TO_STRING_PRETTY
));
11380 json_object_free(json
);
11381 } else if (output_count
> 0) {
11382 if (filtered_count
> 0)
11384 "\nTotal number of prefixes %ld (%ld filtered)\n",
11385 output_count
, filtered_count
);
11387 vty_out(vty
, "\nTotal number of prefixes %ld\n",
11392 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11393 safi_t safi
, enum bgp_show_adj_route_type type
,
11394 const char *rmap_name
, bool use_json
)
11396 json_object
*json
= NULL
;
11399 json
= json_object_new_object();
11401 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11403 json_object_string_add(
11405 "No such neighbor or address family");
11406 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11407 json_object_free(json
);
11409 vty_out(vty
, "%% No such neighbor or address family\n");
11411 return CMD_WARNING
;
11414 if ((type
== bgp_show_adj_route_received
11415 || type
== bgp_show_adj_route_filtered
)
11416 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
11417 PEER_FLAG_SOFT_RECONFIG
)) {
11419 json_object_string_add(
11421 "Inbound soft reconfiguration not enabled");
11422 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11423 json_object_free(json
);
11426 "%% Inbound soft reconfiguration not enabled\n");
11428 return CMD_WARNING
;
11431 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
11433 return CMD_SUCCESS
;
11436 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
11437 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
11438 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11439 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
11443 BGP_INSTANCE_HELP_STR
11445 BGP_SAFI_WITH_LABEL_HELP_STR
11446 "Detailed information on TCP and BGP neighbor connections\n"
11447 "Neighbor to display information about\n"
11448 "Neighbor to display information about\n"
11449 "Neighbor on BGP configured interface\n"
11450 "Display the routes advertised to a BGP neighbor\n"
11451 "Display the received routes from neighbor\n"
11452 "Display the filtered routes received from neighbor\n"
11453 "Route-map to modify the attributes\n"
11454 "Name of the route map\n"
11457 afi_t afi
= AFI_IP6
;
11458 safi_t safi
= SAFI_UNICAST
;
11459 char *rmap_name
= NULL
;
11460 char *peerstr
= NULL
;
11461 struct bgp
*bgp
= NULL
;
11463 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
11465 bool uj
= use_json(argc
, argv
);
11470 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11473 return CMD_WARNING
;
11475 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11476 argv_find(argv
, argc
, "neighbors", &idx
);
11477 peerstr
= argv
[++idx
]->arg
;
11479 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11481 return CMD_WARNING
;
11483 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
11484 type
= bgp_show_adj_route_advertised
;
11485 else if (argv_find(argv
, argc
, "received-routes", &idx
))
11486 type
= bgp_show_adj_route_received
;
11487 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
11488 type
= bgp_show_adj_route_filtered
;
11490 if (argv_find(argv
, argc
, "route-map", &idx
))
11491 rmap_name
= argv
[++idx
]->arg
;
11493 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
11496 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
11497 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
11498 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
11504 "Address Family modifier\n"
11505 "Detailed information on TCP and BGP neighbor connections\n"
11506 "Neighbor to display information about\n"
11507 "Neighbor to display information about\n"
11508 "Neighbor on BGP configured interface\n"
11509 "Display information received from a BGP neighbor\n"
11510 "Display the prefixlist filter\n"
11513 afi_t afi
= AFI_IP6
;
11514 safi_t safi
= SAFI_UNICAST
;
11515 char *peerstr
= NULL
;
11518 union sockunion su
;
11524 /* show [ip] bgp */
11525 if (argv_find(argv
, argc
, "ip", &idx
))
11527 /* [<ipv4|ipv6> [unicast]] */
11528 if (argv_find(argv
, argc
, "ipv4", &idx
))
11530 if (argv_find(argv
, argc
, "ipv6", &idx
))
11532 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11533 argv_find(argv
, argc
, "neighbors", &idx
);
11534 peerstr
= argv
[++idx
]->arg
;
11536 bool uj
= use_json(argc
, argv
);
11538 ret
= str2sockunion(peerstr
, &su
);
11540 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
11543 vty_out(vty
, "{}\n");
11546 "%% Malformed address or name: %s\n",
11548 return CMD_WARNING
;
11551 peer
= peer_lookup(NULL
, &su
);
11554 vty_out(vty
, "{}\n");
11556 vty_out(vty
, "No peer\n");
11557 return CMD_WARNING
;
11561 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
11562 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11565 vty_out(vty
, "Address Family: %s\n",
11566 afi_safi_print(afi
, safi
));
11567 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11570 vty_out(vty
, "{}\n");
11572 vty_out(vty
, "No functional output\n");
11575 return CMD_SUCCESS
;
11578 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11579 afi_t afi
, safi_t safi
,
11580 enum bgp_show_type type
, bool use_json
)
11582 /* labeled-unicast routes live in the unicast table */
11583 if (safi
== SAFI_LABELED_UNICAST
)
11584 safi
= SAFI_UNICAST
;
11586 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11588 json_object
*json_no
= NULL
;
11589 json_no
= json_object_new_object();
11590 json_object_string_add(
11591 json_no
, "warning",
11592 "No such neighbor or address family");
11593 vty_out(vty
, "%s\n",
11594 json_object_to_json_string(json_no
));
11595 json_object_free(json_no
);
11597 vty_out(vty
, "%% No such neighbor or address family\n");
11598 return CMD_WARNING
;
11601 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
11604 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
11605 show_ip_bgp_flowspec_routes_detailed_cmd
,
11606 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
11610 BGP_INSTANCE_HELP_STR
11613 "Detailed information on flowspec entries\n"
11616 afi_t afi
= AFI_IP
;
11617 safi_t safi
= SAFI_UNICAST
;
11618 struct bgp
*bgp
= NULL
;
11620 bool uj
= use_json(argc
, argv
);
11625 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11628 return CMD_WARNING
;
11630 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
11633 DEFUN (show_ip_bgp_neighbor_routes
,
11634 show_ip_bgp_neighbor_routes_cmd
,
11635 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11636 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
11640 BGP_INSTANCE_HELP_STR
11642 BGP_SAFI_WITH_LABEL_HELP_STR
11643 "Detailed information on TCP and BGP neighbor connections\n"
11644 "Neighbor to display information about\n"
11645 "Neighbor to display information about\n"
11646 "Neighbor on BGP configured interface\n"
11647 "Display flap statistics of the routes learned from neighbor\n"
11648 "Display the dampened routes received from neighbor\n"
11649 "Display routes learned from neighbor\n"
11652 char *peerstr
= NULL
;
11653 struct bgp
*bgp
= NULL
;
11654 afi_t afi
= AFI_IP6
;
11655 safi_t safi
= SAFI_UNICAST
;
11657 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
11659 bool uj
= use_json(argc
, argv
);
11664 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11667 return CMD_WARNING
;
11669 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11670 argv_find(argv
, argc
, "neighbors", &idx
);
11671 peerstr
= argv
[++idx
]->arg
;
11673 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11675 return CMD_WARNING
;
11677 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11678 sh_type
= bgp_show_type_flap_neighbor
;
11679 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
11680 sh_type
= bgp_show_type_damp_neighbor
;
11681 else if (argv_find(argv
, argc
, "routes", &idx
))
11682 sh_type
= bgp_show_type_neighbor
;
11684 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
11687 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
11689 struct bgp_distance
{
11690 /* Distance value for the IP source prefix. */
11693 /* Name of the access-list to be matched. */
11697 DEFUN (show_bgp_afi_vpn_rd_route
,
11698 show_bgp_afi_vpn_rd_route_cmd
,
11699 "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]",
11703 "Address Family modifier\n"
11704 "Display information for a route distinguisher\n"
11705 "Route Distinguisher\n"
11706 "Network in the BGP routing table to display\n"
11707 "Network in the BGP routing table to display\n"
11711 struct prefix_rd prd
;
11712 afi_t afi
= AFI_MAX
;
11715 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
11716 vty_out(vty
, "%% Malformed Address Family\n");
11717 return CMD_WARNING
;
11720 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
11722 vty_out(vty
, "%% Malformed Route Distinguisher\n");
11723 return CMD_WARNING
;
11726 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
11727 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11730 static struct bgp_distance
*bgp_distance_new(void)
11732 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
11735 static void bgp_distance_free(struct bgp_distance
*bdistance
)
11737 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
11740 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
11741 const char *ip_str
, const char *access_list_str
)
11748 struct bgp_node
*rn
;
11749 struct bgp_distance
*bdistance
;
11751 afi
= bgp_node_afi(vty
);
11752 safi
= bgp_node_safi(vty
);
11754 ret
= str2prefix(ip_str
, &p
);
11756 vty_out(vty
, "Malformed prefix\n");
11757 return CMD_WARNING_CONFIG_FAILED
;
11760 distance
= atoi(distance_str
);
11762 /* Get BGP distance node. */
11763 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
11764 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11766 bgp_unlock_node(rn
);
11768 bdistance
= bgp_distance_new();
11769 bgp_node_set_bgp_distance_info(rn
, bdistance
);
11772 /* Set distance value. */
11773 bdistance
->distance
= distance
;
11775 /* Reset access-list configuration. */
11776 if (bdistance
->access_list
) {
11777 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11778 bdistance
->access_list
= NULL
;
11780 if (access_list_str
)
11781 bdistance
->access_list
=
11782 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11784 return CMD_SUCCESS
;
11787 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11788 const char *ip_str
, const char *access_list_str
)
11795 struct bgp_node
*rn
;
11796 struct bgp_distance
*bdistance
;
11798 afi
= bgp_node_afi(vty
);
11799 safi
= bgp_node_safi(vty
);
11801 ret
= str2prefix(ip_str
, &p
);
11803 vty_out(vty
, "Malformed prefix\n");
11804 return CMD_WARNING_CONFIG_FAILED
;
11807 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11808 (struct prefix
*)&p
);
11810 vty_out(vty
, "Can't find specified prefix\n");
11811 return CMD_WARNING_CONFIG_FAILED
;
11814 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11815 distance
= atoi(distance_str
);
11817 if (bdistance
->distance
!= distance
) {
11818 vty_out(vty
, "Distance does not match configured\n");
11819 return CMD_WARNING_CONFIG_FAILED
;
11822 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11823 bgp_distance_free(bdistance
);
11825 bgp_node_set_bgp_path_info(rn
, NULL
);
11826 bgp_unlock_node(rn
);
11827 bgp_unlock_node(rn
);
11829 return CMD_SUCCESS
;
11832 /* Apply BGP information to distance method. */
11833 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11834 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
11836 struct bgp_node
*rn
;
11839 struct bgp_distance
*bdistance
;
11840 struct access_list
*alist
;
11841 struct bgp_static
*bgp_static
;
11846 peer
= pinfo
->peer
;
11848 /* Check source address. */
11849 sockunion2hostprefix(&peer
->su
, &q
);
11850 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
11852 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11853 bgp_unlock_node(rn
);
11855 if (bdistance
->access_list
) {
11856 alist
= access_list_lookup(afi
, bdistance
->access_list
);
11858 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
11859 return bdistance
->distance
;
11861 return bdistance
->distance
;
11864 /* Backdoor check. */
11865 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
11867 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11868 bgp_unlock_node(rn
);
11870 if (bgp_static
->backdoor
) {
11871 if (bgp
->distance_local
[afi
][safi
])
11872 return bgp
->distance_local
[afi
][safi
];
11874 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11878 if (peer
->sort
== BGP_PEER_EBGP
) {
11879 if (bgp
->distance_ebgp
[afi
][safi
])
11880 return bgp
->distance_ebgp
[afi
][safi
];
11881 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
11883 if (bgp
->distance_ibgp
[afi
][safi
])
11884 return bgp
->distance_ibgp
[afi
][safi
];
11885 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11889 DEFUN (bgp_distance
,
11891 "distance bgp (1-255) (1-255) (1-255)",
11892 "Define an administrative distance\n"
11894 "Distance for routes external to the AS\n"
11895 "Distance for routes internal to the AS\n"
11896 "Distance for local routes\n")
11898 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11899 int idx_number
= 2;
11900 int idx_number_2
= 3;
11901 int idx_number_3
= 4;
11905 afi
= bgp_node_afi(vty
);
11906 safi
= bgp_node_safi(vty
);
11908 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
11909 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
11910 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
11911 return CMD_SUCCESS
;
11914 DEFUN (no_bgp_distance
,
11915 no_bgp_distance_cmd
,
11916 "no distance bgp [(1-255) (1-255) (1-255)]",
11918 "Define an administrative distance\n"
11920 "Distance for routes external to the AS\n"
11921 "Distance for routes internal to the AS\n"
11922 "Distance for local routes\n")
11924 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11928 afi
= bgp_node_afi(vty
);
11929 safi
= bgp_node_safi(vty
);
11931 bgp
->distance_ebgp
[afi
][safi
] = 0;
11932 bgp
->distance_ibgp
[afi
][safi
] = 0;
11933 bgp
->distance_local
[afi
][safi
] = 0;
11934 return CMD_SUCCESS
;
11938 DEFUN (bgp_distance_source
,
11939 bgp_distance_source_cmd
,
11940 "distance (1-255) A.B.C.D/M",
11941 "Define an administrative distance\n"
11942 "Administrative distance\n"
11943 "IP source prefix\n")
11945 int idx_number
= 1;
11946 int idx_ipv4_prefixlen
= 2;
11947 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11948 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11949 return CMD_SUCCESS
;
11952 DEFUN (no_bgp_distance_source
,
11953 no_bgp_distance_source_cmd
,
11954 "no distance (1-255) A.B.C.D/M",
11956 "Define an administrative distance\n"
11957 "Administrative distance\n"
11958 "IP source prefix\n")
11960 int idx_number
= 2;
11961 int idx_ipv4_prefixlen
= 3;
11962 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11963 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11964 return CMD_SUCCESS
;
11967 DEFUN (bgp_distance_source_access_list
,
11968 bgp_distance_source_access_list_cmd
,
11969 "distance (1-255) A.B.C.D/M WORD",
11970 "Define an administrative distance\n"
11971 "Administrative distance\n"
11972 "IP source prefix\n"
11973 "Access list name\n")
11975 int idx_number
= 1;
11976 int idx_ipv4_prefixlen
= 2;
11978 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11979 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11980 return CMD_SUCCESS
;
11983 DEFUN (no_bgp_distance_source_access_list
,
11984 no_bgp_distance_source_access_list_cmd
,
11985 "no distance (1-255) A.B.C.D/M WORD",
11987 "Define an administrative distance\n"
11988 "Administrative distance\n"
11989 "IP source prefix\n"
11990 "Access list name\n")
11992 int idx_number
= 2;
11993 int idx_ipv4_prefixlen
= 3;
11995 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11996 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11997 return CMD_SUCCESS
;
12000 DEFUN (ipv6_bgp_distance_source
,
12001 ipv6_bgp_distance_source_cmd
,
12002 "distance (1-255) X:X::X:X/M",
12003 "Define an administrative distance\n"
12004 "Administrative distance\n"
12005 "IP source prefix\n")
12007 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
12008 return CMD_SUCCESS
;
12011 DEFUN (no_ipv6_bgp_distance_source
,
12012 no_ipv6_bgp_distance_source_cmd
,
12013 "no distance (1-255) X:X::X:X/M",
12015 "Define an administrative distance\n"
12016 "Administrative distance\n"
12017 "IP source prefix\n")
12019 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
12020 return CMD_SUCCESS
;
12023 DEFUN (ipv6_bgp_distance_source_access_list
,
12024 ipv6_bgp_distance_source_access_list_cmd
,
12025 "distance (1-255) X:X::X:X/M WORD",
12026 "Define an administrative distance\n"
12027 "Administrative distance\n"
12028 "IP source prefix\n"
12029 "Access list name\n")
12031 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
12032 return CMD_SUCCESS
;
12035 DEFUN (no_ipv6_bgp_distance_source_access_list
,
12036 no_ipv6_bgp_distance_source_access_list_cmd
,
12037 "no distance (1-255) X:X::X:X/M WORD",
12039 "Define an administrative distance\n"
12040 "Administrative distance\n"
12041 "IP source prefix\n"
12042 "Access list name\n")
12044 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
12045 return CMD_SUCCESS
;
12048 DEFUN (bgp_damp_set
,
12050 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12051 "BGP Specific commands\n"
12052 "Enable route-flap dampening\n"
12053 "Half-life time for the penalty\n"
12054 "Value to start reusing a route\n"
12055 "Value to start suppressing a route\n"
12056 "Maximum duration to suppress a stable route\n")
12058 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12059 int idx_half_life
= 2;
12061 int idx_suppress
= 4;
12062 int idx_max_suppress
= 5;
12063 int half
= DEFAULT_HALF_LIFE
* 60;
12064 int reuse
= DEFAULT_REUSE
;
12065 int suppress
= DEFAULT_SUPPRESS
;
12066 int max
= 4 * half
;
12069 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12070 reuse
= atoi(argv
[idx_reuse
]->arg
);
12071 suppress
= atoi(argv
[idx_suppress
]->arg
);
12072 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
12073 } else if (argc
== 3) {
12074 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12078 if (suppress
< reuse
) {
12080 "Suppress value cannot be less than reuse value \n");
12084 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
12085 reuse
, suppress
, max
);
12088 DEFUN (bgp_damp_unset
,
12089 bgp_damp_unset_cmd
,
12090 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12092 "BGP Specific commands\n"
12093 "Enable route-flap dampening\n"
12094 "Half-life time for the penalty\n"
12095 "Value to start reusing a route\n"
12096 "Value to start suppressing a route\n"
12097 "Maximum duration to suppress a stable route\n")
12099 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12100 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
12103 /* Display specified route of BGP table. */
12104 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
12105 const char *ip_str
, afi_t afi
, safi_t safi
,
12106 struct prefix_rd
*prd
, int prefix_check
)
12109 struct prefix match
;
12110 struct bgp_node
*rn
;
12111 struct bgp_node
*rm
;
12112 struct bgp_path_info
*pi
;
12113 struct bgp_path_info
*pi_temp
;
12115 struct bgp_table
*table
;
12117 /* BGP structure lookup. */
12119 bgp
= bgp_lookup_by_name(view_name
);
12121 vty_out(vty
, "%% Can't find BGP instance %s\n",
12123 return CMD_WARNING
;
12126 bgp
= bgp_get_default();
12128 vty_out(vty
, "%% No BGP process is configured\n");
12129 return CMD_WARNING
;
12133 /* Check IP address argument. */
12134 ret
= str2prefix(ip_str
, &match
);
12136 vty_out(vty
, "%% address is malformed\n");
12137 return CMD_WARNING
;
12140 match
.family
= afi2family(afi
);
12142 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
12143 || (safi
== SAFI_EVPN
)) {
12144 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
12145 rn
= bgp_route_next(rn
)) {
12146 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
12148 table
= bgp_node_get_bgp_table_info(rn
);
12151 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
12155 || rm
->p
.prefixlen
== match
.prefixlen
) {
12156 pi
= bgp_node_get_bgp_path_info(rm
);
12158 if (pi
->extra
&& pi
->extra
->damp_info
) {
12159 pi_temp
= pi
->next
;
12160 bgp_damp_info_free(
12161 pi
->extra
->damp_info
,
12169 bgp_unlock_node(rm
);
12172 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
12175 || rn
->p
.prefixlen
== match
.prefixlen
) {
12176 pi
= bgp_node_get_bgp_path_info(rn
);
12178 if (pi
->extra
&& pi
->extra
->damp_info
) {
12179 pi_temp
= pi
->next
;
12180 bgp_damp_info_free(
12181 pi
->extra
->damp_info
,
12189 bgp_unlock_node(rn
);
12193 return CMD_SUCCESS
;
12196 DEFUN (clear_ip_bgp_dampening
,
12197 clear_ip_bgp_dampening_cmd
,
12198 "clear ip bgp dampening",
12202 "Clear route flap dampening information\n")
12204 bgp_damp_info_clean();
12205 return CMD_SUCCESS
;
12208 DEFUN (clear_ip_bgp_dampening_prefix
,
12209 clear_ip_bgp_dampening_prefix_cmd
,
12210 "clear ip bgp dampening A.B.C.D/M",
12214 "Clear route flap dampening information\n"
12217 int idx_ipv4_prefixlen
= 4;
12218 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
12219 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
12222 DEFUN (clear_ip_bgp_dampening_address
,
12223 clear_ip_bgp_dampening_address_cmd
,
12224 "clear ip bgp dampening A.B.C.D",
12228 "Clear route flap dampening information\n"
12229 "Network to clear damping information\n")
12232 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
12233 SAFI_UNICAST
, NULL
, 0);
12236 DEFUN (clear_ip_bgp_dampening_address_mask
,
12237 clear_ip_bgp_dampening_address_mask_cmd
,
12238 "clear ip bgp dampening A.B.C.D A.B.C.D",
12242 "Clear route flap dampening information\n"
12243 "Network to clear damping information\n"
12247 int idx_ipv4_2
= 5;
12249 char prefix_str
[BUFSIZ
];
12251 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
12254 vty_out(vty
, "%% Inconsistent address and mask\n");
12255 return CMD_WARNING
;
12258 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
12262 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
12264 struct vty
*vty
= arg
;
12265 struct peer
*peer
= bucket
->data
;
12266 char buf
[SU_ADDRSTRLEN
];
12268 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
12269 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
12272 DEFUN (show_bgp_peerhash
,
12273 show_bgp_peerhash_cmd
,
12274 "show bgp peerhash",
12277 "Display information about the BGP peerhash\n")
12279 struct list
*instances
= bm
->bgp
;
12280 struct listnode
*node
;
12283 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
12284 vty_out(vty
, "BGP: %s\n", bgp
->name
);
12285 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
12289 return CMD_SUCCESS
;
12292 /* also used for encap safi */
12293 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
12294 afi_t afi
, safi_t safi
)
12296 struct bgp_node
*prn
;
12297 struct bgp_node
*rn
;
12298 struct bgp_table
*table
;
12300 struct prefix_rd
*prd
;
12301 struct bgp_static
*bgp_static
;
12302 mpls_label_t label
;
12303 char buf
[SU_ADDRSTRLEN
];
12304 char rdbuf
[RD_ADDRSTRLEN
];
12306 /* Network configuration. */
12307 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12308 prn
= bgp_route_next(prn
)) {
12309 table
= bgp_node_get_bgp_table_info(prn
);
12313 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12314 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12315 if (bgp_static
== NULL
)
12319 prd
= (struct prefix_rd
*)&prn
->p
;
12321 /* "network" configuration display. */
12322 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12323 label
= decode_label(&bgp_static
->label
);
12325 vty_out(vty
, " network %s/%d rd %s",
12326 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12328 p
->prefixlen
, rdbuf
);
12329 if (safi
== SAFI_MPLS_VPN
)
12330 vty_out(vty
, " label %u", label
);
12332 if (bgp_static
->rmap
.name
)
12333 vty_out(vty
, " route-map %s",
12334 bgp_static
->rmap
.name
);
12336 if (bgp_static
->backdoor
)
12337 vty_out(vty
, " backdoor");
12339 vty_out(vty
, "\n");
12344 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
12345 afi_t afi
, safi_t safi
)
12347 struct bgp_node
*prn
;
12348 struct bgp_node
*rn
;
12349 struct bgp_table
*table
;
12351 struct prefix_rd
*prd
;
12352 struct bgp_static
*bgp_static
;
12353 char buf
[PREFIX_STRLEN
* 2];
12354 char buf2
[SU_ADDRSTRLEN
];
12355 char rdbuf
[RD_ADDRSTRLEN
];
12357 /* Network configuration. */
12358 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12359 prn
= bgp_route_next(prn
)) {
12360 table
= bgp_node_get_bgp_table_info(prn
);
12364 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12365 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12366 if (bgp_static
== NULL
)
12369 char *macrouter
= NULL
;
12372 if (bgp_static
->router_mac
)
12373 macrouter
= prefix_mac2str(
12374 bgp_static
->router_mac
, NULL
, 0);
12375 if (bgp_static
->eth_s_id
)
12376 esi
= esi2str(bgp_static
->eth_s_id
);
12378 prd
= (struct prefix_rd
*)&prn
->p
;
12380 /* "network" configuration display. */
12381 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12382 if (p
->u
.prefix_evpn
.route_type
== 5) {
12383 char local_buf
[PREFIX_STRLEN
];
12384 uint8_t family
= is_evpn_prefix_ipaddr_v4((
12385 struct prefix_evpn
*)p
)
12389 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
12390 local_buf
, PREFIX_STRLEN
);
12391 sprintf(buf
, "%s/%u", local_buf
,
12392 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
12394 prefix2str(p
, buf
, sizeof(buf
));
12397 if (bgp_static
->gatewayIp
.family
== AF_INET
12398 || bgp_static
->gatewayIp
.family
== AF_INET6
)
12399 inet_ntop(bgp_static
->gatewayIp
.family
,
12400 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
12403 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
12405 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
12406 decode_label(&bgp_static
->label
), esi
, buf2
,
12409 XFREE(MTYPE_TMP
, macrouter
);
12410 XFREE(MTYPE_TMP
, esi
);
12415 /* Configuration of static route announcement and aggregate
12417 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12420 struct bgp_node
*rn
;
12422 struct bgp_static
*bgp_static
;
12423 struct bgp_aggregate
*bgp_aggregate
;
12424 char buf
[SU_ADDRSTRLEN
];
12426 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
12427 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
12431 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
12432 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
12436 /* Network configuration. */
12437 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
12438 rn
= bgp_route_next(rn
)) {
12439 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12440 if (bgp_static
== NULL
)
12445 vty_out(vty
, " network %s/%d",
12446 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12449 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
12450 vty_out(vty
, " label-index %u",
12451 bgp_static
->label_index
);
12453 if (bgp_static
->rmap
.name
)
12454 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
12456 if (bgp_static
->backdoor
)
12457 vty_out(vty
, " backdoor");
12459 vty_out(vty
, "\n");
12462 /* Aggregate-address configuration. */
12463 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
12464 rn
= bgp_route_next(rn
)) {
12465 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
12466 if (bgp_aggregate
== NULL
)
12471 vty_out(vty
, " aggregate-address %s/%d",
12472 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12475 if (bgp_aggregate
->as_set
)
12476 vty_out(vty
, " as-set");
12478 if (bgp_aggregate
->summary_only
)
12479 vty_out(vty
, " summary-only");
12481 vty_out(vty
, "\n");
12485 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12488 struct bgp_node
*rn
;
12489 struct bgp_distance
*bdistance
;
12491 /* Distance configuration. */
12492 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
12493 && bgp
->distance_local
[afi
][safi
]
12494 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
12495 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
12496 || bgp
->distance_local
[afi
][safi
]
12497 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
12498 vty_out(vty
, " distance bgp %d %d %d\n",
12499 bgp
->distance_ebgp
[afi
][safi
],
12500 bgp
->distance_ibgp
[afi
][safi
],
12501 bgp
->distance_local
[afi
][safi
]);
12504 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
12505 rn
= bgp_route_next(rn
)) {
12506 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12507 if (bdistance
!= NULL
) {
12508 char buf
[PREFIX_STRLEN
];
12510 vty_out(vty
, " distance %d %s %s\n",
12511 bdistance
->distance
,
12512 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
12513 bdistance
->access_list
? bdistance
->access_list
12519 /* Allocate routing table structure and install commands. */
12520 void bgp_route_init(void)
12525 /* Init BGP distance table. */
12526 FOREACH_AFI_SAFI (afi
, safi
)
12527 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
12529 /* IPv4 BGP commands. */
12530 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12531 install_element(BGP_NODE
, &bgp_network_cmd
);
12532 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
12534 install_element(BGP_NODE
, &aggregate_address_cmd
);
12535 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
12536 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
12537 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
12539 /* IPv4 unicast configuration. */
12540 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
12541 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
12542 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
12544 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
12545 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
12546 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
12547 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
12549 /* IPv4 multicast configuration. */
12550 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
12551 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
12552 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
12553 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
12554 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
12555 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
12556 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
12558 /* IPv4 labeled-unicast configuration. */
12559 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
12560 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
12561 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
12562 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
12563 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
12565 install_element(VIEW_NODE
,
12566 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
12567 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
12568 install_element(VIEW_NODE
,
12569 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
12570 #ifdef KEEP_OLD_VPN_COMMANDS
12571 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
12572 #endif /* KEEP_OLD_VPN_COMMANDS */
12573 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
12574 install_element(VIEW_NODE
,
12575 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
12577 /* BGP dampening clear commands */
12578 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
12579 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
12581 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
12582 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
12585 install_element(ENABLE_NODE
,
12586 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
12587 #ifdef KEEP_OLD_VPN_COMMANDS
12588 install_element(ENABLE_NODE
,
12589 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
12590 #endif /* KEEP_OLD_VPN_COMMANDS */
12592 /* New config IPv6 BGP commands. */
12593 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
12594 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
12595 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
12597 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
12598 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
12600 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
12602 install_element(BGP_NODE
, &bgp_distance_cmd
);
12603 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
12604 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
12605 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
12606 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
12607 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
12608 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
12609 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
12610 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
12611 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
12612 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
12613 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
12614 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
12615 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
12616 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
12617 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
12618 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
12619 install_element(BGP_IPV4M_NODE
,
12620 &no_bgp_distance_source_access_list_cmd
);
12621 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
12622 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
12623 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
12624 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12625 install_element(BGP_IPV6_NODE
,
12626 &ipv6_bgp_distance_source_access_list_cmd
);
12627 install_element(BGP_IPV6_NODE
,
12628 &no_ipv6_bgp_distance_source_access_list_cmd
);
12629 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
12630 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
12631 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
12632 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12633 install_element(BGP_IPV6M_NODE
,
12634 &ipv6_bgp_distance_source_access_list_cmd
);
12635 install_element(BGP_IPV6M_NODE
,
12636 &no_ipv6_bgp_distance_source_access_list_cmd
);
12638 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
12639 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
12640 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
12641 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
12643 /* IPv4 Multicast Mode */
12644 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
12645 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
12647 /* Large Communities */
12648 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
12649 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
12651 /* show bgp ipv4 flowspec detailed */
12652 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
12654 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
12657 void bgp_route_finish(void)
12662 FOREACH_AFI_SAFI (afi
, safi
) {
12663 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
12664 bgp_distance_table
[afi
][safi
] = NULL
;