1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* BGP routing information
3 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
4 * Copyright (C) 2016 Job Snijders <job@instituut.net>
21 #include "sockunion.h"
24 #include "workqueue.h"
29 #include "lib_errors.h"
31 #include "bgpd/bgpd.h"
32 #include "bgpd/bgp_table.h"
33 #include "bgpd/bgp_route.h"
34 #include "bgpd/bgp_attr.h"
35 #include "bgpd/bgp_debug.h"
36 #include "bgpd/bgp_errors.h"
37 #include "bgpd/bgp_aspath.h"
38 #include "bgpd/bgp_regex.h"
39 #include "bgpd/bgp_community.h"
40 #include "bgpd/bgp_community_alias.h"
41 #include "bgpd/bgp_ecommunity.h"
42 #include "bgpd/bgp_lcommunity.h"
43 #include "bgpd/bgp_clist.h"
44 #include "bgpd/bgp_packet.h"
45 #include "bgpd/bgp_filter.h"
46 #include "bgpd/bgp_fsm.h"
47 #include "bgpd/bgp_mplsvpn.h"
48 #include "bgpd/bgp_nexthop.h"
49 #include "bgpd/bgp_damp.h"
50 #include "bgpd/bgp_advertise.h"
51 #include "bgpd/bgp_zebra.h"
52 #include "bgpd/bgp_vty.h"
53 #include "bgpd/bgp_mpath.h"
54 #include "bgpd/bgp_nht.h"
55 #include "bgpd/bgp_updgrp.h"
56 #include "bgpd/bgp_label.h"
57 #include "bgpd/bgp_addpath.h"
58 #include "bgpd/bgp_mac.h"
59 #include "bgpd/bgp_network.h"
60 #include "bgpd/bgp_trace.h"
61 #include "bgpd/bgp_rpki.h"
64 #include "bgpd/rfapi/rfapi_backend.h"
65 #include "bgpd/rfapi/vnc_import_bgp.h"
66 #include "bgpd/rfapi/vnc_export_bgp.h"
68 #include "bgpd/bgp_encap_types.h"
69 #include "bgpd/bgp_encap_tlv.h"
70 #include "bgpd/bgp_evpn.h"
71 #include "bgpd/bgp_evpn_mh.h"
72 #include "bgpd/bgp_evpn_vty.h"
73 #include "bgpd/bgp_flowspec.h"
74 #include "bgpd/bgp_flowspec_util.h"
75 #include "bgpd/bgp_pbr.h"
77 #include "bgpd/bgp_route_clippy.c"
79 DEFINE_HOOK(bgp_snmp_update_stats
,
80 (struct bgp_node
*rn
, struct bgp_path_info
*pi
, bool added
),
83 DEFINE_HOOK(bgp_rpki_prefix_status
,
84 (struct peer
*peer
, struct attr
*attr
,
85 const struct prefix
*prefix
),
86 (peer
, attr
, prefix
));
88 /* Extern from bgp_dump.c */
89 extern const char *bgp_origin_str
[];
90 extern const char *bgp_origin_long_str
[];
93 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
94 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
95 static const struct message bgp_pmsi_tnltype_str
[] = {
96 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
97 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
98 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
99 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
100 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
101 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
102 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
103 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
107 #define VRFID_NONE_STR "-"
108 #define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
110 DEFINE_HOOK(bgp_process
,
111 (struct bgp
* bgp
, afi_t afi
, safi_t safi
, struct bgp_dest
*bn
,
112 struct peer
*peer
, bool withdraw
),
113 (bgp
, afi
, safi
, bn
, peer
, withdraw
));
115 /** Test if path is suppressed. */
116 static bool bgp_path_suppressed(struct bgp_path_info
*pi
)
118 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
121 return listcount(pi
->extra
->aggr_suppressors
) > 0;
124 struct bgp_dest
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
125 safi_t safi
, const struct prefix
*p
,
126 struct prefix_rd
*prd
)
128 struct bgp_dest
*dest
;
129 struct bgp_dest
*pdest
= NULL
;
133 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
134 || (safi
== SAFI_EVPN
)) {
135 pdest
= bgp_node_get(table
, (struct prefix
*)prd
);
137 if (!bgp_dest_has_bgp_path_info_data(pdest
))
138 bgp_dest_set_bgp_table_info(
139 pdest
, bgp_table_init(table
->bgp
, afi
, safi
));
141 bgp_dest_unlock_node(pdest
);
142 table
= bgp_dest_get_bgp_table_info(pdest
);
145 dest
= bgp_node_get(table
, p
);
147 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
148 || (safi
== SAFI_EVPN
))
154 struct bgp_dest
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
155 safi_t safi
, const struct prefix
*p
,
156 struct prefix_rd
*prd
)
158 struct bgp_dest
*dest
;
159 struct bgp_dest
*pdest
= NULL
;
164 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
165 || (safi
== SAFI_EVPN
)) {
166 pdest
= bgp_node_lookup(table
, (struct prefix
*)prd
);
170 if (!bgp_dest_has_bgp_path_info_data(pdest
)) {
171 bgp_dest_unlock_node(pdest
);
175 table
= bgp_dest_get_bgp_table_info(pdest
);
178 dest
= bgp_node_lookup(table
, p
);
183 /* Allocate bgp_path_info_extra */
184 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
186 struct bgp_path_info_extra
*new;
187 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
188 sizeof(struct bgp_path_info_extra
));
189 new->label
[0] = MPLS_INVALID_LABEL
;
191 new->bgp_fs_pbr
= NULL
;
192 new->bgp_fs_iprule
= NULL
;
196 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
198 struct bgp_path_info_extra
*e
;
200 if (!extra
|| !*extra
)
205 bgp_damp_info_free(e
->damp_info
, 0, e
->damp_info
->afi
,
210 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
213 /* FIXME: since multiple e may have the same e->parent
214 * and e->parent->net is holding a refcount for each
215 * of them, we need to do some fudging here.
217 * WARNING: if bpi->net->lock drops to 0, bpi may be
218 * freed as well (because bpi->net was holding the
219 * last reference to bpi) => write after free!
223 bpi
= bgp_path_info_lock(bpi
);
224 refcount
= bgp_dest_get_lock_count(bpi
->net
) - 1;
225 bgp_dest_unlock_node((struct bgp_dest
*)bpi
->net
);
228 bgp_path_info_unlock(bpi
);
230 bgp_path_info_unlock(e
->parent
);
235 bgp_unlock(e
->bgp_orig
);
238 peer_unlock(e
->peer_orig
);
240 if (e
->aggr_suppressors
)
241 list_delete(&e
->aggr_suppressors
);
244 bgp_evpn_path_mh_info_free(e
->mh_info
);
246 if ((*extra
)->bgp_fs_iprule
)
247 list_delete(&((*extra
)->bgp_fs_iprule
));
248 if ((*extra
)->bgp_fs_pbr
)
249 list_delete(&((*extra
)->bgp_fs_pbr
));
250 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
253 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
254 * allocated if required.
256 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
259 pi
->extra
= bgp_path_info_extra_new();
263 /* Free bgp route information. */
264 void bgp_path_info_free_with_caller(const char *name
,
265 struct bgp_path_info
*path
)
267 frrtrace(2, frr_bgp
, bgp_path_info_free
, path
, name
);
268 bgp_attr_unintern(&path
->attr
);
270 bgp_unlink_nexthop(path
);
271 bgp_path_info_extra_free(&path
->extra
);
272 bgp_path_info_mpath_free(&path
->mpath
);
274 bgp_addpath_free_info_data(&path
->tx_addpath
,
275 &path
->net
->tx_addpath
);
277 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
279 XFREE(MTYPE_BGP_ROUTE
, path
);
282 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
288 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
290 assert(path
&& path
->lock
> 0);
293 if (path
->lock
== 0) {
294 bgp_path_info_free(path
);
301 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
302 static int bgp_dest_set_defer_flag(struct bgp_dest
*dest
, bool delete)
305 struct bgp_path_info
*old_pi
, *nextpi
;
306 bool set_flag
= false;
307 struct bgp
*bgp
= NULL
;
308 struct bgp_table
*table
= NULL
;
312 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
313 * then the route selection is deferred
315 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
318 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
319 if (BGP_DEBUG(update
, UPDATE_OUT
))
321 "Route %pBD is in workqueue and being processed, not deferred.",
327 table
= bgp_dest_table(dest
);
334 for (old_pi
= bgp_dest_get_bgp_path_info(dest
);
335 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
336 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
339 /* Route selection is deferred if there is a stale path which
340 * which indicates peer is in restart mode
342 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
343 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
346 /* If the peer is graceful restart capable and peer is
347 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
350 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
351 && BGP_PEER_RESTARTING_MODE(peer
)
353 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
361 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
364 if (set_flag
&& table
) {
365 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
366 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
367 bgp
->gr_info
[afi
][safi
].gr_deferred
++;
368 SET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
369 if (BGP_DEBUG(update
, UPDATE_OUT
))
370 zlog_debug("DEFER route %pBD, dest %p", dest
,
378 void bgp_path_info_add_with_caller(const char *name
, struct bgp_dest
*dest
,
379 struct bgp_path_info
*pi
)
381 frrtrace(3, frr_bgp
, bgp_path_info_add
, dest
, pi
, name
);
382 struct bgp_path_info
*top
;
384 top
= bgp_dest_get_bgp_path_info(dest
);
390 bgp_dest_set_bgp_path_info(dest
, pi
);
392 bgp_path_info_lock(pi
);
393 bgp_dest_lock_node(dest
);
394 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
395 bgp_dest_set_defer_flag(dest
, false);
396 hook_call(bgp_snmp_update_stats
, dest
, pi
, true);
399 /* Do the actual removal of info from RIB, for use by bgp_process
400 completion callback *only* */
401 void bgp_path_info_reap(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
404 pi
->next
->prev
= pi
->prev
;
406 pi
->prev
->next
= pi
->next
;
408 bgp_dest_set_bgp_path_info(dest
, pi
->next
);
410 bgp_path_info_mpath_dequeue(pi
);
411 bgp_path_info_unlock(pi
);
412 hook_call(bgp_snmp_update_stats
, dest
, pi
, false);
413 bgp_dest_unlock_node(dest
);
416 void bgp_path_info_delete(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
418 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_REMOVED
);
419 /* set of previous already took care of pcount */
420 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
423 /* undo the effects of a previous call to bgp_path_info_delete; typically
424 called when a route is deleted and then quickly re-added before the
425 deletion has been processed */
426 void bgp_path_info_restore(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
428 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_REMOVED
);
429 /* unset of previous already took care of pcount */
430 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
433 /* Adjust pcount as required */
434 static void bgp_pcount_adjust(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
436 struct bgp_table
*table
;
438 assert(dest
&& bgp_dest_table(dest
));
439 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
441 table
= bgp_dest_table(dest
);
443 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
446 if (!BGP_PATH_COUNTABLE(pi
)
447 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
449 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
451 /* slight hack, but more robust against errors. */
452 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
453 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
455 flog_err(EC_LIB_DEVELOPMENT
,
456 "Asked to decrement 0 prefix count for peer");
457 } else if (BGP_PATH_COUNTABLE(pi
)
458 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
459 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
460 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
464 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
465 struct bgp_path_info
*pi2
)
467 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
470 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
471 * This is here primarily to keep prefix-count in check.
473 void bgp_path_info_set_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
476 SET_FLAG(pi
->flags
, flag
);
478 /* early bath if we know it's not a flag that changes countability state
480 if (!CHECK_FLAG(flag
,
481 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
484 bgp_pcount_adjust(dest
, pi
);
487 void bgp_path_info_unset_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
490 UNSET_FLAG(pi
->flags
, flag
);
492 /* early bath if we know it's not a flag that changes countability state
494 if (!CHECK_FLAG(flag
,
495 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
498 bgp_pcount_adjust(dest
, pi
);
501 /* Get MED value. If MED value is missing and "bgp bestpath
502 missing-as-worst" is specified, treat it as the worst value. */
503 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
505 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
508 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
515 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
,
518 if (pi
->addpath_rx_id
)
519 snprintf(buf
, buf_len
, "path %s (addpath rxid %d)",
520 pi
->peer
->host
, pi
->addpath_rx_id
);
522 snprintf(buf
, buf_len
, "path %s", pi
->peer
->host
);
527 * Get the ultimate path info.
529 struct bgp_path_info
*bgp_get_imported_bpi_ultimate(struct bgp_path_info
*info
)
531 struct bgp_path_info
*bpi_ultimate
;
533 if (info
->sub_type
!= BGP_ROUTE_IMPORTED
)
536 for (bpi_ultimate
= info
;
537 bpi_ultimate
->extra
&& bpi_ultimate
->extra
->parent
;
538 bpi_ultimate
= bpi_ultimate
->extra
->parent
)
544 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
546 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
547 struct bgp_path_info
*exist
, int *paths_eq
,
548 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
549 char *pfx_buf
, afi_t afi
, safi_t safi
,
550 enum bgp_path_selection_reason
*reason
)
552 const struct prefix
*new_p
;
553 struct attr
*newattr
, *existattr
;
554 enum bgp_peer_sort new_sort
;
555 enum bgp_peer_sort exist_sort
;
561 uint32_t exist_weight
;
562 uint32_t newm
, existm
;
563 struct in_addr new_id
;
564 struct in_addr exist_id
;
567 int internal_as_route
;
570 int igp_metric_ret
= 0;
571 int peer_sort_ret
= -1;
572 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
573 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
575 uint32_t exist_mm_seq
;
582 bool new_origin
, exist_origin
;
583 struct bgp_path_info
*bpi_ultimate
;
589 *reason
= bgp_path_selection_none
;
591 zlog_debug("%s: new is NULL", pfx_buf
);
596 bpi_ultimate
= bgp_get_imported_bpi_ultimate(new);
597 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, new_buf
,
602 *reason
= bgp_path_selection_first
;
604 zlog_debug("%s(%s): %s is the initial bestpath",
605 pfx_buf
, bgp
->name_pretty
, new_buf
);
610 bpi_ultimate
= bgp_get_imported_bpi_ultimate(exist
);
611 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, exist_buf
,
613 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
614 pfx_buf
, bgp
->name_pretty
, new_buf
, new->flags
,
615 exist_buf
, exist
->flags
);
619 existattr
= exist
->attr
;
621 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
622 * Capability" to a neighbor MUST perform the following upon receiving
623 * a route from that neighbor with the "LLGR_STALE" community, or upon
624 * attaching the "LLGR_STALE" community itself per Section 4.2:
626 * Treat the route as the least-preferred in route selection (see
627 * below). See the Risks of Depreferencing Routes section (Section 5.2)
628 * for a discussion of potential risks inherent in doing this.
630 if (bgp_attr_get_community(newattr
) &&
631 community_include(bgp_attr_get_community(newattr
),
632 COMMUNITY_LLGR_STALE
)) {
635 "%s: %s wins over %s due to LLGR_STALE community",
636 pfx_buf
, new_buf
, exist_buf
);
640 if (bgp_attr_get_community(existattr
) &&
641 community_include(bgp_attr_get_community(existattr
),
642 COMMUNITY_LLGR_STALE
)) {
645 "%s: %s loses to %s due to LLGR_STALE community",
646 pfx_buf
, new_buf
, exist_buf
);
650 new_p
= bgp_dest_get_prefix(new->net
);
652 /* For EVPN routes, we cannot just go by local vs remote, we have to
653 * look at the MAC mobility sequence number, if present.
655 if ((safi
== SAFI_EVPN
)
656 && (new_p
->u
.prefix_evpn
.route_type
== BGP_EVPN_MAC_IP_ROUTE
)) {
657 /* This is an error condition described in RFC 7432 Section
659 * states that in this scenario "the PE MUST alert the operator"
661 * does not state what other action to take. In order to provide
663 * consistency in this scenario we are going to prefer the path
667 if (newattr
->sticky
!= existattr
->sticky
) {
669 prefix2str(new_p
, pfx_buf
,
671 * PREFIX2STR_BUFFER
);
672 bgp_path_info_path_with_addpath_rx_str(
673 new, new_buf
, sizeof(new_buf
));
674 bgp_path_info_path_with_addpath_rx_str(
675 exist
, exist_buf
, sizeof(exist_buf
));
678 if (newattr
->sticky
&& !existattr
->sticky
) {
679 *reason
= bgp_path_selection_evpn_sticky_mac
;
682 "%s: %s wins over %s due to sticky MAC flag",
683 pfx_buf
, new_buf
, exist_buf
);
687 if (!newattr
->sticky
&& existattr
->sticky
) {
688 *reason
= bgp_path_selection_evpn_sticky_mac
;
691 "%s: %s loses to %s due to sticky MAC flag",
692 pfx_buf
, new_buf
, exist_buf
);
697 new_esi
= bgp_evpn_attr_get_esi(newattr
);
698 exist_esi
= bgp_evpn_attr_get_esi(existattr
);
699 if (bgp_evpn_is_esi_valid(new_esi
) &&
700 !memcmp(new_esi
, exist_esi
, sizeof(esi_t
))) {
706 /* If both paths have the same non-zero ES and
707 * one path is local it wins.
708 * PS: Note the local path wins even if the remote
709 * has the higher MM seq. The local path's
710 * MM seq will be fixed up to match the highest
711 * rem seq, subsequently.
714 char esi_buf
[ESI_STR_LEN
];
716 if (bgp_evpn_is_path_local(bgp
, new)) {
717 *reason
= bgp_path_selection_evpn_local_path
;
720 "%s: %s wins over %s as ES %s is same and local",
721 pfx_buf
, new_buf
, exist_buf
,
722 esi_to_str(new_esi
, esi_buf
,
726 if (bgp_evpn_is_path_local(bgp
, exist
)) {
727 *reason
= bgp_path_selection_evpn_local_path
;
730 "%s: %s loses to %s as ES %s is same and local",
731 pfx_buf
, new_buf
, exist_buf
,
732 esi_to_str(new_esi
, esi_buf
,
738 new_mm_seq
= mac_mobility_seqnum(newattr
);
739 exist_mm_seq
= mac_mobility_seqnum(existattr
);
741 if (new_mm_seq
> exist_mm_seq
) {
742 *reason
= bgp_path_selection_evpn_seq
;
745 "%s: %s wins over %s due to MM seq %u > %u",
746 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
751 if (new_mm_seq
< exist_mm_seq
) {
752 *reason
= bgp_path_selection_evpn_seq
;
755 "%s: %s loses to %s due to MM seq %u < %u",
756 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
761 /* if the sequence numbers and ESI are the same and one path
762 * is non-proxy it wins (over proxy)
764 new_proxy
= bgp_evpn_attr_is_proxy(newattr
);
765 old_proxy
= bgp_evpn_attr_is_proxy(existattr
);
766 if (same_esi
&& bgp_evpn_attr_is_local_es(newattr
) &&
767 old_proxy
!= new_proxy
) {
769 *reason
= bgp_path_selection_evpn_non_proxy
;
772 "%s: %s wins over %s, same seq/es and non-proxy",
773 pfx_buf
, new_buf
, exist_buf
);
777 *reason
= bgp_path_selection_evpn_non_proxy
;
780 "%s: %s loses to %s, same seq/es and non-proxy",
781 pfx_buf
, new_buf
, exist_buf
);
786 * if sequence numbers are the same path with the lowest IP
789 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
791 *reason
= bgp_path_selection_evpn_lower_ip
;
794 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
795 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
796 &new->attr
->nexthop
);
800 *reason
= bgp_path_selection_evpn_lower_ip
;
803 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
804 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
805 &new->attr
->nexthop
);
810 /* 1. Weight check. */
811 new_weight
= newattr
->weight
;
812 exist_weight
= existattr
->weight
;
814 if (new_weight
> exist_weight
) {
815 *reason
= bgp_path_selection_weight
;
817 zlog_debug("%s: %s wins over %s due to weight %d > %d",
818 pfx_buf
, new_buf
, exist_buf
, new_weight
,
823 if (new_weight
< exist_weight
) {
824 *reason
= bgp_path_selection_weight
;
826 zlog_debug("%s: %s loses to %s due to weight %d < %d",
827 pfx_buf
, new_buf
, exist_buf
, new_weight
,
832 /* 2. Local preference check. */
833 new_pref
= exist_pref
= bgp
->default_local_pref
;
835 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
836 new_pref
= newattr
->local_pref
;
837 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
838 exist_pref
= existattr
->local_pref
;
840 if (new_pref
> exist_pref
) {
841 *reason
= bgp_path_selection_local_pref
;
844 "%s: %s wins over %s due to localpref %d > %d",
845 pfx_buf
, new_buf
, exist_buf
, new_pref
,
850 if (new_pref
< exist_pref
) {
851 *reason
= bgp_path_selection_local_pref
;
854 "%s: %s loses to %s due to localpref %d < %d",
855 pfx_buf
, new_buf
, exist_buf
, new_pref
,
860 /* If a BGP speaker supports ACCEPT_OWN and is configured for the
861 * extensions defined in this document, the following step is inserted
862 * after the LOCAL_PREF comparison step in the BGP decision process:
863 * When comparing a pair of routes for a BGP destination, the
864 * route with the ACCEPT_OWN community attached is preferred over
865 * the route that does not have the community.
866 * This extra step MUST only be invoked during the best path selection
867 * process of VPN-IP routes.
869 if (safi
== SAFI_MPLS_VPN
&&
870 (CHECK_FLAG(new->peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
) ||
871 CHECK_FLAG(exist
->peer
->af_flags
[afi
][safi
],
872 PEER_FLAG_ACCEPT_OWN
))) {
873 bool new_accept_own
= false;
874 bool exist_accept_own
= false;
875 uint32_t accept_own
= COMMUNITY_ACCEPT_OWN
;
877 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))
878 new_accept_own
= community_include(
879 bgp_attr_get_community(newattr
), accept_own
);
880 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))
881 exist_accept_own
= community_include(
882 bgp_attr_get_community(existattr
), accept_own
);
884 if (new_accept_own
&& !exist_accept_own
) {
885 *reason
= bgp_path_selection_accept_own
;
888 "%s: %s wins over %s due to accept-own",
889 pfx_buf
, new_buf
, exist_buf
);
893 if (!new_accept_own
&& exist_accept_own
) {
894 *reason
= bgp_path_selection_accept_own
;
897 "%s: %s loses to %s due to accept-own",
898 pfx_buf
, new_buf
, exist_buf
);
903 /* Tie-breaker - AIGP (Metric TLV) attribute */
904 if (CHECK_FLAG(newattr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) &&
905 CHECK_FLAG(existattr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) &&
906 CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_AIGP
)) {
907 uint64_t new_aigp
= bgp_attr_get_aigp_metric(newattr
);
908 uint64_t exist_aigp
= bgp_attr_get_aigp_metric(existattr
);
910 if (new_aigp
< exist_aigp
) {
911 *reason
= bgp_path_selection_aigp
;
914 "%s: %s wins over %s due to AIGP %" PRIu64
916 pfx_buf
, new_buf
, exist_buf
, new_aigp
,
921 if (new_aigp
> exist_aigp
) {
922 *reason
= bgp_path_selection_aigp
;
925 "%s: %s loses to %s due to AIGP %" PRIu64
927 pfx_buf
, new_buf
, exist_buf
, new_aigp
,
933 /* 3. Local route check. We prefer:
935 * - BGP_ROUTE_AGGREGATE
936 * - BGP_ROUTE_REDISTRIBUTE
938 new_origin
= !(new->sub_type
== BGP_ROUTE_NORMAL
||
939 new->sub_type
== BGP_ROUTE_IMPORTED
);
940 exist_origin
= !(exist
->sub_type
== BGP_ROUTE_NORMAL
||
941 exist
->sub_type
== BGP_ROUTE_IMPORTED
);
943 if (new_origin
&& !exist_origin
) {
944 *reason
= bgp_path_selection_local_route
;
947 "%s: %s wins over %s due to preferred BGP_ROUTE type",
948 pfx_buf
, new_buf
, exist_buf
);
952 if (!new_origin
&& exist_origin
) {
953 *reason
= bgp_path_selection_local_route
;
956 "%s: %s loses to %s due to preferred BGP_ROUTE type",
957 pfx_buf
, new_buf
, exist_buf
);
961 /* Here if these are imported routes then get ultimate pi for
964 new = bgp_get_imported_bpi_ultimate(new);
965 exist
= bgp_get_imported_bpi_ultimate(exist
);
967 existattr
= exist
->attr
;
969 /* 4. AS path length check. */
970 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
971 int exist_hops
= aspath_count_hops(existattr
->aspath
);
972 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
974 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
977 aspath_hops
= aspath_count_hops(newattr
->aspath
);
978 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
980 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
981 *reason
= bgp_path_selection_confed_as_path
;
984 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
985 pfx_buf
, new_buf
, exist_buf
,
987 (exist_hops
+ exist_confeds
));
991 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
992 *reason
= bgp_path_selection_confed_as_path
;
995 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
996 pfx_buf
, new_buf
, exist_buf
,
998 (exist_hops
+ exist_confeds
));
1002 int newhops
= aspath_count_hops(newattr
->aspath
);
1004 if (newhops
< exist_hops
) {
1005 *reason
= bgp_path_selection_as_path
;
1008 "%s: %s wins over %s due to aspath hopcount %d < %d",
1009 pfx_buf
, new_buf
, exist_buf
,
1010 newhops
, exist_hops
);
1014 if (newhops
> exist_hops
) {
1015 *reason
= bgp_path_selection_as_path
;
1018 "%s: %s loses to %s due to aspath hopcount %d > %d",
1019 pfx_buf
, new_buf
, exist_buf
,
1020 newhops
, exist_hops
);
1026 /* 5. Origin check. */
1027 if (newattr
->origin
< existattr
->origin
) {
1028 *reason
= bgp_path_selection_origin
;
1030 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
1031 pfx_buf
, new_buf
, exist_buf
,
1032 bgp_origin_long_str
[newattr
->origin
],
1033 bgp_origin_long_str
[existattr
->origin
]);
1037 if (newattr
->origin
> existattr
->origin
) {
1038 *reason
= bgp_path_selection_origin
;
1040 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
1041 pfx_buf
, new_buf
, exist_buf
,
1042 bgp_origin_long_str
[newattr
->origin
],
1043 bgp_origin_long_str
[existattr
->origin
]);
1048 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
1049 && aspath_count_hops(existattr
->aspath
) == 0);
1050 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
1051 && aspath_count_confeds(existattr
->aspath
) > 0
1052 && aspath_count_hops(newattr
->aspath
) == 0
1053 && aspath_count_hops(existattr
->aspath
) == 0);
1055 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
1056 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
1057 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
1058 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
1059 || internal_as_route
) {
1060 new_med
= bgp_med_value(new->attr
, bgp
);
1061 exist_med
= bgp_med_value(exist
->attr
, bgp
);
1063 if (new_med
< exist_med
) {
1064 *reason
= bgp_path_selection_med
;
1067 "%s: %s wins over %s due to MED %d < %d",
1068 pfx_buf
, new_buf
, exist_buf
, new_med
,
1073 if (new_med
> exist_med
) {
1074 *reason
= bgp_path_selection_med
;
1077 "%s: %s loses to %s due to MED %d > %d",
1078 pfx_buf
, new_buf
, exist_buf
, new_med
,
1084 /* 7. Peer type check. */
1085 new_sort
= new->peer
->sort
;
1086 exist_sort
= exist
->peer
->sort
;
1088 if (new_sort
== BGP_PEER_EBGP
1089 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
1090 *reason
= bgp_path_selection_peer
;
1093 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1094 pfx_buf
, new_buf
, exist_buf
);
1095 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1100 if (exist_sort
== BGP_PEER_EBGP
1101 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
1102 *reason
= bgp_path_selection_peer
;
1105 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1106 pfx_buf
, new_buf
, exist_buf
);
1107 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1112 /* 8. IGP metric check. */
1116 newm
= new->extra
->igpmetric
;
1118 existm
= exist
->extra
->igpmetric
;
1120 if (newm
< existm
) {
1121 if (debug
&& peer_sort_ret
< 0)
1123 "%s: %s wins over %s due to IGP metric %u < %u",
1124 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1128 if (newm
> existm
) {
1129 if (debug
&& peer_sort_ret
< 0)
1131 "%s: %s loses to %s due to IGP metric %u > %u",
1132 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1136 /* 9. Same IGP metric. Compare the cluster list length as
1137 representative of IGP hops metric. Rewrite the metric value
1138 pair (newm, existm) with the cluster list length. Prefer the
1139 path with smaller cluster list length. */
1140 if (newm
== existm
) {
1141 if (peer_sort_lookup(new->peer
) == BGP_PEER_IBGP
&&
1142 peer_sort_lookup(exist
->peer
) == BGP_PEER_IBGP
&&
1143 (mpath_cfg
== NULL
|| mpath_cfg
->same_clusterlen
)) {
1144 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1145 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1147 if (newm
< existm
) {
1148 if (debug
&& peer_sort_ret
< 0)
1150 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
1151 pfx_buf
, new_buf
, exist_buf
,
1156 if (newm
> existm
) {
1157 if (debug
&& peer_sort_ret
< 0)
1159 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
1160 pfx_buf
, new_buf
, exist_buf
,
1167 /* 10. confed-external vs. confed-internal */
1168 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1169 if (new_sort
== BGP_PEER_CONFED
1170 && exist_sort
== BGP_PEER_IBGP
) {
1171 *reason
= bgp_path_selection_confed
;
1174 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1175 pfx_buf
, new_buf
, exist_buf
);
1176 if (!CHECK_FLAG(bgp
->flags
,
1177 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1182 if (exist_sort
== BGP_PEER_CONFED
1183 && new_sort
== BGP_PEER_IBGP
) {
1184 *reason
= bgp_path_selection_confed
;
1187 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1188 pfx_buf
, new_buf
, exist_buf
);
1189 if (!CHECK_FLAG(bgp
->flags
,
1190 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1196 /* 11. Maximum path check. */
1197 if (newm
== existm
) {
1198 /* If one path has a label but the other does not, do not treat
1199 * them as equals for multipath
1206 newl
= new->extra
->num_labels
;
1208 existl
= exist
->extra
->num_labels
;
1209 if (((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0])) !=
1211 bgp_is_valid_label(&exist
->extra
->label
[0]))) ||
1215 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1216 pfx_buf
, new_buf
, exist_buf
);
1217 } else if (CHECK_FLAG(bgp
->flags
,
1218 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
1221 * For the two paths, all comparison steps till IGP
1223 * have succeeded - including AS_PATH hop count. Since
1225 * bestpath as-path multipath-relax' knob is on, we
1227 * an exact match of AS_PATH. Thus, mark the paths are
1229 * That will trigger both these paths to get into the
1237 "%s: %s and %s are equal via multipath-relax",
1238 pfx_buf
, new_buf
, exist_buf
);
1239 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
1240 if (aspath_cmp(new->attr
->aspath
,
1241 exist
->attr
->aspath
)) {
1246 "%s: %s and %s are equal via matching aspaths",
1247 pfx_buf
, new_buf
, exist_buf
);
1249 } else if (new->peer
->as
== exist
->peer
->as
) {
1254 "%s: %s and %s are equal via same remote-as",
1255 pfx_buf
, new_buf
, exist_buf
);
1259 * TODO: If unequal cost ibgp multipath is enabled we can
1260 * mark the paths as equal here instead of returning
1263 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1264 * if either step 7 or 10 (peer type checks) yielded a winner,
1265 * that result was returned immediately. Returning from step 10
1266 * ignored the return value computed in steps 8 and 9 (IGP
1267 * metric checks). In order to preserve that behavior, if
1268 * peer_sort_ret is set, return that rather than igp_metric_ret.
1270 ret
= peer_sort_ret
;
1271 if (peer_sort_ret
< 0) {
1272 ret
= igp_metric_ret
;
1276 "%s: %s wins over %s after IGP metric comparison",
1277 pfx_buf
, new_buf
, exist_buf
);
1280 "%s: %s loses to %s after IGP metric comparison",
1281 pfx_buf
, new_buf
, exist_buf
);
1283 *reason
= bgp_path_selection_igp_metric
;
1289 * At this point, the decision whether to set *paths_eq = 1 has been
1290 * completed. If we deferred returning because of bestpath peer-type
1291 * relax configuration, return now.
1293 if (peer_sort_ret
>= 0)
1294 return peer_sort_ret
;
1296 /* 12. If both paths are external, prefer the path that was received
1297 first (the oldest one). This step minimizes route-flap, since a
1298 newer path won't displace an older one, even if it was the
1299 preferred route based on the additional decision criteria below. */
1300 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1301 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1302 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1303 *reason
= bgp_path_selection_older
;
1306 "%s: %s wins over %s due to oldest external",
1307 pfx_buf
, new_buf
, exist_buf
);
1311 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1312 *reason
= bgp_path_selection_older
;
1315 "%s: %s loses to %s due to oldest external",
1316 pfx_buf
, new_buf
, exist_buf
);
1321 /* 13. Router-ID comparison. */
1322 /* If one of the paths is "stale", the corresponding peer router-id will
1323 * be 0 and would always win over the other path. If originator id is
1324 * used for the comparison, it will decide which path is better.
1326 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1327 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1329 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
1330 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1331 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1333 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
1335 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1336 *reason
= bgp_path_selection_router_id
;
1339 "%s: %s wins over %s due to Router-ID comparison",
1340 pfx_buf
, new_buf
, exist_buf
);
1344 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1345 *reason
= bgp_path_selection_router_id
;
1348 "%s: %s loses to %s due to Router-ID comparison",
1349 pfx_buf
, new_buf
, exist_buf
);
1353 /* 14. Cluster length comparison. */
1354 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1355 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1357 if (new_cluster
< exist_cluster
) {
1358 *reason
= bgp_path_selection_cluster_length
;
1361 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1362 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1367 if (new_cluster
> exist_cluster
) {
1368 *reason
= bgp_path_selection_cluster_length
;
1371 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1372 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1377 /* 15. Neighbor address comparison. */
1378 /* Do this only if neither path is "stale" as stale paths do not have
1379 * valid peer information (as the connection may or may not be up).
1381 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1382 *reason
= bgp_path_selection_stale
;
1385 "%s: %s wins over %s due to latter path being STALE",
1386 pfx_buf
, new_buf
, exist_buf
);
1390 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1391 *reason
= bgp_path_selection_stale
;
1394 "%s: %s loses to %s due to former path being STALE",
1395 pfx_buf
, new_buf
, exist_buf
);
1399 /* locally configured routes to advertise do not have su_remote */
1400 if (new->peer
->su_remote
== NULL
) {
1401 *reason
= bgp_path_selection_local_configured
;
1404 if (exist
->peer
->su_remote
== NULL
) {
1405 *reason
= bgp_path_selection_local_configured
;
1409 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1412 *reason
= bgp_path_selection_neighbor_ip
;
1415 "%s: %s loses to %s due to Neighor IP comparison",
1416 pfx_buf
, new_buf
, exist_buf
);
1421 *reason
= bgp_path_selection_neighbor_ip
;
1424 "%s: %s wins over %s due to Neighor IP comparison",
1425 pfx_buf
, new_buf
, exist_buf
);
1429 *reason
= bgp_path_selection_default
;
1431 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1432 pfx_buf
, new_buf
, exist_buf
);
1438 int bgp_evpn_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
1439 struct bgp_path_info
*exist
, int *paths_eq
)
1441 enum bgp_path_selection_reason reason
;
1442 char pfx_buf
[PREFIX2STR_BUFFER
];
1444 return bgp_path_info_cmp(bgp
, new, exist
, paths_eq
, NULL
, 0, pfx_buf
,
1445 AFI_L2VPN
, SAFI_EVPN
, &reason
);
1448 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1449 * is preferred, or 0 if they are the same (usually will only occur if
1450 * multipath is enabled
1451 * This version is compatible with */
1452 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1453 struct bgp_path_info
*exist
, char *pfx_buf
,
1454 afi_t afi
, safi_t safi
,
1455 enum bgp_path_selection_reason
*reason
)
1459 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1473 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1474 const struct prefix
*p
,
1475 struct attr
*attr
, afi_t afi
,
1478 struct bgp_filter
*filter
;
1479 enum filter_type ret
= FILTER_PERMIT
;
1481 filter
= &peer
->filter
[afi
][safi
];
1483 #define FILTER_EXIST_WARN(F, f, filter) \
1484 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1485 zlog_debug("%s: Could not find configured input %s-list %s!", \
1486 peer->host, #f, F##_IN_NAME(filter));
1488 if (DISTRIBUTE_IN_NAME(filter
)) {
1489 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1491 if (access_list_apply(DISTRIBUTE_IN(filter
), p
)
1498 if (PREFIX_LIST_IN_NAME(filter
)) {
1499 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1501 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
)
1508 if (FILTER_LIST_IN_NAME(filter
)) {
1509 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1511 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1512 == AS_FILTER_DENY
) {
1519 if (frrtrace_enabled(frr_bgp
, input_filter
)) {
1520 char pfxprint
[PREFIX2STR_BUFFER
];
1522 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1523 frrtrace(5, frr_bgp
, input_filter
, peer
, pfxprint
, afi
, safi
,
1524 ret
== FILTER_PERMIT
? "permit" : "deny");
1528 #undef FILTER_EXIST_WARN
1531 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1532 const struct prefix
*p
,
1533 struct attr
*attr
, afi_t afi
,
1536 struct bgp_filter
*filter
;
1537 enum filter_type ret
= FILTER_PERMIT
;
1539 filter
= &peer
->filter
[afi
][safi
];
1541 #define FILTER_EXIST_WARN(F, f, filter) \
1542 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1543 zlog_debug("%s: Could not find configured output %s-list %s!", \
1544 peer->host, #f, F##_OUT_NAME(filter));
1546 if (DISTRIBUTE_OUT_NAME(filter
)) {
1547 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1549 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
)
1556 if (PREFIX_LIST_OUT_NAME(filter
)) {
1557 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1559 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1566 if (FILTER_LIST_OUT_NAME(filter
)) {
1567 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1569 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1570 == AS_FILTER_DENY
) {
1576 if (frrtrace_enabled(frr_bgp
, output_filter
)) {
1577 char pfxprint
[PREFIX2STR_BUFFER
];
1579 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1580 frrtrace(5, frr_bgp
, output_filter
, peer
, pfxprint
, afi
, safi
,
1581 ret
== FILTER_PERMIT
? "permit" : "deny");
1586 #undef FILTER_EXIST_WARN
1589 /* If community attribute includes no_export then return 1. */
1590 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1592 if (bgp_attr_get_community(attr
)) {
1593 /* NO_ADVERTISE check. */
1594 if (community_include(bgp_attr_get_community(attr
),
1595 COMMUNITY_NO_ADVERTISE
))
1598 /* NO_EXPORT check. */
1599 if (peer
->sort
== BGP_PEER_EBGP
&&
1600 community_include(bgp_attr_get_community(attr
),
1601 COMMUNITY_NO_EXPORT
))
1604 /* NO_EXPORT_SUBCONFED check. */
1605 if (peer
->sort
== BGP_PEER_EBGP
1606 || peer
->sort
== BGP_PEER_CONFED
)
1607 if (community_include(bgp_attr_get_community(attr
),
1608 COMMUNITY_NO_EXPORT_SUBCONFED
))
1614 /* Route reflection loop check. */
1615 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1617 struct in_addr cluster_id
;
1618 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1621 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1622 cluster_id
= peer
->bgp
->cluster_id
;
1624 cluster_id
= peer
->bgp
->router_id
;
1626 if (cluster_loop_check(cluster
, cluster_id
))
1632 static bool bgp_otc_filter(struct peer
*peer
, struct attr
*attr
)
1634 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1635 if (peer
->local_role
== ROLE_PROVIDER
||
1636 peer
->local_role
== ROLE_RS_SERVER
)
1638 if (peer
->local_role
== ROLE_PEER
&& attr
->otc
!= peer
->as
)
1642 if (peer
->local_role
== ROLE_CUSTOMER
||
1643 peer
->local_role
== ROLE_PEER
||
1644 peer
->local_role
== ROLE_RS_CLIENT
) {
1645 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1646 attr
->otc
= peer
->as
;
1651 static bool bgp_otc_egress(struct peer
*peer
, struct attr
*attr
)
1653 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1654 if (peer
->local_role
== ROLE_CUSTOMER
||
1655 peer
->local_role
== ROLE_RS_CLIENT
||
1656 peer
->local_role
== ROLE_PEER
)
1660 if (peer
->local_role
== ROLE_PROVIDER
||
1661 peer
->local_role
== ROLE_PEER
||
1662 peer
->local_role
== ROLE_RS_SERVER
) {
1663 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1664 attr
->otc
= peer
->bgp
->as
;
1669 static bool bgp_check_role_applicability(afi_t afi
, safi_t safi
)
1671 return ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_UNICAST
);
1674 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1675 struct attr
*attr
, afi_t afi
, safi_t safi
,
1676 const char *rmap_name
, mpls_label_t
*label
,
1677 uint32_t num_labels
, struct bgp_dest
*dest
)
1679 struct bgp_filter
*filter
;
1680 struct bgp_path_info rmap_path
= { 0 };
1681 struct bgp_path_info_extra extra
= { 0 };
1682 route_map_result_t ret
;
1683 struct route_map
*rmap
= NULL
;
1685 filter
= &peer
->filter
[afi
][safi
];
1687 /* Apply default weight value. */
1688 if (peer
->weight
[afi
][safi
])
1689 attr
->weight
= peer
->weight
[afi
][safi
];
1692 rmap
= route_map_lookup_by_name(rmap_name
);
1697 if (ROUTE_MAP_IN_NAME(filter
)) {
1698 rmap
= ROUTE_MAP_IN(filter
);
1705 /* Route map apply. */
1707 memset(&rmap_path
, 0, sizeof(rmap_path
));
1708 /* Duplicate current value to new structure for modification. */
1709 rmap_path
.peer
= peer
;
1710 rmap_path
.attr
= attr
;
1711 rmap_path
.extra
= &extra
;
1712 rmap_path
.net
= dest
;
1714 extra
.num_labels
= num_labels
;
1715 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1716 memcpy(extra
.label
, label
,
1717 num_labels
* sizeof(mpls_label_t
));
1719 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1721 /* Apply BGP route map to the attribute. */
1722 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1724 peer
->rmap_type
= 0;
1726 if (ret
== RMAP_DENYMATCH
)
1732 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1733 struct attr
*attr
, afi_t afi
, safi_t safi
,
1734 const char *rmap_name
)
1736 struct bgp_path_info rmap_path
;
1737 route_map_result_t ret
;
1738 struct route_map
*rmap
= NULL
;
1742 * So if we get to this point and have no rmap_name
1743 * we want to just show the output as it currently
1749 /* Apply default weight value. */
1750 if (peer
->weight
[afi
][safi
])
1751 attr
->weight
= peer
->weight
[afi
][safi
];
1753 rmap
= route_map_lookup_by_name(rmap_name
);
1756 * If we have a route map name and we do not find
1757 * the routemap that means we have an implicit
1763 memset(&rmap_path
, 0, sizeof(rmap_path
));
1764 /* Route map apply. */
1765 /* Duplicate current value to new structure for modification. */
1766 rmap_path
.peer
= peer
;
1767 rmap_path
.attr
= attr
;
1769 rmap_type
= peer
->rmap_type
;
1770 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1772 /* Apply BGP route map to the attribute. */
1773 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1775 peer
->rmap_type
= rmap_type
;
1777 if (ret
== RMAP_DENYMATCH
)
1779 * caller has multiple error paths with bgp_attr_flush()
1786 /* If this is an EBGP peer with remove-private-AS */
1787 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1788 struct peer
*peer
, struct attr
*attr
)
1790 if (peer
->sort
== BGP_PEER_EBGP
1791 && (peer_af_flag_check(peer
, afi
, safi
,
1792 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1793 || peer_af_flag_check(peer
, afi
, safi
,
1794 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1795 || peer_af_flag_check(peer
, afi
, safi
,
1796 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1797 || peer_af_flag_check(peer
, afi
, safi
,
1798 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1799 // Take action on the entire aspath
1800 if (peer_af_flag_check(peer
, afi
, safi
,
1801 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1802 || peer_af_flag_check(peer
, afi
, safi
,
1803 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1804 if (peer_af_flag_check(
1806 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1807 attr
->aspath
= aspath_replace_private_asns(
1808 attr
->aspath
, bgp
->as
, peer
->as
);
1811 * Even if the aspath consists of just private ASNs we
1812 * need to walk the AS-Path to maintain all instances
1813 * of the peer's ASN to break possible loops.
1816 attr
->aspath
= aspath_remove_private_asns(
1817 attr
->aspath
, peer
->as
);
1820 // 'all' was not specified so the entire aspath must be private
1822 // for us to do anything
1823 else if (aspath_private_as_check(attr
->aspath
)) {
1824 if (peer_af_flag_check(
1826 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1827 attr
->aspath
= aspath_replace_private_asns(
1828 attr
->aspath
, bgp
->as
, peer
->as
);
1831 * Walk the aspath to retain any instances of
1834 attr
->aspath
= aspath_remove_private_asns(
1835 attr
->aspath
, peer
->as
);
1840 /* If this is an EBGP peer with as-override */
1841 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1842 struct peer
*peer
, struct attr
*attr
)
1844 struct aspath
*aspath
;
1846 if (peer
->sort
== BGP_PEER_EBGP
&&
1847 peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1848 if (attr
->aspath
->refcnt
)
1849 aspath
= aspath_dup(attr
->aspath
);
1851 aspath
= attr
->aspath
;
1853 attr
->aspath
= aspath_intern(
1854 aspath_replace_specific_asn(aspath
, peer
->as
, bgp
->as
));
1856 aspath_free(aspath
);
1860 void bgp_attr_add_llgr_community(struct attr
*attr
)
1862 struct community
*old
;
1863 struct community
*new;
1864 struct community
*merge
;
1865 struct community
*llgr
;
1867 old
= bgp_attr_get_community(attr
);
1868 llgr
= community_str2com("llgr-stale");
1873 merge
= community_merge(community_dup(old
), llgr
);
1875 if (old
->refcnt
== 0)
1876 community_free(&old
);
1878 new = community_uniq_sort(merge
);
1879 community_free(&merge
);
1881 new = community_dup(llgr
);
1884 community_free(&llgr
);
1886 bgp_attr_set_community(attr
, new);
1889 void bgp_attr_add_gshut_community(struct attr
*attr
)
1891 struct community
*old
;
1892 struct community
*new;
1893 struct community
*merge
;
1894 struct community
*gshut
;
1896 old
= bgp_attr_get_community(attr
);
1897 gshut
= community_str2com("graceful-shutdown");
1902 merge
= community_merge(community_dup(old
), gshut
);
1904 if (old
->refcnt
== 0)
1905 community_free(&old
);
1907 new = community_uniq_sort(merge
);
1908 community_free(&merge
);
1910 new = community_dup(gshut
);
1913 community_free(&gshut
);
1914 bgp_attr_set_community(attr
, new);
1916 /* When we add the graceful-shutdown community we must also
1917 * lower the local-preference */
1918 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1919 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1923 /* Notify BGP Conditional advertisement scanner process. */
1924 void bgp_notify_conditional_adv_scanner(struct update_subgroup
*subgrp
)
1926 struct peer
*peer
= SUBGRP_PEER(subgrp
);
1927 afi_t afi
= SUBGRP_AFI(subgrp
);
1928 safi_t safi
= SUBGRP_SAFI(subgrp
);
1929 struct bgp_filter
*filter
= &peer
->filter
[afi
][safi
];
1931 if (!ADVERTISE_MAP_NAME(filter
))
1934 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
))
1937 peer
->advmap_table_change
= true;
1941 void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1943 if (family
== AF_INET
) {
1944 attr
->nexthop
.s_addr
= INADDR_ANY
;
1945 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1947 if (family
== AF_INET6
)
1948 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1949 if (family
== AF_EVPN
)
1950 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1953 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
1954 struct update_subgroup
*subgrp
,
1955 const struct prefix
*p
, struct attr
*attr
,
1956 struct attr
*post_attr
)
1958 struct bgp_filter
*filter
;
1961 struct peer
*onlypeer
;
1963 struct attr
*piattr
;
1964 route_map_result_t ret
;
1969 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1970 bool nh_reset
= false;
1973 if (DISABLE_BGP_ANNOUNCE
)
1976 afi
= SUBGRP_AFI(subgrp
);
1977 safi
= SUBGRP_SAFI(subgrp
);
1978 peer
= SUBGRP_PEER(subgrp
);
1980 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1981 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1984 filter
= &peer
->filter
[afi
][safi
];
1985 bgp
= SUBGRP_INST(subgrp
);
1986 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1989 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX_OUT
) &&
1990 peer
->pmax_out
[afi
][safi
] != 0 &&
1991 subgrp
->pscount
>= peer
->pmax_out
[afi
][safi
]) {
1992 if (BGP_DEBUG(update
, UPDATE_OUT
) ||
1993 BGP_DEBUG(update
, UPDATE_PREFIX
)) {
1994 zlog_debug("%s reached maximum prefix to be send (%u)",
1995 peer
->host
, peer
->pmax_out
[afi
][safi
]);
2000 #ifdef ENABLE_BGP_VNC
2001 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
2002 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
2003 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
2006 * direct and direct_ext type routes originate internally even
2007 * though they can have peer pointers that reference other
2010 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
2016 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
2017 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
2018 && (pi
->type
== ZEBRA_ROUTE_BGP
)
2019 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2021 /* Applies to routes leaked vpn->vrf and vrf->vpn */
2026 /* With addpath we may be asked to TX all kinds of paths so make sure
2028 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
2029 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
2030 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
2034 /* If this is not the bestpath then check to see if there is an enabled
2036 * feature that requires us to advertise it */
2037 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2038 if (!bgp_addpath_capable(pi
, peer
, afi
, safi
))
2041 /* Aggregate-address suppress check. */
2042 if (bgp_path_suppressed(pi
) && !UNSUPPRESS_MAP_NAME(filter
))
2046 * If we are doing VRF 2 VRF leaking via the import
2047 * statement, we want to prevent the route going
2048 * off box as that the RT and RD created are localy
2049 * significant and globaly useless.
2051 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
2052 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
2055 /* If it's labeled safi, make sure the route has a valid label. */
2056 if (safi
== SAFI_LABELED_UNICAST
) {
2057 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
2058 if (!bgp_is_valid_label(&label
)) {
2059 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2060 zlog_debug("u%" PRIu64
":s%" PRIu64
2061 " %pFX is filtered - no label (%p)",
2062 subgrp
->update_group
->id
, subgrp
->id
,
2068 /* Do not send back route to sender. */
2069 if (onlypeer
&& from
== onlypeer
) {
2073 /* Do not send the default route in the BGP table if the neighbor is
2074 * configured for default-originate */
2075 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2076 PEER_FLAG_DEFAULT_ORIGINATE
)) {
2077 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
2079 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
2083 /* Transparency check. */
2084 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
2085 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
2090 /* If community is not disabled check the no-export and local. */
2091 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
2092 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2093 zlog_debug("%s: community filter check fail for %pFX",
2098 /* If the attribute has originator-id and it is same as remote
2100 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2101 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
2102 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2104 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2109 /* ORF prefix-list filter check */
2110 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
2111 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
2112 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
2113 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
2114 if (peer
->orf_plist
[afi
][safi
]) {
2115 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
2117 if (bgp_debug_update(NULL
, p
,
2118 subgrp
->update_group
, 0))
2120 "%pBP [Update:SEND] %pFX is filtered via ORF",
2126 /* Output filter check. */
2127 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
2128 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2129 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer
,
2134 /* AS path loop check. */
2135 if (peer
->as_path_loop_detection
&&
2136 aspath_loop_check(piattr
->aspath
, peer
->as
)) {
2137 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2139 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2144 /* If we're a CONFED we need to loop check the CONFED ID too */
2145 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
2146 if (aspath_loop_check_confed(piattr
->aspath
, bgp
->confed_id
)) {
2147 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2149 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2150 peer
, bgp
->confed_id
);
2155 /* Route-Reflect check. */
2156 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2161 /* IBGP reflection check. */
2162 if (reflect
&& !samepeer_safe
) {
2163 /* A route from a Client peer. */
2164 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
2165 PEER_FLAG_REFLECTOR_CLIENT
)) {
2166 /* Reflect to all the Non-Client peers and also to the
2167 Client peers other than the originator. Originator
2169 is already done. So there is noting to do. */
2170 /* no bgp client-to-client reflection check. */
2171 if (CHECK_FLAG(bgp
->flags
,
2172 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
2173 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2174 PEER_FLAG_REFLECTOR_CLIENT
))
2177 /* A route from a Non-client peer. Reflect to all other
2179 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2180 PEER_FLAG_REFLECTOR_CLIENT
))
2185 /* For modify attribute, copy it to temporary structure.
2186 * post_attr comes from BGP conditional advertisements, where
2187 * attributes are already processed by advertise-map route-map,
2188 * and this needs to be saved instead of overwriting from the
2196 /* If local-preference is not set. */
2197 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
2198 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
2199 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2200 attr
->local_pref
= bgp
->default_local_pref
;
2203 /* If originator-id is not set and the route is to be reflected,
2204 set the originator id */
2206 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
2207 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
2208 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
2211 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2213 if (peer
->sort
== BGP_PEER_EBGP
2214 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
2215 if (from
!= bgp
->peer_self
&& !transparent
2216 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2217 PEER_FLAG_MED_UNCHANGED
))
2219 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
2222 /* Since the nexthop attribute can vary per peer, it is not explicitly
2224 * in announce check, only certain flags and length (or number of
2226 * -- for IPv6/MP_REACH) are set here in order to guide the update
2228 * code in setting the nexthop(s) on a per peer basis in
2230 * Typically, the source nexthop in the attribute is preserved but in
2232 * scenarios where we know it will always be overwritten, we reset the
2233 * nexthop to "0" in an attempt to achieve better Update packing. An
2234 * example of this is when a prefix from each of 2 IBGP peers needs to
2236 * announced to an EBGP peer (and they have the same attributes barring
2240 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
2242 #define NEXTHOP_IS_V6 \
2243 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2244 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2245 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2246 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2248 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2250 * the peer (group) is configured to receive link-local nexthop
2252 * and it is available in the prefix OR we're not reflecting the route,
2253 * link-local nexthop address is valid and
2254 * the peer (group) to whom we're going to announce is on a shared
2256 * and this is either a self-originated route or the peer is EBGP.
2257 * By checking if nexthop LL address is valid we are sure that
2258 * we do not announce LL address as `::`.
2260 if (NEXTHOP_IS_V6
) {
2261 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2262 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2263 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
2264 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
2265 || (!reflect
&& !transparent
2266 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
2267 && peer
->shared_network
2268 && (from
== bgp
->peer_self
2269 || peer
->sort
== BGP_PEER_EBGP
))) {
2270 if (safi
== SAFI_MPLS_VPN
)
2271 attr
->mp_nexthop_len
=
2272 BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
;
2274 attr
->mp_nexthop_len
=
2275 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2278 /* Clear off link-local nexthop in source, whenever it is not
2280 * ensure more prefixes share the same attribute for
2283 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2284 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
2285 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
2288 if (bgp_check_role_applicability(afi
, safi
) &&
2289 bgp_otc_egress(peer
, attr
))
2292 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
2293 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
2295 if (filter
->advmap
.update_type
== UPDATE_TYPE_WITHDRAW
&&
2296 filter
->advmap
.aname
&&
2297 route_map_lookup_by_name(filter
->advmap
.aname
)) {
2298 struct bgp_path_info rmap_path
= {0};
2299 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2300 struct attr dummy_attr
= *attr
;
2302 /* Fill temp path_info */
2303 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2304 pi
, peer
, &dummy_attr
);
2306 struct route_map
*amap
=
2307 route_map_lookup_by_name(filter
->advmap
.aname
);
2309 ret
= route_map_apply(amap
, p
, &rmap_path
);
2311 bgp_attr_flush(&dummy_attr
);
2314 * The conditional advertisement mode is Withdraw and this
2315 * prefix is a conditional prefix. Don't advertise it
2317 if (ret
== RMAP_PERMITMATCH
)
2321 /* Route map & unsuppress-map apply. */
2323 (ROUTE_MAP_OUT_NAME(filter
) || bgp_path_suppressed(pi
))) {
2324 struct bgp_path_info rmap_path
= {0};
2325 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2326 struct attr dummy_attr
= {0};
2328 /* Fill temp path_info */
2329 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2332 /* don't confuse inbound and outbound setting */
2333 RESET_FLAG(attr
->rmap_change_flags
);
2336 * The route reflector is not allowed to modify the attributes
2337 * of the reflected IBGP routes unless explicitly allowed.
2339 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2340 && !CHECK_FLAG(bgp
->flags
,
2341 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
2343 rmap_path
.attr
= &dummy_attr
;
2346 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
2348 if (bgp_path_suppressed(pi
))
2349 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
2352 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
2355 bgp_attr_flush(&dummy_attr
);
2356 peer
->rmap_type
= 0;
2358 if (ret
== RMAP_DENYMATCH
) {
2359 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2361 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2362 peer
, p
, ROUTE_MAP_OUT_NAME(filter
));
2363 bgp_attr_flush(rmap_path
.attr
);
2368 /* RFC 8212 to prevent route leaks.
2369 * This specification intends to improve this situation by requiring the
2370 * explicit configuration of both BGP Import and Export Policies for any
2371 * External BGP (EBGP) session such as customers, peers, or
2372 * confederation boundaries for all enabled address families. Through
2373 * codification of the aforementioned requirement, operators will
2374 * benefit from consistent behavior across different BGP
2377 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2378 if (!bgp_outbound_policy_exists(peer
, filter
)) {
2379 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
2380 NULL
) > FIFTEENMINUTE2USEC
||
2381 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
2383 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2384 monotime(&bgp
->ebgprequirespolicywarning
);
2389 /* draft-ietf-idr-deprecate-as-set-confed-set
2390 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2391 * Eventually, This document (if approved) updates RFC 4271
2392 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2393 * and obsoletes RFC 6472.
2395 if (peer
->bgp
->reject_as_sets
)
2396 if (aspath_check_as_sets(attr
->aspath
))
2399 /* If neighbor soo is configured, then check if the route has
2400 * SoO extended community and validate against the configured
2401 * one. If they match, do not announce, to prevent routing
2404 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) &&
2405 peer
->soo
[afi
][safi
]) {
2406 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
2407 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
2409 if ((ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS
,
2410 ECOMMUNITY_SITE_ORIGIN
) ||
2411 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS4
,
2412 ECOMMUNITY_SITE_ORIGIN
) ||
2413 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_IP
,
2414 ECOMMUNITY_SITE_ORIGIN
)) &&
2415 ecommunity_include(ecomm
, ecomm_soo
)) {
2416 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2418 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2419 peer
, p
, ecommunity_str(ecomm_soo
));
2424 /* Codification of AS 0 Processing */
2425 if (aspath_check_as_zero(attr
->aspath
))
2428 if (bgp_in_graceful_shutdown(bgp
)) {
2429 if (peer
->sort
== BGP_PEER_IBGP
2430 || peer
->sort
== BGP_PEER_CONFED
) {
2431 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2432 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2434 bgp_attr_add_gshut_community(attr
);
2438 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2439 * Capability" to a neighbor MUST perform the following upon receiving
2440 * a route from that neighbor with the "LLGR_STALE" community, or upon
2441 * attaching the "LLGR_STALE" community itself per Section 4.2:
2443 * The route SHOULD NOT be advertised to any neighbor from which the
2444 * Long-lived Graceful Restart Capability has not been received.
2446 if (bgp_attr_get_community(attr
) &&
2447 community_include(bgp_attr_get_community(attr
),
2448 COMMUNITY_LLGR_STALE
) &&
2449 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_RCV
) &&
2450 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_ADV
))
2453 /* After route-map has been applied, we check to see if the nexthop to
2454 * be carried in the attribute (that is used for the announcement) can
2455 * be cleared off or not. We do this in all cases where we would be
2456 * setting the nexthop to "ourselves". For IPv6, we only need to
2458 * the global nexthop here; the link-local nexthop would have been
2460 * already, and if not, it is required by the update formation code.
2461 * Also see earlier comments in this function.
2464 * If route-map has performed some operation on the nexthop or the peer
2465 * configuration says to pass it unchanged, we cannot reset the nexthop
2466 * here, so only attempt to do it if these aren't true. Note that the
2467 * route-map handler itself might have cleared the nexthop, if for
2469 * it is configured as 'peer-address'.
2471 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2472 piattr
->rmap_change_flags
)
2474 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2475 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2476 /* We can reset the nexthop, if setting (or forcing) it to
2478 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2479 PEER_FLAG_NEXTHOP_SELF
)
2480 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2481 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2483 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2484 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2485 subgroup_announce_reset_nhop(
2486 (peer_cap_enhe(peer
, afi
, safi
)
2492 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2493 /* Can also reset the nexthop if announcing to EBGP, but
2495 * no peer in the subgroup is on a shared subnet.
2496 * Note: 3rd party nexthop currently implemented for
2499 if ((p
->family
== AF_INET
) &&
2500 (!bgp_subgrp_multiaccess_check_v4(
2503 subgroup_announce_reset_nhop(
2504 (peer_cap_enhe(peer
, afi
, safi
)
2511 if ((p
->family
== AF_INET6
) &&
2512 (!bgp_subgrp_multiaccess_check_v6(
2513 piattr
->mp_nexthop_global
,
2515 subgroup_announce_reset_nhop(
2516 (peer_cap_enhe(peer
, afi
, safi
)
2525 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2527 * This flag is used for leaked vpn-vrf routes
2529 int family
= p
->family
;
2531 if (peer_cap_enhe(peer
, afi
, safi
))
2534 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2536 "%s: %pFX BGP_PATH_ANNC_NH_SELF, family=%s",
2537 __func__
, p
, family2str(family
));
2538 subgroup_announce_reset_nhop(family
, attr
);
2543 /* If IPv6/MP and nexthop does not have any override and happens
2545 * be a link-local address, reset it so that we don't pass along
2547 * source's link-local IPv6 address to recipients who may not be
2549 * the same interface.
2551 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2552 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2553 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2558 /* If this is an iBGP, send Origin Validation State (OVS)
2559 * extended community (rfc8097).
2561 if (peer
->sort
== BGP_PEER_IBGP
) {
2562 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
2564 rpki_state
= hook_call(bgp_rpki_prefix_status
, peer
, attr
, p
);
2566 if (rpki_state
!= RPKI_NOT_BEING_USED
)
2567 bgp_attr_set_ecommunity(
2568 attr
, ecommunity_add_origin_validation_state(
2570 bgp_attr_get_ecommunity(attr
)));
2574 * When the next hop is set to ourselves, if all multipaths have
2575 * link-bandwidth announce the cumulative bandwidth as that makes
2576 * the most sense. However, don't modify if the link-bandwidth has
2577 * been explicitly set by user policy.
2580 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2581 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2582 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2583 bgp_attr_set_ecommunity(
2585 ecommunity_replace_linkbw(
2586 bgp
->as
, bgp_attr_get_ecommunity(attr
), cum_bw
,
2589 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
)));
2594 static void bgp_route_select_timer_expire(struct thread
*thread
)
2596 struct afi_safi_info
*info
;
2601 info
= THREAD_ARG(thread
);
2606 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2607 XFREE(MTYPE_TMP
, info
);
2609 /* Best path selection */
2610 bgp_best_path_select_defer(bgp
, afi
, safi
);
2613 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2614 struct bgp_maxpaths_cfg
*mpath_cfg
,
2615 struct bgp_path_info_pair
*result
, afi_t afi
,
2618 struct bgp_path_info
*new_select
;
2619 struct bgp_path_info
*old_select
;
2620 struct bgp_path_info
*pi
;
2621 struct bgp_path_info
*pi1
;
2622 struct bgp_path_info
*pi2
;
2623 struct bgp_path_info
*nextpi
= NULL
;
2624 int paths_eq
, do_mpath
, debug
;
2625 struct list mp_list
;
2626 char pfx_buf
[PREFIX2STR_BUFFER
];
2627 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2629 bgp_mp_list_init(&mp_list
);
2631 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2633 debug
= bgp_debug_bestpath(dest
);
2636 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2638 dest
->reason
= bgp_path_selection_none
;
2639 /* bgp deterministic-med */
2641 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2643 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2644 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2646 bgp_path_info_unset_flag(dest
, pi1
,
2647 BGP_PATH_DMED_SELECTED
);
2649 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2651 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2653 if (BGP_PATH_HOLDDOWN(pi1
))
2655 if (pi1
->peer
!= bgp
->peer_self
&&
2656 !CHECK_FLAG(pi1
->peer
->sflags
,
2657 PEER_STATUS_NSF_WAIT
)) {
2658 if (!peer_established(pi1
->peer
))
2664 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2665 if (CHECK_FLAG(pi2
->flags
,
2666 BGP_PATH_DMED_CHECK
))
2668 if (BGP_PATH_HOLDDOWN(pi2
))
2670 if (pi2
->peer
!= bgp
->peer_self
2673 PEER_STATUS_NSF_WAIT
))
2674 if (pi2
->peer
->status
2678 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2680 && !aspath_cmp_left_confed(
2685 if (bgp_path_info_cmp(
2686 bgp
, pi2
, new_select
,
2687 &paths_eq
, mpath_cfg
, debug
,
2690 bgp_path_info_unset_flag(
2692 BGP_PATH_DMED_SELECTED
);
2696 bgp_path_info_set_flag(
2697 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2700 bgp_path_info_set_flag(dest
, new_select
,
2701 BGP_PATH_DMED_CHECK
);
2702 bgp_path_info_set_flag(dest
, new_select
,
2703 BGP_PATH_DMED_SELECTED
);
2706 bgp_path_info_path_with_addpath_rx_str(
2707 new_select
, path_buf
, sizeof(path_buf
));
2709 "%pBD(%s): %s is the bestpath from AS %u",
2710 dest
, bgp
->name_pretty
, path_buf
,
2711 aspath_get_first_as(
2712 new_select
->attr
->aspath
));
2717 /* Check old selected route and new selected route. */
2720 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2721 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2722 enum bgp_path_selection_reason reason
;
2724 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2727 if (BGP_PATH_HOLDDOWN(pi
)) {
2728 /* reap REMOVED routes, if needs be
2729 * selected route must stay for a while longer though
2731 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2732 && (pi
!= old_select
))
2733 bgp_path_info_reap(dest
, pi
);
2736 zlog_debug("%s: pi %p in holddown", __func__
,
2742 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2743 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2744 if (!peer_established(pi
->peer
)) {
2748 "%s: pi %p non self peer %s not estab state",
2749 __func__
, pi
, pi
->peer
->host
);
2754 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2755 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2756 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2758 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2762 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2764 reason
= dest
->reason
;
2765 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2766 debug
, pfx_buf
, afi
, safi
,
2768 if (new_select
== NULL
&&
2769 reason
!= bgp_path_selection_none
)
2770 dest
->reason
= reason
;
2775 /* Now that we know which path is the bestpath see if any of the other
2777 * qualify as multipaths
2781 bgp_path_info_path_with_addpath_rx_str(
2782 new_select
, path_buf
, sizeof(path_buf
));
2784 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2786 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2787 dest
, bgp
->name_pretty
, path_buf
,
2788 old_select
? old_select
->peer
->host
: "NONE");
2791 if (do_mpath
&& new_select
) {
2792 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2793 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2796 bgp_path_info_path_with_addpath_rx_str(
2797 pi
, path_buf
, sizeof(path_buf
));
2799 if (pi
== new_select
) {
2802 "%pBD(%s): %s is the bestpath, add to the multipath list",
2803 dest
, bgp
->name_pretty
,
2805 bgp_mp_list_add(&mp_list
, pi
);
2809 if (BGP_PATH_HOLDDOWN(pi
))
2812 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2813 && !CHECK_FLAG(pi
->peer
->sflags
,
2814 PEER_STATUS_NSF_WAIT
))
2815 if (!peer_established(pi
->peer
))
2818 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2821 "%pBD: %s has the same nexthop as the bestpath, skip it",
2826 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2827 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2833 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2835 bgp_mp_list_add(&mp_list
, pi
);
2840 bgp_path_info_mpath_update(bgp
, dest
, new_select
, old_select
, &mp_list
,
2842 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2843 bgp_mp_list_clear(&mp_list
);
2845 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2847 result
->old
= old_select
;
2848 result
->new = new_select
;
2854 * A new route/change in bestpath of an existing route. Evaluate the path
2855 * for advertisement to the subgroup.
2857 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2858 struct bgp_path_info
*selected
,
2859 struct bgp_dest
*dest
,
2860 uint32_t addpath_tx_id
)
2862 const struct prefix
*p
;
2863 struct peer
*onlypeer
;
2870 p
= bgp_dest_get_prefix(dest
);
2871 afi
= SUBGRP_AFI(subgrp
);
2872 safi
= SUBGRP_SAFI(subgrp
);
2873 bgp
= SUBGRP_INST(subgrp
);
2874 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2877 if (BGP_DEBUG(update
, UPDATE_OUT
))
2878 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2880 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2881 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2882 PEER_STATUS_ORF_WAIT_REFRESH
))
2885 memset(&attr
, 0, sizeof(attr
));
2886 /* It's initialized in bgp_announce_check() */
2888 /* Announcement to the subgroup. If the route is filtered withdraw it.
2889 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2890 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2893 advertise
= bgp_check_advertise(bgp
, dest
);
2896 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2898 /* Route is selected, if the route is already installed
2899 * in FIB, then it is advertised
2902 if (!bgp_check_withdrawal(bgp
, dest
))
2903 bgp_adj_out_set_subgroup(
2904 dest
, subgrp
, &attr
, selected
);
2906 bgp_adj_out_unset_subgroup(
2907 dest
, subgrp
, 1, addpath_tx_id
);
2910 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2914 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2916 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2921 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2922 * This is called at the end of route processing.
2924 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2926 struct bgp_path_info
*pi
;
2928 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2929 if (BGP_PATH_HOLDDOWN(pi
))
2931 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2932 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2937 * Has the route changed from the RIB's perspective? This is invoked only
2938 * if the route selection returns the same best route as earlier - to
2939 * determine if we need to update zebra or not.
2941 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2943 struct bgp_path_info
*mpinfo
;
2945 /* If this is multipath, check all selected paths for any nexthop
2946 * change or attribute change. Some attribute changes (e.g., community)
2947 * aren't of relevance to the RIB, but we'll update zebra to ensure
2948 * we handle the case of BGP nexthop change. This is the behavior
2949 * when the best path has an attribute change anyway.
2951 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2952 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2953 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2957 * If this is multipath, check all selected paths for any nexthop change
2959 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2960 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2961 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2962 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2966 /* Nothing has changed from the RIB's perspective. */
2970 struct bgp_process_queue
{
2972 STAILQ_HEAD(, bgp_dest
) pqueue
;
2973 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2975 unsigned int queued
;
2978 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
2979 safi_t safi
, struct bgp_dest
*dest
,
2980 struct bgp_path_info
*new_select
,
2981 struct bgp_path_info
*old_select
)
2983 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2985 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
2988 if (advertise_type5_routes(bgp
, afi
) && new_select
2989 && is_route_injectable_into_evpn(new_select
)) {
2991 /* apply the route-map */
2992 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2993 route_map_result_t ret
;
2994 struct bgp_path_info rmap_path
;
2995 struct bgp_path_info_extra rmap_path_extra
;
2996 struct attr dummy_attr
;
2998 dummy_attr
= *new_select
->attr
;
3000 /* Fill temp path_info */
3001 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
3002 new_select
, new_select
->peer
,
3005 RESET_FLAG(dummy_attr
.rmap_change_flags
);
3007 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
3010 if (ret
== RMAP_DENYMATCH
) {
3011 bgp_attr_flush(&dummy_attr
);
3012 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
3015 bgp_evpn_advertise_type5_route(
3016 bgp
, p
, &dummy_attr
, afi
, safi
);
3018 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
3021 } else if (advertise_type5_routes(bgp
, afi
) && old_select
3022 && is_route_injectable_into_evpn(old_select
))
3023 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
3027 * Utility to determine whether a particular path_info should use
3028 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3029 * in a path where we basically _know_ this is a BGP-LU route.
3031 static bool bgp_lu_need_imp_null(const struct bgp_path_info
*new_select
)
3033 /* Certain types get imp null; so do paths where the nexthop is
3036 if (new_select
->sub_type
== BGP_ROUTE_STATIC
3037 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3038 || new_select
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
3040 else if (new_select
->extra
== NULL
||
3041 !bgp_is_valid_label(&new_select
->extra
->label
[0]))
3042 /* TODO -- should be configurable? */
3049 * old_select = The old best path
3050 * new_select = the new best path
3052 * if (!old_select && new_select)
3053 * We are sending new information on.
3055 * if (old_select && new_select) {
3056 * if (new_select != old_select)
3057 * We have a new best path send a change
3059 * We've received a update with new attributes that needs
3063 * if (old_select && !new_select)
3064 * We have no eligible route that we can announce or the rn
3067 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
3068 afi_t afi
, safi_t safi
)
3070 struct bgp_path_info
*new_select
;
3071 struct bgp_path_info
*old_select
;
3072 struct bgp_path_info_pair old_and_new
;
3075 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
3077 debug
= bgp_debug_bestpath(dest
);
3080 "%s: bgp delete in progress, ignoring event, p=%pBD",
3084 /* Is it end of initial update? (after startup) */
3086 frr_timestamp(3, bgp
->update_delay_zebra_resume_time
,
3087 sizeof(bgp
->update_delay_zebra_resume_time
));
3089 bgp
->main_zebra_update_hold
= 0;
3090 FOREACH_AFI_SAFI (afi
, safi
) {
3091 if (bgp_fibupd_safi(safi
))
3092 bgp_zebra_announce_table(bgp
, afi
, safi
);
3094 bgp
->main_peers_update_hold
= 0;
3096 bgp_start_routeadv(bgp
);
3100 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3102 debug
= bgp_debug_bestpath(dest
);
3104 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__
,
3105 dest
, bgp
->name_pretty
, afi2str(afi
),
3108 /* The best path calculation for the route is deferred if
3109 * BGP_NODE_SELECT_DEFER is set
3111 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3112 if (BGP_DEBUG(update
, UPDATE_OUT
))
3113 zlog_debug("SELECT_DEFER flag set for route %p", dest
);
3117 /* Best path selection. */
3118 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
3120 old_select
= old_and_new
.old
;
3121 new_select
= old_and_new
.new;
3123 /* Do we need to allocate or free labels?
3124 * Right now, since we only deal with per-prefix labels, it is not
3125 * necessary to do this upon changes to best path. Exceptions:
3126 * - label index has changed -> recalculate resulting label
3127 * - path_info sub_type changed -> switch to/from implicit-null
3128 * - no valid label (due to removed static label binding) -> get new one
3130 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
3133 || bgp_label_index_differs(new_select
, old_select
)
3134 || new_select
->sub_type
!= old_select
->sub_type
3135 || !bgp_is_valid_label(&dest
->local_label
)) {
3136 /* Enforced penultimate hop popping:
3137 * implicit-null for local routes, aggregate
3138 * and redistributed routes
3140 if (bgp_lu_need_imp_null(new_select
)) {
3143 BGP_NODE_REGISTERED_FOR_LABEL
)
3146 BGP_NODE_LABEL_REQUESTED
))
3147 bgp_unregister_for_label(dest
);
3148 dest
->local_label
= mpls_lse_encode(
3149 MPLS_LABEL_IMPLICIT_NULL
, 0, 0,
3151 bgp_set_valid_label(&dest
->local_label
);
3153 bgp_register_for_label(dest
,
3156 } else if (CHECK_FLAG(dest
->flags
,
3157 BGP_NODE_REGISTERED_FOR_LABEL
)
3158 || CHECK_FLAG(dest
->flags
,
3159 BGP_NODE_LABEL_REQUESTED
)) {
3160 bgp_unregister_for_label(dest
);
3162 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
3163 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
3164 bgp_unregister_for_label(dest
);
3169 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3170 __func__
, dest
, bgp
->name_pretty
, afi2str(afi
),
3171 safi2str(safi
), old_select
, new_select
);
3173 /* If best route remains the same and this is not due to user-initiated
3174 * clear, see exactly what needs to be done.
3176 if (old_select
&& old_select
== new_select
3177 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
3178 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3179 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
3180 if (bgp_zebra_has_route_changed(old_select
)) {
3181 #ifdef ENABLE_BGP_VNC
3182 vnc_import_bgp_add_route(bgp
, p
, old_select
);
3183 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
3185 if (bgp_fibupd_safi(safi
)
3186 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3188 if (BGP_SUPPRESS_FIB_ENABLED(bgp
)
3189 && new_select
->sub_type
== BGP_ROUTE_NORMAL
)
3190 SET_FLAG(dest
->flags
,
3191 BGP_NODE_FIB_INSTALL_PENDING
);
3193 if (new_select
->type
== ZEBRA_ROUTE_BGP
3194 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3195 || new_select
->sub_type
3196 == BGP_ROUTE_IMPORTED
))
3198 bgp_zebra_announce(dest
, p
, old_select
,
3203 /* If there is a change of interest to peers, reannounce the
3205 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3206 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3207 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
3208 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3210 /* unicast routes must also be annouced to
3211 * labeled-unicast update-groups */
3212 if (safi
== SAFI_UNICAST
)
3213 group_announce_route(bgp
, afi
,
3214 SAFI_LABELED_UNICAST
, dest
,
3217 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
3218 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
3221 /* advertise/withdraw type-5 routes */
3222 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3223 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
3224 bgp_process_evpn_route_injection(
3225 bgp
, afi
, safi
, dest
, old_select
, old_select
);
3227 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3228 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3229 bgp_zebra_clear_route_change_flags(dest
);
3230 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3234 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3236 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
3238 /* bestpath has changed; bump version */
3239 if (old_select
|| new_select
) {
3240 bgp_bump_version(dest
);
3242 if (!bgp
->t_rmap_def_originate_eval
) {
3246 update_group_refresh_default_originate_route_map
,
3247 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
3248 &bgp
->t_rmap_def_originate_eval
);
3253 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
3256 zlog_debug("%s: setting SELECTED flag", __func__
);
3257 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
3258 bgp_path_info_unset_flag(dest
, new_select
,
3259 BGP_PATH_ATTR_CHANGED
);
3260 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3261 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3264 #ifdef ENABLE_BGP_VNC
3265 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3266 if (old_select
!= new_select
) {
3268 vnc_import_bgp_exterior_del_route(bgp
, p
,
3270 vnc_import_bgp_del_route(bgp
, p
, old_select
);
3273 vnc_import_bgp_exterior_add_route(bgp
, p
,
3275 vnc_import_bgp_add_route(bgp
, p
, new_select
);
3281 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3283 /* unicast routes must also be annouced to labeled-unicast update-groups
3285 if (safi
== SAFI_UNICAST
)
3286 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
3290 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
3291 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3293 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
3294 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3295 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3296 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
3298 if (BGP_SUPPRESS_FIB_ENABLED(bgp
))
3299 SET_FLAG(dest
->flags
,
3300 BGP_NODE_FIB_INSTALL_PENDING
);
3302 /* if this is an evpn imported type-5 prefix,
3303 * we need to withdraw the route first to clear
3304 * the nh neigh and the RMAC entry.
3307 is_route_parent_evpn(old_select
))
3308 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3310 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
3312 /* Withdraw the route from the kernel. */
3313 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
3314 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
3315 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
3316 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
3318 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3322 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
3325 /* Clear any route change flags. */
3326 bgp_zebra_clear_route_change_flags(dest
);
3328 /* Reap old select bgp_path_info, if it has been removed */
3329 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
3330 bgp_path_info_reap(dest
, old_select
);
3332 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3336 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3337 void bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
3339 struct bgp_dest
*dest
;
3341 struct afi_safi_info
*thread_info
;
3343 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
3344 struct thread
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
3346 thread_info
= THREAD_ARG(t
);
3347 XFREE(MTYPE_TMP
, thread_info
);
3348 THREAD_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
3351 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
3352 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
3353 get_afi_safi_str(afi
, safi
, false),
3354 bgp
->gr_info
[afi
][safi
].gr_deferred
);
3357 /* Process the route list */
3358 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
3359 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0 &&
3360 cnt
< BGP_MAX_BEST_ROUTE_SELECT
;
3361 dest
= bgp_route_next(dest
)) {
3362 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
3365 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3366 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3367 bgp_process_main_one(bgp
, dest
, afi
, safi
);
3370 /* If iteration stopped before the entire table was traversed then the
3371 * node needs to be unlocked.
3374 bgp_dest_unlock_node(dest
);
3378 /* Send EOR message when all routes are processed */
3379 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
3380 bgp_send_delayed_eor(bgp
);
3381 /* Send route processing complete message to RIB */
3382 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
3383 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
3387 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3389 thread_info
->afi
= afi
;
3390 thread_info
->safi
= safi
;
3391 thread_info
->bgp
= bgp
;
3393 /* If there are more routes to be processed, start the
3396 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3397 BGP_ROUTE_SELECT_DELAY
,
3398 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3401 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3403 struct bgp_process_queue
*pqnode
= data
;
3404 struct bgp
*bgp
= pqnode
->bgp
;
3405 struct bgp_table
*table
;
3406 struct bgp_dest
*dest
;
3409 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3410 bgp_process_main_one(bgp
, NULL
, 0, 0);
3411 /* should always have dedicated wq call */
3412 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3416 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3417 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3418 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3419 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3420 table
= bgp_dest_table(dest
);
3421 /* note, new DESTs may be added as part of processing */
3422 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3424 bgp_dest_unlock_node(dest
);
3425 bgp_table_unlock(table
);
3431 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3433 struct bgp_process_queue
*pqnode
= data
;
3435 bgp_unlock(pqnode
->bgp
);
3437 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3440 void bgp_process_queue_init(struct bgp
*bgp
)
3442 if (!bgp
->process_queue
) {
3445 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3446 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3449 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3450 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3451 bgp
->process_queue
->spec
.max_retries
= 0;
3452 bgp
->process_queue
->spec
.hold
= 50;
3453 /* Use a higher yield value of 50ms for main queue processing */
3454 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3457 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3459 struct bgp_process_queue
*pqnode
;
3461 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3462 sizeof(struct bgp_process_queue
));
3464 /* unlocked in bgp_processq_del */
3465 pqnode
->bgp
= bgp_lock(bgp
);
3466 STAILQ_INIT(&pqnode
->pqueue
);
3471 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3473 #define ARBITRARY_PROCESS_QLEN 10000
3474 struct work_queue
*wq
= bgp
->process_queue
;
3475 struct bgp_process_queue
*pqnode
;
3476 int pqnode_reuse
= 0;
3478 /* already scheduled for processing? */
3479 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3482 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3485 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3486 if (BGP_DEBUG(update
, UPDATE_OUT
))
3487 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3492 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
)) {
3493 if (BGP_DEBUG(update
, UPDATE_OUT
))
3495 "Soft reconfigure table in progress for route %p",
3503 /* Add route nodes to an existing work queue item until reaching the
3504 limit only if is from the same BGP view and it's not an EOIU marker
3506 if (work_queue_item_count(wq
)) {
3507 struct work_queue_item
*item
= work_queue_last_item(wq
);
3508 pqnode
= item
->data
;
3510 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3511 || pqnode
->bgp
!= bgp
3512 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3513 pqnode
= bgp_processq_alloc(bgp
);
3517 pqnode
= bgp_processq_alloc(bgp
);
3518 /* all unlocked in bgp_process_wq */
3519 bgp_table_lock(bgp_dest_table(dest
));
3521 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3522 bgp_dest_lock_node(dest
);
3524 /* can't be enqueued twice */
3525 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3526 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3530 work_queue_add(wq
, pqnode
);
3535 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3537 struct bgp_process_queue
*pqnode
;
3539 if (bgp
->process_queue
== NULL
)
3542 pqnode
= bgp_processq_alloc(bgp
);
3544 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3545 work_queue_add(bgp
->process_queue
, pqnode
);
3548 static void bgp_maximum_prefix_restart_timer(struct thread
*thread
)
3552 peer
= THREAD_ARG(thread
);
3553 peer
->t_pmax_restart
= NULL
;
3555 if (bgp_debug_neighbor_events(peer
))
3557 "%s Maximum-prefix restart timer expired, restore peering",
3560 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3561 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3564 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3568 bool filtered
= false;
3569 struct bgp_dest
*dest
;
3570 struct bgp_adj_in
*ain
;
3571 struct attr attr
= {};
3572 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3574 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3575 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3576 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3580 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3584 if (bgp_input_modifier(
3585 peer
, rn_p
, &attr
, afi
, safi
,
3586 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3594 bgp_attr_flush(&attr
);
3601 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3605 iana_safi_t pkt_safi
;
3606 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3607 PEER_FLAG_MAX_PREFIX_FORCE
))
3608 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3609 + peer
->pcount
[afi
][safi
]
3610 : peer
->pcount
[afi
][safi
];
3612 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3615 if (pcount
> peer
->pmax
[afi
][safi
]) {
3616 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3617 PEER_STATUS_PREFIX_LIMIT
)
3622 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3623 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3624 peer
->pmax
[afi
][safi
]);
3625 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3627 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3628 PEER_FLAG_MAX_PREFIX_WARNING
))
3631 /* Convert AFI, SAFI to values for packet. */
3632 pkt_afi
= afi_int2iana(afi
);
3633 pkt_safi
= safi_int2iana(safi
);
3637 ndata
[0] = (pkt_afi
>> 8);
3639 ndata
[2] = pkt_safi
;
3640 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3641 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3642 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3643 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3645 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3646 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3647 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3651 /* Dynamic peers will just close their connection. */
3652 if (peer_dynamic_neighbor(peer
))
3655 /* restart timer start */
3656 if (peer
->pmax_restart
[afi
][safi
]) {
3657 peer
->v_pmax_restart
=
3658 peer
->pmax_restart
[afi
][safi
] * 60;
3660 if (bgp_debug_neighbor_events(peer
))
3662 "%pBP Maximum-prefix restart timer started for %d secs",
3663 peer
, peer
->v_pmax_restart
);
3665 BGP_TIMER_ON(peer
->t_pmax_restart
,
3666 bgp_maximum_prefix_restart_timer
,
3667 peer
->v_pmax_restart
);
3672 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3673 PEER_STATUS_PREFIX_LIMIT
);
3676 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3677 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3678 PEER_STATUS_PREFIX_THRESHOLD
)
3683 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3684 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3685 peer
->pmax
[afi
][safi
]);
3686 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3687 PEER_STATUS_PREFIX_THRESHOLD
);
3689 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3690 PEER_STATUS_PREFIX_THRESHOLD
);
3694 /* Unconditionally remove the route from the RIB, without taking
3695 * damping into consideration (eg, because the session went down)
3697 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3698 struct peer
*peer
, afi_t afi
, safi_t safi
)
3701 struct bgp
*bgp
= NULL
;
3702 bool delete_route
= false;
3704 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3707 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3708 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3710 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3713 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3714 delete_route
= true;
3715 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3716 delete_route
= true;
3718 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3719 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3720 bgp
= pi
->peer
->bgp
;
3721 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3726 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3727 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3730 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3731 struct peer
*peer
, afi_t afi
, safi_t safi
,
3732 struct prefix_rd
*prd
)
3734 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3736 /* apply dampening, if result is suppressed, we'll be retaining
3737 * the bgp_path_info in the RIB for historical reference.
3739 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3740 && peer
->sort
== BGP_PEER_EBGP
)
3741 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3742 == BGP_DAMP_SUPPRESSED
) {
3743 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3748 #ifdef ENABLE_BGP_VNC
3749 if (safi
== SAFI_MPLS_VPN
) {
3750 struct bgp_dest
*pdest
= NULL
;
3751 struct bgp_table
*table
= NULL
;
3753 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3754 (struct prefix
*)prd
);
3755 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3756 table
= bgp_dest_get_bgp_table_info(pdest
);
3758 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3759 peer
->bgp
, prd
, table
, p
, pi
);
3761 bgp_dest_unlock_node(pdest
);
3763 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3764 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3766 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3767 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3772 /* If this is an EVPN route, process for un-import. */
3773 if (safi
== SAFI_EVPN
)
3774 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3776 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3779 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3780 struct peer
*peer
, struct attr
*attr
,
3781 struct bgp_dest
*dest
)
3783 struct bgp_path_info
*new;
3785 /* Make new BGP info. */
3786 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3788 new->instance
= instance
;
3789 new->sub_type
= sub_type
;
3792 new->uptime
= monotime(NULL
);
3797 /* Check if received nexthop is valid or not. */
3798 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3799 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3800 struct bgp_dest
*dest
)
3803 bool is_bgp_static_route
=
3804 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3808 * Only validated for unicast and multicast currently.
3809 * Also valid for EVPN where the nexthop is an IP address.
3810 * If we are a bgp static route being checked then there is
3811 * no need to check to see if the nexthop is martian as
3812 * that it should be ok.
3814 if (is_bgp_static_route
||
3815 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3818 /* If NEXT_HOP is present, validate it. */
3819 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3820 if (attr
->nexthop
.s_addr
== INADDR_ANY
||
3821 !ipv4_unicast_valid(&attr
->nexthop
) ||
3822 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3826 /* If MP_NEXTHOP is present, validate it. */
3827 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3828 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3829 * it is not an IPv6 link-local address.
3831 * If we receive an UPDATE with nexthop length set to 32 bytes
3832 * we shouldn't discard an UPDATE if it's set to (::).
3833 * The link-local (2st) is validated along the code path later.
3835 if (attr
->mp_nexthop_len
) {
3836 switch (attr
->mp_nexthop_len
) {
3837 case BGP_ATTR_NHLEN_IPV4
:
3838 case BGP_ATTR_NHLEN_VPNV4
:
3839 ret
= (attr
->mp_nexthop_global_in
.s_addr
==
3841 !ipv4_unicast_valid(
3842 &attr
->mp_nexthop_global_in
) ||
3843 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3847 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3848 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3849 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3850 &attr
->mp_nexthop_global
)
3851 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3852 || IN6_IS_ADDR_MULTICAST(
3853 &attr
->mp_nexthop_global
)
3854 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3857 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3858 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3859 || IN6_IS_ADDR_MULTICAST(
3860 &attr
->mp_nexthop_global
)
3861 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3874 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3876 struct community
*old
;
3877 struct community
*new;
3878 struct community
*merge
;
3879 struct community
*no_export
;
3881 old
= bgp_attr_get_community(attr
);
3882 no_export
= community_str2com("no-export");
3887 merge
= community_merge(community_dup(old
), no_export
);
3890 community_free(&old
);
3892 new = community_uniq_sort(merge
);
3893 community_free(&merge
);
3895 new = community_dup(no_export
);
3898 community_free(&no_export
);
3900 bgp_attr_set_community(attr
, new);
3903 static bool bgp_accept_own(struct peer
*peer
, afi_t afi
, safi_t safi
,
3904 struct attr
*attr
, const struct prefix
*prefix
,
3907 struct listnode
*node
, *nnode
;
3909 bool accept_own_found
= false;
3911 if (safi
!= SAFI_MPLS_VPN
)
3914 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3915 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
))
3918 /* The route in question carries the ACCEPT_OWN community */
3919 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
3920 struct community
*comm
= bgp_attr_get_community(attr
);
3922 if (community_include(comm
, COMMUNITY_ACCEPT_OWN
))
3923 accept_own_found
= true;
3926 /* The route in question is targeted to one or more destination VRFs
3927 * on the router (as determined by inspecting the Route Target(s)).
3929 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
3930 if (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
)
3933 if (accept_own_found
&&
3935 bgp
->vpn_policy
[afi
]
3936 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
],
3937 bgp_attr_get_ecommunity(attr
))) {
3938 if (bgp_debug_update(peer
, prefix
, NULL
, 1))
3940 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3943 /* Treat this route as imported, because it's leaked
3944 * already from another VRF, and we got an updated
3945 * version from route-reflector with ACCEPT_OWN
3948 *sub_type
= BGP_ROUTE_IMPORTED
;
3957 void bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
3958 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3959 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3960 uint32_t num_labels
, int soft_reconfig
,
3961 struct bgp_route_evpn
*evpn
)
3964 int aspath_loop_count
= 0;
3965 struct bgp_dest
*dest
;
3967 struct attr new_attr
;
3968 struct attr
*attr_new
;
3969 struct bgp_path_info
*pi
;
3970 struct bgp_path_info
*new = NULL
;
3971 struct bgp_path_info_extra
*extra
;
3973 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3975 int do_loop_check
= 1;
3976 int has_valid_label
= 0;
3978 bool force_evpn_import
= false;
3979 safi_t orig_safi
= safi
;
3980 bool leak_success
= true;
3983 if (frrtrace_enabled(frr_bgp
, process_update
)) {
3984 char pfxprint
[PREFIX2STR_BUFFER
];
3986 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
3987 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
3991 #ifdef ENABLE_BGP_VNC
3992 int vnc_implicit_withdraw
= 0;
3995 const struct prefix
*bgp_nht_param_prefix
;
3997 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
3998 if (orig_safi
== SAFI_LABELED_UNICAST
)
3999 safi
= SAFI_UNICAST
;
4001 memset(&new_attr
, 0, sizeof(new_attr
));
4002 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
4003 new_attr
.label
= MPLS_INVALID_LABEL
;
4006 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4007 /* TODO: Check to see if we can get rid of "is_valid_label" */
4008 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
4009 has_valid_label
= (num_labels
> 0) ? 1 : 0;
4011 has_valid_label
= bgp_is_valid_label(label
);
4013 if (has_valid_label
)
4014 assert(label
!= NULL
);
4016 /* Update overlay index of the attribute */
4017 if (afi
== AFI_L2VPN
&& evpn
)
4018 memcpy(&attr
->evpn_overlay
, evpn
,
4019 sizeof(struct bgp_route_evpn
));
4021 /* When peer's soft reconfiguration enabled. Record input packet in
4024 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4025 && peer
!= bgp
->peer_self
)
4026 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
4028 /* Update permitted loop count */
4029 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN
))
4030 allowas_in
= peer
->allowas_in
[afi
][safi
];
4032 /* Check previously received route. */
4033 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4034 if (pi
->peer
== peer
&& pi
->type
== type
4035 && pi
->sub_type
== sub_type
4036 && pi
->addpath_rx_id
== addpath_id
)
4039 /* AS path local-as loop check. */
4040 if (peer
->change_local_as
) {
4042 aspath_loop_count
= allowas_in
;
4043 else if (!CHECK_FLAG(peer
->flags
,
4044 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
4045 aspath_loop_count
= 1;
4047 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
4048 > aspath_loop_count
) {
4049 peer
->stat_pfx_aspath_loop
++;
4050 reason
= "as-path contains our own AS;";
4055 /* If the peer is configured for "allowas-in origin" and the last ASN in
4057 * as-path is our ASN then we do not need to call aspath_loop_check
4059 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
4060 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
4063 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_REFLECTOR_CLIENT
))
4064 bgp_nht_param_prefix
= NULL
;
4066 bgp_nht_param_prefix
= p
;
4068 /* AS path loop check. */
4069 if (do_loop_check
) {
4070 if (aspath_loop_check(attr
->aspath
, bgp
->as
) >
4071 peer
->allowas_in
[afi
][safi
]) {
4072 peer
->stat_pfx_aspath_loop
++;
4073 reason
= "as-path contains our own AS;";
4078 /* If we're a CONFED we need to loop check the CONFED ID too */
4079 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
) && do_loop_check
)
4080 if (aspath_loop_check_confed(attr
->aspath
, bgp
->confed_id
) >
4081 peer
->allowas_in
[afi
][safi
]) {
4082 peer
->stat_pfx_aspath_loop
++;
4083 reason
= "as-path contains our own confed AS;";
4087 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4088 * enabled, then take care of that too.
4090 bool accept_own
= false;
4092 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
4093 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
4095 bgp_accept_own(peer
, afi
, safi
, attr
, p
, &sub_type
);
4097 peer
->stat_pfx_originator_loop
++;
4098 reason
= "originator is us;";
4103 /* Route reflector cluster ID check. */
4104 if (bgp_cluster_filter(peer
, attr
)) {
4105 peer
->stat_pfx_cluster_loop
++;
4106 reason
= "reflected from the same cluster;";
4110 /* Apply incoming filter. */
4111 if (bgp_input_filter(peer
, p
, attr
, afi
, orig_safi
) == FILTER_DENY
) {
4112 peer
->stat_pfx_filter
++;
4117 /* RFC 8212 to prevent route leaks.
4118 * This specification intends to improve this situation by requiring the
4119 * explicit configuration of both BGP Import and Export Policies for any
4120 * External BGP (EBGP) session such as customers, peers, or
4121 * confederation boundaries for all enabled address families. Through
4122 * codification of the aforementioned requirement, operators will
4123 * benefit from consistent behavior across different BGP
4126 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
4127 if (!bgp_inbound_policy_exists(peer
,
4128 &peer
->filter
[afi
][safi
])) {
4129 reason
= "inbound policy missing";
4130 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
4131 NULL
) > FIFTEENMINUTE2USEC
||
4132 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
4134 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4135 monotime(&bgp
->ebgprequirespolicywarning
);
4140 /* draft-ietf-idr-deprecate-as-set-confed-set
4141 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4142 * Eventually, This document (if approved) updates RFC 4271
4143 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4144 * and obsoletes RFC 6472.
4146 if (peer
->bgp
->reject_as_sets
)
4147 if (aspath_check_as_sets(attr
->aspath
)) {
4149 "as-path contains AS_SET or AS_CONFED_SET type;";
4155 /* Apply incoming route-map.
4156 * NB: new_attr may now contain newly allocated values from route-map
4158 * commands, so we need bgp_attr_flush in the error paths, until we
4160 * the attr (which takes over the memory references) */
4161 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, orig_safi
, NULL
, label
,
4164 peer
->stat_pfx_filter
++;
4165 reason
= "route-map;";
4166 bgp_attr_flush(&new_attr
);
4170 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
4171 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
4172 /* remove from RIB previous entry */
4173 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
4176 if (peer
->sort
== BGP_PEER_EBGP
) {
4179 * A BGP speaker receiving an announcement tagged with the
4180 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4181 * NO_EXPORT community as defined in RFC1997, or a
4182 * similar community, to prevent propagation of the
4183 * prefix outside the local AS. The community to prevent
4184 * propagation SHOULD be chosen according to the operator's
4187 if (bgp_attr_get_community(&new_attr
) &&
4188 community_include(bgp_attr_get_community(&new_attr
),
4189 COMMUNITY_BLACKHOLE
))
4190 bgp_attr_add_no_export_community(&new_attr
);
4192 /* If we receive the graceful-shutdown community from an eBGP
4193 * peer we must lower local-preference */
4194 if (bgp_attr_get_community(&new_attr
) &&
4195 community_include(bgp_attr_get_community(&new_attr
),
4197 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
4198 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
4200 /* If graceful-shutdown is configured globally or
4201 * per neighbor, then add the GSHUT community to
4202 * all paths received from eBGP peers. */
4203 } else if (bgp_in_graceful_shutdown(peer
->bgp
) ||
4204 CHECK_FLAG(peer
->flags
, PEER_FLAG_GRACEFUL_SHUTDOWN
))
4205 bgp_attr_add_gshut_community(&new_attr
);
4208 /* next hop check. */
4209 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
) &&
4210 bgp_update_martian_nexthop(bgp
, afi
, safi
, type
, sub_type
,
4212 peer
->stat_pfx_nh_invalid
++;
4213 reason
= "martian or self next-hop;";
4214 bgp_attr_flush(&new_attr
);
4218 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
4219 peer
->stat_pfx_nh_invalid
++;
4220 reason
= "self mac;";
4221 bgp_attr_flush(&new_attr
);
4225 if (bgp_check_role_applicability(afi
, safi
) &&
4226 bgp_otc_filter(peer
, &new_attr
)) {
4227 reason
= "failing otc validation";
4228 bgp_attr_flush(&new_attr
);
4231 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4233 * Suppress fib is enabled
4234 * BGP_OPT_NO_FIB is not enabled
4235 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4236 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4238 if (bgp_fibupd_safi(safi
) && BGP_SUPPRESS_FIB_ENABLED(bgp
)
4239 && (sub_type
== BGP_ROUTE_NORMAL
)
4240 && (!bgp_option_check(BGP_OPT_NO_FIB
))
4241 && (!CHECK_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALLED
)))
4242 SET_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALL_PENDING
);
4244 /* If neighbor soo is configured, tag all incoming routes with
4245 * this SoO tag and then filter out advertisements in
4246 * subgroup_announce_check() if it matches the configured SoO
4247 * on the other peer.
4249 if (peer
->soo
[afi
][safi
]) {
4250 struct ecommunity
*old_ecomm
=
4251 bgp_attr_get_ecommunity(&new_attr
);
4252 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
4253 struct ecommunity
*new_ecomm
;
4256 new_ecomm
= ecommunity_merge(ecommunity_dup(old_ecomm
),
4259 if (!old_ecomm
->refcnt
)
4260 ecommunity_free(&old_ecomm
);
4262 new_ecomm
= ecommunity_dup(ecomm_soo
);
4265 bgp_attr_set_ecommunity(&new_attr
, new_ecomm
);
4268 attr_new
= bgp_attr_intern(&new_attr
);
4270 /* If the update is implicit withdraw. */
4272 pi
->uptime
= monotime(NULL
);
4273 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
4275 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4277 /* Same attribute comes in. */
4278 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4280 && (!has_valid_label
4281 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
4282 num_labels
* sizeof(mpls_label_t
))
4284 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4285 BGP_CONFIG_DAMPENING
)
4286 && peer
->sort
== BGP_PEER_EBGP
4287 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4288 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4289 bgp_debug_rdpfxpath2str(
4290 afi
, safi
, prd
, p
, label
,
4291 num_labels
, addpath_id
? 1 : 0,
4292 addpath_id
, evpn
, pfx_buf
,
4294 zlog_debug("%pBP rcvd %s", peer
,
4298 if (bgp_damp_update(pi
, dest
, afi
, safi
)
4299 != BGP_DAMP_SUPPRESSED
) {
4300 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
4302 bgp_process(bgp
, dest
, afi
, safi
);
4304 } else /* Duplicate - odd */
4306 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4307 if (!peer
->rcvd_attr_printed
) {
4309 "%pBP rcvd UPDATE w/ attr: %s",
4311 peer
->rcvd_attr_str
);
4312 peer
->rcvd_attr_printed
= 1;
4315 bgp_debug_rdpfxpath2str(
4316 afi
, safi
, prd
, p
, label
,
4317 num_labels
, addpath_id
? 1 : 0,
4318 addpath_id
, evpn
, pfx_buf
,
4321 "%pBP rcvd %s...duplicate ignored",
4325 /* graceful restart STALE flag unset. */
4326 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4327 bgp_path_info_unset_flag(
4328 dest
, pi
, BGP_PATH_STALE
);
4329 bgp_dest_set_defer_flag(dest
, false);
4330 bgp_process(bgp
, dest
, afi
, safi
);
4334 bgp_dest_unlock_node(dest
);
4335 bgp_attr_unintern(&attr_new
);
4340 /* Withdraw/Announce before we fully processed the withdraw */
4341 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4342 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4343 bgp_debug_rdpfxpath2str(
4344 afi
, safi
, prd
, p
, label
, num_labels
,
4345 addpath_id
? 1 : 0, addpath_id
, evpn
,
4346 pfx_buf
, sizeof(pfx_buf
));
4348 "%pBP rcvd %s, flapped quicker than processing",
4352 bgp_path_info_restore(dest
, pi
);
4355 * If the BGP_PATH_REMOVED flag is set, then EVPN
4356 * routes would have been unimported already when a
4357 * prior BGP withdraw processing happened. Such routes
4358 * need to be imported again, so flag accordingly.
4360 force_evpn_import
= true;
4362 /* implicit withdraw, decrement aggregate and pcount
4363 * here. only if update is accepted, they'll increment
4366 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4369 /* Received Logging. */
4370 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4371 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
4372 num_labels
, addpath_id
? 1 : 0,
4373 addpath_id
, evpn
, pfx_buf
,
4375 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4378 /* graceful restart STALE flag unset. */
4379 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4380 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
4381 bgp_dest_set_defer_flag(dest
, false);
4384 /* The attribute is changed. */
4385 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
4387 /* Update bgp route dampening information. */
4388 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4389 && peer
->sort
== BGP_PEER_EBGP
) {
4390 /* This is implicit withdraw so we should update
4393 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
4394 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
4396 #ifdef ENABLE_BGP_VNC
4397 if (safi
== SAFI_MPLS_VPN
) {
4398 struct bgp_dest
*pdest
= NULL
;
4399 struct bgp_table
*table
= NULL
;
4401 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4402 (struct prefix
*)prd
);
4403 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4404 table
= bgp_dest_get_bgp_table_info(pdest
);
4406 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
4407 bgp
, prd
, table
, p
, pi
);
4409 bgp_dest_unlock_node(pdest
);
4411 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4412 && (safi
== SAFI_UNICAST
)) {
4413 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4415 * Implicit withdraw case.
4417 ++vnc_implicit_withdraw
;
4418 vnc_import_bgp_del_route(bgp
, p
, pi
);
4419 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
4424 /* Special handling for EVPN update of an existing route. If the
4425 * extended community attribute has changed, we need to
4427 * the route using its existing extended community. It will be
4428 * subsequently processed for import with the new extended
4431 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
4434 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
4436 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4439 cmp
= ecommunity_cmp(
4440 bgp_attr_get_ecommunity(pi
->attr
),
4441 bgp_attr_get_ecommunity(attr_new
));
4443 if (bgp_debug_update(peer
, p
, NULL
, 1))
4445 "Change in EXT-COMM, existing %s new %s",
4447 bgp_attr_get_ecommunity(
4450 bgp_attr_get_ecommunity(
4452 if (safi
== SAFI_EVPN
)
4453 bgp_evpn_unimport_route(
4454 bgp
, afi
, safi
, p
, pi
);
4455 else /* SAFI_MPLS_VPN */
4456 vpn_leak_to_vrf_withdraw(pi
);
4461 /* Update to new attribute. */
4462 bgp_attr_unintern(&pi
->attr
);
4463 pi
->attr
= attr_new
;
4465 /* Update MPLS label */
4466 if (has_valid_label
) {
4467 extra
= bgp_path_info_extra_get(pi
);
4468 if (extra
->label
!= label
) {
4469 memcpy(&extra
->label
, label
,
4470 num_labels
* sizeof(mpls_label_t
));
4471 extra
->num_labels
= num_labels
;
4473 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4474 bgp_set_valid_label(&extra
->label
[0]);
4477 /* Update SRv6 SID */
4478 if (attr
->srv6_l3vpn
) {
4479 extra
= bgp_path_info_extra_get(pi
);
4480 if (sid_diff(&extra
->sid
[0].sid
,
4481 &attr
->srv6_l3vpn
->sid
)) {
4482 sid_copy(&extra
->sid
[0].sid
,
4483 &attr
->srv6_l3vpn
->sid
);
4484 extra
->num_sids
= 1;
4486 extra
->sid
[0].loc_block_len
= 0;
4487 extra
->sid
[0].loc_node_len
= 0;
4488 extra
->sid
[0].func_len
= 0;
4489 extra
->sid
[0].arg_len
= 0;
4490 extra
->sid
[0].transposition_len
= 0;
4491 extra
->sid
[0].transposition_offset
= 0;
4493 if (attr
->srv6_l3vpn
->loc_block_len
!= 0) {
4494 extra
->sid
[0].loc_block_len
=
4495 attr
->srv6_l3vpn
->loc_block_len
;
4496 extra
->sid
[0].loc_node_len
=
4497 attr
->srv6_l3vpn
->loc_node_len
;
4498 extra
->sid
[0].func_len
=
4499 attr
->srv6_l3vpn
->func_len
;
4500 extra
->sid
[0].arg_len
=
4501 attr
->srv6_l3vpn
->arg_len
;
4502 extra
->sid
[0].transposition_len
=
4504 ->transposition_len
;
4505 extra
->sid
[0].transposition_offset
=
4507 ->transposition_offset
;
4510 } else if (attr
->srv6_vpn
) {
4511 extra
= bgp_path_info_extra_get(pi
);
4512 if (sid_diff(&extra
->sid
[0].sid
,
4513 &attr
->srv6_vpn
->sid
)) {
4514 sid_copy(&extra
->sid
[0].sid
,
4515 &attr
->srv6_vpn
->sid
);
4516 extra
->num_sids
= 1;
4520 #ifdef ENABLE_BGP_VNC
4521 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4522 && (safi
== SAFI_UNICAST
)) {
4523 if (vnc_implicit_withdraw
) {
4525 * Add back the route with its new attributes
4527 * The route is still selected, until the route
4529 * queued by bgp_process actually runs. We have
4531 * update to the VNC side immediately to avoid
4533 * configuration changes (e.g., route-map
4535 * trigger re-importation of the entire RIB.
4537 vnc_import_bgp_add_route(bgp
, p
, pi
);
4538 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4543 /* Update bgp route dampening information. */
4544 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4545 && peer
->sort
== BGP_PEER_EBGP
) {
4546 /* Now we do normal update dampening. */
4547 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4548 if (ret
== BGP_DAMP_SUPPRESSED
) {
4549 bgp_dest_unlock_node(dest
);
4554 /* Nexthop reachability check - for unicast and
4555 * labeled-unicast.. */
4556 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4557 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4558 || (safi
== SAFI_EVPN
&&
4559 bgp_evpn_is_prefix_nht_supported(p
))) {
4560 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4561 && peer
->ttl
== BGP_DEFAULT_TTL
4562 && !CHECK_FLAG(peer
->flags
,
4563 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4564 && !CHECK_FLAG(bgp
->flags
,
4565 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4570 struct bgp
*bgp_nexthop
= bgp
;
4572 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4573 bgp_nexthop
= pi
->extra
->bgp_orig
;
4575 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4577 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4578 safi
, pi
, NULL
, connected
,
4579 bgp_nht_param_prefix
) ||
4580 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4581 bgp_path_info_set_flag(dest
, pi
,
4584 if (BGP_DEBUG(nht
, NHT
)) {
4585 zlog_debug("%s(%pI4): NH unresolved",
4587 (in_addr_t
*)&attr_new
->nexthop
);
4589 bgp_path_info_unset_flag(dest
, pi
,
4594 bgp_path_info_set_flag(dest
, pi
,
4595 BGP_PATH_ACCEPT_OWN
);
4597 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4600 #ifdef ENABLE_BGP_VNC
4601 if (safi
== SAFI_MPLS_VPN
) {
4602 struct bgp_dest
*pdest
= NULL
;
4603 struct bgp_table
*table
= NULL
;
4605 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4606 (struct prefix
*)prd
);
4607 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4608 table
= bgp_dest_get_bgp_table_info(pdest
);
4610 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4611 bgp
, prd
, table
, p
, pi
);
4613 bgp_dest_unlock_node(pdest
);
4617 /* If this is an EVPN route and some attribute has changed,
4618 * or we are explicitly told to perform a route import, process
4619 * route for import. If the extended community has changed, we
4621 * have done the un-import earlier and the import would result
4623 * route getting injected into appropriate L2 VNIs. If it is
4625 * some other attribute change, the import will result in
4627 * the attributes for the route in the VNI(s).
4629 if (safi
== SAFI_EVPN
&&
4630 (!same_attr
|| force_evpn_import
) &&
4631 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4632 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4634 /* Process change. */
4635 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4637 bgp_process(bgp
, dest
, afi
, safi
);
4638 bgp_dest_unlock_node(dest
);
4640 if (SAFI_UNICAST
== safi
4641 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4642 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4644 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4646 if ((SAFI_MPLS_VPN
== safi
)
4647 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4648 leak_success
= vpn_leak_to_vrf_update(bgp
, pi
, prd
);
4651 #ifdef ENABLE_BGP_VNC
4652 if (SAFI_MPLS_VPN
== safi
) {
4653 mpls_label_t label_decoded
= decode_label(label
);
4655 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4656 type
, sub_type
, &label_decoded
);
4658 if (SAFI_ENCAP
== safi
) {
4659 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4660 type
, sub_type
, NULL
);
4663 if ((safi
== SAFI_MPLS_VPN
) &&
4664 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4665 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4667 bgp_unlink_nexthop(pi
);
4668 bgp_path_info_delete(dest
, pi
);
4671 } // End of implicit withdraw
4673 /* Received Logging. */
4674 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4675 if (!peer
->rcvd_attr_printed
) {
4676 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4677 peer
->rcvd_attr_str
);
4678 peer
->rcvd_attr_printed
= 1;
4681 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4682 addpath_id
? 1 : 0, addpath_id
, evpn
,
4683 pfx_buf
, sizeof(pfx_buf
));
4684 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4687 /* Make new BGP info. */
4688 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4690 /* Update MPLS label */
4691 if (has_valid_label
) {
4692 extra
= bgp_path_info_extra_get(new);
4693 if (extra
->label
!= label
) {
4694 memcpy(&extra
->label
, label
,
4695 num_labels
* sizeof(mpls_label_t
));
4696 extra
->num_labels
= num_labels
;
4698 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4699 bgp_set_valid_label(&extra
->label
[0]);
4702 /* Update SRv6 SID */
4703 if (safi
== SAFI_MPLS_VPN
) {
4704 extra
= bgp_path_info_extra_get(new);
4705 if (attr
->srv6_l3vpn
) {
4706 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_l3vpn
->sid
);
4707 extra
->num_sids
= 1;
4709 extra
->sid
[0].loc_block_len
=
4710 attr
->srv6_l3vpn
->loc_block_len
;
4711 extra
->sid
[0].loc_node_len
=
4712 attr
->srv6_l3vpn
->loc_node_len
;
4713 extra
->sid
[0].func_len
= attr
->srv6_l3vpn
->func_len
;
4714 extra
->sid
[0].arg_len
= attr
->srv6_l3vpn
->arg_len
;
4715 extra
->sid
[0].transposition_len
=
4716 attr
->srv6_l3vpn
->transposition_len
;
4717 extra
->sid
[0].transposition_offset
=
4718 attr
->srv6_l3vpn
->transposition_offset
;
4719 } else if (attr
->srv6_vpn
) {
4720 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_vpn
->sid
);
4721 extra
->num_sids
= 1;
4725 /* Nexthop reachability check. */
4726 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4727 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4728 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4729 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4730 && peer
->ttl
== BGP_DEFAULT_TTL
4731 && !CHECK_FLAG(peer
->flags
,
4732 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4733 && !CHECK_FLAG(bgp
->flags
,
4734 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4739 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4741 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4742 connected
, bgp_nht_param_prefix
) ||
4743 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4744 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4746 if (BGP_DEBUG(nht
, NHT
))
4747 zlog_debug("%s(%pI4): NH unresolved", __func__
,
4748 &attr_new
->nexthop
);
4749 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4753 bgp_path_info_set_flag(dest
, new, BGP_PATH_ACCEPT_OWN
);
4755 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4758 /* If maximum prefix count is configured and current prefix
4761 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0)) {
4762 reason
= "maximum-prefix overflow";
4763 bgp_attr_flush(&new_attr
);
4768 new->addpath_rx_id
= addpath_id
;
4770 /* Increment prefix */
4771 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4773 /* Register new BGP information. */
4774 bgp_path_info_add(dest
, new);
4776 /* route_node_get lock */
4777 bgp_dest_unlock_node(dest
);
4779 #ifdef ENABLE_BGP_VNC
4780 if (safi
== SAFI_MPLS_VPN
) {
4781 struct bgp_dest
*pdest
= NULL
;
4782 struct bgp_table
*table
= NULL
;
4784 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4785 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4786 table
= bgp_dest_get_bgp_table_info(pdest
);
4788 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4789 bgp
, prd
, table
, p
, new);
4791 bgp_dest_unlock_node(pdest
);
4795 /* If this is an EVPN route, process for import. */
4796 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4797 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4799 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4801 /* Process change. */
4802 bgp_process(bgp
, dest
, afi
, safi
);
4804 if (SAFI_UNICAST
== safi
4805 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4806 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4807 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4809 if ((SAFI_MPLS_VPN
== safi
)
4810 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4811 leak_success
= vpn_leak_to_vrf_update(bgp
, new, prd
);
4813 #ifdef ENABLE_BGP_VNC
4814 if (SAFI_MPLS_VPN
== safi
) {
4815 mpls_label_t label_decoded
= decode_label(label
);
4817 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4818 sub_type
, &label_decoded
);
4820 if (SAFI_ENCAP
== safi
) {
4821 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4825 if ((safi
== SAFI_MPLS_VPN
) &&
4826 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4827 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4829 bgp_unlink_nexthop(new);
4830 bgp_path_info_delete(dest
, new);
4835 /* This BGP update is filtered. Log the reason then update BGP
4839 bgp_unlink_nexthop(new);
4840 bgp_path_info_delete(dest
, new);
4841 bgp_path_info_extra_free(&new->extra
);
4842 XFREE(MTYPE_BGP_ROUTE
, new);
4845 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4847 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4848 if (!peer
->rcvd_attr_printed
) {
4849 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4850 peer
->rcvd_attr_str
);
4851 peer
->rcvd_attr_printed
= 1;
4854 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4855 addpath_id
? 1 : 0, addpath_id
, evpn
,
4856 pfx_buf
, sizeof(pfx_buf
));
4857 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4858 peer
, pfx_buf
, reason
);
4862 /* If this is an EVPN route, un-import it as it is now filtered.
4864 if (safi
== SAFI_EVPN
)
4865 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4867 if (SAFI_UNICAST
== safi
4868 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4869 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4871 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4873 if ((SAFI_MPLS_VPN
== safi
)
4874 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4876 vpn_leak_to_vrf_withdraw(pi
);
4879 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4882 bgp_dest_unlock_node(dest
);
4884 #ifdef ENABLE_BGP_VNC
4886 * Filtered update is treated as an implicit withdrawal (see
4888 * a few lines above)
4890 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4891 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4899 void bgp_withdraw(struct peer
*peer
, const struct prefix
*p
,
4900 uint32_t addpath_id
, afi_t afi
, safi_t safi
, int type
,
4901 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4902 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4905 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4906 struct bgp_dest
*dest
;
4907 struct bgp_path_info
*pi
;
4909 #ifdef ENABLE_BGP_VNC
4910 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4911 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4919 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4921 /* If peer is soft reconfiguration enabled. Record input packet for
4922 * further calculation.
4924 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4925 * routes that are filtered. This tanks out Quagga RS pretty badly due
4927 * the iteration over all RS clients.
4928 * Since we need to remove the entry from adj_in anyway, do that first
4930 * if there was no entry, we don't need to do anything more.
4932 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4933 && peer
!= bgp
->peer_self
)
4934 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4935 peer
->stat_pfx_dup_withdraw
++;
4937 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4938 bgp_debug_rdpfxpath2str(
4939 afi
, safi
, prd
, p
, label
, num_labels
,
4940 addpath_id
? 1 : 0, addpath_id
, NULL
,
4941 pfx_buf
, sizeof(pfx_buf
));
4943 "%s withdrawing route %s not in adj-in",
4944 peer
->host
, pfx_buf
);
4946 bgp_dest_unlock_node(dest
);
4950 /* Lookup withdrawn route. */
4951 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4952 if (pi
->peer
== peer
&& pi
->type
== type
4953 && pi
->sub_type
== sub_type
4954 && pi
->addpath_rx_id
== addpath_id
)
4958 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4959 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4960 addpath_id
? 1 : 0, addpath_id
, NULL
,
4961 pfx_buf
, sizeof(pfx_buf
));
4962 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer
,
4966 /* Withdraw specified route from routing table. */
4967 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4968 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4969 if (SAFI_UNICAST
== safi
4970 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4971 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4972 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4974 if ((SAFI_MPLS_VPN
== safi
)
4975 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4977 vpn_leak_to_vrf_withdraw(pi
);
4979 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4980 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4981 addpath_id
? 1 : 0, addpath_id
, NULL
,
4982 pfx_buf
, sizeof(pfx_buf
));
4983 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4986 /* Unlock bgp_node_get() lock. */
4987 bgp_dest_unlock_node(dest
);
4992 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4995 struct update_subgroup
*subgrp
;
4996 subgrp
= peer_subgroup(peer
, afi
, safi
);
4997 subgroup_default_originate(subgrp
, withdraw
);
5002 * bgp_stop_announce_route_timer
5004 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
5006 if (!paf
->t_announce_route
)
5009 THREAD_OFF(paf
->t_announce_route
);
5013 * bgp_announce_route_timer_expired
5015 * Callback that is invoked when the route announcement timer for a
5018 static void bgp_announce_route_timer_expired(struct thread
*t
)
5020 struct peer_af
*paf
;
5023 paf
= THREAD_ARG(t
);
5026 if (!peer_established(peer
))
5029 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
5032 peer_af_announce_route(paf
, 1);
5034 /* Notify BGP conditional advertisement scanner percess */
5035 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
5039 * bgp_announce_route
5041 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
5043 * if force is true we will force an update even if the update
5044 * limiting code is attempted to kick in.
5046 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
, bool force
)
5048 struct peer_af
*paf
;
5049 struct update_subgroup
*subgrp
;
5051 paf
= peer_af_find(peer
, afi
, safi
);
5054 subgrp
= PAF_SUBGRP(paf
);
5057 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5058 * or a refresh has already been triggered.
5060 if (!subgrp
|| paf
->t_announce_route
)
5064 SET_FLAG(subgrp
->sflags
, SUBGRP_STATUS_FORCE_UPDATES
);
5067 * Start a timer to stagger/delay the announce. This serves
5068 * two purposes - announcement can potentially be combined for
5069 * multiple peers and the announcement doesn't happen in the
5072 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
5073 (subgrp
->peer_count
== 1)
5074 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5075 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
5076 &paf
->t_announce_route
);
5080 * Announce routes from all AF tables to a peer.
5082 * This should ONLY be called when there is a need to refresh the
5083 * routes to the peer based on a policy change for this peer alone
5084 * or a route refresh request received from the peer.
5085 * The operation will result in splitting the peer from its existing
5086 * subgroups and putting it in new subgroups.
5088 void bgp_announce_route_all(struct peer
*peer
)
5093 FOREACH_AFI_SAFI (afi
, safi
)
5094 bgp_announce_route(peer
, afi
, safi
, false);
5097 /* Flag or unflag bgp_dest to determine whether it should be treated by
5098 * bgp_soft_reconfig_table_task.
5099 * Flag if flag is true. Unflag if flag is false.
5101 static void bgp_soft_reconfig_table_flag(struct bgp_table
*table
, bool flag
)
5103 struct bgp_dest
*dest
;
5104 struct bgp_adj_in
*ain
;
5109 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5110 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5111 if (ain
->peer
!= NULL
)
5114 if (flag
&& ain
!= NULL
&& ain
->peer
!= NULL
)
5115 SET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5117 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5121 static void bgp_soft_reconfig_table_update(struct peer
*peer
,
5122 struct bgp_dest
*dest
,
5123 struct bgp_adj_in
*ain
, afi_t afi
,
5124 safi_t safi
, struct prefix_rd
*prd
)
5126 struct bgp_path_info
*pi
;
5127 uint32_t num_labels
= 0;
5128 mpls_label_t
*label_pnt
= NULL
;
5129 struct bgp_route_evpn evpn
;
5131 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5132 if (pi
->peer
== peer
)
5135 if (pi
&& pi
->extra
)
5136 num_labels
= pi
->extra
->num_labels
;
5138 label_pnt
= &pi
->extra
->label
[0];
5140 memcpy(&evpn
, bgp_attr_get_evpn_overlay(pi
->attr
),
5143 memset(&evpn
, 0, sizeof(evpn
));
5145 bgp_update(peer
, bgp_dest_get_prefix(dest
), ain
->addpath_rx_id
,
5146 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, prd
,
5147 label_pnt
, num_labels
, 1, &evpn
);
5150 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5151 struct bgp_table
*table
,
5152 struct prefix_rd
*prd
)
5154 struct bgp_dest
*dest
;
5155 struct bgp_adj_in
*ain
;
5158 table
= peer
->bgp
->rib
[afi
][safi
];
5160 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5161 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5162 if (ain
->peer
!= peer
)
5165 bgp_soft_reconfig_table_update(peer
, dest
, ain
, afi
,
5170 /* Do soft reconfig table per bgp table.
5171 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5172 * when BGP_NODE_SOFT_RECONFIG is set,
5173 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5174 * Schedule a new thread to continue the job.
5175 * Without splitting the full job into several part,
5176 * vtysh waits for the job to finish before responding to a BGP command
5178 static void bgp_soft_reconfig_table_task(struct thread
*thread
)
5180 uint32_t iter
, max_iter
;
5181 struct bgp_dest
*dest
;
5182 struct bgp_adj_in
*ain
;
5184 struct bgp_table
*table
;
5185 struct prefix_rd
*prd
;
5186 struct listnode
*node
, *nnode
;
5188 table
= THREAD_ARG(thread
);
5191 max_iter
= SOFT_RECONFIG_TASK_MAX_PREFIX
;
5192 if (table
->soft_reconfig_init
) {
5193 /* first call of the function with a new srta structure.
5194 * Don't do any treatment this time on nodes
5195 * in order vtysh to respond quickly
5200 for (iter
= 0, dest
= bgp_table_top(table
); (dest
&& iter
< max_iter
);
5201 dest
= bgp_route_next(dest
)) {
5202 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
))
5205 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5207 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5208 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
,
5210 if (ain
->peer
!= peer
)
5213 bgp_soft_reconfig_table_update(
5214 peer
, dest
, ain
, table
->afi
,
5221 /* we're either starting the initial iteration,
5222 * or we're going to continue an ongoing iteration
5224 if (dest
|| table
->soft_reconfig_init
) {
5225 table
->soft_reconfig_init
= false;
5226 thread_add_event(bm
->master
, bgp_soft_reconfig_table_task
,
5227 table
, 0, &table
->soft_reconfig_thread
);
5230 /* we're done, clean up the background iteration context info and
5231 schedule route annoucement
5233 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
, peer
)) {
5234 listnode_delete(table
->soft_reconfig_peers
, peer
);
5235 bgp_announce_route(peer
, table
->afi
, table
->safi
, false);
5238 list_delete(&table
->soft_reconfig_peers
);
5242 /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5244 * - bgp cannot be NULL
5245 * - if table and peer are NULL, cancel all threads within the bgp instance
5246 * - if table is NULL and peer is not,
5247 * remove peer in all threads within the bgp instance
5248 * - if peer is NULL, cancel all threads matching table within the bgp instance
5250 void bgp_soft_reconfig_table_task_cancel(const struct bgp
*bgp
,
5251 const struct bgp_table
*table
,
5252 const struct peer
*peer
)
5255 struct listnode
*node
, *nnode
;
5257 struct bgp_table
*ntable
;
5262 FOREACH_AFI_SAFI (afi
, safi
) {
5263 ntable
= bgp
->rib
[afi
][safi
];
5266 if (table
&& table
!= ntable
)
5269 for (ALL_LIST_ELEMENTS(ntable
->soft_reconfig_peers
, node
, nnode
,
5271 if (peer
&& peer
!= npeer
)
5273 listnode_delete(ntable
->soft_reconfig_peers
, npeer
);
5276 if (!ntable
->soft_reconfig_peers
5277 || !list_isempty(ntable
->soft_reconfig_peers
))
5280 list_delete(&ntable
->soft_reconfig_peers
);
5281 bgp_soft_reconfig_table_flag(ntable
, false);
5282 THREAD_OFF(ntable
->soft_reconfig_thread
);
5287 * Returns false if the peer is not configured for soft reconfig in
5289 bool bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5291 struct bgp_dest
*dest
;
5292 struct bgp_table
*table
;
5293 struct listnode
*node
, *nnode
;
5295 struct peer_af
*paf
;
5297 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
))
5300 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
5301 && (safi
!= SAFI_EVPN
)) {
5302 table
= peer
->bgp
->rib
[afi
][safi
];
5306 table
->soft_reconfig_init
= true;
5308 if (!table
->soft_reconfig_peers
)
5309 table
->soft_reconfig_peers
= list_new();
5311 /* add peer to the table soft_reconfig_peers if not already
5314 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
,
5320 listnode_add(table
->soft_reconfig_peers
, peer
);
5322 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5323 * on table would start back at the beginning.
5325 bgp_soft_reconfig_table_flag(table
, true);
5327 if (!table
->soft_reconfig_thread
)
5328 thread_add_event(bm
->master
,
5329 bgp_soft_reconfig_table_task
, table
, 0,
5330 &table
->soft_reconfig_thread
);
5331 /* Cancel bgp_announce_route_timer_expired threads.
5332 * bgp_announce_route_timer_expired threads have been scheduled
5333 * to announce routes as soon as the soft_reconfigure process
5335 * In this case, soft_reconfigure is also scheduled by using
5336 * a thread but is planned after the
5337 * bgp_announce_route_timer_expired threads. It means that,
5338 * without cancelling the threads, the route announcement task
5339 * would run before the soft reconfiguration one. That would
5340 * useless and would block vtysh during several seconds. Route
5341 * announcements are rescheduled as soon as the soft_reconfigure
5344 paf
= peer_af_find(peer
, afi
, safi
);
5346 bgp_stop_announce_route_timer(paf
);
5348 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5349 dest
= bgp_route_next(dest
)) {
5350 table
= bgp_dest_get_bgp_table_info(dest
);
5355 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5356 struct prefix_rd prd
;
5358 prd
.family
= AF_UNSPEC
;
5360 memcpy(&prd
.val
, p
->u
.val
, 8);
5362 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
5369 struct bgp_clear_node_queue
{
5370 struct bgp_dest
*dest
;
5373 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
5375 struct bgp_clear_node_queue
*cnq
= data
;
5376 struct bgp_dest
*dest
= cnq
->dest
;
5377 struct peer
*peer
= wq
->spec
.data
;
5378 struct bgp_path_info
*pi
;
5380 afi_t afi
= bgp_dest_table(dest
)->afi
;
5381 safi_t safi
= bgp_dest_table(dest
)->safi
;
5383 assert(dest
&& peer
);
5386 /* It is possible that we have multiple paths for a prefix from a peer
5387 * if that peer is using AddPath.
5389 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5390 if (pi
->peer
!= peer
)
5393 /* graceful restart STALE flag set. */
5394 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
5395 && peer
->nsf
[afi
][safi
])
5396 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5397 PEER_STATUS_ENHANCED_REFRESH
))
5398 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5399 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
5400 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
5402 /* If this is an EVPN route, process for
5404 if (safi
== SAFI_EVPN
)
5405 bgp_evpn_unimport_route(
5407 bgp_dest_get_prefix(dest
), pi
);
5408 /* Handle withdraw for VRF route-leaking and L3VPN */
5409 if (SAFI_UNICAST
== safi
5410 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
5411 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5412 vpn_leak_from_vrf_withdraw(bgp_get_default(),
5415 if (SAFI_MPLS_VPN
== safi
&&
5416 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5417 vpn_leak_to_vrf_withdraw(pi
);
5420 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5426 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
5428 struct bgp_clear_node_queue
*cnq
= data
;
5429 struct bgp_dest
*dest
= cnq
->dest
;
5430 struct bgp_table
*table
= bgp_dest_table(dest
);
5432 bgp_dest_unlock_node(dest
);
5433 bgp_table_unlock(table
);
5434 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
5437 static void bgp_clear_node_complete(struct work_queue
*wq
)
5439 struct peer
*peer
= wq
->spec
.data
;
5441 /* Tickle FSM to start moving again */
5442 BGP_EVENT_ADD(peer
, Clearing_Completed
);
5444 peer_unlock(peer
); /* bgp_clear_route */
5447 static void bgp_clear_node_queue_init(struct peer
*peer
)
5449 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5451 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
5452 #undef CLEAR_QUEUE_NAME_LEN
5454 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
5455 peer
->clear_node_queue
->spec
.hold
= 10;
5456 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
5457 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
5458 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
5459 peer
->clear_node_queue
->spec
.max_retries
= 0;
5461 /* we only 'lock' this peer reference when the queue is actually active
5463 peer
->clear_node_queue
->spec
.data
= peer
;
5466 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5467 struct bgp_table
*table
)
5469 struct bgp_dest
*dest
;
5470 int force
= peer
->bgp
->process_queue
? 0 : 1;
5473 table
= peer
->bgp
->rib
[afi
][safi
];
5475 /* If still no table => afi/safi isn't configured at all or smth. */
5479 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5480 struct bgp_path_info
*pi
, *next
;
5481 struct bgp_adj_in
*ain
;
5482 struct bgp_adj_in
*ain_next
;
5484 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5485 * queued for every clearing peer, regardless of whether it is
5486 * relevant to the peer at hand.
5488 * Overview: There are 3 different indices which need to be
5489 * scrubbed, potentially, when a peer is removed:
5491 * 1 peer's routes visible via the RIB (ie accepted routes)
5492 * 2 peer's routes visible by the (optional) peer's adj-in index
5493 * 3 other routes visible by the peer's adj-out index
5495 * 3 there is no hurry in scrubbing, once the struct peer is
5496 * removed from bgp->peer, we could just GC such deleted peer's
5497 * adj-outs at our leisure.
5499 * 1 and 2 must be 'scrubbed' in some way, at least made
5500 * invisible via RIB index before peer session is allowed to be
5501 * brought back up. So one needs to know when such a 'search' is
5506 * - there'd be a single global queue or a single RIB walker
5507 * - rather than tracking which route_nodes still need to be
5508 * examined on a peer basis, we'd track which peers still
5511 * Given that our per-peer prefix-counts now should be reliable,
5512 * this may actually be achievable. It doesn't seem to be a huge
5513 * problem at this time,
5515 * It is possible that we have multiple paths for a prefix from
5517 * if that peer is using AddPath.
5521 ain_next
= ain
->next
;
5523 if (ain
->peer
== peer
)
5524 bgp_adj_in_remove(dest
, ain
);
5529 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5531 if (pi
->peer
!= peer
)
5535 bgp_path_info_reap(dest
, pi
);
5537 struct bgp_clear_node_queue
*cnq
;
5539 /* both unlocked in bgp_clear_node_queue_del */
5540 bgp_table_lock(bgp_dest_table(dest
));
5541 bgp_dest_lock_node(dest
);
5543 MTYPE_BGP_CLEAR_NODE_QUEUE
,
5544 sizeof(struct bgp_clear_node_queue
));
5546 work_queue_add(peer
->clear_node_queue
, cnq
);
5554 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5556 struct bgp_dest
*dest
;
5557 struct bgp_table
*table
;
5559 if (peer
->clear_node_queue
== NULL
)
5560 bgp_clear_node_queue_init(peer
);
5562 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5563 * Idle until it receives a Clearing_Completed event. This protects
5564 * against peers which flap faster than we can we clear, which could
5567 * a) race with routes from the new session being installed before
5568 * clear_route_node visits the node (to delete the route of that
5570 * b) resource exhaustion, clear_route_node likely leads to an entry
5571 * on the process_main queue. Fast-flapping could cause that queue
5575 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5576 * the unlock will happen upon work-queue completion; other wise, the
5577 * unlock happens at the end of this function.
5579 if (!peer
->clear_node_queue
->thread
)
5582 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
5583 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
5585 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5586 dest
= bgp_route_next(dest
)) {
5587 table
= bgp_dest_get_bgp_table_info(dest
);
5591 bgp_clear_route_table(peer
, afi
, safi
, table
);
5594 /* unlock if no nodes got added to the clear-node-queue. */
5595 if (!peer
->clear_node_queue
->thread
)
5599 void bgp_clear_route_all(struct peer
*peer
)
5604 FOREACH_AFI_SAFI (afi
, safi
)
5605 bgp_clear_route(peer
, afi
, safi
);
5607 #ifdef ENABLE_BGP_VNC
5608 rfapiProcessPeerDown(peer
);
5612 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5614 struct bgp_table
*table
;
5615 struct bgp_dest
*dest
;
5616 struct bgp_adj_in
*ain
;
5617 struct bgp_adj_in
*ain_next
;
5619 table
= peer
->bgp
->rib
[afi
][safi
];
5621 /* It is possible that we have multiple paths for a prefix from a peer
5622 * if that peer is using AddPath.
5624 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5628 ain_next
= ain
->next
;
5630 if (ain
->peer
== peer
)
5631 bgp_adj_in_remove(dest
, ain
);
5638 /* If any of the routes from the peer have been marked with the NO_LLGR
5639 * community, either as sent by the peer, or as the result of a configured
5640 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5641 * operation of [RFC4271].
5643 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5645 struct bgp_dest
*dest
;
5646 struct bgp_path_info
*pi
;
5647 struct bgp_table
*table
;
5649 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5650 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5651 dest
= bgp_route_next(dest
)) {
5652 struct bgp_dest
*rm
;
5654 /* look for neighbor in tables */
5655 table
= bgp_dest_get_bgp_table_info(dest
);
5659 for (rm
= bgp_table_top(table
); rm
;
5660 rm
= bgp_route_next(rm
))
5661 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
5663 if (pi
->peer
!= peer
)
5666 peer
->af_sflags
[afi
][safi
],
5667 PEER_STATUS_LLGR_WAIT
) &&
5668 bgp_attr_get_community(pi
->attr
) &&
5670 bgp_attr_get_community(
5674 if (!CHECK_FLAG(pi
->flags
,
5679 * If this is VRF leaked route
5680 * process for withdraw.
5683 BGP_ROUTE_IMPORTED
&&
5684 peer
->bgp
->inst_type
==
5685 BGP_INSTANCE_TYPE_DEFAULT
)
5686 vpn_leak_to_vrf_withdraw(pi
);
5688 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
5693 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5694 dest
= bgp_route_next(dest
))
5695 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5697 if (pi
->peer
!= peer
)
5699 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5700 PEER_STATUS_LLGR_WAIT
) &&
5701 bgp_attr_get_community(pi
->attr
) &&
5703 bgp_attr_get_community(pi
->attr
),
5706 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
5708 if (safi
== SAFI_UNICAST
&&
5709 (peer
->bgp
->inst_type
==
5710 BGP_INSTANCE_TYPE_VRF
||
5711 peer
->bgp
->inst_type
==
5712 BGP_INSTANCE_TYPE_DEFAULT
))
5713 vpn_leak_from_vrf_withdraw(
5714 bgp_get_default(), peer
->bgp
,
5717 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5723 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5725 struct bgp_dest
*dest
, *ndest
;
5726 struct bgp_path_info
*pi
;
5727 struct bgp_table
*table
;
5729 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5730 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5731 dest
= bgp_route_next(dest
)) {
5732 table
= bgp_dest_get_bgp_table_info(dest
);
5736 for (ndest
= bgp_table_top(table
); ndest
;
5737 ndest
= bgp_route_next(ndest
)) {
5738 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5740 if (pi
->peer
!= peer
)
5744 peer
->af_sflags
[afi
][safi
],
5745 PEER_STATUS_ENHANCED_REFRESH
))
5746 && !CHECK_FLAG(pi
->flags
,
5750 BGP_PATH_UNUSEABLE
)) {
5751 if (bgp_debug_neighbor_events(
5754 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5758 bgp_dest_get_prefix(
5761 bgp_path_info_set_flag(
5769 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5770 dest
= bgp_route_next(dest
)) {
5771 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5773 if (pi
->peer
!= peer
)
5776 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5777 PEER_STATUS_ENHANCED_REFRESH
))
5778 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5779 && !CHECK_FLAG(pi
->flags
,
5780 BGP_PATH_UNUSEABLE
)) {
5781 if (bgp_debug_neighbor_events(peer
))
5783 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5786 bgp_dest_get_prefix(
5789 bgp_path_info_set_flag(dest
, pi
,
5797 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5799 if (peer
->sort
== BGP_PEER_IBGP
)
5802 if (peer
->sort
== BGP_PEER_EBGP
5803 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5804 || FILTER_LIST_OUT_NAME(filter
)
5805 || DISTRIBUTE_OUT_NAME(filter
)))
5810 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5812 if (peer
->sort
== BGP_PEER_IBGP
)
5815 if (peer
->sort
== BGP_PEER_EBGP
5816 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5817 || FILTER_LIST_IN_NAME(filter
)
5818 || DISTRIBUTE_IN_NAME(filter
)))
5823 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5826 struct bgp_dest
*dest
;
5827 struct bgp_path_info
*pi
;
5828 struct bgp_path_info
*next
;
5830 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5831 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5832 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5836 /* Unimport EVPN routes from VRFs */
5837 if (safi
== SAFI_EVPN
)
5838 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5841 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5842 && pi
->type
== ZEBRA_ROUTE_BGP
5843 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5844 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5845 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5847 if (bgp_fibupd_safi(safi
))
5848 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5851 bgp_path_info_reap(dest
, pi
);
5855 /* Delete all kernel routes. */
5856 void bgp_cleanup_routes(struct bgp
*bgp
)
5859 struct bgp_dest
*dest
;
5860 struct bgp_table
*table
;
5862 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5863 if (afi
== AFI_L2VPN
)
5865 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5868 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5870 if (afi
!= AFI_L2VPN
) {
5872 safi
= SAFI_MPLS_VPN
;
5873 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5874 dest
= bgp_route_next(dest
)) {
5875 table
= bgp_dest_get_bgp_table_info(dest
);
5876 if (table
!= NULL
) {
5877 bgp_cleanup_table(bgp
, table
, safi
);
5878 bgp_table_finish(&table
);
5879 bgp_dest_set_bgp_table_info(dest
, NULL
);
5880 bgp_dest_unlock_node(dest
);
5884 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5885 dest
= bgp_route_next(dest
)) {
5886 table
= bgp_dest_get_bgp_table_info(dest
);
5887 if (table
!= NULL
) {
5888 bgp_cleanup_table(bgp
, table
, safi
);
5889 bgp_table_finish(&table
);
5890 bgp_dest_set_bgp_table_info(dest
, NULL
);
5891 bgp_dest_unlock_node(dest
);
5896 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5897 dest
= bgp_route_next(dest
)) {
5898 table
= bgp_dest_get_bgp_table_info(dest
);
5899 if (table
!= NULL
) {
5900 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5901 bgp_table_finish(&table
);
5902 bgp_dest_set_bgp_table_info(dest
, NULL
);
5903 bgp_dest_unlock_node(dest
);
5908 void bgp_reset(void)
5911 bgp_zclient_reset();
5912 access_list_reset();
5913 prefix_list_reset();
5916 bool bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5918 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5919 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5920 PEER_CAP_ADDPATH_AF_TX_RCV
));
5923 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5925 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5926 struct bgp_nlri
*packet
)
5934 bool addpath_capable
;
5935 uint32_t addpath_id
;
5938 lim
= pnt
+ packet
->length
;
5940 safi
= packet
->safi
;
5942 addpath_capable
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5944 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5945 syntactic validity. If the field is syntactically incorrect,
5946 then the Error Subcode is set to Invalid Network Field. */
5947 for (; pnt
< lim
; pnt
+= psize
) {
5948 /* Clear prefix structure. */
5949 memset(&p
, 0, sizeof(p
));
5951 if (addpath_capable
) {
5953 /* When packet overflow occurs return immediately. */
5954 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5955 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5957 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5958 addpath_id
= ntohl(addpath_id
);
5959 pnt
+= BGP_ADDPATH_ID_LEN
;
5962 /* Fetch prefix length. */
5963 p
.prefixlen
= *pnt
++;
5964 /* afi/safi validity already verified by caller,
5965 * bgp_update_receive */
5966 p
.family
= afi2family(afi
);
5968 /* Prefix length check. */
5969 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
5972 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5973 peer
->host
, p
.prefixlen
, packet
->afi
);
5974 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
5977 /* Packet size overflow check. */
5978 psize
= PSIZE(p
.prefixlen
);
5980 /* When packet overflow occur return immediately. */
5981 if (pnt
+ psize
> lim
) {
5984 "%s [Error] Update packet error (prefix length %d overflows packet)",
5985 peer
->host
, p
.prefixlen
);
5986 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5989 /* Defensive coding, double-check the psize fits in a struct
5990 * prefix for the v4 and v6 afi's and unicast/multicast */
5991 if (psize
> (ssize_t
)sizeof(p
.u
.val
)) {
5994 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5995 peer
->host
, p
.prefixlen
, sizeof(p
.u
.val
));
5996 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5999 /* Fetch prefix from NLRI packet. */
6000 memcpy(p
.u
.val
, pnt
, psize
);
6002 /* Check address. */
6003 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
6004 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
6005 /* From RFC4271 Section 6.3:
6007 * If a prefix in the NLRI field is semantically
6009 * (e.g., an unexpected multicast IP address),
6011 * be logged locally, and the prefix SHOULD be
6016 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6017 peer
->host
, &p
.u
.prefix4
);
6022 /* Check address. */
6023 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
6024 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6027 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6028 peer
->host
, &p
.u
.prefix6
);
6032 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
6035 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6036 peer
->host
, &p
.u
.prefix6
);
6042 /* Normal process. */
6044 bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
6045 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
,
6048 bgp_withdraw(peer
, &p
, addpath_id
, afi
, safi
,
6049 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
,
6052 /* Do not send BGP notification twice when maximum-prefix count
6054 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
6055 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
6058 /* Packet length consistency check. */
6062 "%s [Error] Update packet error (prefix length mismatch with total length)",
6064 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6067 return BGP_NLRI_PARSE_OK
;
6070 static struct bgp_static
*bgp_static_new(void)
6072 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
6075 static void bgp_static_free(struct bgp_static
*bgp_static
)
6077 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6078 route_map_counter_decrement(bgp_static
->rmap
.map
);
6080 if (bgp_static
->prd_pretty
)
6081 XFREE(MTYPE_BGP
, bgp_static
->prd_pretty
);
6082 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
6083 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
6086 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
6087 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
6089 struct bgp_dest
*dest
;
6090 struct bgp_path_info
*pi
;
6091 struct bgp_path_info
*new;
6092 struct bgp_path_info rmap_path
;
6094 struct attr
*attr_new
;
6095 route_map_result_t ret
;
6096 #ifdef ENABLE_BGP_VNC
6097 int vnc_implicit_withdraw
= 0;
6102 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6104 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6106 attr
.nexthop
= bgp_static
->igpnexthop
;
6107 attr
.med
= bgp_static
->igpmetric
;
6108 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6111 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
6113 if (bgp_static
->igpmetric
)
6114 bgp_attr_set_aigp_metric(&attr
, bgp_static
->igpmetric
);
6116 if (bgp_static
->atomic
)
6117 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
6119 /* Store label index, if required. */
6120 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
6121 attr
.label_index
= bgp_static
->label_index
;
6122 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
6125 /* Apply route-map. */
6126 if (bgp_static
->rmap
.name
) {
6127 struct attr attr_tmp
= attr
;
6129 memset(&rmap_path
, 0, sizeof(rmap_path
));
6130 rmap_path
.peer
= bgp
->peer_self
;
6131 rmap_path
.attr
= &attr_tmp
;
6133 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6135 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6137 bgp
->peer_self
->rmap_type
= 0;
6139 if (ret
== RMAP_DENYMATCH
) {
6140 /* Free uninterned attribute. */
6141 bgp_attr_flush(&attr_tmp
);
6143 /* Unintern original. */
6144 aspath_unintern(&attr
.aspath
);
6145 bgp_static_withdraw(bgp
, p
, afi
, safi
);
6146 bgp_dest_unlock_node(dest
);
6150 if (bgp_in_graceful_shutdown(bgp
))
6151 bgp_attr_add_gshut_community(&attr_tmp
);
6153 attr_new
= bgp_attr_intern(&attr_tmp
);
6156 if (bgp_in_graceful_shutdown(bgp
))
6157 bgp_attr_add_gshut_community(&attr
);
6159 attr_new
= bgp_attr_intern(&attr
);
6162 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6163 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6164 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6168 if (attrhash_cmp(pi
->attr
, attr_new
)
6169 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
6170 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
6171 bgp_dest_unlock_node(dest
);
6172 bgp_attr_unintern(&attr_new
);
6173 aspath_unintern(&attr
.aspath
);
6176 /* The attribute is changed. */
6177 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6179 /* Rewrite BGP route information. */
6180 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6181 bgp_path_info_restore(dest
, pi
);
6183 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6184 #ifdef ENABLE_BGP_VNC
6185 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6186 && (safi
== SAFI_UNICAST
)) {
6187 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
6189 * Implicit withdraw case.
6190 * We have to do this before pi is
6193 ++vnc_implicit_withdraw
;
6194 vnc_import_bgp_del_route(bgp
, p
, pi
);
6195 vnc_import_bgp_exterior_del_route(
6200 bgp_attr_unintern(&pi
->attr
);
6201 pi
->attr
= attr_new
;
6202 pi
->uptime
= monotime(NULL
);
6203 #ifdef ENABLE_BGP_VNC
6204 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6205 && (safi
== SAFI_UNICAST
)) {
6206 if (vnc_implicit_withdraw
) {
6207 vnc_import_bgp_add_route(bgp
, p
, pi
);
6208 vnc_import_bgp_exterior_add_route(
6214 /* Nexthop reachability check. */
6215 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6216 && (safi
== SAFI_UNICAST
6217 || safi
== SAFI_LABELED_UNICAST
)) {
6219 struct bgp
*bgp_nexthop
= bgp
;
6221 if (pi
->extra
&& pi
->extra
->bgp_orig
)
6222 bgp_nexthop
= pi
->extra
->bgp_orig
;
6224 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
6225 afi
, safi
, pi
, NULL
,
6227 bgp_path_info_set_flag(dest
, pi
,
6230 if (BGP_DEBUG(nht
, NHT
)) {
6231 char buf1
[INET6_ADDRSTRLEN
];
6232 inet_ntop(p
->family
,
6236 "%s(%s): Route not in table, not advertising",
6239 bgp_path_info_unset_flag(
6240 dest
, pi
, BGP_PATH_VALID
);
6243 /* Delete the NHT structure if any, if we're
6245 * enabling/disabling import check. We
6246 * deregister the route
6247 * from NHT to avoid overloading NHT and the
6248 * process interaction
6250 bgp_unlink_nexthop(pi
);
6251 bgp_path_info_set_flag(dest
, pi
,
6254 /* Process change. */
6255 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6256 bgp_process(bgp
, dest
, afi
, safi
);
6258 if (SAFI_UNICAST
== safi
6259 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6261 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6262 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
6266 bgp_dest_unlock_node(dest
);
6267 aspath_unintern(&attr
.aspath
);
6272 /* Make new BGP info. */
6273 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6275 /* Nexthop reachability check. */
6276 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6277 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
6278 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0,
6280 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6282 if (BGP_DEBUG(nht
, NHT
)) {
6283 char buf1
[INET6_ADDRSTRLEN
];
6285 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
6288 "%s(%s): Route not in table, not advertising",
6291 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
6294 /* Delete the NHT structure if any, if we're toggling between
6295 * enabling/disabling import check. We deregister the route
6296 * from NHT to avoid overloading NHT and the process interaction
6298 bgp_unlink_nexthop(new);
6300 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6303 /* Aggregate address increment. */
6304 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6306 /* Register new BGP information. */
6307 bgp_path_info_add(dest
, new);
6309 /* route_node_get lock */
6310 bgp_dest_unlock_node(dest
);
6312 /* Process change. */
6313 bgp_process(bgp
, dest
, afi
, safi
);
6315 if (SAFI_UNICAST
== safi
6316 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6317 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6318 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6321 /* Unintern original. */
6322 aspath_unintern(&attr
.aspath
);
6325 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6328 struct bgp_dest
*dest
;
6329 struct bgp_path_info
*pi
;
6331 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6333 /* Check selected route and self inserted route. */
6334 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6335 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6336 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6339 /* Withdraw static BGP route from routing table. */
6341 if (SAFI_UNICAST
== safi
6342 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6343 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6344 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
6346 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6347 bgp_unlink_nexthop(pi
);
6348 bgp_path_info_delete(dest
, pi
);
6349 bgp_process(bgp
, dest
, afi
, safi
);
6352 /* Unlock bgp_node_lookup. */
6353 bgp_dest_unlock_node(dest
);
6357 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6359 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
6360 afi_t afi
, safi_t safi
,
6361 struct prefix_rd
*prd
)
6363 struct bgp_dest
*dest
;
6364 struct bgp_path_info
*pi
;
6366 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
6368 /* Check selected route and self inserted route. */
6369 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6370 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6371 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6374 /* Withdraw static BGP route from routing table. */
6376 #ifdef ENABLE_BGP_VNC
6377 rfapiProcessWithdraw(
6378 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
6379 1); /* Kill, since it is an administrative change */
6381 if (SAFI_MPLS_VPN
== safi
6382 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6383 vpn_leak_to_vrf_withdraw(pi
);
6385 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6386 bgp_path_info_delete(dest
, pi
);
6387 bgp_process(bgp
, dest
, afi
, safi
);
6390 /* Unlock bgp_node_lookup. */
6391 bgp_dest_unlock_node(dest
);
6394 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
6395 struct bgp_static
*bgp_static
, afi_t afi
,
6398 struct bgp_dest
*dest
;
6399 struct bgp_path_info
*new;
6400 struct attr
*attr_new
;
6401 struct attr attr
= {0};
6402 struct bgp_path_info
*pi
;
6403 #ifdef ENABLE_BGP_VNC
6404 mpls_label_t label
= 0;
6406 uint32_t num_labels
= 0;
6410 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
6412 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
6415 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6417 attr
.nexthop
= bgp_static
->igpnexthop
;
6418 attr
.med
= bgp_static
->igpmetric
;
6419 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6421 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
6422 || (safi
== SAFI_ENCAP
)) {
6423 if (afi
== AFI_IP
) {
6424 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
6425 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
6428 if (afi
== AFI_L2VPN
) {
6429 if (bgp_static
->gatewayIp
.family
== AF_INET
) {
6430 SET_IPADDR_V4(&attr
.evpn_overlay
.gw_ip
);
6431 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v4
,
6432 &bgp_static
->gatewayIp
.u
.prefix4
,
6434 } else if (bgp_static
->gatewayIp
.family
== AF_INET6
) {
6435 SET_IPADDR_V6(&attr
.evpn_overlay
.gw_ip
);
6436 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v6
,
6437 &bgp_static
->gatewayIp
.u
.prefix6
,
6440 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
6441 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
6442 struct bgp_encap_type_vxlan bet
;
6443 memset(&bet
, 0, sizeof(bet
));
6444 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
6445 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
6447 if (bgp_static
->router_mac
) {
6448 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
6451 /* Apply route-map. */
6452 if (bgp_static
->rmap
.name
) {
6453 struct attr attr_tmp
= attr
;
6454 struct bgp_path_info rmap_path
;
6455 route_map_result_t ret
;
6457 rmap_path
.peer
= bgp
->peer_self
;
6458 rmap_path
.attr
= &attr_tmp
;
6460 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6462 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6464 bgp
->peer_self
->rmap_type
= 0;
6466 if (ret
== RMAP_DENYMATCH
) {
6467 /* Free uninterned attribute. */
6468 bgp_attr_flush(&attr_tmp
);
6470 /* Unintern original. */
6471 aspath_unintern(&attr
.aspath
);
6472 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
6474 bgp_dest_unlock_node(dest
);
6478 attr_new
= bgp_attr_intern(&attr_tmp
);
6480 attr_new
= bgp_attr_intern(&attr
);
6483 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6484 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6485 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6489 if (attrhash_cmp(pi
->attr
, attr_new
)
6490 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
6491 bgp_dest_unlock_node(dest
);
6492 bgp_attr_unintern(&attr_new
);
6493 aspath_unintern(&attr
.aspath
);
6496 /* The attribute is changed. */
6497 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6499 /* Rewrite BGP route information. */
6500 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6501 bgp_path_info_restore(dest
, pi
);
6503 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6504 bgp_attr_unintern(&pi
->attr
);
6505 pi
->attr
= attr_new
;
6506 pi
->uptime
= monotime(NULL
);
6507 #ifdef ENABLE_BGP_VNC
6509 label
= decode_label(&pi
->extra
->label
[0]);
6512 /* Process change. */
6513 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6514 bgp_process(bgp
, dest
, afi
, safi
);
6516 if (SAFI_MPLS_VPN
== safi
6517 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6518 vpn_leak_to_vrf_update(bgp
, pi
,
6521 #ifdef ENABLE_BGP_VNC
6522 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
6523 pi
->attr
, afi
, safi
, pi
->type
,
6524 pi
->sub_type
, &label
);
6526 bgp_dest_unlock_node(dest
);
6527 aspath_unintern(&attr
.aspath
);
6533 /* Make new BGP info. */
6534 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6536 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6537 bgp_path_info_extra_get(new);
6539 new->extra
->label
[0] = bgp_static
->label
;
6540 new->extra
->num_labels
= num_labels
;
6542 #ifdef ENABLE_BGP_VNC
6543 label
= decode_label(&bgp_static
->label
);
6546 /* Aggregate address increment. */
6547 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6549 /* Register new BGP information. */
6550 bgp_path_info_add(dest
, new);
6551 /* route_node_get lock */
6552 bgp_dest_unlock_node(dest
);
6554 /* Process change. */
6555 bgp_process(bgp
, dest
, afi
, safi
);
6557 if (SAFI_MPLS_VPN
== safi
6558 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6559 vpn_leak_to_vrf_update(bgp
, new, &bgp_static
->prd
);
6561 #ifdef ENABLE_BGP_VNC
6562 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6563 safi
, new->type
, new->sub_type
, &label
);
6566 /* Unintern original. */
6567 aspath_unintern(&attr
.aspath
);
6570 /* Configure static BGP network. When user don't run zebra, static
6571 route should be installed as valid. */
6572 static int bgp_static_set(struct vty
*vty
, const char *negate
,
6573 const char *ip_str
, afi_t afi
, safi_t safi
,
6574 const char *rmap
, int backdoor
, uint32_t label_index
)
6576 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6579 struct bgp_static
*bgp_static
;
6580 struct bgp_dest
*dest
;
6581 uint8_t need_update
= 0;
6583 /* Convert IP prefix string to struct prefix. */
6584 ret
= str2prefix(ip_str
, &p
);
6586 vty_out(vty
, "%% Malformed prefix\n");
6587 return CMD_WARNING_CONFIG_FAILED
;
6589 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6590 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
6591 return CMD_WARNING_CONFIG_FAILED
;
6598 /* Set BGP static route configuration. */
6599 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6602 vty_out(vty
, "%% Can't find static route specified\n");
6603 return CMD_WARNING_CONFIG_FAILED
;
6606 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6608 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6609 && (label_index
!= bgp_static
->label_index
)) {
6611 "%% label-index doesn't match static route\n");
6612 bgp_dest_unlock_node(dest
);
6613 return CMD_WARNING_CONFIG_FAILED
;
6616 if ((rmap
&& bgp_static
->rmap
.name
)
6617 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6619 "%% route-map name doesn't match static route\n");
6620 bgp_dest_unlock_node(dest
);
6621 return CMD_WARNING_CONFIG_FAILED
;
6624 /* Update BGP RIB. */
6625 if (!bgp_static
->backdoor
)
6626 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6628 /* Clear configuration. */
6629 bgp_static_free(bgp_static
);
6630 bgp_dest_set_bgp_static_info(dest
, NULL
);
6631 bgp_dest_unlock_node(dest
);
6632 bgp_dest_unlock_node(dest
);
6635 /* Set BGP static route configuration. */
6636 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6637 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6639 /* Configuration change. */
6640 /* Label index cannot be changed. */
6641 if (bgp_static
->label_index
!= label_index
) {
6642 vty_out(vty
, "%% cannot change label-index\n");
6643 bgp_dest_unlock_node(dest
);
6644 return CMD_WARNING_CONFIG_FAILED
;
6647 /* Check previous routes are installed into BGP. */
6648 if (bgp_static
->valid
6649 && bgp_static
->backdoor
!= backdoor
)
6652 bgp_static
->backdoor
= backdoor
;
6655 XFREE(MTYPE_ROUTE_MAP_NAME
,
6656 bgp_static
->rmap
.name
);
6657 route_map_counter_decrement(
6658 bgp_static
->rmap
.map
);
6659 bgp_static
->rmap
.name
=
6660 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6661 bgp_static
->rmap
.map
=
6662 route_map_lookup_by_name(rmap
);
6663 route_map_counter_increment(
6664 bgp_static
->rmap
.map
);
6666 XFREE(MTYPE_ROUTE_MAP_NAME
,
6667 bgp_static
->rmap
.name
);
6668 route_map_counter_decrement(
6669 bgp_static
->rmap
.map
);
6670 bgp_static
->rmap
.map
= NULL
;
6671 bgp_static
->valid
= 0;
6673 bgp_dest_unlock_node(dest
);
6675 /* New configuration. */
6676 bgp_static
= bgp_static_new();
6677 bgp_static
->backdoor
= backdoor
;
6678 bgp_static
->valid
= 0;
6679 bgp_static
->igpmetric
= 0;
6680 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6681 bgp_static
->label_index
= label_index
;
6684 XFREE(MTYPE_ROUTE_MAP_NAME
,
6685 bgp_static
->rmap
.name
);
6686 route_map_counter_decrement(
6687 bgp_static
->rmap
.map
);
6688 bgp_static
->rmap
.name
=
6689 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6690 bgp_static
->rmap
.map
=
6691 route_map_lookup_by_name(rmap
);
6692 route_map_counter_increment(
6693 bgp_static
->rmap
.map
);
6695 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6698 bgp_static
->valid
= 1;
6700 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6702 if (!bgp_static
->backdoor
)
6703 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6709 void bgp_static_add(struct bgp
*bgp
)
6713 struct bgp_dest
*dest
;
6714 struct bgp_dest
*rm
;
6715 struct bgp_table
*table
;
6716 struct bgp_static
*bgp_static
;
6718 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6719 FOREACH_AFI_SAFI (afi
, safi
)
6720 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6721 dest
= bgp_route_next(dest
)) {
6722 if (!bgp_dest_has_bgp_path_info_data(dest
))
6725 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6726 || (safi
== SAFI_EVPN
)) {
6727 table
= bgp_dest_get_bgp_table_info(dest
);
6729 for (rm
= bgp_table_top(table
); rm
;
6730 rm
= bgp_route_next(rm
)) {
6732 bgp_dest_get_bgp_static_info(
6734 bgp_static_update_safi(
6735 bgp
, bgp_dest_get_prefix(rm
),
6736 bgp_static
, afi
, safi
);
6740 bgp
, bgp_dest_get_prefix(dest
),
6741 bgp_dest_get_bgp_static_info(dest
), afi
,
6745 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6748 /* Called from bgp_delete(). Delete all static routes from the BGP
6750 void bgp_static_delete(struct bgp
*bgp
)
6754 struct bgp_dest
*dest
;
6755 struct bgp_dest
*rm
;
6756 struct bgp_table
*table
;
6757 struct bgp_static
*bgp_static
;
6759 FOREACH_AFI_SAFI (afi
, safi
)
6760 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6761 dest
= bgp_route_next(dest
)) {
6762 if (!bgp_dest_has_bgp_path_info_data(dest
))
6765 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6766 || (safi
== SAFI_EVPN
)) {
6767 table
= bgp_dest_get_bgp_table_info(dest
);
6769 for (rm
= bgp_table_top(table
); rm
;
6770 rm
= bgp_route_next(rm
)) {
6772 bgp_dest_get_bgp_static_info(
6777 bgp_static_withdraw_safi(
6778 bgp
, bgp_dest_get_prefix(rm
),
6780 (struct prefix_rd
*)
6781 bgp_dest_get_prefix(
6783 bgp_static_free(bgp_static
);
6784 bgp_dest_set_bgp_static_info(rm
,
6786 bgp_dest_unlock_node(rm
);
6789 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6790 bgp_static_withdraw(bgp
,
6791 bgp_dest_get_prefix(dest
),
6793 bgp_static_free(bgp_static
);
6794 bgp_dest_set_bgp_static_info(dest
, NULL
);
6795 bgp_dest_unlock_node(dest
);
6800 void bgp_static_redo_import_check(struct bgp
*bgp
)
6804 struct bgp_dest
*dest
;
6805 struct bgp_dest
*rm
;
6806 struct bgp_table
*table
;
6807 struct bgp_static
*bgp_static
;
6809 /* Use this flag to force reprocessing of the route */
6810 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6811 FOREACH_AFI_SAFI (afi
, safi
) {
6812 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6813 dest
= bgp_route_next(dest
)) {
6814 if (!bgp_dest_has_bgp_path_info_data(dest
))
6817 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6818 || (safi
== SAFI_EVPN
)) {
6819 table
= bgp_dest_get_bgp_table_info(dest
);
6821 for (rm
= bgp_table_top(table
); rm
;
6822 rm
= bgp_route_next(rm
)) {
6824 bgp_dest_get_bgp_static_info(
6826 bgp_static_update_safi(
6827 bgp
, bgp_dest_get_prefix(rm
),
6828 bgp_static
, afi
, safi
);
6831 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6832 bgp_static_update(bgp
,
6833 bgp_dest_get_prefix(dest
),
6834 bgp_static
, afi
, safi
);
6838 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6841 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6844 struct bgp_table
*table
;
6845 struct bgp_dest
*dest
;
6846 struct bgp_path_info
*pi
;
6848 /* Do not install the aggregate route if BGP is in the
6849 * process of termination.
6851 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6852 || (bgp
->peer_self
== NULL
))
6855 table
= bgp
->rib
[afi
][safi
];
6856 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6857 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6858 if (pi
->peer
== bgp
->peer_self
6859 && ((pi
->type
== ZEBRA_ROUTE_BGP
6860 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6861 || (pi
->type
!= ZEBRA_ROUTE_BGP
6863 == BGP_ROUTE_REDISTRIBUTE
))) {
6864 bgp_aggregate_decrement(
6865 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6867 bgp_unlink_nexthop(pi
);
6868 bgp_path_info_delete(dest
, pi
);
6869 bgp_process(bgp
, dest
, afi
, safi
);
6876 * Purge all networks and redistributed routes from routing table.
6877 * Invoked upon the instance going down.
6879 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6884 FOREACH_AFI_SAFI (afi
, safi
)
6885 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6890 * Currently this is used to set static routes for VPN and ENCAP.
6891 * I think it can probably be factored with bgp_static_set.
6893 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6894 const char *ip_str
, const char *rd_str
,
6895 const char *label_str
, const char *rmap_str
,
6896 int evpn_type
, const char *esi
, const char *gwip
,
6897 const char *ethtag
, const char *routermac
)
6899 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6902 struct prefix_rd prd
;
6903 struct bgp_dest
*pdest
;
6904 struct bgp_dest
*dest
;
6905 struct bgp_table
*table
;
6906 struct bgp_static
*bgp_static
;
6907 mpls_label_t label
= MPLS_INVALID_LABEL
;
6908 struct prefix gw_ip
;
6910 /* validate ip prefix */
6911 ret
= str2prefix(ip_str
, &p
);
6913 vty_out(vty
, "%% Malformed prefix\n");
6914 return CMD_WARNING_CONFIG_FAILED
;
6917 if ((afi
== AFI_L2VPN
)
6918 && (bgp_build_evpn_prefix(evpn_type
,
6919 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6920 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6921 return CMD_WARNING_CONFIG_FAILED
;
6924 ret
= str2prefix_rd(rd_str
, &prd
);
6926 vty_out(vty
, "%% Malformed rd\n");
6927 return CMD_WARNING_CONFIG_FAILED
;
6931 unsigned long label_val
;
6932 label_val
= strtoul(label_str
, NULL
, 10);
6933 encode_label(label_val
, &label
);
6936 if (safi
== SAFI_EVPN
) {
6937 if (esi
&& str2esi(esi
, NULL
) == 0) {
6938 vty_out(vty
, "%% Malformed ESI\n");
6939 return CMD_WARNING_CONFIG_FAILED
;
6941 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6942 vty_out(vty
, "%% Malformed Router MAC\n");
6943 return CMD_WARNING_CONFIG_FAILED
;
6946 memset(&gw_ip
, 0, sizeof(gw_ip
));
6947 ret
= str2prefix(gwip
, &gw_ip
);
6949 vty_out(vty
, "%% Malformed GatewayIp\n");
6950 return CMD_WARNING_CONFIG_FAILED
;
6952 if ((gw_ip
.family
== AF_INET
6953 && is_evpn_prefix_ipaddr_v6(
6954 (struct prefix_evpn
*)&p
))
6955 || (gw_ip
.family
== AF_INET6
6956 && is_evpn_prefix_ipaddr_v4(
6957 (struct prefix_evpn
*)&p
))) {
6959 "%% GatewayIp family differs with IP prefix\n");
6960 return CMD_WARNING_CONFIG_FAILED
;
6964 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6965 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6966 bgp_dest_set_bgp_table_info(pdest
,
6967 bgp_table_init(bgp
, afi
, safi
));
6968 table
= bgp_dest_get_bgp_table_info(pdest
);
6970 dest
= bgp_node_get(table
, &p
);
6972 if (bgp_dest_has_bgp_path_info_data(dest
)) {
6973 vty_out(vty
, "%% Same network configuration exists\n");
6974 bgp_dest_unlock_node(dest
);
6976 /* New configuration. */
6977 bgp_static
= bgp_static_new();
6978 bgp_static
->backdoor
= 0;
6979 bgp_static
->valid
= 0;
6980 bgp_static
->igpmetric
= 0;
6981 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6982 bgp_static
->label
= label
;
6983 bgp_static
->prd
= prd
;
6986 bgp_static
->prd_pretty
= XSTRDUP(MTYPE_BGP
, rd_str
);
6988 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6989 route_map_counter_decrement(bgp_static
->rmap
.map
);
6990 bgp_static
->rmap
.name
=
6991 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
6992 bgp_static
->rmap
.map
=
6993 route_map_lookup_by_name(rmap_str
);
6994 route_map_counter_increment(bgp_static
->rmap
.map
);
6997 if (safi
== SAFI_EVPN
) {
6999 bgp_static
->eth_s_id
=
7002 str2esi(esi
, bgp_static
->eth_s_id
);
7005 bgp_static
->router_mac
=
7006 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
7007 (void)prefix_str2mac(routermac
,
7008 bgp_static
->router_mac
);
7011 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
7013 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
7015 bgp_static
->valid
= 1;
7016 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
7022 /* Configure static BGP network. */
7023 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
7024 const char *ip_str
, const char *rd_str
,
7025 const char *label_str
, int evpn_type
, const char *esi
,
7026 const char *gwip
, const char *ethtag
)
7028 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7031 struct prefix_rd prd
;
7032 struct bgp_dest
*pdest
;
7033 struct bgp_dest
*dest
;
7034 struct bgp_table
*table
;
7035 struct bgp_static
*bgp_static
;
7036 mpls_label_t label
= MPLS_INVALID_LABEL
;
7038 /* Convert IP prefix string to struct prefix. */
7039 ret
= str2prefix(ip_str
, &p
);
7041 vty_out(vty
, "%% Malformed prefix\n");
7042 return CMD_WARNING_CONFIG_FAILED
;
7045 if ((afi
== AFI_L2VPN
)
7046 && (bgp_build_evpn_prefix(evpn_type
,
7047 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
7048 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
7049 return CMD_WARNING_CONFIG_FAILED
;
7051 ret
= str2prefix_rd(rd_str
, &prd
);
7053 vty_out(vty
, "%% Malformed rd\n");
7054 return CMD_WARNING_CONFIG_FAILED
;
7058 unsigned long label_val
;
7059 label_val
= strtoul(label_str
, NULL
, 10);
7060 encode_label(label_val
, &label
);
7063 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7064 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7065 bgp_dest_set_bgp_table_info(pdest
,
7066 bgp_table_init(bgp
, afi
, safi
));
7068 bgp_dest_unlock_node(pdest
);
7069 table
= bgp_dest_get_bgp_table_info(pdest
);
7071 dest
= bgp_node_lookup(table
, &p
);
7074 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
7076 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
7077 bgp_static_free(bgp_static
);
7078 bgp_dest_set_bgp_static_info(dest
, NULL
);
7079 bgp_dest_unlock_node(dest
);
7080 bgp_dest_unlock_node(dest
);
7082 vty_out(vty
, "%% Can't find the route\n");
7087 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
7088 const char *rmap_name
)
7090 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7091 struct bgp_rmap
*rmap
;
7093 rmap
= &bgp
->table_map
[afi
][safi
];
7095 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7096 route_map_counter_decrement(rmap
->map
);
7097 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
7098 rmap
->map
= route_map_lookup_by_name(rmap_name
);
7099 route_map_counter_increment(rmap
->map
);
7101 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7102 route_map_counter_decrement(rmap
->map
);
7106 if (bgp_fibupd_safi(safi
))
7107 bgp_zebra_announce_table(bgp
, afi
, safi
);
7112 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
7113 const char *rmap_name
)
7115 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7116 struct bgp_rmap
*rmap
;
7118 rmap
= &bgp
->table_map
[afi
][safi
];
7119 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7120 route_map_counter_decrement(rmap
->map
);
7123 if (bgp_fibupd_safi(safi
))
7124 bgp_zebra_announce_table(bgp
, afi
, safi
);
7129 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
7132 if (bgp
->table_map
[afi
][safi
].name
) {
7133 vty_out(vty
, " table-map %s\n",
7134 bgp
->table_map
[afi
][safi
].name
);
7138 DEFUN (bgp_table_map
,
7141 "BGP table to RIB route download filter\n"
7142 "Name of the route map\n")
7145 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7146 argv
[idx_word
]->arg
);
7148 DEFUN (no_bgp_table_map
,
7149 no_bgp_table_map_cmd
,
7150 "no table-map WORD",
7152 "BGP table to RIB route download filter\n"
7153 "Name of the route map\n")
7156 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7157 argv
[idx_word
]->arg
);
7163 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
7164 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
7165 backdoor$backdoor}]",
7167 "Specify a network to announce via BGP\n"
7172 "Route-map to modify the attributes\n"
7173 "Name of the route map\n"
7174 "Label index to associate with the prefix\n"
7175 "Label index value\n"
7176 "Specify a BGP backdoor route\n")
7178 char addr_prefix_str
[BUFSIZ
];
7183 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
7185 sizeof(addr_prefix_str
));
7187 vty_out(vty
, "%% Inconsistent address and mask\n");
7188 return CMD_WARNING_CONFIG_FAILED
;
7192 return bgp_static_set(
7193 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
7194 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
7195 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7198 DEFPY(ipv6_bgp_network
,
7199 ipv6_bgp_network_cmd
,
7200 "[no] network X:X::X:X/M$prefix \
7201 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
7203 "Specify a network to announce via BGP\n"
7205 "Route-map to modify the attributes\n"
7206 "Name of the route map\n"
7207 "Label index to associate with the prefix\n"
7208 "Label index value\n")
7210 return bgp_static_set(
7211 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
7212 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7215 static struct bgp_aggregate
*bgp_aggregate_new(void)
7217 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
7220 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
7222 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7223 route_map_counter_decrement(aggregate
->suppress_map
);
7224 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7225 route_map_counter_decrement(aggregate
->rmap
.map
);
7226 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
7230 * Helper function to avoid repeated code: prepare variables for a
7231 * `route_map_apply` call.
7233 * \returns `true` on route map match, otherwise `false`.
7235 static bool aggr_suppress_map_test(struct bgp
*bgp
,
7236 struct bgp_aggregate
*aggregate
,
7237 struct bgp_path_info
*pi
)
7239 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
7240 route_map_result_t rmr
= RMAP_DENYMATCH
;
7241 struct bgp_path_info rmap_path
= {};
7242 struct attr attr
= {};
7244 /* No route map entries created, just don't match. */
7245 if (aggregate
->suppress_map
== NULL
)
7248 /* Call route map matching and return result. */
7249 attr
.aspath
= aspath_empty(bgp
->asnotation
);
7250 rmap_path
.peer
= bgp
->peer_self
;
7251 rmap_path
.attr
= &attr
;
7253 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
7254 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
7255 bgp
->peer_self
->rmap_type
= 0;
7257 bgp_attr_flush(&attr
);
7258 aspath_unintern(&attr
.aspath
);
7260 return rmr
== RMAP_PERMITMATCH
;
7263 /** Test whether the aggregation has suppressed this path or not. */
7264 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
7265 struct bgp_path_info
*pi
)
7267 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
7270 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
7274 * Suppress this path and keep the reference.
7276 * \returns `true` if needs processing otherwise `false`.
7278 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
7279 struct bgp_path_info
*pi
)
7281 struct bgp_path_info_extra
*pie
;
7283 /* Path is already suppressed by this aggregation. */
7284 if (aggr_suppress_exists(aggregate
, pi
))
7287 pie
= bgp_path_info_extra_get(pi
);
7289 /* This is the first suppression, allocate memory and list it. */
7290 if (pie
->aggr_suppressors
== NULL
)
7291 pie
->aggr_suppressors
= list_new();
7293 listnode_add(pie
->aggr_suppressors
, aggregate
);
7295 /* Only mark for processing if suppressed. */
7296 if (listcount(pie
->aggr_suppressors
) == 1) {
7297 if (BGP_DEBUG(update
, UPDATE_OUT
))
7298 zlog_debug("aggregate-address suppressing: %pFX",
7299 bgp_dest_get_prefix(pi
->net
));
7301 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7309 * Unsuppress this path and remove the reference.
7311 * \returns `true` if needs processing otherwise `false`.
7313 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
7314 struct bgp_path_info
*pi
)
7316 /* Path wasn't suppressed. */
7317 if (!aggr_suppress_exists(aggregate
, pi
))
7320 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
7322 /* Unsuppress and free extra memory if last item. */
7323 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
7324 if (BGP_DEBUG(update
, UPDATE_OUT
))
7325 zlog_debug("aggregate-address unsuppressing: %pFX",
7326 bgp_dest_get_prefix(pi
->net
));
7328 list_delete(&pi
->extra
->aggr_suppressors
);
7329 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7336 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
7337 struct aspath
*aspath
,
7338 struct community
*comm
,
7339 struct ecommunity
*ecomm
,
7340 struct lcommunity
*lcomm
)
7342 static struct aspath
*ae
= NULL
;
7343 enum asnotation_mode asnotation
;
7345 asnotation
= bgp_get_asnotation(NULL
);
7348 ae
= aspath_empty(asnotation
);
7353 if (origin
!= pi
->attr
->origin
)
7356 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
7359 if (!community_cmp(bgp_attr_get_community(pi
->attr
), comm
))
7362 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi
->attr
), ecomm
))
7365 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi
->attr
), lcomm
))
7368 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
7374 static void bgp_aggregate_install(
7375 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
7376 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
7377 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
7378 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
7380 struct bgp_dest
*dest
;
7381 struct bgp_table
*table
;
7382 struct bgp_path_info
*pi
, *orig
, *new;
7385 table
= bgp
->rib
[afi
][safi
];
7387 dest
= bgp_node_get(table
, p
);
7389 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7390 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
7391 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7395 * If we have paths with different MEDs, then don't install
7396 * (or uninstall) the aggregate route.
7398 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
7399 goto uninstall_aggregate_route
;
7401 if (aggregate
->count
> 0) {
7403 * If the aggregate information has not changed
7404 * no need to re-install it again.
7406 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
7407 ecommunity
, lcommunity
)) {
7408 bgp_dest_unlock_node(dest
);
7411 aspath_free(aspath
);
7413 community_free(&community
);
7415 ecommunity_free(&ecommunity
);
7417 lcommunity_free(&lcommunity
);
7423 * Mark the old as unusable
7426 bgp_path_info_delete(dest
, pi
);
7428 attr
= bgp_attr_aggregate_intern(
7429 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
7430 aggregate
, atomic_aggregate
, p
);
7433 bgp_dest_unlock_node(dest
);
7434 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
7435 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
7436 zlog_debug("%s: %pFX null attribute", __func__
,
7441 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
7442 bgp
->peer_self
, attr
, dest
);
7444 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7446 bgp_path_info_add(dest
, new);
7447 bgp_process(bgp
, dest
, afi
, safi
);
7449 uninstall_aggregate_route
:
7450 for (pi
= orig
; pi
; pi
= pi
->next
)
7451 if (pi
->peer
== bgp
->peer_self
7452 && pi
->type
== ZEBRA_ROUTE_BGP
7453 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7456 /* Withdraw static BGP route from routing table. */
7458 bgp_path_info_delete(dest
, pi
);
7459 bgp_process(bgp
, dest
, afi
, safi
);
7463 bgp_dest_unlock_node(dest
);
7467 * Check if the current path has different MED than other known paths.
7469 * \returns `true` if the MED matched the others else `false`.
7471 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
7472 struct bgp
*bgp
, struct bgp_path_info
*pi
)
7474 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
7476 /* This is the first route being analyzed. */
7477 if (!aggregate
->med_initialized
) {
7478 aggregate
->med_initialized
= true;
7479 aggregate
->med_mismatched
= false;
7480 aggregate
->med_matched_value
= cur_med
;
7482 /* Check if routes with different MED showed up. */
7483 if (cur_med
!= aggregate
->med_matched_value
)
7484 aggregate
->med_mismatched
= true;
7487 return !aggregate
->med_mismatched
;
7491 * Initializes and tests all routes in the aggregate address path for MED
7494 * \returns `true` if all MEDs are the same otherwise `false`.
7496 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
7497 struct bgp
*bgp
, const struct prefix
*p
,
7498 afi_t afi
, safi_t safi
)
7500 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7501 const struct prefix
*dest_p
;
7502 struct bgp_dest
*dest
, *top
;
7503 struct bgp_path_info
*pi
;
7504 bool med_matched
= true;
7506 aggregate
->med_initialized
= false;
7508 top
= bgp_node_get(table
, p
);
7509 for (dest
= bgp_node_get(table
, p
); dest
;
7510 dest
= bgp_route_next_until(dest
, top
)) {
7511 dest_p
= bgp_dest_get_prefix(dest
);
7512 if (dest_p
->prefixlen
<= p
->prefixlen
)
7515 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7516 if (BGP_PATH_HOLDDOWN(pi
))
7518 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7520 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
7521 med_matched
= false;
7528 bgp_dest_unlock_node(top
);
7534 * Toggles the route suppression status for this aggregate address
7537 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
7538 struct bgp
*bgp
, const struct prefix
*p
,
7539 afi_t afi
, safi_t safi
, bool suppress
)
7541 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7542 const struct prefix
*dest_p
;
7543 struct bgp_dest
*dest
, *top
;
7544 struct bgp_path_info
*pi
;
7545 bool toggle_suppression
;
7547 /* We've found a different MED we must revert any suppressed routes. */
7548 top
= bgp_node_get(table
, p
);
7549 for (dest
= bgp_node_get(table
, p
); dest
;
7550 dest
= bgp_route_next_until(dest
, top
)) {
7551 dest_p
= bgp_dest_get_prefix(dest
);
7552 if (dest_p
->prefixlen
<= p
->prefixlen
)
7555 toggle_suppression
= false;
7556 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7557 if (BGP_PATH_HOLDDOWN(pi
))
7559 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7562 /* We are toggling suppression back. */
7564 /* Suppress route if not suppressed already. */
7565 if (aggr_suppress_path(aggregate
, pi
))
7566 toggle_suppression
= true;
7570 /* Install route if there is no more suppression. */
7571 if (aggr_unsuppress_path(aggregate
, pi
))
7572 toggle_suppression
= true;
7575 if (toggle_suppression
)
7576 bgp_process(bgp
, dest
, afi
, safi
);
7578 bgp_dest_unlock_node(top
);
7582 * Aggregate address MED matching incremental test: this function is called
7583 * when the initial aggregation occurred and we are only testing a single
7586 * In addition to testing and setting the MED validity it also installs back
7587 * suppressed routes (if summary is configured).
7589 * Must not be called in `bgp_aggregate_route`.
7591 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7592 struct bgp
*bgp
, const struct prefix
*p
,
7593 afi_t afi
, safi_t safi
,
7594 struct bgp_path_info
*pi
)
7596 /* MED matching disabled. */
7597 if (!aggregate
->match_med
)
7600 /* Aggregation with different MED, recheck if we have got equal MEDs
7603 if (aggregate
->med_mismatched
&&
7604 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
) &&
7605 aggregate
->summary_only
)
7606 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
,
7609 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7611 /* No mismatches, just quit. */
7612 if (!aggregate
->med_mismatched
)
7615 /* Route summarization is disabled. */
7616 if (!aggregate
->summary_only
)
7619 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7622 /* Update an aggregate as routes are added/removed from the BGP table */
7623 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7624 safi_t safi
, struct bgp_aggregate
*aggregate
)
7626 struct bgp_table
*table
;
7627 struct bgp_dest
*top
;
7628 struct bgp_dest
*dest
;
7630 struct aspath
*aspath
= NULL
;
7631 struct community
*community
= NULL
;
7632 struct ecommunity
*ecommunity
= NULL
;
7633 struct lcommunity
*lcommunity
= NULL
;
7634 struct bgp_path_info
*pi
;
7635 unsigned long match
= 0;
7636 uint8_t atomic_aggregate
= 0;
7638 /* If the bgp instance is being deleted or self peer is deleted
7639 * then do not create aggregate route
7641 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7642 || (bgp
->peer_self
== NULL
))
7645 /* Initialize and test routes for MED difference. */
7646 if (aggregate
->match_med
)
7647 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7650 * Reset aggregate count: we might've been called from route map
7651 * update so in that case we must retest all more specific routes.
7653 * \see `bgp_route_map_process_update`.
7655 aggregate
->count
= 0;
7656 aggregate
->incomplete_origin_count
= 0;
7657 aggregate
->incomplete_origin_count
= 0;
7658 aggregate
->egp_origin_count
= 0;
7660 /* ORIGIN attribute: If at least one route among routes that are
7661 aggregated has ORIGIN with the value INCOMPLETE, then the
7662 aggregated route must have the ORIGIN attribute with the value
7663 INCOMPLETE. Otherwise, if at least one route among routes that
7664 are aggregated has ORIGIN with the value EGP, then the aggregated
7665 route must have the origin attribute with the value EGP. In all
7666 other case the value of the ORIGIN attribute of the aggregated
7667 route is INTERNAL. */
7668 origin
= BGP_ORIGIN_IGP
;
7670 table
= bgp
->rib
[afi
][safi
];
7672 top
= bgp_node_get(table
, p
);
7673 for (dest
= bgp_node_get(table
, p
); dest
;
7674 dest
= bgp_route_next_until(dest
, top
)) {
7675 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7677 if (dest_p
->prefixlen
<= p
->prefixlen
)
7680 /* If suppress fib is enabled and route not installed
7681 * in FIB, skip the route
7683 if (!bgp_check_advertise(bgp
, dest
))
7688 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7689 if (BGP_PATH_HOLDDOWN(pi
))
7693 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7694 atomic_aggregate
= 1;
7696 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7700 * summary-only aggregate route suppress
7701 * aggregated route announcements.
7704 * Don't create summaries if MED didn't match
7705 * otherwise neither the specific routes and the
7706 * aggregation will be announced.
7708 if (aggregate
->summary_only
7709 && AGGREGATE_MED_VALID(aggregate
)) {
7710 if (aggr_suppress_path(aggregate
, pi
))
7715 * Suppress more specific routes that match the route
7719 * Don't suppress routes if MED matching is enabled and
7720 * it mismatched otherwise we might end up with no
7721 * routes for this path.
7723 if (aggregate
->suppress_map_name
7724 && AGGREGATE_MED_VALID(aggregate
)
7725 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7726 if (aggr_suppress_path(aggregate
, pi
))
7733 * If at least one route among routes that are
7734 * aggregated has ORIGIN with the value INCOMPLETE,
7735 * then the aggregated route MUST have the ORIGIN
7736 * attribute with the value INCOMPLETE. Otherwise, if
7737 * at least one route among routes that are aggregated
7738 * has ORIGIN with the value EGP, then the aggregated
7739 * route MUST have the ORIGIN attribute with the value
7742 switch (pi
->attr
->origin
) {
7743 case BGP_ORIGIN_INCOMPLETE
:
7744 aggregate
->incomplete_origin_count
++;
7746 case BGP_ORIGIN_EGP
:
7747 aggregate
->egp_origin_count
++;
7755 if (!aggregate
->as_set
)
7759 * as-set aggregate route generate origin, as path,
7760 * and community aggregation.
7762 /* Compute aggregate route's as-path.
7764 bgp_compute_aggregate_aspath_hash(aggregate
,
7767 /* Compute aggregate route's community.
7769 if (bgp_attr_get_community(pi
->attr
))
7770 bgp_compute_aggregate_community_hash(
7772 bgp_attr_get_community(pi
->attr
));
7774 /* Compute aggregate route's extended community.
7776 if (bgp_attr_get_ecommunity(pi
->attr
))
7777 bgp_compute_aggregate_ecommunity_hash(
7779 bgp_attr_get_ecommunity(pi
->attr
));
7781 /* Compute aggregate route's large community.
7783 if (bgp_attr_get_lcommunity(pi
->attr
))
7784 bgp_compute_aggregate_lcommunity_hash(
7786 bgp_attr_get_lcommunity(pi
->attr
));
7789 bgp_process(bgp
, dest
, afi
, safi
);
7791 if (aggregate
->as_set
) {
7792 bgp_compute_aggregate_aspath_val(aggregate
);
7793 bgp_compute_aggregate_community_val(aggregate
);
7794 bgp_compute_aggregate_ecommunity_val(aggregate
);
7795 bgp_compute_aggregate_lcommunity_val(aggregate
);
7799 bgp_dest_unlock_node(top
);
7802 if (aggregate
->incomplete_origin_count
> 0)
7803 origin
= BGP_ORIGIN_INCOMPLETE
;
7804 else if (aggregate
->egp_origin_count
> 0)
7805 origin
= BGP_ORIGIN_EGP
;
7807 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7808 origin
= aggregate
->origin
;
7810 if (aggregate
->as_set
) {
7811 if (aggregate
->aspath
)
7812 /* Retrieve aggregate route's as-path.
7814 aspath
= aspath_dup(aggregate
->aspath
);
7816 if (aggregate
->community
)
7817 /* Retrieve aggregate route's community.
7819 community
= community_dup(aggregate
->community
);
7821 if (aggregate
->ecommunity
)
7822 /* Retrieve aggregate route's ecommunity.
7824 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7826 if (aggregate
->lcommunity
)
7827 /* Retrieve aggregate route's lcommunity.
7829 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7832 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7833 ecommunity
, lcommunity
, atomic_aggregate
,
7837 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7838 safi_t safi
, struct bgp_aggregate
*aggregate
)
7840 struct bgp_table
*table
;
7841 struct bgp_dest
*top
;
7842 struct bgp_dest
*dest
;
7843 struct bgp_path_info
*pi
;
7844 unsigned long match
;
7846 table
= bgp
->rib
[afi
][safi
];
7848 /* If routes exists below this node, generate aggregate routes. */
7849 top
= bgp_node_get(table
, p
);
7850 for (dest
= bgp_node_get(table
, p
); dest
;
7851 dest
= bgp_route_next_until(dest
, top
)) {
7852 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7854 if (dest_p
->prefixlen
<= p
->prefixlen
)
7858 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7859 if (BGP_PATH_HOLDDOWN(pi
))
7862 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7866 * This route is suppressed: attempt to unsuppress it.
7868 * `aggr_unsuppress_path` will fail if this particular
7869 * aggregate route was not the suppressor.
7871 if (pi
->extra
&& pi
->extra
->aggr_suppressors
&&
7872 listcount(pi
->extra
->aggr_suppressors
)) {
7873 if (aggr_unsuppress_path(aggregate
, pi
))
7879 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7880 aggregate
->incomplete_origin_count
--;
7881 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7882 aggregate
->egp_origin_count
--;
7884 if (aggregate
->as_set
) {
7885 /* Remove as-path from aggregate.
7887 bgp_remove_aspath_from_aggregate_hash(
7891 if (bgp_attr_get_community(pi
->attr
))
7892 /* Remove community from aggregate.
7894 bgp_remove_comm_from_aggregate_hash(
7896 bgp_attr_get_community(
7899 if (bgp_attr_get_ecommunity(pi
->attr
))
7900 /* Remove ecommunity from aggregate.
7902 bgp_remove_ecomm_from_aggregate_hash(
7904 bgp_attr_get_ecommunity(
7907 if (bgp_attr_get_lcommunity(pi
->attr
))
7908 /* Remove lcommunity from aggregate.
7910 bgp_remove_lcomm_from_aggregate_hash(
7912 bgp_attr_get_lcommunity(
7917 /* If this node was suppressed, process the change. */
7919 bgp_process(bgp
, dest
, afi
, safi
);
7921 if (aggregate
->as_set
) {
7922 aspath_free(aggregate
->aspath
);
7923 aggregate
->aspath
= NULL
;
7924 if (aggregate
->community
)
7925 community_free(&aggregate
->community
);
7926 if (aggregate
->ecommunity
)
7927 ecommunity_free(&aggregate
->ecommunity
);
7928 if (aggregate
->lcommunity
)
7929 lcommunity_free(&aggregate
->lcommunity
);
7932 bgp_dest_unlock_node(top
);
7935 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7936 const struct prefix
*aggr_p
,
7937 struct bgp_path_info
*pinew
, afi_t afi
,
7939 struct bgp_aggregate
*aggregate
)
7942 struct aspath
*aspath
= NULL
;
7943 uint8_t atomic_aggregate
= 0;
7944 struct community
*community
= NULL
;
7945 struct ecommunity
*ecommunity
= NULL
;
7946 struct lcommunity
*lcommunity
= NULL
;
7948 /* If the bgp instance is being deleted or self peer is deleted
7949 * then do not create aggregate route
7951 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7952 || (bgp
->peer_self
== NULL
))
7955 /* ORIGIN attribute: If at least one route among routes that are
7956 * aggregated has ORIGIN with the value INCOMPLETE, then the
7957 * aggregated route must have the ORIGIN attribute with the value
7958 * INCOMPLETE. Otherwise, if at least one route among routes that
7959 * are aggregated has ORIGIN with the value EGP, then the aggregated
7960 * route must have the origin attribute with the value EGP. In all
7961 * other case the value of the ORIGIN attribute of the aggregated
7962 * route is INTERNAL.
7964 origin
= BGP_ORIGIN_IGP
;
7969 * This must be called before `summary` check to avoid
7970 * "suppressing" twice.
7972 if (aggregate
->match_med
)
7973 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
7976 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7977 aggr_suppress_path(aggregate
, pinew
);
7979 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7980 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
7981 aggr_suppress_path(aggregate
, pinew
);
7983 switch (pinew
->attr
->origin
) {
7984 case BGP_ORIGIN_INCOMPLETE
:
7985 aggregate
->incomplete_origin_count
++;
7987 case BGP_ORIGIN_EGP
:
7988 aggregate
->egp_origin_count
++;
7996 if (aggregate
->incomplete_origin_count
> 0)
7997 origin
= BGP_ORIGIN_INCOMPLETE
;
7998 else if (aggregate
->egp_origin_count
> 0)
7999 origin
= BGP_ORIGIN_EGP
;
8001 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8002 origin
= aggregate
->origin
;
8004 if (aggregate
->as_set
) {
8005 /* Compute aggregate route's as-path.
8007 bgp_compute_aggregate_aspath(aggregate
,
8008 pinew
->attr
->aspath
);
8010 /* Compute aggregate route's community.
8012 if (bgp_attr_get_community(pinew
->attr
))
8013 bgp_compute_aggregate_community(
8014 aggregate
, bgp_attr_get_community(pinew
->attr
));
8016 /* Compute aggregate route's extended community.
8018 if (bgp_attr_get_ecommunity(pinew
->attr
))
8019 bgp_compute_aggregate_ecommunity(
8021 bgp_attr_get_ecommunity(pinew
->attr
));
8023 /* Compute aggregate route's large community.
8025 if (bgp_attr_get_lcommunity(pinew
->attr
))
8026 bgp_compute_aggregate_lcommunity(
8028 bgp_attr_get_lcommunity(pinew
->attr
));
8030 /* Retrieve aggregate route's as-path.
8032 if (aggregate
->aspath
)
8033 aspath
= aspath_dup(aggregate
->aspath
);
8035 /* Retrieve aggregate route's community.
8037 if (aggregate
->community
)
8038 community
= community_dup(aggregate
->community
);
8040 /* Retrieve aggregate route's ecommunity.
8042 if (aggregate
->ecommunity
)
8043 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8045 /* Retrieve aggregate route's lcommunity.
8047 if (aggregate
->lcommunity
)
8048 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8051 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8052 aspath
, community
, ecommunity
,
8053 lcommunity
, atomic_aggregate
, aggregate
);
8056 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
8058 struct bgp_path_info
*pi
,
8059 struct bgp_aggregate
*aggregate
,
8060 const struct prefix
*aggr_p
)
8063 struct aspath
*aspath
= NULL
;
8064 uint8_t atomic_aggregate
= 0;
8065 struct community
*community
= NULL
;
8066 struct ecommunity
*ecommunity
= NULL
;
8067 struct lcommunity
*lcommunity
= NULL
;
8068 unsigned long match
= 0;
8070 /* If the bgp instance is being deleted or self peer is deleted
8071 * then do not create aggregate route
8073 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
8074 || (bgp
->peer_self
== NULL
))
8077 if (BGP_PATH_HOLDDOWN(pi
))
8080 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
8083 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8084 if (aggr_unsuppress_path(aggregate
, pi
))
8087 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8088 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
8089 if (aggr_unsuppress_path(aggregate
, pi
))
8093 * This must be called after `summary`, `suppress-map` check to avoid
8094 * "unsuppressing" twice.
8096 if (aggregate
->match_med
)
8097 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
);
8099 if (aggregate
->count
> 0)
8102 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
8103 aggregate
->incomplete_origin_count
--;
8104 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
8105 aggregate
->egp_origin_count
--;
8107 if (aggregate
->as_set
) {
8108 /* Remove as-path from aggregate.
8110 bgp_remove_aspath_from_aggregate(aggregate
,
8113 if (bgp_attr_get_community(pi
->attr
))
8114 /* Remove community from aggregate.
8116 bgp_remove_community_from_aggregate(
8117 aggregate
, bgp_attr_get_community(pi
->attr
));
8119 if (bgp_attr_get_ecommunity(pi
->attr
))
8120 /* Remove ecommunity from aggregate.
8122 bgp_remove_ecommunity_from_aggregate(
8123 aggregate
, bgp_attr_get_ecommunity(pi
->attr
));
8125 if (bgp_attr_get_lcommunity(pi
->attr
))
8126 /* Remove lcommunity from aggregate.
8128 bgp_remove_lcommunity_from_aggregate(
8129 aggregate
, bgp_attr_get_lcommunity(pi
->attr
));
8132 /* If this node was suppressed, process the change. */
8134 bgp_process(bgp
, pi
->net
, afi
, safi
);
8136 origin
= BGP_ORIGIN_IGP
;
8137 if (aggregate
->incomplete_origin_count
> 0)
8138 origin
= BGP_ORIGIN_INCOMPLETE
;
8139 else if (aggregate
->egp_origin_count
> 0)
8140 origin
= BGP_ORIGIN_EGP
;
8142 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8143 origin
= aggregate
->origin
;
8145 if (aggregate
->as_set
) {
8146 /* Retrieve aggregate route's as-path.
8148 if (aggregate
->aspath
)
8149 aspath
= aspath_dup(aggregate
->aspath
);
8151 /* Retrieve aggregate route's community.
8153 if (aggregate
->community
)
8154 community
= community_dup(aggregate
->community
);
8156 /* Retrieve aggregate route's ecommunity.
8158 if (aggregate
->ecommunity
)
8159 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8161 /* Retrieve aggregate route's lcommunity.
8163 if (aggregate
->lcommunity
)
8164 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8167 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8168 aspath
, community
, ecommunity
,
8169 lcommunity
, atomic_aggregate
, aggregate
);
8172 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
8173 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
8175 struct bgp_dest
*child
;
8176 struct bgp_dest
*dest
;
8177 struct bgp_aggregate
*aggregate
;
8178 struct bgp_table
*table
;
8180 table
= bgp
->aggregate
[afi
][safi
];
8182 /* No aggregates configured. */
8183 if (bgp_table_top_nolock(table
) == NULL
)
8186 if (p
->prefixlen
== 0)
8189 if (BGP_PATH_HOLDDOWN(pi
))
8192 /* If suppress fib is enabled and route not installed
8193 * in FIB, do not update the aggregate route
8195 if (!bgp_check_advertise(bgp
, pi
->net
))
8198 child
= bgp_node_get(table
, p
);
8200 /* Aggregate address configuration check. */
8201 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8202 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8204 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8205 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8206 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
8210 bgp_dest_unlock_node(child
);
8213 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
8214 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
8216 struct bgp_dest
*child
;
8217 struct bgp_dest
*dest
;
8218 struct bgp_aggregate
*aggregate
;
8219 struct bgp_table
*table
;
8221 table
= bgp
->aggregate
[afi
][safi
];
8223 /* No aggregates configured. */
8224 if (bgp_table_top_nolock(table
) == NULL
)
8227 if (p
->prefixlen
== 0)
8230 child
= bgp_node_get(table
, p
);
8232 /* Aggregate address configuration check. */
8233 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8234 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8236 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8237 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8238 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
8242 bgp_dest_unlock_node(child
);
8245 /* Aggregate route attribute. */
8246 #define AGGREGATE_SUMMARY_ONLY 1
8247 #define AGGREGATE_AS_SET 1
8248 #define AGGREGATE_AS_UNSET 0
8250 static const char *bgp_origin2str(uint8_t origin
)
8253 case BGP_ORIGIN_IGP
:
8255 case BGP_ORIGIN_EGP
:
8257 case BGP_ORIGIN_INCOMPLETE
:
8258 return "incomplete";
8263 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
8266 case RPKI_NOT_BEING_USED
:
8276 assert(!"We should never get here this is a dev escape");
8280 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
8281 afi_t afi
, safi_t safi
)
8283 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8286 struct bgp_dest
*dest
;
8287 struct bgp_aggregate
*aggregate
;
8289 /* Convert string to prefix structure. */
8290 ret
= str2prefix(prefix_str
, &p
);
8292 vty_out(vty
, "Malformed prefix\n");
8293 return CMD_WARNING_CONFIG_FAILED
;
8297 /* Old configuration check. */
8298 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
8301 "%% There is no aggregate-address configuration.\n");
8302 return CMD_WARNING_CONFIG_FAILED
;
8305 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8306 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
8307 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
8308 NULL
, NULL
, 0, aggregate
);
8310 /* Unlock aggregate address configuration. */
8311 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
8313 if (aggregate
->community
)
8314 community_free(&aggregate
->community
);
8316 if (aggregate
->community_hash
) {
8317 /* Delete all communities in the hash.
8319 hash_clean(aggregate
->community_hash
,
8320 bgp_aggr_community_remove
);
8321 /* Free up the community_hash.
8323 hash_free(aggregate
->community_hash
);
8326 if (aggregate
->ecommunity
)
8327 ecommunity_free(&aggregate
->ecommunity
);
8329 if (aggregate
->ecommunity_hash
) {
8330 /* Delete all ecommunities in the hash.
8332 hash_clean(aggregate
->ecommunity_hash
,
8333 bgp_aggr_ecommunity_remove
);
8334 /* Free up the ecommunity_hash.
8336 hash_free(aggregate
->ecommunity_hash
);
8339 if (aggregate
->lcommunity
)
8340 lcommunity_free(&aggregate
->lcommunity
);
8342 if (aggregate
->lcommunity_hash
) {
8343 /* Delete all lcommunities in the hash.
8345 hash_clean(aggregate
->lcommunity_hash
,
8346 bgp_aggr_lcommunity_remove
);
8347 /* Free up the lcommunity_hash.
8349 hash_free(aggregate
->lcommunity_hash
);
8352 if (aggregate
->aspath
)
8353 aspath_free(aggregate
->aspath
);
8355 if (aggregate
->aspath_hash
) {
8356 /* Delete all as-paths in the hash.
8358 hash_clean(aggregate
->aspath_hash
,
8359 bgp_aggr_aspath_remove
);
8360 /* Free up the aspath_hash.
8362 hash_free(aggregate
->aspath_hash
);
8365 bgp_aggregate_free(aggregate
);
8366 bgp_dest_unlock_node(dest
);
8367 bgp_dest_unlock_node(dest
);
8372 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
8373 safi_t safi
, const char *rmap
,
8374 uint8_t summary_only
, uint8_t as_set
,
8375 uint8_t origin
, bool match_med
,
8376 const char *suppress_map
)
8378 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8381 struct bgp_dest
*dest
;
8382 struct bgp_aggregate
*aggregate
;
8383 uint8_t as_set_new
= as_set
;
8385 if (suppress_map
&& summary_only
) {
8387 "'summary-only' and 'suppress-map' can't be used at the same time\n");
8388 return CMD_WARNING_CONFIG_FAILED
;
8391 /* Convert string to prefix structure. */
8392 ret
= str2prefix(prefix_str
, &p
);
8394 vty_out(vty
, "Malformed prefix\n");
8395 return CMD_WARNING_CONFIG_FAILED
;
8399 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
8400 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
8401 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8403 return CMD_WARNING_CONFIG_FAILED
;
8406 /* Old configuration check. */
8407 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
8408 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8411 vty_out(vty
, "There is already same aggregate network.\n");
8412 /* try to remove the old entry */
8413 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
8415 vty_out(vty
, "Error deleting aggregate.\n");
8416 bgp_dest_unlock_node(dest
);
8417 return CMD_WARNING_CONFIG_FAILED
;
8421 /* Make aggregate address structure. */
8422 aggregate
= bgp_aggregate_new();
8423 aggregate
->summary_only
= summary_only
;
8424 aggregate
->match_med
= match_med
;
8426 /* Network operators MUST NOT locally generate any new
8427 * announcements containing AS_SET or AS_CONFED_SET. If they have
8428 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8429 * SHOULD withdraw those routes and re-announce routes for the
8430 * aggregate or component prefixes (i.e., the more-specific routes
8431 * subsumed by the previously aggregated route) without AS_SET
8432 * or AS_CONFED_SET in the updates.
8434 if (bgp
->reject_as_sets
) {
8435 if (as_set
== AGGREGATE_AS_SET
) {
8436 as_set_new
= AGGREGATE_AS_UNSET
;
8438 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8441 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8445 aggregate
->as_set
= as_set_new
;
8446 aggregate
->safi
= safi
;
8447 /* Override ORIGIN attribute if defined.
8448 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8449 * to IGP which is not what rfc4271 says.
8450 * This enables the same behavior, optionally.
8452 aggregate
->origin
= origin
;
8455 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
8456 route_map_counter_decrement(aggregate
->rmap
.map
);
8457 aggregate
->rmap
.name
=
8458 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
8459 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
8460 route_map_counter_increment(aggregate
->rmap
.map
);
8464 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
8465 route_map_counter_decrement(aggregate
->suppress_map
);
8467 aggregate
->suppress_map_name
=
8468 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
8469 aggregate
->suppress_map
=
8470 route_map_lookup_by_name(aggregate
->suppress_map_name
);
8471 route_map_counter_increment(aggregate
->suppress_map
);
8474 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
8476 /* Aggregate address insert into BGP routing table. */
8477 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
8482 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
8483 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8485 "|summary-only$summary_only"
8486 "|route-map RMAP_NAME$rmap_name"
8487 "|origin <egp|igp|incomplete>$origin_s"
8488 "|matching-MED-only$match_med"
8489 "|suppress-map RMAP_NAME$suppress_map"
8492 "Configure BGP aggregate entries\n"
8493 "Aggregate prefix\n"
8494 "Aggregate address\n"
8496 "Generate AS set path information\n"
8497 "Filter more specific routes from updates\n"
8498 "Apply route map to aggregate network\n"
8503 "Unknown heritage\n"
8504 "Only aggregate routes with matching MED\n"
8505 "Suppress the selected more specific routes\n"
8506 "Route map with the route selectors\n")
8508 const char *prefix_s
= NULL
;
8509 safi_t safi
= bgp_node_safi(vty
);
8510 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8511 int as_set
= AGGREGATE_AS_UNSET
;
8512 char prefix_buf
[PREFIX2STR_BUFFER
];
8515 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8518 vty_out(vty
, "%% Inconsistent address and mask\n");
8519 return CMD_WARNING_CONFIG_FAILED
;
8521 prefix_s
= prefix_buf
;
8523 prefix_s
= prefix_str
;
8526 if (strcmp(origin_s
, "egp") == 0)
8527 origin
= BGP_ORIGIN_EGP
;
8528 else if (strcmp(origin_s
, "igp") == 0)
8529 origin
= BGP_ORIGIN_IGP
;
8530 else if (strcmp(origin_s
, "incomplete") == 0)
8531 origin
= BGP_ORIGIN_INCOMPLETE
;
8535 as_set
= AGGREGATE_AS_SET
;
8537 /* Handle configuration removal, otherwise installation. */
8539 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8541 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8542 summary_only
!= NULL
, as_set
, origin
,
8543 match_med
!= NULL
, suppress_map
);
8546 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8547 "[no] aggregate-address X:X::X:X/M$prefix [{"
8549 "|summary-only$summary_only"
8550 "|route-map RMAP_NAME$rmap_name"
8551 "|origin <egp|igp|incomplete>$origin_s"
8552 "|matching-MED-only$match_med"
8553 "|suppress-map RMAP_NAME$suppress_map"
8556 "Configure BGP aggregate entries\n"
8557 "Aggregate prefix\n"
8558 "Generate AS set path information\n"
8559 "Filter more specific routes from updates\n"
8560 "Apply route map to aggregate network\n"
8565 "Unknown heritage\n"
8566 "Only aggregate routes with matching MED\n"
8567 "Suppress the selected more specific routes\n"
8568 "Route map with the route selectors\n")
8570 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8571 int as_set
= AGGREGATE_AS_UNSET
;
8574 if (strcmp(origin_s
, "egp") == 0)
8575 origin
= BGP_ORIGIN_EGP
;
8576 else if (strcmp(origin_s
, "igp") == 0)
8577 origin
= BGP_ORIGIN_IGP
;
8578 else if (strcmp(origin_s
, "incomplete") == 0)
8579 origin
= BGP_ORIGIN_INCOMPLETE
;
8583 as_set
= AGGREGATE_AS_SET
;
8585 /* Handle configuration removal, otherwise installation. */
8587 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8590 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8591 rmap_name
, summary_only
!= NULL
, as_set
,
8592 origin
, match_med
!= NULL
, suppress_map
);
8595 /* Redistribute route treatment. */
8596 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8597 const union g_addr
*nexthop
, ifindex_t ifindex
,
8598 enum nexthop_types_t nhtype
, uint8_t distance
,
8599 enum blackhole_type bhtype
, uint32_t metric
,
8600 uint8_t type
, unsigned short instance
,
8603 struct bgp_path_info
*new;
8604 struct bgp_path_info
*bpi
;
8605 struct bgp_path_info rmap_path
;
8606 struct bgp_dest
*bn
;
8608 struct attr
*new_attr
;
8610 route_map_result_t ret
;
8611 struct bgp_redist
*red
;
8613 /* Make default attribute. */
8614 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
8616 * This must not be NULL to satisfy Coverity SA
8618 assert(attr
.aspath
);
8621 case NEXTHOP_TYPE_IFINDEX
:
8622 switch (p
->family
) {
8624 attr
.nexthop
.s_addr
= INADDR_ANY
;
8625 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8628 memset(&attr
.mp_nexthop_global
, 0,
8629 sizeof(attr
.mp_nexthop_global
));
8630 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8634 case NEXTHOP_TYPE_IPV4
:
8635 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8636 attr
.nexthop
= nexthop
->ipv4
;
8637 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8639 case NEXTHOP_TYPE_IPV6
:
8640 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8641 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8642 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8644 case NEXTHOP_TYPE_BLACKHOLE
:
8645 switch (p
->family
) {
8647 attr
.nexthop
.s_addr
= INADDR_ANY
;
8648 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8651 memset(&attr
.mp_nexthop_global
, 0,
8652 sizeof(attr
.mp_nexthop_global
));
8653 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8656 attr
.bh_type
= bhtype
;
8659 attr
.nh_type
= nhtype
;
8660 attr
.nh_ifindex
= ifindex
;
8663 attr
.distance
= distance
;
8664 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8668 bgp_attr_set_aigp_metric(&attr
, metric
);
8670 afi
= family2afi(p
->family
);
8672 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8674 struct attr attr_new
;
8676 /* Copy attribute for modification. */
8679 if (red
->redist_metric_flag
) {
8680 attr_new
.med
= red
->redist_metric
;
8681 bgp_attr_set_aigp_metric(&attr_new
, red
->redist_metric
);
8684 /* Apply route-map. */
8685 if (red
->rmap
.name
) {
8686 memset(&rmap_path
, 0, sizeof(rmap_path
));
8687 rmap_path
.peer
= bgp
->peer_self
;
8688 rmap_path
.attr
= &attr_new
;
8690 SET_FLAG(bgp
->peer_self
->rmap_type
,
8691 PEER_RMAP_TYPE_REDISTRIBUTE
);
8693 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8695 bgp
->peer_self
->rmap_type
= 0;
8697 if (ret
== RMAP_DENYMATCH
) {
8698 /* Free uninterned attribute. */
8699 bgp_attr_flush(&attr_new
);
8701 /* Unintern original. */
8702 aspath_unintern(&attr
.aspath
);
8703 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8708 if (bgp_in_graceful_shutdown(bgp
))
8709 bgp_attr_add_gshut_community(&attr_new
);
8711 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8712 SAFI_UNICAST
, p
, NULL
);
8714 new_attr
= bgp_attr_intern(&attr_new
);
8716 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8717 if (bpi
->peer
== bgp
->peer_self
8718 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8722 /* Ensure the (source route) type is updated. */
8724 if (attrhash_cmp(bpi
->attr
, new_attr
)
8725 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8726 bgp_attr_unintern(&new_attr
);
8727 aspath_unintern(&attr
.aspath
);
8728 bgp_dest_unlock_node(bn
);
8731 /* The attribute is changed. */
8732 bgp_path_info_set_flag(bn
, bpi
,
8733 BGP_PATH_ATTR_CHANGED
);
8735 /* Rewrite BGP route information. */
8736 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8737 bgp_path_info_restore(bn
, bpi
);
8739 bgp_aggregate_decrement(
8740 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8741 bgp_attr_unintern(&bpi
->attr
);
8742 bpi
->attr
= new_attr
;
8743 bpi
->uptime
= monotime(NULL
);
8745 /* Process change. */
8746 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8748 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8749 bgp_dest_unlock_node(bn
);
8750 aspath_unintern(&attr
.aspath
);
8752 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8754 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8756 vpn_leak_from_vrf_update(
8757 bgp_get_default(), bgp
, bpi
);
8763 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8764 bgp
->peer_self
, new_attr
, bn
);
8765 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8767 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8768 bgp_path_info_add(bn
, new);
8769 bgp_dest_unlock_node(bn
);
8770 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8771 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8773 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8774 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8776 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8780 /* Unintern original. */
8781 aspath_unintern(&attr
.aspath
);
8784 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8785 unsigned short instance
)
8788 struct bgp_dest
*dest
;
8789 struct bgp_path_info
*pi
;
8790 struct bgp_redist
*red
;
8792 afi
= family2afi(p
->family
);
8794 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8796 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8797 SAFI_UNICAST
, p
, NULL
);
8799 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8800 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8804 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8805 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8807 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8810 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8811 bgp_path_info_delete(dest
, pi
);
8812 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8814 bgp_dest_unlock_node(dest
);
8818 /* Withdraw specified route type's route. */
8819 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8820 unsigned short instance
)
8822 struct bgp_dest
*dest
;
8823 struct bgp_path_info
*pi
;
8824 struct bgp_table
*table
;
8826 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8828 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8829 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8830 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8831 && pi
->instance
== instance
)
8835 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8836 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8838 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8841 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8842 pi
, afi
, SAFI_UNICAST
);
8843 bgp_path_info_delete(dest
, pi
);
8844 if (!CHECK_FLAG(bgp
->flags
,
8845 BGP_FLAG_DELETE_IN_PROGRESS
))
8846 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8848 bgp_path_info_reap(dest
, pi
);
8853 /* Static function to display route. */
8854 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8855 struct vty
*vty
, json_object
*json
, bool wide
)
8858 char buf
[INET6_ADDRSTRLEN
];
8860 if (p
->family
== AF_INET
) {
8862 len
= vty_out(vty
, "%pFX", p
);
8864 json_object_string_add(json
, "prefix",
8865 inet_ntop(p
->family
,
8868 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8869 json_object_string_addf(json
, "network", "%pFX", p
);
8870 json_object_int_add(json
, "version", dest
->version
);
8872 } else if (p
->family
== AF_ETHERNET
) {
8873 len
= vty_out(vty
, "%pFX", p
);
8874 } else if (p
->family
== AF_EVPN
) {
8876 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8878 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8879 } else if (p
->family
== AF_FLOWSPEC
) {
8880 route_vty_out_flowspec(vty
, p
, NULL
,
8882 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8883 NLRI_STRING_FORMAT_MIN
, json
);
8886 len
= vty_out(vty
, "%pFX", p
);
8888 json_object_string_add(json
, "prefix",
8889 inet_ntop(p
->family
,
8892 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8893 json_object_string_addf(json
, "network", "%pFX", p
);
8894 json_object_int_add(json
, "version", dest
->version
);
8899 len
= wide
? (45 - len
) : (17 - len
);
8901 vty_out(vty
, "\n%*s", 20, " ");
8903 vty_out(vty
, "%*s", len
, " ");
8907 enum bgp_display_type
{
8911 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8914 case bgp_path_selection_none
:
8915 return "Nothing to Select";
8916 case bgp_path_selection_first
:
8917 return "First path received";
8918 case bgp_path_selection_evpn_sticky_mac
:
8919 return "EVPN Sticky Mac";
8920 case bgp_path_selection_evpn_seq
:
8921 return "EVPN sequence number";
8922 case bgp_path_selection_evpn_lower_ip
:
8923 return "EVPN lower IP";
8924 case bgp_path_selection_evpn_local_path
:
8925 return "EVPN local ES path";
8926 case bgp_path_selection_evpn_non_proxy
:
8927 return "EVPN non proxy";
8928 case bgp_path_selection_weight
:
8930 case bgp_path_selection_local_pref
:
8931 return "Local Pref";
8932 case bgp_path_selection_accept_own
:
8933 return "Accept Own";
8934 case bgp_path_selection_local_route
:
8935 return "Local Route";
8936 case bgp_path_selection_aigp
:
8938 case bgp_path_selection_confed_as_path
:
8939 return "Confederation based AS Path";
8940 case bgp_path_selection_as_path
:
8942 case bgp_path_selection_origin
:
8944 case bgp_path_selection_med
:
8946 case bgp_path_selection_peer
:
8948 case bgp_path_selection_confed
:
8949 return "Confed Peer Type";
8950 case bgp_path_selection_igp_metric
:
8951 return "IGP Metric";
8952 case bgp_path_selection_older
:
8953 return "Older Path";
8954 case bgp_path_selection_router_id
:
8956 case bgp_path_selection_cluster_length
:
8957 return "Cluster length";
8958 case bgp_path_selection_stale
:
8959 return "Path Staleness";
8960 case bgp_path_selection_local_configured
:
8961 return "Locally configured route";
8962 case bgp_path_selection_neighbor_ip
:
8963 return "Neighbor IP";
8964 case bgp_path_selection_default
:
8965 return "Nothing left to compare";
8967 return "Invalid (internal error)";
8970 /* Print the short form route status for a bgp_path_info */
8971 static void route_vty_short_status_out(struct vty
*vty
,
8972 struct bgp_path_info
*path
,
8973 const struct prefix
*p
,
8974 json_object
*json_path
)
8976 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
8980 /* Route status display. */
8981 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8982 json_object_boolean_true_add(json_path
, "removed");
8984 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8985 json_object_boolean_true_add(json_path
, "stale");
8987 if (path
->extra
&& bgp_path_suppressed(path
))
8988 json_object_boolean_true_add(json_path
, "suppressed");
8990 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8991 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8992 json_object_boolean_true_add(json_path
, "valid");
8995 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8996 json_object_boolean_true_add(json_path
, "history");
8998 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8999 json_object_boolean_true_add(json_path
, "damped");
9001 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9002 json_object_boolean_true_add(json_path
, "bestpath");
9003 json_object_string_add(json_path
, "selectionReason",
9004 bgp_path_selection_reason2str(
9005 path
->net
->reason
));
9008 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9009 json_object_boolean_true_add(json_path
, "multipath");
9011 /* Internal route. */
9012 if ((path
->peer
->as
)
9013 && (path
->peer
->as
== path
->peer
->local_as
))
9014 json_object_string_add(json_path
, "pathFrom",
9017 json_object_string_add(json_path
, "pathFrom",
9023 /* RPKI validation state */
9025 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
9027 if (rpki_state
== RPKI_VALID
)
9029 else if (rpki_state
== RPKI_INVALID
)
9031 else if (rpki_state
== RPKI_NOTFOUND
)
9036 /* Route status display. */
9037 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9039 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9041 else if (bgp_path_suppressed(path
))
9043 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9044 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9050 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9052 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9054 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
9056 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9061 /* Internal route. */
9062 if (path
->peer
&& (path
->peer
->as
)
9063 && (path
->peer
->as
== path
->peer
->local_as
))
9069 static char *bgp_nexthop_hostname(struct peer
*peer
,
9070 struct bgp_nexthop_cache
*bnc
)
9073 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
9074 return peer
->hostname
;
9078 /* called from terminal list command */
9079 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9080 struct bgp_path_info
*path
, int display
, safi_t safi
,
9081 json_object
*json_paths
, bool wide
)
9084 struct attr
*attr
= path
->attr
;
9085 json_object
*json_path
= NULL
;
9086 json_object
*json_nexthops
= NULL
;
9087 json_object
*json_nexthop_global
= NULL
;
9088 json_object
*json_nexthop_ll
= NULL
;
9089 json_object
*json_ext_community
= NULL
;
9090 char vrf_id_str
[VRF_NAMSIZ
] = {0};
9092 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9093 bool nexthop_othervrf
= false;
9094 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
9095 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
9096 char *nexthop_hostname
=
9097 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9098 char esi_buf
[ESI_STR_LEN
];
9101 json_path
= json_object_new_object();
9103 /* short status lead text */
9104 route_vty_short_status_out(vty
, path
, p
, json_path
);
9107 /* print prefix and mask */
9109 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9111 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
9113 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9117 * If vrf id of nexthop is different from that of prefix,
9118 * set up printable string to append
9120 if (path
->extra
&& path
->extra
->bgp_orig
) {
9121 const char *self
= "";
9126 nexthop_othervrf
= true;
9127 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9129 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
9130 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
9131 "@%s%s", VRFID_NONE_STR
, self
);
9133 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
9134 path
->extra
->bgp_orig
->vrf_id
, self
);
9136 if (path
->extra
->bgp_orig
->inst_type
9137 != BGP_INSTANCE_TYPE_DEFAULT
)
9139 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
9141 const char *self
= "";
9146 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
9150 * For ENCAP and EVPN routes, nexthop address family is not
9151 * neccessarily the same as the prefix address family.
9152 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9153 * EVPN routes are also exchanged with a MP nexthop. Currently,
9155 * is only IPv4, the value will be present in either
9157 * attr->mp_nexthop_global_in
9159 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
9161 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9165 snprintfrr(nexthop
, sizeof(nexthop
), "%pI4",
9166 &attr
->mp_nexthop_global_in
);
9169 snprintfrr(nexthop
, sizeof(nexthop
), "%pI6",
9170 &attr
->mp_nexthop_global
);
9173 snprintf(nexthop
, sizeof(nexthop
), "?");
9178 json_nexthop_global
= json_object_new_object();
9180 json_object_string_add(json_nexthop_global
, "ip",
9183 if (path
->peer
->hostname
)
9184 json_object_string_add(json_nexthop_global
,
9186 path
->peer
->hostname
);
9188 json_object_string_add(json_nexthop_global
, "afi",
9189 (af
== AF_INET
) ? "ipv4"
9191 json_object_boolean_true_add(json_nexthop_global
,
9194 if (nexthop_hostname
)
9195 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
9196 nexthop_hostname
, vrf_id_str
);
9198 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
9200 len
= wide
? (41 - len
) : (16 - len
);
9202 vty_out(vty
, "\n%*s", 36, " ");
9204 vty_out(vty
, "%*s", len
, " ");
9206 } else if (safi
== SAFI_EVPN
) {
9208 json_nexthop_global
= json_object_new_object();
9210 json_object_string_addf(json_nexthop_global
, "ip",
9212 &attr
->mp_nexthop_global_in
);
9214 if (path
->peer
->hostname
)
9215 json_object_string_add(json_nexthop_global
,
9217 path
->peer
->hostname
);
9219 json_object_string_add(json_nexthop_global
, "afi",
9221 json_object_boolean_true_add(json_nexthop_global
,
9224 if (nexthop_hostname
)
9225 len
= vty_out(vty
, "%pI4(%s)%s",
9226 &attr
->mp_nexthop_global_in
,
9227 nexthop_hostname
, vrf_id_str
);
9229 len
= vty_out(vty
, "%pI4%s",
9230 &attr
->mp_nexthop_global_in
,
9233 len
= wide
? (41 - len
) : (16 - len
);
9235 vty_out(vty
, "\n%*s", 36, " ");
9237 vty_out(vty
, "%*s", len
, " ");
9239 } else if (safi
== SAFI_FLOWSPEC
) {
9240 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
9242 json_nexthop_global
= json_object_new_object();
9244 json_object_string_add(json_nexthop_global
,
9246 json_object_string_addf(json_nexthop_global
,
9250 if (path
->peer
->hostname
)
9251 json_object_string_add(
9252 json_nexthop_global
, "hostname",
9253 path
->peer
->hostname
);
9255 json_object_boolean_true_add(
9256 json_nexthop_global
,
9259 if (nexthop_hostname
)
9260 len
= vty_out(vty
, "%pI4(%s)%s",
9265 len
= vty_out(vty
, "%pI4%s",
9269 len
= wide
? (41 - len
) : (16 - len
);
9271 vty_out(vty
, "\n%*s", 36, " ");
9273 vty_out(vty
, "%*s", len
, " ");
9276 } else if (p
->family
== AF_INET
&& !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9278 json_nexthop_global
= json_object_new_object();
9280 json_object_string_addf(json_nexthop_global
, "ip",
9281 "%pI4", &attr
->nexthop
);
9283 if (path
->peer
->hostname
)
9284 json_object_string_add(json_nexthop_global
,
9286 path
->peer
->hostname
);
9288 json_object_string_add(json_nexthop_global
, "afi",
9290 json_object_boolean_true_add(json_nexthop_global
,
9293 if (nexthop_hostname
)
9294 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
9295 nexthop_hostname
, vrf_id_str
);
9297 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
9300 len
= wide
? (41 - len
) : (16 - len
);
9302 vty_out(vty
, "\n%*s", 36, " ");
9304 vty_out(vty
, "%*s", len
, " ");
9309 else if (p
->family
== AF_INET6
|| BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9311 json_nexthop_global
= json_object_new_object();
9312 json_object_string_addf(json_nexthop_global
, "ip",
9314 &attr
->mp_nexthop_global
);
9316 if (path
->peer
->hostname
)
9317 json_object_string_add(json_nexthop_global
,
9319 path
->peer
->hostname
);
9321 json_object_string_add(json_nexthop_global
, "afi",
9323 json_object_string_add(json_nexthop_global
, "scope",
9326 /* We display both LL & GL if both have been
9328 if ((attr
->mp_nexthop_len
9329 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9330 || (path
->peer
->conf_if
)) {
9331 json_nexthop_ll
= json_object_new_object();
9332 json_object_string_addf(
9333 json_nexthop_ll
, "ip", "%pI6",
9334 &attr
->mp_nexthop_local
);
9336 if (path
->peer
->hostname
)
9337 json_object_string_add(
9338 json_nexthop_ll
, "hostname",
9339 path
->peer
->hostname
);
9341 json_object_string_add(json_nexthop_ll
, "afi",
9343 json_object_string_add(json_nexthop_ll
, "scope",
9346 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9347 &attr
->mp_nexthop_local
)
9349 && !attr
->mp_nexthop_prefer_global
)
9350 json_object_boolean_true_add(
9351 json_nexthop_ll
, "used");
9353 json_object_boolean_true_add(
9354 json_nexthop_global
, "used");
9356 json_object_boolean_true_add(
9357 json_nexthop_global
, "used");
9359 /* Display LL if LL/Global both in table unless
9360 * prefer-global is set */
9361 if (((attr
->mp_nexthop_len
9362 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9363 && !attr
->mp_nexthop_prefer_global
)
9364 || (path
->peer
->conf_if
)) {
9365 if (path
->peer
->conf_if
) {
9366 len
= vty_out(vty
, "%s",
9367 path
->peer
->conf_if
);
9368 /* len of IPv6 addr + max len of def
9370 len
= wide
? (41 - len
) : (16 - len
);
9373 vty_out(vty
, "\n%*s", 36, " ");
9375 vty_out(vty
, "%*s", len
, " ");
9377 if (nexthop_hostname
)
9380 &attr
->mp_nexthop_local
,
9386 &attr
->mp_nexthop_local
,
9389 len
= wide
? (41 - len
) : (16 - len
);
9392 vty_out(vty
, "\n%*s", 36, " ");
9394 vty_out(vty
, "%*s", len
, " ");
9397 if (nexthop_hostname
)
9398 len
= vty_out(vty
, "%pI6(%s)%s",
9399 &attr
->mp_nexthop_global
,
9403 len
= vty_out(vty
, "%pI6%s",
9404 &attr
->mp_nexthop_global
,
9407 len
= wide
? (41 - len
) : (16 - len
);
9410 vty_out(vty
, "\n%*s", 36, " ");
9412 vty_out(vty
, "%*s", len
, " ");
9418 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9420 json_object_int_add(json_path
, "metric", attr
->med
);
9422 vty_out(vty
, "%7u", attr
->med
);
9424 vty_out(vty
, "%10u", attr
->med
);
9425 else if (!json_paths
) {
9427 vty_out(vty
, "%*s", 7, " ");
9429 vty_out(vty
, "%*s", 10, " ");
9433 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9435 json_object_int_add(json_path
, "locPrf",
9438 vty_out(vty
, "%7u", attr
->local_pref
);
9439 else if (!json_paths
)
9443 json_object_int_add(json_path
, "weight", attr
->weight
);
9445 vty_out(vty
, "%7u ", attr
->weight
);
9448 json_object_string_addf(json_path
, "peerId", "%pSU",
9454 json_object_string_add(json_path
, "path",
9457 aspath_print_vty(vty
, attr
->aspath
);
9462 json_object_string_add(json_path
, "origin",
9463 bgp_origin_long_str
[attr
->origin
]);
9465 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9468 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9469 json_object_string_add(json_path
, "esi",
9470 esi_to_str(&attr
->esi
,
9471 esi_buf
, sizeof(esi_buf
)));
9473 if (safi
== SAFI_EVPN
&&
9474 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9475 json_ext_community
= json_object_new_object();
9476 json_object_string_add(
9477 json_ext_community
, "string",
9478 bgp_attr_get_ecommunity(attr
)->str
);
9479 json_object_object_add(json_path
,
9480 "extendedCommunity",
9481 json_ext_community
);
9485 json_object_boolean_true_add(json_path
,
9486 "announceNexthopSelf");
9487 if (nexthop_othervrf
) {
9488 json_object_string_add(json_path
, "nhVrfName",
9491 json_object_int_add(json_path
, "nhVrfId",
9492 ((nexthop_vrfid
== VRF_UNKNOWN
)
9494 : (int)nexthop_vrfid
));
9499 if (json_nexthop_global
|| json_nexthop_ll
) {
9500 json_nexthops
= json_object_new_array();
9502 if (json_nexthop_global
)
9503 json_object_array_add(json_nexthops
,
9504 json_nexthop_global
);
9506 if (json_nexthop_ll
)
9507 json_object_array_add(json_nexthops
,
9510 json_object_object_add(json_path
, "nexthops",
9514 json_object_array_add(json_paths
, json_path
);
9518 if (safi
== SAFI_EVPN
) {
9519 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9520 /* XXX - add these params to the json out */
9521 vty_out(vty
, "%*s", 20, " ");
9522 vty_out(vty
, "ESI:%s",
9523 esi_to_str(&attr
->esi
, esi_buf
,
9529 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9530 vty_out(vty
, "%*s", 20, " ");
9531 vty_out(vty
, "%s\n",
9532 bgp_attr_get_ecommunity(attr
)->str
);
9536 #ifdef ENABLE_BGP_VNC
9537 /* prints an additional line, indented, with VNC info, if
9539 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9540 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9545 /* called from terminal list command */
9546 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9547 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9548 bool use_json
, json_object
*json_ar
, bool wide
)
9550 json_object
*json_status
= NULL
;
9551 json_object
*json_net
= NULL
;
9555 /* Route status display. */
9557 json_status
= json_object_new_object();
9558 json_net
= json_object_new_object();
9565 /* print prefix and mask */
9567 if (safi
== SAFI_EVPN
)
9568 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9569 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9570 json_object_string_add(
9571 json_net
, "addrPrefix",
9572 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9574 json_object_int_add(json_net
, "prefixLen",
9576 json_object_string_addf(json_net
, "network", "%pFX", p
);
9579 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9581 /* Print attribute */
9584 if (p
->family
== AF_INET
&&
9585 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9586 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9587 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9588 json_object_string_addf(
9589 json_net
, "nextHop", "%pI4",
9590 &attr
->mp_nexthop_global_in
);
9592 json_object_string_addf(
9593 json_net
, "nextHop", "%pI4",
9595 } else if (p
->family
== AF_INET6
||
9596 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9597 json_object_string_addf(
9598 json_net
, "nextHopGlobal", "%pI6",
9599 &attr
->mp_nexthop_global
);
9600 } else if (p
->family
== AF_EVPN
&&
9601 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9602 json_object_string_addf(
9603 json_net
, "nextHop", "%pI4",
9604 &attr
->mp_nexthop_global_in
);
9608 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9609 json_object_int_add(json_net
, "metric",
9612 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9613 json_object_int_add(json_net
, "locPrf",
9616 json_object_int_add(json_net
, "weight", attr
->weight
);
9620 json_object_string_add(json_net
, "path",
9624 #if CONFDATE > 20231208
9625 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9627 json_object_string_add(json_net
, "bgpOriginCode",
9628 bgp_origin_str
[attr
->origin
]);
9629 json_object_string_add(
9631 bgp_origin_long_str
[attr
->origin
]);
9633 if (p
->family
== AF_INET
&&
9634 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9635 safi
== SAFI_EVPN
||
9636 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9637 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9638 || safi
== SAFI_EVPN
)
9639 vty_out(vty
, "%-16pI4",
9640 &attr
->mp_nexthop_global_in
);
9642 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9644 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9645 } else if (p
->family
== AF_INET6
||
9646 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9647 len
= vty_out(vty
, "%pI6",
9648 &attr
->mp_nexthop_global
);
9649 len
= wide
? (41 - len
) : (16 - len
);
9651 vty_out(vty
, "\n%*s", 36, " ");
9653 vty_out(vty
, "%*s", len
, " ");
9656 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9658 vty_out(vty
, "%7u", attr
->med
);
9660 vty_out(vty
, "%10u", attr
->med
);
9666 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9667 vty_out(vty
, "%7u", attr
->local_pref
);
9671 vty_out(vty
, "%7u ", attr
->weight
);
9675 aspath_print_vty(vty
, attr
->aspath
);
9678 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9682 struct bgp_path_info
*bpi
= bgp_dest_get_bgp_path_info(dest
);
9684 #if CONFDATE > 20231208
9685 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9687 json_object_boolean_true_add(json_status
, "*");
9688 json_object_boolean_true_add(json_status
, ">");
9689 json_object_boolean_true_add(json_net
, "valid");
9690 json_object_boolean_true_add(json_net
, "best");
9692 if (bpi
&& CHECK_FLAG(bpi
->flags
, BGP_PATH_MULTIPATH
)) {
9693 json_object_boolean_true_add(json_status
, "=");
9694 json_object_boolean_true_add(json_net
, "multipath");
9696 json_object_object_add(json_net
, "appliedStatusSymbols",
9698 json_object_object_addf(json_ar
, json_net
, "%pFX", p
);
9703 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9704 struct bgp_path_info
*path
, int display
, safi_t safi
,
9707 json_object
*json_out
= NULL
;
9709 mpls_label_t label
= MPLS_INVALID_LABEL
;
9715 json_out
= json_object_new_object();
9717 /* short status lead text */
9718 route_vty_short_status_out(vty
, path
, p
, json_out
);
9720 /* print prefix and mask */
9723 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9725 vty_out(vty
, "%*s", 17, " ");
9728 /* Print attribute */
9730 if (((p
->family
== AF_INET
) &&
9731 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9732 (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) ||
9733 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9734 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9735 || safi
== SAFI_EVPN
) {
9737 json_object_string_addf(
9738 json_out
, "mpNexthopGlobalIn", "%pI4",
9739 &attr
->mp_nexthop_global_in
);
9741 vty_out(vty
, "%-16pI4",
9742 &attr
->mp_nexthop_global_in
);
9745 json_object_string_addf(json_out
, "nexthop",
9746 "%pI4", &attr
->nexthop
);
9748 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9750 } else if (((p
->family
== AF_INET6
) &&
9751 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9752 (safi
== SAFI_EVPN
&& BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) ||
9753 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9756 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9758 json_object_string_addf(
9759 json_out
, "mpNexthopGlobalIn", "%pI6",
9760 &attr
->mp_nexthop_global
);
9764 &attr
->mp_nexthop_global
,
9765 buf_a
, sizeof(buf_a
)));
9766 } else if (attr
->mp_nexthop_len
9767 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9768 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9769 &attr
->mp_nexthop_global
,
9770 &attr
->mp_nexthop_local
);
9772 json_object_string_add(json_out
,
9773 "mpNexthopGlobalLocal",
9776 vty_out(vty
, "%s", buf_a
);
9780 label
= decode_label(&path
->extra
->label
[0]);
9782 if (bgp_is_valid_label(&label
)) {
9784 json_object_int_add(json_out
, "notag", label
);
9785 json_object_array_add(json
, json_out
);
9787 vty_out(vty
, "notag/%d", label
);
9794 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9795 struct bgp_path_info
*path
, int display
,
9796 json_object
*json_paths
)
9799 json_object
*json_path
= NULL
;
9800 json_object
*json_nexthop
= NULL
;
9801 json_object
*json_overlay
= NULL
;
9807 json_path
= json_object_new_object();
9808 json_overlay
= json_object_new_object();
9809 json_nexthop
= json_object_new_object();
9812 /* short status lead text */
9813 route_vty_short_status_out(vty
, path
, p
, json_path
);
9815 /* print prefix and mask */
9817 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9819 vty_out(vty
, "%*s", 17, " ");
9821 /* Print attribute */
9823 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9828 vty_out(vty
, "%-16pI4", &attr
->mp_nexthop_global_in
);
9830 json_object_string_addf(json_nexthop
, "ip", "%pI4",
9831 &attr
->mp_nexthop_global_in
);
9833 json_object_string_add(json_nexthop
, "afi", "ipv4");
9835 json_object_object_add(json_path
, "nexthop",
9841 vty_out(vty
, "%pI6(%pI6)", &attr
->mp_nexthop_global
,
9842 &attr
->mp_nexthop_local
);
9844 json_object_string_addf(json_nexthop
, "ipv6Global",
9846 &attr
->mp_nexthop_global
);
9848 json_object_string_addf(json_nexthop
, "ipv6LinkLocal",
9850 &attr
->mp_nexthop_local
);
9852 json_object_string_add(json_nexthop
, "afi", "ipv6");
9854 json_object_object_add(json_path
, "nexthop",
9862 json_object_string_add(json_nexthop
, "error",
9863 "Unsupported address-family");
9867 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9870 vty_out(vty
, "/%pIA", &eo
->gw_ip
);
9872 json_object_string_addf(json_overlay
, "gw", "%pIA", &eo
->gw_ip
);
9874 if (bgp_attr_get_ecommunity(attr
)) {
9876 struct ecommunity_val
*routermac
= ecommunity_lookup(
9877 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9878 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9881 mac
= ecom_mac2str((char *)routermac
->val
);
9884 vty_out(vty
, "/%s", mac
);
9886 json_object_string_add(json_overlay
, "rmac",
9889 XFREE(MTYPE_TMP
, mac
);
9896 json_object_object_add(json_path
, "overlay", json_overlay
);
9898 json_object_array_add(json_paths
, json_path
);
9902 /* dampening route */
9903 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9904 struct bgp_path_info
*path
, int display
,
9905 afi_t afi
, safi_t safi
, bool use_json
,
9906 json_object
*json_paths
)
9908 struct attr
*attr
= path
->attr
;
9910 char timebuf
[BGP_UPTIME_LEN
];
9911 json_object
*json_path
= NULL
;
9914 json_path
= json_object_new_object();
9916 /* short status lead text */
9917 route_vty_short_status_out(vty
, path
, p
, json_path
);
9919 /* print prefix and mask */
9922 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9924 vty_out(vty
, "%*s", 17, " ");
9926 len
= vty_out(vty
, "%s", path
->peer
->host
);
9930 vty_out(vty
, "\n%*s", 34, " ");
9932 vty_out(vty
, "%*s", len
, " ");
9935 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9936 BGP_UPTIME_LEN
, afi
, safi
,
9940 aspath_print_vty(vty
, attr
->aspath
);
9942 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9946 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9947 safi
, use_json
, json_path
);
9950 json_object_string_add(json_path
, "asPath",
9953 json_object_string_add(json_path
, "origin",
9954 bgp_origin_str
[attr
->origin
]);
9955 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9957 json_object_array_add(json_paths
, json_path
);
9962 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9963 struct bgp_path_info
*path
, int display
,
9964 afi_t afi
, safi_t safi
, bool use_json
,
9965 json_object
*json_paths
)
9967 struct attr
*attr
= path
->attr
;
9968 struct bgp_damp_info
*bdi
;
9969 char timebuf
[BGP_UPTIME_LEN
];
9971 json_object
*json_path
= NULL
;
9977 json_path
= json_object_new_object();
9979 bdi
= path
->extra
->damp_info
;
9981 /* short status lead text */
9982 route_vty_short_status_out(vty
, path
, p
, json_path
);
9986 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9988 vty_out(vty
, "%*s", 17, " ");
9990 len
= vty_out(vty
, "%s", path
->peer
->host
);
9993 vty_out(vty
, "\n%*s", 33, " ");
9995 vty_out(vty
, "%*s", len
, " ");
9997 len
= vty_out(vty
, "%d", bdi
->flap
);
10002 vty_out(vty
, "%*s", len
, " ");
10004 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
10005 BGP_UPTIME_LEN
, 0, NULL
));
10007 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10008 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10009 vty_out(vty
, "%s ",
10010 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10011 BGP_UPTIME_LEN
, afi
,
10012 safi
, use_json
, NULL
));
10014 vty_out(vty
, "%*s ", 8, " ");
10017 aspath_print_vty(vty
, attr
->aspath
);
10019 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10021 vty_out(vty
, "\n");
10023 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10024 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
10026 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
10029 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10030 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10031 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10032 BGP_UPTIME_LEN
, afi
, safi
,
10033 use_json
, json_path
);
10036 json_object_string_add(json_path
, "asPath",
10037 attr
->aspath
->str
);
10039 json_object_string_add(json_path
, "origin",
10040 bgp_origin_str
[attr
->origin
]);
10042 json_object_array_add(json_paths
, json_path
);
10046 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
10047 int *first
, const char *header
,
10048 json_object
*json_adv_to
)
10050 json_object
*json_peer
= NULL
;
10053 /* 'advertised-to' is a dictionary of peers we have advertised
10055 * prefix too. The key is the peer's IP or swpX, the value is
10057 * hostname if we know it and "" if not.
10059 json_peer
= json_object_new_object();
10061 if (peer
->hostname
)
10062 json_object_string_add(json_peer
, "hostname",
10066 json_object_object_add(json_adv_to
, peer
->conf_if
,
10069 json_object_object_addf(json_adv_to
, json_peer
, "%pSU",
10073 vty_out(vty
, "%s", header
);
10078 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
10080 vty_out(vty
, " %s(%s)", peer
->hostname
,
10083 vty_out(vty
, " %s(%pSU)", peer
->hostname
,
10087 vty_out(vty
, " %s", peer
->conf_if
);
10089 vty_out(vty
, " %pSU", &peer
->su
);
10094 static void route_vty_out_tx_ids(struct vty
*vty
,
10095 struct bgp_addpath_info_data
*d
)
10099 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10100 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
10101 d
->addpath_tx_id
[i
],
10102 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
10106 static void route_vty_out_detail_es_info(struct vty
*vty
,
10107 struct bgp_path_info
*pi
,
10109 json_object
*json_path
)
10111 char esi_buf
[ESI_STR_LEN
];
10112 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
10113 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
10114 ATTR_ES_PEER_ROUTER
);
10115 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
10116 ATTR_ES_PEER_ACTIVE
);
10117 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
10118 ATTR_ES_PEER_PROXY
);
10119 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
10121 json_object
*json_es_info
= NULL
;
10123 json_object_string_add(
10126 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
10127 json_es_info
= json_object_new_object();
10129 json_object_boolean_true_add(
10130 json_es_info
, "localEs");
10132 json_object_boolean_true_add(
10133 json_es_info
, "peerActive");
10135 json_object_boolean_true_add(
10136 json_es_info
, "peerProxy");
10138 json_object_boolean_true_add(
10139 json_es_info
, "peerRouter");
10140 if (attr
->mm_sync_seqnum
)
10141 json_object_int_add(
10142 json_es_info
, "peerSeq",
10143 attr
->mm_sync_seqnum
);
10144 json_object_object_add(
10145 json_path
, "es_info",
10149 if (bgp_evpn_attr_is_sync(attr
))
10151 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10153 es_local
? "local-es":"",
10154 peer_proxy
? "proxy " : "",
10155 peer_active
? "active ":"",
10156 peer_router
? "router ":"",
10157 attr
->mm_sync_seqnum
);
10159 vty_out(vty
, " ESI %s %s\n",
10161 es_local
? "local-es":"");
10165 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
10166 const struct prefix
*p
, struct bgp_path_info
*path
,
10167 afi_t afi
, safi_t safi
,
10168 enum rpki_states rpki_curr_state
,
10169 json_object
*json_paths
)
10171 char buf
[INET6_ADDRSTRLEN
];
10173 struct attr
*attr
= path
->attr
;
10175 json_object
*json_bestpath
= NULL
;
10176 json_object
*json_cluster_list
= NULL
;
10177 json_object
*json_cluster_list_list
= NULL
;
10178 json_object
*json_ext_community
= NULL
;
10179 json_object
*json_last_update
= NULL
;
10180 json_object
*json_pmsi
= NULL
;
10181 json_object
*json_nexthop_global
= NULL
;
10182 json_object
*json_nexthop_ll
= NULL
;
10183 json_object
*json_nexthops
= NULL
;
10184 json_object
*json_path
= NULL
;
10185 json_object
*json_peer
= NULL
;
10186 json_object
*json_string
= NULL
;
10187 json_object
*json_adv_to
= NULL
;
10189 struct listnode
*node
, *nnode
;
10191 bool addpath_capable
;
10193 unsigned int first_as
;
10194 bool nexthop_self
=
10195 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
10197 char *nexthop_hostname
=
10198 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
10202 mpls_label_t label
= MPLS_INVALID_LABEL
;
10204 struct bgp_path_info
*bpi_ultimate
=
10205 bgp_get_imported_bpi_ultimate(path
);
10208 json_path
= json_object_new_object();
10209 json_peer
= json_object_new_object();
10210 json_nexthop_global
= json_object_new_object();
10213 if (safi
== SAFI_EVPN
) {
10215 vty_out(vty
, " Route %pFX", p
);
10219 if (path
->extra
&& path
->extra
->num_labels
) {
10220 bgp_evpn_label2str(path
->extra
->label
,
10221 path
->extra
->num_labels
, tag_buf
,
10224 if (safi
== SAFI_EVPN
) {
10226 if (tag_buf
[0] != '\0')
10227 vty_out(vty
, " VNI %s", tag_buf
);
10230 json_object_string_add(json_path
, "vni",
10236 if (safi
== SAFI_EVPN
10237 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
10238 char gwip_buf
[INET6_ADDRSTRLEN
];
10240 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
10244 json_object_string_add(json_path
, "gatewayIP",
10247 vty_out(vty
, " Gateway IP %s", gwip_buf
);
10250 if (safi
== SAFI_EVPN
&& !json_path
)
10251 vty_out(vty
, "\n");
10254 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
10255 struct bgp_path_info
*parent_ri
;
10256 struct bgp_dest
*dest
, *pdest
;
10258 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
10259 dest
= parent_ri
->net
;
10260 if (dest
&& dest
->pdest
) {
10261 pdest
= dest
->pdest
;
10262 if (is_pi_family_evpn(parent_ri
)) {
10263 vty_out(vty
, " Imported from ");
10264 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
10265 (struct prefix_rd
*)bgp_dest_get_prefix(
10267 vty_out(vty
, ":%pFX, VNI %s",
10268 (struct prefix_evpn
*)
10269 bgp_dest_get_prefix(dest
),
10271 if (CHECK_FLAG(attr
->es_flags
, ATTR_ES_L3_NHG
))
10272 vty_out(vty
, ", L3NHG %s",
10275 ATTR_ES_L3_NHG_ACTIVE
)
10278 vty_out(vty
, "\n");
10281 vty_out(vty
, " Imported from ");
10282 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
10283 (struct prefix_rd
*)bgp_dest_get_prefix(
10285 vty_out(vty
, ":%pFX\n",
10286 (struct prefix_evpn
*)
10287 bgp_dest_get_prefix(dest
));
10292 /* Line1 display AS-path, Aggregator */
10293 if (attr
->aspath
) {
10295 if (!attr
->aspath
->json
)
10296 aspath_str_update(attr
->aspath
, true);
10297 json_object_lock(attr
->aspath
->json
);
10298 json_object_object_add(json_path
, "aspath",
10299 attr
->aspath
->json
);
10301 if (attr
->aspath
->segments
)
10302 vty_out(vty
, " %s", attr
->aspath
->str
);
10304 vty_out(vty
, " Local");
10308 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
10310 json_object_boolean_true_add(json_path
, "removed");
10312 vty_out(vty
, ", (removed)");
10315 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10317 json_object_boolean_true_add(json_path
, "stale");
10319 vty_out(vty
, ", (stale)");
10322 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
10324 json_object_int_add(json_path
, "aggregatorAs",
10325 attr
->aggregator_as
);
10326 json_object_string_addf(json_path
, "aggregatorId",
10327 "%pI4", &attr
->aggregator_addr
);
10329 vty_out(vty
, ", (aggregated by %u %pI4)",
10330 attr
->aggregator_as
, &attr
->aggregator_addr
);
10334 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10335 PEER_FLAG_REFLECTOR_CLIENT
)) {
10337 json_object_boolean_true_add(json_path
,
10338 "rxedFromRrClient");
10340 vty_out(vty
, ", (Received from a RR-client)");
10343 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10344 PEER_FLAG_RSERVER_CLIENT
)) {
10346 json_object_boolean_true_add(json_path
,
10347 "rxedFromRsClient");
10349 vty_out(vty
, ", (Received from a RS-client)");
10352 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10354 json_object_boolean_true_add(json_path
,
10355 "dampeningHistoryEntry");
10357 vty_out(vty
, ", (history entry)");
10358 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10360 json_object_boolean_true_add(json_path
,
10361 "dampeningSuppressed");
10363 vty_out(vty
, ", (suppressed due to dampening)");
10367 vty_out(vty
, "\n");
10369 /* Line2 display Next-hop, Neighbor, Router-id */
10370 /* Display the nexthop */
10372 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
||
10373 p
->family
== AF_EVPN
) &&
10374 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
||
10375 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10376 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10377 || safi
== SAFI_EVPN
) {
10379 json_object_string_addf(
10380 json_nexthop_global
, "ip", "%pI4",
10381 &attr
->mp_nexthop_global_in
);
10383 if (path
->peer
->hostname
)
10384 json_object_string_add(
10385 json_nexthop_global
, "hostname",
10386 path
->peer
->hostname
);
10388 if (nexthop_hostname
)
10389 vty_out(vty
, " %pI4(%s)",
10390 &attr
->mp_nexthop_global_in
,
10393 vty_out(vty
, " %pI4",
10394 &attr
->mp_nexthop_global_in
);
10398 json_object_string_addf(json_nexthop_global
,
10402 if (path
->peer
->hostname
)
10403 json_object_string_add(
10404 json_nexthop_global
, "hostname",
10405 path
->peer
->hostname
);
10407 if (nexthop_hostname
)
10408 vty_out(vty
, " %pI4(%s)",
10412 vty_out(vty
, " %pI4",
10418 json_object_string_add(json_nexthop_global
, "afi",
10422 json_object_string_addf(json_nexthop_global
, "ip",
10424 &attr
->mp_nexthop_global
);
10426 if (path
->peer
->hostname
)
10427 json_object_string_add(json_nexthop_global
,
10429 path
->peer
->hostname
);
10431 json_object_string_add(json_nexthop_global
, "afi",
10433 json_object_string_add(json_nexthop_global
, "scope",
10436 if (nexthop_hostname
)
10437 vty_out(vty
, " %pI6(%s)",
10438 &attr
->mp_nexthop_global
,
10441 vty_out(vty
, " %pI6",
10442 &attr
->mp_nexthop_global
);
10446 /* Display the IGP cost or 'inaccessible' */
10447 if (!CHECK_FLAG(bpi_ultimate
->flags
, BGP_PATH_VALID
)) {
10448 bool import
= CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
);
10451 json_object_boolean_false_add(json_nexthop_global
,
10453 json_object_boolean_add(json_nexthop_global
,
10454 "importCheckEnabled", import
);
10456 vty_out(vty
, " (inaccessible%s)",
10457 import
? ", import-check enabled" : "");
10460 if (bpi_ultimate
->extra
&& bpi_ultimate
->extra
->igpmetric
) {
10462 json_object_int_add(
10463 json_nexthop_global
, "metric",
10464 bpi_ultimate
->extra
->igpmetric
);
10466 vty_out(vty
, " (metric %u)",
10467 bpi_ultimate
->extra
->igpmetric
);
10470 /* IGP cost is 0, display this only for json */
10473 json_object_int_add(json_nexthop_global
,
10478 json_object_boolean_true_add(json_nexthop_global
,
10482 /* Display peer "from" output */
10483 /* This path was originated locally */
10484 if (path
->peer
== bgp
->peer_self
) {
10486 if (safi
== SAFI_EVPN
|| (p
->family
== AF_INET
&&
10487 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10489 json_object_string_add(json_peer
, "peerId",
10492 vty_out(vty
, " from 0.0.0.0 ");
10495 json_object_string_add(json_peer
, "peerId",
10498 vty_out(vty
, " from :: ");
10502 json_object_string_addf(json_peer
, "routerId", "%pI4",
10505 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10508 /* We RXed this path from one of our peers */
10512 json_object_string_addf(json_peer
, "peerId", "%pSU",
10514 json_object_string_addf(json_peer
, "routerId", "%pI4",
10515 &path
->peer
->remote_id
);
10517 if (path
->peer
->hostname
)
10518 json_object_string_add(json_peer
, "hostname",
10519 path
->peer
->hostname
);
10521 if (path
->peer
->domainname
)
10522 json_object_string_add(json_peer
, "domainname",
10523 path
->peer
->domainname
);
10525 if (path
->peer
->conf_if
)
10526 json_object_string_add(json_peer
, "interface",
10527 path
->peer
->conf_if
);
10529 if (path
->peer
->conf_if
) {
10530 if (path
->peer
->hostname
10531 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10532 BGP_FLAG_SHOW_HOSTNAME
))
10533 vty_out(vty
, " from %s(%s)",
10534 path
->peer
->hostname
,
10535 path
->peer
->conf_if
);
10537 vty_out(vty
, " from %s",
10538 path
->peer
->conf_if
);
10540 if (path
->peer
->hostname
10541 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10542 BGP_FLAG_SHOW_HOSTNAME
))
10543 vty_out(vty
, " from %s(%s)",
10544 path
->peer
->hostname
,
10547 vty_out(vty
, " from %pSU",
10551 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10552 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10554 vty_out(vty
, " (%pI4)", &path
->peer
->remote_id
);
10559 * Note when vrfid of nexthop is different from that of prefix
10561 if (path
->extra
&& path
->extra
->bgp_orig
) {
10562 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10567 if (path
->extra
->bgp_orig
->inst_type
10568 == BGP_INSTANCE_TYPE_DEFAULT
)
10569 vn
= VRF_DEFAULT_NAME
;
10571 vn
= path
->extra
->bgp_orig
->name
;
10573 json_object_string_add(json_path
, "nhVrfName", vn
);
10575 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10576 json_object_int_add(json_path
, "nhVrfId", -1);
10578 json_object_int_add(json_path
, "nhVrfId",
10579 (int)nexthop_vrfid
);
10582 if (nexthop_vrfid
== VRF_UNKNOWN
)
10583 vty_out(vty
, " vrf ?");
10587 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10588 vty_out(vty
, " vrf %s(%u)",
10589 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10594 if (nexthop_self
) {
10596 json_object_boolean_true_add(json_path
,
10597 "announceNexthopSelf");
10599 vty_out(vty
, " announce-nh-self");
10604 vty_out(vty
, "\n");
10606 /* display the link-local nexthop */
10607 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10609 json_nexthop_ll
= json_object_new_object();
10610 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10611 &attr
->mp_nexthop_local
);
10613 if (path
->peer
->hostname
)
10614 json_object_string_add(json_nexthop_ll
,
10616 path
->peer
->hostname
);
10618 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10619 json_object_string_add(json_nexthop_ll
, "scope",
10622 json_object_boolean_true_add(json_nexthop_ll
,
10625 if (!attr
->mp_nexthop_prefer_global
)
10626 json_object_boolean_true_add(json_nexthop_ll
,
10629 json_object_boolean_true_add(
10630 json_nexthop_global
, "used");
10632 vty_out(vty
, " (%s) %s\n",
10633 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10634 buf
, INET6_ADDRSTRLEN
),
10635 attr
->mp_nexthop_prefer_global
10636 ? "(prefer-global)"
10640 /* If we do not have a link-local nexthop then we must flag the
10641 global as "used" */
10644 json_object_boolean_true_add(json_nexthop_global
,
10648 if (safi
== SAFI_EVPN
&&
10649 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10650 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10653 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10654 * Int/Ext/Local, Atomic, best */
10656 json_object_string_add(json_path
, "origin",
10657 bgp_origin_long_str
[attr
->origin
]);
10659 vty_out(vty
, " Origin %s",
10660 bgp_origin_long_str
[attr
->origin
]);
10662 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10664 json_object_int_add(json_path
, "metric", attr
->med
);
10666 vty_out(vty
, ", metric %u", attr
->med
);
10669 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10671 json_object_int_add(json_path
, "locPrf",
10674 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10677 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
10679 json_object_int_add(json_path
, "aigpMetric",
10680 bgp_attr_get_aigp_metric(attr
));
10682 vty_out(vty
, ", aigp-metric %" PRIu64
,
10683 bgp_attr_get_aigp_metric(attr
));
10686 if (attr
->weight
!= 0) {
10688 json_object_int_add(json_path
, "weight", attr
->weight
);
10690 vty_out(vty
, ", weight %u", attr
->weight
);
10693 if (attr
->tag
!= 0) {
10695 json_object_int_add(json_path
, "tag", attr
->tag
);
10697 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10700 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10702 json_object_boolean_false_add(json_path
, "valid");
10704 vty_out(vty
, ", invalid");
10705 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10707 json_object_boolean_true_add(json_path
, "valid");
10709 vty_out(vty
, ", valid");
10713 json_object_int_add(json_path
, "version", bn
->version
);
10715 if (path
->peer
!= bgp
->peer_self
) {
10716 if (path
->peer
->as
== path
->peer
->local_as
) {
10717 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10719 json_object_string_add(
10721 "confed-internal");
10723 vty_out(vty
, ", confed-internal");
10726 json_object_string_add(
10727 json_peer
, "type", "internal");
10729 vty_out(vty
, ", internal");
10732 if (bgp_confederation_peers_check(bgp
,
10735 json_object_string_add(
10737 "confed-external");
10739 vty_out(vty
, ", confed-external");
10742 json_object_string_add(
10743 json_peer
, "type", "external");
10745 vty_out(vty
, ", external");
10748 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10750 json_object_boolean_true_add(json_path
, "aggregated");
10751 json_object_boolean_true_add(json_path
, "local");
10753 vty_out(vty
, ", aggregated, local");
10755 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10757 json_object_boolean_true_add(json_path
, "sourced");
10759 vty_out(vty
, ", sourced");
10762 json_object_boolean_true_add(json_path
, "sourced");
10763 json_object_boolean_true_add(json_path
, "local");
10765 vty_out(vty
, ", sourced, local");
10769 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10771 json_object_boolean_true_add(json_path
,
10772 "atomicAggregate");
10774 vty_out(vty
, ", atomic-aggregate");
10777 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
10779 json_object_int_add(json_path
, "otc", attr
->otc
);
10781 vty_out(vty
, ", otc %u", attr
->otc
);
10784 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10785 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10786 && bgp_path_info_mpath_count(path
))) {
10788 json_object_boolean_true_add(json_path
, "multipath");
10790 vty_out(vty
, ", multipath");
10793 // Mark the bestpath(s)
10794 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10795 first_as
= aspath_get_first_as(attr
->aspath
);
10798 if (!json_bestpath
)
10799 json_bestpath
= json_object_new_object();
10800 json_object_int_add(json_bestpath
, "bestpathFromAs",
10804 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10806 vty_out(vty
, ", bestpath-from-AS Local");
10810 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10812 if (!json_bestpath
)
10813 json_bestpath
= json_object_new_object();
10814 json_object_boolean_true_add(json_bestpath
, "overall");
10815 json_object_string_add(
10816 json_bestpath
, "selectionReason",
10817 bgp_path_selection_reason2str(bn
->reason
));
10819 vty_out(vty
, ", best");
10820 vty_out(vty
, " (%s)",
10821 bgp_path_selection_reason2str(bn
->reason
));
10825 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10827 json_object_string_add(
10828 json_path
, "rpkiValidationState",
10829 bgp_rpki_validation2str(rpki_curr_state
));
10831 vty_out(vty
, ", rpki validation-state: %s",
10832 bgp_rpki_validation2str(rpki_curr_state
));
10836 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10839 vty_out(vty
, "\n");
10841 /* Line 4 display Community */
10842 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10844 if (!bgp_attr_get_community(attr
)->json
)
10845 community_str(bgp_attr_get_community(attr
),
10847 json_object_lock(bgp_attr_get_community(attr
)->json
);
10848 json_object_object_add(
10849 json_path
, "community",
10850 bgp_attr_get_community(attr
)->json
);
10852 vty_out(vty
, " Community: %s\n",
10853 bgp_attr_get_community(attr
)->str
);
10857 /* Line 5 display Extended-community */
10858 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10860 json_ext_community
= json_object_new_object();
10861 json_object_string_add(
10862 json_ext_community
, "string",
10863 bgp_attr_get_ecommunity(attr
)->str
);
10864 json_object_object_add(json_path
, "extendedCommunity",
10865 json_ext_community
);
10867 vty_out(vty
, " Extended Community: %s\n",
10868 bgp_attr_get_ecommunity(attr
)->str
);
10872 /* Line 6 display Large community */
10873 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10875 if (!bgp_attr_get_lcommunity(attr
)->json
)
10876 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10878 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10879 json_object_object_add(
10880 json_path
, "largeCommunity",
10881 bgp_attr_get_lcommunity(attr
)->json
);
10883 vty_out(vty
, " Large Community: %s\n",
10884 bgp_attr_get_lcommunity(attr
)->str
);
10888 /* Line 7 display Originator, Cluster-id */
10889 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10890 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10891 char buf
[BUFSIZ
] = {0};
10893 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10895 json_object_string_addf(json_path
,
10896 "originatorId", "%pI4",
10897 &attr
->originator_id
);
10899 vty_out(vty
, " Originator: %pI4",
10900 &attr
->originator_id
);
10903 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10904 struct cluster_list
*cluster
=
10905 bgp_attr_get_cluster(attr
);
10909 json_cluster_list
= json_object_new_object();
10910 json_cluster_list_list
=
10911 json_object_new_array();
10913 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10914 json_string
= json_object_new_string(
10917 buf
, sizeof(buf
)));
10918 json_object_array_add(
10919 json_cluster_list_list
,
10924 * struct cluster_list does not have
10925 * "str" variable like aspath and community
10926 * do. Add this someday if someone asks
10928 * json_object_string_add(json_cluster_list,
10929 * "string", cluster->str);
10931 json_object_object_add(json_cluster_list
,
10933 json_cluster_list_list
);
10934 json_object_object_add(json_path
, "clusterList",
10935 json_cluster_list
);
10937 vty_out(vty
, ", Cluster list: ");
10939 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10940 vty_out(vty
, "%pI4 ",
10941 &cluster
->list
[i
]);
10947 vty_out(vty
, "\n");
10950 if (path
->extra
&& path
->extra
->damp_info
)
10951 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
10954 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10955 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10956 mpls_lse_decode(path
->extra
->label
[0], &label
, &ttl
, &exp
,
10960 json_object_int_add(json_path
, "remoteLabel", label
);
10962 vty_out(vty
, " Remote label: %d\n", label
);
10966 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10968 json_object_string_addf(json_path
, "remoteSid", "%pI6",
10969 &path
->extra
->sid
[0].sid
);
10971 vty_out(vty
, " Remote SID: %pI6\n",
10972 &path
->extra
->sid
[0].sid
);
10976 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
10978 json_object_int_add(json_path
, "labelIndex",
10979 attr
->label_index
);
10981 vty_out(vty
, " Label Index: %d\n",
10982 attr
->label_index
);
10985 /* Line 8 display Addpath IDs */
10986 if (path
->addpath_rx_id
10987 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
10989 json_object_int_add(json_path
, "addpathRxId",
10990 path
->addpath_rx_id
);
10992 /* Keep backwards compatibility with the old API
10993 * by putting TX All's ID in the old field
10995 json_object_int_add(
10996 json_path
, "addpathTxId",
10998 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
11000 /* ... but create a specific field for each
11003 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
11004 json_object_int_add(
11006 bgp_addpath_names(i
)->id_json_name
,
11007 path
->tx_addpath
.addpath_tx_id
[i
]);
11010 vty_out(vty
, " AddPath ID: RX %u, ",
11011 path
->addpath_rx_id
);
11013 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
11017 /* If we used addpath to TX a non-bestpath we need to display
11018 * "Advertised to" on a path-by-path basis
11020 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11023 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11025 bgp_addpath_encode_tx(peer
, afi
, safi
);
11026 has_adj
= bgp_adj_out_lookup(
11028 bgp_addpath_id_for_peer(peer
, afi
, safi
,
11029 &path
->tx_addpath
));
11031 if ((addpath_capable
&& has_adj
)
11032 || (!addpath_capable
&& has_adj
11033 && CHECK_FLAG(path
->flags
,
11034 BGP_PATH_SELECTED
))) {
11035 if (json_path
&& !json_adv_to
)
11036 json_adv_to
= json_object_new_object();
11038 route_vty_out_advertised_to(
11040 " Advertised to:", json_adv_to
);
11046 json_object_object_add(
11047 json_path
, "advertisedTo", json_adv_to
);
11051 vty_out(vty
, "\n");
11056 /* Line 9 display Uptime */
11057 tbuf
= time(NULL
) - (monotime(NULL
) - path
->uptime
);
11059 json_last_update
= json_object_new_object();
11060 json_object_int_add(json_last_update
, "epoch", tbuf
);
11061 json_object_string_add(json_last_update
, "string",
11063 json_object_object_add(json_path
, "lastUpdate",
11066 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
11068 /* Line 10 display PMSI tunnel attribute, if present */
11069 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
11070 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
11071 bgp_attr_get_pmsi_tnl_type(attr
),
11072 PMSI_TNLTYPE_STR_DEFAULT
);
11075 json_pmsi
= json_object_new_object();
11076 json_object_string_add(json_pmsi
, "tunnelType", str
);
11077 json_object_int_add(json_pmsi
, "label",
11078 label2vni(&attr
->label
));
11079 json_object_object_add(json_path
, "pmsi", json_pmsi
);
11081 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
11082 str
, label2vni(&attr
->label
));
11085 if (path
->peer
->t_gr_restart
&&
11086 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
11087 unsigned long gr_remaining
=
11088 thread_timer_remain_second(path
->peer
->t_gr_restart
);
11091 json_object_int_add(json_path
,
11092 "gracefulRestartSecondsRemaining",
11096 " Time until Graceful Restart stale route deleted: %lu\n",
11100 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
11101 bgp_attr_get_community(attr
) &&
11102 community_include(bgp_attr_get_community(attr
),
11103 COMMUNITY_LLGR_STALE
)) {
11104 unsigned long llgr_remaining
= thread_timer_remain_second(
11105 path
->peer
->t_llgr_stale
[afi
][safi
]);
11108 json_object_int_add(json_path
, "llgrSecondsRemaining",
11112 " Time until Long-lived stale route deleted: %lu\n",
11116 /* Output some debug about internal state of the dest flags */
11118 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
11119 json_object_boolean_true_add(json_path
, "processScheduled");
11120 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
11121 json_object_boolean_true_add(json_path
, "userCleared");
11122 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
11123 json_object_boolean_true_add(json_path
, "labelChanged");
11124 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
11125 json_object_boolean_true_add(json_path
, "registeredForLabel");
11126 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
11127 json_object_boolean_true_add(json_path
, "selectDefered");
11128 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
11129 json_object_boolean_true_add(json_path
, "fibInstalled");
11130 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
11131 json_object_boolean_true_add(json_path
, "fibPending");
11133 if (json_nexthop_global
|| json_nexthop_ll
) {
11134 json_nexthops
= json_object_new_array();
11136 if (json_nexthop_global
)
11137 json_object_array_add(json_nexthops
,
11138 json_nexthop_global
);
11140 if (json_nexthop_ll
)
11141 json_object_array_add(json_nexthops
,
11144 json_object_object_add(json_path
, "nexthops",
11148 json_object_object_add(json_path
, "peer", json_peer
);
11149 json_object_array_add(json_paths
, json_path
);
11153 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
11154 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11155 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
11157 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11158 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11160 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11161 const char *comstr
, int exact
, afi_t afi
,
11162 safi_t safi
, uint16_t show_flags
);
11164 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11165 struct bgp_table
*table
, enum bgp_show_type type
,
11166 void *output_arg
, const char *rd
, int is_last
,
11167 unsigned long *output_cum
, unsigned long *total_cum
,
11168 unsigned long *json_header_depth
, uint16_t show_flags
,
11169 enum rpki_states rpki_target_state
)
11171 struct bgp_path_info
*pi
;
11172 struct bgp_dest
*dest
;
11173 bool header
= true;
11174 bool json_detail_header
= false;
11176 unsigned long output_count
= 0;
11177 unsigned long total_count
= 0;
11179 json_object
*json_paths
= NULL
;
11181 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11182 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11183 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11184 bool detail_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
11185 bool detail_routes
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
11187 if (output_cum
&& *output_cum
!= 0)
11190 if (use_json
&& !*json_header_depth
) {
11192 *json_header_depth
= 1;
11194 vty_out(vty
, "{\n");
11195 *json_header_depth
= 2;
11198 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11199 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
11201 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
11202 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
11205 table
->version
, &bgp
->router_id
,
11206 bgp
->default_local_pref
);
11207 if ((bgp
->asnotation
== ASNOTATION_PLAIN
) ||
11208 ((bgp
->asnotation
== ASNOTATION_DOT
) &&
11209 (bgp
->as
< UINT16_MAX
)))
11210 vty_out(vty
, "%u", bgp
->as
);
11212 vty_out(vty
, "\"");
11213 vty_out(vty
, ASN_FORMAT(bgp
->asnotation
), &bgp
->as
);
11214 vty_out(vty
, "\"");
11216 vty_out(vty
, ",\n \"routes\": { ");
11218 vty_out(vty
, " \"routeDistinguishers\" : {");
11219 ++*json_header_depth
;
11223 if (use_json
&& rd
) {
11224 vty_out(vty
, " \"%s\" : { ", rd
);
11227 /* Check for 'json detail', where we need header output once per dest */
11228 if (use_json
&& detail_json
&& type
!= bgp_show_type_dampend_paths
&&
11229 type
!= bgp_show_type_damp_neighbor
&&
11230 type
!= bgp_show_type_flap_statistics
&&
11231 type
!= bgp_show_type_flap_neighbor
)
11232 json_detail_header
= true;
11234 /* Start processing of routes. */
11235 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
11236 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11237 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11238 bool json_detail_header_used
= false;
11240 pi
= bgp_dest_get_bgp_path_info(dest
);
11246 json_paths
= json_object_new_array();
11250 for (; pi
; pi
= pi
->next
) {
11251 struct community
*picomm
= NULL
;
11253 picomm
= bgp_attr_get_community(pi
->attr
);
11257 if (type
== bgp_show_type_prefix_version
) {
11259 strtoul(output_arg
, NULL
, 10);
11260 if (dest
->version
< version
)
11264 if (type
== bgp_show_type_community_alias
) {
11265 char *alias
= output_arg
;
11266 char **communities
;
11268 bool found
= false;
11271 frrstr_split(picomm
->str
, " ",
11272 &communities
, &num
);
11273 for (int i
= 0; i
< num
; i
++) {
11274 const char *com2alias
=
11275 bgp_community2alias(
11278 && strcmp(alias
, com2alias
)
11284 XFREE(MTYPE_TMP
, communities
);
11288 bgp_attr_get_lcommunity(pi
->attr
)) {
11289 frrstr_split(bgp_attr_get_lcommunity(
11292 " ", &communities
, &num
);
11293 for (int i
= 0; i
< num
; i
++) {
11294 const char *com2alias
=
11295 bgp_community2alias(
11298 && strcmp(alias
, com2alias
)
11304 XFREE(MTYPE_TMP
, communities
);
11311 if (type
== bgp_show_type_rpki
) {
11312 if (dest_p
->family
== AF_INET
11313 || dest_p
->family
== AF_INET6
)
11314 rpki_curr_state
= hook_call(
11315 bgp_rpki_prefix_status
,
11316 pi
->peer
, pi
->attr
, dest_p
);
11317 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11318 && rpki_curr_state
!= rpki_target_state
)
11322 if (type
== bgp_show_type_flap_statistics
11323 || type
== bgp_show_type_flap_neighbor
11324 || type
== bgp_show_type_dampend_paths
11325 || type
== bgp_show_type_damp_neighbor
) {
11326 if (!(pi
->extra
&& pi
->extra
->damp_info
))
11329 if (type
== bgp_show_type_regexp
) {
11330 regex_t
*regex
= output_arg
;
11332 if (bgp_regexec(regex
, pi
->attr
->aspath
)
11336 if (type
== bgp_show_type_prefix_list
) {
11337 struct prefix_list
*plist
= output_arg
;
11339 if (prefix_list_apply(plist
, dest_p
)
11343 if (type
== bgp_show_type_access_list
) {
11344 struct access_list
*alist
= output_arg
;
11346 if (access_list_apply(alist
, dest_p
) !=
11350 if (type
== bgp_show_type_filter_list
) {
11351 struct as_list
*as_list
= output_arg
;
11353 if (as_list_apply(as_list
, pi
->attr
->aspath
)
11354 != AS_FILTER_PERMIT
)
11357 if (type
== bgp_show_type_route_map
) {
11358 struct route_map
*rmap
= output_arg
;
11359 struct bgp_path_info path
;
11360 struct bgp_path_info_extra extra
;
11361 struct attr dummy_attr
= {};
11362 route_map_result_t ret
;
11364 dummy_attr
= *pi
->attr
;
11366 prep_for_rmap_apply(&path
, &extra
, dest
, pi
,
11367 pi
->peer
, &dummy_attr
);
11369 ret
= route_map_apply(rmap
, dest_p
, &path
);
11370 bgp_attr_flush(&dummy_attr
);
11371 if (ret
== RMAP_DENYMATCH
)
11374 if (type
== bgp_show_type_neighbor
11375 || type
== bgp_show_type_flap_neighbor
11376 || type
== bgp_show_type_damp_neighbor
) {
11377 union sockunion
*su
= output_arg
;
11379 if (pi
->peer
== NULL
11380 || pi
->peer
->su_remote
== NULL
11381 || !sockunion_same(pi
->peer
->su_remote
, su
))
11384 if (type
== bgp_show_type_cidr_only
) {
11385 uint32_t destination
;
11387 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11388 if (IN_CLASSC(destination
)
11389 && dest_p
->prefixlen
== 24)
11391 if (IN_CLASSB(destination
)
11392 && dest_p
->prefixlen
== 16)
11394 if (IN_CLASSA(destination
)
11395 && dest_p
->prefixlen
== 8)
11398 if (type
== bgp_show_type_prefix_longer
) {
11400 if (!prefix_match(p
, dest_p
))
11403 if (type
== bgp_show_type_community_all
) {
11407 if (type
== bgp_show_type_community
) {
11408 struct community
*com
= output_arg
;
11410 if (!picomm
|| !community_match(picomm
, com
))
11413 if (type
== bgp_show_type_community_exact
) {
11414 struct community
*com
= output_arg
;
11416 if (!picomm
|| !community_cmp(picomm
, com
))
11419 if (type
== bgp_show_type_community_list
) {
11420 struct community_list
*list
= output_arg
;
11422 if (!community_list_match(picomm
, list
))
11425 if (type
== bgp_show_type_community_list_exact
) {
11426 struct community_list
*list
= output_arg
;
11428 if (!community_list_exact_match(picomm
, list
))
11431 if (type
== bgp_show_type_lcommunity
) {
11432 struct lcommunity
*lcom
= output_arg
;
11434 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11436 bgp_attr_get_lcommunity(pi
->attr
),
11441 if (type
== bgp_show_type_lcommunity_exact
) {
11442 struct lcommunity
*lcom
= output_arg
;
11444 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11446 bgp_attr_get_lcommunity(pi
->attr
),
11450 if (type
== bgp_show_type_lcommunity_list
) {
11451 struct community_list
*list
= output_arg
;
11453 if (!lcommunity_list_match(
11454 bgp_attr_get_lcommunity(pi
->attr
),
11459 == bgp_show_type_lcommunity_list_exact
) {
11460 struct community_list
*list
= output_arg
;
11462 if (!lcommunity_list_exact_match(
11463 bgp_attr_get_lcommunity(pi
->attr
),
11467 if (type
== bgp_show_type_lcommunity_all
) {
11468 if (!bgp_attr_get_lcommunity(pi
->attr
))
11471 if (type
== bgp_show_type_dampend_paths
11472 || type
== bgp_show_type_damp_neighbor
) {
11473 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11474 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11477 if (type
== bgp_show_type_self_originated
) {
11478 if (pi
->peer
!= bgp
->peer_self
)
11482 if (!use_json
&& header
) {
11484 "BGP table version is %" PRIu64
11485 ", local router ID is %pI4, vrf id ",
11486 table
->version
, &bgp
->router_id
);
11487 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11488 vty_out(vty
, "%s", VRFID_NONE_STR
);
11490 vty_out(vty
, "%u", bgp
->vrf_id
);
11491 vty_out(vty
, "\n");
11492 vty_out(vty
, "Default local pref %u, ",
11493 bgp
->default_local_pref
);
11494 vty_out(vty
, "local AS ");
11495 vty_out(vty
, ASN_FORMAT(bgp
->asnotation
),
11497 vty_out(vty
, "\n");
11498 if (!detail_routes
) {
11499 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11500 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11501 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11502 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11504 if (type
== bgp_show_type_dampend_paths
11505 || type
== bgp_show_type_damp_neighbor
)
11506 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11507 else if (type
== bgp_show_type_flap_statistics
11508 || type
== bgp_show_type_flap_neighbor
)
11509 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11510 else if (!detail_routes
)
11511 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11512 : BGP_SHOW_HEADER
));
11516 if (rd
!= NULL
&& !display
&& !output_count
) {
11519 "Route Distinguisher: %s\n",
11522 if (type
== bgp_show_type_dampend_paths
11523 || type
== bgp_show_type_damp_neighbor
)
11524 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11525 AFI_IP
, safi
, use_json
,
11527 else if (type
== bgp_show_type_flap_statistics
11528 || type
== bgp_show_type_flap_neighbor
)
11529 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11530 AFI_IP
, safi
, use_json
,
11533 if (detail_routes
|| detail_json
) {
11534 const struct prefix_rd
*prd
= NULL
;
11537 prd
= bgp_rd_from_dest(
11538 dest
->pdest
, safi
);
11541 route_vty_out_detail_header(
11543 bgp_dest_get_prefix(
11545 prd
, table
->afi
, safi
,
11548 route_vty_out_detail(
11549 vty
, bgp
, dest
, dest_p
, pi
,
11550 family2afi(dest_p
->family
),
11551 safi
, RPKI_NOT_BEING_USED
,
11554 route_vty_out(vty
, dest_p
, pi
, display
,
11555 safi
, json_paths
, wide
);
11566 /* encode prefix */
11567 if (dest_p
->family
== AF_FLOWSPEC
) {
11568 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11571 bgp_fs_nlri_get_string(
11573 dest_p
->u
.prefix_flowspec
.ptr
,
11574 dest_p
->u
.prefix_flowspec
.prefixlen
,
11575 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11576 family2afi(dest_p
->u
11577 .prefix_flowspec
.family
));
11579 vty_out(vty
, "\"%s/%d\": ", retstr
,
11580 dest_p
->u
.prefix_flowspec
11583 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11584 dest_p
->u
.prefix_flowspec
11588 vty_out(vty
, "\"%pFX\": ", dest_p
);
11590 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11593 if (json_detail_header
&& json_paths
!= NULL
) {
11594 const struct prefix_rd
*prd
;
11596 vty_out(vty
, "{\n");
11598 prd
= bgp_rd_from_dest(dest
, safi
);
11600 route_vty_out_detail_header(
11602 bgp_dest_get_prefix(dest
), prd
,
11603 table
->afi
, safi
, json_paths
, true);
11605 vty_out(vty
, "\"paths\": ");
11606 json_detail_header_used
= true;
11610 * We are using no_pretty here because under
11611 * extremely high settings( say lots and lots of
11612 * routes with lots and lots of ways to reach
11613 * that route via different paths ) this can
11614 * save several minutes of output when FRR
11615 * is run on older cpu's or more underperforming
11616 * routers out there
11618 vty_json_no_pretty(vty
, json_paths
);
11620 if (json_detail_header_used
)
11621 vty_out(vty
, "} ");
11626 json_object_free(json_paths
);
11630 output_count
+= *output_cum
;
11631 *output_cum
= output_count
;
11634 total_count
+= *total_cum
;
11635 *total_cum
= total_count
;
11639 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11643 for (i
= 0; i
< *json_header_depth
; ++i
)
11644 vty_out(vty
, " } ");
11646 vty_out(vty
, "\n");
11650 /* No route is displayed */
11651 if (output_count
== 0) {
11652 if (type
== bgp_show_type_normal
)
11654 "No BGP prefixes displayed, %ld exist\n",
11658 "\nDisplayed %ld routes and %ld total paths\n",
11659 output_count
, total_count
);
11663 return CMD_SUCCESS
;
11666 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11667 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11668 enum bgp_show_type type
, void *output_arg
,
11669 uint16_t show_flags
)
11671 struct bgp_dest
*dest
, *next
;
11672 unsigned long output_cum
= 0;
11673 unsigned long total_cum
= 0;
11674 unsigned long json_header_depth
= 0;
11675 struct bgp_table
*itable
;
11677 bool use_json
= !!CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11679 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11681 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11682 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11684 next
= bgp_route_next(dest
);
11685 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11688 itable
= bgp_dest_get_bgp_table_info(dest
);
11689 if (itable
!= NULL
) {
11690 struct prefix_rd prd
;
11691 char rd
[RD_ADDRSTRLEN
];
11693 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11694 prefix_rd2str(&prd
, rd
, sizeof(rd
), bgp
->asnotation
);
11695 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11696 rd
, next
== NULL
, &output_cum
,
11697 &total_cum
, &json_header_depth
,
11698 show_flags
, RPKI_NOT_BEING_USED
);
11704 if (output_cum
== 0)
11705 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11709 "\nDisplayed %ld routes and %ld total paths\n",
11710 output_cum
, total_cum
);
11712 if (use_json
&& output_cum
== 0)
11713 vty_out(vty
, "{}\n");
11715 return CMD_SUCCESS
;
11718 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11719 enum bgp_show_type type
, void *output_arg
,
11720 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11722 struct bgp_table
*table
;
11723 unsigned long json_header_depth
= 0;
11724 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11727 bgp
= bgp_get_default();
11732 vty_out(vty
, "No BGP process is configured\n");
11734 vty_out(vty
, "{}\n");
11735 return CMD_WARNING
;
11738 /* Labeled-unicast routes live in the unicast table. */
11739 if (safi
== SAFI_LABELED_UNICAST
)
11740 safi
= SAFI_UNICAST
;
11742 table
= bgp
->rib
[afi
][safi
];
11743 /* use MPLS and ENCAP specific shows until they are merged */
11744 if (safi
== SAFI_MPLS_VPN
) {
11745 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11746 output_arg
, show_flags
);
11749 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11750 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11751 output_arg
, use_json
,
11755 if (safi
== SAFI_EVPN
)
11756 return bgp_evpn_show_all_routes(vty
, bgp
, type
, use_json
, 0);
11758 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11759 NULL
, NULL
, &json_header_depth
, show_flags
,
11760 rpki_target_state
);
11763 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11764 safi_t safi
, uint16_t show_flags
)
11766 struct listnode
*node
, *nnode
;
11769 bool route_output
= false;
11770 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11773 vty_out(vty
, "{\n");
11775 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11776 route_output
= true;
11779 vty_out(vty
, ",\n");
11783 vty_out(vty
, "\"%s\":",
11784 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11788 vty_out(vty
, "\nInstance %s:\n",
11789 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11793 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11794 show_flags
, RPKI_NOT_BEING_USED
);
11798 vty_out(vty
, "}\n");
11799 else if (!route_output
)
11800 vty_out(vty
, "%% BGP instance not found\n");
11803 /* Header of detailed BGP route information */
11804 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11805 struct bgp_dest
*dest
, const struct prefix
*p
,
11806 const struct prefix_rd
*prd
, afi_t afi
,
11807 safi_t safi
, json_object
*json
,
11808 bool incremental_print
)
11810 struct bgp_path_info
*pi
;
11812 struct listnode
*node
, *nnode
;
11813 char buf1
[RD_ADDRSTRLEN
];
11817 int accept_own
= 0;
11818 int route_filter_translated_v4
= 0;
11819 int route_filter_v4
= 0;
11820 int route_filter_translated_v6
= 0;
11821 int route_filter_v6
= 0;
11822 int llgr_stale
= 0;
11824 int accept_own_nexthop
= 0;
11827 int no_advertise
= 0;
11831 int has_valid_label
= 0;
11832 mpls_label_t label
= 0;
11833 json_object
*json_adv_to
= NULL
;
11838 mpls_lse_decode(dest
->local_label
, &label
, &ttl
, &exp
, &bos
);
11840 has_valid_label
= bgp_is_valid_label(&label
);
11842 if (safi
== SAFI_EVPN
) {
11844 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11845 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
),
11848 prd
? ":" : "", (struct prefix_evpn
*)p
);
11850 json_object_string_add(
11852 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
),
11855 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11860 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11862 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11863 ? prefix_rd2str(prd
, buf1
,
11867 safi
== SAFI_MPLS_VPN
? ":" : "", p
,
11871 if (incremental_print
) {
11872 vty_out(vty
, "\"prefix\": \"%pFX\",\n", p
);
11873 vty_out(vty
, "\"version\": \"%" PRIu64
"\",\n",
11876 json_object_string_addf(json
, "prefix", "%pFX",
11878 json_object_int_add(json
, "version",
11884 if (has_valid_label
) {
11886 if (incremental_print
)
11887 vty_out(vty
, "\"localLabel\": \"%u\",\n",
11890 json_object_int_add(json
, "localLabel", label
);
11892 vty_out(vty
, "Local label: %d\n", label
);
11896 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11897 vty_out(vty
, "not allocated\n");
11899 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11900 struct community
*picomm
= NULL
;
11902 picomm
= bgp_attr_get_community(pi
->attr
);
11905 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11907 if (bgp_path_suppressed(pi
))
11913 no_advertise
+= community_include(
11914 picomm
, COMMUNITY_NO_ADVERTISE
);
11916 community_include(picomm
, COMMUNITY_NO_EXPORT
);
11918 community_include(picomm
, COMMUNITY_LOCAL_AS
);
11920 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
11921 route_filter_translated_v4
+= community_include(
11922 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11923 route_filter_translated_v6
+= community_include(
11924 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11925 route_filter_v4
+= community_include(
11926 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
11927 route_filter_v6
+= community_include(
11928 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
11930 community_include(picomm
, COMMUNITY_LLGR_STALE
);
11931 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
11932 accept_own_nexthop
+= community_include(
11933 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11935 community_include(picomm
, COMMUNITY_BLACKHOLE
);
11936 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
11941 vty_out(vty
, "Paths: (%d available", count
);
11943 vty_out(vty
, ", best #%d", best
);
11944 if (safi
== SAFI_UNICAST
) {
11945 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11946 vty_out(vty
, ", table %s",
11949 vty_out(vty
, ", vrf %s",
11953 vty_out(vty
, ", no best path");
11957 ", accept own local route exported and imported in different VRF");
11958 else if (route_filter_translated_v4
)
11960 ", mark translated RTs for VPNv4 route filtering");
11961 else if (route_filter_v4
)
11963 ", attach RT as-is for VPNv4 route filtering");
11964 else if (route_filter_translated_v6
)
11966 ", mark translated RTs for VPNv6 route filtering");
11967 else if (route_filter_v6
)
11969 ", attach RT as-is for VPNv6 route filtering");
11970 else if (llgr_stale
)
11972 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
11975 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11976 else if (accept_own_nexthop
)
11978 ", accept local nexthop");
11979 else if (blackhole
)
11980 vty_out(vty
, ", inform peer to blackhole prefix");
11981 else if (no_export
)
11982 vty_out(vty
, ", not advertised to EBGP peer");
11983 else if (no_advertise
)
11984 vty_out(vty
, ", not advertised to any peer");
11986 vty_out(vty
, ", not advertised outside local AS");
11989 ", inform EBGP peer not to advertise to their EBGP peers");
11993 ", Advertisements suppressed by an aggregate.");
11994 vty_out(vty
, ")\n");
11997 /* If we are not using addpath then we can display Advertised to and
11999 * show what peers we advertised the bestpath to. If we are using
12001 * though then we must display Advertised to on a path-by-path basis. */
12002 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
12003 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
12004 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
12005 if (json
&& !json_adv_to
)
12006 json_adv_to
= json_object_new_object();
12008 route_vty_out_advertised_to(
12010 " Advertised to non peer-group peers:\n ",
12015 if (json
&& json_adv_to
) {
12016 if (incremental_print
) {
12017 vty_out(vty
, "\"advertisedTo\": ");
12018 vty_json(vty
, json_adv_to
);
12021 json_object_object_add(json
, "advertisedTo",
12024 if (!json
&& first
)
12025 vty_out(vty
, " Not advertised to any peer");
12026 vty_out(vty
, "\n");
12031 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
12032 struct bgp_dest
*bgp_node
, struct vty
*vty
,
12033 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
12034 json_object
*json
, enum bgp_path_type pathtype
,
12035 int *display
, enum rpki_states rpki_target_state
)
12037 struct bgp_path_info
*pi
;
12039 json_object
*json_header
= NULL
;
12040 json_object
*json_paths
= NULL
;
12041 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
12043 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
12044 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
12046 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
12047 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
12048 pi
->peer
, pi
->attr
, p
);
12050 if (rpki_target_state
!= RPKI_NOT_BEING_USED
12051 && rpki_curr_state
!= rpki_target_state
)
12054 if (json
&& !json_paths
) {
12055 /* Instantiate json_paths only if path is valid */
12056 json_paths
= json_object_new_array();
12058 json_header
= json_object_new_object();
12060 json_header
= json
;
12064 route_vty_out_detail_header(
12065 vty
, bgp
, bgp_node
,
12066 bgp_dest_get_prefix(bgp_node
), pfx_rd
, AFI_IP
,
12067 safi
, json_header
, false);
12072 if (pathtype
== BGP_PATH_SHOW_ALL
12073 || (pathtype
== BGP_PATH_SHOW_BESTPATH
12074 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12075 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
12076 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
12077 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
12078 route_vty_out_detail(vty
, bgp
, bgp_node
,
12079 bgp_dest_get_prefix(bgp_node
), pi
,
12080 AFI_IP
, safi
, rpki_curr_state
,
12084 if (json
&& json_paths
) {
12085 json_object_object_add(json_header
, "paths", json_paths
);
12088 json_object_object_addf(
12090 BGP_RD_AS_FORMAT(bgp
->asnotation
), pfx_rd
);
12095 * Return rd based on safi
12097 const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
12101 case SAFI_MPLS_VPN
:
12104 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
12107 case SAFI_MULTICAST
:
12108 case SAFI_LABELED_UNICAST
:
12109 case SAFI_FLOWSPEC
:
12114 assert(!"Reached end of function when we were not expecting it");
12117 /* Display specified route of BGP table. */
12118 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
12119 struct bgp_table
*rib
, const char *ip_str
,
12120 afi_t afi
, safi_t safi
,
12121 enum rpki_states rpki_target_state
,
12122 struct prefix_rd
*prd
, int prefix_check
,
12123 enum bgp_path_type pathtype
, bool use_json
)
12127 struct prefix match
;
12128 struct bgp_dest
*dest
;
12129 struct bgp_dest
*rm
;
12130 struct bgp_table
*table
;
12131 json_object
*json
= NULL
;
12132 json_object
*json_paths
= NULL
;
12134 /* Check IP address argument. */
12135 ret
= str2prefix(ip_str
, &match
);
12137 vty_out(vty
, "address is malformed\n");
12138 return CMD_WARNING
;
12141 match
.family
= afi2family(afi
);
12144 json
= json_object_new_object();
12146 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
12147 for (dest
= bgp_table_top(rib
); dest
;
12148 dest
= bgp_route_next(dest
)) {
12149 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12151 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
12153 table
= bgp_dest_get_bgp_table_info(dest
);
12157 rm
= bgp_node_match(table
, &match
);
12161 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
12163 && rm_p
->prefixlen
!= match
.prefixlen
) {
12164 bgp_dest_unlock_node(rm
);
12168 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12169 bgp
, afi
, safi
, json
, pathtype
,
12170 &display
, rpki_target_state
);
12172 bgp_dest_unlock_node(rm
);
12174 } else if (safi
== SAFI_EVPN
) {
12175 struct bgp_dest
*longest_pfx
;
12176 bool is_exact_pfxlen_match
= false;
12178 for (dest
= bgp_table_top(rib
); dest
;
12179 dest
= bgp_route_next(dest
)) {
12180 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12182 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
12184 table
= bgp_dest_get_bgp_table_info(dest
);
12188 longest_pfx
= NULL
;
12189 is_exact_pfxlen_match
= false;
12191 * Search through all the prefixes for a match. The
12192 * pfx's are enumerated in ascending order of pfxlens.
12193 * So, the last pfx match is the longest match. Set
12194 * is_exact_pfxlen_match when we get exact pfxlen match
12196 for (rm
= bgp_table_top(table
); rm
;
12197 rm
= bgp_route_next(rm
)) {
12198 const struct prefix
*rm_p
=
12199 bgp_dest_get_prefix(rm
);
12201 * Get prefixlen of the ip-prefix within type5
12204 if (evpn_type5_prefix_match(rm_p
, &match
)
12208 bgp_evpn_get_type5_prefixlen(
12210 if (type5_pfxlen
== match
.prefixlen
) {
12211 is_exact_pfxlen_match
= true;
12212 bgp_dest_unlock_node(rm
);
12221 if (prefix_check
&& !is_exact_pfxlen_match
)
12225 bgp_dest_lock_node(rm
);
12227 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12228 bgp
, afi
, safi
, json
, pathtype
,
12229 &display
, rpki_target_state
);
12231 bgp_dest_unlock_node(rm
);
12233 } else if (safi
== SAFI_FLOWSPEC
) {
12235 json_paths
= json_object_new_array();
12237 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
12238 &match
, prefix_check
,
12244 json_object_object_add(json
, "paths",
12247 json_object_free(json_paths
);
12250 dest
= bgp_node_match(rib
, &match
);
12251 if (dest
!= NULL
) {
12252 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12254 || dest_p
->prefixlen
== match
.prefixlen
) {
12255 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
12256 safi
, json
, pathtype
,
12257 &display
, rpki_target_state
);
12260 bgp_dest_unlock_node(dest
);
12265 vty_json(vty
, json
);
12268 vty_out(vty
, "%% Network not in table\n");
12269 return CMD_WARNING
;
12273 return CMD_SUCCESS
;
12276 /* Display specified route of Main RIB */
12277 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
12278 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
12279 int prefix_check
, enum bgp_path_type pathtype
,
12280 enum rpki_states rpki_target_state
, bool use_json
)
12283 bgp
= bgp_get_default();
12286 vty_out(vty
, "No BGP process is configured\n");
12288 vty_out(vty
, "{}\n");
12289 return CMD_WARNING
;
12293 /* labeled-unicast routes live in the unicast table */
12294 if (safi
== SAFI_LABELED_UNICAST
)
12295 safi
= SAFI_UNICAST
;
12297 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
12298 afi
, safi
, rpki_target_state
, prd
,
12299 prefix_check
, pathtype
, use_json
);
12302 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
12303 struct cmd_token
**argv
, bool exact
, afi_t afi
,
12304 safi_t safi
, bool uj
)
12306 struct lcommunity
*lcom
;
12311 uint16_t show_flags
= 0;
12315 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12317 b
= buffer_new(1024);
12318 for (i
= 0; i
< argc
; i
++) {
12320 buffer_putc(b
, ' ');
12322 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
12324 buffer_putstr(b
, argv
[i
]->arg
);
12328 buffer_putc(b
, '\0');
12330 str
= buffer_getstr(b
);
12333 lcom
= lcommunity_str2com(str
);
12334 XFREE(MTYPE_TMP
, str
);
12336 vty_out(vty
, "%% Large-community malformed\n");
12337 return CMD_WARNING
;
12340 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12341 (exact
? bgp_show_type_lcommunity_exact
12342 : bgp_show_type_lcommunity
),
12343 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
12345 lcommunity_free(&lcom
);
12349 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
12350 const char *lcom
, bool exact
, afi_t afi
,
12351 safi_t safi
, bool uj
)
12353 struct community_list
*list
;
12354 uint16_t show_flags
= 0;
12357 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12360 list
= community_list_lookup(bgp_clist
, lcom
, 0,
12361 LARGE_COMMUNITY_LIST_MASTER
);
12362 if (list
== NULL
) {
12363 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
12365 return CMD_WARNING
;
12368 return bgp_show(vty
, bgp
, afi
, safi
,
12369 (exact
? bgp_show_type_lcommunity_list_exact
12370 : bgp_show_type_lcommunity_list
),
12371 list
, show_flags
, RPKI_NOT_BEING_USED
);
12374 DEFUN (show_ip_bgp_large_community_list
,
12375 show_ip_bgp_large_community_list_cmd
,
12376 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|LCOMMUNITY_LIST_NAME> [exact-match] [json]",
12380 BGP_INSTANCE_HELP_STR
12382 BGP_SAFI_WITH_LABEL_HELP_STR
12383 "Display routes matching the large-community-list\n"
12384 "large-community-list number\n"
12385 "large-community-list name\n"
12386 "Exact match of the large-communities\n"
12389 afi_t afi
= AFI_IP6
;
12390 safi_t safi
= SAFI_UNICAST
;
12392 bool exact_match
= 0;
12393 struct bgp
*bgp
= NULL
;
12394 bool uj
= use_json(argc
, argv
);
12399 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12402 return CMD_WARNING
;
12404 argv_find(argv
, argc
, "large-community-list", &idx
);
12406 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12408 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
12411 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
12412 exact_match
, afi
, safi
, uj
);
12414 DEFUN (show_ip_bgp_large_community
,
12415 show_ip_bgp_large_community_cmd
,
12416 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
12420 BGP_INSTANCE_HELP_STR
12422 BGP_SAFI_WITH_LABEL_HELP_STR
12423 "Display routes matching the large-communities\n"
12424 "List of large-community numbers\n"
12425 "Exact match of the large-communities\n"
12428 afi_t afi
= AFI_IP6
;
12429 safi_t safi
= SAFI_UNICAST
;
12431 bool exact_match
= 0;
12432 struct bgp
*bgp
= NULL
;
12433 bool uj
= use_json(argc
, argv
);
12434 uint16_t show_flags
= 0;
12438 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12441 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12444 return CMD_WARNING
;
12446 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12447 if (argv_find(argv
, argc
, "exact-match", &idx
)) {
12451 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12452 exact_match
, afi
, safi
, uj
);
12454 return bgp_show(vty
, bgp
, afi
, safi
,
12455 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12456 RPKI_NOT_BEING_USED
);
12459 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12460 safi_t safi
, struct json_object
*json_array
);
12461 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12462 safi_t safi
, struct json_object
*json
);
12465 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12466 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12467 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12468 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12470 bool uj
= use_json(argc
, argv
);
12471 struct bgp
*bgp
= NULL
;
12472 safi_t safi
= SAFI_UNICAST
;
12473 afi_t afi
= AFI_IP6
;
12475 struct json_object
*json_all
= NULL
;
12476 struct json_object
*json_afi_safi
= NULL
;
12478 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12481 return CMD_WARNING
;
12484 json_all
= json_object_new_object();
12486 FOREACH_AFI_SAFI (afi
, safi
) {
12488 * So limit output to those afi/safi pairs that
12489 * actually have something interesting in them
12491 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12496 json_afi_safi
= json_object_new_array();
12497 json_object_object_add(
12499 get_afi_safi_str(afi
, safi
, true),
12502 json_afi_safi
= NULL
;
12505 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12509 vty_json(vty
, json_all
);
12511 return CMD_SUCCESS
;
12514 /* BGP route print out function without JSON */
12515 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12516 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12517 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12521 BGP_INSTANCE_HELP_STR
12524 "BGP RIB advertisement statistics\n"
12527 afi_t afi
= AFI_IP6
;
12528 safi_t safi
= SAFI_UNICAST
;
12529 struct bgp
*bgp
= NULL
;
12531 bool uj
= use_json(argc
, argv
);
12532 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12534 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12537 return CMD_WARNING
;
12540 json_afi_safi
= json_object_new_array();
12542 json_afi_safi
= NULL
;
12544 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12547 json
= json_object_new_object();
12548 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12550 vty_json(vty
, json
);
12555 /* BGP route print out function without JSON */
12556 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12557 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12558 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12560 statistics [json]",
12561 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12562 BGP_SAFI_WITH_LABEL_HELP_STR
12563 "BGP RIB advertisement statistics\n" JSON_STR
)
12565 afi_t afi
= AFI_IP6
;
12566 safi_t safi
= SAFI_UNICAST
;
12567 struct bgp
*bgp
= NULL
;
12569 bool uj
= use_json(argc
, argv
);
12570 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12572 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12575 return CMD_WARNING
;
12578 json_afi_safi
= json_object_new_array();
12580 json_afi_safi
= NULL
;
12582 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12585 json
= json_object_new_object();
12586 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12588 vty_json(vty
, json
);
12593 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12594 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12595 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12596 "]] [all$all] dampening parameters [json]",
12597 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12598 BGP_SAFI_WITH_LABEL_HELP_STR
12599 "Display the entries for all address families\n"
12600 "Display detailed information about dampening\n"
12601 "Display detail of configured dampening parameters\n"
12604 afi_t afi
= AFI_IP6
;
12605 safi_t safi
= SAFI_UNICAST
;
12606 struct bgp
*bgp
= NULL
;
12608 uint16_t show_flags
= 0;
12609 bool uj
= use_json(argc
, argv
);
12613 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12616 /* [<ipv4|ipv6> [all]] */
12618 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12619 if (argv_find(argv
, argc
, "ipv4", &idx
))
12620 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12622 if (argv_find(argv
, argc
, "ipv6", &idx
))
12623 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12626 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12629 return CMD_WARNING
;
12631 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12634 /* BGP route print out function */
12635 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12636 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12637 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12641 |dampening <flap-statistics|dampened-paths>\
12642 |community [AA:NN|local-AS|no-advertise|no-export\
12643 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12644 |accept-own|accept-own-nexthop|route-filter-v6\
12645 |route-filter-v4|route-filter-translated-v6\
12646 |route-filter-translated-v4] [exact-match]\
12647 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12648 |filter-list AS_PATH_FILTER_NAME\
12650 |access-list ACCESSLIST_NAME\
12651 |route-map RMAP_NAME\
12652 |rpki <invalid|valid|notfound>\
12653 |version (1-4294967295)\
12655 |A.B.C.D/M longer-prefixes\
12656 |X:X::X:X/M longer-prefixes\
12657 |"BGP_SELF_ORIG_CMD_STR
"\
12658 |detail-routes$detail_routes\
12659 ] [json$uj [detail$detail_json] | wide$wide]",
12660 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12661 BGP_SAFI_WITH_LABEL_HELP_STR
12662 "Display the entries for all address families\n"
12663 "Display only routes with non-natural netmasks\n"
12664 "Display detailed information about dampening\n"
12665 "Display flap statistics of routes\n"
12666 "Display paths suppressed due to dampening\n"
12667 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12668 "Do not send outside local AS (well-known community)\n"
12669 "Do not advertise to any peer (well-known community)\n"
12670 "Do not export to next AS (well-known community)\n"
12671 "Graceful shutdown (well-known community)\n"
12672 "Do not export to any peer (well-known community)\n"
12673 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12674 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12675 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12676 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12677 "Should accept VPN route with local nexthop (well-known community)\n"
12678 "RT VPNv6 route filtering (well-known community)\n"
12679 "RT VPNv4 route filtering (well-known community)\n"
12680 "RT translated VPNv6 route filtering (well-known community)\n"
12681 "RT translated VPNv4 route filtering (well-known community)\n"
12682 "Exact match of the communities\n"
12683 "Community-list number\n"
12684 "Community-list name\n"
12685 "Display routes matching the community-list\n"
12686 "Exact match of the communities\n"
12687 "Display routes conforming to the filter-list\n"
12688 "Regular expression access list name\n"
12689 "Display routes conforming to the prefix-list\n"
12690 "Prefix-list name\n"
12691 "Display routes conforming to the access-list\n"
12692 "Access-list name\n"
12693 "Display routes matching the route-map\n"
12694 "A route-map to match on\n"
12695 "RPKI route types\n"
12696 "A valid path as determined by rpki\n"
12697 "A invalid path as determined by rpki\n"
12698 "A path that has no rpki data\n"
12699 "Display prefixes with matching version numbers\n"
12700 "Version number and above\n"
12701 "Display prefixes with matching BGP community alias\n"
12702 "BGP community alias\n"
12704 "Display route and more specific routes\n"
12706 "Display route and more specific routes\n"
12707 BGP_SELF_ORIG_HELP_STR
12708 "Display detailed version of all routes\n"
12710 "Display detailed version of JSON output\n"
12711 "Increase table width for longer prefixes\n")
12713 afi_t afi
= AFI_IP6
;
12714 safi_t safi
= SAFI_UNICAST
;
12715 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12716 void *output_arg
= NULL
;
12717 struct bgp
*bgp
= NULL
;
12719 int exact_match
= 0;
12720 char *community
= NULL
;
12722 uint16_t show_flags
= 0;
12723 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12728 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12732 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
12735 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
12737 /* [<ipv4|ipv6> [all]] */
12739 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12741 if (argv_find(argv
, argc
, "ipv4", &idx
))
12742 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12744 if (argv_find(argv
, argc
, "ipv6", &idx
))
12745 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12749 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12751 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12754 return CMD_WARNING
;
12756 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12757 sh_type
= bgp_show_type_cidr_only
;
12759 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12760 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12761 sh_type
= bgp_show_type_dampend_paths
;
12762 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12763 sh_type
= bgp_show_type_flap_statistics
;
12766 if (argv_find(argv
, argc
, "community", &idx
)) {
12767 char *maybecomm
= NULL
;
12769 if (idx
+ 1 < argc
) {
12770 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12771 maybecomm
= argv
[idx
+ 1]->arg
;
12773 maybecomm
= argv
[idx
+ 1]->text
;
12776 if (maybecomm
&& !strmatch(maybecomm
, "json")
12777 && !strmatch(maybecomm
, "exact-match"))
12778 community
= maybecomm
;
12780 if (argv_find(argv
, argc
, "exact-match", &idx
))
12784 sh_type
= bgp_show_type_community_all
;
12787 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12788 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12789 struct community_list
*list
;
12791 if (argv_find(argv
, argc
, "exact-match", &idx
))
12794 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12795 COMMUNITY_LIST_MASTER
);
12796 if (list
== NULL
) {
12797 vty_out(vty
, "%% %s community-list not found\n",
12798 clist_number_or_name
);
12799 return CMD_WARNING
;
12803 sh_type
= bgp_show_type_community_list_exact
;
12805 sh_type
= bgp_show_type_community_list
;
12809 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12810 const char *filter
= argv
[++idx
]->arg
;
12811 struct as_list
*as_list
;
12813 as_list
= as_list_lookup(filter
);
12814 if (as_list
== NULL
) {
12815 vty_out(vty
, "%% %s AS-path access-list not found\n",
12817 return CMD_WARNING
;
12820 sh_type
= bgp_show_type_filter_list
;
12821 output_arg
= as_list
;
12824 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12825 const char *prefix_list_str
= argv
[++idx
]->arg
;
12826 struct prefix_list
*plist
;
12828 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12829 if (plist
== NULL
) {
12830 vty_out(vty
, "%% %s prefix-list not found\n",
12832 return CMD_WARNING
;
12835 sh_type
= bgp_show_type_prefix_list
;
12836 output_arg
= plist
;
12839 if (argv_find(argv
, argc
, "access-list", &idx
)) {
12840 const char *access_list_str
= argv
[++idx
]->arg
;
12841 struct access_list
*alist
;
12843 alist
= access_list_lookup(afi
, access_list_str
);
12845 vty_out(vty
, "%% %s access-list not found\n",
12847 return CMD_WARNING
;
12850 sh_type
= bgp_show_type_access_list
;
12851 output_arg
= alist
;
12854 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12855 const char *rmap_str
= argv
[++idx
]->arg
;
12856 struct route_map
*rmap
;
12858 rmap
= route_map_lookup_by_name(rmap_str
);
12860 vty_out(vty
, "%% %s route-map not found\n", rmap_str
);
12861 return CMD_WARNING
;
12864 sh_type
= bgp_show_type_route_map
;
12868 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12869 sh_type
= bgp_show_type_rpki
;
12870 if (argv_find(argv
, argc
, "valid", &idx
))
12871 rpki_target_state
= RPKI_VALID
;
12872 else if (argv_find(argv
, argc
, "invalid", &idx
))
12873 rpki_target_state
= RPKI_INVALID
;
12876 /* Display prefixes with matching version numbers */
12877 if (argv_find(argv
, argc
, "version", &idx
)) {
12878 sh_type
= bgp_show_type_prefix_version
;
12879 output_arg
= argv
[idx
+ 1]->arg
;
12882 /* Display prefixes with matching BGP community alias */
12883 if (argv_find(argv
, argc
, "alias", &idx
)) {
12884 sh_type
= bgp_show_type_community_alias
;
12885 output_arg
= argv
[idx
+ 1]->arg
;
12888 /* prefix-longer */
12889 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12890 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12891 const char *prefix_str
= argv
[idx
]->arg
;
12893 if (!str2prefix(prefix_str
, &p
)) {
12894 vty_out(vty
, "%% Malformed Prefix\n");
12895 return CMD_WARNING
;
12898 sh_type
= bgp_show_type_prefix_longer
;
12902 /* self originated only */
12903 if (argv_find(argv
, argc
, BGP_SELF_ORIG_CMD_STR
, &idx
))
12904 sh_type
= bgp_show_type_self_originated
;
12907 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12909 return bgp_show_community(vty
, bgp
, community
,
12910 exact_match
, afi
, safi
,
12913 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12914 output_arg
, show_flags
,
12915 rpki_target_state
);
12917 struct listnode
*node
;
12919 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12923 vty_out(vty
, "{\n");
12925 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12926 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12927 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12930 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12931 FOREACH_SAFI (safi
) {
12932 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12940 vty_out(vty
, ",\n");
12941 vty_out(vty
, "\"%s\":{\n",
12942 get_afi_safi_str(afi
,
12947 "\nFor address family: %s\n",
12953 bgp_show_community(
12954 vty
, abgp
, community
,
12955 exact_match
, afi
, safi
,
12958 bgp_show(vty
, abgp
, afi
, safi
,
12959 sh_type
, output_arg
,
12961 rpki_target_state
);
12963 vty_out(vty
, "}\n");
12967 /* show <ip> bgp all: for each AFI and SAFI*/
12968 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12969 FOREACH_AFI_SAFI (afi
, safi
) {
12970 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12978 vty_out(vty
, ",\n");
12980 vty_out(vty
, "\"%s\":{\n",
12981 get_afi_safi_str(afi
,
12986 "\nFor address family: %s\n",
12992 bgp_show_community(
12993 vty
, abgp
, community
,
12994 exact_match
, afi
, safi
,
12997 bgp_show(vty
, abgp
, afi
, safi
,
12998 sh_type
, output_arg
,
13000 rpki_target_state
);
13002 vty_out(vty
, "}\n");
13007 vty_out(vty
, "}\n");
13009 return CMD_SUCCESS
;
13012 DEFUN (show_ip_bgp_route
,
13013 show_ip_bgp_route_cmd
,
13014 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [rpki <valid|invalid|notfound>] [json]",
13018 BGP_INSTANCE_HELP_STR
13020 BGP_SAFI_WITH_LABEL_HELP_STR
13021 "Network in the BGP routing table to display\n"
13023 "Network in the BGP routing table to display\n"
13025 "Display only the bestpath\n"
13026 "Display only multipaths\n"
13027 "Display only paths that match the specified rpki state\n"
13028 "A valid path as determined by rpki\n"
13029 "A invalid path as determined by rpki\n"
13030 "A path that has no rpki data\n"
13033 int prefix_check
= 0;
13035 afi_t afi
= AFI_IP6
;
13036 safi_t safi
= SAFI_UNICAST
;
13037 char *prefix
= NULL
;
13038 struct bgp
*bgp
= NULL
;
13039 enum bgp_path_type path_type
;
13040 bool uj
= use_json(argc
, argv
);
13044 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13047 return CMD_WARNING
;
13051 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13052 return CMD_WARNING
;
13055 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13056 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
13057 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
13059 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
13060 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
13063 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
13064 && afi
!= AFI_IP6
) {
13066 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13067 return CMD_WARNING
;
13069 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
13070 && afi
!= AFI_IP
) {
13072 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13073 return CMD_WARNING
;
13076 prefix
= argv
[idx
]->arg
;
13078 /* [<bestpath|multipath>] */
13079 if (argv_find(argv
, argc
, "bestpath", &idx
))
13080 path_type
= BGP_PATH_SHOW_BESTPATH
;
13081 else if (argv_find(argv
, argc
, "multipath", &idx
))
13082 path_type
= BGP_PATH_SHOW_MULTIPATH
;
13084 path_type
= BGP_PATH_SHOW_ALL
;
13086 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
13087 path_type
, RPKI_NOT_BEING_USED
, uj
);
13090 DEFUN (show_ip_bgp_regexp
,
13091 show_ip_bgp_regexp_cmd
,
13092 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
13096 BGP_INSTANCE_HELP_STR
13098 BGP_SAFI_WITH_LABEL_HELP_STR
13099 "Display routes matching the AS path regular expression\n"
13100 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13103 afi_t afi
= AFI_IP6
;
13104 safi_t safi
= SAFI_UNICAST
;
13105 struct bgp
*bgp
= NULL
;
13106 bool uj
= use_json(argc
, argv
);
13107 char *regstr
= NULL
;
13110 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13113 return CMD_WARNING
;
13115 // get index of regex
13116 if (argv_find(argv
, argc
, "REGEX", &idx
))
13117 regstr
= argv
[idx
]->arg
;
13120 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
13121 bgp_show_type_regexp
, uj
);
13124 DEFPY (show_ip_bgp_instance_all
,
13125 show_ip_bgp_instance_all_cmd
,
13126 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
13130 BGP_INSTANCE_ALL_HELP_STR
13132 BGP_SAFI_WITH_LABEL_HELP_STR
13134 "Increase table width for longer prefixes\n")
13136 afi_t afi
= AFI_IP6
;
13137 safi_t safi
= SAFI_UNICAST
;
13138 struct bgp
*bgp
= NULL
;
13140 uint16_t show_flags
= 0;
13144 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13148 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13150 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13153 return CMD_WARNING
;
13155 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
13156 return CMD_SUCCESS
;
13159 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
13160 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
13165 uint16_t show_flags
= 0;
13168 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13170 if (!config_bgp_aspath_validate(regstr
)) {
13171 vty_out(vty
, "Invalid character in REGEX %s\n",
13173 return CMD_WARNING_CONFIG_FAILED
;
13176 regex
= bgp_regcomp(regstr
);
13178 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
13179 return CMD_WARNING
;
13182 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
13183 RPKI_NOT_BEING_USED
);
13184 bgp_regex_free(regex
);
13188 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
13189 const char *comstr
, int exact
, afi_t afi
,
13190 safi_t safi
, uint16_t show_flags
)
13192 struct community
*com
;
13195 com
= community_str2com(comstr
);
13197 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
13198 return CMD_WARNING
;
13201 ret
= bgp_show(vty
, bgp
, afi
, safi
,
13202 (exact
? bgp_show_type_community_exact
13203 : bgp_show_type_community
),
13204 com
, show_flags
, RPKI_NOT_BEING_USED
);
13205 community_free(&com
);
13211 BGP_STATS_MAXBITLEN
= 0,
13213 BGP_STATS_PREFIXES
,
13215 BGP_STATS_UNAGGREGATEABLE
,
13216 BGP_STATS_MAX_AGGREGATEABLE
,
13217 BGP_STATS_AGGREGATES
,
13219 BGP_STATS_ASPATH_COUNT
,
13220 BGP_STATS_ASPATH_MAXHOPS
,
13221 BGP_STATS_ASPATH_TOTHOPS
,
13222 BGP_STATS_ASPATH_MAXSIZE
,
13223 BGP_STATS_ASPATH_TOTSIZE
,
13224 BGP_STATS_ASN_HIGHEST
,
13228 #define TABLE_STATS_IDX_VTY 0
13229 #define TABLE_STATS_IDX_JSON 1
13231 static const char *table_stats_strs
[][2] = {
13232 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
13233 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
13234 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
13235 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
13236 "unaggregateablePrefixes"},
13237 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
13238 "maximumAggregateablePrefixes"},
13239 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
13240 "bgpAggregateAdvertisements"},
13241 [BGP_STATS_SPACE
] = {"Address space advertised",
13242 "addressSpaceAdvertised"},
13243 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
13244 "advertisementsWithPaths"},
13245 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
13247 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
13249 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
13250 "averageAsPathLengthHops"},
13251 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
13252 "averageAsPathSizeBytes"},
13253 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
13254 [BGP_STATS_MAX
] = {NULL
, NULL
}
13257 struct bgp_table_stats
{
13258 struct bgp_table
*table
;
13259 unsigned long long counts
[BGP_STATS_MAX
];
13262 prefix_len_count
[MAX(EVPN_ROUTE_PREFIXLEN
, IPV6_MAX_BITLEN
) +
13265 double total_space
;
13268 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
13269 struct bgp_table_stats
*ts
, unsigned int space
)
13271 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
13272 struct bgp_path_info
*pi
;
13273 const struct prefix
*rn_p
;
13275 if (!bgp_dest_has_bgp_path_info_data(dest
))
13278 rn_p
= bgp_dest_get_prefix(dest
);
13279 ts
->counts
[BGP_STATS_PREFIXES
]++;
13280 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
13282 ts
->prefix_len_count
[rn_p
->prefixlen
]++;
13283 /* check if the prefix is included by any other announcements */
13284 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
13285 pdest
= bgp_dest_parent_nolock(pdest
);
13287 if (pdest
== NULL
|| pdest
== top
) {
13288 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
13289 /* announced address space */
13291 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
13292 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
13293 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
13296 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
13297 ts
->counts
[BGP_STATS_RIB
]++;
13299 if (CHECK_FLAG(pi
->attr
->flag
,
13300 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
13301 ts
->counts
[BGP_STATS_AGGREGATES
]++;
13303 /* as-path stats */
13304 if (pi
->attr
->aspath
) {
13305 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
13306 unsigned int size
= aspath_size(pi
->attr
->aspath
);
13307 as_t highest
= aspath_highest(pi
->attr
->aspath
);
13309 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
13311 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
13312 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
13314 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
13315 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
13317 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
13318 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
13319 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
13320 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
13325 static void bgp_table_stats_walker(struct thread
*t
)
13327 struct bgp_dest
*dest
, *ndest
;
13328 struct bgp_dest
*top
;
13329 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
13330 unsigned int space
= 0;
13332 if (!(top
= bgp_table_top(ts
->table
)))
13335 switch (ts
->table
->afi
) {
13337 space
= IPV4_MAX_BITLEN
;
13340 space
= IPV6_MAX_BITLEN
;
13343 space
= EVPN_ROUTE_PREFIXLEN
;
13350 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
13352 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
13353 if (ts
->table
->safi
== SAFI_MPLS_VPN
13354 || ts
->table
->safi
== SAFI_ENCAP
13355 || ts
->table
->safi
== SAFI_EVPN
) {
13356 struct bgp_table
*table
;
13358 table
= bgp_dest_get_bgp_table_info(dest
);
13362 top
= bgp_table_top(table
);
13363 for (ndest
= bgp_table_top(table
); ndest
;
13364 ndest
= bgp_route_next(ndest
))
13365 bgp_table_stats_rn(ndest
, top
, ts
, space
);
13367 bgp_table_stats_rn(dest
, top
, ts
, space
);
13372 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
13373 struct json_object
*json_array
)
13375 struct listnode
*node
, *nnode
;
13378 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
13379 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13382 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13383 safi_t safi
, struct json_object
*json_array
)
13385 struct bgp_table_stats ts
;
13387 int ret
= CMD_SUCCESS
;
13389 struct json_object
*json
= NULL
;
13390 uint32_t bitlen
= 0;
13391 struct json_object
*json_bitlen
;
13394 json
= json_object_new_object();
13396 if (!bgp
->rib
[afi
][safi
]) {
13397 char warning_msg
[50];
13399 snprintf(warning_msg
, sizeof(warning_msg
),
13400 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
13404 vty_out(vty
, "%s\n", warning_msg
);
13406 json_object_string_add(json
, "warning", warning_msg
);
13409 goto end_table_stats
;
13413 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
13414 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
13416 json_object_string_add(json
, "instance", bgp
->name_pretty
);
13418 /* labeled-unicast routes live in the unicast table */
13419 if (safi
== SAFI_LABELED_UNICAST
)
13420 safi
= SAFI_UNICAST
;
13422 memset(&ts
, 0, sizeof(ts
));
13423 ts
.table
= bgp
->rib
[afi
][safi
];
13424 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
13426 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
13427 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
13428 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
13432 case BGP_STATS_ASPATH_TOTHOPS
:
13433 case BGP_STATS_ASPATH_TOTSIZE
:
13436 temp_buf
, sizeof(temp_buf
), "%12.2f",
13438 ? (float)ts
.counts
[i
]
13440 [BGP_STATS_ASPATH_COUNT
]
13442 vty_out(vty
, "%-30s: %s",
13443 table_stats_strs
[i
]
13444 [TABLE_STATS_IDX_VTY
],
13447 json_object_double_add(
13449 table_stats_strs
[i
]
13450 [TABLE_STATS_IDX_JSON
],
13452 ? (double)ts
.counts
[i
]
13453 / (double)ts
.counts
13454 [BGP_STATS_ASPATH_COUNT
]
13458 case BGP_STATS_TOTPLEN
:
13461 temp_buf
, sizeof(temp_buf
), "%12.2f",
13463 ? (float)ts
.counts
[i
]
13465 [BGP_STATS_PREFIXES
]
13467 vty_out(vty
, "%-30s: %s",
13468 table_stats_strs
[i
]
13469 [TABLE_STATS_IDX_VTY
],
13472 json_object_double_add(
13474 table_stats_strs
[i
]
13475 [TABLE_STATS_IDX_JSON
],
13477 ? (double)ts
.counts
[i
]
13478 / (double)ts
.counts
13479 [BGP_STATS_PREFIXES
]
13483 case BGP_STATS_SPACE
:
13485 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13487 vty_out(vty
, "%-30s: %s\n",
13488 table_stats_strs
[i
]
13489 [TABLE_STATS_IDX_VTY
],
13492 json_object_double_add(
13494 table_stats_strs
[i
]
13495 [TABLE_STATS_IDX_JSON
],
13496 (double)ts
.total_space
);
13498 if (afi
== AFI_IP6
) {
13500 snprintf(temp_buf
, sizeof(temp_buf
),
13503 * pow(2.0, -128 + 32));
13504 vty_out(vty
, "%30s: %s\n",
13505 "/32 equivalent %s\n",
13508 json_object_double_add(
13509 json
, "/32equivalent",
13510 (double)(ts
.total_space
13515 snprintf(temp_buf
, sizeof(temp_buf
),
13518 * pow(2.0, -128 + 48));
13519 vty_out(vty
, "%30s: %s\n",
13520 "/48 equivalent %s\n",
13523 json_object_double_add(
13524 json
, "/48equivalent",
13525 (double)(ts
.total_space
13531 snprintf(temp_buf
, sizeof(temp_buf
),
13533 ts
.total_space
* 100.
13535 vty_out(vty
, "%30s: %s\n",
13536 "% announced ", temp_buf
);
13538 json_object_double_add(
13539 json
, "%announced",
13540 (double)(ts
.total_space
* 100.
13544 snprintf(temp_buf
, sizeof(temp_buf
),
13547 * pow(2.0, -32 + 8));
13548 vty_out(vty
, "%30s: %s\n",
13549 "/8 equivalent ", temp_buf
);
13551 json_object_double_add(
13552 json
, "/8equivalent",
13553 (double)(ts
.total_space
13554 * pow(2.0, -32 + 8)));
13557 snprintf(temp_buf
, sizeof(temp_buf
),
13560 * pow(2.0, -32 + 24));
13561 vty_out(vty
, "%30s: %s\n",
13562 "/24 equivalent ", temp_buf
);
13564 json_object_double_add(
13565 json
, "/24equivalent",
13566 (double)(ts
.total_space
13567 * pow(2.0, -32 + 24)));
13573 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13575 vty_out(vty
, "%-30s: %s",
13576 table_stats_strs
[i
]
13577 [TABLE_STATS_IDX_VTY
],
13580 json_object_int_add(
13582 table_stats_strs
[i
]
13583 [TABLE_STATS_IDX_JSON
],
13588 vty_out(vty
, "\n");
13593 bitlen
= IPV4_MAX_BITLEN
;
13596 bitlen
= IPV6_MAX_BITLEN
;
13599 bitlen
= EVPN_ROUTE_PREFIXLEN
;
13607 json_bitlen
= json_object_new_array();
13609 for (i
= 0; i
<= bitlen
; i
++) {
13610 struct json_object
*ind_bit
= json_object_new_object();
13612 if (!ts
.prefix_len_count
[i
])
13615 snprintf(temp_buf
, sizeof(temp_buf
), "%u", i
);
13616 json_object_int_add(ind_bit
, temp_buf
,
13617 ts
.prefix_len_count
[i
]);
13618 json_object_array_add(json_bitlen
, ind_bit
);
13620 json_object_object_add(json
, "prefixLength", json_bitlen
);
13625 json_object_array_add(json_array
, json
);
13629 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13630 safi_t safi
, struct json_object
*json_array
)
13633 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13634 return CMD_SUCCESS
;
13637 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13649 PCOUNT_BPATH_SELECTED
,
13650 PCOUNT_PFCNT
, /* the figure we display to users */
13654 static const char *const pcount_strs
[] = {
13655 [PCOUNT_ADJ_IN
] = "Adj-in",
13656 [PCOUNT_DAMPED
] = "Damped",
13657 [PCOUNT_REMOVED
] = "Removed",
13658 [PCOUNT_HISTORY
] = "History",
13659 [PCOUNT_STALE
] = "Stale",
13660 [PCOUNT_VALID
] = "Valid",
13661 [PCOUNT_ALL
] = "All RIB",
13662 [PCOUNT_COUNTED
] = "PfxCt counted",
13663 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13664 [PCOUNT_PFCNT
] = "Useable",
13665 [PCOUNT_MAX
] = NULL
,
13668 struct peer_pcounts
{
13669 unsigned int count
[PCOUNT_MAX
];
13670 const struct peer
*peer
;
13671 const struct bgp_table
*table
;
13675 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13677 const struct bgp_adj_in
*ain
;
13678 const struct bgp_path_info
*pi
;
13679 const struct peer
*peer
= pc
->peer
;
13681 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13682 if (ain
->peer
== peer
)
13683 pc
->count
[PCOUNT_ADJ_IN
]++;
13685 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13687 if (pi
->peer
!= peer
)
13690 pc
->count
[PCOUNT_ALL
]++;
13692 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13693 pc
->count
[PCOUNT_DAMPED
]++;
13694 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13695 pc
->count
[PCOUNT_HISTORY
]++;
13696 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13697 pc
->count
[PCOUNT_REMOVED
]++;
13698 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13699 pc
->count
[PCOUNT_STALE
]++;
13700 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13701 pc
->count
[PCOUNT_VALID
]++;
13702 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13703 pc
->count
[PCOUNT_PFCNT
]++;
13704 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13705 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13707 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13708 pc
->count
[PCOUNT_COUNTED
]++;
13709 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13711 EC_LIB_DEVELOPMENT
,
13712 "Attempting to count but flags say it is unusable");
13714 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13716 EC_LIB_DEVELOPMENT
,
13717 "Not counted but flags say we should");
13722 static void bgp_peer_count_walker(struct thread
*t
)
13724 struct bgp_dest
*rn
, *rm
;
13725 const struct bgp_table
*table
;
13726 struct peer_pcounts
*pc
= THREAD_ARG(t
);
13728 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13729 || pc
->safi
== SAFI_EVPN
) {
13730 /* Special handling for 2-level routing tables. */
13731 for (rn
= bgp_table_top(pc
->table
); rn
;
13732 rn
= bgp_route_next(rn
)) {
13733 table
= bgp_dest_get_bgp_table_info(rn
);
13735 for (rm
= bgp_table_top(table
); rm
;
13736 rm
= bgp_route_next(rm
))
13737 bgp_peer_count_proc(rm
, pc
);
13740 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13741 bgp_peer_count_proc(rn
, pc
);
13744 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13745 safi_t safi
, bool use_json
)
13747 struct peer_pcounts pcounts
= {.peer
= peer
};
13749 json_object
*json
= NULL
;
13750 json_object
*json_loop
= NULL
;
13753 json
= json_object_new_object();
13754 json_loop
= json_object_new_object();
13757 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13758 || !peer
->bgp
->rib
[afi
][safi
]) {
13760 json_object_string_add(
13762 "No such neighbor or address family");
13763 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13764 json_object_free(json
);
13765 json_object_free(json_loop
);
13767 vty_out(vty
, "%% No such neighbor or address family\n");
13769 return CMD_WARNING
;
13772 memset(&pcounts
, 0, sizeof(pcounts
));
13773 pcounts
.peer
= peer
;
13774 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13775 pcounts
.safi
= safi
;
13777 /* in-place call via thread subsystem so as to record execution time
13778 * stats for the thread-walk (i.e. ensure this can't be blamed on
13779 * on just vty_read()).
13781 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13784 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13785 json_object_string_add(json
, "multiProtocol",
13786 get_afi_safi_str(afi
, safi
, true));
13787 json_object_int_add(json
, "pfxCounter",
13788 peer
->pcount
[afi
][safi
]);
13790 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13791 json_object_int_add(json_loop
, pcount_strs
[i
],
13794 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13796 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13797 json_object_string_add(json
, "pfxctDriftFor",
13799 json_object_string_add(
13800 json
, "recommended",
13801 "Please report this bug, with the above command output");
13803 vty_json(vty
, json
);
13807 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13808 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13809 peer
->hostname
, peer
->host
,
13810 get_afi_safi_str(afi
, safi
, false));
13812 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13813 get_afi_safi_str(afi
, safi
, false));
13816 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13817 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13819 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13820 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13823 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13824 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13826 "Please report this bug, with the above command output\n");
13830 return CMD_SUCCESS
;
13833 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13834 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13835 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13839 BGP_INSTANCE_HELP_STR
13842 "Detailed information on TCP and BGP neighbor connections\n"
13843 "Neighbor to display information about\n"
13844 "Neighbor to display information about\n"
13845 "Neighbor on BGP configured interface\n"
13846 "Display detailed prefix count information\n"
13849 afi_t afi
= AFI_IP6
;
13850 safi_t safi
= SAFI_UNICAST
;
13853 struct bgp
*bgp
= NULL
;
13854 bool uj
= use_json(argc
, argv
);
13859 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13862 return CMD_WARNING
;
13864 argv_find(argv
, argc
, "neighbors", &idx
);
13865 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13867 return CMD_WARNING
;
13869 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13872 #ifdef KEEP_OLD_VPN_COMMANDS
13873 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13874 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13875 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13880 "Display information about all VPNv4 NLRIs\n"
13881 "Detailed information on TCP and BGP neighbor connections\n"
13882 "Neighbor to display information about\n"
13883 "Neighbor to display information about\n"
13884 "Neighbor on BGP configured interface\n"
13885 "Display detailed prefix count information\n"
13890 bool uj
= use_json(argc
, argv
);
13892 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13894 return CMD_WARNING
;
13896 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13899 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13900 show_ip_bgp_vpn_all_route_prefix_cmd
,
13901 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13906 "Display information about all VPNv4 NLRIs\n"
13907 "Network in the BGP routing table to display\n"
13908 "Network in the BGP routing table to display\n"
13912 char *network
= NULL
;
13913 struct bgp
*bgp
= bgp_get_default();
13915 vty_out(vty
, "Can't find default instance\n");
13916 return CMD_WARNING
;
13919 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13920 network
= argv
[idx
]->arg
;
13921 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13922 network
= argv
[idx
]->arg
;
13924 vty_out(vty
, "Unable to figure out Network\n");
13925 return CMD_WARNING
;
13928 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13929 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13930 use_json(argc
, argv
));
13932 #endif /* KEEP_OLD_VPN_COMMANDS */
13934 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13935 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13936 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13941 "Network in the BGP routing table to display\n"
13942 "Network in the BGP routing table to display\n"
13943 "Network in the BGP routing table to display\n"
13944 "Network in the BGP routing table to display\n"
13948 char *network
= NULL
;
13949 int prefix_check
= 0;
13951 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13952 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13953 network
= argv
[idx
]->arg
;
13954 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13955 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
13956 network
= argv
[idx
]->arg
;
13959 vty_out(vty
, "Unable to figure out Network\n");
13960 return CMD_WARNING
;
13962 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13963 prefix_check
, BGP_PATH_SHOW_ALL
,
13964 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
13967 static void show_adj_route_header(struct vty
*vty
, struct peer
*peer
,
13968 struct bgp_table
*table
, int *header1
,
13969 int *header2
, json_object
*json
,
13970 json_object
*json_scode
,
13971 json_object
*json_ocode
, bool wide
,
13974 uint64_t version
= table
? table
->version
: 0;
13978 json_object_int_add(json
, "bgpTableVersion", version
);
13979 json_object_string_addf(json
, "bgpLocalRouterId",
13980 "%pI4", &peer
->bgp
->router_id
);
13981 json_object_int_add(json
, "defaultLocPrf",
13982 peer
->bgp
->default_local_pref
);
13983 json_object_int_add(json
, "localAS",
13984 peer
->change_local_as
13985 ? peer
->change_local_as
13987 json_object_object_add(json
, "bgpStatusCodes",
13989 json_object_object_add(json
, "bgpOriginCodes",
13993 "BGP table version is %" PRIu64
13994 ", local router ID is %pI4, vrf id ",
13995 version
, &peer
->bgp
->router_id
);
13996 if (peer
->bgp
->vrf_id
== VRF_UNKNOWN
)
13997 vty_out(vty
, "%s", VRFID_NONE_STR
);
13999 vty_out(vty
, "%u", peer
->bgp
->vrf_id
);
14000 vty_out(vty
, "\n");
14001 vty_out(vty
, "Default local pref %u, ",
14002 peer
->bgp
->default_local_pref
);
14003 vty_out(vty
, "local AS %u\n",
14004 peer
->change_local_as
? peer
->change_local_as
14007 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14008 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14009 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14010 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14016 if (!json
&& !detail
)
14017 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
14018 : BGP_SHOW_HEADER
));
14024 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
14025 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
14026 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
14027 json_object
*json_scode
, json_object
*json_ocode
,
14028 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
14029 const struct prefix
*match
, unsigned long *output_count
,
14030 unsigned long *filtered_count
)
14032 struct bgp_adj_in
*ain
= NULL
;
14033 struct bgp_adj_out
*adj
= NULL
;
14034 struct bgp_dest
*dest
;
14038 struct update_subgroup
*subgrp
;
14039 struct peer_af
*paf
= NULL
;
14040 bool route_filtered
;
14041 bool detail
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14042 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14043 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14044 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14045 || (safi
== SAFI_EVPN
))
14049 json_object
*json_net
= NULL
;
14053 /* If the user supplied a prefix, look for a matching route instead
14054 * of walking the whole table.
14057 dest
= bgp_node_match(table
, match
);
14060 vty_out(vty
, "Network not in table\n");
14064 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
14066 if (rn_p
->prefixlen
!= match
->prefixlen
) {
14068 vty_out(vty
, "Network not in table\n");
14069 bgp_dest_unlock_node(dest
);
14073 if (type
== bgp_show_adj_route_received
||
14074 type
== bgp_show_adj_route_filtered
) {
14075 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14076 if (ain
->peer
== peer
) {
14081 /* bail out if if adj_out is empty, or
14082 * if the prefix isn't in this peer's
14085 if (!ain
|| ain
->peer
!= peer
) {
14087 vty_out(vty
, "Network not in table\n");
14088 bgp_dest_unlock_node(dest
);
14091 } else if (type
== bgp_show_adj_route_advertised
) {
14092 bool peer_found
= false;
14094 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
) {
14095 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14096 if (paf
->peer
== peer
&& adj
->attr
) {
14105 /* bail out if if adj_out is empty, or
14106 * if the prefix isn't in this peer's
14109 if (!paf
|| !peer_found
) {
14111 vty_out(vty
, "Network not in table\n");
14112 bgp_dest_unlock_node(dest
);
14117 ret
= bgp_output_modifier(peer
, rn_p
, &attr
, afi
, safi
,
14120 if (ret
!= RMAP_DENY
) {
14121 show_adj_route_header(vty
, peer
, table
, header1
,
14122 header2
, json
, json_scode
,
14123 json_ocode
, wide
, detail
);
14126 json_net
= json_object_new_object();
14128 bgp_show_path_info(NULL
/* prefix_rd */, dest
, vty
, bgp
,
14129 afi
, safi
, json_net
,
14130 BGP_PATH_SHOW_ALL
, &display
,
14131 RPKI_NOT_BEING_USED
);
14133 json_object_object_addf(json_ar
, json_net
,
14137 (*filtered_count
)++;
14139 bgp_attr_flush(&attr
);
14140 bgp_dest_unlock_node(dest
);
14145 subgrp
= peer_subgroup(peer
, afi
, safi
);
14147 if (type
== bgp_show_adj_route_advertised
&& subgrp
14148 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
14150 json_object_int_add(json
, "bgpTableVersion",
14152 json_object_string_addf(json
, "bgpLocalRouterId",
14153 "%pI4", &bgp
->router_id
);
14154 json_object_int_add(json
, "defaultLocPrf",
14155 bgp
->default_local_pref
);
14156 json_object_int_add(json
, "localAS",
14157 peer
->change_local_as
14158 ? peer
->change_local_as
14160 json_object_object_add(json
, "bgpStatusCodes",
14162 json_object_object_add(json
, "bgpOriginCodes",
14164 json_object_string_add(
14165 json
, "bgpOriginatingDefaultNetwork",
14166 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14169 "BGP table version is %" PRIu64
14170 ", local router ID is %pI4, vrf id ",
14171 table
->version
, &bgp
->router_id
);
14172 if (bgp
->vrf_id
== VRF_UNKNOWN
)
14173 vty_out(vty
, "%s", VRFID_NONE_STR
);
14175 vty_out(vty
, "%u", bgp
->vrf_id
);
14176 vty_out(vty
, "\n");
14177 vty_out(vty
, "Default local pref %u, ",
14178 bgp
->default_local_pref
);
14179 vty_out(vty
, "local AS %u\n",
14180 peer
->change_local_as
? peer
->change_local_as
14183 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14184 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14185 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14186 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14189 vty_out(vty
, "Originating default network %s\n\n",
14190 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14196 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
14197 if (type
== bgp_show_adj_route_received
14198 || type
== bgp_show_adj_route_filtered
) {
14199 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14200 if (ain
->peer
!= peer
)
14203 show_adj_route_header(vty
, peer
, table
, header1
,
14204 header2
, json
, json_scode
,
14205 json_ocode
, wide
, detail
);
14207 if ((safi
== SAFI_MPLS_VPN
)
14208 || (safi
== SAFI_ENCAP
)
14209 || (safi
== SAFI_EVPN
)) {
14211 json_object_string_add(
14212 json_ar
, "rd", rd_str
);
14213 else if (show_rd
&& rd_str
) {
14215 "Route Distinguisher: %s\n",
14222 route_filtered
= false;
14224 /* Filter prefix using distribute list,
14225 * filter list or prefix list
14227 const struct prefix
*rn_p
=
14228 bgp_dest_get_prefix(dest
);
14229 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
14232 route_filtered
= true;
14234 /* Filter prefix using route-map */
14235 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
14236 safi
, rmap_name
, NULL
,
14239 if (type
== bgp_show_adj_route_filtered
&&
14240 !route_filtered
&& ret
!= RMAP_DENY
) {
14241 bgp_attr_flush(&attr
);
14245 if (type
== bgp_show_adj_route_received
14246 && (route_filtered
|| ret
== RMAP_DENY
))
14247 (*filtered_count
)++;
14252 json_object_new_object();
14253 bgp_show_path_info(
14254 NULL
/* prefix_rd */, dest
, vty
,
14255 bgp
, afi
, safi
, json_net
,
14256 BGP_PATH_SHOW_ALL
, &display
,
14257 RPKI_NOT_BEING_USED
);
14259 json_object_object_addf(
14263 route_vty_out_tmp(vty
, dest
, rn_p
,
14264 &attr
, safi
, use_json
,
14266 bgp_attr_flush(&attr
);
14269 } else if (type
== bgp_show_adj_route_advertised
) {
14270 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
14271 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14272 if (paf
->peer
!= peer
|| !adj
->attr
)
14275 show_adj_route_header(
14276 vty
, peer
, table
, header1
,
14277 header2
, json
, json_scode
,
14278 json_ocode
, wide
, detail
);
14280 const struct prefix
*rn_p
=
14281 bgp_dest_get_prefix(dest
);
14284 ret
= bgp_output_modifier(
14285 peer
, rn_p
, &attr
, afi
, safi
,
14288 if (ret
!= RMAP_DENY
) {
14289 if ((safi
== SAFI_MPLS_VPN
)
14290 || (safi
== SAFI_ENCAP
)
14291 || (safi
== SAFI_EVPN
)) {
14293 json_object_string_add(
14300 "Route Distinguisher: %s\n",
14308 json_object_new_object();
14309 bgp_show_path_info(
14318 RPKI_NOT_BEING_USED
);
14320 json_object_object_addf(
14333 (*filtered_count
)++;
14336 bgp_attr_flush(&attr
);
14338 } else if (type
== bgp_show_adj_route_bestpath
) {
14339 struct bgp_path_info
*pi
;
14341 show_adj_route_header(vty
, peer
, table
, header1
,
14342 header2
, json
, json_scode
,
14343 json_ocode
, wide
, detail
);
14345 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
14347 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
14349 if (pi
->peer
!= peer
)
14352 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
14358 json_object_new_object();
14359 bgp_show_path_info(
14360 NULL
/* prefix_rd */, dest
, vty
,
14361 bgp
, afi
, safi
, json_net
,
14362 BGP_PATH_SHOW_BESTPATH
,
14363 &display
, RPKI_NOT_BEING_USED
);
14365 json_object_object_addf(
14370 vty
, dest
, rn_p
, pi
->attr
, safi
,
14371 use_json
, json_ar
, wide
);
14378 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
14379 safi_t safi
, enum bgp_show_adj_route_type type
,
14380 const char *rmap_name
, const struct prefix
*match
,
14381 uint16_t show_flags
)
14384 struct bgp_table
*table
;
14385 json_object
*json
= NULL
;
14386 json_object
*json_scode
= NULL
;
14387 json_object
*json_ocode
= NULL
;
14388 json_object
*json_ar
= NULL
;
14389 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14391 /* Init BGP headers here so they're only displayed once
14392 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14398 * Initialize variables for each RD
14399 * All prefixes under an RD is aggregated within "json_routes"
14401 char rd_str
[BUFSIZ
] = {0};
14402 json_object
*json_routes
= NULL
;
14405 /* For 2-tier tables, prefix counts need to be
14406 * maintained across multiple runs of show_adj_route()
14408 unsigned long output_count_per_rd
;
14409 unsigned long filtered_count_per_rd
;
14410 unsigned long output_count
= 0;
14411 unsigned long filtered_count
= 0;
14414 json
= json_object_new_object();
14415 json_ar
= json_object_new_object();
14416 json_scode
= json_object_new_object();
14417 json_ocode
= json_object_new_object();
14418 #if CONFDATE > 20231208
14419 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14421 json_object_string_add(json_scode
, "suppressed", "s");
14422 json_object_string_add(json_scode
, "damped", "d");
14423 json_object_string_add(json_scode
, "history", "h");
14424 json_object_string_add(json_scode
, "valid", "*");
14425 json_object_string_add(json_scode
, "best", ">");
14426 json_object_string_add(json_scode
, "multipath", "=");
14427 json_object_string_add(json_scode
, "internal", "i");
14428 json_object_string_add(json_scode
, "ribFailure", "r");
14429 json_object_string_add(json_scode
, "stale", "S");
14430 json_object_string_add(json_scode
, "removed", "R");
14432 #if CONFDATE > 20231208
14433 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14435 json_object_string_add(json_ocode
, "igp", "i");
14436 json_object_string_add(json_ocode
, "egp", "e");
14437 json_object_string_add(json_ocode
, "incomplete", "?");
14440 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14442 json_object_string_add(
14444 "No such neighbor or address family");
14445 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14446 json_object_free(json
);
14447 json_object_free(json_ar
);
14448 json_object_free(json_scode
);
14449 json_object_free(json_ocode
);
14451 vty_out(vty
, "%% No such neighbor or address family\n");
14453 return CMD_WARNING
;
14456 if ((type
== bgp_show_adj_route_received
14457 || type
== bgp_show_adj_route_filtered
)
14458 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
14459 PEER_FLAG_SOFT_RECONFIG
)) {
14461 json_object_string_add(
14463 "Inbound soft reconfiguration not enabled");
14464 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14465 json_object_free(json
);
14466 json_object_free(json_ar
);
14467 json_object_free(json_scode
);
14468 json_object_free(json_ocode
);
14471 "%% Inbound soft reconfiguration not enabled\n");
14473 return CMD_WARNING
;
14478 /* labeled-unicast routes live in the unicast table */
14479 if (safi
== SAFI_LABELED_UNICAST
)
14480 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
14482 table
= bgp
->rib
[afi
][safi
];
14484 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14485 || (safi
== SAFI_EVPN
)) {
14487 struct bgp_dest
*dest
;
14489 for (dest
= bgp_table_top(table
); dest
;
14490 dest
= bgp_route_next(dest
)) {
14491 table
= bgp_dest_get_bgp_table_info(dest
);
14495 output_count_per_rd
= 0;
14496 filtered_count_per_rd
= 0;
14499 json_routes
= json_object_new_object();
14501 const struct prefix_rd
*prd
;
14502 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14505 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
),
14509 vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14510 json
, json_routes
, json_scode
, json_ocode
,
14511 show_flags
, &header1
, &header2
, rd_str
, match
,
14512 &output_count_per_rd
, &filtered_count_per_rd
);
14514 /* Don't include an empty RD in the output! */
14515 if (json_routes
&& (output_count_per_rd
> 0))
14516 json_object_object_add(json_ar
, rd_str
,
14519 output_count
+= output_count_per_rd
;
14520 filtered_count
+= filtered_count_per_rd
;
14523 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14524 json
, json_ar
, json_scode
, json_ocode
,
14525 show_flags
, &header1
, &header2
, rd_str
, match
,
14526 &output_count
, &filtered_count
);
14529 if (type
== bgp_show_adj_route_advertised
)
14530 json_object_object_add(json
, "advertisedRoutes",
14533 json_object_object_add(json
, "receivedRoutes", json_ar
);
14534 json_object_int_add(json
, "totalPrefixCounter", output_count
);
14535 json_object_int_add(json
, "filteredPrefixCounter",
14539 * These fields only give up ownership to `json` when `header1`
14540 * is used (set to zero). See code in `show_adj_route` and
14541 * `show_adj_route_header`.
14543 if (header1
== 1) {
14544 json_object_free(json_scode
);
14545 json_object_free(json_ocode
);
14548 vty_json(vty
, json
);
14549 } else if (output_count
> 0) {
14550 if (!match
&& filtered_count
> 0)
14552 "\nTotal number of prefixes %ld (%ld filtered)\n",
14553 output_count
, filtered_count
);
14555 vty_out(vty
, "\nTotal number of prefixes %ld\n",
14559 return CMD_SUCCESS
;
14562 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
14563 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
14564 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
" [" BGP_SAFI_WITH_LABEL_CMD_STR
"]] neighbors <A.B.C.D|X:X::X:X|WORD> bestpath-routes [detail$detail] [json$uj | wide$wide]",
14568 BGP_INSTANCE_HELP_STR
14570 BGP_SAFI_WITH_LABEL_HELP_STR
14571 "Detailed information on TCP and BGP neighbor connections\n"
14572 "Neighbor to display information about\n"
14573 "Neighbor to display information about\n"
14574 "Neighbor on BGP configured interface\n"
14575 "Display the routes selected by best path\n"
14576 "Display detailed version of routes\n"
14578 "Increase table width for longer prefixes\n")
14580 afi_t afi
= AFI_IP6
;
14581 safi_t safi
= SAFI_UNICAST
;
14582 char *rmap_name
= NULL
;
14583 char *peerstr
= NULL
;
14584 struct bgp
*bgp
= NULL
;
14586 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
14588 uint16_t show_flags
= 0;
14591 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14594 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14597 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14599 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14603 return CMD_WARNING
;
14605 argv_find(argv
, argc
, "neighbors", &idx
);
14606 peerstr
= argv
[++idx
]->arg
;
14608 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14610 return CMD_WARNING
;
14612 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, NULL
,
14616 DEFPY(show_ip_bgp_instance_neighbor_advertised_route
,
14617 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
14618 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
" [" BGP_SAFI_WITH_LABEL_CMD_STR
"]] [all$all] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map RMAP_NAME$route_map] [<A.B.C.D/M|X:X::X:X/M>$prefix | detail$detail] [json$uj | wide$wide]",
14622 BGP_INSTANCE_HELP_STR
14624 BGP_SAFI_WITH_LABEL_HELP_STR
14625 "Display the entries for all address families\n"
14626 "Detailed information on TCP and BGP neighbor connections\n"
14627 "Neighbor to display information about\n"
14628 "Neighbor to display information about\n"
14629 "Neighbor on BGP configured interface\n"
14630 "Display the routes advertised to a BGP neighbor\n"
14631 "Display the received routes from neighbor\n"
14632 "Display the filtered routes received from neighbor\n"
14633 "Route-map to modify the attributes\n"
14634 "Name of the route map\n"
14637 "Display detailed version of routes\n"
14639 "Increase table width for longer prefixes\n")
14641 afi_t afi
= AFI_IP6
;
14642 safi_t safi
= SAFI_UNICAST
;
14643 char *peerstr
= NULL
;
14644 struct bgp
*bgp
= NULL
;
14646 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
14649 uint16_t show_flags
= 0;
14650 struct listnode
*node
;
14653 if (detail
|| prefix_str
)
14654 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14658 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14662 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
14663 if (argv_find(argv
, argc
, "ipv4", &idx
))
14664 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
14666 if (argv_find(argv
, argc
, "ipv6", &idx
))
14667 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
14671 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14673 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14676 return CMD_WARNING
;
14678 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14679 argv_find(argv
, argc
, "neighbors", &idx
);
14680 peerstr
= argv
[++idx
]->arg
;
14682 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14684 return CMD_WARNING
;
14686 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
14687 type
= bgp_show_adj_route_advertised
;
14688 else if (argv_find(argv
, argc
, "received-routes", &idx
))
14689 type
= bgp_show_adj_route_received
;
14690 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
14691 type
= bgp_show_adj_route_filtered
;
14694 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, route_map
,
14695 prefix_str
? prefix
: NULL
, show_flags
);
14697 vty_out(vty
, "{\n");
14699 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14700 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14701 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14703 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14704 FOREACH_SAFI (safi
) {
14705 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14712 vty_out(vty
, ",\n");
14713 vty_out(vty
, "\"%s\":",
14714 get_afi_safi_str(afi
, safi
,
14718 "\nFor address family: %s\n",
14719 get_afi_safi_str(afi
, safi
,
14722 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14723 route_map
, prefix
, show_flags
);
14727 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14728 FOREACH_AFI_SAFI (afi
, safi
) {
14729 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14736 vty_out(vty
, ",\n");
14737 vty_out(vty
, "\"%s\":",
14738 get_afi_safi_str(afi
, safi
,
14742 "\nFor address family: %s\n",
14743 get_afi_safi_str(afi
, safi
,
14746 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14747 route_map
, prefix
, show_flags
);
14752 vty_out(vty
, "}\n");
14754 return CMD_SUCCESS
;
14757 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14758 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14759 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14763 BGP_INSTANCE_HELP_STR
14766 BGP_AF_MODIFIER_STR
14767 "Detailed information on TCP and BGP neighbor connections\n"
14768 "Neighbor to display information about\n"
14769 "Neighbor to display information about\n"
14770 "Neighbor on BGP configured interface\n"
14771 "Display information received from a BGP neighbor\n"
14772 "Display the prefixlist filter\n"
14775 afi_t afi
= AFI_IP6
;
14776 safi_t safi
= SAFI_UNICAST
;
14777 char *peerstr
= NULL
;
14782 struct bgp
*bgp
= NULL
;
14783 bool uj
= use_json(argc
, argv
);
14788 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14791 return CMD_WARNING
;
14793 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14794 argv_find(argv
, argc
, "neighbors", &idx
);
14795 peerstr
= argv
[++idx
]->arg
;
14797 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14799 return CMD_WARNING
;
14801 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14802 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14805 vty_out(vty
, "Address Family: %s\n",
14806 get_afi_safi_str(afi
, safi
, false));
14807 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14810 vty_out(vty
, "{}\n");
14812 vty_out(vty
, "No functional output\n");
14815 return CMD_SUCCESS
;
14818 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14819 afi_t afi
, safi_t safi
,
14820 enum bgp_show_type type
, bool use_json
)
14822 uint16_t show_flags
= 0;
14825 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14827 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14829 json_object
*json_no
= NULL
;
14830 json_no
= json_object_new_object();
14831 json_object_string_add(
14832 json_no
, "warning",
14833 "No such neighbor or address family");
14834 vty_out(vty
, "%s\n",
14835 json_object_to_json_string(json_no
));
14836 json_object_free(json_no
);
14838 vty_out(vty
, "%% No such neighbor or address family\n");
14839 return CMD_WARNING
;
14842 /* labeled-unicast routes live in the unicast table */
14843 if (safi
== SAFI_LABELED_UNICAST
)
14844 safi
= SAFI_UNICAST
;
14846 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14847 RPKI_NOT_BEING_USED
);
14850 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14851 show_ip_bgp_flowspec_routes_detailed_cmd
,
14852 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14856 BGP_INSTANCE_HELP_STR
14859 "Detailed information on flowspec entries\n"
14862 afi_t afi
= AFI_IP6
;
14863 safi_t safi
= SAFI_UNICAST
;
14864 struct bgp
*bgp
= NULL
;
14866 bool uj
= use_json(argc
, argv
);
14867 uint16_t show_flags
= BGP_SHOW_OPT_ROUTES_DETAIL
;
14871 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14874 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14877 return CMD_WARNING
;
14879 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14880 show_flags
, RPKI_NOT_BEING_USED
);
14883 DEFUN (show_ip_bgp_neighbor_routes
,
14884 show_ip_bgp_neighbor_routes_cmd
,
14885 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
14889 BGP_INSTANCE_HELP_STR
14891 BGP_SAFI_WITH_LABEL_HELP_STR
14892 "Detailed information on TCP and BGP neighbor connections\n"
14893 "Neighbor to display information about\n"
14894 "Neighbor to display information about\n"
14895 "Neighbor on BGP configured interface\n"
14896 "Display flap statistics of the routes learned from neighbor\n"
14897 "Display the dampened routes received from neighbor\n"
14898 "Display routes learned from neighbor\n"
14901 char *peerstr
= NULL
;
14902 struct bgp
*bgp
= NULL
;
14903 afi_t afi
= AFI_IP6
;
14904 safi_t safi
= SAFI_UNICAST
;
14906 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14908 bool uj
= use_json(argc
, argv
);
14913 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14916 return CMD_WARNING
;
14918 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14919 argv_find(argv
, argc
, "neighbors", &idx
);
14920 peerstr
= argv
[++idx
]->arg
;
14922 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14924 return CMD_WARNING
;
14926 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14927 sh_type
= bgp_show_type_flap_neighbor
;
14928 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14929 sh_type
= bgp_show_type_damp_neighbor
;
14930 else if (argv_find(argv
, argc
, "routes", &idx
))
14931 sh_type
= bgp_show_type_neighbor
;
14933 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14936 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14938 struct bgp_distance
{
14939 /* Distance value for the IP source prefix. */
14942 /* Name of the access-list to be matched. */
14946 DEFUN (show_bgp_afi_vpn_rd_route
,
14947 show_bgp_afi_vpn_rd_route_cmd
,
14948 "show bgp "BGP_AFI_CMD_STR
" vpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> <A.B.C.D/M|X:X::X:X/M> [json]",
14952 BGP_AF_MODIFIER_STR
14953 "Display information for a route distinguisher\n"
14954 "Route Distinguisher\n"
14955 "All Route Distinguishers\n"
14956 "Network in the BGP routing table to display\n"
14957 "Network in the BGP routing table to display\n"
14961 struct prefix_rd prd
;
14962 afi_t afi
= AFI_MAX
;
14965 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
14966 vty_out(vty
, "%% Malformed Address Family\n");
14967 return CMD_WARNING
;
14970 if (!strcmp(argv
[5]->arg
, "all"))
14971 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
14972 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
14973 RPKI_NOT_BEING_USED
,
14974 use_json(argc
, argv
));
14976 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
14978 vty_out(vty
, "%% Malformed Route Distinguisher\n");
14979 return CMD_WARNING
;
14982 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
14983 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14984 use_json(argc
, argv
));
14987 static struct bgp_distance
*bgp_distance_new(void)
14989 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
14992 static void bgp_distance_free(struct bgp_distance
*bdistance
)
14994 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
14997 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
14998 const char *ip_str
, const char *access_list_str
)
15005 struct bgp_dest
*dest
;
15006 struct bgp_distance
*bdistance
;
15008 afi
= bgp_node_afi(vty
);
15009 safi
= bgp_node_safi(vty
);
15011 ret
= str2prefix(ip_str
, &p
);
15013 vty_out(vty
, "Malformed prefix\n");
15014 return CMD_WARNING_CONFIG_FAILED
;
15017 distance
= atoi(distance_str
);
15019 /* Get BGP distance node. */
15020 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
15021 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15023 bgp_dest_unlock_node(dest
);
15025 bdistance
= bgp_distance_new();
15026 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
15029 /* Set distance value. */
15030 bdistance
->distance
= distance
;
15032 /* Reset access-list configuration. */
15033 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
15034 if (access_list_str
)
15035 bdistance
->access_list
=
15036 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
15038 return CMD_SUCCESS
;
15041 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
15042 const char *ip_str
, const char *access_list_str
)
15049 struct bgp_dest
*dest
;
15050 struct bgp_distance
*bdistance
;
15052 afi
= bgp_node_afi(vty
);
15053 safi
= bgp_node_safi(vty
);
15055 ret
= str2prefix(ip_str
, &p
);
15057 vty_out(vty
, "Malformed prefix\n");
15058 return CMD_WARNING_CONFIG_FAILED
;
15061 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
15063 vty_out(vty
, "Can't find specified prefix\n");
15064 return CMD_WARNING_CONFIG_FAILED
;
15067 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15068 distance
= atoi(distance_str
);
15070 if (bdistance
->distance
!= distance
) {
15071 vty_out(vty
, "Distance does not match configured\n");
15072 bgp_dest_unlock_node(dest
);
15073 return CMD_WARNING_CONFIG_FAILED
;
15076 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
15077 bgp_distance_free(bdistance
);
15079 bgp_dest_set_bgp_path_info(dest
, NULL
);
15080 bgp_dest_unlock_node(dest
);
15081 bgp_dest_unlock_node(dest
);
15083 return CMD_SUCCESS
;
15086 /* Apply BGP information to distance method. */
15087 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
15088 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
15090 struct bgp_dest
*dest
;
15091 struct prefix q
= {0};
15093 struct bgp_distance
*bdistance
;
15094 struct access_list
*alist
;
15095 struct bgp_static
*bgp_static
;
15096 struct bgp_path_info
*bpi_ultimate
;
15101 peer
= pinfo
->peer
;
15103 if (pinfo
->attr
->distance
)
15104 return pinfo
->attr
->distance
;
15106 /* get peer origin to calculate appropriate distance */
15107 if (pinfo
->sub_type
== BGP_ROUTE_IMPORTED
) {
15108 bpi_ultimate
= bgp_get_imported_bpi_ultimate(pinfo
);
15109 peer
= bpi_ultimate
->peer
;
15112 /* Check source address.
15113 * Note: for aggregate route, peer can have unspec af type.
15115 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
15116 && !sockunion2hostprefix(&peer
->su
, &q
))
15119 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
15121 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15122 bgp_dest_unlock_node(dest
);
15124 if (bdistance
->access_list
) {
15125 alist
= access_list_lookup(afi
, bdistance
->access_list
);
15127 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
15128 return bdistance
->distance
;
15130 return bdistance
->distance
;
15133 /* Backdoor check. */
15134 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
15136 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15137 bgp_dest_unlock_node(dest
);
15139 if (bgp_static
->backdoor
) {
15140 if (bgp
->distance_local
[afi
][safi
])
15141 return bgp
->distance_local
[afi
][safi
];
15143 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15147 if (peer
->sort
== BGP_PEER_EBGP
) {
15148 if (bgp
->distance_ebgp
[afi
][safi
])
15149 return bgp
->distance_ebgp
[afi
][safi
];
15150 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
15151 } else if (peer
->sort
== BGP_PEER_IBGP
) {
15152 if (bgp
->distance_ibgp
[afi
][safi
])
15153 return bgp
->distance_ibgp
[afi
][safi
];
15154 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15156 if (bgp
->distance_local
[afi
][safi
])
15157 return bgp
->distance_local
[afi
][safi
];
15158 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15162 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15163 * we should tell ZEBRA update the routes for a specific
15164 * AFI/SAFI to reflect changes in RIB.
15166 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
15168 safi_t update_safi
)
15173 FOREACH_AFI_SAFI (afi
, safi
) {
15174 if (!bgp_fibupd_safi(safi
))
15177 if (afi
!= update_afi
&& safi
!= update_safi
)
15180 if (BGP_DEBUG(zebra
, ZEBRA
))
15182 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15183 __func__
, afi
, safi
);
15184 bgp_zebra_announce_table(bgp
, afi
, safi
);
15188 DEFUN (bgp_distance
,
15190 "distance bgp (1-255) (1-255) (1-255)",
15191 "Define an administrative distance\n"
15193 "Distance for routes external to the AS\n"
15194 "Distance for routes internal to the AS\n"
15195 "Distance for local routes\n")
15197 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15198 int idx_number
= 2;
15199 int idx_number_2
= 3;
15200 int idx_number_3
= 4;
15201 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
15202 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
15203 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
15207 afi
= bgp_node_afi(vty
);
15208 safi
= bgp_node_safi(vty
);
15210 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
15211 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
15212 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
15213 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
15214 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
15215 bgp
->distance_local
[afi
][safi
] = distance_local
;
15216 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15218 return CMD_SUCCESS
;
15221 DEFUN (no_bgp_distance
,
15222 no_bgp_distance_cmd
,
15223 "no distance bgp [(1-255) (1-255) (1-255)]",
15225 "Define an administrative distance\n"
15227 "Distance for routes external to the AS\n"
15228 "Distance for routes internal to the AS\n"
15229 "Distance for local routes\n")
15231 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15235 afi
= bgp_node_afi(vty
);
15236 safi
= bgp_node_safi(vty
);
15238 if (bgp
->distance_ebgp
[afi
][safi
] != 0
15239 || bgp
->distance_ibgp
[afi
][safi
] != 0
15240 || bgp
->distance_local
[afi
][safi
] != 0) {
15241 bgp
->distance_ebgp
[afi
][safi
] = 0;
15242 bgp
->distance_ibgp
[afi
][safi
] = 0;
15243 bgp
->distance_local
[afi
][safi
] = 0;
15244 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15246 return CMD_SUCCESS
;
15250 DEFUN (bgp_distance_source
,
15251 bgp_distance_source_cmd
,
15252 "distance (1-255) A.B.C.D/M",
15253 "Define an administrative distance\n"
15254 "Administrative distance\n"
15255 "IP source prefix\n")
15257 int idx_number
= 1;
15258 int idx_ipv4_prefixlen
= 2;
15259 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15260 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15261 return CMD_SUCCESS
;
15264 DEFUN (no_bgp_distance_source
,
15265 no_bgp_distance_source_cmd
,
15266 "no distance (1-255) A.B.C.D/M",
15268 "Define an administrative distance\n"
15269 "Administrative distance\n"
15270 "IP source prefix\n")
15272 int idx_number
= 2;
15273 int idx_ipv4_prefixlen
= 3;
15274 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15275 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15276 return CMD_SUCCESS
;
15279 DEFUN (bgp_distance_source_access_list
,
15280 bgp_distance_source_access_list_cmd
,
15281 "distance (1-255) A.B.C.D/M WORD",
15282 "Define an administrative distance\n"
15283 "Administrative distance\n"
15284 "IP source prefix\n"
15285 "Access list name\n")
15287 int idx_number
= 1;
15288 int idx_ipv4_prefixlen
= 2;
15290 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15291 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15292 return CMD_SUCCESS
;
15295 DEFUN (no_bgp_distance_source_access_list
,
15296 no_bgp_distance_source_access_list_cmd
,
15297 "no distance (1-255) A.B.C.D/M WORD",
15299 "Define an administrative distance\n"
15300 "Administrative distance\n"
15301 "IP source prefix\n"
15302 "Access list name\n")
15304 int idx_number
= 2;
15305 int idx_ipv4_prefixlen
= 3;
15307 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15308 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15309 return CMD_SUCCESS
;
15312 DEFUN (ipv6_bgp_distance_source
,
15313 ipv6_bgp_distance_source_cmd
,
15314 "distance (1-255) X:X::X:X/M",
15315 "Define an administrative distance\n"
15316 "Administrative distance\n"
15317 "IP source prefix\n")
15319 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
15320 return CMD_SUCCESS
;
15323 DEFUN (no_ipv6_bgp_distance_source
,
15324 no_ipv6_bgp_distance_source_cmd
,
15325 "no distance (1-255) X:X::X:X/M",
15327 "Define an administrative distance\n"
15328 "Administrative distance\n"
15329 "IP source prefix\n")
15331 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
15332 return CMD_SUCCESS
;
15335 DEFUN (ipv6_bgp_distance_source_access_list
,
15336 ipv6_bgp_distance_source_access_list_cmd
,
15337 "distance (1-255) X:X::X:X/M WORD",
15338 "Define an administrative distance\n"
15339 "Administrative distance\n"
15340 "IP source prefix\n"
15341 "Access list name\n")
15343 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
15344 return CMD_SUCCESS
;
15347 DEFUN (no_ipv6_bgp_distance_source_access_list
,
15348 no_ipv6_bgp_distance_source_access_list_cmd
,
15349 "no distance (1-255) X:X::X:X/M WORD",
15351 "Define an administrative distance\n"
15352 "Administrative distance\n"
15353 "IP source prefix\n"
15354 "Access list name\n")
15356 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
15357 return CMD_SUCCESS
;
15360 DEFUN (bgp_damp_set
,
15362 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15363 "BGP Specific commands\n"
15364 "Enable route-flap dampening\n"
15365 "Half-life time for the penalty\n"
15366 "Value to start reusing a route\n"
15367 "Value to start suppressing a route\n"
15368 "Maximum duration to suppress a stable route\n")
15370 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15371 int idx_half_life
= 2;
15373 int idx_suppress
= 4;
15374 int idx_max_suppress
= 5;
15375 int half
= DEFAULT_HALF_LIFE
* 60;
15376 int reuse
= DEFAULT_REUSE
;
15377 int suppress
= DEFAULT_SUPPRESS
;
15378 int max
= 4 * half
;
15381 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15382 reuse
= atoi(argv
[idx_reuse
]->arg
);
15383 suppress
= atoi(argv
[idx_suppress
]->arg
);
15384 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
15385 } else if (argc
== 3) {
15386 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15391 * These can't be 0 but our SA doesn't understand the
15392 * way our cli is constructed
15396 if (suppress
< reuse
) {
15398 "Suppress value cannot be less than reuse value \n");
15402 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
15403 reuse
, suppress
, max
);
15406 DEFUN (bgp_damp_unset
,
15407 bgp_damp_unset_cmd
,
15408 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15410 "BGP Specific commands\n"
15411 "Enable route-flap dampening\n"
15412 "Half-life time for the penalty\n"
15413 "Value to start reusing a route\n"
15414 "Value to start suppressing a route\n"
15415 "Maximum duration to suppress a stable route\n")
15417 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15418 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
15421 /* Display specified route of BGP table. */
15422 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
15423 const char *ip_str
, afi_t afi
, safi_t safi
,
15424 struct prefix_rd
*prd
, int prefix_check
)
15427 struct prefix match
;
15428 struct bgp_dest
*dest
;
15429 struct bgp_dest
*rm
;
15430 struct bgp_path_info
*pi
;
15431 struct bgp_path_info
*pi_temp
;
15433 struct bgp_table
*table
;
15435 /* BGP structure lookup. */
15437 bgp
= bgp_lookup_by_name(view_name
);
15439 vty_out(vty
, "%% Can't find BGP instance %s\n",
15441 return CMD_WARNING
;
15444 bgp
= bgp_get_default();
15446 vty_out(vty
, "%% No BGP process is configured\n");
15447 return CMD_WARNING
;
15451 /* Check IP address argument. */
15452 ret
= str2prefix(ip_str
, &match
);
15454 vty_out(vty
, "%% address is malformed\n");
15455 return CMD_WARNING
;
15458 match
.family
= afi2family(afi
);
15460 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
15461 || (safi
== SAFI_EVPN
)) {
15462 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
15463 dest
= bgp_route_next(dest
)) {
15464 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15466 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
15468 table
= bgp_dest_get_bgp_table_info(dest
);
15471 rm
= bgp_node_match(table
, &match
);
15475 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
15478 || rm_p
->prefixlen
== match
.prefixlen
) {
15479 pi
= bgp_dest_get_bgp_path_info(rm
);
15481 if (pi
->extra
&& pi
->extra
->damp_info
) {
15482 pi_temp
= pi
->next
;
15483 bgp_damp_info_free(
15484 pi
->extra
->damp_info
,
15492 bgp_dest_unlock_node(rm
);
15495 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
15496 if (dest
!= NULL
) {
15497 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15500 || dest_p
->prefixlen
== match
.prefixlen
) {
15501 pi
= bgp_dest_get_bgp_path_info(dest
);
15503 if (pi
->extra
&& pi
->extra
->damp_info
) {
15504 pi_temp
= pi
->next
;
15505 bgp_damp_info_free(
15506 pi
->extra
->damp_info
,
15514 bgp_dest_unlock_node(dest
);
15518 return CMD_SUCCESS
;
15521 DEFUN (clear_ip_bgp_dampening
,
15522 clear_ip_bgp_dampening_cmd
,
15523 "clear ip bgp dampening",
15527 "Clear route flap dampening information\n")
15529 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
15530 return CMD_SUCCESS
;
15533 DEFUN (clear_ip_bgp_dampening_prefix
,
15534 clear_ip_bgp_dampening_prefix_cmd
,
15535 "clear ip bgp dampening A.B.C.D/M",
15539 "Clear route flap dampening information\n"
15542 int idx_ipv4_prefixlen
= 4;
15543 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
15544 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
15547 DEFUN (clear_ip_bgp_dampening_address
,
15548 clear_ip_bgp_dampening_address_cmd
,
15549 "clear ip bgp dampening A.B.C.D",
15553 "Clear route flap dampening information\n"
15554 "Network to clear damping information\n")
15557 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
15558 SAFI_UNICAST
, NULL
, 0);
15561 DEFUN (clear_ip_bgp_dampening_address_mask
,
15562 clear_ip_bgp_dampening_address_mask_cmd
,
15563 "clear ip bgp dampening A.B.C.D A.B.C.D",
15567 "Clear route flap dampening information\n"
15568 "Network to clear damping information\n"
15572 int idx_ipv4_2
= 5;
15574 char prefix_str
[BUFSIZ
];
15576 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
15577 prefix_str
, sizeof(prefix_str
));
15579 vty_out(vty
, "%% Inconsistent address and mask\n");
15580 return CMD_WARNING
;
15583 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
15587 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
15589 struct vty
*vty
= arg
;
15590 struct peer
*peer
= bucket
->data
;
15592 vty_out(vty
, "\tPeer: %s %pSU\n", peer
->host
, &peer
->su
);
15595 DEFUN (show_bgp_listeners
,
15596 show_bgp_listeners_cmd
,
15597 "show bgp listeners",
15600 "Display Listen Sockets and who created them\n")
15602 bgp_dump_listener_info(vty
);
15604 return CMD_SUCCESS
;
15607 DEFUN (show_bgp_peerhash
,
15608 show_bgp_peerhash_cmd
,
15609 "show bgp peerhash",
15612 "Display information about the BGP peerhash\n")
15614 struct list
*instances
= bm
->bgp
;
15615 struct listnode
*node
;
15618 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
15619 vty_out(vty
, "BGP: %s\n", bgp
->name
);
15620 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
15624 return CMD_SUCCESS
;
15627 /* also used for encap safi */
15628 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
15629 afi_t afi
, safi_t safi
)
15631 struct bgp_dest
*pdest
;
15632 struct bgp_dest
*dest
;
15633 struct bgp_table
*table
;
15634 const struct prefix
*p
;
15635 struct bgp_static
*bgp_static
;
15636 mpls_label_t label
;
15638 /* Network configuration. */
15639 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15640 pdest
= bgp_route_next(pdest
)) {
15641 table
= bgp_dest_get_bgp_table_info(pdest
);
15645 for (dest
= bgp_table_top(table
); dest
;
15646 dest
= bgp_route_next(dest
)) {
15647 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15648 if (bgp_static
== NULL
)
15651 p
= bgp_dest_get_prefix(dest
);
15653 /* "network" configuration display. */
15654 label
= decode_label(&bgp_static
->label
);
15656 vty_out(vty
, " network %pFX rd %s", p
,
15657 bgp_static
->prd_pretty
);
15658 if (safi
== SAFI_MPLS_VPN
)
15659 vty_out(vty
, " label %u", label
);
15661 if (bgp_static
->rmap
.name
)
15662 vty_out(vty
, " route-map %s",
15663 bgp_static
->rmap
.name
);
15665 if (bgp_static
->backdoor
)
15666 vty_out(vty
, " backdoor");
15668 vty_out(vty
, "\n");
15673 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
15674 afi_t afi
, safi_t safi
)
15676 struct bgp_dest
*pdest
;
15677 struct bgp_dest
*dest
;
15678 struct bgp_table
*table
;
15679 const struct prefix
*p
;
15680 struct bgp_static
*bgp_static
;
15681 char buf
[PREFIX_STRLEN
* 2];
15682 char buf2
[SU_ADDRSTRLEN
];
15683 char esi_buf
[ESI_STR_LEN
];
15685 /* Network configuration. */
15686 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15687 pdest
= bgp_route_next(pdest
)) {
15688 table
= bgp_dest_get_bgp_table_info(pdest
);
15692 for (dest
= bgp_table_top(table
); dest
;
15693 dest
= bgp_route_next(dest
)) {
15694 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15695 if (bgp_static
== NULL
)
15698 char *macrouter
= NULL
;
15700 if (bgp_static
->router_mac
)
15701 macrouter
= prefix_mac2str(
15702 bgp_static
->router_mac
, NULL
, 0);
15703 if (bgp_static
->eth_s_id
)
15704 esi_to_str(bgp_static
->eth_s_id
,
15705 esi_buf
, sizeof(esi_buf
));
15706 p
= bgp_dest_get_prefix(dest
);
15708 /* "network" configuration display. */
15709 if (p
->u
.prefix_evpn
.route_type
== 5) {
15710 char local_buf
[PREFIX_STRLEN
];
15712 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15713 struct prefix_evpn
*)p
)
15717 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
15719 local_buf
, sizeof(local_buf
));
15720 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15721 p
->u
.prefix_evpn
.prefix_addr
15722 .ip_prefix_length
);
15724 prefix2str(p
, buf
, sizeof(buf
));
15727 if (bgp_static
->gatewayIp
.family
== AF_INET
15728 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15729 inet_ntop(bgp_static
->gatewayIp
.family
,
15730 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15733 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15734 buf
, bgp_static
->prd_pretty
,
15735 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15736 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15739 XFREE(MTYPE_TMP
, macrouter
);
15744 /* Configuration of static route announcement and aggregate
15746 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15749 struct bgp_dest
*dest
;
15750 const struct prefix
*p
;
15751 struct bgp_static
*bgp_static
;
15752 struct bgp_aggregate
*bgp_aggregate
;
15754 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15755 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15759 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15760 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15764 /* Network configuration. */
15765 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15766 dest
= bgp_route_next(dest
)) {
15767 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15768 if (bgp_static
== NULL
)
15771 p
= bgp_dest_get_prefix(dest
);
15773 vty_out(vty
, " network %pFX", p
);
15775 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15776 vty_out(vty
, " label-index %u",
15777 bgp_static
->label_index
);
15779 if (bgp_static
->rmap
.name
)
15780 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15782 if (bgp_static
->backdoor
)
15783 vty_out(vty
, " backdoor");
15785 vty_out(vty
, "\n");
15788 /* Aggregate-address configuration. */
15789 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15790 dest
= bgp_route_next(dest
)) {
15791 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15792 if (bgp_aggregate
== NULL
)
15795 p
= bgp_dest_get_prefix(dest
);
15797 vty_out(vty
, " aggregate-address %pFX", p
);
15799 if (bgp_aggregate
->as_set
)
15800 vty_out(vty
, " as-set");
15802 if (bgp_aggregate
->summary_only
)
15803 vty_out(vty
, " summary-only");
15805 if (bgp_aggregate
->rmap
.name
)
15806 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15808 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15809 vty_out(vty
, " origin %s",
15810 bgp_origin2str(bgp_aggregate
->origin
));
15812 if (bgp_aggregate
->match_med
)
15813 vty_out(vty
, " matching-MED-only");
15815 if (bgp_aggregate
->suppress_map_name
)
15816 vty_out(vty
, " suppress-map %s",
15817 bgp_aggregate
->suppress_map_name
);
15819 vty_out(vty
, "\n");
15823 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15826 struct bgp_dest
*dest
;
15827 struct bgp_distance
*bdistance
;
15829 /* Distance configuration. */
15830 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15831 && bgp
->distance_local
[afi
][safi
]
15832 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15833 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15834 || bgp
->distance_local
[afi
][safi
]
15835 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15836 vty_out(vty
, " distance bgp %d %d %d\n",
15837 bgp
->distance_ebgp
[afi
][safi
],
15838 bgp
->distance_ibgp
[afi
][safi
],
15839 bgp
->distance_local
[afi
][safi
]);
15842 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15843 dest
= bgp_route_next(dest
)) {
15844 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15845 if (bdistance
!= NULL
)
15846 vty_out(vty
, " distance %d %pBD %s\n",
15847 bdistance
->distance
, dest
,
15848 bdistance
->access_list
? bdistance
->access_list
15853 /* Allocate routing table structure and install commands. */
15854 void bgp_route_init(void)
15859 /* Init BGP distance table. */
15860 FOREACH_AFI_SAFI (afi
, safi
)
15861 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15863 /* IPv4 BGP commands. */
15864 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15865 install_element(BGP_NODE
, &bgp_network_cmd
);
15866 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15868 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15870 /* IPv4 unicast configuration. */
15871 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15872 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15873 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15875 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15877 /* IPv4 multicast configuration. */
15878 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15879 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15880 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15881 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15883 /* IPv4 labeled-unicast configuration. */
15884 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15885 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15887 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15888 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15889 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15890 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15891 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15892 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15893 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15894 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15896 install_element(VIEW_NODE
,
15897 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15898 install_element(VIEW_NODE
,
15899 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15900 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15901 install_element(VIEW_NODE
,
15902 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15903 #ifdef KEEP_OLD_VPN_COMMANDS
15904 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15905 #endif /* KEEP_OLD_VPN_COMMANDS */
15906 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15907 install_element(VIEW_NODE
,
15908 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15910 /* BGP dampening clear commands */
15911 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15912 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15914 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15915 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15918 install_element(ENABLE_NODE
,
15919 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15920 #ifdef KEEP_OLD_VPN_COMMANDS
15921 install_element(ENABLE_NODE
,
15922 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15923 #endif /* KEEP_OLD_VPN_COMMANDS */
15925 /* New config IPv6 BGP commands. */
15926 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15927 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15928 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15930 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15932 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15934 /* IPv6 labeled unicast address family. */
15935 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15936 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15938 install_element(BGP_NODE
, &bgp_distance_cmd
);
15939 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15940 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15941 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
15942 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
15943 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
15944 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15945 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15946 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15947 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
15948 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
15949 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
15950 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15951 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15952 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
15953 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
15954 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
15955 install_element(BGP_IPV4M_NODE
,
15956 &no_bgp_distance_source_access_list_cmd
);
15957 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
15958 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
15959 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
15960 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15961 install_element(BGP_IPV6_NODE
,
15962 &ipv6_bgp_distance_source_access_list_cmd
);
15963 install_element(BGP_IPV6_NODE
,
15964 &no_ipv6_bgp_distance_source_access_list_cmd
);
15965 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
15966 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
15967 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
15968 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15969 install_element(BGP_IPV6M_NODE
,
15970 &ipv6_bgp_distance_source_access_list_cmd
);
15971 install_element(BGP_IPV6M_NODE
,
15972 &no_ipv6_bgp_distance_source_access_list_cmd
);
15974 /* BGP dampening */
15975 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
15976 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
15977 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
15978 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
15979 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
15980 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
15981 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
15982 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
15983 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
15984 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
15985 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
15986 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
15987 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
15988 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
15990 /* Large Communities */
15991 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
15992 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
15994 /* show bgp ipv4 flowspec detailed */
15995 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
15997 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
15998 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
16001 void bgp_route_finish(void)
16006 FOREACH_AFI_SAFI (afi
, safi
) {
16007 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
16008 bgp_distance_table
[afi
][safi
] = NULL
;