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_safi_node_lookup(struct bgp_table
*table
, safi_t safi
,
155 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
)) {
320 table
= bgp_dest_table(dest
);
325 "Route %pBD(%s) is in workqueue and being processed, not deferred.",
326 dest
, bgp
? bgp
->name_pretty
: "(Unknown)");
332 table
= bgp_dest_table(dest
);
339 for (old_pi
= bgp_dest_get_bgp_path_info(dest
);
340 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
341 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
344 /* Route selection is deferred if there is a stale path which
345 * which indicates peer is in restart mode
347 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
348 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
351 /* If the peer is graceful restart capable and peer is
352 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
355 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
356 && BGP_PEER_RESTARTING_MODE(peer
)
358 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
366 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
369 if (set_flag
&& table
) {
370 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
371 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
372 bgp
->gr_info
[afi
][safi
].gr_deferred
++;
373 SET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
374 if (BGP_DEBUG(update
, UPDATE_OUT
))
375 zlog_debug("DEFER route %pBD(%s), dest %p",
376 dest
, bgp
->name_pretty
, dest
);
383 void bgp_path_info_add_with_caller(const char *name
, struct bgp_dest
*dest
,
384 struct bgp_path_info
*pi
)
386 frrtrace(3, frr_bgp
, bgp_path_info_add
, dest
, pi
, name
);
387 struct bgp_path_info
*top
;
389 top
= bgp_dest_get_bgp_path_info(dest
);
395 bgp_dest_set_bgp_path_info(dest
, pi
);
397 bgp_path_info_lock(pi
);
398 bgp_dest_lock_node(dest
);
399 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
400 bgp_dest_set_defer_flag(dest
, false);
401 hook_call(bgp_snmp_update_stats
, dest
, pi
, true);
404 /* Do the actual removal of info from RIB, for use by bgp_process
405 completion callback *only* */
406 void bgp_path_info_reap(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
409 pi
->next
->prev
= pi
->prev
;
411 pi
->prev
->next
= pi
->next
;
413 bgp_dest_set_bgp_path_info(dest
, pi
->next
);
415 bgp_path_info_mpath_dequeue(pi
);
416 bgp_path_info_unlock(pi
);
417 hook_call(bgp_snmp_update_stats
, dest
, pi
, false);
418 bgp_dest_unlock_node(dest
);
421 void bgp_path_info_delete(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
423 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_REMOVED
);
424 /* set of previous already took care of pcount */
425 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
428 /* undo the effects of a previous call to bgp_path_info_delete; typically
429 called when a route is deleted and then quickly re-added before the
430 deletion has been processed */
431 void bgp_path_info_restore(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
433 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_REMOVED
);
434 /* unset of previous already took care of pcount */
435 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
438 /* Adjust pcount as required */
439 static void bgp_pcount_adjust(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
441 struct bgp_table
*table
;
443 assert(dest
&& bgp_dest_table(dest
));
444 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
446 table
= bgp_dest_table(dest
);
448 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
451 if (!BGP_PATH_COUNTABLE(pi
)
452 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
454 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
456 /* slight hack, but more robust against errors. */
457 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
458 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
460 flog_err(EC_LIB_DEVELOPMENT
,
461 "Asked to decrement 0 prefix count for peer");
462 } else if (BGP_PATH_COUNTABLE(pi
)
463 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
464 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
465 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
469 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
470 struct bgp_path_info
*pi2
)
472 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
475 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
476 * This is here primarily to keep prefix-count in check.
478 void bgp_path_info_set_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
481 SET_FLAG(pi
->flags
, flag
);
483 /* early bath if we know it's not a flag that changes countability state
485 if (!CHECK_FLAG(flag
,
486 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
489 bgp_pcount_adjust(dest
, pi
);
492 void bgp_path_info_unset_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
495 UNSET_FLAG(pi
->flags
, flag
);
497 /* early bath if we know it's not a flag that changes countability state
499 if (!CHECK_FLAG(flag
,
500 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
503 bgp_pcount_adjust(dest
, pi
);
506 /* Get MED value. If MED value is missing and "bgp bestpath
507 missing-as-worst" is specified, treat it as the worst value. */
508 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
510 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
513 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
520 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
,
525 if (pi
->sub_type
== BGP_ROUTE_IMPORTED
&&
526 bgp_get_imported_bpi_ultimate(pi
))
527 peer
= bgp_get_imported_bpi_ultimate(pi
)->peer
;
531 if (pi
->addpath_rx_id
)
532 snprintf(buf
, buf_len
, "path %s (addpath rxid %d)", peer
->host
,
535 snprintf(buf
, buf_len
, "path %s", peer
->host
);
540 * Get the ultimate path info.
542 struct bgp_path_info
*bgp_get_imported_bpi_ultimate(struct bgp_path_info
*info
)
544 struct bgp_path_info
*bpi_ultimate
;
546 if (info
->sub_type
!= BGP_ROUTE_IMPORTED
)
549 for (bpi_ultimate
= info
;
550 bpi_ultimate
->extra
&& bpi_ultimate
->extra
->parent
;
551 bpi_ultimate
= bpi_ultimate
->extra
->parent
)
557 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
559 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
560 struct bgp_path_info
*exist
, int *paths_eq
,
561 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
562 char *pfx_buf
, afi_t afi
, safi_t safi
,
563 enum bgp_path_selection_reason
*reason
)
565 const struct prefix
*new_p
;
566 struct attr
*newattr
, *existattr
;
567 enum bgp_peer_sort new_sort
;
568 enum bgp_peer_sort exist_sort
;
574 uint32_t exist_weight
;
575 uint32_t newm
, existm
;
576 struct in_addr new_id
;
577 struct in_addr exist_id
;
580 int internal_as_route
;
583 int igp_metric_ret
= 0;
584 int peer_sort_ret
= -1;
585 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
586 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
588 uint32_t exist_mm_seq
;
595 bool new_origin
, exist_origin
;
596 struct bgp_path_info
*bpi_ultimate
;
597 struct peer
*peer_new
, *peer_exist
;
603 *reason
= bgp_path_selection_none
;
605 zlog_debug("%s: new is NULL", pfx_buf
);
610 bpi_ultimate
= bgp_get_imported_bpi_ultimate(new);
611 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, new_buf
,
616 *reason
= bgp_path_selection_first
;
618 zlog_debug("%s(%s): %s is the initial bestpath",
619 pfx_buf
, bgp
->name_pretty
, new_buf
);
624 bpi_ultimate
= bgp_get_imported_bpi_ultimate(exist
);
625 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, exist_buf
,
627 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
628 pfx_buf
, bgp
->name_pretty
, new_buf
, new->flags
,
629 exist_buf
, exist
->flags
);
633 existattr
= exist
->attr
;
635 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
636 * Capability" to a neighbor MUST perform the following upon receiving
637 * a route from that neighbor with the "LLGR_STALE" community, or upon
638 * attaching the "LLGR_STALE" community itself per Section 4.2:
640 * Treat the route as the least-preferred in route selection (see
641 * below). See the Risks of Depreferencing Routes section (Section 5.2)
642 * for a discussion of potential risks inherent in doing this.
644 if (bgp_attr_get_community(newattr
) &&
645 community_include(bgp_attr_get_community(newattr
),
646 COMMUNITY_LLGR_STALE
)) {
649 "%s: %s wins over %s due to LLGR_STALE community",
650 pfx_buf
, new_buf
, exist_buf
);
654 if (bgp_attr_get_community(existattr
) &&
655 community_include(bgp_attr_get_community(existattr
),
656 COMMUNITY_LLGR_STALE
)) {
659 "%s: %s loses to %s due to LLGR_STALE community",
660 pfx_buf
, new_buf
, exist_buf
);
664 new_p
= bgp_dest_get_prefix(new->net
);
666 /* For EVPN routes, we cannot just go by local vs remote, we have to
667 * look at the MAC mobility sequence number, if present.
669 if ((safi
== SAFI_EVPN
)
670 && (new_p
->u
.prefix_evpn
.route_type
== BGP_EVPN_MAC_IP_ROUTE
)) {
671 /* This is an error condition described in RFC 7432 Section
673 * states that in this scenario "the PE MUST alert the operator"
675 * does not state what other action to take. In order to provide
677 * consistency in this scenario we are going to prefer the path
681 if (newattr
->sticky
!= existattr
->sticky
) {
683 prefix2str(new_p
, pfx_buf
,
685 * PREFIX2STR_BUFFER
);
686 bgp_path_info_path_with_addpath_rx_str(
687 new, new_buf
, sizeof(new_buf
));
688 bgp_path_info_path_with_addpath_rx_str(
689 exist
, exist_buf
, sizeof(exist_buf
));
692 if (newattr
->sticky
&& !existattr
->sticky
) {
693 *reason
= bgp_path_selection_evpn_sticky_mac
;
696 "%s: %s wins over %s due to sticky MAC flag",
697 pfx_buf
, new_buf
, exist_buf
);
701 if (!newattr
->sticky
&& existattr
->sticky
) {
702 *reason
= bgp_path_selection_evpn_sticky_mac
;
705 "%s: %s loses to %s due to sticky MAC flag",
706 pfx_buf
, new_buf
, exist_buf
);
711 new_esi
= bgp_evpn_attr_get_esi(newattr
);
712 exist_esi
= bgp_evpn_attr_get_esi(existattr
);
713 if (bgp_evpn_is_esi_valid(new_esi
) &&
714 !memcmp(new_esi
, exist_esi
, sizeof(esi_t
))) {
720 /* If both paths have the same non-zero ES and
721 * one path is local it wins.
722 * PS: Note the local path wins even if the remote
723 * has the higher MM seq. The local path's
724 * MM seq will be fixed up to match the highest
725 * rem seq, subsequently.
728 char esi_buf
[ESI_STR_LEN
];
730 if (bgp_evpn_is_path_local(bgp
, new)) {
731 *reason
= bgp_path_selection_evpn_local_path
;
734 "%s: %s wins over %s as ES %s is same and local",
735 pfx_buf
, new_buf
, exist_buf
,
736 esi_to_str(new_esi
, esi_buf
,
740 if (bgp_evpn_is_path_local(bgp
, exist
)) {
741 *reason
= bgp_path_selection_evpn_local_path
;
744 "%s: %s loses to %s as ES %s is same and local",
745 pfx_buf
, new_buf
, exist_buf
,
746 esi_to_str(new_esi
, esi_buf
,
752 new_mm_seq
= mac_mobility_seqnum(newattr
);
753 exist_mm_seq
= mac_mobility_seqnum(existattr
);
755 if (new_mm_seq
> exist_mm_seq
) {
756 *reason
= bgp_path_selection_evpn_seq
;
759 "%s: %s wins over %s due to MM seq %u > %u",
760 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
765 if (new_mm_seq
< exist_mm_seq
) {
766 *reason
= bgp_path_selection_evpn_seq
;
769 "%s: %s loses to %s due to MM seq %u < %u",
770 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
775 /* if the sequence numbers and ESI are the same and one path
776 * is non-proxy it wins (over proxy)
778 new_proxy
= bgp_evpn_attr_is_proxy(newattr
);
779 old_proxy
= bgp_evpn_attr_is_proxy(existattr
);
780 if (same_esi
&& bgp_evpn_attr_is_local_es(newattr
) &&
781 old_proxy
!= new_proxy
) {
783 *reason
= bgp_path_selection_evpn_non_proxy
;
786 "%s: %s wins over %s, same seq/es and non-proxy",
787 pfx_buf
, new_buf
, exist_buf
);
791 *reason
= bgp_path_selection_evpn_non_proxy
;
794 "%s: %s loses to %s, same seq/es and non-proxy",
795 pfx_buf
, new_buf
, exist_buf
);
800 * if sequence numbers are the same path with the lowest IP
803 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
805 *reason
= bgp_path_selection_evpn_lower_ip
;
808 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
809 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
810 &new->attr
->nexthop
);
814 *reason
= bgp_path_selection_evpn_lower_ip
;
817 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
818 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
819 &new->attr
->nexthop
);
824 /* 1. Weight check. */
825 new_weight
= newattr
->weight
;
826 exist_weight
= existattr
->weight
;
828 if (new_weight
> exist_weight
) {
829 *reason
= bgp_path_selection_weight
;
831 zlog_debug("%s: %s wins over %s due to weight %d > %d",
832 pfx_buf
, new_buf
, exist_buf
, new_weight
,
837 if (new_weight
< exist_weight
) {
838 *reason
= bgp_path_selection_weight
;
840 zlog_debug("%s: %s loses to %s due to weight %d < %d",
841 pfx_buf
, new_buf
, exist_buf
, new_weight
,
846 /* 2. Local preference check. */
847 new_pref
= exist_pref
= bgp
->default_local_pref
;
849 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
850 new_pref
= newattr
->local_pref
;
851 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
852 exist_pref
= existattr
->local_pref
;
854 if (new_pref
> exist_pref
) {
855 *reason
= bgp_path_selection_local_pref
;
858 "%s: %s wins over %s due to localpref %d > %d",
859 pfx_buf
, new_buf
, exist_buf
, new_pref
,
864 if (new_pref
< exist_pref
) {
865 *reason
= bgp_path_selection_local_pref
;
868 "%s: %s loses to %s due to localpref %d < %d",
869 pfx_buf
, new_buf
, exist_buf
, new_pref
,
874 /* If a BGP speaker supports ACCEPT_OWN and is configured for the
875 * extensions defined in this document, the following step is inserted
876 * after the LOCAL_PREF comparison step in the BGP decision process:
877 * When comparing a pair of routes for a BGP destination, the
878 * route with the ACCEPT_OWN community attached is preferred over
879 * the route that does not have the community.
880 * This extra step MUST only be invoked during the best path selection
881 * process of VPN-IP routes.
883 if (safi
== SAFI_MPLS_VPN
&&
884 (CHECK_FLAG(new->peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
) ||
885 CHECK_FLAG(exist
->peer
->af_flags
[afi
][safi
],
886 PEER_FLAG_ACCEPT_OWN
))) {
887 bool new_accept_own
= false;
888 bool exist_accept_own
= false;
889 uint32_t accept_own
= COMMUNITY_ACCEPT_OWN
;
891 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))
892 new_accept_own
= community_include(
893 bgp_attr_get_community(newattr
), accept_own
);
894 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))
895 exist_accept_own
= community_include(
896 bgp_attr_get_community(existattr
), accept_own
);
898 if (new_accept_own
&& !exist_accept_own
) {
899 *reason
= bgp_path_selection_accept_own
;
902 "%s: %s wins over %s due to accept-own",
903 pfx_buf
, new_buf
, exist_buf
);
907 if (!new_accept_own
&& exist_accept_own
) {
908 *reason
= bgp_path_selection_accept_own
;
911 "%s: %s loses to %s due to accept-own",
912 pfx_buf
, new_buf
, exist_buf
);
917 /* Tie-breaker - AIGP (Metric TLV) attribute */
918 if (CHECK_FLAG(newattr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) &&
919 CHECK_FLAG(existattr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) &&
920 CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_AIGP
)) {
921 uint64_t new_aigp
= bgp_attr_get_aigp_metric(newattr
);
922 uint64_t exist_aigp
= bgp_attr_get_aigp_metric(existattr
);
924 if (new_aigp
< exist_aigp
) {
925 *reason
= bgp_path_selection_aigp
;
928 "%s: %s wins over %s due to AIGP %" PRIu64
930 pfx_buf
, new_buf
, exist_buf
, new_aigp
,
935 if (new_aigp
> exist_aigp
) {
936 *reason
= bgp_path_selection_aigp
;
939 "%s: %s loses to %s due to AIGP %" PRIu64
941 pfx_buf
, new_buf
, exist_buf
, new_aigp
,
947 /* 3. Local route check. We prefer:
949 * - BGP_ROUTE_AGGREGATE
950 * - BGP_ROUTE_REDISTRIBUTE
952 new_origin
= !(new->sub_type
== BGP_ROUTE_NORMAL
||
953 new->sub_type
== BGP_ROUTE_IMPORTED
);
954 exist_origin
= !(exist
->sub_type
== BGP_ROUTE_NORMAL
||
955 exist
->sub_type
== BGP_ROUTE_IMPORTED
);
957 if (new_origin
&& !exist_origin
) {
958 *reason
= bgp_path_selection_local_route
;
961 "%s: %s wins over %s due to preferred BGP_ROUTE type",
962 pfx_buf
, new_buf
, exist_buf
);
966 if (!new_origin
&& exist_origin
) {
967 *reason
= bgp_path_selection_local_route
;
970 "%s: %s loses to %s due to preferred BGP_ROUTE type",
971 pfx_buf
, new_buf
, exist_buf
);
975 /* Here if these are imported routes then get ultimate pi for
978 new = bgp_get_imported_bpi_ultimate(new);
979 exist
= bgp_get_imported_bpi_ultimate(exist
);
981 existattr
= exist
->attr
;
983 /* 4. AS path length check. */
984 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
985 int exist_hops
= aspath_count_hops(existattr
->aspath
);
986 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
988 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
991 aspath_hops
= aspath_count_hops(newattr
->aspath
);
992 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
994 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
995 *reason
= bgp_path_selection_confed_as_path
;
998 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
999 pfx_buf
, new_buf
, exist_buf
,
1001 (exist_hops
+ exist_confeds
));
1005 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
1006 *reason
= bgp_path_selection_confed_as_path
;
1009 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
1010 pfx_buf
, new_buf
, exist_buf
,
1012 (exist_hops
+ exist_confeds
));
1016 int newhops
= aspath_count_hops(newattr
->aspath
);
1018 if (newhops
< exist_hops
) {
1019 *reason
= bgp_path_selection_as_path
;
1022 "%s: %s wins over %s due to aspath hopcount %d < %d",
1023 pfx_buf
, new_buf
, exist_buf
,
1024 newhops
, exist_hops
);
1028 if (newhops
> exist_hops
) {
1029 *reason
= bgp_path_selection_as_path
;
1032 "%s: %s loses to %s due to aspath hopcount %d > %d",
1033 pfx_buf
, new_buf
, exist_buf
,
1034 newhops
, exist_hops
);
1040 /* 5. Origin check. */
1041 if (newattr
->origin
< existattr
->origin
) {
1042 *reason
= bgp_path_selection_origin
;
1044 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
1045 pfx_buf
, new_buf
, exist_buf
,
1046 bgp_origin_long_str
[newattr
->origin
],
1047 bgp_origin_long_str
[existattr
->origin
]);
1051 if (newattr
->origin
> existattr
->origin
) {
1052 *reason
= bgp_path_selection_origin
;
1054 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
1055 pfx_buf
, new_buf
, exist_buf
,
1056 bgp_origin_long_str
[newattr
->origin
],
1057 bgp_origin_long_str
[existattr
->origin
]);
1062 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
1063 && aspath_count_hops(existattr
->aspath
) == 0);
1064 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
1065 && aspath_count_confeds(existattr
->aspath
) > 0
1066 && aspath_count_hops(newattr
->aspath
) == 0
1067 && aspath_count_hops(existattr
->aspath
) == 0);
1069 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
1070 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
1071 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
1072 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
1073 || internal_as_route
) {
1074 new_med
= bgp_med_value(new->attr
, bgp
);
1075 exist_med
= bgp_med_value(exist
->attr
, bgp
);
1077 if (new_med
< exist_med
) {
1078 *reason
= bgp_path_selection_med
;
1081 "%s: %s wins over %s due to MED %d < %d",
1082 pfx_buf
, new_buf
, exist_buf
, new_med
,
1087 if (new_med
> exist_med
) {
1088 *reason
= bgp_path_selection_med
;
1091 "%s: %s loses to %s due to MED %d > %d",
1092 pfx_buf
, new_buf
, exist_buf
, new_med
,
1098 if (exist
->sub_type
== BGP_ROUTE_IMPORTED
) {
1099 bpi_ultimate
= bgp_get_imported_bpi_ultimate(exist
);
1100 peer_exist
= bpi_ultimate
->peer
;
1102 peer_exist
= exist
->peer
;
1104 if (new->sub_type
== BGP_ROUTE_IMPORTED
) {
1105 bpi_ultimate
= bgp_get_imported_bpi_ultimate(new);
1106 peer_new
= bpi_ultimate
->peer
;
1108 peer_new
= new->peer
;
1110 /* 7. Peer type check. */
1111 new_sort
= peer_new
->sort
;
1112 exist_sort
= peer_exist
->sort
;
1114 if (new_sort
== BGP_PEER_EBGP
1115 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
1116 *reason
= bgp_path_selection_peer
;
1119 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1120 pfx_buf
, new_buf
, exist_buf
);
1121 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1126 if (exist_sort
== BGP_PEER_EBGP
1127 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
1128 *reason
= bgp_path_selection_peer
;
1131 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1132 pfx_buf
, new_buf
, exist_buf
);
1133 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1138 /* 8. IGP metric check. */
1142 newm
= new->extra
->igpmetric
;
1144 existm
= exist
->extra
->igpmetric
;
1146 if (newm
< existm
) {
1147 if (debug
&& peer_sort_ret
< 0)
1149 "%s: %s wins over %s due to IGP metric %u < %u",
1150 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1154 if (newm
> existm
) {
1155 if (debug
&& peer_sort_ret
< 0)
1157 "%s: %s loses to %s due to IGP metric %u > %u",
1158 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1162 /* 9. Same IGP metric. Compare the cluster list length as
1163 representative of IGP hops metric. Rewrite the metric value
1164 pair (newm, existm) with the cluster list length. Prefer the
1165 path with smaller cluster list length. */
1166 if (newm
== existm
) {
1167 if (peer_sort_lookup(peer_new
) == BGP_PEER_IBGP
&&
1168 peer_sort_lookup(peer_exist
) == BGP_PEER_IBGP
&&
1169 (mpath_cfg
== NULL
|| mpath_cfg
->same_clusterlen
)) {
1170 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1171 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1173 if (newm
< existm
) {
1174 if (debug
&& peer_sort_ret
< 0)
1176 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
1177 pfx_buf
, new_buf
, exist_buf
,
1182 if (newm
> existm
) {
1183 if (debug
&& peer_sort_ret
< 0)
1185 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
1186 pfx_buf
, new_buf
, exist_buf
,
1193 /* 10. confed-external vs. confed-internal */
1194 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1195 if (new_sort
== BGP_PEER_CONFED
1196 && exist_sort
== BGP_PEER_IBGP
) {
1197 *reason
= bgp_path_selection_confed
;
1200 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1201 pfx_buf
, new_buf
, exist_buf
);
1202 if (!CHECK_FLAG(bgp
->flags
,
1203 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1208 if (exist_sort
== BGP_PEER_CONFED
1209 && new_sort
== BGP_PEER_IBGP
) {
1210 *reason
= bgp_path_selection_confed
;
1213 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1214 pfx_buf
, new_buf
, exist_buf
);
1215 if (!CHECK_FLAG(bgp
->flags
,
1216 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1222 /* 11. Maximum path check. */
1223 if (newm
== existm
) {
1224 /* If one path has a label but the other does not, do not treat
1225 * them as equals for multipath
1232 newl
= new->extra
->num_labels
;
1234 existl
= exist
->extra
->num_labels
;
1235 if (((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0])) !=
1237 bgp_is_valid_label(&exist
->extra
->label
[0]))) ||
1241 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1242 pfx_buf
, new_buf
, exist_buf
);
1243 } else if (CHECK_FLAG(bgp
->flags
,
1244 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
1247 * For the two paths, all comparison steps till IGP
1249 * have succeeded - including AS_PATH hop count. Since
1251 * bestpath as-path multipath-relax' knob is on, we
1253 * an exact match of AS_PATH. Thus, mark the paths are
1255 * That will trigger both these paths to get into the
1263 "%s: %s and %s are equal via multipath-relax",
1264 pfx_buf
, new_buf
, exist_buf
);
1265 } else if (peer_new
->sort
== BGP_PEER_IBGP
) {
1266 if (aspath_cmp(new->attr
->aspath
,
1267 exist
->attr
->aspath
)) {
1272 "%s: %s and %s are equal via matching aspaths",
1273 pfx_buf
, new_buf
, exist_buf
);
1275 } else if (peer_new
->as
== peer_exist
->as
) {
1280 "%s: %s and %s are equal via same remote-as",
1281 pfx_buf
, new_buf
, exist_buf
);
1285 * TODO: If unequal cost ibgp multipath is enabled we can
1286 * mark the paths as equal here instead of returning
1289 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1290 * if either step 7 or 10 (peer type checks) yielded a winner,
1291 * that result was returned immediately. Returning from step 10
1292 * ignored the return value computed in steps 8 and 9 (IGP
1293 * metric checks). In order to preserve that behavior, if
1294 * peer_sort_ret is set, return that rather than igp_metric_ret.
1296 ret
= peer_sort_ret
;
1297 if (peer_sort_ret
< 0) {
1298 ret
= igp_metric_ret
;
1302 "%s: %s wins over %s after IGP metric comparison",
1303 pfx_buf
, new_buf
, exist_buf
);
1306 "%s: %s loses to %s after IGP metric comparison",
1307 pfx_buf
, new_buf
, exist_buf
);
1309 *reason
= bgp_path_selection_igp_metric
;
1315 * At this point, the decision whether to set *paths_eq = 1 has been
1316 * completed. If we deferred returning because of bestpath peer-type
1317 * relax configuration, return now.
1319 if (peer_sort_ret
>= 0)
1320 return peer_sort_ret
;
1322 /* 12. If both paths are external, prefer the path that was received
1323 first (the oldest one). This step minimizes route-flap, since a
1324 newer path won't displace an older one, even if it was the
1325 preferred route based on the additional decision criteria below. */
1326 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1327 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1328 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1329 *reason
= bgp_path_selection_older
;
1332 "%s: %s wins over %s due to oldest external",
1333 pfx_buf
, new_buf
, exist_buf
);
1337 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1338 *reason
= bgp_path_selection_older
;
1341 "%s: %s loses to %s due to oldest external",
1342 pfx_buf
, new_buf
, exist_buf
);
1347 /* 13. Router-ID comparison. */
1348 /* If one of the paths is "stale", the corresponding peer router-id will
1349 * be 0 and would always win over the other path. If originator id is
1350 * used for the comparison, it will decide which path is better.
1352 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1353 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1355 new_id
.s_addr
= peer_new
->remote_id
.s_addr
;
1356 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1357 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1359 exist_id
.s_addr
= peer_exist
->remote_id
.s_addr
;
1361 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1362 *reason
= bgp_path_selection_router_id
;
1365 "%s: %s wins over %s due to Router-ID comparison",
1366 pfx_buf
, new_buf
, exist_buf
);
1370 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1371 *reason
= bgp_path_selection_router_id
;
1374 "%s: %s loses to %s due to Router-ID comparison",
1375 pfx_buf
, new_buf
, exist_buf
);
1379 /* 14. Cluster length comparison. */
1380 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1381 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1383 if (new_cluster
< exist_cluster
) {
1384 *reason
= bgp_path_selection_cluster_length
;
1387 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1388 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1393 if (new_cluster
> exist_cluster
) {
1394 *reason
= bgp_path_selection_cluster_length
;
1397 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1398 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1403 /* 15. Neighbor address comparison. */
1404 /* Do this only if neither path is "stale" as stale paths do not have
1405 * valid peer information (as the connection may or may not be up).
1407 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1408 *reason
= bgp_path_selection_stale
;
1411 "%s: %s wins over %s due to latter path being STALE",
1412 pfx_buf
, new_buf
, exist_buf
);
1416 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1417 *reason
= bgp_path_selection_stale
;
1420 "%s: %s loses to %s due to former path being STALE",
1421 pfx_buf
, new_buf
, exist_buf
);
1425 /* locally configured routes to advertise do not have su_remote */
1426 if (peer_new
->su_remote
== NULL
) {
1427 *reason
= bgp_path_selection_local_configured
;
1431 if (peer_exist
->su_remote
== NULL
) {
1432 *reason
= bgp_path_selection_local_configured
;
1436 ret
= sockunion_cmp(peer_new
->su_remote
, peer_exist
->su_remote
);
1439 *reason
= bgp_path_selection_neighbor_ip
;
1442 "%s: %s loses to %s due to Neighor IP comparison",
1443 pfx_buf
, new_buf
, exist_buf
);
1448 *reason
= bgp_path_selection_neighbor_ip
;
1451 "%s: %s wins over %s due to Neighor IP comparison",
1452 pfx_buf
, new_buf
, exist_buf
);
1456 *reason
= bgp_path_selection_default
;
1458 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1459 pfx_buf
, new_buf
, exist_buf
);
1465 int bgp_evpn_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
1466 struct bgp_path_info
*exist
, int *paths_eq
)
1468 enum bgp_path_selection_reason reason
;
1469 char pfx_buf
[PREFIX2STR_BUFFER
];
1471 return bgp_path_info_cmp(bgp
, new, exist
, paths_eq
, NULL
, 0, pfx_buf
,
1472 AFI_L2VPN
, SAFI_EVPN
, &reason
);
1475 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1476 * is preferred, or 0 if they are the same (usually will only occur if
1477 * multipath is enabled
1478 * This version is compatible with */
1479 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1480 struct bgp_path_info
*exist
, char *pfx_buf
,
1481 afi_t afi
, safi_t safi
,
1482 enum bgp_path_selection_reason
*reason
)
1486 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1500 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1501 const struct prefix
*p
,
1502 struct attr
*attr
, afi_t afi
,
1505 struct bgp_filter
*filter
;
1506 enum filter_type ret
= FILTER_PERMIT
;
1508 filter
= &peer
->filter
[afi
][safi
];
1510 #define FILTER_EXIST_WARN(F, f, filter) \
1511 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1512 zlog_debug("%s: Could not find configured input %s-list %s!", \
1513 peer->host, #f, F##_IN_NAME(filter));
1515 if (DISTRIBUTE_IN_NAME(filter
)) {
1516 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1518 if (access_list_apply(DISTRIBUTE_IN(filter
), p
)
1525 if (PREFIX_LIST_IN_NAME(filter
)) {
1526 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1528 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
)
1535 if (FILTER_LIST_IN_NAME(filter
)) {
1536 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1538 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1539 == AS_FILTER_DENY
) {
1546 if (frrtrace_enabled(frr_bgp
, input_filter
)) {
1547 char pfxprint
[PREFIX2STR_BUFFER
];
1549 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1550 frrtrace(5, frr_bgp
, input_filter
, peer
, pfxprint
, afi
, safi
,
1551 ret
== FILTER_PERMIT
? "permit" : "deny");
1555 #undef FILTER_EXIST_WARN
1558 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1559 const struct prefix
*p
,
1560 struct attr
*attr
, afi_t afi
,
1563 struct bgp_filter
*filter
;
1564 enum filter_type ret
= FILTER_PERMIT
;
1566 filter
= &peer
->filter
[afi
][safi
];
1568 #define FILTER_EXIST_WARN(F, f, filter) \
1569 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1570 zlog_debug("%s: Could not find configured output %s-list %s!", \
1571 peer->host, #f, F##_OUT_NAME(filter));
1573 if (DISTRIBUTE_OUT_NAME(filter
)) {
1574 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1576 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
)
1583 if (PREFIX_LIST_OUT_NAME(filter
)) {
1584 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1586 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1593 if (FILTER_LIST_OUT_NAME(filter
)) {
1594 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1596 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1597 == AS_FILTER_DENY
) {
1603 if (frrtrace_enabled(frr_bgp
, output_filter
)) {
1604 char pfxprint
[PREFIX2STR_BUFFER
];
1606 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1607 frrtrace(5, frr_bgp
, output_filter
, peer
, pfxprint
, afi
, safi
,
1608 ret
== FILTER_PERMIT
? "permit" : "deny");
1613 #undef FILTER_EXIST_WARN
1616 /* If community attribute includes no_export then return 1. */
1617 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1619 if (bgp_attr_get_community(attr
)) {
1620 /* NO_ADVERTISE check. */
1621 if (community_include(bgp_attr_get_community(attr
),
1622 COMMUNITY_NO_ADVERTISE
))
1625 /* NO_EXPORT check. */
1626 if (peer
->sort
== BGP_PEER_EBGP
&&
1627 community_include(bgp_attr_get_community(attr
),
1628 COMMUNITY_NO_EXPORT
))
1631 /* NO_EXPORT_SUBCONFED check. */
1632 if (peer
->sort
== BGP_PEER_EBGP
1633 || peer
->sort
== BGP_PEER_CONFED
)
1634 if (community_include(bgp_attr_get_community(attr
),
1635 COMMUNITY_NO_EXPORT_SUBCONFED
))
1641 /* Route reflection loop check. */
1642 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1644 struct in_addr cluster_id
;
1645 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1648 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1649 cluster_id
= peer
->bgp
->cluster_id
;
1651 cluster_id
= peer
->bgp
->router_id
;
1653 if (cluster_loop_check(cluster
, cluster_id
))
1659 static bool bgp_otc_filter(struct peer
*peer
, struct attr
*attr
)
1661 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1662 if (peer
->local_role
== ROLE_PROVIDER
||
1663 peer
->local_role
== ROLE_RS_SERVER
)
1665 if (peer
->local_role
== ROLE_PEER
&& attr
->otc
!= peer
->as
)
1669 if (peer
->local_role
== ROLE_CUSTOMER
||
1670 peer
->local_role
== ROLE_PEER
||
1671 peer
->local_role
== ROLE_RS_CLIENT
) {
1672 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1673 attr
->otc
= peer
->as
;
1678 static bool bgp_otc_egress(struct peer
*peer
, struct attr
*attr
)
1680 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1681 if (peer
->local_role
== ROLE_CUSTOMER
||
1682 peer
->local_role
== ROLE_RS_CLIENT
||
1683 peer
->local_role
== ROLE_PEER
)
1687 if (peer
->local_role
== ROLE_PROVIDER
||
1688 peer
->local_role
== ROLE_PEER
||
1689 peer
->local_role
== ROLE_RS_SERVER
) {
1690 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1691 attr
->otc
= peer
->bgp
->as
;
1696 static bool bgp_check_role_applicability(afi_t afi
, safi_t safi
)
1698 return ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_UNICAST
);
1701 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1702 struct attr
*attr
, afi_t afi
, safi_t safi
,
1703 const char *rmap_name
, mpls_label_t
*label
,
1704 uint32_t num_labels
, struct bgp_dest
*dest
)
1706 struct bgp_filter
*filter
;
1707 struct bgp_path_info rmap_path
= { 0 };
1708 struct bgp_path_info_extra extra
= { 0 };
1709 route_map_result_t ret
;
1710 struct route_map
*rmap
= NULL
;
1712 filter
= &peer
->filter
[afi
][safi
];
1714 /* Apply default weight value. */
1715 if (peer
->weight
[afi
][safi
])
1716 attr
->weight
= peer
->weight
[afi
][safi
];
1719 rmap
= route_map_lookup_by_name(rmap_name
);
1724 if (ROUTE_MAP_IN_NAME(filter
)) {
1725 rmap
= ROUTE_MAP_IN(filter
);
1732 /* Route map apply. */
1734 memset(&rmap_path
, 0, sizeof(rmap_path
));
1735 /* Duplicate current value to new structure for modification. */
1736 rmap_path
.peer
= peer
;
1737 rmap_path
.attr
= attr
;
1738 rmap_path
.extra
= &extra
;
1739 rmap_path
.net
= dest
;
1741 extra
.num_labels
= num_labels
;
1742 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1743 memcpy(extra
.label
, label
,
1744 num_labels
* sizeof(mpls_label_t
));
1746 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1748 /* Apply BGP route map to the attribute. */
1749 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1751 peer
->rmap_type
= 0;
1753 if (ret
== RMAP_DENYMATCH
)
1759 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1760 struct attr
*attr
, afi_t afi
, safi_t safi
,
1761 const char *rmap_name
)
1763 struct bgp_path_info rmap_path
;
1764 route_map_result_t ret
;
1765 struct route_map
*rmap
= NULL
;
1769 * So if we get to this point and have no rmap_name
1770 * we want to just show the output as it currently
1776 /* Apply default weight value. */
1777 if (peer
->weight
[afi
][safi
])
1778 attr
->weight
= peer
->weight
[afi
][safi
];
1780 rmap
= route_map_lookup_by_name(rmap_name
);
1783 * If we have a route map name and we do not find
1784 * the routemap that means we have an implicit
1790 memset(&rmap_path
, 0, sizeof(rmap_path
));
1791 /* Route map apply. */
1792 /* Duplicate current value to new structure for modification. */
1793 rmap_path
.peer
= peer
;
1794 rmap_path
.attr
= attr
;
1796 rmap_type
= peer
->rmap_type
;
1797 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1799 /* Apply BGP route map to the attribute. */
1800 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1802 peer
->rmap_type
= rmap_type
;
1804 if (ret
== RMAP_DENYMATCH
)
1806 * caller has multiple error paths with bgp_attr_flush()
1813 /* If this is an EBGP peer with remove-private-AS */
1814 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1815 struct peer
*peer
, struct attr
*attr
)
1817 if (peer
->sort
== BGP_PEER_EBGP
1818 && (peer_af_flag_check(peer
, afi
, safi
,
1819 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1820 || peer_af_flag_check(peer
, afi
, safi
,
1821 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1822 || peer_af_flag_check(peer
, afi
, safi
,
1823 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1824 || peer_af_flag_check(peer
, afi
, safi
,
1825 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1826 // Take action on the entire aspath
1827 if (peer_af_flag_check(peer
, afi
, safi
,
1828 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1829 || peer_af_flag_check(peer
, afi
, safi
,
1830 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1831 if (peer_af_flag_check(
1833 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1834 attr
->aspath
= aspath_replace_private_asns(
1835 attr
->aspath
, bgp
->as
, peer
->as
);
1838 * Even if the aspath consists of just private ASNs we
1839 * need to walk the AS-Path to maintain all instances
1840 * of the peer's ASN to break possible loops.
1843 attr
->aspath
= aspath_remove_private_asns(
1844 attr
->aspath
, peer
->as
);
1847 // 'all' was not specified so the entire aspath must be private
1849 // for us to do anything
1850 else if (aspath_private_as_check(attr
->aspath
)) {
1851 if (peer_af_flag_check(
1853 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1854 attr
->aspath
= aspath_replace_private_asns(
1855 attr
->aspath
, bgp
->as
, peer
->as
);
1858 * Walk the aspath to retain any instances of
1861 attr
->aspath
= aspath_remove_private_asns(
1862 attr
->aspath
, peer
->as
);
1867 /* If this is an EBGP peer with as-override */
1868 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1869 struct peer
*peer
, struct attr
*attr
)
1871 struct aspath
*aspath
;
1873 if (peer
->sort
== BGP_PEER_EBGP
&&
1874 peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1875 if (attr
->aspath
->refcnt
)
1876 aspath
= aspath_dup(attr
->aspath
);
1878 aspath
= attr
->aspath
;
1880 attr
->aspath
= aspath_intern(
1881 aspath_replace_specific_asn(aspath
, peer
->as
, bgp
->as
));
1883 aspath_free(aspath
);
1887 void bgp_attr_add_llgr_community(struct attr
*attr
)
1889 struct community
*old
;
1890 struct community
*new;
1891 struct community
*merge
;
1892 struct community
*llgr
;
1894 old
= bgp_attr_get_community(attr
);
1895 llgr
= community_str2com("llgr-stale");
1900 merge
= community_merge(community_dup(old
), llgr
);
1902 if (old
->refcnt
== 0)
1903 community_free(&old
);
1905 new = community_uniq_sort(merge
);
1906 community_free(&merge
);
1908 new = community_dup(llgr
);
1911 community_free(&llgr
);
1913 bgp_attr_set_community(attr
, new);
1916 void bgp_attr_add_gshut_community(struct attr
*attr
)
1918 struct community
*old
;
1919 struct community
*new;
1920 struct community
*merge
;
1921 struct community
*gshut
;
1923 old
= bgp_attr_get_community(attr
);
1924 gshut
= community_str2com("graceful-shutdown");
1929 merge
= community_merge(community_dup(old
), gshut
);
1931 if (old
->refcnt
== 0)
1932 community_free(&old
);
1934 new = community_uniq_sort(merge
);
1935 community_free(&merge
);
1937 new = community_dup(gshut
);
1940 community_free(&gshut
);
1941 bgp_attr_set_community(attr
, new);
1943 /* When we add the graceful-shutdown community we must also
1944 * lower the local-preference */
1945 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1946 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1950 /* Notify BGP Conditional advertisement scanner process. */
1951 void bgp_notify_conditional_adv_scanner(struct update_subgroup
*subgrp
)
1953 struct peer
*peer
= SUBGRP_PEER(subgrp
);
1954 afi_t afi
= SUBGRP_AFI(subgrp
);
1955 safi_t safi
= SUBGRP_SAFI(subgrp
);
1956 struct bgp_filter
*filter
= &peer
->filter
[afi
][safi
];
1958 if (!ADVERTISE_MAP_NAME(filter
))
1961 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
))
1964 peer
->advmap_table_change
= true;
1968 void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1970 if (family
== AF_INET
) {
1971 attr
->nexthop
.s_addr
= INADDR_ANY
;
1972 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1974 if (family
== AF_INET6
)
1975 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1976 if (family
== AF_EVPN
)
1977 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1980 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
1981 struct update_subgroup
*subgrp
,
1982 const struct prefix
*p
, struct attr
*attr
,
1983 struct attr
*post_attr
)
1985 struct bgp_filter
*filter
;
1988 struct peer
*onlypeer
;
1990 struct attr
*piattr
;
1991 route_map_result_t ret
;
1996 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1997 bool nh_reset
= false;
2000 if (DISABLE_BGP_ANNOUNCE
)
2003 afi
= SUBGRP_AFI(subgrp
);
2004 safi
= SUBGRP_SAFI(subgrp
);
2005 peer
= SUBGRP_PEER(subgrp
);
2007 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
2008 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
2011 filter
= &peer
->filter
[afi
][safi
];
2012 bgp
= SUBGRP_INST(subgrp
);
2013 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
2016 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX_OUT
) &&
2017 peer
->pmax_out
[afi
][safi
] != 0 &&
2018 subgrp
->pscount
>= peer
->pmax_out
[afi
][safi
]) {
2019 if (BGP_DEBUG(update
, UPDATE_OUT
) ||
2020 BGP_DEBUG(update
, UPDATE_PREFIX
)) {
2021 zlog_debug("%s reached maximum prefix to be send (%u)",
2022 peer
->host
, peer
->pmax_out
[afi
][safi
]);
2027 #ifdef ENABLE_BGP_VNC
2028 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
2029 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
2030 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
2033 * direct and direct_ext type routes originate internally even
2034 * though they can have peer pointers that reference other
2037 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
2043 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
2044 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
2045 && (pi
->type
== ZEBRA_ROUTE_BGP
)
2046 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2048 /* Applies to routes leaked vpn->vrf and vrf->vpn */
2053 /* With addpath we may be asked to TX all kinds of paths so make sure
2055 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
2056 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
2057 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
2061 /* If this is not the bestpath then check to see if there is an enabled
2063 * feature that requires us to advertise it */
2064 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2065 if (!bgp_addpath_capable(pi
, peer
, afi
, safi
))
2068 /* Aggregate-address suppress check. */
2069 if (bgp_path_suppressed(pi
) && !UNSUPPRESS_MAP_NAME(filter
))
2073 * If we are doing VRF 2 VRF leaking via the import
2074 * statement, we want to prevent the route going
2075 * off box as that the RT and RD created are localy
2076 * significant and globaly useless.
2078 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
2079 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
2082 /* If it's labeled safi, make sure the route has a valid label. */
2083 if (safi
== SAFI_LABELED_UNICAST
) {
2084 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
2085 if (!bgp_is_valid_label(&label
)) {
2086 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2087 zlog_debug("u%" PRIu64
":s%" PRIu64
2088 " %pFX is filtered - no label (%p)",
2089 subgrp
->update_group
->id
, subgrp
->id
,
2095 /* Do not send back route to sender. */
2096 if (onlypeer
&& from
== onlypeer
) {
2100 /* Do not send the default route in the BGP table if the neighbor is
2101 * configured for default-originate */
2102 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2103 PEER_FLAG_DEFAULT_ORIGINATE
)) {
2104 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
2106 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
2110 /* Transparency check. */
2111 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
2112 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
2117 /* If community is not disabled check the no-export and local. */
2118 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
2119 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2120 zlog_debug("%s: community filter check fail for %pFX",
2125 /* If the attribute has originator-id and it is same as remote
2127 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2128 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
2129 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2131 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2136 /* ORF prefix-list filter check */
2137 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
2138 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
2139 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
2140 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
2141 if (peer
->orf_plist
[afi
][safi
]) {
2142 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
2144 if (bgp_debug_update(NULL
, p
,
2145 subgrp
->update_group
, 0))
2147 "%pBP [Update:SEND] %pFX is filtered via ORF",
2153 /* Output filter check. */
2154 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
2155 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2156 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer
,
2161 /* AS path loop check. */
2162 if (peer
->as_path_loop_detection
&&
2163 aspath_loop_check(piattr
->aspath
, peer
->as
)) {
2164 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2166 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2171 /* If we're a CONFED we need to loop check the CONFED ID too */
2172 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
2173 if (aspath_loop_check_confed(piattr
->aspath
, bgp
->confed_id
)) {
2174 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2176 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2177 peer
, bgp
->confed_id
);
2182 /* Route-Reflect check. */
2183 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2188 /* IBGP reflection check. */
2189 if (reflect
&& !samepeer_safe
) {
2190 /* A route from a Client peer. */
2191 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
2192 PEER_FLAG_REFLECTOR_CLIENT
)) {
2193 /* Reflect to all the Non-Client peers and also to the
2194 Client peers other than the originator. Originator
2196 is already done. So there is noting to do. */
2197 /* no bgp client-to-client reflection check. */
2198 if (CHECK_FLAG(bgp
->flags
,
2199 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
2200 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2201 PEER_FLAG_REFLECTOR_CLIENT
))
2204 /* A route from a Non-client peer. Reflect to all other
2206 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2207 PEER_FLAG_REFLECTOR_CLIENT
))
2212 /* For modify attribute, copy it to temporary structure.
2213 * post_attr comes from BGP conditional advertisements, where
2214 * attributes are already processed by advertise-map route-map,
2215 * and this needs to be saved instead of overwriting from the
2223 /* If local-preference is not set. */
2224 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
2225 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
2226 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2227 attr
->local_pref
= bgp
->default_local_pref
;
2230 /* If originator-id is not set and the route is to be reflected,
2231 set the originator id */
2233 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
2234 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
2235 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
2238 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2240 if (peer
->sort
== BGP_PEER_EBGP
2241 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
2242 if (from
!= bgp
->peer_self
&& !transparent
2243 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2244 PEER_FLAG_MED_UNCHANGED
))
2246 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
2249 /* Since the nexthop attribute can vary per peer, it is not explicitly
2251 * in announce check, only certain flags and length (or number of
2253 * -- for IPv6/MP_REACH) are set here in order to guide the update
2255 * code in setting the nexthop(s) on a per peer basis in
2257 * Typically, the source nexthop in the attribute is preserved but in
2259 * scenarios where we know it will always be overwritten, we reset the
2260 * nexthop to "0" in an attempt to achieve better Update packing. An
2261 * example of this is when a prefix from each of 2 IBGP peers needs to
2263 * announced to an EBGP peer (and they have the same attributes barring
2267 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
2269 #define NEXTHOP_IS_V6 \
2270 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2271 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2272 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2273 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2275 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2277 * the peer (group) is configured to receive link-local nexthop
2279 * and it is available in the prefix OR we're not reflecting the route,
2280 * link-local nexthop address is valid and
2281 * the peer (group) to whom we're going to announce is on a shared
2283 * and this is either a self-originated route or the peer is EBGP.
2284 * By checking if nexthop LL address is valid we are sure that
2285 * we do not announce LL address as `::`.
2287 if (NEXTHOP_IS_V6
) {
2288 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2289 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2290 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
2291 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
2292 || (!reflect
&& !transparent
2293 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
2294 && peer
->shared_network
2295 && (from
== bgp
->peer_self
2296 || peer
->sort
== BGP_PEER_EBGP
))) {
2297 if (safi
== SAFI_MPLS_VPN
)
2298 attr
->mp_nexthop_len
=
2299 BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
;
2301 attr
->mp_nexthop_len
=
2302 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2305 /* Clear off link-local nexthop in source, whenever it is not
2307 * ensure more prefixes share the same attribute for
2310 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2311 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
2312 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
2315 if (bgp_check_role_applicability(afi
, safi
) &&
2316 bgp_otc_egress(peer
, attr
))
2319 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
2320 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
2322 if (filter
->advmap
.update_type
== UPDATE_TYPE_WITHDRAW
&&
2323 filter
->advmap
.aname
&&
2324 route_map_lookup_by_name(filter
->advmap
.aname
)) {
2325 struct bgp_path_info rmap_path
= {0};
2326 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2327 struct attr dummy_attr
= *attr
;
2329 /* Fill temp path_info */
2330 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2331 pi
, peer
, &dummy_attr
);
2333 struct route_map
*amap
=
2334 route_map_lookup_by_name(filter
->advmap
.aname
);
2336 ret
= route_map_apply(amap
, p
, &rmap_path
);
2338 bgp_attr_flush(&dummy_attr
);
2341 * The conditional advertisement mode is Withdraw and this
2342 * prefix is a conditional prefix. Don't advertise it
2344 if (ret
== RMAP_PERMITMATCH
)
2348 /* Route map & unsuppress-map apply. */
2350 (ROUTE_MAP_OUT_NAME(filter
) || bgp_path_suppressed(pi
))) {
2351 struct bgp_path_info rmap_path
= {0};
2352 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2353 struct attr dummy_attr
= {0};
2355 /* Fill temp path_info */
2356 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2359 /* don't confuse inbound and outbound setting */
2360 RESET_FLAG(attr
->rmap_change_flags
);
2363 * The route reflector is not allowed to modify the attributes
2364 * of the reflected IBGP routes unless explicitly allowed.
2366 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2367 && !CHECK_FLAG(bgp
->flags
,
2368 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
2370 rmap_path
.attr
= &dummy_attr
;
2373 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
2375 if (bgp_path_suppressed(pi
))
2376 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
2379 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
2382 bgp_attr_flush(&dummy_attr
);
2383 peer
->rmap_type
= 0;
2385 if (ret
== RMAP_DENYMATCH
) {
2386 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2388 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2390 bgp_path_suppressed(pi
)
2391 ? UNSUPPRESS_MAP_NAME(filter
)
2392 : ROUTE_MAP_OUT_NAME(filter
));
2393 bgp_attr_flush(rmap_path
.attr
);
2398 /* RFC 8212 to prevent route leaks.
2399 * This specification intends to improve this situation by requiring the
2400 * explicit configuration of both BGP Import and Export Policies for any
2401 * External BGP (EBGP) session such as customers, peers, or
2402 * confederation boundaries for all enabled address families. Through
2403 * codification of the aforementioned requirement, operators will
2404 * benefit from consistent behavior across different BGP
2407 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2408 if (!bgp_outbound_policy_exists(peer
, filter
)) {
2409 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
2410 NULL
) > FIFTEENMINUTE2USEC
||
2411 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
2413 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2414 monotime(&bgp
->ebgprequirespolicywarning
);
2419 /* draft-ietf-idr-deprecate-as-set-confed-set
2420 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2421 * Eventually, This document (if approved) updates RFC 4271
2422 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2423 * and obsoletes RFC 6472.
2425 if (peer
->bgp
->reject_as_sets
)
2426 if (aspath_check_as_sets(attr
->aspath
))
2429 /* If neighbor soo is configured, then check if the route has
2430 * SoO extended community and validate against the configured
2431 * one. If they match, do not announce, to prevent routing
2434 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) &&
2435 peer
->soo
[afi
][safi
]) {
2436 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
2437 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
2439 if ((ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS
,
2440 ECOMMUNITY_SITE_ORIGIN
) ||
2441 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS4
,
2442 ECOMMUNITY_SITE_ORIGIN
) ||
2443 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_IP
,
2444 ECOMMUNITY_SITE_ORIGIN
)) &&
2445 ecommunity_include(ecomm
, ecomm_soo
)) {
2446 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2448 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2449 peer
, p
, ecommunity_str(ecomm_soo
));
2454 /* Codification of AS 0 Processing */
2455 if (aspath_check_as_zero(attr
->aspath
))
2458 if (bgp_in_graceful_shutdown(bgp
)) {
2459 if (peer
->sort
== BGP_PEER_IBGP
2460 || peer
->sort
== BGP_PEER_CONFED
) {
2461 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2462 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2464 bgp_attr_add_gshut_community(attr
);
2468 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2469 * Capability" to a neighbor MUST perform the following upon receiving
2470 * a route from that neighbor with the "LLGR_STALE" community, or upon
2471 * attaching the "LLGR_STALE" community itself per Section 4.2:
2473 * The route SHOULD NOT be advertised to any neighbor from which the
2474 * Long-lived Graceful Restart Capability has not been received.
2476 if (bgp_attr_get_community(attr
) &&
2477 community_include(bgp_attr_get_community(attr
),
2478 COMMUNITY_LLGR_STALE
) &&
2479 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_RCV
) &&
2480 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_ADV
))
2483 /* After route-map has been applied, we check to see if the nexthop to
2484 * be carried in the attribute (that is used for the announcement) can
2485 * be cleared off or not. We do this in all cases where we would be
2486 * setting the nexthop to "ourselves". For IPv6, we only need to
2488 * the global nexthop here; the link-local nexthop would have been
2490 * already, and if not, it is required by the update formation code.
2491 * Also see earlier comments in this function.
2494 * If route-map has performed some operation on the nexthop or the peer
2495 * configuration says to pass it unchanged, we cannot reset the nexthop
2496 * here, so only attempt to do it if these aren't true. Note that the
2497 * route-map handler itself might have cleared the nexthop, if for
2499 * it is configured as 'peer-address'.
2501 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2502 piattr
->rmap_change_flags
)
2504 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2505 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2506 /* We can reset the nexthop, if setting (or forcing) it to
2508 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2509 PEER_FLAG_NEXTHOP_SELF
)
2510 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2511 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2513 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2514 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2515 subgroup_announce_reset_nhop(
2516 (peer_cap_enhe(peer
, afi
, safi
)
2522 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2523 /* Can also reset the nexthop if announcing to EBGP, but
2525 * no peer in the subgroup is on a shared subnet.
2526 * Note: 3rd party nexthop currently implemented for
2529 if ((p
->family
== AF_INET
) &&
2530 (!bgp_subgrp_multiaccess_check_v4(
2533 subgroup_announce_reset_nhop(
2534 (peer_cap_enhe(peer
, afi
, safi
)
2541 if ((p
->family
== AF_INET6
) &&
2542 (!bgp_subgrp_multiaccess_check_v6(
2543 piattr
->mp_nexthop_global
,
2545 subgroup_announce_reset_nhop(
2546 (peer_cap_enhe(peer
, afi
, safi
)
2555 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2557 * This flag is used for leaked vpn-vrf routes
2559 int family
= p
->family
;
2561 if (peer_cap_enhe(peer
, afi
, safi
))
2564 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2566 "%s: %pFX BGP_PATH_ANNC_NH_SELF, family=%s",
2567 __func__
, p
, family2str(family
));
2568 subgroup_announce_reset_nhop(family
, attr
);
2573 /* If IPv6/MP and nexthop does not have any override and happens
2575 * be a link-local address, reset it so that we don't pass along
2577 * source's link-local IPv6 address to recipients who may not be
2579 * the same interface.
2581 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2582 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2583 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2588 /* If this is an iBGP, send Origin Validation State (OVS)
2589 * extended community (rfc8097).
2591 if (peer
->sort
== BGP_PEER_IBGP
) {
2592 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
2594 rpki_state
= hook_call(bgp_rpki_prefix_status
, peer
, attr
, p
);
2596 if (rpki_state
!= RPKI_NOT_BEING_USED
)
2597 bgp_attr_set_ecommunity(
2598 attr
, ecommunity_add_origin_validation_state(
2600 bgp_attr_get_ecommunity(attr
)));
2604 * When the next hop is set to ourselves, if all multipaths have
2605 * link-bandwidth announce the cumulative bandwidth as that makes
2606 * the most sense. However, don't modify if the link-bandwidth has
2607 * been explicitly set by user policy.
2610 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2611 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2612 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2613 bgp_attr_set_ecommunity(
2615 ecommunity_replace_linkbw(
2616 bgp
->as
, bgp_attr_get_ecommunity(attr
), cum_bw
,
2619 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
)));
2624 static void bgp_route_select_timer_expire(struct event
*thread
)
2626 struct afi_safi_info
*info
;
2631 info
= EVENT_ARG(thread
);
2636 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2637 XFREE(MTYPE_TMP
, info
);
2639 /* Best path selection */
2640 bgp_best_path_select_defer(bgp
, afi
, safi
);
2643 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2644 struct bgp_maxpaths_cfg
*mpath_cfg
,
2645 struct bgp_path_info_pair
*result
, afi_t afi
,
2648 struct bgp_path_info
*new_select
;
2649 struct bgp_path_info
*old_select
;
2650 struct bgp_path_info
*pi
;
2651 struct bgp_path_info
*pi1
;
2652 struct bgp_path_info
*pi2
;
2653 struct bgp_path_info
*nextpi
= NULL
;
2654 int paths_eq
, do_mpath
, debug
;
2655 struct list mp_list
;
2656 char pfx_buf
[PREFIX2STR_BUFFER
];
2657 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2659 bgp_mp_list_init(&mp_list
);
2661 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2663 debug
= bgp_debug_bestpath(dest
);
2666 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2668 dest
->reason
= bgp_path_selection_none
;
2669 /* bgp deterministic-med */
2671 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2673 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2674 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2676 bgp_path_info_unset_flag(dest
, pi1
,
2677 BGP_PATH_DMED_SELECTED
);
2679 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2681 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2683 if (BGP_PATH_HOLDDOWN(pi1
))
2685 if (pi1
->peer
!= bgp
->peer_self
&&
2686 !CHECK_FLAG(pi1
->peer
->sflags
,
2687 PEER_STATUS_NSF_WAIT
)) {
2688 if (!peer_established(pi1
->peer
))
2694 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2695 if (CHECK_FLAG(pi2
->flags
,
2696 BGP_PATH_DMED_CHECK
))
2698 if (BGP_PATH_HOLDDOWN(pi2
))
2700 if (pi2
->peer
!= bgp
->peer_self
2703 PEER_STATUS_NSF_WAIT
))
2704 if (pi2
->peer
->status
2708 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2710 && !aspath_cmp_left_confed(
2715 if (bgp_path_info_cmp(
2716 bgp
, pi2
, new_select
,
2717 &paths_eq
, mpath_cfg
, debug
,
2720 bgp_path_info_unset_flag(
2722 BGP_PATH_DMED_SELECTED
);
2726 bgp_path_info_set_flag(
2727 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2730 bgp_path_info_set_flag(dest
, new_select
,
2731 BGP_PATH_DMED_CHECK
);
2732 bgp_path_info_set_flag(dest
, new_select
,
2733 BGP_PATH_DMED_SELECTED
);
2736 bgp_path_info_path_with_addpath_rx_str(
2737 new_select
, path_buf
, sizeof(path_buf
));
2739 "%pBD(%s): %s is the bestpath from AS %u",
2740 dest
, bgp
->name_pretty
, path_buf
,
2741 aspath_get_first_as(
2742 new_select
->attr
->aspath
));
2747 /* Check old selected route and new selected route. */
2750 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2751 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2752 enum bgp_path_selection_reason reason
;
2754 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2757 if (BGP_PATH_HOLDDOWN(pi
)) {
2758 /* reap REMOVED routes, if needs be
2759 * selected route must stay for a while longer though
2761 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2762 && (pi
!= old_select
))
2763 bgp_path_info_reap(dest
, pi
);
2767 "%s: %pBD(%s) pi from %s in holddown",
2768 __func__
, dest
, bgp
->name_pretty
,
2774 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2775 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2776 if (!peer_established(pi
->peer
)) {
2780 "%s: %pBD(%s) non self peer %s not estab state",
2788 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2789 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2790 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2792 zlog_debug("%s: %pBD(%s) pi %s dmed", __func__
,
2793 dest
, bgp
->name_pretty
,
2798 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2800 reason
= dest
->reason
;
2801 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2802 debug
, pfx_buf
, afi
, safi
,
2804 if (new_select
== NULL
&&
2805 reason
!= bgp_path_selection_none
)
2806 dest
->reason
= reason
;
2811 /* Now that we know which path is the bestpath see if any of the other
2813 * qualify as multipaths
2817 bgp_path_info_path_with_addpath_rx_str(
2818 new_select
, path_buf
, sizeof(path_buf
));
2820 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2822 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2823 dest
, bgp
->name_pretty
, path_buf
,
2824 old_select
? old_select
->peer
->host
: "NONE");
2827 if (do_mpath
&& new_select
) {
2828 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2829 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2832 bgp_path_info_path_with_addpath_rx_str(
2833 pi
, path_buf
, sizeof(path_buf
));
2835 if (pi
== new_select
) {
2838 "%pBD(%s): %s is the bestpath, add to the multipath list",
2839 dest
, bgp
->name_pretty
,
2841 bgp_mp_list_add(&mp_list
, pi
);
2845 if (BGP_PATH_HOLDDOWN(pi
))
2848 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2849 && !CHECK_FLAG(pi
->peer
->sflags
,
2850 PEER_STATUS_NSF_WAIT
))
2851 if (!peer_established(pi
->peer
))
2854 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2857 "%pBD(%s): %s has the same nexthop as the bestpath, skip it",
2858 dest
, bgp
->name_pretty
,
2863 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2864 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2870 "%pBD(%s): %s is equivalent to the bestpath, add to the multipath list",
2871 dest
, bgp
->name_pretty
,
2873 bgp_mp_list_add(&mp_list
, pi
);
2878 bgp_path_info_mpath_update(bgp
, dest
, new_select
, old_select
, &mp_list
,
2880 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2881 bgp_mp_list_clear(&mp_list
);
2883 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2885 result
->old
= old_select
;
2886 result
->new = new_select
;
2892 * A new route/change in bestpath of an existing route. Evaluate the path
2893 * for advertisement to the subgroup.
2895 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2896 struct bgp_path_info
*selected
,
2897 struct bgp_dest
*dest
,
2898 uint32_t addpath_tx_id
)
2900 const struct prefix
*p
;
2901 struct peer
*onlypeer
;
2908 p
= bgp_dest_get_prefix(dest
);
2909 afi
= SUBGRP_AFI(subgrp
);
2910 safi
= SUBGRP_SAFI(subgrp
);
2911 bgp
= SUBGRP_INST(subgrp
);
2912 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2915 if (BGP_DEBUG(update
, UPDATE_OUT
))
2916 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2918 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2919 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2920 PEER_STATUS_ORF_WAIT_REFRESH
))
2923 memset(&attr
, 0, sizeof(attr
));
2924 /* It's initialized in bgp_announce_check() */
2926 /* Announcement to the subgroup. If the route is filtered withdraw it.
2927 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2928 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2931 advertise
= bgp_check_advertise(bgp
, dest
);
2934 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2936 /* Route is selected, if the route is already installed
2937 * in FIB, then it is advertised
2940 if (!bgp_check_withdrawal(bgp
, dest
)) {
2941 struct attr
*adv_attr
=
2942 bgp_attr_intern(&attr
);
2944 bgp_adj_out_set_subgroup(dest
, subgrp
,
2948 bgp_adj_out_unset_subgroup(
2949 dest
, subgrp
, 1, addpath_tx_id
);
2952 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2956 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2958 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2963 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2964 * This is called at the end of route processing.
2966 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2968 struct bgp_path_info
*pi
;
2970 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2971 if (BGP_PATH_HOLDDOWN(pi
))
2973 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2974 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2979 * Has the route changed from the RIB's perspective? This is invoked only
2980 * if the route selection returns the same best route as earlier - to
2981 * determine if we need to update zebra or not.
2983 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2985 struct bgp_path_info
*mpinfo
;
2987 /* If this is multipath, check all selected paths for any nexthop
2988 * change or attribute change. Some attribute changes (e.g., community)
2989 * aren't of relevance to the RIB, but we'll update zebra to ensure
2990 * we handle the case of BGP nexthop change. This is the behavior
2991 * when the best path has an attribute change anyway.
2993 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2994 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2995 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2999 * If this is multipath, check all selected paths for any nexthop change
3001 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
3002 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
3003 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
3004 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
3008 /* Nothing has changed from the RIB's perspective. */
3012 struct bgp_process_queue
{
3014 STAILQ_HEAD(, bgp_dest
) pqueue
;
3015 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
3017 unsigned int queued
;
3020 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
3021 safi_t safi
, struct bgp_dest
*dest
,
3022 struct bgp_path_info
*new_select
,
3023 struct bgp_path_info
*old_select
)
3025 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3027 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
3030 if (advertise_type5_routes(bgp
, afi
) && new_select
3031 && is_route_injectable_into_evpn(new_select
)) {
3033 /* apply the route-map */
3034 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
3035 route_map_result_t ret
;
3036 struct bgp_path_info rmap_path
;
3037 struct bgp_path_info_extra rmap_path_extra
;
3038 struct attr dummy_attr
;
3040 dummy_attr
= *new_select
->attr
;
3042 /* Fill temp path_info */
3043 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
3044 new_select
, new_select
->peer
,
3047 RESET_FLAG(dummy_attr
.rmap_change_flags
);
3049 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
3052 if (ret
== RMAP_DENYMATCH
) {
3053 bgp_attr_flush(&dummy_attr
);
3054 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
3057 bgp_evpn_advertise_type5_route(
3058 bgp
, p
, &dummy_attr
, afi
, safi
);
3060 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
3063 } else if (advertise_type5_routes(bgp
, afi
) && old_select
3064 && is_route_injectable_into_evpn(old_select
))
3065 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
3069 * Utility to determine whether a particular path_info should use
3070 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3071 * in a path where we basically _know_ this is a BGP-LU route.
3073 static bool bgp_lu_need_imp_null(const struct bgp_path_info
*new_select
)
3075 /* Certain types get imp null; so do paths where the nexthop is
3078 if (new_select
->sub_type
== BGP_ROUTE_STATIC
3079 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3080 || new_select
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
3082 else if (new_select
->extra
== NULL
||
3083 !bgp_is_valid_label(&new_select
->extra
->label
[0]))
3084 /* TODO -- should be configurable? */
3091 * old_select = The old best path
3092 * new_select = the new best path
3094 * if (!old_select && new_select)
3095 * We are sending new information on.
3097 * if (old_select && new_select) {
3098 * if (new_select != old_select)
3099 * We have a new best path send a change
3101 * We've received a update with new attributes that needs
3105 * if (old_select && !new_select)
3106 * We have no eligible route that we can announce or the rn
3109 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
3110 afi_t afi
, safi_t safi
)
3112 struct bgp_path_info
*new_select
;
3113 struct bgp_path_info
*old_select
;
3114 struct bgp_path_info_pair old_and_new
;
3117 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
3119 debug
= bgp_debug_bestpath(dest
);
3122 "%s: bgp delete in progress, ignoring event, p=%pBD(%s)",
3123 __func__
, dest
, bgp
->name_pretty
);
3126 /* Is it end of initial update? (after startup) */
3128 frr_timestamp(3, bgp
->update_delay_zebra_resume_time
,
3129 sizeof(bgp
->update_delay_zebra_resume_time
));
3131 bgp
->main_zebra_update_hold
= 0;
3132 FOREACH_AFI_SAFI (afi
, safi
) {
3133 if (bgp_fibupd_safi(safi
))
3134 bgp_zebra_announce_table(bgp
, afi
, safi
);
3136 bgp
->main_peers_update_hold
= 0;
3138 bgp_start_routeadv(bgp
);
3142 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3144 debug
= bgp_debug_bestpath(dest
);
3146 zlog_debug("%s: p=%pBD(%s) afi=%s, safi=%s start", __func__
,
3147 dest
, bgp
->name_pretty
, afi2str(afi
),
3150 /* The best path calculation for the route is deferred if
3151 * BGP_NODE_SELECT_DEFER is set
3153 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3154 if (BGP_DEBUG(update
, UPDATE_OUT
))
3155 zlog_debug("SELECT_DEFER flag set for route %p(%s)",
3156 dest
, bgp
->name_pretty
);
3160 /* Best path selection. */
3161 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
3163 old_select
= old_and_new
.old
;
3164 new_select
= old_and_new
.new;
3166 /* Do we need to allocate or free labels?
3167 * Right now, since we only deal with per-prefix labels, it is not
3168 * necessary to do this upon changes to best path. Exceptions:
3169 * - label index has changed -> recalculate resulting label
3170 * - path_info sub_type changed -> switch to/from implicit-null
3171 * - no valid label (due to removed static label binding) -> get new one
3173 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
3176 || bgp_label_index_differs(new_select
, old_select
)
3177 || new_select
->sub_type
!= old_select
->sub_type
3178 || !bgp_is_valid_label(&dest
->local_label
)) {
3179 /* Enforced penultimate hop popping:
3180 * implicit-null for local routes, aggregate
3181 * and redistributed routes
3183 if (bgp_lu_need_imp_null(new_select
)) {
3186 BGP_NODE_REGISTERED_FOR_LABEL
)
3189 BGP_NODE_LABEL_REQUESTED
))
3190 bgp_unregister_for_label(dest
);
3191 dest
->local_label
= mpls_lse_encode(
3192 MPLS_LABEL_IMPLICIT_NULL
, 0, 0,
3194 bgp_set_valid_label(&dest
->local_label
);
3196 bgp_register_for_label(dest
,
3199 } else if (CHECK_FLAG(dest
->flags
,
3200 BGP_NODE_REGISTERED_FOR_LABEL
)
3201 || CHECK_FLAG(dest
->flags
,
3202 BGP_NODE_LABEL_REQUESTED
)) {
3203 bgp_unregister_for_label(dest
);
3205 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
3206 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
3207 bgp_unregister_for_label(dest
);
3212 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3213 __func__
, dest
, bgp
->name_pretty
, afi2str(afi
),
3214 safi2str(safi
), old_select
, new_select
);
3216 /* If best route remains the same and this is not due to user-initiated
3217 * clear, see exactly what needs to be done.
3219 if (old_select
&& old_select
== new_select
3220 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
3221 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3222 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
3223 if (bgp_zebra_has_route_changed(old_select
)) {
3224 #ifdef ENABLE_BGP_VNC
3225 vnc_import_bgp_add_route(bgp
, p
, old_select
);
3226 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
3228 if (bgp_fibupd_safi(safi
)
3229 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3231 if (new_select
->type
== ZEBRA_ROUTE_BGP
3232 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3233 || new_select
->sub_type
3234 == BGP_ROUTE_IMPORTED
))
3236 bgp_zebra_announce(dest
, p
, old_select
,
3241 /* If there is a change of interest to peers, reannounce the
3243 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3244 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3245 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
3246 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3248 /* unicast routes must also be annouced to
3249 * labeled-unicast update-groups */
3250 if (safi
== SAFI_UNICAST
)
3251 group_announce_route(bgp
, afi
,
3252 SAFI_LABELED_UNICAST
, dest
,
3255 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
3256 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
3259 /* advertise/withdraw type-5 routes */
3260 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3261 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
3262 bgp_process_evpn_route_injection(
3263 bgp
, afi
, safi
, dest
, old_select
, old_select
);
3265 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3266 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3267 bgp_zebra_clear_route_change_flags(dest
);
3268 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3272 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3274 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
3276 /* bestpath has changed; bump version */
3277 if (old_select
|| new_select
) {
3278 bgp_bump_version(dest
);
3280 if (!bgp
->t_rmap_def_originate_eval
) {
3284 update_group_refresh_default_originate_route_map
,
3285 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
3286 &bgp
->t_rmap_def_originate_eval
);
3291 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
3294 zlog_debug("%s: setting SELECTED flag", __func__
);
3295 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
3296 bgp_path_info_unset_flag(dest
, new_select
,
3297 BGP_PATH_ATTR_CHANGED
);
3298 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3299 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3302 #ifdef ENABLE_BGP_VNC
3303 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3304 if (old_select
!= new_select
) {
3306 vnc_import_bgp_exterior_del_route(bgp
, p
,
3308 vnc_import_bgp_del_route(bgp
, p
, old_select
);
3311 vnc_import_bgp_exterior_add_route(bgp
, p
,
3313 vnc_import_bgp_add_route(bgp
, p
, new_select
);
3319 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3321 /* unicast routes must also be annouced to labeled-unicast update-groups
3323 if (safi
== SAFI_UNICAST
)
3324 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
3328 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
3329 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3331 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
3332 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3333 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3334 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
3336 /* if this is an evpn imported type-5 prefix,
3337 * we need to withdraw the route first to clear
3338 * the nh neigh and the RMAC entry.
3341 is_route_parent_evpn(old_select
))
3342 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3344 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
3346 /* Withdraw the route from the kernel. */
3347 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
3348 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
3349 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
3350 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
3352 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3356 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
3359 /* Clear any route change flags. */
3360 bgp_zebra_clear_route_change_flags(dest
);
3362 /* Reap old select bgp_path_info, if it has been removed */
3363 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
3364 bgp_path_info_reap(dest
, old_select
);
3366 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3370 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3371 void bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
3373 struct bgp_dest
*dest
;
3375 struct afi_safi_info
*thread_info
;
3377 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
3378 struct event
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
3380 thread_info
= EVENT_ARG(t
);
3381 XFREE(MTYPE_TMP
, thread_info
);
3382 EVENT_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
3385 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
3386 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
3387 get_afi_safi_str(afi
, safi
, false),
3388 bgp
->gr_info
[afi
][safi
].gr_deferred
);
3391 /* Process the route list */
3392 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
3393 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0 &&
3394 cnt
< BGP_MAX_BEST_ROUTE_SELECT
;
3395 dest
= bgp_route_next(dest
)) {
3396 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
3399 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3400 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3401 bgp_process_main_one(bgp
, dest
, afi
, safi
);
3404 /* If iteration stopped before the entire table was traversed then the
3405 * node needs to be unlocked.
3408 bgp_dest_unlock_node(dest
);
3412 /* Send EOR message when all routes are processed */
3413 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
3414 bgp_send_delayed_eor(bgp
);
3415 /* Send route processing complete message to RIB */
3416 bgp_zebra_update(bgp
, afi
, safi
,
3417 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
3421 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3423 thread_info
->afi
= afi
;
3424 thread_info
->safi
= safi
;
3425 thread_info
->bgp
= bgp
;
3427 /* If there are more routes to be processed, start the
3430 event_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3431 BGP_ROUTE_SELECT_DELAY
,
3432 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3435 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3437 struct bgp_process_queue
*pqnode
= data
;
3438 struct bgp
*bgp
= pqnode
->bgp
;
3439 struct bgp_table
*table
;
3440 struct bgp_dest
*dest
;
3443 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3444 bgp_process_main_one(bgp
, NULL
, 0, 0);
3445 /* should always have dedicated wq call */
3446 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3450 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3451 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3452 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3453 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3454 table
= bgp_dest_table(dest
);
3455 /* note, new DESTs may be added as part of processing */
3456 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3458 bgp_dest_unlock_node(dest
);
3459 bgp_table_unlock(table
);
3465 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3467 struct bgp_process_queue
*pqnode
= data
;
3469 bgp_unlock(pqnode
->bgp
);
3471 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3474 void bgp_process_queue_init(struct bgp
*bgp
)
3476 if (!bgp
->process_queue
) {
3479 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3480 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3483 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3484 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3485 bgp
->process_queue
->spec
.max_retries
= 0;
3486 bgp
->process_queue
->spec
.hold
= 50;
3487 /* Use a higher yield value of 50ms for main queue processing */
3488 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3491 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3493 struct bgp_process_queue
*pqnode
;
3495 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3496 sizeof(struct bgp_process_queue
));
3498 /* unlocked in bgp_processq_del */
3499 pqnode
->bgp
= bgp_lock(bgp
);
3500 STAILQ_INIT(&pqnode
->pqueue
);
3505 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3507 #define ARBITRARY_PROCESS_QLEN 10000
3508 struct work_queue
*wq
= bgp
->process_queue
;
3509 struct bgp_process_queue
*pqnode
;
3510 int pqnode_reuse
= 0;
3512 /* already scheduled for processing? */
3513 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3516 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3519 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3520 if (BGP_DEBUG(update
, UPDATE_OUT
))
3521 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3526 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
)) {
3527 if (BGP_DEBUG(update
, UPDATE_OUT
))
3529 "Soft reconfigure table in progress for route %p",
3537 /* Add route nodes to an existing work queue item until reaching the
3538 limit only if is from the same BGP view and it's not an EOIU marker
3540 if (work_queue_item_count(wq
)) {
3541 struct work_queue_item
*item
= work_queue_last_item(wq
);
3542 pqnode
= item
->data
;
3544 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3545 || pqnode
->bgp
!= bgp
3546 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3547 pqnode
= bgp_processq_alloc(bgp
);
3551 pqnode
= bgp_processq_alloc(bgp
);
3552 /* all unlocked in bgp_process_wq */
3553 bgp_table_lock(bgp_dest_table(dest
));
3555 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3556 bgp_dest_lock_node(dest
);
3558 /* can't be enqueued twice */
3559 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3560 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3564 work_queue_add(wq
, pqnode
);
3569 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3571 struct bgp_process_queue
*pqnode
;
3573 if (bgp
->process_queue
== NULL
)
3576 pqnode
= bgp_processq_alloc(bgp
);
3578 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3579 work_queue_add(bgp
->process_queue
, pqnode
);
3582 static void bgp_maximum_prefix_restart_timer(struct event
*thread
)
3586 peer
= EVENT_ARG(thread
);
3587 peer
->t_pmax_restart
= NULL
;
3589 if (bgp_debug_neighbor_events(peer
))
3591 "%s Maximum-prefix restart timer expired, restore peering",
3594 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3595 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3598 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3602 bool filtered
= false;
3603 struct bgp_dest
*dest
;
3604 struct bgp_adj_in
*ain
;
3605 struct attr attr
= {};
3606 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3608 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3609 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3610 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3614 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3618 if (bgp_input_modifier(
3619 peer
, rn_p
, &attr
, afi
, safi
,
3620 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3628 bgp_attr_flush(&attr
);
3635 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3639 iana_safi_t pkt_safi
;
3640 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3641 PEER_FLAG_MAX_PREFIX_FORCE
))
3642 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3643 + peer
->pcount
[afi
][safi
]
3644 : peer
->pcount
[afi
][safi
];
3646 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3649 if (pcount
> peer
->pmax
[afi
][safi
]) {
3650 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3651 PEER_STATUS_PREFIX_LIMIT
)
3656 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3657 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3658 peer
->pmax
[afi
][safi
]);
3659 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3661 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3662 PEER_FLAG_MAX_PREFIX_WARNING
))
3665 /* Convert AFI, SAFI to values for packet. */
3666 pkt_afi
= afi_int2iana(afi
);
3667 pkt_safi
= safi_int2iana(safi
);
3671 ndata
[0] = (pkt_afi
>> 8);
3673 ndata
[2] = pkt_safi
;
3674 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3675 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3676 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3677 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3679 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3680 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3681 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3685 /* Dynamic peers will just close their connection. */
3686 if (peer_dynamic_neighbor(peer
))
3689 /* restart timer start */
3690 if (peer
->pmax_restart
[afi
][safi
]) {
3691 peer
->v_pmax_restart
=
3692 peer
->pmax_restart
[afi
][safi
] * 60;
3694 if (bgp_debug_neighbor_events(peer
))
3696 "%pBP Maximum-prefix restart timer started for %d secs",
3697 peer
, peer
->v_pmax_restart
);
3699 BGP_TIMER_ON(peer
->t_pmax_restart
,
3700 bgp_maximum_prefix_restart_timer
,
3701 peer
->v_pmax_restart
);
3706 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3707 PEER_STATUS_PREFIX_LIMIT
);
3710 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3711 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3712 PEER_STATUS_PREFIX_THRESHOLD
)
3717 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3718 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3719 peer
->pmax
[afi
][safi
]);
3720 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3721 PEER_STATUS_PREFIX_THRESHOLD
);
3723 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3724 PEER_STATUS_PREFIX_THRESHOLD
);
3728 /* Unconditionally remove the route from the RIB, without taking
3729 * damping into consideration (eg, because the session went down)
3731 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3732 struct peer
*peer
, afi_t afi
, safi_t safi
)
3735 struct bgp
*bgp
= NULL
;
3736 bool delete_route
= false;
3738 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3741 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3742 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3744 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3747 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3748 delete_route
= true;
3749 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3750 delete_route
= true;
3752 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3753 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3754 bgp
= pi
->peer
->bgp
;
3755 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3760 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3761 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3764 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3765 struct peer
*peer
, afi_t afi
, safi_t safi
,
3766 struct prefix_rd
*prd
)
3768 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3770 /* apply dampening, if result is suppressed, we'll be retaining
3771 * the bgp_path_info in the RIB for historical reference.
3773 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3774 && peer
->sort
== BGP_PEER_EBGP
)
3775 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3776 == BGP_DAMP_SUPPRESSED
) {
3777 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3782 #ifdef ENABLE_BGP_VNC
3783 if (safi
== SAFI_MPLS_VPN
) {
3784 struct bgp_dest
*pdest
= NULL
;
3785 struct bgp_table
*table
= NULL
;
3787 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3788 (struct prefix
*)prd
);
3789 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3790 table
= bgp_dest_get_bgp_table_info(pdest
);
3792 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3793 peer
->bgp
, prd
, table
, p
, pi
);
3795 bgp_dest_unlock_node(pdest
);
3797 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3798 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3800 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3801 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3806 /* If this is an EVPN route, process for un-import. */
3807 if (safi
== SAFI_EVPN
)
3808 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3810 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3813 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3814 struct peer
*peer
, struct attr
*attr
,
3815 struct bgp_dest
*dest
)
3817 struct bgp_path_info
*new;
3819 /* Make new BGP info. */
3820 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3822 new->instance
= instance
;
3823 new->sub_type
= sub_type
;
3826 new->uptime
= monotime(NULL
);
3831 /* Check if received nexthop is valid or not. */
3832 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3833 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3834 struct bgp_dest
*dest
)
3837 bool is_bgp_static_route
=
3838 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3841 /* If `bgp allow-martian-nexthop` is turned on, return next-hop
3844 if (bgp
->allow_martian
)
3848 * Only validated for unicast and multicast currently.
3849 * Also valid for EVPN where the nexthop is an IP address.
3850 * If we are a bgp static route being checked then there is
3851 * no need to check to see if the nexthop is martian as
3852 * that it should be ok.
3854 if (is_bgp_static_route
||
3855 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3858 /* If NEXT_HOP is present, validate it. */
3859 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3860 if (attr
->nexthop
.s_addr
== INADDR_ANY
||
3861 !ipv4_unicast_valid(&attr
->nexthop
) ||
3862 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3866 /* If MP_NEXTHOP is present, validate it. */
3867 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3868 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3869 * it is not an IPv6 link-local address.
3871 * If we receive an UPDATE with nexthop length set to 32 bytes
3872 * we shouldn't discard an UPDATE if it's set to (::).
3873 * The link-local (2st) is validated along the code path later.
3875 if (attr
->mp_nexthop_len
) {
3876 switch (attr
->mp_nexthop_len
) {
3877 case BGP_ATTR_NHLEN_IPV4
:
3878 case BGP_ATTR_NHLEN_VPNV4
:
3879 ret
= (attr
->mp_nexthop_global_in
.s_addr
==
3881 !ipv4_unicast_valid(
3882 &attr
->mp_nexthop_global_in
) ||
3883 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3887 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3888 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3889 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3890 &attr
->mp_nexthop_global
)
3891 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3892 || IN6_IS_ADDR_MULTICAST(
3893 &attr
->mp_nexthop_global
)
3894 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3897 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3898 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3899 || IN6_IS_ADDR_MULTICAST(
3900 &attr
->mp_nexthop_global
)
3901 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3914 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3916 struct community
*old
;
3917 struct community
*new;
3918 struct community
*merge
;
3919 struct community
*no_export
;
3921 old
= bgp_attr_get_community(attr
);
3922 no_export
= community_str2com("no-export");
3927 merge
= community_merge(community_dup(old
), no_export
);
3930 community_free(&old
);
3932 new = community_uniq_sort(merge
);
3933 community_free(&merge
);
3935 new = community_dup(no_export
);
3938 community_free(&no_export
);
3940 bgp_attr_set_community(attr
, new);
3943 static bool bgp_accept_own(struct peer
*peer
, afi_t afi
, safi_t safi
,
3944 struct attr
*attr
, const struct prefix
*prefix
,
3947 struct listnode
*node
, *nnode
;
3949 bool accept_own_found
= false;
3951 if (safi
!= SAFI_MPLS_VPN
)
3954 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3955 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
))
3958 /* The route in question carries the ACCEPT_OWN community */
3959 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
3960 struct community
*comm
= bgp_attr_get_community(attr
);
3962 if (community_include(comm
, COMMUNITY_ACCEPT_OWN
))
3963 accept_own_found
= true;
3966 /* The route in question is targeted to one or more destination VRFs
3967 * on the router (as determined by inspecting the Route Target(s)).
3969 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
3970 if (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
)
3973 if (accept_own_found
&&
3975 bgp
->vpn_policy
[afi
]
3976 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
],
3977 bgp_attr_get_ecommunity(attr
))) {
3978 if (bgp_debug_update(peer
, prefix
, NULL
, 1))
3980 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3983 /* Treat this route as imported, because it's leaked
3984 * already from another VRF, and we got an updated
3985 * version from route-reflector with ACCEPT_OWN
3988 *sub_type
= BGP_ROUTE_IMPORTED
;
3997 void bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
3998 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3999 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4000 uint32_t num_labels
, int soft_reconfig
,
4001 struct bgp_route_evpn
*evpn
)
4004 int aspath_loop_count
= 0;
4005 struct bgp_dest
*dest
;
4007 struct attr new_attr
;
4008 struct attr
*attr_new
;
4009 struct bgp_path_info
*pi
;
4010 struct bgp_path_info
*new = NULL
;
4011 struct bgp_path_info_extra
*extra
;
4013 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4015 int do_loop_check
= 1;
4016 int has_valid_label
= 0;
4018 bool force_evpn_import
= false;
4019 safi_t orig_safi
= safi
;
4020 bool leak_success
= true;
4023 if (frrtrace_enabled(frr_bgp
, process_update
)) {
4024 char pfxprint
[PREFIX2STR_BUFFER
];
4026 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
4027 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
4031 #ifdef ENABLE_BGP_VNC
4032 int vnc_implicit_withdraw
= 0;
4035 const struct prefix
*bgp_nht_param_prefix
;
4037 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4038 if (orig_safi
== SAFI_LABELED_UNICAST
)
4039 safi
= SAFI_UNICAST
;
4041 memset(&new_attr
, 0, sizeof(new_attr
));
4042 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
4043 new_attr
.label
= MPLS_INVALID_LABEL
;
4046 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4047 /* TODO: Check to see if we can get rid of "is_valid_label" */
4048 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
4049 has_valid_label
= (num_labels
> 0) ? 1 : 0;
4051 has_valid_label
= bgp_is_valid_label(label
);
4053 if (has_valid_label
)
4054 assert(label
!= NULL
);
4056 /* Update overlay index of the attribute */
4057 if (afi
== AFI_L2VPN
&& evpn
)
4058 memcpy(&attr
->evpn_overlay
, evpn
,
4059 sizeof(struct bgp_route_evpn
));
4061 /* When peer's soft reconfiguration enabled. Record input packet in
4064 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4065 && peer
!= bgp
->peer_self
)
4066 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
4068 /* Update permitted loop count */
4069 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN
))
4070 allowas_in
= peer
->allowas_in
[afi
][safi
];
4072 /* Check previously received route. */
4073 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4074 if (pi
->peer
== peer
&& pi
->type
== type
4075 && pi
->sub_type
== sub_type
4076 && pi
->addpath_rx_id
== addpath_id
)
4079 /* AS path local-as loop check. */
4080 if (peer
->change_local_as
) {
4082 aspath_loop_count
= allowas_in
;
4083 else if (!CHECK_FLAG(peer
->flags
,
4084 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
4085 aspath_loop_count
= 1;
4087 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
4088 > aspath_loop_count
) {
4089 peer
->stat_pfx_aspath_loop
++;
4090 reason
= "as-path contains our own AS;";
4095 /* If the peer is configured for "allowas-in origin" and the last ASN in
4097 * as-path is our ASN then we do not need to call aspath_loop_check
4099 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
4100 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
4103 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_REFLECTOR_CLIENT
))
4104 bgp_nht_param_prefix
= NULL
;
4106 bgp_nht_param_prefix
= p
;
4108 /* AS path loop check. */
4109 if (do_loop_check
) {
4110 if (aspath_loop_check(attr
->aspath
, bgp
->as
) >
4111 peer
->allowas_in
[afi
][safi
]) {
4112 peer
->stat_pfx_aspath_loop
++;
4113 reason
= "as-path contains our own AS;";
4118 /* If we're a CONFED we need to loop check the CONFED ID too */
4119 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
) && do_loop_check
)
4120 if (aspath_loop_check_confed(attr
->aspath
, bgp
->confed_id
) >
4121 peer
->allowas_in
[afi
][safi
]) {
4122 peer
->stat_pfx_aspath_loop
++;
4123 reason
= "as-path contains our own confed AS;";
4127 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4128 * enabled, then take care of that too.
4130 bool accept_own
= false;
4132 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
4133 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
4135 bgp_accept_own(peer
, afi
, safi
, attr
, p
, &sub_type
);
4137 peer
->stat_pfx_originator_loop
++;
4138 reason
= "originator is us;";
4143 /* Route reflector cluster ID check. */
4144 if (bgp_cluster_filter(peer
, attr
)) {
4145 peer
->stat_pfx_cluster_loop
++;
4146 reason
= "reflected from the same cluster;";
4150 /* Apply incoming filter. */
4151 if (bgp_input_filter(peer
, p
, attr
, afi
, orig_safi
) == FILTER_DENY
) {
4152 peer
->stat_pfx_filter
++;
4157 /* RFC 8212 to prevent route leaks.
4158 * This specification intends to improve this situation by requiring the
4159 * explicit configuration of both BGP Import and Export Policies for any
4160 * External BGP (EBGP) session such as customers, peers, or
4161 * confederation boundaries for all enabled address families. Through
4162 * codification of the aforementioned requirement, operators will
4163 * benefit from consistent behavior across different BGP
4166 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
4167 if (!bgp_inbound_policy_exists(peer
,
4168 &peer
->filter
[afi
][safi
])) {
4169 reason
= "inbound policy missing";
4170 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
4171 NULL
) > FIFTEENMINUTE2USEC
||
4172 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
4174 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4175 monotime(&bgp
->ebgprequirespolicywarning
);
4180 /* draft-ietf-idr-deprecate-as-set-confed-set
4181 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4182 * Eventually, This document (if approved) updates RFC 4271
4183 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4184 * and obsoletes RFC 6472.
4186 if (peer
->bgp
->reject_as_sets
)
4187 if (aspath_check_as_sets(attr
->aspath
)) {
4189 "as-path contains AS_SET or AS_CONFED_SET type;";
4195 /* Apply incoming route-map.
4196 * NB: new_attr may now contain newly allocated values from route-map
4198 * commands, so we need bgp_attr_flush in the error paths, until we
4200 * the attr (which takes over the memory references) */
4201 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, orig_safi
, NULL
, label
,
4204 peer
->stat_pfx_filter
++;
4205 reason
= "route-map;";
4206 bgp_attr_flush(&new_attr
);
4210 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
4211 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
4212 /* remove from RIB previous entry */
4213 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
4216 if (peer
->sort
== BGP_PEER_EBGP
) {
4219 * A BGP speaker receiving an announcement tagged with the
4220 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4221 * NO_EXPORT community as defined in RFC1997, or a
4222 * similar community, to prevent propagation of the
4223 * prefix outside the local AS. The community to prevent
4224 * propagation SHOULD be chosen according to the operator's
4227 if (bgp_attr_get_community(&new_attr
) &&
4228 community_include(bgp_attr_get_community(&new_attr
),
4229 COMMUNITY_BLACKHOLE
))
4230 bgp_attr_add_no_export_community(&new_attr
);
4232 /* If we receive the graceful-shutdown community from an eBGP
4233 * peer we must lower local-preference */
4234 if (bgp_attr_get_community(&new_attr
) &&
4235 community_include(bgp_attr_get_community(&new_attr
),
4237 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
4238 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
4240 /* If graceful-shutdown is configured globally or
4241 * per neighbor, then add the GSHUT community to
4242 * all paths received from eBGP peers. */
4243 } else if (bgp_in_graceful_shutdown(peer
->bgp
) ||
4244 CHECK_FLAG(peer
->flags
, PEER_FLAG_GRACEFUL_SHUTDOWN
))
4245 bgp_attr_add_gshut_community(&new_attr
);
4248 /* next hop check. */
4249 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
) &&
4250 bgp_update_martian_nexthop(bgp
, afi
, safi
, type
, sub_type
,
4252 peer
->stat_pfx_nh_invalid
++;
4253 reason
= "martian or self next-hop;";
4254 bgp_attr_flush(&new_attr
);
4258 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
4259 peer
->stat_pfx_nh_invalid
++;
4260 reason
= "self mac;";
4261 bgp_attr_flush(&new_attr
);
4265 if (bgp_check_role_applicability(afi
, safi
) &&
4266 bgp_otc_filter(peer
, &new_attr
)) {
4267 reason
= "failing otc validation";
4268 bgp_attr_flush(&new_attr
);
4272 /* If neighbor soo is configured, tag all incoming routes with
4273 * this SoO tag and then filter out advertisements in
4274 * subgroup_announce_check() if it matches the configured SoO
4275 * on the other peer.
4277 if (peer
->soo
[afi
][safi
]) {
4278 struct ecommunity
*old_ecomm
=
4279 bgp_attr_get_ecommunity(&new_attr
);
4280 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
4281 struct ecommunity
*new_ecomm
;
4284 new_ecomm
= ecommunity_merge(ecommunity_dup(old_ecomm
),
4287 if (!old_ecomm
->refcnt
)
4288 ecommunity_free(&old_ecomm
);
4290 new_ecomm
= ecommunity_dup(ecomm_soo
);
4293 bgp_attr_set_ecommunity(&new_attr
, new_ecomm
);
4296 attr_new
= bgp_attr_intern(&new_attr
);
4298 /* If the update is implicit withdraw. */
4300 pi
->uptime
= monotime(NULL
);
4301 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
4303 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4305 /* Same attribute comes in. */
4306 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4308 && (!has_valid_label
4309 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
4310 num_labels
* sizeof(mpls_label_t
))
4312 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4313 BGP_CONFIG_DAMPENING
)
4314 && peer
->sort
== BGP_PEER_EBGP
4315 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4316 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4317 bgp_debug_rdpfxpath2str(
4318 afi
, safi
, prd
, p
, label
,
4319 num_labels
, addpath_id
? 1 : 0,
4320 addpath_id
, evpn
, pfx_buf
,
4322 zlog_debug("%pBP rcvd %s", peer
,
4326 if (bgp_damp_update(pi
, dest
, afi
, safi
)
4327 != BGP_DAMP_SUPPRESSED
) {
4328 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
4330 bgp_process(bgp
, dest
, afi
, safi
);
4332 } else /* Duplicate - odd */
4334 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4335 if (!peer
->rcvd_attr_printed
) {
4337 "%pBP rcvd UPDATE w/ attr: %s",
4339 peer
->rcvd_attr_str
);
4340 peer
->rcvd_attr_printed
= 1;
4343 bgp_debug_rdpfxpath2str(
4344 afi
, safi
, prd
, p
, label
,
4345 num_labels
, addpath_id
? 1 : 0,
4346 addpath_id
, evpn
, pfx_buf
,
4349 "%pBP rcvd %s...duplicate ignored",
4353 /* graceful restart STALE flag unset. */
4354 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4355 bgp_path_info_unset_flag(
4356 dest
, pi
, BGP_PATH_STALE
);
4357 bgp_dest_set_defer_flag(dest
, false);
4358 bgp_process(bgp
, dest
, afi
, safi
);
4362 bgp_dest_unlock_node(dest
);
4363 bgp_attr_unintern(&attr_new
);
4368 /* Withdraw/Announce before we fully processed the withdraw */
4369 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4370 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4371 bgp_debug_rdpfxpath2str(
4372 afi
, safi
, prd
, p
, label
, num_labels
,
4373 addpath_id
? 1 : 0, addpath_id
, evpn
,
4374 pfx_buf
, sizeof(pfx_buf
));
4376 "%pBP rcvd %s, flapped quicker than processing",
4380 bgp_path_info_restore(dest
, pi
);
4383 * If the BGP_PATH_REMOVED flag is set, then EVPN
4384 * routes would have been unimported already when a
4385 * prior BGP withdraw processing happened. Such routes
4386 * need to be imported again, so flag accordingly.
4388 force_evpn_import
= true;
4390 /* implicit withdraw, decrement aggregate and pcount
4391 * here. only if update is accepted, they'll increment
4394 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4397 /* Received Logging. */
4398 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4399 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
4400 num_labels
, addpath_id
? 1 : 0,
4401 addpath_id
, evpn
, pfx_buf
,
4403 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4406 /* graceful restart STALE flag unset. */
4407 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4408 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
4409 bgp_dest_set_defer_flag(dest
, false);
4412 /* The attribute is changed. */
4413 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
4415 /* Update bgp route dampening information. */
4416 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4417 && peer
->sort
== BGP_PEER_EBGP
) {
4418 /* This is implicit withdraw so we should update
4421 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
4422 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
4424 #ifdef ENABLE_BGP_VNC
4425 if (safi
== SAFI_MPLS_VPN
) {
4426 struct bgp_dest
*pdest
= NULL
;
4427 struct bgp_table
*table
= NULL
;
4429 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4430 (struct prefix
*)prd
);
4431 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4432 table
= bgp_dest_get_bgp_table_info(pdest
);
4434 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
4435 bgp
, prd
, table
, p
, pi
);
4437 bgp_dest_unlock_node(pdest
);
4439 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4440 && (safi
== SAFI_UNICAST
)) {
4441 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4443 * Implicit withdraw case.
4445 ++vnc_implicit_withdraw
;
4446 vnc_import_bgp_del_route(bgp
, p
, pi
);
4447 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
4452 /* Special handling for EVPN update of an existing route. If the
4453 * extended community attribute has changed, we need to
4455 * the route using its existing extended community. It will be
4456 * subsequently processed for import with the new extended
4459 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
4462 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
4464 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4467 cmp
= ecommunity_cmp(
4468 bgp_attr_get_ecommunity(pi
->attr
),
4469 bgp_attr_get_ecommunity(attr_new
));
4471 if (bgp_debug_update(peer
, p
, NULL
, 1))
4473 "Change in EXT-COMM, existing %s new %s",
4475 bgp_attr_get_ecommunity(
4478 bgp_attr_get_ecommunity(
4480 if (safi
== SAFI_EVPN
)
4481 bgp_evpn_unimport_route(
4482 bgp
, afi
, safi
, p
, pi
);
4483 else /* SAFI_MPLS_VPN */
4484 vpn_leak_to_vrf_withdraw(pi
);
4489 /* Update to new attribute. */
4490 bgp_attr_unintern(&pi
->attr
);
4491 pi
->attr
= attr_new
;
4493 /* Update MPLS label */
4494 if (has_valid_label
) {
4495 extra
= bgp_path_info_extra_get(pi
);
4496 if (extra
->label
!= label
) {
4497 memcpy(&extra
->label
, label
,
4498 num_labels
* sizeof(mpls_label_t
));
4499 extra
->num_labels
= num_labels
;
4501 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4502 bgp_set_valid_label(&extra
->label
[0]);
4505 /* Update SRv6 SID */
4506 if (attr
->srv6_l3vpn
) {
4507 extra
= bgp_path_info_extra_get(pi
);
4508 if (sid_diff(&extra
->sid
[0].sid
,
4509 &attr
->srv6_l3vpn
->sid
)) {
4510 sid_copy(&extra
->sid
[0].sid
,
4511 &attr
->srv6_l3vpn
->sid
);
4512 extra
->num_sids
= 1;
4514 extra
->sid
[0].loc_block_len
= 0;
4515 extra
->sid
[0].loc_node_len
= 0;
4516 extra
->sid
[0].func_len
= 0;
4517 extra
->sid
[0].arg_len
= 0;
4518 extra
->sid
[0].transposition_len
= 0;
4519 extra
->sid
[0].transposition_offset
= 0;
4521 if (attr
->srv6_l3vpn
->loc_block_len
!= 0) {
4522 extra
->sid
[0].loc_block_len
=
4523 attr
->srv6_l3vpn
->loc_block_len
;
4524 extra
->sid
[0].loc_node_len
=
4525 attr
->srv6_l3vpn
->loc_node_len
;
4526 extra
->sid
[0].func_len
=
4527 attr
->srv6_l3vpn
->func_len
;
4528 extra
->sid
[0].arg_len
=
4529 attr
->srv6_l3vpn
->arg_len
;
4530 extra
->sid
[0].transposition_len
=
4532 ->transposition_len
;
4533 extra
->sid
[0].transposition_offset
=
4535 ->transposition_offset
;
4538 } else if (attr
->srv6_vpn
) {
4539 extra
= bgp_path_info_extra_get(pi
);
4540 if (sid_diff(&extra
->sid
[0].sid
,
4541 &attr
->srv6_vpn
->sid
)) {
4542 sid_copy(&extra
->sid
[0].sid
,
4543 &attr
->srv6_vpn
->sid
);
4544 extra
->num_sids
= 1;
4548 #ifdef ENABLE_BGP_VNC
4549 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4550 && (safi
== SAFI_UNICAST
)) {
4551 if (vnc_implicit_withdraw
) {
4553 * Add back the route with its new attributes
4555 * The route is still selected, until the route
4557 * queued by bgp_process actually runs. We have
4559 * update to the VNC side immediately to avoid
4561 * configuration changes (e.g., route-map
4563 * trigger re-importation of the entire RIB.
4565 vnc_import_bgp_add_route(bgp
, p
, pi
);
4566 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4571 /* Update bgp route dampening information. */
4572 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4573 && peer
->sort
== BGP_PEER_EBGP
) {
4574 /* Now we do normal update dampening. */
4575 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4576 if (ret
== BGP_DAMP_SUPPRESSED
) {
4577 bgp_dest_unlock_node(dest
);
4582 /* Nexthop reachability check - for unicast and
4583 * labeled-unicast.. */
4584 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4585 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4586 || (safi
== SAFI_EVPN
&&
4587 bgp_evpn_is_prefix_nht_supported(p
))) {
4588 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4589 && peer
->ttl
== BGP_DEFAULT_TTL
4590 && !CHECK_FLAG(peer
->flags
,
4591 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4592 && !CHECK_FLAG(bgp
->flags
,
4593 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4598 struct bgp
*bgp_nexthop
= bgp
;
4600 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4601 bgp_nexthop
= pi
->extra
->bgp_orig
;
4603 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4605 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4606 safi
, pi
, NULL
, connected
,
4607 bgp_nht_param_prefix
) ||
4608 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4609 bgp_path_info_set_flag(dest
, pi
,
4612 if (BGP_DEBUG(nht
, NHT
)) {
4613 zlog_debug("%s(%pI4): NH unresolved",
4615 (in_addr_t
*)&attr_new
->nexthop
);
4617 bgp_path_info_unset_flag(dest
, pi
,
4622 bgp_path_info_set_flag(dest
, pi
,
4623 BGP_PATH_ACCEPT_OWN
);
4625 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4628 #ifdef ENABLE_BGP_VNC
4629 if (safi
== SAFI_MPLS_VPN
) {
4630 struct bgp_dest
*pdest
= NULL
;
4631 struct bgp_table
*table
= NULL
;
4633 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4634 (struct prefix
*)prd
);
4635 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4636 table
= bgp_dest_get_bgp_table_info(pdest
);
4638 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4639 bgp
, prd
, table
, p
, pi
);
4641 bgp_dest_unlock_node(pdest
);
4645 /* If this is an EVPN route and some attribute has changed,
4646 * or we are explicitly told to perform a route import, process
4647 * route for import. If the extended community has changed, we
4649 * have done the un-import earlier and the import would result
4651 * route getting injected into appropriate L2 VNIs. If it is
4653 * some other attribute change, the import will result in
4655 * the attributes for the route in the VNI(s).
4657 if (safi
== SAFI_EVPN
&&
4658 (!same_attr
|| force_evpn_import
) &&
4659 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4660 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4662 /* Process change. */
4663 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4665 bgp_process(bgp
, dest
, afi
, safi
);
4666 bgp_dest_unlock_node(dest
);
4668 if (SAFI_UNICAST
== safi
4669 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4670 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4672 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4674 if ((SAFI_MPLS_VPN
== safi
)
4675 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4676 leak_success
= vpn_leak_to_vrf_update(bgp
, pi
, prd
);
4679 #ifdef ENABLE_BGP_VNC
4680 if (SAFI_MPLS_VPN
== safi
) {
4681 mpls_label_t label_decoded
= decode_label(label
);
4683 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4684 type
, sub_type
, &label_decoded
);
4686 if (SAFI_ENCAP
== safi
) {
4687 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4688 type
, sub_type
, NULL
);
4691 if ((safi
== SAFI_MPLS_VPN
) &&
4692 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4693 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4695 bgp_unlink_nexthop(pi
);
4696 bgp_path_info_delete(dest
, pi
);
4699 } // End of implicit withdraw
4701 /* Received Logging. */
4702 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4703 if (!peer
->rcvd_attr_printed
) {
4704 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4705 peer
->rcvd_attr_str
);
4706 peer
->rcvd_attr_printed
= 1;
4709 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4710 addpath_id
? 1 : 0, addpath_id
, evpn
,
4711 pfx_buf
, sizeof(pfx_buf
));
4712 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4715 /* Make new BGP info. */
4716 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4718 /* Update MPLS label */
4719 if (has_valid_label
) {
4720 extra
= bgp_path_info_extra_get(new);
4721 if (extra
->label
!= label
) {
4722 memcpy(&extra
->label
, label
,
4723 num_labels
* sizeof(mpls_label_t
));
4724 extra
->num_labels
= num_labels
;
4726 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4727 bgp_set_valid_label(&extra
->label
[0]);
4730 /* Update SRv6 SID */
4731 if (safi
== SAFI_MPLS_VPN
) {
4732 extra
= bgp_path_info_extra_get(new);
4733 if (attr
->srv6_l3vpn
) {
4734 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_l3vpn
->sid
);
4735 extra
->num_sids
= 1;
4737 extra
->sid
[0].loc_block_len
=
4738 attr
->srv6_l3vpn
->loc_block_len
;
4739 extra
->sid
[0].loc_node_len
=
4740 attr
->srv6_l3vpn
->loc_node_len
;
4741 extra
->sid
[0].func_len
= attr
->srv6_l3vpn
->func_len
;
4742 extra
->sid
[0].arg_len
= attr
->srv6_l3vpn
->arg_len
;
4743 extra
->sid
[0].transposition_len
=
4744 attr
->srv6_l3vpn
->transposition_len
;
4745 extra
->sid
[0].transposition_offset
=
4746 attr
->srv6_l3vpn
->transposition_offset
;
4747 } else if (attr
->srv6_vpn
) {
4748 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_vpn
->sid
);
4749 extra
->num_sids
= 1;
4753 /* Nexthop reachability check. */
4754 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4755 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4756 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4757 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4758 && peer
->ttl
== BGP_DEFAULT_TTL
4759 && !CHECK_FLAG(peer
->flags
,
4760 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4761 && !CHECK_FLAG(bgp
->flags
,
4762 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4767 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4769 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4770 connected
, bgp_nht_param_prefix
) ||
4771 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4772 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4774 if (BGP_DEBUG(nht
, NHT
))
4775 zlog_debug("%s(%pI4): NH unresolved", __func__
,
4776 &attr_new
->nexthop
);
4777 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4781 bgp_path_info_set_flag(dest
, new, BGP_PATH_ACCEPT_OWN
);
4783 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4786 /* If maximum prefix count is configured and current prefix
4789 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0)) {
4790 reason
= "maximum-prefix overflow";
4791 bgp_attr_flush(&new_attr
);
4796 new->addpath_rx_id
= addpath_id
;
4798 /* Increment prefix */
4799 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4801 /* Register new BGP information. */
4802 bgp_path_info_add(dest
, new);
4804 /* route_node_get lock */
4805 bgp_dest_unlock_node(dest
);
4807 #ifdef ENABLE_BGP_VNC
4808 if (safi
== SAFI_MPLS_VPN
) {
4809 struct bgp_dest
*pdest
= NULL
;
4810 struct bgp_table
*table
= NULL
;
4812 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4813 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4814 table
= bgp_dest_get_bgp_table_info(pdest
);
4816 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4817 bgp
, prd
, table
, p
, new);
4819 bgp_dest_unlock_node(pdest
);
4823 /* If this is an EVPN route, process for import. */
4824 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4825 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4827 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4829 /* Process change. */
4830 bgp_process(bgp
, dest
, afi
, safi
);
4832 if (SAFI_UNICAST
== safi
4833 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4834 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4835 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4837 if ((SAFI_MPLS_VPN
== safi
)
4838 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4839 leak_success
= vpn_leak_to_vrf_update(bgp
, new, prd
);
4841 #ifdef ENABLE_BGP_VNC
4842 if (SAFI_MPLS_VPN
== safi
) {
4843 mpls_label_t label_decoded
= decode_label(label
);
4845 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4846 sub_type
, &label_decoded
);
4848 if (SAFI_ENCAP
== safi
) {
4849 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4853 if ((safi
== SAFI_MPLS_VPN
) &&
4854 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4855 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4857 bgp_unlink_nexthop(new);
4858 bgp_path_info_delete(dest
, new);
4863 /* This BGP update is filtered. Log the reason then update BGP
4867 bgp_unlink_nexthop(new);
4868 bgp_path_info_delete(dest
, new);
4869 bgp_path_info_extra_free(&new->extra
);
4870 XFREE(MTYPE_BGP_ROUTE
, new);
4873 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4875 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4876 if (!peer
->rcvd_attr_printed
) {
4877 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4878 peer
->rcvd_attr_str
);
4879 peer
->rcvd_attr_printed
= 1;
4882 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4883 addpath_id
? 1 : 0, addpath_id
, evpn
,
4884 pfx_buf
, sizeof(pfx_buf
));
4885 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4886 peer
, pfx_buf
, reason
);
4890 /* If this is an EVPN route, un-import it as it is now filtered.
4892 if (safi
== SAFI_EVPN
)
4893 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4895 if (SAFI_UNICAST
== safi
4896 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4897 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4899 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4901 if ((SAFI_MPLS_VPN
== safi
)
4902 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4904 vpn_leak_to_vrf_withdraw(pi
);
4907 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4910 bgp_dest_unlock_node(dest
);
4912 #ifdef ENABLE_BGP_VNC
4914 * Filtered update is treated as an implicit withdrawal (see
4916 * a few lines above)
4918 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4919 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4927 void bgp_withdraw(struct peer
*peer
, const struct prefix
*p
,
4928 uint32_t addpath_id
, afi_t afi
, safi_t safi
, int type
,
4929 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4930 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4933 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4934 struct bgp_dest
*dest
;
4935 struct bgp_path_info
*pi
;
4937 #ifdef ENABLE_BGP_VNC
4938 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4939 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4947 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4949 /* If peer is soft reconfiguration enabled. Record input packet for
4950 * further calculation.
4952 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4953 * routes that are filtered. This tanks out Quagga RS pretty badly due
4955 * the iteration over all RS clients.
4956 * Since we need to remove the entry from adj_in anyway, do that first
4958 * if there was no entry, we don't need to do anything more.
4960 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4961 && peer
!= bgp
->peer_self
)
4962 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4963 peer
->stat_pfx_dup_withdraw
++;
4965 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4966 bgp_debug_rdpfxpath2str(
4967 afi
, safi
, prd
, p
, label
, num_labels
,
4968 addpath_id
? 1 : 0, addpath_id
, NULL
,
4969 pfx_buf
, sizeof(pfx_buf
));
4971 "%s withdrawing route %s not in adj-in",
4972 peer
->host
, pfx_buf
);
4974 bgp_dest_unlock_node(dest
);
4978 /* Lookup withdrawn route. */
4979 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4980 if (pi
->peer
== peer
&& pi
->type
== type
4981 && pi
->sub_type
== sub_type
4982 && pi
->addpath_rx_id
== addpath_id
)
4986 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4987 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4988 addpath_id
? 1 : 0, addpath_id
, NULL
,
4989 pfx_buf
, sizeof(pfx_buf
));
4990 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer
,
4994 /* Withdraw specified route from routing table. */
4995 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4996 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4997 if (SAFI_UNICAST
== safi
4998 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4999 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5000 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5002 if ((SAFI_MPLS_VPN
== safi
)
5003 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5005 vpn_leak_to_vrf_withdraw(pi
);
5007 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
5008 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
5009 addpath_id
? 1 : 0, addpath_id
, NULL
,
5010 pfx_buf
, sizeof(pfx_buf
));
5011 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
5014 /* Unlock bgp_node_get() lock. */
5015 bgp_dest_unlock_node(dest
);
5020 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
5023 struct update_subgroup
*subgrp
;
5024 subgrp
= peer_subgroup(peer
, afi
, safi
);
5025 subgroup_default_originate(subgrp
, withdraw
);
5030 * bgp_stop_announce_route_timer
5032 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
5034 if (!paf
->t_announce_route
)
5037 EVENT_OFF(paf
->t_announce_route
);
5041 * bgp_announce_route_timer_expired
5043 * Callback that is invoked when the route announcement timer for a
5046 static void bgp_announce_route_timer_expired(struct event
*t
)
5048 struct peer_af
*paf
;
5054 if (!peer_established(peer
))
5057 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
5060 peer_af_announce_route(paf
, 1);
5062 /* Notify BGP conditional advertisement scanner percess */
5063 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
5067 * bgp_announce_route
5069 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
5071 * if force is true we will force an update even if the update
5072 * limiting code is attempted to kick in.
5074 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
, bool force
)
5076 struct peer_af
*paf
;
5077 struct update_subgroup
*subgrp
;
5079 paf
= peer_af_find(peer
, afi
, safi
);
5082 subgrp
= PAF_SUBGRP(paf
);
5085 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5086 * or a refresh has already been triggered.
5088 if (!subgrp
|| paf
->t_announce_route
)
5092 SET_FLAG(subgrp
->sflags
, SUBGRP_STATUS_FORCE_UPDATES
);
5095 * Start a timer to stagger/delay the announce. This serves
5096 * two purposes - announcement can potentially be combined for
5097 * multiple peers and the announcement doesn't happen in the
5100 event_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
5101 (subgrp
->peer_count
== 1)
5102 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5103 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
5104 &paf
->t_announce_route
);
5108 * Announce routes from all AF tables to a peer.
5110 * This should ONLY be called when there is a need to refresh the
5111 * routes to the peer based on a policy change for this peer alone
5112 * or a route refresh request received from the peer.
5113 * The operation will result in splitting the peer from its existing
5114 * subgroups and putting it in new subgroups.
5116 void bgp_announce_route_all(struct peer
*peer
)
5121 FOREACH_AFI_SAFI (afi
, safi
)
5122 bgp_announce_route(peer
, afi
, safi
, false);
5125 /* Flag or unflag bgp_dest to determine whether it should be treated by
5126 * bgp_soft_reconfig_table_task.
5127 * Flag if flag is true. Unflag if flag is false.
5129 static void bgp_soft_reconfig_table_flag(struct bgp_table
*table
, bool flag
)
5131 struct bgp_dest
*dest
;
5132 struct bgp_adj_in
*ain
;
5137 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5138 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5139 if (ain
->peer
!= NULL
)
5142 if (flag
&& ain
!= NULL
&& ain
->peer
!= NULL
)
5143 SET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5145 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5149 static void bgp_soft_reconfig_table_update(struct peer
*peer
,
5150 struct bgp_dest
*dest
,
5151 struct bgp_adj_in
*ain
, afi_t afi
,
5152 safi_t safi
, struct prefix_rd
*prd
)
5154 struct bgp_path_info
*pi
;
5155 uint32_t num_labels
= 0;
5156 mpls_label_t
*label_pnt
= NULL
;
5157 struct bgp_route_evpn evpn
;
5159 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5160 if (pi
->peer
== peer
)
5163 if (pi
&& pi
->extra
)
5164 num_labels
= pi
->extra
->num_labels
;
5166 label_pnt
= &pi
->extra
->label
[0];
5168 memcpy(&evpn
, bgp_attr_get_evpn_overlay(pi
->attr
),
5171 memset(&evpn
, 0, sizeof(evpn
));
5173 bgp_update(peer
, bgp_dest_get_prefix(dest
), ain
->addpath_rx_id
,
5174 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, prd
,
5175 label_pnt
, num_labels
, 1, &evpn
);
5178 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5179 struct bgp_table
*table
,
5180 struct prefix_rd
*prd
)
5182 struct bgp_dest
*dest
;
5183 struct bgp_adj_in
*ain
;
5186 table
= peer
->bgp
->rib
[afi
][safi
];
5188 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5189 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5190 if (ain
->peer
!= peer
)
5193 bgp_soft_reconfig_table_update(peer
, dest
, ain
, afi
,
5198 /* Do soft reconfig table per bgp table.
5199 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5200 * when BGP_NODE_SOFT_RECONFIG is set,
5201 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5202 * Schedule a new thread to continue the job.
5203 * Without splitting the full job into several part,
5204 * vtysh waits for the job to finish before responding to a BGP command
5206 static void bgp_soft_reconfig_table_task(struct event
*thread
)
5208 uint32_t iter
, max_iter
;
5209 struct bgp_dest
*dest
;
5210 struct bgp_adj_in
*ain
;
5212 struct bgp_table
*table
;
5213 struct prefix_rd
*prd
;
5214 struct listnode
*node
, *nnode
;
5216 table
= EVENT_ARG(thread
);
5219 max_iter
= SOFT_RECONFIG_TASK_MAX_PREFIX
;
5220 if (table
->soft_reconfig_init
) {
5221 /* first call of the function with a new srta structure.
5222 * Don't do any treatment this time on nodes
5223 * in order vtysh to respond quickly
5228 for (iter
= 0, dest
= bgp_table_top(table
); (dest
&& iter
< max_iter
);
5229 dest
= bgp_route_next(dest
)) {
5230 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
))
5233 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5235 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5236 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
,
5238 if (ain
->peer
!= peer
)
5241 bgp_soft_reconfig_table_update(
5242 peer
, dest
, ain
, table
->afi
,
5249 /* we're either starting the initial iteration,
5250 * or we're going to continue an ongoing iteration
5252 if (dest
|| table
->soft_reconfig_init
) {
5253 table
->soft_reconfig_init
= false;
5254 event_add_event(bm
->master
, bgp_soft_reconfig_table_task
, table
,
5255 0, &table
->soft_reconfig_thread
);
5258 /* we're done, clean up the background iteration context info and
5259 schedule route annoucement
5261 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
, peer
)) {
5262 listnode_delete(table
->soft_reconfig_peers
, peer
);
5263 bgp_announce_route(peer
, table
->afi
, table
->safi
, false);
5266 list_delete(&table
->soft_reconfig_peers
);
5270 /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5272 * - bgp cannot be NULL
5273 * - if table and peer are NULL, cancel all threads within the bgp instance
5274 * - if table is NULL and peer is not,
5275 * remove peer in all threads within the bgp instance
5276 * - if peer is NULL, cancel all threads matching table within the bgp instance
5278 void bgp_soft_reconfig_table_task_cancel(const struct bgp
*bgp
,
5279 const struct bgp_table
*table
,
5280 const struct peer
*peer
)
5283 struct listnode
*node
, *nnode
;
5285 struct bgp_table
*ntable
;
5290 FOREACH_AFI_SAFI (afi
, safi
) {
5291 ntable
= bgp
->rib
[afi
][safi
];
5294 if (table
&& table
!= ntable
)
5297 for (ALL_LIST_ELEMENTS(ntable
->soft_reconfig_peers
, node
, nnode
,
5299 if (peer
&& peer
!= npeer
)
5301 listnode_delete(ntable
->soft_reconfig_peers
, npeer
);
5304 if (!ntable
->soft_reconfig_peers
5305 || !list_isempty(ntable
->soft_reconfig_peers
))
5308 list_delete(&ntable
->soft_reconfig_peers
);
5309 bgp_soft_reconfig_table_flag(ntable
, false);
5310 EVENT_OFF(ntable
->soft_reconfig_thread
);
5315 * Returns false if the peer is not configured for soft reconfig in
5317 bool bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5319 struct bgp_dest
*dest
;
5320 struct bgp_table
*table
;
5321 struct listnode
*node
, *nnode
;
5323 struct peer_af
*paf
;
5325 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
))
5328 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
5329 && (safi
!= SAFI_EVPN
)) {
5330 table
= peer
->bgp
->rib
[afi
][safi
];
5334 table
->soft_reconfig_init
= true;
5336 if (!table
->soft_reconfig_peers
)
5337 table
->soft_reconfig_peers
= list_new();
5339 /* add peer to the table soft_reconfig_peers if not already
5342 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
,
5348 listnode_add(table
->soft_reconfig_peers
, peer
);
5350 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5351 * on table would start back at the beginning.
5353 bgp_soft_reconfig_table_flag(table
, true);
5355 if (!table
->soft_reconfig_thread
)
5356 event_add_event(bm
->master
,
5357 bgp_soft_reconfig_table_task
, table
, 0,
5358 &table
->soft_reconfig_thread
);
5359 /* Cancel bgp_announce_route_timer_expired threads.
5360 * bgp_announce_route_timer_expired threads have been scheduled
5361 * to announce routes as soon as the soft_reconfigure process
5363 * In this case, soft_reconfigure is also scheduled by using
5364 * a thread but is planned after the
5365 * bgp_announce_route_timer_expired threads. It means that,
5366 * without cancelling the threads, the route announcement task
5367 * would run before the soft reconfiguration one. That would
5368 * useless and would block vtysh during several seconds. Route
5369 * announcements are rescheduled as soon as the soft_reconfigure
5372 paf
= peer_af_find(peer
, afi
, safi
);
5374 bgp_stop_announce_route_timer(paf
);
5376 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5377 dest
= bgp_route_next(dest
)) {
5378 table
= bgp_dest_get_bgp_table_info(dest
);
5383 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5384 struct prefix_rd prd
;
5386 prd
.family
= AF_UNSPEC
;
5388 memcpy(&prd
.val
, p
->u
.val
, 8);
5390 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
5397 struct bgp_clear_node_queue
{
5398 struct bgp_dest
*dest
;
5401 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
5403 struct bgp_clear_node_queue
*cnq
= data
;
5404 struct bgp_dest
*dest
= cnq
->dest
;
5405 struct peer
*peer
= wq
->spec
.data
;
5406 struct bgp_path_info
*pi
;
5408 afi_t afi
= bgp_dest_table(dest
)->afi
;
5409 safi_t safi
= bgp_dest_table(dest
)->safi
;
5411 assert(dest
&& peer
);
5414 /* It is possible that we have multiple paths for a prefix from a peer
5415 * if that peer is using AddPath.
5417 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5418 if (pi
->peer
!= peer
)
5421 /* graceful restart STALE flag set. */
5422 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
5423 && peer
->nsf
[afi
][safi
])
5424 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5425 PEER_STATUS_ENHANCED_REFRESH
))
5426 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5427 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
5428 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
5430 /* If this is an EVPN route, process for
5432 if (safi
== SAFI_EVPN
)
5433 bgp_evpn_unimport_route(
5435 bgp_dest_get_prefix(dest
), pi
);
5436 /* Handle withdraw for VRF route-leaking and L3VPN */
5437 if (SAFI_UNICAST
== safi
5438 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
5439 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5440 vpn_leak_from_vrf_withdraw(bgp_get_default(),
5443 if (SAFI_MPLS_VPN
== safi
&&
5444 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5445 vpn_leak_to_vrf_withdraw(pi
);
5448 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5454 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
5456 struct bgp_clear_node_queue
*cnq
= data
;
5457 struct bgp_dest
*dest
= cnq
->dest
;
5458 struct bgp_table
*table
= bgp_dest_table(dest
);
5460 bgp_dest_unlock_node(dest
);
5461 bgp_table_unlock(table
);
5462 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
5465 static void bgp_clear_node_complete(struct work_queue
*wq
)
5467 struct peer
*peer
= wq
->spec
.data
;
5469 /* Tickle FSM to start moving again */
5470 BGP_EVENT_ADD(peer
, Clearing_Completed
);
5472 peer_unlock(peer
); /* bgp_clear_route */
5475 static void bgp_clear_node_queue_init(struct peer
*peer
)
5477 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5479 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
5480 #undef CLEAR_QUEUE_NAME_LEN
5482 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
5483 peer
->clear_node_queue
->spec
.hold
= 10;
5484 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
5485 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
5486 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
5487 peer
->clear_node_queue
->spec
.max_retries
= 0;
5489 /* we only 'lock' this peer reference when the queue is actually active
5491 peer
->clear_node_queue
->spec
.data
= peer
;
5494 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5495 struct bgp_table
*table
)
5497 struct bgp_dest
*dest
;
5498 int force
= peer
->bgp
->process_queue
? 0 : 1;
5501 table
= peer
->bgp
->rib
[afi
][safi
];
5503 /* If still no table => afi/safi isn't configured at all or smth. */
5507 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5508 struct bgp_path_info
*pi
, *next
;
5509 struct bgp_adj_in
*ain
;
5510 struct bgp_adj_in
*ain_next
;
5512 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5513 * queued for every clearing peer, regardless of whether it is
5514 * relevant to the peer at hand.
5516 * Overview: There are 3 different indices which need to be
5517 * scrubbed, potentially, when a peer is removed:
5519 * 1 peer's routes visible via the RIB (ie accepted routes)
5520 * 2 peer's routes visible by the (optional) peer's adj-in index
5521 * 3 other routes visible by the peer's adj-out index
5523 * 3 there is no hurry in scrubbing, once the struct peer is
5524 * removed from bgp->peer, we could just GC such deleted peer's
5525 * adj-outs at our leisure.
5527 * 1 and 2 must be 'scrubbed' in some way, at least made
5528 * invisible via RIB index before peer session is allowed to be
5529 * brought back up. So one needs to know when such a 'search' is
5534 * - there'd be a single global queue or a single RIB walker
5535 * - rather than tracking which route_nodes still need to be
5536 * examined on a peer basis, we'd track which peers still
5539 * Given that our per-peer prefix-counts now should be reliable,
5540 * this may actually be achievable. It doesn't seem to be a huge
5541 * problem at this time,
5543 * It is possible that we have multiple paths for a prefix from
5545 * if that peer is using AddPath.
5549 ain_next
= ain
->next
;
5551 if (ain
->peer
== peer
)
5552 bgp_adj_in_remove(dest
, ain
);
5557 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5559 if (pi
->peer
!= peer
)
5563 bgp_path_info_reap(dest
, pi
);
5565 struct bgp_clear_node_queue
*cnq
;
5567 /* both unlocked in bgp_clear_node_queue_del */
5568 bgp_table_lock(bgp_dest_table(dest
));
5569 bgp_dest_lock_node(dest
);
5571 MTYPE_BGP_CLEAR_NODE_QUEUE
,
5572 sizeof(struct bgp_clear_node_queue
));
5574 work_queue_add(peer
->clear_node_queue
, cnq
);
5582 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5584 struct bgp_dest
*dest
;
5585 struct bgp_table
*table
;
5587 if (peer
->clear_node_queue
== NULL
)
5588 bgp_clear_node_queue_init(peer
);
5590 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5591 * Idle until it receives a Clearing_Completed event. This protects
5592 * against peers which flap faster than we can we clear, which could
5595 * a) race with routes from the new session being installed before
5596 * clear_route_node visits the node (to delete the route of that
5598 * b) resource exhaustion, clear_route_node likely leads to an entry
5599 * on the process_main queue. Fast-flapping could cause that queue
5603 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5604 * the unlock will happen upon work-queue completion; other wise, the
5605 * unlock happens at the end of this function.
5607 if (!peer
->clear_node_queue
->thread
)
5610 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
5611 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
5613 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5614 dest
= bgp_route_next(dest
)) {
5615 table
= bgp_dest_get_bgp_table_info(dest
);
5619 bgp_clear_route_table(peer
, afi
, safi
, table
);
5622 /* unlock if no nodes got added to the clear-node-queue. */
5623 if (!peer
->clear_node_queue
->thread
)
5627 void bgp_clear_route_all(struct peer
*peer
)
5632 FOREACH_AFI_SAFI (afi
, safi
)
5633 bgp_clear_route(peer
, afi
, safi
);
5635 #ifdef ENABLE_BGP_VNC
5636 rfapiProcessPeerDown(peer
);
5640 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5642 struct bgp_table
*table
;
5643 struct bgp_dest
*dest
;
5644 struct bgp_adj_in
*ain
;
5645 struct bgp_adj_in
*ain_next
;
5647 table
= peer
->bgp
->rib
[afi
][safi
];
5649 /* It is possible that we have multiple paths for a prefix from a peer
5650 * if that peer is using AddPath.
5652 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5656 ain_next
= ain
->next
;
5658 if (ain
->peer
== peer
)
5659 bgp_adj_in_remove(dest
, ain
);
5666 /* If any of the routes from the peer have been marked with the NO_LLGR
5667 * community, either as sent by the peer, or as the result of a configured
5668 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5669 * operation of [RFC4271].
5671 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5673 struct bgp_dest
*dest
;
5674 struct bgp_path_info
*pi
;
5675 struct bgp_table
*table
;
5677 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5678 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5679 dest
= bgp_route_next(dest
)) {
5680 struct bgp_dest
*rm
;
5682 /* look for neighbor in tables */
5683 table
= bgp_dest_get_bgp_table_info(dest
);
5687 for (rm
= bgp_table_top(table
); rm
;
5688 rm
= bgp_route_next(rm
))
5689 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
5691 if (pi
->peer
!= peer
)
5694 peer
->af_sflags
[afi
][safi
],
5695 PEER_STATUS_LLGR_WAIT
) &&
5696 bgp_attr_get_community(pi
->attr
) &&
5698 bgp_attr_get_community(
5702 if (!CHECK_FLAG(pi
->flags
,
5707 * If this is VRF leaked route
5708 * process for withdraw.
5711 BGP_ROUTE_IMPORTED
&&
5712 peer
->bgp
->inst_type
==
5713 BGP_INSTANCE_TYPE_DEFAULT
)
5714 vpn_leak_to_vrf_withdraw(pi
);
5716 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
5721 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5722 dest
= bgp_route_next(dest
))
5723 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5725 if (pi
->peer
!= peer
)
5727 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5728 PEER_STATUS_LLGR_WAIT
) &&
5729 bgp_attr_get_community(pi
->attr
) &&
5731 bgp_attr_get_community(pi
->attr
),
5734 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
5736 if (safi
== SAFI_UNICAST
&&
5737 (peer
->bgp
->inst_type
==
5738 BGP_INSTANCE_TYPE_VRF
||
5739 peer
->bgp
->inst_type
==
5740 BGP_INSTANCE_TYPE_DEFAULT
))
5741 vpn_leak_from_vrf_withdraw(
5742 bgp_get_default(), peer
->bgp
,
5745 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5751 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5753 struct bgp_dest
*dest
, *ndest
;
5754 struct bgp_path_info
*pi
;
5755 struct bgp_table
*table
;
5757 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5758 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5759 dest
= bgp_route_next(dest
)) {
5760 table
= bgp_dest_get_bgp_table_info(dest
);
5764 for (ndest
= bgp_table_top(table
); ndest
;
5765 ndest
= bgp_route_next(ndest
)) {
5766 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5768 if (pi
->peer
!= peer
)
5772 peer
->af_sflags
[afi
][safi
],
5773 PEER_STATUS_ENHANCED_REFRESH
))
5774 && !CHECK_FLAG(pi
->flags
,
5778 BGP_PATH_UNUSEABLE
)) {
5779 if (bgp_debug_neighbor_events(
5782 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5786 bgp_dest_get_prefix(
5789 bgp_path_info_set_flag(
5797 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5798 dest
= bgp_route_next(dest
)) {
5799 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5801 if (pi
->peer
!= peer
)
5804 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5805 PEER_STATUS_ENHANCED_REFRESH
))
5806 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5807 && !CHECK_FLAG(pi
->flags
,
5808 BGP_PATH_UNUSEABLE
)) {
5809 if (bgp_debug_neighbor_events(peer
))
5811 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5814 bgp_dest_get_prefix(
5817 bgp_path_info_set_flag(dest
, pi
,
5825 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5827 if (peer
->sort
== BGP_PEER_IBGP
)
5830 if (peer
->sort
== BGP_PEER_EBGP
5831 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5832 || FILTER_LIST_OUT_NAME(filter
)
5833 || DISTRIBUTE_OUT_NAME(filter
)))
5838 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5840 if (peer
->sort
== BGP_PEER_IBGP
)
5843 if (peer
->sort
== BGP_PEER_EBGP
5844 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5845 || FILTER_LIST_IN_NAME(filter
)
5846 || DISTRIBUTE_IN_NAME(filter
)))
5851 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5854 struct bgp_dest
*dest
;
5855 struct bgp_path_info
*pi
;
5856 struct bgp_path_info
*next
;
5858 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5859 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5860 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5864 /* Unimport EVPN routes from VRFs */
5865 if (safi
== SAFI_EVPN
)
5866 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5869 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5870 && pi
->type
== ZEBRA_ROUTE_BGP
5871 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5872 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5873 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5875 if (bgp_fibupd_safi(safi
))
5876 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5879 bgp_path_info_reap(dest
, pi
);
5883 /* Delete all kernel routes. */
5884 void bgp_cleanup_routes(struct bgp
*bgp
)
5887 struct bgp_dest
*dest
;
5888 struct bgp_table
*table
;
5890 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5891 if (afi
== AFI_L2VPN
)
5893 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5896 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5898 if (afi
!= AFI_L2VPN
) {
5900 safi
= SAFI_MPLS_VPN
;
5901 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5902 dest
= bgp_route_next(dest
)) {
5903 table
= bgp_dest_get_bgp_table_info(dest
);
5904 if (table
!= NULL
) {
5905 bgp_cleanup_table(bgp
, table
, safi
);
5906 bgp_table_finish(&table
);
5907 bgp_dest_set_bgp_table_info(dest
, NULL
);
5908 bgp_dest_unlock_node(dest
);
5912 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5913 dest
= bgp_route_next(dest
)) {
5914 table
= bgp_dest_get_bgp_table_info(dest
);
5915 if (table
!= NULL
) {
5916 bgp_cleanup_table(bgp
, table
, safi
);
5917 bgp_table_finish(&table
);
5918 bgp_dest_set_bgp_table_info(dest
, NULL
);
5919 bgp_dest_unlock_node(dest
);
5924 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5925 dest
= bgp_route_next(dest
)) {
5926 table
= bgp_dest_get_bgp_table_info(dest
);
5927 if (table
!= NULL
) {
5928 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5929 bgp_table_finish(&table
);
5930 bgp_dest_set_bgp_table_info(dest
, NULL
);
5931 bgp_dest_unlock_node(dest
);
5936 void bgp_reset(void)
5939 bgp_zclient_reset();
5940 access_list_reset();
5941 prefix_list_reset();
5944 bool bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5946 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5947 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5948 PEER_CAP_ADDPATH_AF_TX_RCV
));
5951 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5953 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5954 struct bgp_nlri
*packet
)
5962 bool addpath_capable
;
5963 uint32_t addpath_id
;
5966 lim
= pnt
+ packet
->length
;
5968 safi
= packet
->safi
;
5970 addpath_capable
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5972 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5973 syntactic validity. If the field is syntactically incorrect,
5974 then the Error Subcode is set to Invalid Network Field. */
5975 for (; pnt
< lim
; pnt
+= psize
) {
5976 /* Clear prefix structure. */
5977 memset(&p
, 0, sizeof(p
));
5979 if (addpath_capable
) {
5981 /* When packet overflow occurs return immediately. */
5982 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5983 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5985 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5986 addpath_id
= ntohl(addpath_id
);
5987 pnt
+= BGP_ADDPATH_ID_LEN
;
5990 /* Fetch prefix length. */
5991 p
.prefixlen
= *pnt
++;
5992 /* afi/safi validity already verified by caller,
5993 * bgp_update_receive */
5994 p
.family
= afi2family(afi
);
5996 /* Prefix length check. */
5997 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
6000 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
6001 peer
->host
, p
.prefixlen
, packet
->afi
);
6002 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
6005 /* Packet size overflow check. */
6006 psize
= PSIZE(p
.prefixlen
);
6008 /* When packet overflow occur return immediately. */
6009 if (pnt
+ psize
> lim
) {
6012 "%s [Error] Update packet error (prefix length %d overflows packet)",
6013 peer
->host
, p
.prefixlen
);
6014 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
6017 /* Defensive coding, double-check the psize fits in a struct
6018 * prefix for the v4 and v6 afi's and unicast/multicast */
6019 if (psize
> (ssize_t
)sizeof(p
.u
.val
)) {
6022 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
6023 peer
->host
, p
.prefixlen
, sizeof(p
.u
.val
));
6024 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6027 /* Fetch prefix from NLRI packet. */
6028 memcpy(p
.u
.val
, pnt
, psize
);
6030 /* Check address. */
6031 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
6032 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
6033 /* From RFC4271 Section 6.3:
6035 * If a prefix in the NLRI field is semantically
6037 * (e.g., an unexpected multicast IP address),
6039 * be logged locally, and the prefix SHOULD be
6044 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6045 peer
->host
, &p
.u
.prefix4
);
6050 /* Check address. */
6051 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
6052 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6055 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6056 peer
->host
, &p
.u
.prefix6
);
6060 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
6063 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6064 peer
->host
, &p
.u
.prefix6
);
6070 /* Normal process. */
6072 bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
6073 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
,
6076 bgp_withdraw(peer
, &p
, addpath_id
, afi
, safi
,
6077 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
,
6080 /* Do not send BGP notification twice when maximum-prefix count
6082 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
6083 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
6086 /* Packet length consistency check. */
6090 "%s [Error] Update packet error (prefix length mismatch with total length)",
6092 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6095 return BGP_NLRI_PARSE_OK
;
6098 static struct bgp_static
*bgp_static_new(void)
6100 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
6103 static void bgp_static_free(struct bgp_static
*bgp_static
)
6105 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6106 route_map_counter_decrement(bgp_static
->rmap
.map
);
6108 if (bgp_static
->prd_pretty
)
6109 XFREE(MTYPE_BGP
, bgp_static
->prd_pretty
);
6110 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
6111 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
6114 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
6115 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
6117 struct bgp_dest
*dest
;
6118 struct bgp_path_info
*pi
;
6119 struct bgp_path_info
*new;
6120 struct bgp_path_info rmap_path
;
6122 struct attr
*attr_new
;
6123 route_map_result_t ret
;
6124 #ifdef ENABLE_BGP_VNC
6125 int vnc_implicit_withdraw
= 0;
6130 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6132 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6134 attr
.nexthop
= bgp_static
->igpnexthop
;
6135 attr
.med
= bgp_static
->igpmetric
;
6136 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6139 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
6141 if (bgp_static
->igpmetric
)
6142 bgp_attr_set_aigp_metric(&attr
, bgp_static
->igpmetric
);
6144 if (bgp_static
->atomic
)
6145 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
6147 /* Store label index, if required. */
6148 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
6149 attr
.label_index
= bgp_static
->label_index
;
6150 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
6153 /* Apply route-map. */
6154 if (bgp_static
->rmap
.name
) {
6155 struct attr attr_tmp
= attr
;
6157 memset(&rmap_path
, 0, sizeof(rmap_path
));
6158 rmap_path
.peer
= bgp
->peer_self
;
6159 rmap_path
.attr
= &attr_tmp
;
6161 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6163 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6165 bgp
->peer_self
->rmap_type
= 0;
6167 if (ret
== RMAP_DENYMATCH
) {
6168 /* Free uninterned attribute. */
6169 bgp_attr_flush(&attr_tmp
);
6171 /* Unintern original. */
6172 aspath_unintern(&attr
.aspath
);
6173 bgp_static_withdraw(bgp
, p
, afi
, safi
);
6174 bgp_dest_unlock_node(dest
);
6178 if (bgp_in_graceful_shutdown(bgp
))
6179 bgp_attr_add_gshut_community(&attr_tmp
);
6181 attr_new
= bgp_attr_intern(&attr_tmp
);
6184 if (bgp_in_graceful_shutdown(bgp
))
6185 bgp_attr_add_gshut_community(&attr
);
6187 attr_new
= bgp_attr_intern(&attr
);
6190 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6191 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6192 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6196 if (attrhash_cmp(pi
->attr
, attr_new
)
6197 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
6198 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
6199 bgp_dest_unlock_node(dest
);
6200 bgp_attr_unintern(&attr_new
);
6201 aspath_unintern(&attr
.aspath
);
6204 /* The attribute is changed. */
6205 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6207 /* Rewrite BGP route information. */
6208 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6209 bgp_path_info_restore(dest
, pi
);
6211 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6212 #ifdef ENABLE_BGP_VNC
6213 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6214 && (safi
== SAFI_UNICAST
)) {
6215 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
6217 * Implicit withdraw case.
6218 * We have to do this before pi is
6221 ++vnc_implicit_withdraw
;
6222 vnc_import_bgp_del_route(bgp
, p
, pi
);
6223 vnc_import_bgp_exterior_del_route(
6228 bgp_attr_unintern(&pi
->attr
);
6229 pi
->attr
= attr_new
;
6230 pi
->uptime
= monotime(NULL
);
6231 #ifdef ENABLE_BGP_VNC
6232 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6233 && (safi
== SAFI_UNICAST
)) {
6234 if (vnc_implicit_withdraw
) {
6235 vnc_import_bgp_add_route(bgp
, p
, pi
);
6236 vnc_import_bgp_exterior_add_route(
6242 /* Nexthop reachability check. */
6243 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6244 && (safi
== SAFI_UNICAST
6245 || safi
== SAFI_LABELED_UNICAST
)) {
6247 struct bgp
*bgp_nexthop
= bgp
;
6249 if (pi
->extra
&& pi
->extra
->bgp_orig
)
6250 bgp_nexthop
= pi
->extra
->bgp_orig
;
6252 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
6253 afi
, safi
, pi
, NULL
,
6255 bgp_path_info_set_flag(dest
, pi
,
6258 if (BGP_DEBUG(nht
, NHT
)) {
6259 char buf1
[INET6_ADDRSTRLEN
];
6260 inet_ntop(p
->family
,
6264 "%s(%s): Route not in table, not advertising",
6267 bgp_path_info_unset_flag(
6268 dest
, pi
, BGP_PATH_VALID
);
6271 /* Delete the NHT structure if any, if we're
6273 * enabling/disabling import check. We
6274 * deregister the route
6275 * from NHT to avoid overloading NHT and the
6276 * process interaction
6278 bgp_unlink_nexthop(pi
);
6279 bgp_path_info_set_flag(dest
, pi
,
6282 /* Process change. */
6283 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6284 bgp_process(bgp
, dest
, afi
, safi
);
6286 if (SAFI_UNICAST
== safi
6287 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6289 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6290 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
6294 bgp_dest_unlock_node(dest
);
6295 aspath_unintern(&attr
.aspath
);
6300 /* Make new BGP info. */
6301 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6303 /* Nexthop reachability check. */
6304 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6305 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
6306 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0,
6308 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6310 if (BGP_DEBUG(nht
, NHT
)) {
6311 char buf1
[INET6_ADDRSTRLEN
];
6313 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
6316 "%s(%s): Route not in table, not advertising",
6319 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
6322 /* Delete the NHT structure if any, if we're toggling between
6323 * enabling/disabling import check. We deregister the route
6324 * from NHT to avoid overloading NHT and the process interaction
6326 bgp_unlink_nexthop(new);
6328 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6331 /* Aggregate address increment. */
6332 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6334 /* Register new BGP information. */
6335 bgp_path_info_add(dest
, new);
6337 /* route_node_get lock */
6338 bgp_dest_unlock_node(dest
);
6340 /* Process change. */
6341 bgp_process(bgp
, dest
, afi
, safi
);
6343 if (SAFI_UNICAST
== safi
6344 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6345 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6346 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6349 /* Unintern original. */
6350 aspath_unintern(&attr
.aspath
);
6353 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6356 struct bgp_dest
*dest
;
6357 struct bgp_path_info
*pi
;
6359 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6361 /* Check selected route and self inserted route. */
6362 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6363 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6364 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6367 /* Withdraw static BGP route from routing table. */
6369 if (SAFI_UNICAST
== safi
6370 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6371 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6372 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
6374 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6375 bgp_unlink_nexthop(pi
);
6376 bgp_path_info_delete(dest
, pi
);
6377 bgp_process(bgp
, dest
, afi
, safi
);
6380 /* Unlock bgp_node_lookup. */
6381 bgp_dest_unlock_node(dest
);
6385 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6387 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
6388 afi_t afi
, safi_t safi
,
6389 struct prefix_rd
*prd
)
6391 struct bgp_dest
*dest
;
6392 struct bgp_path_info
*pi
;
6394 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
6396 /* Check selected route and self inserted route. */
6397 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6398 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6399 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6402 /* Withdraw static BGP route from routing table. */
6404 #ifdef ENABLE_BGP_VNC
6405 rfapiProcessWithdraw(
6406 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
6407 1); /* Kill, since it is an administrative change */
6409 if (SAFI_MPLS_VPN
== safi
6410 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6411 vpn_leak_to_vrf_withdraw(pi
);
6413 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6414 bgp_path_info_delete(dest
, pi
);
6415 bgp_process(bgp
, dest
, afi
, safi
);
6418 /* Unlock bgp_node_lookup. */
6419 bgp_dest_unlock_node(dest
);
6422 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
6423 struct bgp_static
*bgp_static
, afi_t afi
,
6426 struct bgp_dest
*dest
;
6427 struct bgp_path_info
*new;
6428 struct attr
*attr_new
;
6429 struct attr attr
= {0};
6430 struct bgp_path_info
*pi
;
6431 #ifdef ENABLE_BGP_VNC
6432 mpls_label_t label
= 0;
6434 uint32_t num_labels
= 0;
6438 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
6440 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
6443 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6445 attr
.nexthop
= bgp_static
->igpnexthop
;
6446 attr
.med
= bgp_static
->igpmetric
;
6447 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6449 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
6450 || (safi
== SAFI_ENCAP
)) {
6451 if (afi
== AFI_IP
) {
6452 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
6453 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
6456 if (afi
== AFI_L2VPN
) {
6457 if (bgp_static
->gatewayIp
.family
== AF_INET
) {
6458 SET_IPADDR_V4(&attr
.evpn_overlay
.gw_ip
);
6459 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v4
,
6460 &bgp_static
->gatewayIp
.u
.prefix4
,
6462 } else if (bgp_static
->gatewayIp
.family
== AF_INET6
) {
6463 SET_IPADDR_V6(&attr
.evpn_overlay
.gw_ip
);
6464 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v6
,
6465 &bgp_static
->gatewayIp
.u
.prefix6
,
6468 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
6469 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
6470 struct bgp_encap_type_vxlan bet
;
6471 memset(&bet
, 0, sizeof(bet
));
6472 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
6473 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
6475 if (bgp_static
->router_mac
) {
6476 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
6479 /* Apply route-map. */
6480 if (bgp_static
->rmap
.name
) {
6481 struct attr attr_tmp
= attr
;
6482 struct bgp_path_info rmap_path
;
6483 route_map_result_t ret
;
6485 rmap_path
.peer
= bgp
->peer_self
;
6486 rmap_path
.attr
= &attr_tmp
;
6488 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6490 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6492 bgp
->peer_self
->rmap_type
= 0;
6494 if (ret
== RMAP_DENYMATCH
) {
6495 /* Free uninterned attribute. */
6496 bgp_attr_flush(&attr_tmp
);
6498 /* Unintern original. */
6499 aspath_unintern(&attr
.aspath
);
6500 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
6502 bgp_dest_unlock_node(dest
);
6506 attr_new
= bgp_attr_intern(&attr_tmp
);
6508 attr_new
= bgp_attr_intern(&attr
);
6511 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6512 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6513 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6517 if (attrhash_cmp(pi
->attr
, attr_new
)
6518 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
6519 bgp_dest_unlock_node(dest
);
6520 bgp_attr_unintern(&attr_new
);
6521 aspath_unintern(&attr
.aspath
);
6524 /* The attribute is changed. */
6525 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6527 /* Rewrite BGP route information. */
6528 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6529 bgp_path_info_restore(dest
, pi
);
6531 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6532 bgp_attr_unintern(&pi
->attr
);
6533 pi
->attr
= attr_new
;
6534 pi
->uptime
= monotime(NULL
);
6535 #ifdef ENABLE_BGP_VNC
6537 label
= decode_label(&pi
->extra
->label
[0]);
6540 /* Process change. */
6541 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6542 bgp_process(bgp
, dest
, afi
, safi
);
6544 if (SAFI_MPLS_VPN
== safi
6545 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6546 vpn_leak_to_vrf_update(bgp
, pi
,
6549 #ifdef ENABLE_BGP_VNC
6550 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
6551 pi
->attr
, afi
, safi
, pi
->type
,
6552 pi
->sub_type
, &label
);
6554 bgp_dest_unlock_node(dest
);
6555 aspath_unintern(&attr
.aspath
);
6561 /* Make new BGP info. */
6562 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6564 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6565 bgp_path_info_extra_get(new);
6567 new->extra
->label
[0] = bgp_static
->label
;
6568 new->extra
->num_labels
= num_labels
;
6570 #ifdef ENABLE_BGP_VNC
6571 label
= decode_label(&bgp_static
->label
);
6574 /* Aggregate address increment. */
6575 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6577 /* Register new BGP information. */
6578 bgp_path_info_add(dest
, new);
6579 /* route_node_get lock */
6580 bgp_dest_unlock_node(dest
);
6582 /* Process change. */
6583 bgp_process(bgp
, dest
, afi
, safi
);
6585 if (SAFI_MPLS_VPN
== safi
6586 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6587 vpn_leak_to_vrf_update(bgp
, new, &bgp_static
->prd
);
6589 #ifdef ENABLE_BGP_VNC
6590 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6591 safi
, new->type
, new->sub_type
, &label
);
6594 /* Unintern original. */
6595 aspath_unintern(&attr
.aspath
);
6598 /* Configure static BGP network. When user don't run zebra, static
6599 route should be installed as valid. */
6600 static int bgp_static_set(struct vty
*vty
, const char *negate
,
6601 const char *ip_str
, afi_t afi
, safi_t safi
,
6602 const char *rmap
, int backdoor
, uint32_t label_index
)
6604 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6607 struct bgp_static
*bgp_static
;
6608 struct bgp_dest
*dest
;
6609 uint8_t need_update
= 0;
6611 /* Convert IP prefix string to struct prefix. */
6612 ret
= str2prefix(ip_str
, &p
);
6614 vty_out(vty
, "%% Malformed prefix\n");
6615 return CMD_WARNING_CONFIG_FAILED
;
6617 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6618 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
6619 return CMD_WARNING_CONFIG_FAILED
;
6626 /* Set BGP static route configuration. */
6627 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6630 vty_out(vty
, "%% Can't find static route specified\n");
6631 return CMD_WARNING_CONFIG_FAILED
;
6634 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6636 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6637 && (label_index
!= bgp_static
->label_index
)) {
6639 "%% label-index doesn't match static route\n");
6640 bgp_dest_unlock_node(dest
);
6641 return CMD_WARNING_CONFIG_FAILED
;
6644 if ((rmap
&& bgp_static
->rmap
.name
)
6645 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6647 "%% route-map name doesn't match static route\n");
6648 bgp_dest_unlock_node(dest
);
6649 return CMD_WARNING_CONFIG_FAILED
;
6652 /* Update BGP RIB. */
6653 if (!bgp_static
->backdoor
)
6654 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6656 /* Clear configuration. */
6657 bgp_static_free(bgp_static
);
6658 bgp_dest_set_bgp_static_info(dest
, NULL
);
6659 bgp_dest_unlock_node(dest
);
6660 bgp_dest_unlock_node(dest
);
6663 /* Set BGP static route configuration. */
6664 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6665 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6667 /* Configuration change. */
6668 /* Label index cannot be changed. */
6669 if (bgp_static
->label_index
!= label_index
) {
6670 vty_out(vty
, "%% cannot change label-index\n");
6671 bgp_dest_unlock_node(dest
);
6672 return CMD_WARNING_CONFIG_FAILED
;
6675 /* Check previous routes are installed into BGP. */
6676 if (bgp_static
->valid
6677 && bgp_static
->backdoor
!= backdoor
)
6680 bgp_static
->backdoor
= backdoor
;
6683 XFREE(MTYPE_ROUTE_MAP_NAME
,
6684 bgp_static
->rmap
.name
);
6685 route_map_counter_decrement(
6686 bgp_static
->rmap
.map
);
6687 bgp_static
->rmap
.name
=
6688 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6689 bgp_static
->rmap
.map
=
6690 route_map_lookup_by_name(rmap
);
6691 route_map_counter_increment(
6692 bgp_static
->rmap
.map
);
6694 XFREE(MTYPE_ROUTE_MAP_NAME
,
6695 bgp_static
->rmap
.name
);
6696 route_map_counter_decrement(
6697 bgp_static
->rmap
.map
);
6698 bgp_static
->rmap
.map
= NULL
;
6699 bgp_static
->valid
= 0;
6701 bgp_dest_unlock_node(dest
);
6703 /* New configuration. */
6704 bgp_static
= bgp_static_new();
6705 bgp_static
->backdoor
= backdoor
;
6706 bgp_static
->valid
= 0;
6707 bgp_static
->igpmetric
= 0;
6708 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6709 bgp_static
->label_index
= label_index
;
6712 XFREE(MTYPE_ROUTE_MAP_NAME
,
6713 bgp_static
->rmap
.name
);
6714 route_map_counter_decrement(
6715 bgp_static
->rmap
.map
);
6716 bgp_static
->rmap
.name
=
6717 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6718 bgp_static
->rmap
.map
=
6719 route_map_lookup_by_name(rmap
);
6720 route_map_counter_increment(
6721 bgp_static
->rmap
.map
);
6723 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6726 bgp_static
->valid
= 1;
6728 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6730 if (!bgp_static
->backdoor
)
6731 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6737 void bgp_static_add(struct bgp
*bgp
)
6741 struct bgp_dest
*dest
;
6742 struct bgp_dest
*rm
;
6743 struct bgp_table
*table
;
6744 struct bgp_static
*bgp_static
;
6746 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6747 FOREACH_AFI_SAFI (afi
, safi
)
6748 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6749 dest
= bgp_route_next(dest
)) {
6750 if (!bgp_dest_has_bgp_path_info_data(dest
))
6753 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6754 || (safi
== SAFI_EVPN
)) {
6755 table
= bgp_dest_get_bgp_table_info(dest
);
6757 for (rm
= bgp_table_top(table
); rm
;
6758 rm
= bgp_route_next(rm
)) {
6760 bgp_dest_get_bgp_static_info(
6762 bgp_static_update_safi(
6763 bgp
, bgp_dest_get_prefix(rm
),
6764 bgp_static
, afi
, safi
);
6768 bgp
, bgp_dest_get_prefix(dest
),
6769 bgp_dest_get_bgp_static_info(dest
), afi
,
6773 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6776 /* Called from bgp_delete(). Delete all static routes from the BGP
6778 void bgp_static_delete(struct bgp
*bgp
)
6782 struct bgp_dest
*dest
;
6783 struct bgp_dest
*rm
;
6784 struct bgp_table
*table
;
6785 struct bgp_static
*bgp_static
;
6787 FOREACH_AFI_SAFI (afi
, safi
)
6788 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6789 dest
= bgp_route_next(dest
)) {
6790 if (!bgp_dest_has_bgp_path_info_data(dest
))
6793 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6794 || (safi
== SAFI_EVPN
)) {
6795 table
= bgp_dest_get_bgp_table_info(dest
);
6797 for (rm
= bgp_table_top(table
); rm
;
6798 rm
= bgp_route_next(rm
)) {
6800 bgp_dest_get_bgp_static_info(
6805 bgp_static_withdraw_safi(
6806 bgp
, bgp_dest_get_prefix(rm
),
6808 (struct prefix_rd
*)
6809 bgp_dest_get_prefix(
6811 bgp_static_free(bgp_static
);
6812 bgp_dest_set_bgp_static_info(rm
,
6814 bgp_dest_unlock_node(rm
);
6817 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6818 bgp_static_withdraw(bgp
,
6819 bgp_dest_get_prefix(dest
),
6821 bgp_static_free(bgp_static
);
6822 bgp_dest_set_bgp_static_info(dest
, NULL
);
6823 bgp_dest_unlock_node(dest
);
6828 void bgp_static_redo_import_check(struct bgp
*bgp
)
6832 struct bgp_dest
*dest
;
6833 struct bgp_dest
*rm
;
6834 struct bgp_table
*table
;
6835 struct bgp_static
*bgp_static
;
6837 /* Use this flag to force reprocessing of the route */
6838 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6839 FOREACH_AFI_SAFI (afi
, safi
) {
6840 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6841 dest
= bgp_route_next(dest
)) {
6842 if (!bgp_dest_has_bgp_path_info_data(dest
))
6845 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6846 || (safi
== SAFI_EVPN
)) {
6847 table
= bgp_dest_get_bgp_table_info(dest
);
6849 for (rm
= bgp_table_top(table
); rm
;
6850 rm
= bgp_route_next(rm
)) {
6852 bgp_dest_get_bgp_static_info(
6854 bgp_static_update_safi(
6855 bgp
, bgp_dest_get_prefix(rm
),
6856 bgp_static
, afi
, safi
);
6859 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6860 bgp_static_update(bgp
,
6861 bgp_dest_get_prefix(dest
),
6862 bgp_static
, afi
, safi
);
6866 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6869 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6872 struct bgp_table
*table
;
6873 struct bgp_dest
*dest
;
6874 struct bgp_path_info
*pi
;
6876 /* Do not install the aggregate route if BGP is in the
6877 * process of termination.
6879 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6880 || (bgp
->peer_self
== NULL
))
6883 table
= bgp
->rib
[afi
][safi
];
6884 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6885 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6886 if (pi
->peer
== bgp
->peer_self
6887 && ((pi
->type
== ZEBRA_ROUTE_BGP
6888 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6889 || (pi
->type
!= ZEBRA_ROUTE_BGP
6891 == BGP_ROUTE_REDISTRIBUTE
))) {
6892 bgp_aggregate_decrement(
6893 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6895 bgp_unlink_nexthop(pi
);
6896 bgp_path_info_delete(dest
, pi
);
6897 bgp_process(bgp
, dest
, afi
, safi
);
6904 * Purge all networks and redistributed routes from routing table.
6905 * Invoked upon the instance going down.
6907 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6912 FOREACH_AFI_SAFI (afi
, safi
)
6913 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6918 * Currently this is used to set static routes for VPN and ENCAP.
6919 * I think it can probably be factored with bgp_static_set.
6921 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6922 const char *ip_str
, const char *rd_str
,
6923 const char *label_str
, const char *rmap_str
,
6924 int evpn_type
, const char *esi
, const char *gwip
,
6925 const char *ethtag
, const char *routermac
)
6927 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6930 struct prefix_rd prd
;
6931 struct bgp_dest
*pdest
;
6932 struct bgp_dest
*dest
;
6933 struct bgp_table
*table
;
6934 struct bgp_static
*bgp_static
;
6935 mpls_label_t label
= MPLS_INVALID_LABEL
;
6936 struct prefix gw_ip
;
6938 /* validate ip prefix */
6939 ret
= str2prefix(ip_str
, &p
);
6941 vty_out(vty
, "%% Malformed prefix\n");
6942 return CMD_WARNING_CONFIG_FAILED
;
6945 if ((afi
== AFI_L2VPN
)
6946 && (bgp_build_evpn_prefix(evpn_type
,
6947 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6948 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6949 return CMD_WARNING_CONFIG_FAILED
;
6952 ret
= str2prefix_rd(rd_str
, &prd
);
6954 vty_out(vty
, "%% Malformed rd\n");
6955 return CMD_WARNING_CONFIG_FAILED
;
6959 unsigned long label_val
;
6960 label_val
= strtoul(label_str
, NULL
, 10);
6961 encode_label(label_val
, &label
);
6964 if (safi
== SAFI_EVPN
) {
6965 if (esi
&& str2esi(esi
, NULL
) == 0) {
6966 vty_out(vty
, "%% Malformed ESI\n");
6967 return CMD_WARNING_CONFIG_FAILED
;
6969 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6970 vty_out(vty
, "%% Malformed Router MAC\n");
6971 return CMD_WARNING_CONFIG_FAILED
;
6974 memset(&gw_ip
, 0, sizeof(gw_ip
));
6975 ret
= str2prefix(gwip
, &gw_ip
);
6977 vty_out(vty
, "%% Malformed GatewayIp\n");
6978 return CMD_WARNING_CONFIG_FAILED
;
6980 if ((gw_ip
.family
== AF_INET
6981 && is_evpn_prefix_ipaddr_v6(
6982 (struct prefix_evpn
*)&p
))
6983 || (gw_ip
.family
== AF_INET6
6984 && is_evpn_prefix_ipaddr_v4(
6985 (struct prefix_evpn
*)&p
))) {
6987 "%% GatewayIp family differs with IP prefix\n");
6988 return CMD_WARNING_CONFIG_FAILED
;
6992 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6993 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6994 bgp_dest_set_bgp_table_info(pdest
,
6995 bgp_table_init(bgp
, afi
, safi
));
6996 table
= bgp_dest_get_bgp_table_info(pdest
);
6998 dest
= bgp_node_get(table
, &p
);
7000 if (bgp_dest_has_bgp_path_info_data(dest
)) {
7001 vty_out(vty
, "%% Same network configuration exists\n");
7002 bgp_dest_unlock_node(dest
);
7004 /* New configuration. */
7005 bgp_static
= bgp_static_new();
7006 bgp_static
->backdoor
= 0;
7007 bgp_static
->valid
= 0;
7008 bgp_static
->igpmetric
= 0;
7009 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
7010 bgp_static
->label
= label
;
7011 bgp_static
->prd
= prd
;
7014 bgp_static
->prd_pretty
= XSTRDUP(MTYPE_BGP
, rd_str
);
7016 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
7017 route_map_counter_decrement(bgp_static
->rmap
.map
);
7018 bgp_static
->rmap
.name
=
7019 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
7020 bgp_static
->rmap
.map
=
7021 route_map_lookup_by_name(rmap_str
);
7022 route_map_counter_increment(bgp_static
->rmap
.map
);
7025 if (safi
== SAFI_EVPN
) {
7027 bgp_static
->eth_s_id
=
7030 str2esi(esi
, bgp_static
->eth_s_id
);
7033 bgp_static
->router_mac
=
7034 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
7035 (void)prefix_str2mac(routermac
,
7036 bgp_static
->router_mac
);
7039 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
7041 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
7043 bgp_static
->valid
= 1;
7044 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
7050 /* Configure static BGP network. */
7051 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
7052 const char *ip_str
, const char *rd_str
,
7053 const char *label_str
, int evpn_type
, const char *esi
,
7054 const char *gwip
, const char *ethtag
)
7056 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7059 struct prefix_rd prd
;
7060 struct bgp_dest
*pdest
;
7061 struct bgp_dest
*dest
;
7062 struct bgp_table
*table
;
7063 struct bgp_static
*bgp_static
;
7064 mpls_label_t label
= MPLS_INVALID_LABEL
;
7066 /* Convert IP prefix string to struct prefix. */
7067 ret
= str2prefix(ip_str
, &p
);
7069 vty_out(vty
, "%% Malformed prefix\n");
7070 return CMD_WARNING_CONFIG_FAILED
;
7073 if ((afi
== AFI_L2VPN
)
7074 && (bgp_build_evpn_prefix(evpn_type
,
7075 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
7076 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
7077 return CMD_WARNING_CONFIG_FAILED
;
7079 ret
= str2prefix_rd(rd_str
, &prd
);
7081 vty_out(vty
, "%% Malformed rd\n");
7082 return CMD_WARNING_CONFIG_FAILED
;
7086 unsigned long label_val
;
7087 label_val
= strtoul(label_str
, NULL
, 10);
7088 encode_label(label_val
, &label
);
7091 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7092 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7093 bgp_dest_set_bgp_table_info(pdest
,
7094 bgp_table_init(bgp
, afi
, safi
));
7096 bgp_dest_unlock_node(pdest
);
7097 table
= bgp_dest_get_bgp_table_info(pdest
);
7099 dest
= bgp_node_lookup(table
, &p
);
7102 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
7104 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
7105 bgp_static_free(bgp_static
);
7106 bgp_dest_set_bgp_static_info(dest
, NULL
);
7107 bgp_dest_unlock_node(dest
);
7108 bgp_dest_unlock_node(dest
);
7110 vty_out(vty
, "%% Can't find the route\n");
7115 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
7116 const char *rmap_name
)
7118 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7119 struct bgp_rmap
*rmap
;
7121 rmap
= &bgp
->table_map
[afi
][safi
];
7123 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7124 route_map_counter_decrement(rmap
->map
);
7125 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
7126 rmap
->map
= route_map_lookup_by_name(rmap_name
);
7127 route_map_counter_increment(rmap
->map
);
7129 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7130 route_map_counter_decrement(rmap
->map
);
7134 if (bgp_fibupd_safi(safi
))
7135 bgp_zebra_announce_table(bgp
, afi
, safi
);
7140 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
7141 const char *rmap_name
)
7143 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7144 struct bgp_rmap
*rmap
;
7146 rmap
= &bgp
->table_map
[afi
][safi
];
7147 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7148 route_map_counter_decrement(rmap
->map
);
7151 if (bgp_fibupd_safi(safi
))
7152 bgp_zebra_announce_table(bgp
, afi
, safi
);
7157 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
7160 if (bgp
->table_map
[afi
][safi
].name
) {
7161 vty_out(vty
, " table-map %s\n",
7162 bgp
->table_map
[afi
][safi
].name
);
7166 DEFUN (bgp_table_map
,
7169 "BGP table to RIB route download filter\n"
7170 "Name of the route map\n")
7173 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7174 argv
[idx_word
]->arg
);
7176 DEFUN (no_bgp_table_map
,
7177 no_bgp_table_map_cmd
,
7178 "no table-map WORD",
7180 "BGP table to RIB route download filter\n"
7181 "Name of the route map\n")
7184 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7185 argv
[idx_word
]->arg
);
7191 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
7192 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
7193 backdoor$backdoor}]",
7195 "Specify a network to announce via BGP\n"
7200 "Route-map to modify the attributes\n"
7201 "Name of the route map\n"
7202 "Label index to associate with the prefix\n"
7203 "Label index value\n"
7204 "Specify a BGP backdoor route\n")
7206 char addr_prefix_str
[BUFSIZ
];
7211 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
7213 sizeof(addr_prefix_str
));
7215 vty_out(vty
, "%% Inconsistent address and mask\n");
7216 return CMD_WARNING_CONFIG_FAILED
;
7220 return bgp_static_set(
7221 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
7222 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
7223 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7226 DEFPY(ipv6_bgp_network
,
7227 ipv6_bgp_network_cmd
,
7228 "[no] network X:X::X:X/M$prefix \
7229 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
7231 "Specify a network to announce via BGP\n"
7233 "Route-map to modify the attributes\n"
7234 "Name of the route map\n"
7235 "Label index to associate with the prefix\n"
7236 "Label index value\n")
7238 return bgp_static_set(
7239 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
7240 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7243 static struct bgp_aggregate
*bgp_aggregate_new(void)
7245 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
7248 void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
7250 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7251 route_map_counter_decrement(aggregate
->suppress_map
);
7252 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7253 route_map_counter_decrement(aggregate
->rmap
.map
);
7254 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
7258 * Helper function to avoid repeated code: prepare variables for a
7259 * `route_map_apply` call.
7261 * \returns `true` on route map match, otherwise `false`.
7263 static bool aggr_suppress_map_test(struct bgp
*bgp
,
7264 struct bgp_aggregate
*aggregate
,
7265 struct bgp_path_info
*pi
)
7267 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
7268 route_map_result_t rmr
= RMAP_DENYMATCH
;
7269 struct bgp_path_info rmap_path
= {};
7270 struct attr attr
= {};
7272 /* No route map entries created, just don't match. */
7273 if (aggregate
->suppress_map
== NULL
)
7276 /* Call route map matching and return result. */
7277 attr
.aspath
= aspath_empty(bgp
->asnotation
);
7278 rmap_path
.peer
= bgp
->peer_self
;
7279 rmap_path
.attr
= &attr
;
7281 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
7282 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
7283 bgp
->peer_self
->rmap_type
= 0;
7285 bgp_attr_flush(&attr
);
7286 aspath_unintern(&attr
.aspath
);
7288 return rmr
== RMAP_PERMITMATCH
;
7291 /** Test whether the aggregation has suppressed this path or not. */
7292 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
7293 struct bgp_path_info
*pi
)
7295 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
7298 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
7302 * Suppress this path and keep the reference.
7304 * \returns `true` if needs processing otherwise `false`.
7306 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
7307 struct bgp_path_info
*pi
)
7309 struct bgp_path_info_extra
*pie
;
7311 /* Path is already suppressed by this aggregation. */
7312 if (aggr_suppress_exists(aggregate
, pi
))
7315 pie
= bgp_path_info_extra_get(pi
);
7317 /* This is the first suppression, allocate memory and list it. */
7318 if (pie
->aggr_suppressors
== NULL
)
7319 pie
->aggr_suppressors
= list_new();
7321 listnode_add(pie
->aggr_suppressors
, aggregate
);
7323 /* Only mark for processing if suppressed. */
7324 if (listcount(pie
->aggr_suppressors
) == 1) {
7325 if (BGP_DEBUG(update
, UPDATE_OUT
))
7326 zlog_debug("aggregate-address suppressing: %pFX",
7327 bgp_dest_get_prefix(pi
->net
));
7329 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7337 * Unsuppress this path and remove the reference.
7339 * \returns `true` if needs processing otherwise `false`.
7341 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
7342 struct bgp_path_info
*pi
)
7344 /* Path wasn't suppressed. */
7345 if (!aggr_suppress_exists(aggregate
, pi
))
7348 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
7350 /* Unsuppress and free extra memory if last item. */
7351 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
7352 if (BGP_DEBUG(update
, UPDATE_OUT
))
7353 zlog_debug("aggregate-address unsuppressing: %pFX",
7354 bgp_dest_get_prefix(pi
->net
));
7356 list_delete(&pi
->extra
->aggr_suppressors
);
7357 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7364 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
7365 struct aspath
*aspath
,
7366 struct community
*comm
,
7367 struct ecommunity
*ecomm
,
7368 struct lcommunity
*lcomm
)
7370 static struct aspath
*ae
= NULL
;
7371 enum asnotation_mode asnotation
;
7373 asnotation
= bgp_get_asnotation(NULL
);
7376 ae
= aspath_empty(asnotation
);
7381 if (origin
!= pi
->attr
->origin
)
7384 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
7387 if (!community_cmp(bgp_attr_get_community(pi
->attr
), comm
))
7390 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi
->attr
), ecomm
))
7393 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi
->attr
), lcomm
))
7396 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
7402 static void bgp_aggregate_install(
7403 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
7404 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
7405 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
7406 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
7408 struct bgp_dest
*dest
;
7409 struct bgp_table
*table
;
7410 struct bgp_path_info
*pi
, *orig
, *new;
7413 table
= bgp
->rib
[afi
][safi
];
7415 dest
= bgp_node_get(table
, p
);
7417 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7418 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
7419 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7423 * If we have paths with different MEDs, then don't install
7424 * (or uninstall) the aggregate route.
7426 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
7427 goto uninstall_aggregate_route
;
7429 if (aggregate
->count
> 0) {
7431 * If the aggregate information has not changed
7432 * no need to re-install it again.
7434 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
7435 ecommunity
, lcommunity
)) {
7436 bgp_dest_unlock_node(dest
);
7439 aspath_free(aspath
);
7441 community_free(&community
);
7443 ecommunity_free(&ecommunity
);
7445 lcommunity_free(&lcommunity
);
7451 * Mark the old as unusable
7454 bgp_path_info_delete(dest
, pi
);
7456 attr
= bgp_attr_aggregate_intern(
7457 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
7458 aggregate
, atomic_aggregate
, p
);
7461 aspath_free(aspath
);
7462 community_free(&community
);
7463 ecommunity_free(&ecommunity
);
7464 lcommunity_free(&lcommunity
);
7465 bgp_dest_unlock_node(dest
);
7466 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
7467 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
7468 zlog_debug("%s: %pFX null attribute", __func__
,
7473 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
7474 bgp
->peer_self
, attr
, dest
);
7476 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7478 bgp_path_info_add(dest
, new);
7479 bgp_process(bgp
, dest
, afi
, safi
);
7481 uninstall_aggregate_route
:
7482 for (pi
= orig
; pi
; pi
= pi
->next
)
7483 if (pi
->peer
== bgp
->peer_self
7484 && pi
->type
== ZEBRA_ROUTE_BGP
7485 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7488 /* Withdraw static BGP route from routing table. */
7490 bgp_path_info_delete(dest
, pi
);
7491 bgp_process(bgp
, dest
, afi
, safi
);
7495 bgp_dest_unlock_node(dest
);
7499 * Check if the current path has different MED than other known paths.
7501 * \returns `true` if the MED matched the others else `false`.
7503 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
7504 struct bgp
*bgp
, struct bgp_path_info
*pi
)
7506 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
7508 /* This is the first route being analyzed. */
7509 if (!aggregate
->med_initialized
) {
7510 aggregate
->med_initialized
= true;
7511 aggregate
->med_mismatched
= false;
7512 aggregate
->med_matched_value
= cur_med
;
7514 /* Check if routes with different MED showed up. */
7515 if (cur_med
!= aggregate
->med_matched_value
)
7516 aggregate
->med_mismatched
= true;
7519 return !aggregate
->med_mismatched
;
7523 * Initializes and tests all routes in the aggregate address path for MED
7526 * \returns `true` if all MEDs are the same otherwise `false`.
7528 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
7529 struct bgp
*bgp
, const struct prefix
*p
,
7530 afi_t afi
, safi_t safi
)
7532 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7533 const struct prefix
*dest_p
;
7534 struct bgp_dest
*dest
, *top
;
7535 struct bgp_path_info
*pi
;
7536 bool med_matched
= true;
7538 aggregate
->med_initialized
= false;
7540 top
= bgp_node_get(table
, p
);
7541 for (dest
= bgp_node_get(table
, p
); dest
;
7542 dest
= bgp_route_next_until(dest
, top
)) {
7543 dest_p
= bgp_dest_get_prefix(dest
);
7544 if (dest_p
->prefixlen
<= p
->prefixlen
)
7547 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7548 if (BGP_PATH_HOLDDOWN(pi
))
7550 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7552 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
7553 med_matched
= false;
7560 bgp_dest_unlock_node(top
);
7566 * Toggles the route suppression status for this aggregate address
7569 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
7570 struct bgp
*bgp
, const struct prefix
*p
,
7571 afi_t afi
, safi_t safi
, bool suppress
)
7573 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7574 const struct prefix
*dest_p
;
7575 struct bgp_dest
*dest
, *top
;
7576 struct bgp_path_info
*pi
;
7577 bool toggle_suppression
;
7579 /* We've found a different MED we must revert any suppressed routes. */
7580 top
= bgp_node_get(table
, p
);
7581 for (dest
= bgp_node_get(table
, p
); dest
;
7582 dest
= bgp_route_next_until(dest
, top
)) {
7583 dest_p
= bgp_dest_get_prefix(dest
);
7584 if (dest_p
->prefixlen
<= p
->prefixlen
)
7587 toggle_suppression
= false;
7588 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7589 if (BGP_PATH_HOLDDOWN(pi
))
7591 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7594 /* We are toggling suppression back. */
7596 /* Suppress route if not suppressed already. */
7597 if (aggr_suppress_path(aggregate
, pi
))
7598 toggle_suppression
= true;
7602 /* Install route if there is no more suppression. */
7603 if (aggr_unsuppress_path(aggregate
, pi
))
7604 toggle_suppression
= true;
7607 if (toggle_suppression
)
7608 bgp_process(bgp
, dest
, afi
, safi
);
7610 bgp_dest_unlock_node(top
);
7614 * Aggregate address MED matching incremental test: this function is called
7615 * when the initial aggregation occurred and we are only testing a single
7618 * In addition to testing and setting the MED validity it also installs back
7619 * suppressed routes (if summary is configured).
7621 * Must not be called in `bgp_aggregate_route`.
7623 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7624 struct bgp
*bgp
, const struct prefix
*p
,
7625 afi_t afi
, safi_t safi
,
7626 struct bgp_path_info
*pi
)
7628 /* MED matching disabled. */
7629 if (!aggregate
->match_med
)
7632 /* Aggregation with different MED, recheck if we have got equal MEDs
7635 if (aggregate
->med_mismatched
&&
7636 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
) &&
7637 aggregate
->summary_only
)
7638 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
,
7641 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7643 /* No mismatches, just quit. */
7644 if (!aggregate
->med_mismatched
)
7647 /* Route summarization is disabled. */
7648 if (!aggregate
->summary_only
)
7651 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7654 /* Update an aggregate as routes are added/removed from the BGP table */
7655 bool bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7656 safi_t safi
, struct bgp_aggregate
*aggregate
)
7658 struct bgp_table
*table
;
7659 struct bgp_dest
*top
;
7660 struct bgp_dest
*dest
;
7662 struct aspath
*aspath
= NULL
;
7663 struct community
*community
= NULL
;
7664 struct ecommunity
*ecommunity
= NULL
;
7665 struct lcommunity
*lcommunity
= NULL
;
7666 struct bgp_path_info
*pi
;
7667 unsigned long match
= 0;
7668 uint8_t atomic_aggregate
= 0;
7670 /* If the bgp instance is being deleted or self peer is deleted
7671 * then do not create aggregate route
7673 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
7674 bgp
->peer_self
== NULL
)
7677 /* Initialize and test routes for MED difference. */
7678 if (aggregate
->match_med
)
7679 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7682 * Reset aggregate count: we might've been called from route map
7683 * update so in that case we must retest all more specific routes.
7685 * \see `bgp_route_map_process_update`.
7687 aggregate
->count
= 0;
7688 aggregate
->incomplete_origin_count
= 0;
7689 aggregate
->incomplete_origin_count
= 0;
7690 aggregate
->egp_origin_count
= 0;
7692 /* ORIGIN attribute: If at least one route among routes that are
7693 aggregated has ORIGIN with the value INCOMPLETE, then the
7694 aggregated route must have the ORIGIN attribute with the value
7695 INCOMPLETE. Otherwise, if at least one route among routes that
7696 are aggregated has ORIGIN with the value EGP, then the aggregated
7697 route must have the origin attribute with the value EGP. In all
7698 other case the value of the ORIGIN attribute of the aggregated
7699 route is INTERNAL. */
7700 origin
= BGP_ORIGIN_IGP
;
7702 table
= bgp
->rib
[afi
][safi
];
7704 top
= bgp_node_get(table
, p
);
7705 for (dest
= bgp_node_get(table
, p
); dest
;
7706 dest
= bgp_route_next_until(dest
, top
)) {
7707 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7709 if (dest_p
->prefixlen
<= p
->prefixlen
)
7712 /* If suppress fib is enabled and route not installed
7713 * in FIB, skip the route
7715 if (!bgp_check_advertise(bgp
, dest
))
7720 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7721 if (BGP_PATH_HOLDDOWN(pi
))
7725 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7726 atomic_aggregate
= 1;
7728 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7732 * summary-only aggregate route suppress
7733 * aggregated route announcements.
7736 * Don't create summaries if MED didn't match
7737 * otherwise neither the specific routes and the
7738 * aggregation will be announced.
7740 if (aggregate
->summary_only
7741 && AGGREGATE_MED_VALID(aggregate
)) {
7742 if (aggr_suppress_path(aggregate
, pi
))
7747 * Suppress more specific routes that match the route
7751 * Don't suppress routes if MED matching is enabled and
7752 * it mismatched otherwise we might end up with no
7753 * routes for this path.
7755 if (aggregate
->suppress_map_name
7756 && AGGREGATE_MED_VALID(aggregate
)
7757 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7758 if (aggr_suppress_path(aggregate
, pi
))
7765 * If at least one route among routes that are
7766 * aggregated has ORIGIN with the value INCOMPLETE,
7767 * then the aggregated route MUST have the ORIGIN
7768 * attribute with the value INCOMPLETE. Otherwise, if
7769 * at least one route among routes that are aggregated
7770 * has ORIGIN with the value EGP, then the aggregated
7771 * route MUST have the ORIGIN attribute with the value
7774 switch (pi
->attr
->origin
) {
7775 case BGP_ORIGIN_INCOMPLETE
:
7776 aggregate
->incomplete_origin_count
++;
7778 case BGP_ORIGIN_EGP
:
7779 aggregate
->egp_origin_count
++;
7787 if (!aggregate
->as_set
)
7791 * as-set aggregate route generate origin, as path,
7792 * and community aggregation.
7794 /* Compute aggregate route's as-path.
7796 bgp_compute_aggregate_aspath_hash(aggregate
,
7799 /* Compute aggregate route's community.
7801 if (bgp_attr_get_community(pi
->attr
))
7802 bgp_compute_aggregate_community_hash(
7804 bgp_attr_get_community(pi
->attr
));
7806 /* Compute aggregate route's extended community.
7808 if (bgp_attr_get_ecommunity(pi
->attr
))
7809 bgp_compute_aggregate_ecommunity_hash(
7811 bgp_attr_get_ecommunity(pi
->attr
));
7813 /* Compute aggregate route's large community.
7815 if (bgp_attr_get_lcommunity(pi
->attr
))
7816 bgp_compute_aggregate_lcommunity_hash(
7818 bgp_attr_get_lcommunity(pi
->attr
));
7821 bgp_process(bgp
, dest
, afi
, safi
);
7823 if (aggregate
->as_set
) {
7824 bgp_compute_aggregate_aspath_val(aggregate
);
7825 bgp_compute_aggregate_community_val(aggregate
);
7826 bgp_compute_aggregate_ecommunity_val(aggregate
);
7827 bgp_compute_aggregate_lcommunity_val(aggregate
);
7831 bgp_dest_unlock_node(top
);
7834 if (aggregate
->incomplete_origin_count
> 0)
7835 origin
= BGP_ORIGIN_INCOMPLETE
;
7836 else if (aggregate
->egp_origin_count
> 0)
7837 origin
= BGP_ORIGIN_EGP
;
7839 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7840 origin
= aggregate
->origin
;
7842 if (aggregate
->as_set
) {
7843 if (aggregate
->aspath
)
7844 /* Retrieve aggregate route's as-path.
7846 aspath
= aspath_dup(aggregate
->aspath
);
7848 if (aggregate
->community
)
7849 /* Retrieve aggregate route's community.
7851 community
= community_dup(aggregate
->community
);
7853 if (aggregate
->ecommunity
)
7854 /* Retrieve aggregate route's ecommunity.
7856 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7858 if (aggregate
->lcommunity
)
7859 /* Retrieve aggregate route's lcommunity.
7861 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7864 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7865 ecommunity
, lcommunity
, atomic_aggregate
,
7871 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7872 safi_t safi
, struct bgp_aggregate
*aggregate
)
7874 struct bgp_table
*table
;
7875 struct bgp_dest
*top
;
7876 struct bgp_dest
*dest
;
7877 struct bgp_path_info
*pi
;
7878 unsigned long match
;
7880 table
= bgp
->rib
[afi
][safi
];
7882 /* If routes exists below this node, generate aggregate routes. */
7883 top
= bgp_node_get(table
, p
);
7884 for (dest
= bgp_node_get(table
, p
); dest
;
7885 dest
= bgp_route_next_until(dest
, top
)) {
7886 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7888 if (dest_p
->prefixlen
<= p
->prefixlen
)
7892 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7893 if (BGP_PATH_HOLDDOWN(pi
))
7896 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7900 * This route is suppressed: attempt to unsuppress it.
7902 * `aggr_unsuppress_path` will fail if this particular
7903 * aggregate route was not the suppressor.
7905 if (pi
->extra
&& pi
->extra
->aggr_suppressors
&&
7906 listcount(pi
->extra
->aggr_suppressors
)) {
7907 if (aggr_unsuppress_path(aggregate
, pi
))
7913 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7914 aggregate
->incomplete_origin_count
--;
7915 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7916 aggregate
->egp_origin_count
--;
7918 if (aggregate
->as_set
) {
7919 /* Remove as-path from aggregate.
7921 bgp_remove_aspath_from_aggregate_hash(
7925 if (bgp_attr_get_community(pi
->attr
))
7926 /* Remove community from aggregate.
7928 bgp_remove_comm_from_aggregate_hash(
7930 bgp_attr_get_community(
7933 if (bgp_attr_get_ecommunity(pi
->attr
))
7934 /* Remove ecommunity from aggregate.
7936 bgp_remove_ecomm_from_aggregate_hash(
7938 bgp_attr_get_ecommunity(
7941 if (bgp_attr_get_lcommunity(pi
->attr
))
7942 /* Remove lcommunity from aggregate.
7944 bgp_remove_lcomm_from_aggregate_hash(
7946 bgp_attr_get_lcommunity(
7951 /* If this node was suppressed, process the change. */
7953 bgp_process(bgp
, dest
, afi
, safi
);
7955 if (aggregate
->as_set
) {
7956 aspath_free(aggregate
->aspath
);
7957 aggregate
->aspath
= NULL
;
7958 if (aggregate
->community
)
7959 community_free(&aggregate
->community
);
7960 if (aggregate
->ecommunity
)
7961 ecommunity_free(&aggregate
->ecommunity
);
7962 if (aggregate
->lcommunity
)
7963 lcommunity_free(&aggregate
->lcommunity
);
7966 bgp_dest_unlock_node(top
);
7969 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7970 const struct prefix
*aggr_p
,
7971 struct bgp_path_info
*pinew
, afi_t afi
,
7973 struct bgp_aggregate
*aggregate
)
7976 struct aspath
*aspath
= NULL
;
7977 uint8_t atomic_aggregate
= 0;
7978 struct community
*community
= NULL
;
7979 struct ecommunity
*ecommunity
= NULL
;
7980 struct lcommunity
*lcommunity
= NULL
;
7982 /* If the bgp instance is being deleted or self peer is deleted
7983 * then do not create aggregate route
7985 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7986 || (bgp
->peer_self
== NULL
))
7989 /* ORIGIN attribute: If at least one route among routes that are
7990 * aggregated has ORIGIN with the value INCOMPLETE, then the
7991 * aggregated route must have the ORIGIN attribute with the value
7992 * INCOMPLETE. Otherwise, if at least one route among routes that
7993 * are aggregated has ORIGIN with the value EGP, then the aggregated
7994 * route must have the origin attribute with the value EGP. In all
7995 * other case the value of the ORIGIN attribute of the aggregated
7996 * route is INTERNAL.
7998 origin
= BGP_ORIGIN_IGP
;
8003 * This must be called before `summary` check to avoid
8004 * "suppressing" twice.
8006 if (aggregate
->match_med
)
8007 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
8010 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8011 aggr_suppress_path(aggregate
, pinew
);
8013 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8014 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
8015 aggr_suppress_path(aggregate
, pinew
);
8017 switch (pinew
->attr
->origin
) {
8018 case BGP_ORIGIN_INCOMPLETE
:
8019 aggregate
->incomplete_origin_count
++;
8021 case BGP_ORIGIN_EGP
:
8022 aggregate
->egp_origin_count
++;
8030 if (aggregate
->incomplete_origin_count
> 0)
8031 origin
= BGP_ORIGIN_INCOMPLETE
;
8032 else if (aggregate
->egp_origin_count
> 0)
8033 origin
= BGP_ORIGIN_EGP
;
8035 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8036 origin
= aggregate
->origin
;
8038 if (aggregate
->as_set
) {
8039 /* Compute aggregate route's as-path.
8041 bgp_compute_aggregate_aspath(aggregate
,
8042 pinew
->attr
->aspath
);
8044 /* Compute aggregate route's community.
8046 if (bgp_attr_get_community(pinew
->attr
))
8047 bgp_compute_aggregate_community(
8048 aggregate
, bgp_attr_get_community(pinew
->attr
));
8050 /* Compute aggregate route's extended community.
8052 if (bgp_attr_get_ecommunity(pinew
->attr
))
8053 bgp_compute_aggregate_ecommunity(
8055 bgp_attr_get_ecommunity(pinew
->attr
));
8057 /* Compute aggregate route's large community.
8059 if (bgp_attr_get_lcommunity(pinew
->attr
))
8060 bgp_compute_aggregate_lcommunity(
8062 bgp_attr_get_lcommunity(pinew
->attr
));
8064 /* Retrieve aggregate route's as-path.
8066 if (aggregate
->aspath
)
8067 aspath
= aspath_dup(aggregate
->aspath
);
8069 /* Retrieve aggregate route's community.
8071 if (aggregate
->community
)
8072 community
= community_dup(aggregate
->community
);
8074 /* Retrieve aggregate route's ecommunity.
8076 if (aggregate
->ecommunity
)
8077 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8079 /* Retrieve aggregate route's lcommunity.
8081 if (aggregate
->lcommunity
)
8082 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8085 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8086 aspath
, community
, ecommunity
,
8087 lcommunity
, atomic_aggregate
, aggregate
);
8090 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
8092 struct bgp_path_info
*pi
,
8093 struct bgp_aggregate
*aggregate
,
8094 const struct prefix
*aggr_p
)
8097 struct aspath
*aspath
= NULL
;
8098 uint8_t atomic_aggregate
= 0;
8099 struct community
*community
= NULL
;
8100 struct ecommunity
*ecommunity
= NULL
;
8101 struct lcommunity
*lcommunity
= NULL
;
8102 unsigned long match
= 0;
8104 /* If the bgp instance is being deleted or self peer is deleted
8105 * then do not create aggregate route
8107 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
8108 || (bgp
->peer_self
== NULL
))
8111 if (BGP_PATH_HOLDDOWN(pi
))
8114 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
8117 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8118 if (aggr_unsuppress_path(aggregate
, pi
))
8121 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8122 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
8123 if (aggr_unsuppress_path(aggregate
, pi
))
8127 * This must be called after `summary`, `suppress-map` check to avoid
8128 * "unsuppressing" twice.
8130 if (aggregate
->match_med
)
8131 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
);
8133 if (aggregate
->count
> 0)
8136 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
8137 aggregate
->incomplete_origin_count
--;
8138 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
8139 aggregate
->egp_origin_count
--;
8141 if (aggregate
->as_set
) {
8142 /* Remove as-path from aggregate.
8144 bgp_remove_aspath_from_aggregate(aggregate
,
8147 if (bgp_attr_get_community(pi
->attr
))
8148 /* Remove community from aggregate.
8150 bgp_remove_community_from_aggregate(
8151 aggregate
, bgp_attr_get_community(pi
->attr
));
8153 if (bgp_attr_get_ecommunity(pi
->attr
))
8154 /* Remove ecommunity from aggregate.
8156 bgp_remove_ecommunity_from_aggregate(
8157 aggregate
, bgp_attr_get_ecommunity(pi
->attr
));
8159 if (bgp_attr_get_lcommunity(pi
->attr
))
8160 /* Remove lcommunity from aggregate.
8162 bgp_remove_lcommunity_from_aggregate(
8163 aggregate
, bgp_attr_get_lcommunity(pi
->attr
));
8166 /* If this node was suppressed, process the change. */
8168 bgp_process(bgp
, pi
->net
, afi
, safi
);
8170 origin
= BGP_ORIGIN_IGP
;
8171 if (aggregate
->incomplete_origin_count
> 0)
8172 origin
= BGP_ORIGIN_INCOMPLETE
;
8173 else if (aggregate
->egp_origin_count
> 0)
8174 origin
= BGP_ORIGIN_EGP
;
8176 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8177 origin
= aggregate
->origin
;
8179 if (aggregate
->as_set
) {
8180 /* Retrieve aggregate route's as-path.
8182 if (aggregate
->aspath
)
8183 aspath
= aspath_dup(aggregate
->aspath
);
8185 /* Retrieve aggregate route's community.
8187 if (aggregate
->community
)
8188 community
= community_dup(aggregate
->community
);
8190 /* Retrieve aggregate route's ecommunity.
8192 if (aggregate
->ecommunity
)
8193 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8195 /* Retrieve aggregate route's lcommunity.
8197 if (aggregate
->lcommunity
)
8198 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8201 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8202 aspath
, community
, ecommunity
,
8203 lcommunity
, atomic_aggregate
, aggregate
);
8206 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
8207 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
8209 struct bgp_dest
*child
;
8210 struct bgp_dest
*dest
;
8211 struct bgp_aggregate
*aggregate
;
8212 struct bgp_table
*table
;
8214 table
= bgp
->aggregate
[afi
][safi
];
8216 /* No aggregates configured. */
8217 if (bgp_table_top_nolock(table
) == NULL
)
8220 if (p
->prefixlen
== 0)
8223 if (BGP_PATH_HOLDDOWN(pi
))
8226 /* If suppress fib is enabled and route not installed
8227 * in FIB, do not update the aggregate route
8229 if (!bgp_check_advertise(bgp
, pi
->net
))
8232 child
= bgp_node_get(table
, p
);
8234 /* Aggregate address configuration check. */
8235 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8236 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8238 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8239 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8240 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
8244 bgp_dest_unlock_node(child
);
8247 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
8248 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
8250 struct bgp_dest
*child
;
8251 struct bgp_dest
*dest
;
8252 struct bgp_aggregate
*aggregate
;
8253 struct bgp_table
*table
;
8255 table
= bgp
->aggregate
[afi
][safi
];
8257 /* No aggregates configured. */
8258 if (bgp_table_top_nolock(table
) == NULL
)
8261 if (p
->prefixlen
== 0)
8264 child
= bgp_node_get(table
, p
);
8266 /* Aggregate address configuration check. */
8267 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8268 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8270 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8271 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8272 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
8276 bgp_dest_unlock_node(child
);
8279 /* Aggregate route attribute. */
8280 #define AGGREGATE_SUMMARY_ONLY 1
8281 #define AGGREGATE_AS_SET 1
8282 #define AGGREGATE_AS_UNSET 0
8284 static const char *bgp_origin2str(uint8_t origin
)
8287 case BGP_ORIGIN_IGP
:
8289 case BGP_ORIGIN_EGP
:
8291 case BGP_ORIGIN_INCOMPLETE
:
8292 return "incomplete";
8297 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
8300 case RPKI_NOT_BEING_USED
:
8310 assert(!"We should never get here this is a dev escape");
8314 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
8315 afi_t afi
, safi_t safi
)
8317 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8320 struct bgp_dest
*dest
;
8321 struct bgp_aggregate
*aggregate
;
8323 /* Convert string to prefix structure. */
8324 ret
= str2prefix(prefix_str
, &p
);
8326 vty_out(vty
, "Malformed prefix\n");
8327 return CMD_WARNING_CONFIG_FAILED
;
8331 /* Old configuration check. */
8332 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
8335 "%% There is no aggregate-address configuration.\n");
8336 return CMD_WARNING_CONFIG_FAILED
;
8339 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8340 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
8341 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
8342 NULL
, NULL
, 0, aggregate
);
8344 /* Unlock aggregate address configuration. */
8345 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
8347 bgp_free_aggregate_info(aggregate
);
8348 bgp_dest_unlock_node(dest
);
8349 bgp_dest_unlock_node(dest
);
8354 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
8355 safi_t safi
, const char *rmap
,
8356 uint8_t summary_only
, uint8_t as_set
,
8357 uint8_t origin
, bool match_med
,
8358 const char *suppress_map
)
8360 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8363 struct bgp_dest
*dest
;
8364 struct bgp_aggregate
*aggregate
;
8365 uint8_t as_set_new
= as_set
;
8367 if (suppress_map
&& summary_only
) {
8369 "'summary-only' and 'suppress-map' can't be used at the same time\n");
8370 return CMD_WARNING_CONFIG_FAILED
;
8373 /* Convert string to prefix structure. */
8374 ret
= str2prefix(prefix_str
, &p
);
8376 vty_out(vty
, "Malformed prefix\n");
8377 return CMD_WARNING_CONFIG_FAILED
;
8381 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
8382 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
8383 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8385 return CMD_WARNING_CONFIG_FAILED
;
8388 /* Old configuration check. */
8389 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
8390 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8393 vty_out(vty
, "There is already same aggregate network.\n");
8394 /* try to remove the old entry */
8395 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
8397 vty_out(vty
, "Error deleting aggregate.\n");
8398 bgp_dest_unlock_node(dest
);
8399 return CMD_WARNING_CONFIG_FAILED
;
8403 /* Make aggregate address structure. */
8404 aggregate
= bgp_aggregate_new();
8405 aggregate
->summary_only
= summary_only
;
8406 aggregate
->match_med
= match_med
;
8408 /* Network operators MUST NOT locally generate any new
8409 * announcements containing AS_SET or AS_CONFED_SET. If they have
8410 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8411 * SHOULD withdraw those routes and re-announce routes for the
8412 * aggregate or component prefixes (i.e., the more-specific routes
8413 * subsumed by the previously aggregated route) without AS_SET
8414 * or AS_CONFED_SET in the updates.
8416 if (bgp
->reject_as_sets
) {
8417 if (as_set
== AGGREGATE_AS_SET
) {
8418 as_set_new
= AGGREGATE_AS_UNSET
;
8420 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8423 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8427 aggregate
->as_set
= as_set_new
;
8428 aggregate
->safi
= safi
;
8429 /* Override ORIGIN attribute if defined.
8430 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8431 * to IGP which is not what rfc4271 says.
8432 * This enables the same behavior, optionally.
8434 aggregate
->origin
= origin
;
8437 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
8438 route_map_counter_decrement(aggregate
->rmap
.map
);
8439 aggregate
->rmap
.name
=
8440 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
8441 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
8442 route_map_counter_increment(aggregate
->rmap
.map
);
8446 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
8447 route_map_counter_decrement(aggregate
->suppress_map
);
8449 aggregate
->suppress_map_name
=
8450 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
8451 aggregate
->suppress_map
=
8452 route_map_lookup_by_name(aggregate
->suppress_map_name
);
8453 route_map_counter_increment(aggregate
->suppress_map
);
8456 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
8458 /* Aggregate address insert into BGP routing table. */
8459 if (!bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
)) {
8460 bgp_aggregate_free(aggregate
);
8461 bgp_dest_unlock_node(dest
);
8467 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
8468 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8470 "|summary-only$summary_only"
8471 "|route-map RMAP_NAME$rmap_name"
8472 "|origin <egp|igp|incomplete>$origin_s"
8473 "|matching-MED-only$match_med"
8474 "|suppress-map RMAP_NAME$suppress_map"
8477 "Configure BGP aggregate entries\n"
8478 "Aggregate prefix\n"
8479 "Aggregate address\n"
8481 "Generate AS set path information\n"
8482 "Filter more specific routes from updates\n"
8483 "Apply route map to aggregate network\n"
8488 "Unknown heritage\n"
8489 "Only aggregate routes with matching MED\n"
8490 "Suppress the selected more specific routes\n"
8491 "Route map with the route selectors\n")
8493 const char *prefix_s
= NULL
;
8494 safi_t safi
= bgp_node_safi(vty
);
8495 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8496 int as_set
= AGGREGATE_AS_UNSET
;
8497 char prefix_buf
[PREFIX2STR_BUFFER
];
8500 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8503 vty_out(vty
, "%% Inconsistent address and mask\n");
8504 return CMD_WARNING_CONFIG_FAILED
;
8506 prefix_s
= prefix_buf
;
8508 prefix_s
= prefix_str
;
8511 if (strcmp(origin_s
, "egp") == 0)
8512 origin
= BGP_ORIGIN_EGP
;
8513 else if (strcmp(origin_s
, "igp") == 0)
8514 origin
= BGP_ORIGIN_IGP
;
8515 else if (strcmp(origin_s
, "incomplete") == 0)
8516 origin
= BGP_ORIGIN_INCOMPLETE
;
8520 as_set
= AGGREGATE_AS_SET
;
8522 /* Handle configuration removal, otherwise installation. */
8524 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8526 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8527 summary_only
!= NULL
, as_set
, origin
,
8528 match_med
!= NULL
, suppress_map
);
8531 void bgp_free_aggregate_info(struct bgp_aggregate
*aggregate
)
8533 if (aggregate
->community
)
8534 community_free(&aggregate
->community
);
8536 hash_clean_and_free(&aggregate
->community_hash
,
8537 bgp_aggr_community_remove
);
8539 if (aggregate
->ecommunity
)
8540 ecommunity_free(&aggregate
->ecommunity
);
8542 hash_clean_and_free(&aggregate
->ecommunity_hash
,
8543 bgp_aggr_ecommunity_remove
);
8545 if (aggregate
->lcommunity
)
8546 lcommunity_free(&aggregate
->lcommunity
);
8548 hash_clean_and_free(&aggregate
->lcommunity_hash
,
8549 bgp_aggr_lcommunity_remove
);
8551 if (aggregate
->aspath
)
8552 aspath_free(aggregate
->aspath
);
8554 hash_clean_and_free(&aggregate
->aspath_hash
, bgp_aggr_aspath_remove
);
8556 bgp_aggregate_free(aggregate
);
8559 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8560 "[no] aggregate-address X:X::X:X/M$prefix [{"
8562 "|summary-only$summary_only"
8563 "|route-map RMAP_NAME$rmap_name"
8564 "|origin <egp|igp|incomplete>$origin_s"
8565 "|matching-MED-only$match_med"
8566 "|suppress-map RMAP_NAME$suppress_map"
8569 "Configure BGP aggregate entries\n"
8570 "Aggregate prefix\n"
8571 "Generate AS set path information\n"
8572 "Filter more specific routes from updates\n"
8573 "Apply route map to aggregate network\n"
8578 "Unknown heritage\n"
8579 "Only aggregate routes with matching MED\n"
8580 "Suppress the selected more specific routes\n"
8581 "Route map with the route selectors\n")
8583 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8584 int as_set
= AGGREGATE_AS_UNSET
;
8587 if (strcmp(origin_s
, "egp") == 0)
8588 origin
= BGP_ORIGIN_EGP
;
8589 else if (strcmp(origin_s
, "igp") == 0)
8590 origin
= BGP_ORIGIN_IGP
;
8591 else if (strcmp(origin_s
, "incomplete") == 0)
8592 origin
= BGP_ORIGIN_INCOMPLETE
;
8596 as_set
= AGGREGATE_AS_SET
;
8598 /* Handle configuration removal, otherwise installation. */
8600 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8603 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8604 rmap_name
, summary_only
!= NULL
, as_set
,
8605 origin
, match_med
!= NULL
, suppress_map
);
8608 /* Redistribute route treatment. */
8609 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8610 const union g_addr
*nexthop
, ifindex_t ifindex
,
8611 enum nexthop_types_t nhtype
, uint8_t distance
,
8612 enum blackhole_type bhtype
, uint32_t metric
,
8613 uint8_t type
, unsigned short instance
,
8616 struct bgp_path_info
*new;
8617 struct bgp_path_info
*bpi
;
8618 struct bgp_path_info rmap_path
;
8619 struct bgp_dest
*bn
;
8621 struct attr
*new_attr
;
8623 route_map_result_t ret
;
8624 struct bgp_redist
*red
;
8626 /* Make default attribute. */
8627 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
8629 * This must not be NULL to satisfy Coverity SA
8631 assert(attr
.aspath
);
8634 case NEXTHOP_TYPE_IFINDEX
:
8635 switch (p
->family
) {
8637 attr
.nexthop
.s_addr
= INADDR_ANY
;
8638 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8641 memset(&attr
.mp_nexthop_global
, 0,
8642 sizeof(attr
.mp_nexthop_global
));
8643 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8647 case NEXTHOP_TYPE_IPV4
:
8648 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8649 attr
.nexthop
= nexthop
->ipv4
;
8650 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8652 case NEXTHOP_TYPE_IPV6
:
8653 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8654 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8655 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8657 case NEXTHOP_TYPE_BLACKHOLE
:
8658 switch (p
->family
) {
8660 attr
.nexthop
.s_addr
= INADDR_ANY
;
8661 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8664 memset(&attr
.mp_nexthop_global
, 0,
8665 sizeof(attr
.mp_nexthop_global
));
8666 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8669 attr
.bh_type
= bhtype
;
8672 attr
.nh_type
= nhtype
;
8673 attr
.nh_ifindex
= ifindex
;
8676 attr
.distance
= distance
;
8677 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8681 bgp_attr_set_aigp_metric(&attr
, metric
);
8683 afi
= family2afi(p
->family
);
8685 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8687 struct attr attr_new
;
8689 /* Copy attribute for modification. */
8692 if (red
->redist_metric_flag
) {
8693 attr_new
.med
= red
->redist_metric
;
8694 bgp_attr_set_aigp_metric(&attr_new
, red
->redist_metric
);
8697 /* Apply route-map. */
8698 if (red
->rmap
.name
) {
8699 memset(&rmap_path
, 0, sizeof(rmap_path
));
8700 rmap_path
.peer
= bgp
->peer_self
;
8701 rmap_path
.attr
= &attr_new
;
8703 SET_FLAG(bgp
->peer_self
->rmap_type
,
8704 PEER_RMAP_TYPE_REDISTRIBUTE
);
8706 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8708 bgp
->peer_self
->rmap_type
= 0;
8710 if (ret
== RMAP_DENYMATCH
) {
8711 /* Free uninterned attribute. */
8712 bgp_attr_flush(&attr_new
);
8714 /* Unintern original. */
8715 aspath_unintern(&attr
.aspath
);
8716 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8721 if (bgp_in_graceful_shutdown(bgp
))
8722 bgp_attr_add_gshut_community(&attr_new
);
8724 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8725 SAFI_UNICAST
, p
, NULL
);
8727 new_attr
= bgp_attr_intern(&attr_new
);
8729 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8730 if (bpi
->peer
== bgp
->peer_self
8731 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8735 /* Ensure the (source route) type is updated. */
8737 if (attrhash_cmp(bpi
->attr
, new_attr
)
8738 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8739 bgp_attr_unintern(&new_attr
);
8740 aspath_unintern(&attr
.aspath
);
8741 bgp_dest_unlock_node(bn
);
8744 /* The attribute is changed. */
8745 bgp_path_info_set_flag(bn
, bpi
,
8746 BGP_PATH_ATTR_CHANGED
);
8748 /* Rewrite BGP route information. */
8749 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8750 bgp_path_info_restore(bn
, bpi
);
8752 bgp_aggregate_decrement(
8753 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8754 bgp_attr_unintern(&bpi
->attr
);
8755 bpi
->attr
= new_attr
;
8756 bpi
->uptime
= monotime(NULL
);
8758 /* Process change. */
8759 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8761 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8762 bgp_dest_unlock_node(bn
);
8763 aspath_unintern(&attr
.aspath
);
8765 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8767 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8769 vpn_leak_from_vrf_update(
8770 bgp_get_default(), bgp
, bpi
);
8776 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8777 bgp
->peer_self
, new_attr
, bn
);
8778 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8780 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8781 bgp_path_info_add(bn
, new);
8782 bgp_dest_unlock_node(bn
);
8783 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8784 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8786 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8787 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8789 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8793 /* Unintern original. */
8794 aspath_unintern(&attr
.aspath
);
8797 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8798 unsigned short instance
)
8801 struct bgp_dest
*dest
;
8802 struct bgp_path_info
*pi
;
8803 struct bgp_redist
*red
;
8805 afi
= family2afi(p
->family
);
8807 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8809 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8810 SAFI_UNICAST
, p
, NULL
);
8812 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8813 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8817 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8818 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8820 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8823 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8824 bgp_path_info_delete(dest
, pi
);
8825 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8827 bgp_dest_unlock_node(dest
);
8831 /* Withdraw specified route type's route. */
8832 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8833 unsigned short instance
)
8835 struct bgp_dest
*dest
;
8836 struct bgp_path_info
*pi
;
8837 struct bgp_table
*table
;
8839 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8841 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8842 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8843 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8844 && pi
->instance
== instance
)
8848 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8849 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8851 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8854 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8855 pi
, afi
, SAFI_UNICAST
);
8856 bgp_path_info_delete(dest
, pi
);
8857 if (!CHECK_FLAG(bgp
->flags
,
8858 BGP_FLAG_DELETE_IN_PROGRESS
))
8859 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8861 bgp_path_info_reap(dest
, pi
);
8866 /* Static function to display route. */
8867 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8868 struct vty
*vty
, json_object
*json
, bool wide
)
8871 char buf
[INET6_ADDRSTRLEN
];
8873 if (p
->family
== AF_INET
) {
8875 len
= vty_out(vty
, "%pFX", p
);
8877 json_object_string_add(json
, "prefix",
8878 inet_ntop(p
->family
,
8881 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8882 json_object_string_addf(json
, "network", "%pFX", p
);
8883 json_object_int_add(json
, "version", dest
->version
);
8885 } else if (p
->family
== AF_ETHERNET
) {
8886 len
= vty_out(vty
, "%pFX", p
);
8887 } else if (p
->family
== AF_EVPN
) {
8889 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8891 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8892 } else if (p
->family
== AF_FLOWSPEC
) {
8893 route_vty_out_flowspec(vty
, p
, NULL
,
8895 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8896 NLRI_STRING_FORMAT_MIN
, json
);
8899 len
= vty_out(vty
, "%pFX", p
);
8901 json_object_string_add(json
, "prefix",
8902 inet_ntop(p
->family
,
8905 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8906 json_object_string_addf(json
, "network", "%pFX", p
);
8907 json_object_int_add(json
, "version", dest
->version
);
8912 len
= wide
? (45 - len
) : (17 - len
);
8914 vty_out(vty
, "\n%*s", 20, " ");
8916 vty_out(vty
, "%*s", len
, " ");
8920 enum bgp_display_type
{
8924 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8927 case bgp_path_selection_none
:
8928 return "Nothing to Select";
8929 case bgp_path_selection_first
:
8930 return "First path received";
8931 case bgp_path_selection_evpn_sticky_mac
:
8932 return "EVPN Sticky Mac";
8933 case bgp_path_selection_evpn_seq
:
8934 return "EVPN sequence number";
8935 case bgp_path_selection_evpn_lower_ip
:
8936 return "EVPN lower IP";
8937 case bgp_path_selection_evpn_local_path
:
8938 return "EVPN local ES path";
8939 case bgp_path_selection_evpn_non_proxy
:
8940 return "EVPN non proxy";
8941 case bgp_path_selection_weight
:
8943 case bgp_path_selection_local_pref
:
8944 return "Local Pref";
8945 case bgp_path_selection_accept_own
:
8946 return "Accept Own";
8947 case bgp_path_selection_local_route
:
8948 return "Local Route";
8949 case bgp_path_selection_aigp
:
8951 case bgp_path_selection_confed_as_path
:
8952 return "Confederation based AS Path";
8953 case bgp_path_selection_as_path
:
8955 case bgp_path_selection_origin
:
8957 case bgp_path_selection_med
:
8959 case bgp_path_selection_peer
:
8961 case bgp_path_selection_confed
:
8962 return "Confed Peer Type";
8963 case bgp_path_selection_igp_metric
:
8964 return "IGP Metric";
8965 case bgp_path_selection_older
:
8966 return "Older Path";
8967 case bgp_path_selection_router_id
:
8969 case bgp_path_selection_cluster_length
:
8970 return "Cluster length";
8971 case bgp_path_selection_stale
:
8972 return "Path Staleness";
8973 case bgp_path_selection_local_configured
:
8974 return "Locally configured route";
8975 case bgp_path_selection_neighbor_ip
:
8976 return "Neighbor IP";
8977 case bgp_path_selection_default
:
8978 return "Nothing left to compare";
8980 return "Invalid (internal error)";
8983 /* Print the short form route status for a bgp_path_info */
8984 static void route_vty_short_status_out(struct vty
*vty
,
8985 struct bgp_path_info
*path
,
8986 const struct prefix
*p
,
8987 json_object
*json_path
)
8989 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
8993 /* Route status display. */
8994 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8995 json_object_boolean_true_add(json_path
, "removed");
8997 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8998 json_object_boolean_true_add(json_path
, "stale");
9000 if (path
->extra
&& bgp_path_suppressed(path
))
9001 json_object_boolean_true_add(json_path
, "suppressed");
9003 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9004 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9005 json_object_boolean_true_add(json_path
, "valid");
9008 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9009 json_object_boolean_true_add(json_path
, "history");
9011 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9012 json_object_boolean_true_add(json_path
, "damped");
9014 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9015 json_object_boolean_true_add(json_path
, "bestpath");
9016 json_object_string_add(json_path
, "selectionReason",
9017 bgp_path_selection_reason2str(
9018 path
->net
->reason
));
9021 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9022 json_object_boolean_true_add(json_path
, "multipath");
9024 /* Internal route. */
9025 if ((path
->peer
->as
)
9026 && (path
->peer
->as
== path
->peer
->local_as
))
9027 json_object_string_add(json_path
, "pathFrom",
9030 json_object_string_add(json_path
, "pathFrom",
9036 /* RPKI validation state */
9038 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
9040 if (rpki_state
== RPKI_VALID
)
9042 else if (rpki_state
== RPKI_INVALID
)
9044 else if (rpki_state
== RPKI_NOTFOUND
)
9049 /* Route status display. */
9050 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9052 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9054 else if (bgp_path_suppressed(path
))
9056 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9057 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9063 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9065 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9067 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
9069 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9074 /* Internal route. */
9075 if (path
->peer
&& (path
->peer
->as
)
9076 && (path
->peer
->as
== path
->peer
->local_as
))
9082 static char *bgp_nexthop_hostname(struct peer
*peer
,
9083 struct bgp_nexthop_cache
*bnc
)
9086 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
9087 return peer
->hostname
;
9091 /* called from terminal list command */
9092 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9093 struct bgp_path_info
*path
, int display
, safi_t safi
,
9094 json_object
*json_paths
, bool wide
)
9097 struct attr
*attr
= path
->attr
;
9098 json_object
*json_path
= NULL
;
9099 json_object
*json_nexthops
= NULL
;
9100 json_object
*json_nexthop_global
= NULL
;
9101 json_object
*json_nexthop_ll
= NULL
;
9102 json_object
*json_ext_community
= NULL
;
9103 char vrf_id_str
[VRF_NAMSIZ
] = {0};
9105 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9106 bool nexthop_othervrf
= false;
9107 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
9108 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
9109 char *nexthop_hostname
=
9110 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9111 char esi_buf
[ESI_STR_LEN
];
9114 json_path
= json_object_new_object();
9116 /* short status lead text */
9117 route_vty_short_status_out(vty
, path
, p
, json_path
);
9120 /* print prefix and mask */
9122 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9124 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
9126 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9130 * If vrf id of nexthop is different from that of prefix,
9131 * set up printable string to append
9133 if (path
->extra
&& path
->extra
->bgp_orig
) {
9134 const char *self
= "";
9139 nexthop_othervrf
= true;
9140 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9142 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
9143 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
9144 "@%s%s", VRFID_NONE_STR
, self
);
9146 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
9147 path
->extra
->bgp_orig
->vrf_id
, self
);
9149 if (path
->extra
->bgp_orig
->inst_type
9150 != BGP_INSTANCE_TYPE_DEFAULT
)
9152 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
9154 const char *self
= "";
9159 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
9163 * For ENCAP and EVPN routes, nexthop address family is not
9164 * neccessarily the same as the prefix address family.
9165 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9166 * EVPN routes are also exchanged with a MP nexthop. Currently,
9168 * is only IPv4, the value will be present in either
9170 * attr->mp_nexthop_global_in
9172 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
9174 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9178 snprintfrr(nexthop
, sizeof(nexthop
), "%pI4",
9179 &attr
->mp_nexthop_global_in
);
9182 snprintfrr(nexthop
, sizeof(nexthop
), "%pI6",
9183 &attr
->mp_nexthop_global
);
9186 snprintf(nexthop
, sizeof(nexthop
), "?");
9191 json_nexthop_global
= json_object_new_object();
9193 json_object_string_add(json_nexthop_global
, "ip",
9196 if (path
->peer
->hostname
)
9197 json_object_string_add(json_nexthop_global
,
9199 path
->peer
->hostname
);
9201 json_object_string_add(json_nexthop_global
, "afi",
9202 (af
== AF_INET
) ? "ipv4"
9204 json_object_boolean_true_add(json_nexthop_global
,
9207 if (nexthop_hostname
)
9208 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
9209 nexthop_hostname
, vrf_id_str
);
9211 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
9213 len
= wide
? (41 - len
) : (16 - len
);
9215 vty_out(vty
, "\n%*s", 36, " ");
9217 vty_out(vty
, "%*s", len
, " ");
9219 } else if (safi
== SAFI_EVPN
) {
9221 json_nexthop_global
= json_object_new_object();
9223 json_object_string_addf(json_nexthop_global
, "ip",
9225 &attr
->mp_nexthop_global_in
);
9227 if (path
->peer
->hostname
)
9228 json_object_string_add(json_nexthop_global
,
9230 path
->peer
->hostname
);
9232 json_object_string_add(json_nexthop_global
, "afi",
9234 json_object_boolean_true_add(json_nexthop_global
,
9237 if (nexthop_hostname
)
9238 len
= vty_out(vty
, "%pI4(%s)%s",
9239 &attr
->mp_nexthop_global_in
,
9240 nexthop_hostname
, vrf_id_str
);
9242 len
= vty_out(vty
, "%pI4%s",
9243 &attr
->mp_nexthop_global_in
,
9246 len
= wide
? (41 - len
) : (16 - len
);
9248 vty_out(vty
, "\n%*s", 36, " ");
9250 vty_out(vty
, "%*s", len
, " ");
9252 } else if (safi
== SAFI_FLOWSPEC
) {
9253 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
9255 json_nexthop_global
= json_object_new_object();
9257 json_object_string_add(json_nexthop_global
,
9259 json_object_string_addf(json_nexthop_global
,
9263 if (path
->peer
->hostname
)
9264 json_object_string_add(
9265 json_nexthop_global
, "hostname",
9266 path
->peer
->hostname
);
9268 json_object_boolean_true_add(
9269 json_nexthop_global
,
9272 if (nexthop_hostname
)
9273 len
= vty_out(vty
, "%pI4(%s)%s",
9278 len
= vty_out(vty
, "%pI4%s",
9282 len
= wide
? (41 - len
) : (16 - len
);
9284 vty_out(vty
, "\n%*s", 36, " ");
9286 vty_out(vty
, "%*s", len
, " ");
9289 } else if (p
->family
== AF_INET
&& !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9291 json_nexthop_global
= json_object_new_object();
9293 json_object_string_addf(json_nexthop_global
, "ip",
9294 "%pI4", &attr
->nexthop
);
9296 if (path
->peer
->hostname
)
9297 json_object_string_add(json_nexthop_global
,
9299 path
->peer
->hostname
);
9301 json_object_string_add(json_nexthop_global
, "afi",
9303 json_object_boolean_true_add(json_nexthop_global
,
9306 if (nexthop_hostname
)
9307 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
9308 nexthop_hostname
, vrf_id_str
);
9310 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
9313 len
= wide
? (41 - len
) : (16 - len
);
9315 vty_out(vty
, "\n%*s", 36, " ");
9317 vty_out(vty
, "%*s", len
, " ");
9322 else if (p
->family
== AF_INET6
|| BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9324 json_nexthop_global
= json_object_new_object();
9325 json_object_string_addf(json_nexthop_global
, "ip",
9327 &attr
->mp_nexthop_global
);
9329 if (path
->peer
->hostname
)
9330 json_object_string_add(json_nexthop_global
,
9332 path
->peer
->hostname
);
9334 json_object_string_add(json_nexthop_global
, "afi",
9336 json_object_string_add(json_nexthop_global
, "scope",
9339 /* We display both LL & GL if both have been
9341 if ((attr
->mp_nexthop_len
9342 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9343 || (path
->peer
->conf_if
)) {
9344 json_nexthop_ll
= json_object_new_object();
9345 json_object_string_addf(
9346 json_nexthop_ll
, "ip", "%pI6",
9347 &attr
->mp_nexthop_local
);
9349 if (path
->peer
->hostname
)
9350 json_object_string_add(
9351 json_nexthop_ll
, "hostname",
9352 path
->peer
->hostname
);
9354 json_object_string_add(json_nexthop_ll
, "afi",
9356 json_object_string_add(json_nexthop_ll
, "scope",
9359 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9360 &attr
->mp_nexthop_local
)
9362 && !attr
->mp_nexthop_prefer_global
)
9363 json_object_boolean_true_add(
9364 json_nexthop_ll
, "used");
9366 json_object_boolean_true_add(
9367 json_nexthop_global
, "used");
9369 json_object_boolean_true_add(
9370 json_nexthop_global
, "used");
9372 /* Display LL if LL/Global both in table unless
9373 * prefer-global is set */
9374 if (((attr
->mp_nexthop_len
9375 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9376 && !attr
->mp_nexthop_prefer_global
)
9377 || (path
->peer
->conf_if
)) {
9378 if (path
->peer
->conf_if
) {
9379 len
= vty_out(vty
, "%s",
9380 path
->peer
->conf_if
);
9381 /* len of IPv6 addr + max len of def
9383 len
= wide
? (41 - len
) : (16 - len
);
9386 vty_out(vty
, "\n%*s", 36, " ");
9388 vty_out(vty
, "%*s", len
, " ");
9390 if (nexthop_hostname
)
9393 &attr
->mp_nexthop_local
,
9399 &attr
->mp_nexthop_local
,
9402 len
= wide
? (41 - len
) : (16 - len
);
9405 vty_out(vty
, "\n%*s", 36, " ");
9407 vty_out(vty
, "%*s", len
, " ");
9410 if (nexthop_hostname
)
9411 len
= vty_out(vty
, "%pI6(%s)%s",
9412 &attr
->mp_nexthop_global
,
9416 len
= vty_out(vty
, "%pI6%s",
9417 &attr
->mp_nexthop_global
,
9420 len
= wide
? (41 - len
) : (16 - len
);
9423 vty_out(vty
, "\n%*s", 36, " ");
9425 vty_out(vty
, "%*s", len
, " ");
9431 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9433 json_object_int_add(json_path
, "metric", attr
->med
);
9435 vty_out(vty
, "%7u", attr
->med
);
9437 vty_out(vty
, "%10u", attr
->med
);
9438 else if (!json_paths
) {
9440 vty_out(vty
, "%*s", 7, " ");
9442 vty_out(vty
, "%*s", 10, " ");
9446 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9448 json_object_int_add(json_path
, "locPrf",
9451 vty_out(vty
, "%7u", attr
->local_pref
);
9452 else if (!json_paths
)
9456 json_object_int_add(json_path
, "weight", attr
->weight
);
9458 vty_out(vty
, "%7u ", attr
->weight
);
9461 json_object_string_addf(json_path
, "peerId", "%pSU",
9467 json_object_string_add(json_path
, "path",
9470 aspath_print_vty(vty
, attr
->aspath
);
9475 json_object_string_add(json_path
, "origin",
9476 bgp_origin_long_str
[attr
->origin
]);
9478 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9481 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9482 json_object_string_add(json_path
, "esi",
9483 esi_to_str(&attr
->esi
,
9484 esi_buf
, sizeof(esi_buf
)));
9486 if (safi
== SAFI_EVPN
&&
9487 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9488 json_ext_community
= json_object_new_object();
9489 json_object_string_add(
9490 json_ext_community
, "string",
9491 bgp_attr_get_ecommunity(attr
)->str
);
9492 json_object_object_add(json_path
,
9493 "extendedCommunity",
9494 json_ext_community
);
9498 json_object_boolean_true_add(json_path
,
9499 "announceNexthopSelf");
9500 if (nexthop_othervrf
) {
9501 json_object_string_add(json_path
, "nhVrfName",
9504 json_object_int_add(json_path
, "nhVrfId",
9505 ((nexthop_vrfid
== VRF_UNKNOWN
)
9507 : (int)nexthop_vrfid
));
9512 if (json_nexthop_global
|| json_nexthop_ll
) {
9513 json_nexthops
= json_object_new_array();
9515 if (json_nexthop_global
)
9516 json_object_array_add(json_nexthops
,
9517 json_nexthop_global
);
9519 if (json_nexthop_ll
)
9520 json_object_array_add(json_nexthops
,
9523 json_object_object_add(json_path
, "nexthops",
9527 json_object_array_add(json_paths
, json_path
);
9531 if (safi
== SAFI_EVPN
) {
9532 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9533 /* XXX - add these params to the json out */
9534 vty_out(vty
, "%*s", 20, " ");
9535 vty_out(vty
, "ESI:%s",
9536 esi_to_str(&attr
->esi
, esi_buf
,
9542 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9543 vty_out(vty
, "%*s", 20, " ");
9544 vty_out(vty
, "%s\n",
9545 bgp_attr_get_ecommunity(attr
)->str
);
9549 #ifdef ENABLE_BGP_VNC
9550 /* prints an additional line, indented, with VNC info, if
9552 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9553 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9558 /* called from terminal list command */
9559 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9560 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9561 bool use_json
, json_object
*json_ar
, bool wide
)
9563 json_object
*json_status
= NULL
;
9564 json_object
*json_net
= NULL
;
9568 /* Route status display. */
9570 json_status
= json_object_new_object();
9571 json_net
= json_object_new_object();
9578 /* print prefix and mask */
9580 if (safi
== SAFI_EVPN
)
9581 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9582 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9583 json_object_string_add(
9584 json_net
, "addrPrefix",
9585 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9587 json_object_int_add(json_net
, "prefixLen",
9589 json_object_string_addf(json_net
, "network", "%pFX", p
);
9592 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9594 /* Print attribute */
9597 if (p
->family
== AF_INET
&&
9598 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9599 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9600 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9601 json_object_string_addf(
9602 json_net
, "nextHop", "%pI4",
9603 &attr
->mp_nexthop_global_in
);
9605 json_object_string_addf(
9606 json_net
, "nextHop", "%pI4",
9608 } else if (p
->family
== AF_INET6
||
9609 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9610 json_object_string_addf(
9611 json_net
, "nextHopGlobal", "%pI6",
9612 &attr
->mp_nexthop_global
);
9613 } else if (p
->family
== AF_EVPN
&&
9614 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9615 json_object_string_addf(
9616 json_net
, "nextHop", "%pI4",
9617 &attr
->mp_nexthop_global_in
);
9621 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9622 json_object_int_add(json_net
, "metric",
9625 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9626 json_object_int_add(json_net
, "locPrf",
9629 json_object_int_add(json_net
, "weight", attr
->weight
);
9633 json_object_string_add(json_net
, "path",
9637 #if CONFDATE > 20231208
9638 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9640 json_object_string_add(json_net
, "bgpOriginCode",
9641 bgp_origin_str
[attr
->origin
]);
9642 json_object_string_add(
9644 bgp_origin_long_str
[attr
->origin
]);
9646 if (p
->family
== AF_INET
&&
9647 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9648 safi
== SAFI_EVPN
||
9649 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9650 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9651 || safi
== SAFI_EVPN
)
9652 vty_out(vty
, "%-16pI4",
9653 &attr
->mp_nexthop_global_in
);
9655 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9657 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9658 } else if (p
->family
== AF_INET6
||
9659 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9660 len
= vty_out(vty
, "%pI6",
9661 &attr
->mp_nexthop_global
);
9662 len
= wide
? (41 - len
) : (16 - len
);
9664 vty_out(vty
, "\n%*s", 36, " ");
9666 vty_out(vty
, "%*s", len
, " ");
9669 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9671 vty_out(vty
, "%7u", attr
->med
);
9673 vty_out(vty
, "%10u", attr
->med
);
9679 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9680 vty_out(vty
, "%7u", attr
->local_pref
);
9684 vty_out(vty
, "%7u ", attr
->weight
);
9688 aspath_print_vty(vty
, attr
->aspath
);
9691 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9695 struct bgp_path_info
*bpi
= bgp_dest_get_bgp_path_info(dest
);
9697 #if CONFDATE > 20231208
9698 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9700 json_object_boolean_true_add(json_status
, "*");
9701 json_object_boolean_true_add(json_status
, ">");
9702 json_object_boolean_true_add(json_net
, "valid");
9703 json_object_boolean_true_add(json_net
, "best");
9705 if (bpi
&& CHECK_FLAG(bpi
->flags
, BGP_PATH_MULTIPATH
)) {
9706 json_object_boolean_true_add(json_status
, "=");
9707 json_object_boolean_true_add(json_net
, "multipath");
9709 json_object_object_add(json_net
, "appliedStatusSymbols",
9711 json_object_object_addf(json_ar
, json_net
, "%pFX", p
);
9716 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9717 struct bgp_path_info
*path
, int display
, safi_t safi
,
9720 json_object
*json_out
= NULL
;
9722 mpls_label_t label
= MPLS_INVALID_LABEL
;
9728 json_out
= json_object_new_object();
9730 /* short status lead text */
9731 route_vty_short_status_out(vty
, path
, p
, json_out
);
9733 /* print prefix and mask */
9736 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9738 vty_out(vty
, "%*s", 17, " ");
9741 /* Print attribute */
9743 if (((p
->family
== AF_INET
) &&
9744 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9745 (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) ||
9746 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9747 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9748 || safi
== SAFI_EVPN
) {
9750 json_object_string_addf(
9751 json_out
, "mpNexthopGlobalIn", "%pI4",
9752 &attr
->mp_nexthop_global_in
);
9754 vty_out(vty
, "%-16pI4",
9755 &attr
->mp_nexthop_global_in
);
9758 json_object_string_addf(json_out
, "nexthop",
9759 "%pI4", &attr
->nexthop
);
9761 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9763 } else if (((p
->family
== AF_INET6
) &&
9764 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9765 (safi
== SAFI_EVPN
&& BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) ||
9766 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9769 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9771 json_object_string_addf(
9772 json_out
, "mpNexthopGlobalIn", "%pI6",
9773 &attr
->mp_nexthop_global
);
9777 &attr
->mp_nexthop_global
,
9778 buf_a
, sizeof(buf_a
)));
9779 } else if (attr
->mp_nexthop_len
9780 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9781 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9782 &attr
->mp_nexthop_global
,
9783 &attr
->mp_nexthop_local
);
9785 json_object_string_add(json_out
,
9786 "mpNexthopGlobalLocal",
9789 vty_out(vty
, "%s", buf_a
);
9793 label
= decode_label(&path
->extra
->label
[0]);
9795 if (bgp_is_valid_label(&label
)) {
9797 json_object_int_add(json_out
, "notag", label
);
9798 json_object_array_add(json
, json_out
);
9800 vty_out(vty
, "notag/%d", label
);
9807 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9808 struct bgp_path_info
*path
, int display
,
9809 json_object
*json_paths
)
9812 json_object
*json_path
= NULL
;
9813 json_object
*json_nexthop
= NULL
;
9814 json_object
*json_overlay
= NULL
;
9820 json_path
= json_object_new_object();
9821 json_overlay
= json_object_new_object();
9822 json_nexthop
= json_object_new_object();
9825 /* short status lead text */
9826 route_vty_short_status_out(vty
, path
, p
, json_path
);
9828 /* print prefix and mask */
9830 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9832 vty_out(vty
, "%*s", 17, " ");
9834 /* Print attribute */
9836 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9841 vty_out(vty
, "%-16pI4", &attr
->mp_nexthop_global_in
);
9843 json_object_string_addf(json_nexthop
, "ip", "%pI4",
9844 &attr
->mp_nexthop_global_in
);
9846 json_object_string_add(json_nexthop
, "afi", "ipv4");
9848 json_object_object_add(json_path
, "nexthop",
9854 vty_out(vty
, "%pI6(%pI6)", &attr
->mp_nexthop_global
,
9855 &attr
->mp_nexthop_local
);
9857 json_object_string_addf(json_nexthop
, "ipv6Global",
9859 &attr
->mp_nexthop_global
);
9861 json_object_string_addf(json_nexthop
, "ipv6LinkLocal",
9863 &attr
->mp_nexthop_local
);
9865 json_object_string_add(json_nexthop
, "afi", "ipv6");
9867 json_object_object_add(json_path
, "nexthop",
9875 json_object_string_add(json_nexthop
, "error",
9876 "Unsupported address-family");
9880 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9883 vty_out(vty
, "/%pIA", &eo
->gw_ip
);
9885 json_object_string_addf(json_overlay
, "gw", "%pIA", &eo
->gw_ip
);
9887 if (bgp_attr_get_ecommunity(attr
)) {
9889 struct ecommunity_val
*routermac
= ecommunity_lookup(
9890 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9891 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9894 mac
= ecom_mac2str((char *)routermac
->val
);
9897 vty_out(vty
, "/%s", mac
);
9899 json_object_string_add(json_overlay
, "rmac",
9902 XFREE(MTYPE_TMP
, mac
);
9909 json_object_object_add(json_path
, "overlay", json_overlay
);
9911 json_object_array_add(json_paths
, json_path
);
9915 /* dampening route */
9916 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9917 struct bgp_path_info
*path
, int display
,
9918 afi_t afi
, safi_t safi
, bool use_json
,
9919 json_object
*json_paths
)
9921 struct attr
*attr
= path
->attr
;
9923 char timebuf
[BGP_UPTIME_LEN
];
9924 json_object
*json_path
= NULL
;
9927 json_path
= json_object_new_object();
9929 /* short status lead text */
9930 route_vty_short_status_out(vty
, path
, p
, json_path
);
9932 /* print prefix and mask */
9935 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9937 vty_out(vty
, "%*s", 17, " ");
9939 len
= vty_out(vty
, "%s", path
->peer
->host
);
9943 vty_out(vty
, "\n%*s", 34, " ");
9945 vty_out(vty
, "%*s", len
, " ");
9948 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9949 BGP_UPTIME_LEN
, afi
, safi
,
9953 aspath_print_vty(vty
, attr
->aspath
);
9955 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9959 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9960 safi
, use_json
, json_path
);
9963 json_object_string_add(json_path
, "asPath",
9966 json_object_string_add(json_path
, "origin",
9967 bgp_origin_str
[attr
->origin
]);
9968 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9970 json_object_array_add(json_paths
, json_path
);
9975 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9976 struct bgp_path_info
*path
, int display
,
9977 afi_t afi
, safi_t safi
, bool use_json
,
9978 json_object
*json_paths
)
9980 struct attr
*attr
= path
->attr
;
9981 struct bgp_damp_info
*bdi
;
9982 char timebuf
[BGP_UPTIME_LEN
];
9984 json_object
*json_path
= NULL
;
9990 json_path
= json_object_new_object();
9992 bdi
= path
->extra
->damp_info
;
9994 /* short status lead text */
9995 route_vty_short_status_out(vty
, path
, p
, json_path
);
9999 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
10001 vty_out(vty
, "%*s", 17, " ");
10003 len
= vty_out(vty
, "%s", path
->peer
->host
);
10006 vty_out(vty
, "\n%*s", 33, " ");
10008 vty_out(vty
, "%*s", len
, " ");
10010 len
= vty_out(vty
, "%d", bdi
->flap
);
10015 vty_out(vty
, "%*s", len
, " ");
10017 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
10018 BGP_UPTIME_LEN
, 0, NULL
));
10020 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10021 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10022 vty_out(vty
, "%s ",
10023 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10024 BGP_UPTIME_LEN
, afi
,
10025 safi
, use_json
, NULL
));
10027 vty_out(vty
, "%*s ", 8, " ");
10030 aspath_print_vty(vty
, attr
->aspath
);
10032 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10034 vty_out(vty
, "\n");
10036 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10037 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
10039 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
10042 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10043 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10044 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10045 BGP_UPTIME_LEN
, afi
, safi
,
10046 use_json
, json_path
);
10049 json_object_string_add(json_path
, "asPath",
10050 attr
->aspath
->str
);
10052 json_object_string_add(json_path
, "origin",
10053 bgp_origin_str
[attr
->origin
]);
10055 json_object_array_add(json_paths
, json_path
);
10059 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
10060 int *first
, const char *header
,
10061 json_object
*json_adv_to
)
10063 json_object
*json_peer
= NULL
;
10066 /* 'advertised-to' is a dictionary of peers we have advertised
10068 * prefix too. The key is the peer's IP or swpX, the value is
10070 * hostname if we know it and "" if not.
10072 json_peer
= json_object_new_object();
10074 if (peer
->hostname
)
10075 json_object_string_add(json_peer
, "hostname",
10079 json_object_object_add(json_adv_to
, peer
->conf_if
,
10082 json_object_object_addf(json_adv_to
, json_peer
, "%pSU",
10086 vty_out(vty
, "%s", header
);
10091 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
10093 vty_out(vty
, " %s(%s)", peer
->hostname
,
10096 vty_out(vty
, " %s(%pSU)", peer
->hostname
,
10100 vty_out(vty
, " %s", peer
->conf_if
);
10102 vty_out(vty
, " %pSU", &peer
->su
);
10107 static void route_vty_out_tx_ids(struct vty
*vty
,
10108 struct bgp_addpath_info_data
*d
)
10112 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10113 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
10114 d
->addpath_tx_id
[i
],
10115 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
10119 static void route_vty_out_detail_es_info(struct vty
*vty
,
10120 struct bgp_path_info
*pi
,
10122 json_object
*json_path
)
10124 char esi_buf
[ESI_STR_LEN
];
10125 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
10126 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
10127 ATTR_ES_PEER_ROUTER
);
10128 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
10129 ATTR_ES_PEER_ACTIVE
);
10130 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
10131 ATTR_ES_PEER_PROXY
);
10132 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
10134 json_object
*json_es_info
= NULL
;
10136 json_object_string_add(
10139 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
10140 json_es_info
= json_object_new_object();
10142 json_object_boolean_true_add(
10143 json_es_info
, "localEs");
10145 json_object_boolean_true_add(
10146 json_es_info
, "peerActive");
10148 json_object_boolean_true_add(
10149 json_es_info
, "peerProxy");
10151 json_object_boolean_true_add(
10152 json_es_info
, "peerRouter");
10153 if (attr
->mm_sync_seqnum
)
10154 json_object_int_add(
10155 json_es_info
, "peerSeq",
10156 attr
->mm_sync_seqnum
);
10157 json_object_object_add(
10158 json_path
, "es_info",
10162 if (bgp_evpn_attr_is_sync(attr
))
10164 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10166 es_local
? "local-es":"",
10167 peer_proxy
? "proxy " : "",
10168 peer_active
? "active ":"",
10169 peer_router
? "router ":"",
10170 attr
->mm_sync_seqnum
);
10172 vty_out(vty
, " ESI %s %s\n",
10174 es_local
? "local-es":"");
10178 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
10179 const struct prefix
*p
, struct bgp_path_info
*path
,
10180 afi_t afi
, safi_t safi
,
10181 enum rpki_states rpki_curr_state
,
10182 json_object
*json_paths
)
10184 char buf
[INET6_ADDRSTRLEN
];
10186 struct attr
*attr
= path
->attr
;
10188 json_object
*json_bestpath
= NULL
;
10189 json_object
*json_cluster_list
= NULL
;
10190 json_object
*json_cluster_list_list
= NULL
;
10191 json_object
*json_ext_community
= NULL
;
10192 json_object
*json_last_update
= NULL
;
10193 json_object
*json_pmsi
= NULL
;
10194 json_object
*json_nexthop_global
= NULL
;
10195 json_object
*json_nexthop_ll
= NULL
;
10196 json_object
*json_nexthops
= NULL
;
10197 json_object
*json_path
= NULL
;
10198 json_object
*json_peer
= NULL
;
10199 json_object
*json_string
= NULL
;
10200 json_object
*json_adv_to
= NULL
;
10202 struct listnode
*node
, *nnode
;
10204 bool addpath_capable
;
10206 unsigned int first_as
;
10207 bool nexthop_self
=
10208 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
10210 char *nexthop_hostname
=
10211 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
10215 mpls_label_t label
= MPLS_INVALID_LABEL
;
10217 struct bgp_path_info
*bpi_ultimate
=
10218 bgp_get_imported_bpi_ultimate(path
);
10221 json_path
= json_object_new_object();
10222 json_peer
= json_object_new_object();
10223 json_nexthop_global
= json_object_new_object();
10226 if (safi
== SAFI_EVPN
) {
10228 vty_out(vty
, " Route %pFX", p
);
10232 if (path
->extra
&& path
->extra
->num_labels
) {
10233 bgp_evpn_label2str(path
->extra
->label
,
10234 path
->extra
->num_labels
, tag_buf
,
10237 if (safi
== SAFI_EVPN
) {
10239 if (tag_buf
[0] != '\0')
10240 vty_out(vty
, " VNI %s", tag_buf
);
10243 json_object_string_add(json_path
, "vni",
10249 if (safi
== SAFI_EVPN
10250 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
10251 char gwip_buf
[INET6_ADDRSTRLEN
];
10253 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
10257 json_object_string_add(json_path
, "gatewayIP",
10260 vty_out(vty
, " Gateway IP %s", gwip_buf
);
10263 if (safi
== SAFI_EVPN
&& !json_path
)
10264 vty_out(vty
, "\n");
10267 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
10268 struct bgp_path_info
*parent_ri
;
10269 struct bgp_dest
*dest
, *pdest
;
10271 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
10272 dest
= parent_ri
->net
;
10273 if (dest
&& dest
->pdest
) {
10274 pdest
= dest
->pdest
;
10275 if (is_pi_family_evpn(parent_ri
)) {
10276 vty_out(vty
, " Imported from ");
10277 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
10278 (struct prefix_rd
*)bgp_dest_get_prefix(
10280 vty_out(vty
, ":%pFX, VNI %s",
10281 (struct prefix_evpn
*)
10282 bgp_dest_get_prefix(dest
),
10284 if (CHECK_FLAG(attr
->es_flags
, ATTR_ES_L3_NHG
))
10285 vty_out(vty
, ", L3NHG %s",
10288 ATTR_ES_L3_NHG_ACTIVE
)
10291 vty_out(vty
, "\n");
10294 vty_out(vty
, " Imported from ");
10295 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
10296 (struct prefix_rd
*)bgp_dest_get_prefix(
10298 vty_out(vty
, ":%pFX\n",
10299 (struct prefix_evpn
*)
10300 bgp_dest_get_prefix(dest
));
10305 /* Line1 display AS-path, Aggregator */
10306 if (attr
->aspath
) {
10308 if (!attr
->aspath
->json
)
10309 aspath_str_update(attr
->aspath
, true);
10310 json_object_lock(attr
->aspath
->json
);
10311 json_object_object_add(json_path
, "aspath",
10312 attr
->aspath
->json
);
10314 if (attr
->aspath
->segments
)
10315 vty_out(vty
, " %s", attr
->aspath
->str
);
10317 vty_out(vty
, " Local");
10321 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
10323 json_object_boolean_true_add(json_path
, "removed");
10325 vty_out(vty
, ", (removed)");
10328 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10330 json_object_boolean_true_add(json_path
, "stale");
10332 vty_out(vty
, ", (stale)");
10335 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
10337 json_object_int_add(json_path
, "aggregatorAs",
10338 attr
->aggregator_as
);
10339 json_object_string_addf(json_path
, "aggregatorId",
10340 "%pI4", &attr
->aggregator_addr
);
10342 vty_out(vty
, ", (aggregated by %u %pI4)",
10343 attr
->aggregator_as
, &attr
->aggregator_addr
);
10347 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10348 PEER_FLAG_REFLECTOR_CLIENT
)) {
10350 json_object_boolean_true_add(json_path
,
10351 "rxedFromRrClient");
10353 vty_out(vty
, ", (Received from a RR-client)");
10356 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10357 PEER_FLAG_RSERVER_CLIENT
)) {
10359 json_object_boolean_true_add(json_path
,
10360 "rxedFromRsClient");
10362 vty_out(vty
, ", (Received from a RS-client)");
10365 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10367 json_object_boolean_true_add(json_path
,
10368 "dampeningHistoryEntry");
10370 vty_out(vty
, ", (history entry)");
10371 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10373 json_object_boolean_true_add(json_path
,
10374 "dampeningSuppressed");
10376 vty_out(vty
, ", (suppressed due to dampening)");
10380 vty_out(vty
, "\n");
10382 /* Line2 display Next-hop, Neighbor, Router-id */
10383 /* Display the nexthop */
10385 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
||
10386 p
->family
== AF_EVPN
) &&
10387 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
||
10388 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10389 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10390 || safi
== SAFI_EVPN
) {
10392 json_object_string_addf(
10393 json_nexthop_global
, "ip", "%pI4",
10394 &attr
->mp_nexthop_global_in
);
10396 if (path
->peer
->hostname
)
10397 json_object_string_add(
10398 json_nexthop_global
, "hostname",
10399 path
->peer
->hostname
);
10401 if (nexthop_hostname
)
10402 vty_out(vty
, " %pI4(%s)",
10403 &attr
->mp_nexthop_global_in
,
10406 vty_out(vty
, " %pI4",
10407 &attr
->mp_nexthop_global_in
);
10411 json_object_string_addf(json_nexthop_global
,
10415 if (path
->peer
->hostname
)
10416 json_object_string_add(
10417 json_nexthop_global
, "hostname",
10418 path
->peer
->hostname
);
10420 if (nexthop_hostname
)
10421 vty_out(vty
, " %pI4(%s)",
10425 vty_out(vty
, " %pI4",
10431 json_object_string_add(json_nexthop_global
, "afi",
10435 json_object_string_addf(json_nexthop_global
, "ip",
10437 &attr
->mp_nexthop_global
);
10439 if (path
->peer
->hostname
)
10440 json_object_string_add(json_nexthop_global
,
10442 path
->peer
->hostname
);
10444 json_object_string_add(json_nexthop_global
, "afi",
10446 json_object_string_add(json_nexthop_global
, "scope",
10449 if (nexthop_hostname
)
10450 vty_out(vty
, " %pI6(%s)",
10451 &attr
->mp_nexthop_global
,
10454 vty_out(vty
, " %pI6",
10455 &attr
->mp_nexthop_global
);
10459 /* Display the IGP cost or 'inaccessible' */
10460 if (!CHECK_FLAG(bpi_ultimate
->flags
, BGP_PATH_VALID
)) {
10461 bool import
= CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
);
10464 json_object_boolean_false_add(json_nexthop_global
,
10466 json_object_boolean_add(json_nexthop_global
,
10467 "importCheckEnabled", import
);
10469 vty_out(vty
, " (inaccessible%s)",
10470 import
? ", import-check enabled" : "");
10473 if (bpi_ultimate
->extra
&& bpi_ultimate
->extra
->igpmetric
) {
10475 json_object_int_add(
10476 json_nexthop_global
, "metric",
10477 bpi_ultimate
->extra
->igpmetric
);
10479 vty_out(vty
, " (metric %u)",
10480 bpi_ultimate
->extra
->igpmetric
);
10483 /* IGP cost is 0, display this only for json */
10486 json_object_int_add(json_nexthop_global
,
10491 json_object_boolean_true_add(json_nexthop_global
,
10495 /* Display peer "from" output */
10496 /* This path was originated locally */
10497 if (path
->peer
== bgp
->peer_self
) {
10499 if (safi
== SAFI_EVPN
|| (p
->family
== AF_INET
&&
10500 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10502 json_object_string_add(json_peer
, "peerId",
10505 vty_out(vty
, " from 0.0.0.0 ");
10508 json_object_string_add(json_peer
, "peerId",
10511 vty_out(vty
, " from :: ");
10515 json_object_string_addf(json_peer
, "routerId", "%pI4",
10518 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10521 /* We RXed this path from one of our peers */
10525 json_object_string_addf(json_peer
, "peerId", "%pSU",
10527 json_object_string_addf(json_peer
, "routerId", "%pI4",
10528 &path
->peer
->remote_id
);
10530 if (path
->peer
->hostname
)
10531 json_object_string_add(json_peer
, "hostname",
10532 path
->peer
->hostname
);
10534 if (path
->peer
->domainname
)
10535 json_object_string_add(json_peer
, "domainname",
10536 path
->peer
->domainname
);
10538 if (path
->peer
->conf_if
)
10539 json_object_string_add(json_peer
, "interface",
10540 path
->peer
->conf_if
);
10542 if (path
->peer
->conf_if
) {
10543 if (path
->peer
->hostname
10544 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10545 BGP_FLAG_SHOW_HOSTNAME
))
10546 vty_out(vty
, " from %s(%s)",
10547 path
->peer
->hostname
,
10548 path
->peer
->conf_if
);
10550 vty_out(vty
, " from %s",
10551 path
->peer
->conf_if
);
10553 if (path
->peer
->hostname
10554 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10555 BGP_FLAG_SHOW_HOSTNAME
))
10556 vty_out(vty
, " from %s(%s)",
10557 path
->peer
->hostname
,
10560 vty_out(vty
, " from %pSU",
10564 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10565 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10567 vty_out(vty
, " (%pI4)", &path
->peer
->remote_id
);
10572 * Note when vrfid of nexthop is different from that of prefix
10574 if (path
->extra
&& path
->extra
->bgp_orig
) {
10575 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10580 if (path
->extra
->bgp_orig
->inst_type
10581 == BGP_INSTANCE_TYPE_DEFAULT
)
10582 vn
= VRF_DEFAULT_NAME
;
10584 vn
= path
->extra
->bgp_orig
->name
;
10586 json_object_string_add(json_path
, "nhVrfName", vn
);
10588 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10589 json_object_int_add(json_path
, "nhVrfId", -1);
10591 json_object_int_add(json_path
, "nhVrfId",
10592 (int)nexthop_vrfid
);
10595 if (nexthop_vrfid
== VRF_UNKNOWN
)
10596 vty_out(vty
, " vrf ?");
10600 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10601 vty_out(vty
, " vrf %s(%u)",
10602 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10607 if (nexthop_self
) {
10609 json_object_boolean_true_add(json_path
,
10610 "announceNexthopSelf");
10612 vty_out(vty
, " announce-nh-self");
10617 vty_out(vty
, "\n");
10619 /* display the link-local nexthop */
10620 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10622 json_nexthop_ll
= json_object_new_object();
10623 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10624 &attr
->mp_nexthop_local
);
10626 if (path
->peer
->hostname
)
10627 json_object_string_add(json_nexthop_ll
,
10629 path
->peer
->hostname
);
10631 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10632 json_object_string_add(json_nexthop_ll
, "scope",
10635 json_object_boolean_true_add(json_nexthop_ll
,
10638 if (!attr
->mp_nexthop_prefer_global
)
10639 json_object_boolean_true_add(json_nexthop_ll
,
10642 json_object_boolean_true_add(
10643 json_nexthop_global
, "used");
10645 vty_out(vty
, " (%s) %s\n",
10646 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10647 buf
, INET6_ADDRSTRLEN
),
10648 attr
->mp_nexthop_prefer_global
10649 ? "(prefer-global)"
10653 /* If we do not have a link-local nexthop then we must flag the
10654 global as "used" */
10657 json_object_boolean_true_add(json_nexthop_global
,
10661 if (safi
== SAFI_EVPN
&&
10662 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10663 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10666 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10667 * Int/Ext/Local, Atomic, best */
10669 json_object_string_add(json_path
, "origin",
10670 bgp_origin_long_str
[attr
->origin
]);
10672 vty_out(vty
, " Origin %s",
10673 bgp_origin_long_str
[attr
->origin
]);
10675 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10677 json_object_int_add(json_path
, "metric", attr
->med
);
10679 vty_out(vty
, ", metric %u", attr
->med
);
10682 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10684 json_object_int_add(json_path
, "locPrf",
10687 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10690 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
10692 json_object_int_add(json_path
, "aigpMetric",
10693 bgp_attr_get_aigp_metric(attr
));
10695 vty_out(vty
, ", aigp-metric %" PRIu64
,
10696 bgp_attr_get_aigp_metric(attr
));
10699 if (attr
->weight
!= 0) {
10701 json_object_int_add(json_path
, "weight", attr
->weight
);
10703 vty_out(vty
, ", weight %u", attr
->weight
);
10706 if (attr
->tag
!= 0) {
10708 json_object_int_add(json_path
, "tag", attr
->tag
);
10710 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10713 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10715 json_object_boolean_false_add(json_path
, "valid");
10717 vty_out(vty
, ", invalid");
10718 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10720 json_object_boolean_true_add(json_path
, "valid");
10722 vty_out(vty
, ", valid");
10726 json_object_int_add(json_path
, "version", bn
->version
);
10728 if (path
->peer
!= bgp
->peer_self
) {
10729 if (path
->peer
->as
== path
->peer
->local_as
) {
10730 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10732 json_object_string_add(
10734 "confed-internal");
10736 vty_out(vty
, ", confed-internal");
10739 json_object_string_add(
10740 json_peer
, "type", "internal");
10742 vty_out(vty
, ", internal");
10745 if (bgp_confederation_peers_check(bgp
,
10748 json_object_string_add(
10750 "confed-external");
10752 vty_out(vty
, ", confed-external");
10755 json_object_string_add(
10756 json_peer
, "type", "external");
10758 vty_out(vty
, ", external");
10761 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10763 json_object_boolean_true_add(json_path
, "aggregated");
10764 json_object_boolean_true_add(json_path
, "local");
10766 vty_out(vty
, ", aggregated, local");
10768 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10770 json_object_boolean_true_add(json_path
, "sourced");
10772 vty_out(vty
, ", sourced");
10775 json_object_boolean_true_add(json_path
, "sourced");
10776 json_object_boolean_true_add(json_path
, "local");
10778 vty_out(vty
, ", sourced, local");
10782 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10784 json_object_boolean_true_add(json_path
,
10785 "atomicAggregate");
10787 vty_out(vty
, ", atomic-aggregate");
10790 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
10792 json_object_int_add(json_path
, "otc", attr
->otc
);
10794 vty_out(vty
, ", otc %u", attr
->otc
);
10797 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10798 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10799 && bgp_path_info_mpath_count(path
))) {
10801 json_object_boolean_true_add(json_path
, "multipath");
10803 vty_out(vty
, ", multipath");
10806 // Mark the bestpath(s)
10807 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10808 first_as
= aspath_get_first_as(attr
->aspath
);
10811 if (!json_bestpath
)
10812 json_bestpath
= json_object_new_object();
10813 json_object_int_add(json_bestpath
, "bestpathFromAs",
10817 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10819 vty_out(vty
, ", bestpath-from-AS Local");
10823 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10825 if (!json_bestpath
)
10826 json_bestpath
= json_object_new_object();
10827 json_object_boolean_true_add(json_bestpath
, "overall");
10828 json_object_string_add(
10829 json_bestpath
, "selectionReason",
10830 bgp_path_selection_reason2str(bn
->reason
));
10832 vty_out(vty
, ", best");
10833 vty_out(vty
, " (%s)",
10834 bgp_path_selection_reason2str(bn
->reason
));
10838 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10840 json_object_string_add(
10841 json_path
, "rpkiValidationState",
10842 bgp_rpki_validation2str(rpki_curr_state
));
10844 vty_out(vty
, ", rpki validation-state: %s",
10845 bgp_rpki_validation2str(rpki_curr_state
));
10849 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10852 vty_out(vty
, "\n");
10854 /* Line 4 display Community */
10855 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10857 if (!bgp_attr_get_community(attr
)->json
)
10858 community_str(bgp_attr_get_community(attr
),
10860 json_object_lock(bgp_attr_get_community(attr
)->json
);
10861 json_object_object_add(
10862 json_path
, "community",
10863 bgp_attr_get_community(attr
)->json
);
10865 vty_out(vty
, " Community: %s\n",
10866 bgp_attr_get_community(attr
)->str
);
10870 /* Line 5 display Extended-community */
10871 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10873 json_ext_community
= json_object_new_object();
10874 json_object_string_add(
10875 json_ext_community
, "string",
10876 bgp_attr_get_ecommunity(attr
)->str
);
10877 json_object_object_add(json_path
, "extendedCommunity",
10878 json_ext_community
);
10880 vty_out(vty
, " Extended Community: %s\n",
10881 bgp_attr_get_ecommunity(attr
)->str
);
10885 /* Line 6 display Large community */
10886 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10888 if (!bgp_attr_get_lcommunity(attr
)->json
)
10889 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10891 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10892 json_object_object_add(
10893 json_path
, "largeCommunity",
10894 bgp_attr_get_lcommunity(attr
)->json
);
10896 vty_out(vty
, " Large Community: %s\n",
10897 bgp_attr_get_lcommunity(attr
)->str
);
10901 /* Line 7 display Originator, Cluster-id */
10902 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10903 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10904 char buf
[BUFSIZ
] = {0};
10906 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10908 json_object_string_addf(json_path
,
10909 "originatorId", "%pI4",
10910 &attr
->originator_id
);
10912 vty_out(vty
, " Originator: %pI4",
10913 &attr
->originator_id
);
10916 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10917 struct cluster_list
*cluster
=
10918 bgp_attr_get_cluster(attr
);
10922 json_cluster_list
= json_object_new_object();
10923 json_cluster_list_list
=
10924 json_object_new_array();
10926 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10927 json_string
= json_object_new_string(
10930 buf
, sizeof(buf
)));
10931 json_object_array_add(
10932 json_cluster_list_list
,
10937 * struct cluster_list does not have
10938 * "str" variable like aspath and community
10939 * do. Add this someday if someone asks
10941 * json_object_string_add(json_cluster_list,
10942 * "string", cluster->str);
10944 json_object_object_add(json_cluster_list
,
10946 json_cluster_list_list
);
10947 json_object_object_add(json_path
, "clusterList",
10948 json_cluster_list
);
10950 vty_out(vty
, ", Cluster list: ");
10952 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10953 vty_out(vty
, "%pI4 ",
10954 &cluster
->list
[i
]);
10960 vty_out(vty
, "\n");
10963 if (path
->extra
&& path
->extra
->damp_info
)
10964 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
10967 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10968 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10969 mpls_lse_decode(path
->extra
->label
[0], &label
, &ttl
, &exp
,
10973 json_object_int_add(json_path
, "remoteLabel", label
);
10975 vty_out(vty
, " Remote label: %d\n", label
);
10979 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10981 json_object_string_addf(json_path
, "remoteSid", "%pI6",
10982 &path
->extra
->sid
[0].sid
);
10984 vty_out(vty
, " Remote SID: %pI6\n",
10985 &path
->extra
->sid
[0].sid
);
10989 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
10991 json_object_int_add(json_path
, "labelIndex",
10992 attr
->label_index
);
10994 vty_out(vty
, " Label Index: %d\n",
10995 attr
->label_index
);
10998 /* Line 8 display Addpath IDs */
10999 if (path
->addpath_rx_id
11000 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
11002 json_object_int_add(json_path
, "addpathRxId",
11003 path
->addpath_rx_id
);
11005 /* Keep backwards compatibility with the old API
11006 * by putting TX All's ID in the old field
11008 json_object_int_add(
11009 json_path
, "addpathTxId",
11011 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
11013 /* ... but create a specific field for each
11016 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
11017 json_object_int_add(
11019 bgp_addpath_names(i
)->id_json_name
,
11020 path
->tx_addpath
.addpath_tx_id
[i
]);
11023 vty_out(vty
, " AddPath ID: RX %u, ",
11024 path
->addpath_rx_id
);
11026 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
11030 /* If we used addpath to TX a non-bestpath we need to display
11031 * "Advertised to" on a path-by-path basis
11033 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11036 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11038 bgp_addpath_encode_tx(peer
, afi
, safi
);
11039 has_adj
= bgp_adj_out_lookup(
11041 bgp_addpath_id_for_peer(peer
, afi
, safi
,
11042 &path
->tx_addpath
));
11044 if ((addpath_capable
&& has_adj
)
11045 || (!addpath_capable
&& has_adj
11046 && CHECK_FLAG(path
->flags
,
11047 BGP_PATH_SELECTED
))) {
11048 if (json_path
&& !json_adv_to
)
11049 json_adv_to
= json_object_new_object();
11051 route_vty_out_advertised_to(
11053 " Advertised to:", json_adv_to
);
11059 json_object_object_add(
11060 json_path
, "advertisedTo", json_adv_to
);
11064 vty_out(vty
, "\n");
11069 /* Line 9 display Uptime */
11070 tbuf
= time(NULL
) - (monotime(NULL
) - path
->uptime
);
11072 json_last_update
= json_object_new_object();
11073 json_object_int_add(json_last_update
, "epoch", tbuf
);
11074 json_object_string_add(json_last_update
, "string",
11076 json_object_object_add(json_path
, "lastUpdate",
11079 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
11081 /* Line 10 display PMSI tunnel attribute, if present */
11082 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
11083 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
11084 bgp_attr_get_pmsi_tnl_type(attr
),
11085 PMSI_TNLTYPE_STR_DEFAULT
);
11088 json_pmsi
= json_object_new_object();
11089 json_object_string_add(json_pmsi
, "tunnelType", str
);
11090 json_object_int_add(json_pmsi
, "label",
11091 label2vni(&attr
->label
));
11092 json_object_object_add(json_path
, "pmsi", json_pmsi
);
11094 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
11095 str
, label2vni(&attr
->label
));
11098 if (path
->peer
->t_gr_restart
&&
11099 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
11100 unsigned long gr_remaining
=
11101 event_timer_remain_second(path
->peer
->t_gr_restart
);
11104 json_object_int_add(json_path
,
11105 "gracefulRestartSecondsRemaining",
11109 " Time until Graceful Restart stale route deleted: %lu\n",
11113 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
11114 bgp_attr_get_community(attr
) &&
11115 community_include(bgp_attr_get_community(attr
),
11116 COMMUNITY_LLGR_STALE
)) {
11117 unsigned long llgr_remaining
= event_timer_remain_second(
11118 path
->peer
->t_llgr_stale
[afi
][safi
]);
11121 json_object_int_add(json_path
, "llgrSecondsRemaining",
11125 " Time until Long-lived stale route deleted: %lu\n",
11129 /* Output some debug about internal state of the dest flags */
11131 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
11132 json_object_boolean_true_add(json_path
, "processScheduled");
11133 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
11134 json_object_boolean_true_add(json_path
, "userCleared");
11135 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
11136 json_object_boolean_true_add(json_path
, "labelChanged");
11137 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
11138 json_object_boolean_true_add(json_path
, "registeredForLabel");
11139 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
11140 json_object_boolean_true_add(json_path
, "selectDefered");
11141 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
11142 json_object_boolean_true_add(json_path
, "fibInstalled");
11143 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
11144 json_object_boolean_true_add(json_path
, "fibPending");
11146 if (json_nexthop_global
|| json_nexthop_ll
) {
11147 json_nexthops
= json_object_new_array();
11149 if (json_nexthop_global
)
11150 json_object_array_add(json_nexthops
,
11151 json_nexthop_global
);
11153 if (json_nexthop_ll
)
11154 json_object_array_add(json_nexthops
,
11157 json_object_object_add(json_path
, "nexthops",
11161 json_object_object_add(json_path
, "peer", json_peer
);
11162 json_object_array_add(json_paths
, json_path
);
11166 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
11167 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11168 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
11170 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11171 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11173 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11174 const char *comstr
, int exact
, afi_t afi
,
11175 safi_t safi
, uint16_t show_flags
);
11177 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11178 struct bgp_table
*table
, enum bgp_show_type type
,
11179 void *output_arg
, const char *rd
, int is_last
,
11180 unsigned long *output_cum
, unsigned long *total_cum
,
11181 unsigned long *json_header_depth
, uint16_t show_flags
,
11182 enum rpki_states rpki_target_state
)
11184 struct bgp_path_info
*pi
;
11185 struct bgp_dest
*dest
;
11186 bool header
= true;
11187 bool json_detail_header
= false;
11189 unsigned long output_count
= 0;
11190 unsigned long total_count
= 0;
11192 json_object
*json_paths
= NULL
;
11194 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11195 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11196 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11197 bool detail_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
11198 bool detail_routes
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
11200 if (output_cum
&& *output_cum
!= 0)
11203 if (use_json
&& !*json_header_depth
) {
11205 *json_header_depth
= 1;
11207 vty_out(vty
, "{\n");
11208 *json_header_depth
= 2;
11211 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11212 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
11214 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
11215 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
11218 table
->version
, &bgp
->router_id
,
11219 bgp
->default_local_pref
);
11220 if ((bgp
->asnotation
== ASNOTATION_PLAIN
) ||
11221 ((bgp
->asnotation
== ASNOTATION_DOT
) &&
11222 (bgp
->as
< UINT16_MAX
)))
11223 vty_out(vty
, "%u", bgp
->as
);
11225 vty_out(vty
, "\"");
11226 vty_out(vty
, ASN_FORMAT(bgp
->asnotation
), &bgp
->as
);
11227 vty_out(vty
, "\"");
11229 vty_out(vty
, ",\n \"routes\": { ");
11231 vty_out(vty
, " \"routeDistinguishers\" : {");
11232 ++*json_header_depth
;
11236 if (use_json
&& rd
) {
11237 vty_out(vty
, " \"%s\" : { ", rd
);
11240 /* Check for 'json detail', where we need header output once per dest */
11241 if (use_json
&& detail_json
&& type
!= bgp_show_type_dampend_paths
&&
11242 type
!= bgp_show_type_damp_neighbor
&&
11243 type
!= bgp_show_type_flap_statistics
&&
11244 type
!= bgp_show_type_flap_neighbor
)
11245 json_detail_header
= true;
11247 /* Start processing of routes. */
11248 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
11249 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11250 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11251 bool json_detail_header_used
= false;
11253 pi
= bgp_dest_get_bgp_path_info(dest
);
11259 json_paths
= json_object_new_array();
11263 for (; pi
; pi
= pi
->next
) {
11264 struct community
*picomm
= NULL
;
11266 picomm
= bgp_attr_get_community(pi
->attr
);
11270 if (type
== bgp_show_type_prefix_version
) {
11272 strtoul(output_arg
, NULL
, 10);
11273 if (dest
->version
< version
)
11277 if (type
== bgp_show_type_community_alias
) {
11278 char *alias
= output_arg
;
11279 char **communities
;
11281 bool found
= false;
11284 frrstr_split(picomm
->str
, " ",
11285 &communities
, &num
);
11286 for (int i
= 0; i
< num
; i
++) {
11287 const char *com2alias
=
11288 bgp_community2alias(
11291 && strcmp(alias
, com2alias
)
11297 XFREE(MTYPE_TMP
, communities
);
11301 bgp_attr_get_lcommunity(pi
->attr
)) {
11302 frrstr_split(bgp_attr_get_lcommunity(
11305 " ", &communities
, &num
);
11306 for (int i
= 0; i
< num
; i
++) {
11307 const char *com2alias
=
11308 bgp_community2alias(
11311 && strcmp(alias
, com2alias
)
11317 XFREE(MTYPE_TMP
, communities
);
11324 if (type
== bgp_show_type_rpki
) {
11325 if (dest_p
->family
== AF_INET
11326 || dest_p
->family
== AF_INET6
)
11327 rpki_curr_state
= hook_call(
11328 bgp_rpki_prefix_status
,
11329 pi
->peer
, pi
->attr
, dest_p
);
11330 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11331 && rpki_curr_state
!= rpki_target_state
)
11335 if (type
== bgp_show_type_flap_statistics
11336 || type
== bgp_show_type_flap_neighbor
11337 || type
== bgp_show_type_dampend_paths
11338 || type
== bgp_show_type_damp_neighbor
) {
11339 if (!(pi
->extra
&& pi
->extra
->damp_info
))
11342 if (type
== bgp_show_type_regexp
) {
11343 regex_t
*regex
= output_arg
;
11345 if (bgp_regexec(regex
, pi
->attr
->aspath
)
11349 if (type
== bgp_show_type_prefix_list
) {
11350 struct prefix_list
*plist
= output_arg
;
11352 if (prefix_list_apply(plist
, dest_p
)
11356 if (type
== bgp_show_type_access_list
) {
11357 struct access_list
*alist
= output_arg
;
11359 if (access_list_apply(alist
, dest_p
) !=
11363 if (type
== bgp_show_type_filter_list
) {
11364 struct as_list
*as_list
= output_arg
;
11366 if (as_list_apply(as_list
, pi
->attr
->aspath
)
11367 != AS_FILTER_PERMIT
)
11370 if (type
== bgp_show_type_route_map
) {
11371 struct route_map
*rmap
= output_arg
;
11372 struct bgp_path_info path
;
11373 struct bgp_path_info_extra extra
;
11374 struct attr dummy_attr
= {};
11375 route_map_result_t ret
;
11377 dummy_attr
= *pi
->attr
;
11379 prep_for_rmap_apply(&path
, &extra
, dest
, pi
,
11380 pi
->peer
, &dummy_attr
);
11382 ret
= route_map_apply(rmap
, dest_p
, &path
);
11383 bgp_attr_flush(&dummy_attr
);
11384 if (ret
== RMAP_DENYMATCH
)
11387 if (type
== bgp_show_type_neighbor
11388 || type
== bgp_show_type_flap_neighbor
11389 || type
== bgp_show_type_damp_neighbor
) {
11390 union sockunion
*su
= output_arg
;
11392 if (pi
->peer
== NULL
11393 || pi
->peer
->su_remote
== NULL
11394 || !sockunion_same(pi
->peer
->su_remote
, su
))
11397 if (type
== bgp_show_type_cidr_only
) {
11398 uint32_t destination
;
11400 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11401 if (IN_CLASSC(destination
)
11402 && dest_p
->prefixlen
== 24)
11404 if (IN_CLASSB(destination
)
11405 && dest_p
->prefixlen
== 16)
11407 if (IN_CLASSA(destination
)
11408 && dest_p
->prefixlen
== 8)
11411 if (type
== bgp_show_type_prefix_longer
) {
11413 if (!prefix_match(p
, dest_p
))
11416 if (type
== bgp_show_type_community_all
) {
11420 if (type
== bgp_show_type_community
) {
11421 struct community
*com
= output_arg
;
11423 if (!picomm
|| !community_match(picomm
, com
))
11426 if (type
== bgp_show_type_community_exact
) {
11427 struct community
*com
= output_arg
;
11429 if (!picomm
|| !community_cmp(picomm
, com
))
11432 if (type
== bgp_show_type_community_list
) {
11433 struct community_list
*list
= output_arg
;
11435 if (!community_list_match(picomm
, list
))
11438 if (type
== bgp_show_type_community_list_exact
) {
11439 struct community_list
*list
= output_arg
;
11441 if (!community_list_exact_match(picomm
, list
))
11444 if (type
== bgp_show_type_lcommunity
) {
11445 struct lcommunity
*lcom
= output_arg
;
11447 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11449 bgp_attr_get_lcommunity(pi
->attr
),
11454 if (type
== bgp_show_type_lcommunity_exact
) {
11455 struct lcommunity
*lcom
= output_arg
;
11457 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11459 bgp_attr_get_lcommunity(pi
->attr
),
11463 if (type
== bgp_show_type_lcommunity_list
) {
11464 struct community_list
*list
= output_arg
;
11466 if (!lcommunity_list_match(
11467 bgp_attr_get_lcommunity(pi
->attr
),
11472 == bgp_show_type_lcommunity_list_exact
) {
11473 struct community_list
*list
= output_arg
;
11475 if (!lcommunity_list_exact_match(
11476 bgp_attr_get_lcommunity(pi
->attr
),
11480 if (type
== bgp_show_type_lcommunity_all
) {
11481 if (!bgp_attr_get_lcommunity(pi
->attr
))
11484 if (type
== bgp_show_type_dampend_paths
11485 || type
== bgp_show_type_damp_neighbor
) {
11486 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11487 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11490 if (type
== bgp_show_type_self_originated
) {
11491 if (pi
->peer
!= bgp
->peer_self
)
11495 if (!use_json
&& header
) {
11497 "BGP table version is %" PRIu64
11498 ", local router ID is %pI4, vrf id ",
11499 table
->version
, &bgp
->router_id
);
11500 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11501 vty_out(vty
, "%s", VRFID_NONE_STR
);
11503 vty_out(vty
, "%u", bgp
->vrf_id
);
11504 vty_out(vty
, "\n");
11505 vty_out(vty
, "Default local pref %u, ",
11506 bgp
->default_local_pref
);
11507 vty_out(vty
, "local AS ");
11508 vty_out(vty
, ASN_FORMAT(bgp
->asnotation
),
11510 vty_out(vty
, "\n");
11511 if (!detail_routes
) {
11512 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11513 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11514 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11515 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11517 if (type
== bgp_show_type_dampend_paths
11518 || type
== bgp_show_type_damp_neighbor
)
11519 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11520 else if (type
== bgp_show_type_flap_statistics
11521 || type
== bgp_show_type_flap_neighbor
)
11522 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11523 else if (!detail_routes
)
11524 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11525 : BGP_SHOW_HEADER
));
11529 if (rd
!= NULL
&& !display
&& !output_count
) {
11532 "Route Distinguisher: %s\n",
11535 if (type
== bgp_show_type_dampend_paths
11536 || type
== bgp_show_type_damp_neighbor
)
11537 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11538 AFI_IP
, safi
, use_json
,
11540 else if (type
== bgp_show_type_flap_statistics
11541 || type
== bgp_show_type_flap_neighbor
)
11542 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11543 AFI_IP
, safi
, use_json
,
11546 if (detail_routes
|| detail_json
) {
11547 const struct prefix_rd
*prd
= NULL
;
11550 prd
= bgp_rd_from_dest(
11551 dest
->pdest
, safi
);
11554 route_vty_out_detail_header(
11556 bgp_dest_get_prefix(
11558 prd
, table
->afi
, safi
,
11561 route_vty_out_detail(
11562 vty
, bgp
, dest
, dest_p
, pi
,
11563 family2afi(dest_p
->family
),
11564 safi
, RPKI_NOT_BEING_USED
,
11567 route_vty_out(vty
, dest_p
, pi
, display
,
11568 safi
, json_paths
, wide
);
11579 /* encode prefix */
11580 if (dest_p
->family
== AF_FLOWSPEC
) {
11581 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11584 bgp_fs_nlri_get_string(
11586 dest_p
->u
.prefix_flowspec
.ptr
,
11587 dest_p
->u
.prefix_flowspec
.prefixlen
,
11588 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11589 family2afi(dest_p
->u
11590 .prefix_flowspec
.family
));
11592 vty_out(vty
, "\"%s/%d\": ", retstr
,
11593 dest_p
->u
.prefix_flowspec
11596 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11597 dest_p
->u
.prefix_flowspec
11601 vty_out(vty
, "\"%pFX\": ", dest_p
);
11603 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11606 if (json_detail_header
&& json_paths
!= NULL
) {
11607 const struct prefix_rd
*prd
;
11609 vty_out(vty
, "{\n");
11611 prd
= bgp_rd_from_dest(dest
, safi
);
11613 route_vty_out_detail_header(
11615 bgp_dest_get_prefix(dest
), prd
,
11616 table
->afi
, safi
, json_paths
, true);
11618 vty_out(vty
, "\"paths\": ");
11619 json_detail_header_used
= true;
11623 * We are using no_pretty here because under
11624 * extremely high settings( say lots and lots of
11625 * routes with lots and lots of ways to reach
11626 * that route via different paths ) this can
11627 * save several minutes of output when FRR
11628 * is run on older cpu's or more underperforming
11629 * routers out there
11631 vty_json_no_pretty(vty
, json_paths
);
11633 if (json_detail_header_used
)
11634 vty_out(vty
, "} ");
11639 json_object_free(json_paths
);
11643 output_count
+= *output_cum
;
11644 *output_cum
= output_count
;
11647 total_count
+= *total_cum
;
11648 *total_cum
= total_count
;
11652 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11656 for (i
= 0; i
< *json_header_depth
; ++i
)
11657 vty_out(vty
, " } ");
11659 vty_out(vty
, "\n");
11663 /* No route is displayed */
11664 if (output_count
== 0) {
11665 if (type
== bgp_show_type_normal
)
11667 "No BGP prefixes displayed, %ld exist\n",
11671 "\nDisplayed %ld routes and %ld total paths\n",
11672 output_count
, total_count
);
11676 return CMD_SUCCESS
;
11679 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11680 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11681 enum bgp_show_type type
, void *output_arg
,
11682 uint16_t show_flags
)
11684 struct bgp_dest
*dest
, *next
;
11685 unsigned long output_cum
= 0;
11686 unsigned long total_cum
= 0;
11687 unsigned long json_header_depth
= 0;
11688 struct bgp_table
*itable
;
11690 bool use_json
= !!CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11692 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11694 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11695 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11697 next
= bgp_route_next(dest
);
11698 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11701 itable
= bgp_dest_get_bgp_table_info(dest
);
11702 if (itable
!= NULL
) {
11703 struct prefix_rd prd
;
11704 char rd
[RD_ADDRSTRLEN
];
11706 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11707 prefix_rd2str(&prd
, rd
, sizeof(rd
), bgp
->asnotation
);
11708 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11709 rd
, next
== NULL
, &output_cum
,
11710 &total_cum
, &json_header_depth
,
11711 show_flags
, RPKI_NOT_BEING_USED
);
11717 if (output_cum
== 0)
11718 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11722 "\nDisplayed %ld routes and %ld total paths\n",
11723 output_cum
, total_cum
);
11725 if (use_json
&& output_cum
== 0)
11726 vty_out(vty
, "{}\n");
11728 return CMD_SUCCESS
;
11731 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11732 enum bgp_show_type type
, void *output_arg
,
11733 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11735 struct bgp_table
*table
;
11736 unsigned long json_header_depth
= 0;
11737 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11740 bgp
= bgp_get_default();
11745 vty_out(vty
, "No BGP process is configured\n");
11747 vty_out(vty
, "{}\n");
11748 return CMD_WARNING
;
11751 /* Labeled-unicast routes live in the unicast table. */
11752 if (safi
== SAFI_LABELED_UNICAST
)
11753 safi
= SAFI_UNICAST
;
11755 table
= bgp
->rib
[afi
][safi
];
11756 /* use MPLS and ENCAP specific shows until they are merged */
11757 if (safi
== SAFI_MPLS_VPN
) {
11758 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11759 output_arg
, show_flags
);
11762 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11763 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11764 output_arg
, use_json
,
11768 if (safi
== SAFI_EVPN
)
11769 return bgp_evpn_show_all_routes(vty
, bgp
, type
, use_json
, 0);
11771 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11772 NULL
, NULL
, &json_header_depth
, show_flags
,
11773 rpki_target_state
);
11776 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11777 safi_t safi
, uint16_t show_flags
)
11779 struct listnode
*node
, *nnode
;
11782 bool route_output
= false;
11783 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11786 vty_out(vty
, "{\n");
11788 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11789 route_output
= true;
11792 vty_out(vty
, ",\n");
11796 vty_out(vty
, "\"%s\":",
11797 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11801 vty_out(vty
, "\nInstance %s:\n",
11802 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11806 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11807 show_flags
, RPKI_NOT_BEING_USED
);
11811 vty_out(vty
, "}\n");
11812 else if (!route_output
)
11813 vty_out(vty
, "%% BGP instance not found\n");
11816 /* Header of detailed BGP route information */
11817 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11818 struct bgp_dest
*dest
, const struct prefix
*p
,
11819 const struct prefix_rd
*prd
, afi_t afi
,
11820 safi_t safi
, json_object
*json
,
11821 bool incremental_print
)
11823 struct bgp_path_info
*pi
;
11825 struct listnode
*node
, *nnode
;
11826 char buf1
[RD_ADDRSTRLEN
];
11830 int accept_own
= 0;
11831 int route_filter_translated_v4
= 0;
11832 int route_filter_v4
= 0;
11833 int route_filter_translated_v6
= 0;
11834 int route_filter_v6
= 0;
11835 int llgr_stale
= 0;
11837 int accept_own_nexthop
= 0;
11840 int no_advertise
= 0;
11844 int has_valid_label
= 0;
11845 mpls_label_t label
= 0;
11846 json_object
*json_adv_to
= NULL
;
11851 mpls_lse_decode(dest
->local_label
, &label
, &ttl
, &exp
, &bos
);
11853 has_valid_label
= bgp_is_valid_label(&label
);
11855 if (safi
== SAFI_EVPN
) {
11857 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11858 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
),
11861 prd
? ":" : "", (struct prefix_evpn
*)p
);
11863 json_object_string_add(
11865 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
),
11868 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11873 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11875 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11876 ? prefix_rd2str(prd
, buf1
,
11880 safi
== SAFI_MPLS_VPN
? ":" : "", p
,
11884 if (incremental_print
) {
11885 vty_out(vty
, "\"prefix\": \"%pFX\",\n", p
);
11886 vty_out(vty
, "\"version\": \"%" PRIu64
"\",\n",
11889 json_object_string_addf(json
, "prefix", "%pFX",
11891 json_object_int_add(json
, "version",
11897 if (has_valid_label
) {
11899 if (incremental_print
)
11900 vty_out(vty
, "\"localLabel\": \"%u\",\n",
11903 json_object_int_add(json
, "localLabel", label
);
11905 vty_out(vty
, "Local label: %d\n", label
);
11909 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11910 vty_out(vty
, "not allocated\n");
11912 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11913 struct community
*picomm
= NULL
;
11915 picomm
= bgp_attr_get_community(pi
->attr
);
11918 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11920 if (bgp_path_suppressed(pi
))
11926 no_advertise
+= community_include(
11927 picomm
, COMMUNITY_NO_ADVERTISE
);
11929 community_include(picomm
, COMMUNITY_NO_EXPORT
);
11931 community_include(picomm
, COMMUNITY_LOCAL_AS
);
11933 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
11934 route_filter_translated_v4
+= community_include(
11935 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11936 route_filter_translated_v6
+= community_include(
11937 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11938 route_filter_v4
+= community_include(
11939 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
11940 route_filter_v6
+= community_include(
11941 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
11943 community_include(picomm
, COMMUNITY_LLGR_STALE
);
11944 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
11945 accept_own_nexthop
+= community_include(
11946 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11948 community_include(picomm
, COMMUNITY_BLACKHOLE
);
11949 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
11954 vty_out(vty
, "Paths: (%d available", count
);
11956 vty_out(vty
, ", best #%d", best
);
11957 if (safi
== SAFI_UNICAST
) {
11958 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11959 vty_out(vty
, ", table %s",
11962 vty_out(vty
, ", vrf %s",
11966 vty_out(vty
, ", no best path");
11970 ", accept own local route exported and imported in different VRF");
11971 else if (route_filter_translated_v4
)
11973 ", mark translated RTs for VPNv4 route filtering");
11974 else if (route_filter_v4
)
11976 ", attach RT as-is for VPNv4 route filtering");
11977 else if (route_filter_translated_v6
)
11979 ", mark translated RTs for VPNv6 route filtering");
11980 else if (route_filter_v6
)
11982 ", attach RT as-is for VPNv6 route filtering");
11983 else if (llgr_stale
)
11985 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
11988 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11989 else if (accept_own_nexthop
)
11991 ", accept local nexthop");
11992 else if (blackhole
)
11993 vty_out(vty
, ", inform peer to blackhole prefix");
11994 else if (no_export
)
11995 vty_out(vty
, ", not advertised to EBGP peer");
11996 else if (no_advertise
)
11997 vty_out(vty
, ", not advertised to any peer");
11999 vty_out(vty
, ", not advertised outside local AS");
12002 ", inform EBGP peer not to advertise to their EBGP peers");
12006 ", Advertisements suppressed by an aggregate.");
12007 vty_out(vty
, ")\n");
12010 /* If we are not using addpath then we can display Advertised to and
12012 * show what peers we advertised the bestpath to. If we are using
12014 * though then we must display Advertised to on a path-by-path basis. */
12015 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
12016 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
12017 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
12018 if (json
&& !json_adv_to
)
12019 json_adv_to
= json_object_new_object();
12021 route_vty_out_advertised_to(
12023 " Advertised to non peer-group peers:\n ",
12028 if (json
&& json_adv_to
) {
12029 if (incremental_print
) {
12030 vty_out(vty
, "\"advertisedTo\": ");
12031 vty_json(vty
, json_adv_to
);
12034 json_object_object_add(json
, "advertisedTo",
12037 if (!json
&& first
)
12038 vty_out(vty
, " Not advertised to any peer");
12039 vty_out(vty
, "\n");
12044 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
12045 struct bgp_dest
*bgp_node
, struct vty
*vty
,
12046 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
12047 json_object
*json
, enum bgp_path_type pathtype
,
12048 int *display
, enum rpki_states rpki_target_state
)
12050 struct bgp_path_info
*pi
;
12052 json_object
*json_header
= NULL
;
12053 json_object
*json_paths
= NULL
;
12054 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
12056 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
12057 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
12059 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
12060 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
12061 pi
->peer
, pi
->attr
, p
);
12063 if (rpki_target_state
!= RPKI_NOT_BEING_USED
12064 && rpki_curr_state
!= rpki_target_state
)
12067 if (json
&& !json_paths
) {
12068 /* Instantiate json_paths only if path is valid */
12069 json_paths
= json_object_new_array();
12071 json_header
= json_object_new_object();
12073 json_header
= json
;
12077 route_vty_out_detail_header(
12078 vty
, bgp
, bgp_node
,
12079 bgp_dest_get_prefix(bgp_node
), pfx_rd
, AFI_IP
,
12080 safi
, json_header
, false);
12085 if (pathtype
== BGP_PATH_SHOW_ALL
12086 || (pathtype
== BGP_PATH_SHOW_BESTPATH
12087 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12088 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
12089 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
12090 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
12091 route_vty_out_detail(vty
, bgp
, bgp_node
,
12092 bgp_dest_get_prefix(bgp_node
), pi
,
12093 AFI_IP
, safi
, rpki_curr_state
,
12097 if (json
&& json_paths
) {
12098 json_object_object_add(json_header
, "paths", json_paths
);
12101 json_object_object_addf(
12103 BGP_RD_AS_FORMAT(bgp
->asnotation
), pfx_rd
);
12108 * Return rd based on safi
12110 const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
12114 case SAFI_MPLS_VPN
:
12117 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
12120 case SAFI_MULTICAST
:
12121 case SAFI_LABELED_UNICAST
:
12122 case SAFI_FLOWSPEC
:
12127 assert(!"Reached end of function when we were not expecting it");
12130 /* Display specified route of BGP table. */
12131 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
12132 struct bgp_table
*rib
, const char *ip_str
,
12133 afi_t afi
, safi_t safi
,
12134 enum rpki_states rpki_target_state
,
12135 struct prefix_rd
*prd
, int prefix_check
,
12136 enum bgp_path_type pathtype
, bool use_json
)
12140 struct prefix match
;
12141 struct bgp_dest
*dest
;
12142 struct bgp_dest
*rm
;
12143 struct bgp_table
*table
;
12144 json_object
*json
= NULL
;
12145 json_object
*json_paths
= NULL
;
12147 /* Check IP address argument. */
12148 ret
= str2prefix(ip_str
, &match
);
12150 vty_out(vty
, "address is malformed\n");
12151 return CMD_WARNING
;
12154 match
.family
= afi2family(afi
);
12157 json
= json_object_new_object();
12159 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
12160 for (dest
= bgp_table_top(rib
); dest
;
12161 dest
= bgp_route_next(dest
)) {
12162 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12164 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
12166 table
= bgp_dest_get_bgp_table_info(dest
);
12170 rm
= bgp_node_match(table
, &match
);
12174 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
12176 && rm_p
->prefixlen
!= match
.prefixlen
) {
12177 bgp_dest_unlock_node(rm
);
12181 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12182 bgp
, afi
, safi
, json
, pathtype
,
12183 &display
, rpki_target_state
);
12185 bgp_dest_unlock_node(rm
);
12187 } else if (safi
== SAFI_EVPN
) {
12188 struct bgp_dest
*longest_pfx
;
12189 bool is_exact_pfxlen_match
= false;
12191 for (dest
= bgp_table_top(rib
); dest
;
12192 dest
= bgp_route_next(dest
)) {
12193 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12195 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
12197 table
= bgp_dest_get_bgp_table_info(dest
);
12201 longest_pfx
= NULL
;
12202 is_exact_pfxlen_match
= false;
12204 * Search through all the prefixes for a match. The
12205 * pfx's are enumerated in ascending order of pfxlens.
12206 * So, the last pfx match is the longest match. Set
12207 * is_exact_pfxlen_match when we get exact pfxlen match
12209 for (rm
= bgp_table_top(table
); rm
;
12210 rm
= bgp_route_next(rm
)) {
12211 const struct prefix
*rm_p
=
12212 bgp_dest_get_prefix(rm
);
12214 * Get prefixlen of the ip-prefix within type5
12217 if (evpn_type5_prefix_match(rm_p
, &match
)
12221 bgp_evpn_get_type5_prefixlen(
12223 if (type5_pfxlen
== match
.prefixlen
) {
12224 is_exact_pfxlen_match
= true;
12225 bgp_dest_unlock_node(rm
);
12234 if (prefix_check
&& !is_exact_pfxlen_match
)
12238 bgp_dest_lock_node(rm
);
12240 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12241 bgp
, afi
, safi
, json
, pathtype
,
12242 &display
, rpki_target_state
);
12244 bgp_dest_unlock_node(rm
);
12246 } else if (safi
== SAFI_FLOWSPEC
) {
12248 json_paths
= json_object_new_array();
12250 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
12251 &match
, prefix_check
,
12257 json_object_object_add(json
, "paths",
12260 json_object_free(json_paths
);
12263 dest
= bgp_node_match(rib
, &match
);
12264 if (dest
!= NULL
) {
12265 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12267 || dest_p
->prefixlen
== match
.prefixlen
) {
12268 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
12269 safi
, json
, pathtype
,
12270 &display
, rpki_target_state
);
12273 bgp_dest_unlock_node(dest
);
12278 vty_json(vty
, json
);
12281 vty_out(vty
, "%% Network not in table\n");
12282 return CMD_WARNING
;
12286 return CMD_SUCCESS
;
12289 /* Display specified route of Main RIB */
12290 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
12291 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
12292 int prefix_check
, enum bgp_path_type pathtype
,
12293 enum rpki_states rpki_target_state
, bool use_json
)
12296 bgp
= bgp_get_default();
12299 vty_out(vty
, "No BGP process is configured\n");
12301 vty_out(vty
, "{}\n");
12302 return CMD_WARNING
;
12306 /* labeled-unicast routes live in the unicast table */
12307 if (safi
== SAFI_LABELED_UNICAST
)
12308 safi
= SAFI_UNICAST
;
12310 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
12311 afi
, safi
, rpki_target_state
, prd
,
12312 prefix_check
, pathtype
, use_json
);
12315 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
12316 struct cmd_token
**argv
, bool exact
, afi_t afi
,
12317 safi_t safi
, bool uj
)
12319 struct lcommunity
*lcom
;
12324 uint16_t show_flags
= 0;
12328 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12330 b
= buffer_new(1024);
12331 for (i
= 0; i
< argc
; i
++) {
12333 buffer_putc(b
, ' ');
12335 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
12337 buffer_putstr(b
, argv
[i
]->arg
);
12341 buffer_putc(b
, '\0');
12343 str
= buffer_getstr(b
);
12346 lcom
= lcommunity_str2com(str
);
12347 XFREE(MTYPE_TMP
, str
);
12349 vty_out(vty
, "%% Large-community malformed\n");
12350 return CMD_WARNING
;
12353 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12354 (exact
? bgp_show_type_lcommunity_exact
12355 : bgp_show_type_lcommunity
),
12356 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
12358 lcommunity_free(&lcom
);
12362 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
12363 const char *lcom
, bool exact
, afi_t afi
,
12364 safi_t safi
, bool uj
)
12366 struct community_list
*list
;
12367 uint16_t show_flags
= 0;
12370 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12373 list
= community_list_lookup(bgp_clist
, lcom
, 0,
12374 LARGE_COMMUNITY_LIST_MASTER
);
12375 if (list
== NULL
) {
12376 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
12378 return CMD_WARNING
;
12381 return bgp_show(vty
, bgp
, afi
, safi
,
12382 (exact
? bgp_show_type_lcommunity_list_exact
12383 : bgp_show_type_lcommunity_list
),
12384 list
, show_flags
, RPKI_NOT_BEING_USED
);
12387 DEFUN (show_ip_bgp_large_community_list
,
12388 show_ip_bgp_large_community_list_cmd
,
12389 "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]",
12393 BGP_INSTANCE_HELP_STR
12395 BGP_SAFI_WITH_LABEL_HELP_STR
12396 "Display routes matching the large-community-list\n"
12397 "large-community-list number\n"
12398 "large-community-list name\n"
12399 "Exact match of the large-communities\n"
12402 afi_t afi
= AFI_IP6
;
12403 safi_t safi
= SAFI_UNICAST
;
12405 bool exact_match
= 0;
12406 struct bgp
*bgp
= NULL
;
12407 bool uj
= use_json(argc
, argv
);
12412 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12415 return CMD_WARNING
;
12417 argv_find(argv
, argc
, "large-community-list", &idx
);
12419 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12421 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
12424 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
12425 exact_match
, afi
, safi
, uj
);
12427 DEFUN (show_ip_bgp_large_community
,
12428 show_ip_bgp_large_community_cmd
,
12429 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
12433 BGP_INSTANCE_HELP_STR
12435 BGP_SAFI_WITH_LABEL_HELP_STR
12436 "Display routes matching the large-communities\n"
12437 "List of large-community numbers\n"
12438 "Exact match of the large-communities\n"
12441 afi_t afi
= AFI_IP6
;
12442 safi_t safi
= SAFI_UNICAST
;
12444 bool exact_match
= 0;
12445 struct bgp
*bgp
= NULL
;
12446 bool uj
= use_json(argc
, argv
);
12447 uint16_t show_flags
= 0;
12451 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12454 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12457 return CMD_WARNING
;
12459 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12460 if (argv_find(argv
, argc
, "exact-match", &idx
)) {
12464 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12465 exact_match
, afi
, safi
, uj
);
12467 return bgp_show(vty
, bgp
, afi
, safi
,
12468 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12469 RPKI_NOT_BEING_USED
);
12472 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12473 safi_t safi
, struct json_object
*json_array
);
12474 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12475 safi_t safi
, struct json_object
*json
);
12478 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12479 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12480 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12481 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12483 bool uj
= use_json(argc
, argv
);
12484 struct bgp
*bgp
= NULL
;
12485 safi_t safi
= SAFI_UNICAST
;
12486 afi_t afi
= AFI_IP6
;
12488 struct json_object
*json_all
= NULL
;
12489 struct json_object
*json_afi_safi
= NULL
;
12491 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12494 return CMD_WARNING
;
12497 json_all
= json_object_new_object();
12499 FOREACH_AFI_SAFI (afi
, safi
) {
12501 * So limit output to those afi/safi pairs that
12502 * actually have something interesting in them
12504 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12509 json_afi_safi
= json_object_new_array();
12510 json_object_object_add(
12512 get_afi_safi_str(afi
, safi
, true),
12515 json_afi_safi
= NULL
;
12518 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12522 vty_json(vty
, json_all
);
12524 return CMD_SUCCESS
;
12527 /* BGP route print out function without JSON */
12528 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12529 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12530 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12534 BGP_INSTANCE_HELP_STR
12537 "BGP RIB advertisement statistics\n"
12540 afi_t afi
= AFI_IP6
;
12541 safi_t safi
= SAFI_UNICAST
;
12542 struct bgp
*bgp
= NULL
;
12544 bool uj
= use_json(argc
, argv
);
12545 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12547 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12550 return CMD_WARNING
;
12553 json_afi_safi
= json_object_new_array();
12555 json_afi_safi
= NULL
;
12557 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12560 json
= json_object_new_object();
12561 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12563 vty_json(vty
, json
);
12568 /* BGP route print out function without JSON */
12569 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12570 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12571 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12573 statistics [json]",
12574 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12575 BGP_SAFI_WITH_LABEL_HELP_STR
12576 "BGP RIB advertisement statistics\n" JSON_STR
)
12578 afi_t afi
= AFI_IP6
;
12579 safi_t safi
= SAFI_UNICAST
;
12580 struct bgp
*bgp
= NULL
;
12582 bool uj
= use_json(argc
, argv
);
12583 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12585 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12588 return CMD_WARNING
;
12591 json_afi_safi
= json_object_new_array();
12593 json_afi_safi
= NULL
;
12595 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12598 json
= json_object_new_object();
12599 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12601 vty_json(vty
, json
);
12606 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12607 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12608 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12609 "]] [all$all] dampening parameters [json]",
12610 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12611 BGP_SAFI_WITH_LABEL_HELP_STR
12612 "Display the entries for all address families\n"
12613 "Display detailed information about dampening\n"
12614 "Display detail of configured dampening parameters\n"
12617 afi_t afi
= AFI_IP6
;
12618 safi_t safi
= SAFI_UNICAST
;
12619 struct bgp
*bgp
= NULL
;
12621 uint16_t show_flags
= 0;
12622 bool uj
= use_json(argc
, argv
);
12626 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12629 /* [<ipv4|ipv6> [all]] */
12631 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12632 if (argv_find(argv
, argc
, "ipv4", &idx
))
12633 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12635 if (argv_find(argv
, argc
, "ipv6", &idx
))
12636 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12639 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12642 return CMD_WARNING
;
12644 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12647 /* BGP route print out function */
12648 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12649 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12650 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12654 |dampening <flap-statistics|dampened-paths>\
12655 |community [AA:NN|local-AS|no-advertise|no-export\
12656 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12657 |accept-own|accept-own-nexthop|route-filter-v6\
12658 |route-filter-v4|route-filter-translated-v6\
12659 |route-filter-translated-v4] [exact-match]\
12660 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12661 |filter-list AS_PATH_FILTER_NAME\
12663 |access-list ACCESSLIST_NAME\
12664 |route-map RMAP_NAME\
12665 |rpki <invalid|valid|notfound>\
12666 |version (1-4294967295)\
12668 |A.B.C.D/M longer-prefixes\
12669 |X:X::X:X/M longer-prefixes\
12670 |"BGP_SELF_ORIG_CMD_STR
"\
12671 |detail-routes$detail_routes\
12672 ] [json$uj [detail$detail_json] | wide$wide]",
12673 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12674 BGP_SAFI_WITH_LABEL_HELP_STR
12675 "Display the entries for all address families\n"
12676 "Display only routes with non-natural netmasks\n"
12677 "Display detailed information about dampening\n"
12678 "Display flap statistics of routes\n"
12679 "Display paths suppressed due to dampening\n"
12680 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12681 "Do not send outside local AS (well-known community)\n"
12682 "Do not advertise to any peer (well-known community)\n"
12683 "Do not export to next AS (well-known community)\n"
12684 "Graceful shutdown (well-known community)\n"
12685 "Do not export to any peer (well-known community)\n"
12686 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12687 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12688 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12689 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12690 "Should accept VPN route with local nexthop (well-known community)\n"
12691 "RT VPNv6 route filtering (well-known community)\n"
12692 "RT VPNv4 route filtering (well-known community)\n"
12693 "RT translated VPNv6 route filtering (well-known community)\n"
12694 "RT translated VPNv4 route filtering (well-known community)\n"
12695 "Exact match of the communities\n"
12696 "Community-list number\n"
12697 "Community-list name\n"
12698 "Display routes matching the community-list\n"
12699 "Exact match of the communities\n"
12700 "Display routes conforming to the filter-list\n"
12701 "Regular expression access list name\n"
12702 "Display routes conforming to the prefix-list\n"
12703 "Prefix-list name\n"
12704 "Display routes conforming to the access-list\n"
12705 "Access-list name\n"
12706 "Display routes matching the route-map\n"
12707 "A route-map to match on\n"
12708 "RPKI route types\n"
12709 "A valid path as determined by rpki\n"
12710 "A invalid path as determined by rpki\n"
12711 "A path that has no rpki data\n"
12712 "Display prefixes with matching version numbers\n"
12713 "Version number and above\n"
12714 "Display prefixes with matching BGP community alias\n"
12715 "BGP community alias\n"
12717 "Display route and more specific routes\n"
12719 "Display route and more specific routes\n"
12720 BGP_SELF_ORIG_HELP_STR
12721 "Display detailed version of all routes\n"
12723 "Display detailed version of JSON output\n"
12724 "Increase table width for longer prefixes\n")
12726 afi_t afi
= AFI_IP6
;
12727 safi_t safi
= SAFI_UNICAST
;
12728 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12729 void *output_arg
= NULL
;
12730 struct bgp
*bgp
= NULL
;
12732 int exact_match
= 0;
12733 char *community
= NULL
;
12735 uint16_t show_flags
= 0;
12736 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12741 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12745 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
12748 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
12750 /* [<ipv4|ipv6> [all]] */
12752 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12754 if (argv_find(argv
, argc
, "ipv4", &idx
))
12755 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12757 if (argv_find(argv
, argc
, "ipv6", &idx
))
12758 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12762 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12764 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12767 return CMD_WARNING
;
12769 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12770 sh_type
= bgp_show_type_cidr_only
;
12772 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12773 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12774 sh_type
= bgp_show_type_dampend_paths
;
12775 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12776 sh_type
= bgp_show_type_flap_statistics
;
12779 if (argv_find(argv
, argc
, "community", &idx
)) {
12780 char *maybecomm
= NULL
;
12782 if (idx
+ 1 < argc
) {
12783 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12784 maybecomm
= argv
[idx
+ 1]->arg
;
12786 maybecomm
= argv
[idx
+ 1]->text
;
12789 if (maybecomm
&& !strmatch(maybecomm
, "json")
12790 && !strmatch(maybecomm
, "exact-match"))
12791 community
= maybecomm
;
12793 if (argv_find(argv
, argc
, "exact-match", &idx
))
12797 sh_type
= bgp_show_type_community_all
;
12800 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12801 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12802 struct community_list
*list
;
12804 if (argv_find(argv
, argc
, "exact-match", &idx
))
12807 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12808 COMMUNITY_LIST_MASTER
);
12809 if (list
== NULL
) {
12810 vty_out(vty
, "%% %s community-list not found\n",
12811 clist_number_or_name
);
12812 return CMD_WARNING
;
12816 sh_type
= bgp_show_type_community_list_exact
;
12818 sh_type
= bgp_show_type_community_list
;
12822 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12823 const char *filter
= argv
[++idx
]->arg
;
12824 struct as_list
*as_list
;
12826 as_list
= as_list_lookup(filter
);
12827 if (as_list
== NULL
) {
12828 vty_out(vty
, "%% %s AS-path access-list not found\n",
12830 return CMD_WARNING
;
12833 sh_type
= bgp_show_type_filter_list
;
12834 output_arg
= as_list
;
12837 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12838 const char *prefix_list_str
= argv
[++idx
]->arg
;
12839 struct prefix_list
*plist
;
12841 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12842 if (plist
== NULL
) {
12843 vty_out(vty
, "%% %s prefix-list not found\n",
12845 return CMD_WARNING
;
12848 sh_type
= bgp_show_type_prefix_list
;
12849 output_arg
= plist
;
12852 if (argv_find(argv
, argc
, "access-list", &idx
)) {
12853 const char *access_list_str
= argv
[++idx
]->arg
;
12854 struct access_list
*alist
;
12856 alist
= access_list_lookup(afi
, access_list_str
);
12858 vty_out(vty
, "%% %s access-list not found\n",
12860 return CMD_WARNING
;
12863 sh_type
= bgp_show_type_access_list
;
12864 output_arg
= alist
;
12867 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12868 const char *rmap_str
= argv
[++idx
]->arg
;
12869 struct route_map
*rmap
;
12871 rmap
= route_map_lookup_by_name(rmap_str
);
12873 vty_out(vty
, "%% %s route-map not found\n", rmap_str
);
12874 return CMD_WARNING
;
12877 sh_type
= bgp_show_type_route_map
;
12881 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12882 sh_type
= bgp_show_type_rpki
;
12883 if (argv_find(argv
, argc
, "valid", &idx
))
12884 rpki_target_state
= RPKI_VALID
;
12885 else if (argv_find(argv
, argc
, "invalid", &idx
))
12886 rpki_target_state
= RPKI_INVALID
;
12889 /* Display prefixes with matching version numbers */
12890 if (argv_find(argv
, argc
, "version", &idx
)) {
12891 sh_type
= bgp_show_type_prefix_version
;
12892 output_arg
= argv
[idx
+ 1]->arg
;
12895 /* Display prefixes with matching BGP community alias */
12896 if (argv_find(argv
, argc
, "alias", &idx
)) {
12897 sh_type
= bgp_show_type_community_alias
;
12898 output_arg
= argv
[idx
+ 1]->arg
;
12901 /* prefix-longer */
12902 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12903 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12904 const char *prefix_str
= argv
[idx
]->arg
;
12906 if (!str2prefix(prefix_str
, &p
)) {
12907 vty_out(vty
, "%% Malformed Prefix\n");
12908 return CMD_WARNING
;
12911 sh_type
= bgp_show_type_prefix_longer
;
12915 /* self originated only */
12916 if (argv_find(argv
, argc
, BGP_SELF_ORIG_CMD_STR
, &idx
))
12917 sh_type
= bgp_show_type_self_originated
;
12920 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12922 return bgp_show_community(vty
, bgp
, community
,
12923 exact_match
, afi
, safi
,
12926 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12927 output_arg
, show_flags
,
12928 rpki_target_state
);
12930 struct listnode
*node
;
12932 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12936 vty_out(vty
, "{\n");
12938 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12939 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12940 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12943 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12944 FOREACH_SAFI (safi
) {
12945 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12953 vty_out(vty
, ",\n");
12954 vty_out(vty
, "\"%s\":{\n",
12955 get_afi_safi_str(afi
,
12960 "\nFor address family: %s\n",
12966 bgp_show_community(
12967 vty
, abgp
, community
,
12968 exact_match
, afi
, safi
,
12971 bgp_show(vty
, abgp
, afi
, safi
,
12972 sh_type
, output_arg
,
12974 rpki_target_state
);
12976 vty_out(vty
, "}\n");
12980 /* show <ip> bgp all: for each AFI and SAFI*/
12981 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12982 FOREACH_AFI_SAFI (afi
, safi
) {
12983 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12991 vty_out(vty
, ",\n");
12993 vty_out(vty
, "\"%s\":{\n",
12994 get_afi_safi_str(afi
,
12999 "\nFor address family: %s\n",
13005 bgp_show_community(
13006 vty
, abgp
, community
,
13007 exact_match
, afi
, safi
,
13010 bgp_show(vty
, abgp
, afi
, safi
,
13011 sh_type
, output_arg
,
13013 rpki_target_state
);
13015 vty_out(vty
, "}\n");
13020 vty_out(vty
, "}\n");
13022 return CMD_SUCCESS
;
13025 DEFUN (show_ip_bgp_route
,
13026 show_ip_bgp_route_cmd
,
13027 "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]",
13031 BGP_INSTANCE_HELP_STR
13033 BGP_SAFI_WITH_LABEL_HELP_STR
13034 "Network in the BGP routing table to display\n"
13036 "Network in the BGP routing table to display\n"
13038 "Display only the bestpath\n"
13039 "Display only multipaths\n"
13040 "Display only paths that match the specified rpki state\n"
13041 "A valid path as determined by rpki\n"
13042 "A invalid path as determined by rpki\n"
13043 "A path that has no rpki data\n"
13046 int prefix_check
= 0;
13048 afi_t afi
= AFI_IP6
;
13049 safi_t safi
= SAFI_UNICAST
;
13050 char *prefix
= NULL
;
13051 struct bgp
*bgp
= NULL
;
13052 enum bgp_path_type path_type
;
13053 bool uj
= use_json(argc
, argv
);
13057 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13060 return CMD_WARNING
;
13064 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13065 return CMD_WARNING
;
13068 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13069 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
13070 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
13072 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
13073 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
13076 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
13077 && afi
!= AFI_IP6
) {
13079 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13080 return CMD_WARNING
;
13082 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
13083 && afi
!= AFI_IP
) {
13085 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13086 return CMD_WARNING
;
13089 prefix
= argv
[idx
]->arg
;
13091 /* [<bestpath|multipath>] */
13092 if (argv_find(argv
, argc
, "bestpath", &idx
))
13093 path_type
= BGP_PATH_SHOW_BESTPATH
;
13094 else if (argv_find(argv
, argc
, "multipath", &idx
))
13095 path_type
= BGP_PATH_SHOW_MULTIPATH
;
13097 path_type
= BGP_PATH_SHOW_ALL
;
13099 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
13100 path_type
, RPKI_NOT_BEING_USED
, uj
);
13103 DEFUN (show_ip_bgp_regexp
,
13104 show_ip_bgp_regexp_cmd
,
13105 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
13109 BGP_INSTANCE_HELP_STR
13111 BGP_SAFI_WITH_LABEL_HELP_STR
13112 "Display routes matching the AS path regular expression\n"
13113 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13116 afi_t afi
= AFI_IP6
;
13117 safi_t safi
= SAFI_UNICAST
;
13118 struct bgp
*bgp
= NULL
;
13119 bool uj
= use_json(argc
, argv
);
13120 char *regstr
= NULL
;
13123 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13126 return CMD_WARNING
;
13128 // get index of regex
13129 if (argv_find(argv
, argc
, "REGEX", &idx
))
13130 regstr
= argv
[idx
]->arg
;
13133 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
13134 bgp_show_type_regexp
, uj
);
13137 DEFPY (show_ip_bgp_instance_all
,
13138 show_ip_bgp_instance_all_cmd
,
13139 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
13143 BGP_INSTANCE_ALL_HELP_STR
13145 BGP_SAFI_WITH_LABEL_HELP_STR
13147 "Increase table width for longer prefixes\n")
13149 afi_t afi
= AFI_IP6
;
13150 safi_t safi
= SAFI_UNICAST
;
13151 struct bgp
*bgp
= NULL
;
13153 uint16_t show_flags
= 0;
13157 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13161 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13163 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13166 return CMD_WARNING
;
13168 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
13169 return CMD_SUCCESS
;
13172 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
13173 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
13178 uint16_t show_flags
= 0;
13181 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13183 if (!config_bgp_aspath_validate(regstr
)) {
13184 vty_out(vty
, "Invalid character in REGEX %s\n",
13186 return CMD_WARNING_CONFIG_FAILED
;
13189 regex
= bgp_regcomp(regstr
);
13191 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
13192 return CMD_WARNING
;
13195 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
13196 RPKI_NOT_BEING_USED
);
13197 bgp_regex_free(regex
);
13201 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
13202 const char *comstr
, int exact
, afi_t afi
,
13203 safi_t safi
, uint16_t show_flags
)
13205 struct community
*com
;
13208 com
= community_str2com(comstr
);
13210 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
13211 return CMD_WARNING
;
13214 ret
= bgp_show(vty
, bgp
, afi
, safi
,
13215 (exact
? bgp_show_type_community_exact
13216 : bgp_show_type_community
),
13217 com
, show_flags
, RPKI_NOT_BEING_USED
);
13218 community_free(&com
);
13224 BGP_STATS_MAXBITLEN
= 0,
13226 BGP_STATS_PREFIXES
,
13228 BGP_STATS_UNAGGREGATEABLE
,
13229 BGP_STATS_MAX_AGGREGATEABLE
,
13230 BGP_STATS_AGGREGATES
,
13232 BGP_STATS_ASPATH_COUNT
,
13233 BGP_STATS_ASPATH_MAXHOPS
,
13234 BGP_STATS_ASPATH_TOTHOPS
,
13235 BGP_STATS_ASPATH_MAXSIZE
,
13236 BGP_STATS_ASPATH_TOTSIZE
,
13237 BGP_STATS_ASN_HIGHEST
,
13241 #define TABLE_STATS_IDX_VTY 0
13242 #define TABLE_STATS_IDX_JSON 1
13244 static const char *table_stats_strs
[][2] = {
13245 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
13246 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
13247 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
13248 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
13249 "unaggregateablePrefixes"},
13250 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
13251 "maximumAggregateablePrefixes"},
13252 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
13253 "bgpAggregateAdvertisements"},
13254 [BGP_STATS_SPACE
] = {"Address space advertised",
13255 "addressSpaceAdvertised"},
13256 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
13257 "advertisementsWithPaths"},
13258 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
13260 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
13262 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
13263 "averageAsPathLengthHops"},
13264 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
13265 "averageAsPathSizeBytes"},
13266 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
13267 [BGP_STATS_MAX
] = {NULL
, NULL
}
13270 struct bgp_table_stats
{
13271 struct bgp_table
*table
;
13272 unsigned long long counts
[BGP_STATS_MAX
];
13275 prefix_len_count
[MAX(EVPN_ROUTE_PREFIXLEN
, IPV6_MAX_BITLEN
) +
13278 double total_space
;
13281 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
13282 struct bgp_table_stats
*ts
, unsigned int space
)
13284 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
13285 struct bgp_path_info
*pi
;
13286 const struct prefix
*rn_p
;
13288 if (!bgp_dest_has_bgp_path_info_data(dest
))
13291 rn_p
= bgp_dest_get_prefix(dest
);
13292 ts
->counts
[BGP_STATS_PREFIXES
]++;
13293 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
13295 ts
->prefix_len_count
[rn_p
->prefixlen
]++;
13296 /* check if the prefix is included by any other announcements */
13297 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
13298 pdest
= bgp_dest_parent_nolock(pdest
);
13300 if (pdest
== NULL
|| pdest
== top
) {
13301 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
13302 /* announced address space */
13304 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
13305 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
13306 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
13309 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
13310 ts
->counts
[BGP_STATS_RIB
]++;
13312 if (CHECK_FLAG(pi
->attr
->flag
,
13313 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
13314 ts
->counts
[BGP_STATS_AGGREGATES
]++;
13316 /* as-path stats */
13317 if (pi
->attr
->aspath
) {
13318 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
13319 unsigned int size
= aspath_size(pi
->attr
->aspath
);
13320 as_t highest
= aspath_highest(pi
->attr
->aspath
);
13322 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
13324 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
13325 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
13327 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
13328 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
13330 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
13331 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
13332 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
13333 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
13338 static void bgp_table_stats_walker(struct event
*t
)
13340 struct bgp_dest
*dest
, *ndest
;
13341 struct bgp_dest
*top
;
13342 struct bgp_table_stats
*ts
= EVENT_ARG(t
);
13343 unsigned int space
= 0;
13345 if (!(top
= bgp_table_top(ts
->table
)))
13348 switch (ts
->table
->afi
) {
13350 space
= IPV4_MAX_BITLEN
;
13353 space
= IPV6_MAX_BITLEN
;
13356 space
= EVPN_ROUTE_PREFIXLEN
;
13363 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
13365 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
13366 if (ts
->table
->safi
== SAFI_MPLS_VPN
13367 || ts
->table
->safi
== SAFI_ENCAP
13368 || ts
->table
->safi
== SAFI_EVPN
) {
13369 struct bgp_table
*table
;
13371 table
= bgp_dest_get_bgp_table_info(dest
);
13375 top
= bgp_table_top(table
);
13376 for (ndest
= bgp_table_top(table
); ndest
;
13377 ndest
= bgp_route_next(ndest
))
13378 bgp_table_stats_rn(ndest
, top
, ts
, space
);
13380 bgp_table_stats_rn(dest
, top
, ts
, space
);
13385 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
13386 struct json_object
*json_array
)
13388 struct listnode
*node
, *nnode
;
13391 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
13392 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13395 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13396 safi_t safi
, struct json_object
*json_array
)
13398 struct bgp_table_stats ts
;
13400 int ret
= CMD_SUCCESS
;
13402 struct json_object
*json
= NULL
;
13403 uint32_t bitlen
= 0;
13404 struct json_object
*json_bitlen
;
13407 json
= json_object_new_object();
13409 if (!bgp
->rib
[afi
][safi
]) {
13410 char warning_msg
[50];
13412 snprintf(warning_msg
, sizeof(warning_msg
),
13413 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
13417 vty_out(vty
, "%s\n", warning_msg
);
13419 json_object_string_add(json
, "warning", warning_msg
);
13422 goto end_table_stats
;
13426 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
13427 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
13429 json_object_string_add(json
, "instance", bgp
->name_pretty
);
13431 /* labeled-unicast routes live in the unicast table */
13432 if (safi
== SAFI_LABELED_UNICAST
)
13433 safi
= SAFI_UNICAST
;
13435 memset(&ts
, 0, sizeof(ts
));
13436 ts
.table
= bgp
->rib
[afi
][safi
];
13437 event_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
13439 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
13440 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
13441 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
13445 case BGP_STATS_ASPATH_TOTHOPS
:
13446 case BGP_STATS_ASPATH_TOTSIZE
:
13449 temp_buf
, sizeof(temp_buf
), "%12.2f",
13451 ? (float)ts
.counts
[i
]
13453 [BGP_STATS_ASPATH_COUNT
]
13455 vty_out(vty
, "%-30s: %s",
13456 table_stats_strs
[i
]
13457 [TABLE_STATS_IDX_VTY
],
13460 json_object_double_add(
13462 table_stats_strs
[i
]
13463 [TABLE_STATS_IDX_JSON
],
13465 ? (double)ts
.counts
[i
]
13466 / (double)ts
.counts
13467 [BGP_STATS_ASPATH_COUNT
]
13471 case BGP_STATS_TOTPLEN
:
13474 temp_buf
, sizeof(temp_buf
), "%12.2f",
13476 ? (float)ts
.counts
[i
]
13478 [BGP_STATS_PREFIXES
]
13480 vty_out(vty
, "%-30s: %s",
13481 table_stats_strs
[i
]
13482 [TABLE_STATS_IDX_VTY
],
13485 json_object_double_add(
13487 table_stats_strs
[i
]
13488 [TABLE_STATS_IDX_JSON
],
13490 ? (double)ts
.counts
[i
]
13491 / (double)ts
.counts
13492 [BGP_STATS_PREFIXES
]
13496 case BGP_STATS_SPACE
:
13498 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13500 vty_out(vty
, "%-30s: %s\n",
13501 table_stats_strs
[i
]
13502 [TABLE_STATS_IDX_VTY
],
13505 json_object_double_add(
13507 table_stats_strs
[i
]
13508 [TABLE_STATS_IDX_JSON
],
13509 (double)ts
.total_space
);
13511 if (afi
== AFI_IP6
) {
13513 snprintf(temp_buf
, sizeof(temp_buf
),
13516 * pow(2.0, -128 + 32));
13517 vty_out(vty
, "%30s: %s\n",
13518 "/32 equivalent %s\n",
13521 json_object_double_add(
13522 json
, "/32equivalent",
13523 (double)(ts
.total_space
13528 snprintf(temp_buf
, sizeof(temp_buf
),
13531 * pow(2.0, -128 + 48));
13532 vty_out(vty
, "%30s: %s\n",
13533 "/48 equivalent %s\n",
13536 json_object_double_add(
13537 json
, "/48equivalent",
13538 (double)(ts
.total_space
13544 snprintf(temp_buf
, sizeof(temp_buf
),
13546 ts
.total_space
* 100.
13548 vty_out(vty
, "%30s: %s\n",
13549 "% announced ", temp_buf
);
13551 json_object_double_add(
13552 json
, "%announced",
13553 (double)(ts
.total_space
* 100.
13557 snprintf(temp_buf
, sizeof(temp_buf
),
13560 * pow(2.0, -32 + 8));
13561 vty_out(vty
, "%30s: %s\n",
13562 "/8 equivalent ", temp_buf
);
13564 json_object_double_add(
13565 json
, "/8equivalent",
13566 (double)(ts
.total_space
13567 * pow(2.0, -32 + 8)));
13570 snprintf(temp_buf
, sizeof(temp_buf
),
13573 * pow(2.0, -32 + 24));
13574 vty_out(vty
, "%30s: %s\n",
13575 "/24 equivalent ", temp_buf
);
13577 json_object_double_add(
13578 json
, "/24equivalent",
13579 (double)(ts
.total_space
13580 * pow(2.0, -32 + 24)));
13586 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13588 vty_out(vty
, "%-30s: %s",
13589 table_stats_strs
[i
]
13590 [TABLE_STATS_IDX_VTY
],
13593 json_object_int_add(
13595 table_stats_strs
[i
]
13596 [TABLE_STATS_IDX_JSON
],
13601 vty_out(vty
, "\n");
13606 bitlen
= IPV4_MAX_BITLEN
;
13609 bitlen
= IPV6_MAX_BITLEN
;
13612 bitlen
= EVPN_ROUTE_PREFIXLEN
;
13620 json_bitlen
= json_object_new_array();
13622 for (i
= 0; i
<= bitlen
; i
++) {
13623 struct json_object
*ind_bit
= json_object_new_object();
13625 if (!ts
.prefix_len_count
[i
])
13628 snprintf(temp_buf
, sizeof(temp_buf
), "%u", i
);
13629 json_object_int_add(ind_bit
, temp_buf
,
13630 ts
.prefix_len_count
[i
]);
13631 json_object_array_add(json_bitlen
, ind_bit
);
13633 json_object_object_add(json
, "prefixLength", json_bitlen
);
13638 json_object_array_add(json_array
, json
);
13642 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13643 safi_t safi
, struct json_object
*json_array
)
13646 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13647 return CMD_SUCCESS
;
13650 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13662 PCOUNT_BPATH_SELECTED
,
13663 PCOUNT_PFCNT
, /* the figure we display to users */
13667 static const char *const pcount_strs
[] = {
13668 [PCOUNT_ADJ_IN
] = "Adj-in",
13669 [PCOUNT_DAMPED
] = "Damped",
13670 [PCOUNT_REMOVED
] = "Removed",
13671 [PCOUNT_HISTORY
] = "History",
13672 [PCOUNT_STALE
] = "Stale",
13673 [PCOUNT_VALID
] = "Valid",
13674 [PCOUNT_ALL
] = "All RIB",
13675 [PCOUNT_COUNTED
] = "PfxCt counted",
13676 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13677 [PCOUNT_PFCNT
] = "Useable",
13678 [PCOUNT_MAX
] = NULL
,
13681 struct peer_pcounts
{
13682 unsigned int count
[PCOUNT_MAX
];
13683 const struct peer
*peer
;
13684 const struct bgp_table
*table
;
13688 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13690 const struct bgp_adj_in
*ain
;
13691 const struct bgp_path_info
*pi
;
13692 const struct peer
*peer
= pc
->peer
;
13694 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13695 if (ain
->peer
== peer
)
13696 pc
->count
[PCOUNT_ADJ_IN
]++;
13698 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13700 if (pi
->peer
!= peer
)
13703 pc
->count
[PCOUNT_ALL
]++;
13705 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13706 pc
->count
[PCOUNT_DAMPED
]++;
13707 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13708 pc
->count
[PCOUNT_HISTORY
]++;
13709 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13710 pc
->count
[PCOUNT_REMOVED
]++;
13711 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13712 pc
->count
[PCOUNT_STALE
]++;
13713 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13714 pc
->count
[PCOUNT_VALID
]++;
13715 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13716 pc
->count
[PCOUNT_PFCNT
]++;
13717 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13718 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13720 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13721 pc
->count
[PCOUNT_COUNTED
]++;
13722 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13724 EC_LIB_DEVELOPMENT
,
13725 "Attempting to count but flags say it is unusable");
13727 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13729 EC_LIB_DEVELOPMENT
,
13730 "Not counted but flags say we should");
13735 static void bgp_peer_count_walker(struct event
*t
)
13737 struct bgp_dest
*rn
, *rm
;
13738 const struct bgp_table
*table
;
13739 struct peer_pcounts
*pc
= EVENT_ARG(t
);
13741 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13742 || pc
->safi
== SAFI_EVPN
) {
13743 /* Special handling for 2-level routing tables. */
13744 for (rn
= bgp_table_top(pc
->table
); rn
;
13745 rn
= bgp_route_next(rn
)) {
13746 table
= bgp_dest_get_bgp_table_info(rn
);
13748 for (rm
= bgp_table_top(table
); rm
;
13749 rm
= bgp_route_next(rm
))
13750 bgp_peer_count_proc(rm
, pc
);
13753 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13754 bgp_peer_count_proc(rn
, pc
);
13757 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13758 safi_t safi
, bool use_json
)
13760 struct peer_pcounts pcounts
= {.peer
= peer
};
13762 json_object
*json
= NULL
;
13763 json_object
*json_loop
= NULL
;
13766 json
= json_object_new_object();
13767 json_loop
= json_object_new_object();
13770 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13771 || !peer
->bgp
->rib
[afi
][safi
]) {
13773 json_object_string_add(
13775 "No such neighbor or address family");
13776 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13777 json_object_free(json
);
13778 json_object_free(json_loop
);
13780 vty_out(vty
, "%% No such neighbor or address family\n");
13782 return CMD_WARNING
;
13785 memset(&pcounts
, 0, sizeof(pcounts
));
13786 pcounts
.peer
= peer
;
13787 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13788 pcounts
.safi
= safi
;
13790 /* in-place call via thread subsystem so as to record execution time
13791 * stats for the thread-walk (i.e. ensure this can't be blamed on
13792 * on just vty_read()).
13794 event_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13797 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13798 json_object_string_add(json
, "multiProtocol",
13799 get_afi_safi_str(afi
, safi
, true));
13800 json_object_int_add(json
, "pfxCounter",
13801 peer
->pcount
[afi
][safi
]);
13803 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13804 json_object_int_add(json_loop
, pcount_strs
[i
],
13807 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13809 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13810 json_object_string_add(json
, "pfxctDriftFor",
13812 json_object_string_add(
13813 json
, "recommended",
13814 "Please report this bug, with the above command output");
13816 vty_json(vty
, json
);
13820 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13821 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13822 peer
->hostname
, peer
->host
,
13823 get_afi_safi_str(afi
, safi
, false));
13825 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13826 get_afi_safi_str(afi
, safi
, false));
13829 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13830 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13832 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13833 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13836 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13837 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13839 "Please report this bug, with the above command output\n");
13843 return CMD_SUCCESS
;
13846 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13847 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13848 "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]",
13852 BGP_INSTANCE_HELP_STR
13855 "Detailed information on TCP and BGP neighbor connections\n"
13856 "Neighbor to display information about\n"
13857 "Neighbor to display information about\n"
13858 "Neighbor on BGP configured interface\n"
13859 "Display detailed prefix count information\n"
13862 afi_t afi
= AFI_IP6
;
13863 safi_t safi
= SAFI_UNICAST
;
13866 struct bgp
*bgp
= NULL
;
13867 bool uj
= use_json(argc
, argv
);
13872 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13875 return CMD_WARNING
;
13877 argv_find(argv
, argc
, "neighbors", &idx
);
13878 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13880 return CMD_WARNING
;
13882 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13885 #ifdef KEEP_OLD_VPN_COMMANDS
13886 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13887 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13888 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13893 "Display information about all VPNv4 NLRIs\n"
13894 "Detailed information on TCP and BGP neighbor connections\n"
13895 "Neighbor to display information about\n"
13896 "Neighbor to display information about\n"
13897 "Neighbor on BGP configured interface\n"
13898 "Display detailed prefix count information\n"
13903 bool uj
= use_json(argc
, argv
);
13905 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13907 return CMD_WARNING
;
13909 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13912 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13913 show_ip_bgp_vpn_all_route_prefix_cmd
,
13914 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13919 "Display information about all VPNv4 NLRIs\n"
13920 "Network in the BGP routing table to display\n"
13921 "Network in the BGP routing table to display\n"
13925 char *network
= NULL
;
13926 struct bgp
*bgp
= bgp_get_default();
13928 vty_out(vty
, "Can't find default instance\n");
13929 return CMD_WARNING
;
13932 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13933 network
= argv
[idx
]->arg
;
13934 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13935 network
= argv
[idx
]->arg
;
13937 vty_out(vty
, "Unable to figure out Network\n");
13938 return CMD_WARNING
;
13941 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13942 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13943 use_json(argc
, argv
));
13945 #endif /* KEEP_OLD_VPN_COMMANDS */
13947 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13948 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13949 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13954 "Network in the BGP routing table to display\n"
13955 "Network in the BGP routing table to display\n"
13956 "Network in the BGP routing table to display\n"
13957 "Network in the BGP routing table to display\n"
13961 char *network
= NULL
;
13962 int prefix_check
= 0;
13964 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13965 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13966 network
= argv
[idx
]->arg
;
13967 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13968 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
13969 network
= argv
[idx
]->arg
;
13972 vty_out(vty
, "Unable to figure out Network\n");
13973 return CMD_WARNING
;
13975 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13976 prefix_check
, BGP_PATH_SHOW_ALL
,
13977 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
13980 static void show_adj_route_header(struct vty
*vty
, struct peer
*peer
,
13981 struct bgp_table
*table
, int *header1
,
13982 int *header2
, json_object
*json
,
13983 json_object
*json_scode
,
13984 json_object
*json_ocode
, bool wide
,
13987 uint64_t version
= table
? table
->version
: 0;
13991 json_object_int_add(json
, "bgpTableVersion", version
);
13992 json_object_string_addf(json
, "bgpLocalRouterId",
13993 "%pI4", &peer
->bgp
->router_id
);
13994 json_object_int_add(json
, "defaultLocPrf",
13995 peer
->bgp
->default_local_pref
);
13996 json_object_int_add(json
, "localAS",
13997 peer
->change_local_as
13998 ? peer
->change_local_as
14000 json_object_object_add(json
, "bgpStatusCodes",
14002 json_object_object_add(json
, "bgpOriginCodes",
14006 "BGP table version is %" PRIu64
14007 ", local router ID is %pI4, vrf id ",
14008 version
, &peer
->bgp
->router_id
);
14009 if (peer
->bgp
->vrf_id
== VRF_UNKNOWN
)
14010 vty_out(vty
, "%s", VRFID_NONE_STR
);
14012 vty_out(vty
, "%u", peer
->bgp
->vrf_id
);
14013 vty_out(vty
, "\n");
14014 vty_out(vty
, "Default local pref %u, ",
14015 peer
->bgp
->default_local_pref
);
14016 vty_out(vty
, "local AS %u\n",
14017 peer
->change_local_as
? peer
->change_local_as
14020 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14021 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14022 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14023 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14029 if (!json
&& !detail
)
14030 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
14031 : BGP_SHOW_HEADER
));
14037 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
14038 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
14039 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
14040 json_object
*json_scode
, json_object
*json_ocode
,
14041 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
14042 const struct prefix
*match
, unsigned long *output_count
,
14043 unsigned long *filtered_count
)
14045 struct bgp_adj_in
*ain
= NULL
;
14046 struct bgp_adj_out
*adj
= NULL
;
14047 struct bgp_dest
*dest
;
14051 struct update_subgroup
*subgrp
;
14052 struct peer_af
*paf
= NULL
;
14053 bool route_filtered
;
14054 bool detail
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14055 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14056 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14057 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14058 || (safi
== SAFI_EVPN
))
14062 json_object
*json_net
= NULL
;
14066 /* If the user supplied a prefix, look for a matching route instead
14067 * of walking the whole table.
14070 dest
= bgp_node_match(table
, match
);
14073 vty_out(vty
, "Network not in table\n");
14077 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
14079 if (rn_p
->prefixlen
!= match
->prefixlen
) {
14081 vty_out(vty
, "Network not in table\n");
14082 bgp_dest_unlock_node(dest
);
14086 if (type
== bgp_show_adj_route_received
||
14087 type
== bgp_show_adj_route_filtered
) {
14088 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14089 if (ain
->peer
== peer
) {
14094 /* bail out if if adj_out is empty, or
14095 * if the prefix isn't in this peer's
14098 if (!ain
|| ain
->peer
!= peer
) {
14100 vty_out(vty
, "Network not in table\n");
14101 bgp_dest_unlock_node(dest
);
14104 } else if (type
== bgp_show_adj_route_advertised
) {
14105 bool peer_found
= false;
14107 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
) {
14108 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14109 if (paf
->peer
== peer
&& adj
->attr
) {
14118 /* bail out if if adj_out is empty, or
14119 * if the prefix isn't in this peer's
14122 if (!paf
|| !peer_found
) {
14124 vty_out(vty
, "Network not in table\n");
14125 bgp_dest_unlock_node(dest
);
14130 ret
= bgp_output_modifier(peer
, rn_p
, &attr
, afi
, safi
,
14133 if (ret
!= RMAP_DENY
) {
14134 show_adj_route_header(vty
, peer
, table
, header1
,
14135 header2
, json
, json_scode
,
14136 json_ocode
, wide
, detail
);
14139 json_net
= json_object_new_object();
14141 bgp_show_path_info(NULL
/* prefix_rd */, dest
, vty
, bgp
,
14142 afi
, safi
, json_net
,
14143 BGP_PATH_SHOW_ALL
, &display
,
14144 RPKI_NOT_BEING_USED
);
14146 json_object_object_addf(json_ar
, json_net
,
14150 (*filtered_count
)++;
14152 bgp_attr_flush(&attr
);
14153 bgp_dest_unlock_node(dest
);
14158 subgrp
= peer_subgroup(peer
, afi
, safi
);
14160 if (type
== bgp_show_adj_route_advertised
&& subgrp
14161 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
14163 json_object_int_add(json
, "bgpTableVersion",
14165 json_object_string_addf(json
, "bgpLocalRouterId",
14166 "%pI4", &bgp
->router_id
);
14167 json_object_int_add(json
, "defaultLocPrf",
14168 bgp
->default_local_pref
);
14169 json_object_int_add(json
, "localAS",
14170 peer
->change_local_as
14171 ? peer
->change_local_as
14173 json_object_object_add(json
, "bgpStatusCodes",
14175 json_object_object_add(json
, "bgpOriginCodes",
14177 json_object_string_add(
14178 json
, "bgpOriginatingDefaultNetwork",
14179 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14182 "BGP table version is %" PRIu64
14183 ", local router ID is %pI4, vrf id ",
14184 table
->version
, &bgp
->router_id
);
14185 if (bgp
->vrf_id
== VRF_UNKNOWN
)
14186 vty_out(vty
, "%s", VRFID_NONE_STR
);
14188 vty_out(vty
, "%u", bgp
->vrf_id
);
14189 vty_out(vty
, "\n");
14190 vty_out(vty
, "Default local pref %u, ",
14191 bgp
->default_local_pref
);
14192 vty_out(vty
, "local AS %u\n",
14193 peer
->change_local_as
? peer
->change_local_as
14196 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14197 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14198 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14199 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14202 vty_out(vty
, "Originating default network %s\n\n",
14203 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14209 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
14210 if (type
== bgp_show_adj_route_received
14211 || type
== bgp_show_adj_route_filtered
) {
14212 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14213 if (ain
->peer
!= peer
)
14216 show_adj_route_header(vty
, peer
, table
, header1
,
14217 header2
, json
, json_scode
,
14218 json_ocode
, wide
, detail
);
14220 if ((safi
== SAFI_MPLS_VPN
)
14221 || (safi
== SAFI_ENCAP
)
14222 || (safi
== SAFI_EVPN
)) {
14224 json_object_string_add(
14225 json_ar
, "rd", rd_str
);
14226 else if (show_rd
&& rd_str
) {
14228 "Route Distinguisher: %s\n",
14235 route_filtered
= false;
14237 /* Filter prefix using distribute list,
14238 * filter list or prefix list
14240 const struct prefix
*rn_p
=
14241 bgp_dest_get_prefix(dest
);
14242 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
14245 route_filtered
= true;
14247 /* Filter prefix using route-map */
14248 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
14249 safi
, rmap_name
, NULL
,
14252 if (type
== bgp_show_adj_route_filtered
&&
14253 !route_filtered
&& ret
!= RMAP_DENY
) {
14254 bgp_attr_flush(&attr
);
14258 if (type
== bgp_show_adj_route_received
14259 && (route_filtered
|| ret
== RMAP_DENY
))
14260 (*filtered_count
)++;
14265 json_object_new_object();
14266 bgp_show_path_info(
14267 NULL
/* prefix_rd */, dest
, vty
,
14268 bgp
, afi
, safi
, json_net
,
14269 BGP_PATH_SHOW_ALL
, &display
,
14270 RPKI_NOT_BEING_USED
);
14272 json_object_object_addf(
14276 route_vty_out_tmp(vty
, dest
, rn_p
,
14277 &attr
, safi
, use_json
,
14279 bgp_attr_flush(&attr
);
14282 } else if (type
== bgp_show_adj_route_advertised
) {
14283 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
14284 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14285 if (paf
->peer
!= peer
|| !adj
->attr
)
14288 show_adj_route_header(
14289 vty
, peer
, table
, header1
,
14290 header2
, json
, json_scode
,
14291 json_ocode
, wide
, detail
);
14293 const struct prefix
*rn_p
=
14294 bgp_dest_get_prefix(dest
);
14297 ret
= bgp_output_modifier(
14298 peer
, rn_p
, &attr
, afi
, safi
,
14301 if (ret
!= RMAP_DENY
) {
14302 if ((safi
== SAFI_MPLS_VPN
)
14303 || (safi
== SAFI_ENCAP
)
14304 || (safi
== SAFI_EVPN
)) {
14306 json_object_string_add(
14313 "Route Distinguisher: %s\n",
14321 json_object_new_object();
14322 bgp_show_path_info(
14331 RPKI_NOT_BEING_USED
);
14333 json_object_object_addf(
14346 (*filtered_count
)++;
14349 bgp_attr_flush(&attr
);
14351 } else if (type
== bgp_show_adj_route_bestpath
) {
14352 struct bgp_path_info
*pi
;
14354 show_adj_route_header(vty
, peer
, table
, header1
,
14355 header2
, json
, json_scode
,
14356 json_ocode
, wide
, detail
);
14358 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
14360 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
14362 if (pi
->peer
!= peer
)
14365 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
14371 json_object_new_object();
14372 bgp_show_path_info(
14373 NULL
/* prefix_rd */, dest
, vty
,
14374 bgp
, afi
, safi
, json_net
,
14375 BGP_PATH_SHOW_BESTPATH
,
14376 &display
, RPKI_NOT_BEING_USED
);
14378 json_object_object_addf(
14383 vty
, dest
, rn_p
, pi
->attr
, safi
,
14384 use_json
, json_ar
, wide
);
14391 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
14392 safi_t safi
, enum bgp_show_adj_route_type type
,
14393 const char *rmap_name
, const struct prefix
*match
,
14394 uint16_t show_flags
)
14397 struct bgp_table
*table
;
14398 json_object
*json
= NULL
;
14399 json_object
*json_scode
= NULL
;
14400 json_object
*json_ocode
= NULL
;
14401 json_object
*json_ar
= NULL
;
14402 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14404 /* Init BGP headers here so they're only displayed once
14405 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14411 * Initialize variables for each RD
14412 * All prefixes under an RD is aggregated within "json_routes"
14414 char rd_str
[BUFSIZ
] = {0};
14415 json_object
*json_routes
= NULL
;
14418 /* For 2-tier tables, prefix counts need to be
14419 * maintained across multiple runs of show_adj_route()
14421 unsigned long output_count_per_rd
;
14422 unsigned long filtered_count_per_rd
;
14423 unsigned long output_count
= 0;
14424 unsigned long filtered_count
= 0;
14427 json
= json_object_new_object();
14428 json_ar
= json_object_new_object();
14429 json_scode
= json_object_new_object();
14430 json_ocode
= json_object_new_object();
14431 #if CONFDATE > 20231208
14432 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14434 json_object_string_add(json_scode
, "suppressed", "s");
14435 json_object_string_add(json_scode
, "damped", "d");
14436 json_object_string_add(json_scode
, "history", "h");
14437 json_object_string_add(json_scode
, "valid", "*");
14438 json_object_string_add(json_scode
, "best", ">");
14439 json_object_string_add(json_scode
, "multipath", "=");
14440 json_object_string_add(json_scode
, "internal", "i");
14441 json_object_string_add(json_scode
, "ribFailure", "r");
14442 json_object_string_add(json_scode
, "stale", "S");
14443 json_object_string_add(json_scode
, "removed", "R");
14445 #if CONFDATE > 20231208
14446 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14448 json_object_string_add(json_ocode
, "igp", "i");
14449 json_object_string_add(json_ocode
, "egp", "e");
14450 json_object_string_add(json_ocode
, "incomplete", "?");
14453 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14455 json_object_string_add(
14457 "No such neighbor or address family");
14458 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14459 json_object_free(json
);
14460 json_object_free(json_ar
);
14461 json_object_free(json_scode
);
14462 json_object_free(json_ocode
);
14464 vty_out(vty
, "%% No such neighbor or address family\n");
14466 return CMD_WARNING
;
14469 if ((type
== bgp_show_adj_route_received
14470 || type
== bgp_show_adj_route_filtered
)
14471 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
14472 PEER_FLAG_SOFT_RECONFIG
)) {
14474 json_object_string_add(
14476 "Inbound soft reconfiguration not enabled");
14477 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14478 json_object_free(json
);
14479 json_object_free(json_ar
);
14480 json_object_free(json_scode
);
14481 json_object_free(json_ocode
);
14484 "%% Inbound soft reconfiguration not enabled\n");
14486 return CMD_WARNING
;
14491 /* labeled-unicast routes live in the unicast table */
14492 if (safi
== SAFI_LABELED_UNICAST
)
14493 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
14495 table
= bgp
->rib
[afi
][safi
];
14497 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14498 || (safi
== SAFI_EVPN
)) {
14500 struct bgp_dest
*dest
;
14502 for (dest
= bgp_table_top(table
); dest
;
14503 dest
= bgp_route_next(dest
)) {
14504 table
= bgp_dest_get_bgp_table_info(dest
);
14508 output_count_per_rd
= 0;
14509 filtered_count_per_rd
= 0;
14512 json_routes
= json_object_new_object();
14514 const struct prefix_rd
*prd
;
14515 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14518 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
),
14522 vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14523 json
, json_routes
, json_scode
, json_ocode
,
14524 show_flags
, &header1
, &header2
, rd_str
, match
,
14525 &output_count_per_rd
, &filtered_count_per_rd
);
14527 /* Don't include an empty RD in the output! */
14528 if (json_routes
&& (output_count_per_rd
> 0))
14529 json_object_object_add(json_ar
, rd_str
,
14532 output_count
+= output_count_per_rd
;
14533 filtered_count
+= filtered_count_per_rd
;
14536 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14537 json
, json_ar
, json_scode
, json_ocode
,
14538 show_flags
, &header1
, &header2
, rd_str
, match
,
14539 &output_count
, &filtered_count
);
14542 if (type
== bgp_show_adj_route_advertised
)
14543 json_object_object_add(json
, "advertisedRoutes",
14546 json_object_object_add(json
, "receivedRoutes", json_ar
);
14547 json_object_int_add(json
, "totalPrefixCounter", output_count
);
14548 json_object_int_add(json
, "filteredPrefixCounter",
14552 * These fields only give up ownership to `json` when `header1`
14553 * is used (set to zero). See code in `show_adj_route` and
14554 * `show_adj_route_header`.
14556 if (header1
== 1) {
14557 json_object_free(json_scode
);
14558 json_object_free(json_ocode
);
14561 vty_json(vty
, json
);
14562 } else if (output_count
> 0) {
14563 if (!match
&& filtered_count
> 0)
14565 "\nTotal number of prefixes %ld (%ld filtered)\n",
14566 output_count
, filtered_count
);
14568 vty_out(vty
, "\nTotal number of prefixes %ld\n",
14572 return CMD_SUCCESS
;
14575 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
14576 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
14577 "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]",
14581 BGP_INSTANCE_HELP_STR
14583 BGP_SAFI_WITH_LABEL_HELP_STR
14584 "Detailed information on TCP and BGP neighbor connections\n"
14585 "Neighbor to display information about\n"
14586 "Neighbor to display information about\n"
14587 "Neighbor on BGP configured interface\n"
14588 "Display the routes selected by best path\n"
14589 "Display detailed version of routes\n"
14591 "Increase table width for longer prefixes\n")
14593 afi_t afi
= AFI_IP6
;
14594 safi_t safi
= SAFI_UNICAST
;
14595 char *rmap_name
= NULL
;
14596 char *peerstr
= NULL
;
14597 struct bgp
*bgp
= NULL
;
14599 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
14601 uint16_t show_flags
= 0;
14604 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14607 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14610 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14612 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14616 return CMD_WARNING
;
14618 argv_find(argv
, argc
, "neighbors", &idx
);
14619 peerstr
= argv
[++idx
]->arg
;
14621 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14623 return CMD_WARNING
;
14625 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, NULL
,
14629 DEFPY(show_ip_bgp_instance_neighbor_advertised_route
,
14630 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
14631 "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]",
14635 BGP_INSTANCE_HELP_STR
14637 BGP_SAFI_WITH_LABEL_HELP_STR
14638 "Display the entries for all address families\n"
14639 "Detailed information on TCP and BGP neighbor connections\n"
14640 "Neighbor to display information about\n"
14641 "Neighbor to display information about\n"
14642 "Neighbor on BGP configured interface\n"
14643 "Display the routes advertised to a BGP neighbor\n"
14644 "Display the received routes from neighbor\n"
14645 "Display the filtered routes received from neighbor\n"
14646 "Route-map to modify the attributes\n"
14647 "Name of the route map\n"
14650 "Display detailed version of routes\n"
14652 "Increase table width for longer prefixes\n")
14654 afi_t afi
= AFI_IP6
;
14655 safi_t safi
= SAFI_UNICAST
;
14656 char *peerstr
= NULL
;
14657 struct bgp
*bgp
= NULL
;
14659 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
14662 uint16_t show_flags
= 0;
14663 struct listnode
*node
;
14666 if (detail
|| prefix_str
)
14667 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14671 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14675 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
14676 if (argv_find(argv
, argc
, "ipv4", &idx
))
14677 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
14679 if (argv_find(argv
, argc
, "ipv6", &idx
))
14680 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
14684 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14686 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14689 return CMD_WARNING
;
14691 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14692 argv_find(argv
, argc
, "neighbors", &idx
);
14693 peerstr
= argv
[++idx
]->arg
;
14695 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14697 return CMD_WARNING
;
14699 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
14700 type
= bgp_show_adj_route_advertised
;
14701 else if (argv_find(argv
, argc
, "received-routes", &idx
))
14702 type
= bgp_show_adj_route_received
;
14703 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
14704 type
= bgp_show_adj_route_filtered
;
14707 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, route_map
,
14708 prefix_str
? prefix
: NULL
, show_flags
);
14710 vty_out(vty
, "{\n");
14712 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14713 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14714 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14716 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14717 FOREACH_SAFI (safi
) {
14718 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14725 vty_out(vty
, ",\n");
14726 vty_out(vty
, "\"%s\":",
14727 get_afi_safi_str(afi
, safi
,
14731 "\nFor address family: %s\n",
14732 get_afi_safi_str(afi
, safi
,
14735 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14736 route_map
, prefix
, show_flags
);
14740 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14741 FOREACH_AFI_SAFI (afi
, safi
) {
14742 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14749 vty_out(vty
, ",\n");
14750 vty_out(vty
, "\"%s\":",
14751 get_afi_safi_str(afi
, safi
,
14755 "\nFor address family: %s\n",
14756 get_afi_safi_str(afi
, safi
,
14759 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14760 route_map
, prefix
, show_flags
);
14765 vty_out(vty
, "}\n");
14767 return CMD_SUCCESS
;
14770 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14771 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14772 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14776 BGP_INSTANCE_HELP_STR
14779 BGP_AF_MODIFIER_STR
14780 "Detailed information on TCP and BGP neighbor connections\n"
14781 "Neighbor to display information about\n"
14782 "Neighbor to display information about\n"
14783 "Neighbor on BGP configured interface\n"
14784 "Display information received from a BGP neighbor\n"
14785 "Display the prefixlist filter\n"
14788 afi_t afi
= AFI_IP6
;
14789 safi_t safi
= SAFI_UNICAST
;
14790 char *peerstr
= NULL
;
14795 struct bgp
*bgp
= NULL
;
14796 bool uj
= use_json(argc
, argv
);
14801 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14804 return CMD_WARNING
;
14806 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14807 argv_find(argv
, argc
, "neighbors", &idx
);
14808 peerstr
= argv
[++idx
]->arg
;
14810 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14812 return CMD_WARNING
;
14814 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14815 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14818 vty_out(vty
, "Address Family: %s\n",
14819 get_afi_safi_str(afi
, safi
, false));
14820 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14823 vty_out(vty
, "{}\n");
14825 vty_out(vty
, "No functional output\n");
14828 return CMD_SUCCESS
;
14831 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14832 afi_t afi
, safi_t safi
,
14833 enum bgp_show_type type
, bool use_json
)
14835 uint16_t show_flags
= 0;
14838 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14840 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14842 json_object
*json_no
= NULL
;
14843 json_no
= json_object_new_object();
14844 json_object_string_add(
14845 json_no
, "warning",
14846 "No such neighbor or address family");
14847 vty_out(vty
, "%s\n",
14848 json_object_to_json_string(json_no
));
14849 json_object_free(json_no
);
14851 vty_out(vty
, "%% No such neighbor or address family\n");
14852 return CMD_WARNING
;
14855 /* labeled-unicast routes live in the unicast table */
14856 if (safi
== SAFI_LABELED_UNICAST
)
14857 safi
= SAFI_UNICAST
;
14859 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14860 RPKI_NOT_BEING_USED
);
14863 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14864 show_ip_bgp_flowspec_routes_detailed_cmd
,
14865 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14869 BGP_INSTANCE_HELP_STR
14872 "Detailed information on flowspec entries\n"
14875 afi_t afi
= AFI_IP6
;
14876 safi_t safi
= SAFI_UNICAST
;
14877 struct bgp
*bgp
= NULL
;
14879 bool uj
= use_json(argc
, argv
);
14880 uint16_t show_flags
= BGP_SHOW_OPT_ROUTES_DETAIL
;
14884 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14887 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14890 return CMD_WARNING
;
14892 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14893 show_flags
, RPKI_NOT_BEING_USED
);
14896 DEFUN (show_ip_bgp_neighbor_routes
,
14897 show_ip_bgp_neighbor_routes_cmd
,
14898 "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]",
14902 BGP_INSTANCE_HELP_STR
14904 BGP_SAFI_WITH_LABEL_HELP_STR
14905 "Detailed information on TCP and BGP neighbor connections\n"
14906 "Neighbor to display information about\n"
14907 "Neighbor to display information about\n"
14908 "Neighbor on BGP configured interface\n"
14909 "Display flap statistics of the routes learned from neighbor\n"
14910 "Display the dampened routes received from neighbor\n"
14911 "Display routes learned from neighbor\n"
14914 char *peerstr
= NULL
;
14915 struct bgp
*bgp
= NULL
;
14916 afi_t afi
= AFI_IP6
;
14917 safi_t safi
= SAFI_UNICAST
;
14919 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14921 bool uj
= use_json(argc
, argv
);
14926 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14929 return CMD_WARNING
;
14931 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14932 argv_find(argv
, argc
, "neighbors", &idx
);
14933 peerstr
= argv
[++idx
]->arg
;
14935 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14937 return CMD_WARNING
;
14939 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14940 sh_type
= bgp_show_type_flap_neighbor
;
14941 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14942 sh_type
= bgp_show_type_damp_neighbor
;
14943 else if (argv_find(argv
, argc
, "routes", &idx
))
14944 sh_type
= bgp_show_type_neighbor
;
14946 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14949 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14951 struct bgp_distance
{
14952 /* Distance value for the IP source prefix. */
14955 /* Name of the access-list to be matched. */
14959 DEFUN (show_bgp_afi_vpn_rd_route
,
14960 show_bgp_afi_vpn_rd_route_cmd
,
14961 "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]",
14965 BGP_AF_MODIFIER_STR
14966 "Display information for a route distinguisher\n"
14967 "Route Distinguisher\n"
14968 "All Route Distinguishers\n"
14969 "Network in the BGP routing table to display\n"
14970 "Network in the BGP routing table to display\n"
14974 struct prefix_rd prd
;
14975 afi_t afi
= AFI_MAX
;
14978 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
14979 vty_out(vty
, "%% Malformed Address Family\n");
14980 return CMD_WARNING
;
14983 if (!strcmp(argv
[5]->arg
, "all"))
14984 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
14985 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
14986 RPKI_NOT_BEING_USED
,
14987 use_json(argc
, argv
));
14989 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
14991 vty_out(vty
, "%% Malformed Route Distinguisher\n");
14992 return CMD_WARNING
;
14995 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
14996 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14997 use_json(argc
, argv
));
15000 static struct bgp_distance
*bgp_distance_new(void)
15002 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
15005 static void bgp_distance_free(struct bgp_distance
*bdistance
)
15007 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
15010 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
15011 const char *ip_str
, const char *access_list_str
)
15018 struct bgp_dest
*dest
;
15019 struct bgp_distance
*bdistance
;
15021 afi
= bgp_node_afi(vty
);
15022 safi
= bgp_node_safi(vty
);
15024 ret
= str2prefix(ip_str
, &p
);
15026 vty_out(vty
, "Malformed prefix\n");
15027 return CMD_WARNING_CONFIG_FAILED
;
15030 distance
= atoi(distance_str
);
15032 /* Get BGP distance node. */
15033 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
15034 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15036 bgp_dest_unlock_node(dest
);
15038 bdistance
= bgp_distance_new();
15039 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
15042 /* Set distance value. */
15043 bdistance
->distance
= distance
;
15045 /* Reset access-list configuration. */
15046 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
15047 if (access_list_str
)
15048 bdistance
->access_list
=
15049 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
15051 return CMD_SUCCESS
;
15054 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
15055 const char *ip_str
, const char *access_list_str
)
15062 struct bgp_dest
*dest
;
15063 struct bgp_distance
*bdistance
;
15065 afi
= bgp_node_afi(vty
);
15066 safi
= bgp_node_safi(vty
);
15068 ret
= str2prefix(ip_str
, &p
);
15070 vty_out(vty
, "Malformed prefix\n");
15071 return CMD_WARNING_CONFIG_FAILED
;
15074 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
15076 vty_out(vty
, "Can't find specified prefix\n");
15077 return CMD_WARNING_CONFIG_FAILED
;
15080 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15081 distance
= atoi(distance_str
);
15083 if (bdistance
->distance
!= distance
) {
15084 vty_out(vty
, "Distance does not match configured\n");
15085 bgp_dest_unlock_node(dest
);
15086 return CMD_WARNING_CONFIG_FAILED
;
15089 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
15090 bgp_distance_free(bdistance
);
15092 bgp_dest_set_bgp_path_info(dest
, NULL
);
15093 bgp_dest_unlock_node(dest
);
15094 bgp_dest_unlock_node(dest
);
15096 return CMD_SUCCESS
;
15099 /* Apply BGP information to distance method. */
15100 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
15101 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
15103 struct bgp_dest
*dest
;
15104 struct prefix q
= {0};
15106 struct bgp_distance
*bdistance
;
15107 struct access_list
*alist
;
15108 struct bgp_static
*bgp_static
;
15109 struct bgp_path_info
*bpi_ultimate
;
15114 peer
= pinfo
->peer
;
15116 if (pinfo
->attr
->distance
)
15117 return pinfo
->attr
->distance
;
15119 /* get peer origin to calculate appropriate distance */
15120 if (pinfo
->sub_type
== BGP_ROUTE_IMPORTED
) {
15121 bpi_ultimate
= bgp_get_imported_bpi_ultimate(pinfo
);
15122 peer
= bpi_ultimate
->peer
;
15125 /* Check source address.
15126 * Note: for aggregate route, peer can have unspec af type.
15128 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
15129 && !sockunion2hostprefix(&peer
->su
, &q
))
15132 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
15134 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15135 bgp_dest_unlock_node(dest
);
15137 if (bdistance
->access_list
) {
15138 alist
= access_list_lookup(afi
, bdistance
->access_list
);
15140 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
15141 return bdistance
->distance
;
15143 return bdistance
->distance
;
15146 /* Backdoor check. */
15147 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
15149 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15150 bgp_dest_unlock_node(dest
);
15152 if (bgp_static
->backdoor
) {
15153 if (bgp
->distance_local
[afi
][safi
])
15154 return bgp
->distance_local
[afi
][safi
];
15156 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15160 if (peer
->sort
== BGP_PEER_EBGP
) {
15161 if (bgp
->distance_ebgp
[afi
][safi
])
15162 return bgp
->distance_ebgp
[afi
][safi
];
15163 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
15164 } else if (peer
->sort
== BGP_PEER_IBGP
) {
15165 if (bgp
->distance_ibgp
[afi
][safi
])
15166 return bgp
->distance_ibgp
[afi
][safi
];
15167 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15169 if (bgp
->distance_local
[afi
][safi
])
15170 return bgp
->distance_local
[afi
][safi
];
15171 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15175 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15176 * we should tell ZEBRA update the routes for a specific
15177 * AFI/SAFI to reflect changes in RIB.
15179 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
15181 safi_t update_safi
)
15186 FOREACH_AFI_SAFI (afi
, safi
) {
15187 if (!bgp_fibupd_safi(safi
))
15190 if (afi
!= update_afi
&& safi
!= update_safi
)
15193 if (BGP_DEBUG(zebra
, ZEBRA
))
15195 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15196 __func__
, afi
, safi
);
15197 bgp_zebra_announce_table(bgp
, afi
, safi
);
15201 DEFUN (bgp_distance
,
15203 "distance bgp (1-255) (1-255) (1-255)",
15204 "Define an administrative distance\n"
15206 "Distance for routes external to the AS\n"
15207 "Distance for routes internal to the AS\n"
15208 "Distance for local routes\n")
15210 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15211 int idx_number
= 2;
15212 int idx_number_2
= 3;
15213 int idx_number_3
= 4;
15214 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
15215 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
15216 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
15220 afi
= bgp_node_afi(vty
);
15221 safi
= bgp_node_safi(vty
);
15223 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
15224 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
15225 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
15226 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
15227 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
15228 bgp
->distance_local
[afi
][safi
] = distance_local
;
15229 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15231 return CMD_SUCCESS
;
15234 DEFUN (no_bgp_distance
,
15235 no_bgp_distance_cmd
,
15236 "no distance bgp [(1-255) (1-255) (1-255)]",
15238 "Define an administrative distance\n"
15240 "Distance for routes external to the AS\n"
15241 "Distance for routes internal to the AS\n"
15242 "Distance for local routes\n")
15244 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15248 afi
= bgp_node_afi(vty
);
15249 safi
= bgp_node_safi(vty
);
15251 if (bgp
->distance_ebgp
[afi
][safi
] != 0
15252 || bgp
->distance_ibgp
[afi
][safi
] != 0
15253 || bgp
->distance_local
[afi
][safi
] != 0) {
15254 bgp
->distance_ebgp
[afi
][safi
] = 0;
15255 bgp
->distance_ibgp
[afi
][safi
] = 0;
15256 bgp
->distance_local
[afi
][safi
] = 0;
15257 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15259 return CMD_SUCCESS
;
15263 DEFUN (bgp_distance_source
,
15264 bgp_distance_source_cmd
,
15265 "distance (1-255) A.B.C.D/M",
15266 "Define an administrative distance\n"
15267 "Administrative distance\n"
15268 "IP source prefix\n")
15270 int idx_number
= 1;
15271 int idx_ipv4_prefixlen
= 2;
15272 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15273 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15274 return CMD_SUCCESS
;
15277 DEFUN (no_bgp_distance_source
,
15278 no_bgp_distance_source_cmd
,
15279 "no distance (1-255) A.B.C.D/M",
15281 "Define an administrative distance\n"
15282 "Administrative distance\n"
15283 "IP source prefix\n")
15285 int idx_number
= 2;
15286 int idx_ipv4_prefixlen
= 3;
15287 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15288 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15289 return CMD_SUCCESS
;
15292 DEFUN (bgp_distance_source_access_list
,
15293 bgp_distance_source_access_list_cmd
,
15294 "distance (1-255) A.B.C.D/M WORD",
15295 "Define an administrative distance\n"
15296 "Administrative distance\n"
15297 "IP source prefix\n"
15298 "Access list name\n")
15300 int idx_number
= 1;
15301 int idx_ipv4_prefixlen
= 2;
15303 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15304 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15305 return CMD_SUCCESS
;
15308 DEFUN (no_bgp_distance_source_access_list
,
15309 no_bgp_distance_source_access_list_cmd
,
15310 "no distance (1-255) A.B.C.D/M WORD",
15312 "Define an administrative distance\n"
15313 "Administrative distance\n"
15314 "IP source prefix\n"
15315 "Access list name\n")
15317 int idx_number
= 2;
15318 int idx_ipv4_prefixlen
= 3;
15320 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15321 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15322 return CMD_SUCCESS
;
15325 DEFUN (ipv6_bgp_distance_source
,
15326 ipv6_bgp_distance_source_cmd
,
15327 "distance (1-255) X:X::X:X/M",
15328 "Define an administrative distance\n"
15329 "Administrative distance\n"
15330 "IP source prefix\n")
15332 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
15333 return CMD_SUCCESS
;
15336 DEFUN (no_ipv6_bgp_distance_source
,
15337 no_ipv6_bgp_distance_source_cmd
,
15338 "no distance (1-255) X:X::X:X/M",
15340 "Define an administrative distance\n"
15341 "Administrative distance\n"
15342 "IP source prefix\n")
15344 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
15345 return CMD_SUCCESS
;
15348 DEFUN (ipv6_bgp_distance_source_access_list
,
15349 ipv6_bgp_distance_source_access_list_cmd
,
15350 "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_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
15357 return CMD_SUCCESS
;
15360 DEFUN (no_ipv6_bgp_distance_source_access_list
,
15361 no_ipv6_bgp_distance_source_access_list_cmd
,
15362 "no distance (1-255) X:X::X:X/M WORD",
15364 "Define an administrative distance\n"
15365 "Administrative distance\n"
15366 "IP source prefix\n"
15367 "Access list name\n")
15369 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
15370 return CMD_SUCCESS
;
15373 DEFUN (bgp_damp_set
,
15375 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15376 "BGP Specific commands\n"
15377 "Enable route-flap dampening\n"
15378 "Half-life time for the penalty\n"
15379 "Value to start reusing a route\n"
15380 "Value to start suppressing a route\n"
15381 "Maximum duration to suppress a stable route\n")
15383 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15384 int idx_half_life
= 2;
15386 int idx_suppress
= 4;
15387 int idx_max_suppress
= 5;
15388 int half
= DEFAULT_HALF_LIFE
* 60;
15389 int reuse
= DEFAULT_REUSE
;
15390 int suppress
= DEFAULT_SUPPRESS
;
15391 int max
= 4 * half
;
15394 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15395 reuse
= atoi(argv
[idx_reuse
]->arg
);
15396 suppress
= atoi(argv
[idx_suppress
]->arg
);
15397 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
15398 } else if (argc
== 3) {
15399 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15404 * These can't be 0 but our SA doesn't understand the
15405 * way our cli is constructed
15409 if (suppress
< reuse
) {
15411 "Suppress value cannot be less than reuse value \n");
15415 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
15416 reuse
, suppress
, max
);
15419 DEFUN (bgp_damp_unset
,
15420 bgp_damp_unset_cmd
,
15421 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15423 "BGP Specific commands\n"
15424 "Enable route-flap dampening\n"
15425 "Half-life time for the penalty\n"
15426 "Value to start reusing a route\n"
15427 "Value to start suppressing a route\n"
15428 "Maximum duration to suppress a stable route\n")
15430 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15431 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
15434 /* Display specified route of BGP table. */
15435 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
15436 const char *ip_str
, afi_t afi
, safi_t safi
,
15437 struct prefix_rd
*prd
, int prefix_check
)
15440 struct prefix match
;
15441 struct bgp_dest
*dest
;
15442 struct bgp_dest
*rm
;
15443 struct bgp_path_info
*pi
;
15444 struct bgp_path_info
*pi_temp
;
15446 struct bgp_table
*table
;
15448 /* BGP structure lookup. */
15450 bgp
= bgp_lookup_by_name(view_name
);
15452 vty_out(vty
, "%% Can't find BGP instance %s\n",
15454 return CMD_WARNING
;
15457 bgp
= bgp_get_default();
15459 vty_out(vty
, "%% No BGP process is configured\n");
15460 return CMD_WARNING
;
15464 /* Check IP address argument. */
15465 ret
= str2prefix(ip_str
, &match
);
15467 vty_out(vty
, "%% address is malformed\n");
15468 return CMD_WARNING
;
15471 match
.family
= afi2family(afi
);
15473 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
15474 || (safi
== SAFI_EVPN
)) {
15475 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
15476 dest
= bgp_route_next(dest
)) {
15477 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15479 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
15481 table
= bgp_dest_get_bgp_table_info(dest
);
15484 rm
= bgp_node_match(table
, &match
);
15488 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
15491 || rm_p
->prefixlen
== match
.prefixlen
) {
15492 pi
= bgp_dest_get_bgp_path_info(rm
);
15494 if (pi
->extra
&& pi
->extra
->damp_info
) {
15495 pi_temp
= pi
->next
;
15496 bgp_damp_info_free(
15497 pi
->extra
->damp_info
,
15505 bgp_dest_unlock_node(rm
);
15508 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
15509 if (dest
!= NULL
) {
15510 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15513 || dest_p
->prefixlen
== match
.prefixlen
) {
15514 pi
= bgp_dest_get_bgp_path_info(dest
);
15516 if (pi
->extra
&& pi
->extra
->damp_info
) {
15517 pi_temp
= pi
->next
;
15518 bgp_damp_info_free(
15519 pi
->extra
->damp_info
,
15527 bgp_dest_unlock_node(dest
);
15531 return CMD_SUCCESS
;
15534 DEFUN (clear_ip_bgp_dampening
,
15535 clear_ip_bgp_dampening_cmd
,
15536 "clear ip bgp dampening",
15540 "Clear route flap dampening information\n")
15542 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
15543 return CMD_SUCCESS
;
15546 DEFUN (clear_ip_bgp_dampening_prefix
,
15547 clear_ip_bgp_dampening_prefix_cmd
,
15548 "clear ip bgp dampening A.B.C.D/M",
15552 "Clear route flap dampening information\n"
15555 int idx_ipv4_prefixlen
= 4;
15556 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
15557 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
15560 DEFUN (clear_ip_bgp_dampening_address
,
15561 clear_ip_bgp_dampening_address_cmd
,
15562 "clear ip bgp dampening A.B.C.D",
15566 "Clear route flap dampening information\n"
15567 "Network to clear damping information\n")
15570 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
15571 SAFI_UNICAST
, NULL
, 0);
15574 DEFUN (clear_ip_bgp_dampening_address_mask
,
15575 clear_ip_bgp_dampening_address_mask_cmd
,
15576 "clear ip bgp dampening A.B.C.D A.B.C.D",
15580 "Clear route flap dampening information\n"
15581 "Network to clear damping information\n"
15585 int idx_ipv4_2
= 5;
15587 char prefix_str
[BUFSIZ
];
15589 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
15590 prefix_str
, sizeof(prefix_str
));
15592 vty_out(vty
, "%% Inconsistent address and mask\n");
15593 return CMD_WARNING
;
15596 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
15600 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
15602 struct vty
*vty
= arg
;
15603 struct peer
*peer
= bucket
->data
;
15605 vty_out(vty
, "\tPeer: %s %pSU\n", peer
->host
, &peer
->su
);
15608 DEFUN (show_bgp_listeners
,
15609 show_bgp_listeners_cmd
,
15610 "show bgp listeners",
15613 "Display Listen Sockets and who created them\n")
15615 bgp_dump_listener_info(vty
);
15617 return CMD_SUCCESS
;
15620 DEFUN (show_bgp_peerhash
,
15621 show_bgp_peerhash_cmd
,
15622 "show bgp peerhash",
15625 "Display information about the BGP peerhash\n")
15627 struct list
*instances
= bm
->bgp
;
15628 struct listnode
*node
;
15631 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
15632 vty_out(vty
, "BGP: %s\n", bgp
->name
);
15633 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
15637 return CMD_SUCCESS
;
15640 /* also used for encap safi */
15641 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
15642 afi_t afi
, safi_t safi
)
15644 struct bgp_dest
*pdest
;
15645 struct bgp_dest
*dest
;
15646 struct bgp_table
*table
;
15647 const struct prefix
*p
;
15648 struct bgp_static
*bgp_static
;
15649 mpls_label_t label
;
15651 /* Network configuration. */
15652 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15653 pdest
= bgp_route_next(pdest
)) {
15654 table
= bgp_dest_get_bgp_table_info(pdest
);
15658 for (dest
= bgp_table_top(table
); dest
;
15659 dest
= bgp_route_next(dest
)) {
15660 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15661 if (bgp_static
== NULL
)
15664 p
= bgp_dest_get_prefix(dest
);
15666 /* "network" configuration display. */
15667 label
= decode_label(&bgp_static
->label
);
15669 vty_out(vty
, " network %pFX rd %s", p
,
15670 bgp_static
->prd_pretty
);
15671 if (safi
== SAFI_MPLS_VPN
)
15672 vty_out(vty
, " label %u", label
);
15674 if (bgp_static
->rmap
.name
)
15675 vty_out(vty
, " route-map %s",
15676 bgp_static
->rmap
.name
);
15678 if (bgp_static
->backdoor
)
15679 vty_out(vty
, " backdoor");
15681 vty_out(vty
, "\n");
15686 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
15687 afi_t afi
, safi_t safi
)
15689 struct bgp_dest
*pdest
;
15690 struct bgp_dest
*dest
;
15691 struct bgp_table
*table
;
15692 const struct prefix
*p
;
15693 struct bgp_static
*bgp_static
;
15694 char buf
[PREFIX_STRLEN
* 2];
15695 char buf2
[SU_ADDRSTRLEN
];
15696 char esi_buf
[ESI_STR_LEN
];
15698 /* Network configuration. */
15699 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15700 pdest
= bgp_route_next(pdest
)) {
15701 table
= bgp_dest_get_bgp_table_info(pdest
);
15705 for (dest
= bgp_table_top(table
); dest
;
15706 dest
= bgp_route_next(dest
)) {
15707 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15708 if (bgp_static
== NULL
)
15711 char *macrouter
= NULL
;
15713 if (bgp_static
->router_mac
)
15714 macrouter
= prefix_mac2str(
15715 bgp_static
->router_mac
, NULL
, 0);
15716 if (bgp_static
->eth_s_id
)
15717 esi_to_str(bgp_static
->eth_s_id
,
15718 esi_buf
, sizeof(esi_buf
));
15719 p
= bgp_dest_get_prefix(dest
);
15721 /* "network" configuration display. */
15722 if (p
->u
.prefix_evpn
.route_type
== 5) {
15723 char local_buf
[PREFIX_STRLEN
];
15725 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15726 struct prefix_evpn
*)p
)
15730 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
15732 local_buf
, sizeof(local_buf
));
15733 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15734 p
->u
.prefix_evpn
.prefix_addr
15735 .ip_prefix_length
);
15737 prefix2str(p
, buf
, sizeof(buf
));
15740 if (bgp_static
->gatewayIp
.family
== AF_INET
15741 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15742 inet_ntop(bgp_static
->gatewayIp
.family
,
15743 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15746 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15747 buf
, bgp_static
->prd_pretty
,
15748 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15749 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15752 XFREE(MTYPE_TMP
, macrouter
);
15757 /* Configuration of static route announcement and aggregate
15759 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15762 struct bgp_dest
*dest
;
15763 const struct prefix
*p
;
15764 struct bgp_static
*bgp_static
;
15765 struct bgp_aggregate
*bgp_aggregate
;
15767 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15768 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15772 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15773 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15777 /* Network configuration. */
15778 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15779 dest
= bgp_route_next(dest
)) {
15780 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15781 if (bgp_static
== NULL
)
15784 p
= bgp_dest_get_prefix(dest
);
15786 vty_out(vty
, " network %pFX", p
);
15788 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15789 vty_out(vty
, " label-index %u",
15790 bgp_static
->label_index
);
15792 if (bgp_static
->rmap
.name
)
15793 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15795 if (bgp_static
->backdoor
)
15796 vty_out(vty
, " backdoor");
15798 vty_out(vty
, "\n");
15801 /* Aggregate-address configuration. */
15802 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15803 dest
= bgp_route_next(dest
)) {
15804 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15805 if (bgp_aggregate
== NULL
)
15808 p
= bgp_dest_get_prefix(dest
);
15810 vty_out(vty
, " aggregate-address %pFX", p
);
15812 if (bgp_aggregate
->as_set
)
15813 vty_out(vty
, " as-set");
15815 if (bgp_aggregate
->summary_only
)
15816 vty_out(vty
, " summary-only");
15818 if (bgp_aggregate
->rmap
.name
)
15819 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15821 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15822 vty_out(vty
, " origin %s",
15823 bgp_origin2str(bgp_aggregate
->origin
));
15825 if (bgp_aggregate
->match_med
)
15826 vty_out(vty
, " matching-MED-only");
15828 if (bgp_aggregate
->suppress_map_name
)
15829 vty_out(vty
, " suppress-map %s",
15830 bgp_aggregate
->suppress_map_name
);
15832 vty_out(vty
, "\n");
15836 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15839 struct bgp_dest
*dest
;
15840 struct bgp_distance
*bdistance
;
15842 /* Distance configuration. */
15843 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15844 && bgp
->distance_local
[afi
][safi
]
15845 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15846 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15847 || bgp
->distance_local
[afi
][safi
]
15848 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15849 vty_out(vty
, " distance bgp %d %d %d\n",
15850 bgp
->distance_ebgp
[afi
][safi
],
15851 bgp
->distance_ibgp
[afi
][safi
],
15852 bgp
->distance_local
[afi
][safi
]);
15855 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15856 dest
= bgp_route_next(dest
)) {
15857 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15858 if (bdistance
!= NULL
)
15859 vty_out(vty
, " distance %d %pBD %s\n",
15860 bdistance
->distance
, dest
,
15861 bdistance
->access_list
? bdistance
->access_list
15866 /* Allocate routing table structure and install commands. */
15867 void bgp_route_init(void)
15872 /* Init BGP distance table. */
15873 FOREACH_AFI_SAFI (afi
, safi
)
15874 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15876 /* IPv4 BGP commands. */
15877 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15878 install_element(BGP_NODE
, &bgp_network_cmd
);
15879 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15881 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15883 /* IPv4 unicast configuration. */
15884 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15885 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15886 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15888 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15890 /* IPv4 multicast configuration. */
15891 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15892 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15893 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15894 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15896 /* IPv4 labeled-unicast configuration. */
15897 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15898 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15900 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15901 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15902 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15903 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15904 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15905 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15906 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15907 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15909 install_element(VIEW_NODE
,
15910 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15911 install_element(VIEW_NODE
,
15912 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15913 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15914 install_element(VIEW_NODE
,
15915 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15916 #ifdef KEEP_OLD_VPN_COMMANDS
15917 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15918 #endif /* KEEP_OLD_VPN_COMMANDS */
15919 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15920 install_element(VIEW_NODE
,
15921 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15923 /* BGP dampening clear commands */
15924 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15925 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15927 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15928 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15931 install_element(ENABLE_NODE
,
15932 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15933 #ifdef KEEP_OLD_VPN_COMMANDS
15934 install_element(ENABLE_NODE
,
15935 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15936 #endif /* KEEP_OLD_VPN_COMMANDS */
15938 /* New config IPv6 BGP commands. */
15939 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15940 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15941 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15943 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15945 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15947 /* IPv6 labeled unicast address family. */
15948 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15949 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15951 install_element(BGP_NODE
, &bgp_distance_cmd
);
15952 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15953 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15954 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
15955 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
15956 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
15957 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15958 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15959 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15960 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
15961 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
15962 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
15963 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15964 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15965 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
15966 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
15967 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
15968 install_element(BGP_IPV4M_NODE
,
15969 &no_bgp_distance_source_access_list_cmd
);
15970 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
15971 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
15972 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
15973 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15974 install_element(BGP_IPV6_NODE
,
15975 &ipv6_bgp_distance_source_access_list_cmd
);
15976 install_element(BGP_IPV6_NODE
,
15977 &no_ipv6_bgp_distance_source_access_list_cmd
);
15978 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
15979 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
15980 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
15981 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15982 install_element(BGP_IPV6M_NODE
,
15983 &ipv6_bgp_distance_source_access_list_cmd
);
15984 install_element(BGP_IPV6M_NODE
,
15985 &no_ipv6_bgp_distance_source_access_list_cmd
);
15987 /* BGP dampening */
15988 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
15989 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
15990 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
15991 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
15992 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
15993 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
15994 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
15995 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
15996 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
15997 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
15998 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
15999 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
16000 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
16001 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
16003 /* Large Communities */
16004 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
16005 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
16007 /* show bgp ipv4 flowspec detailed */
16008 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
16010 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
16011 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
16014 void bgp_route_finish(void)
16019 FOREACH_AFI_SAFI (afi
, safi
) {
16020 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
16021 bgp_distance_table
[afi
][safi
] = NULL
;