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'",
2389 peer
, p
, ROUTE_MAP_OUT_NAME(filter
));
2390 bgp_attr_flush(rmap_path
.attr
);
2395 /* RFC 8212 to prevent route leaks.
2396 * This specification intends to improve this situation by requiring the
2397 * explicit configuration of both BGP Import and Export Policies for any
2398 * External BGP (EBGP) session such as customers, peers, or
2399 * confederation boundaries for all enabled address families. Through
2400 * codification of the aforementioned requirement, operators will
2401 * benefit from consistent behavior across different BGP
2404 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2405 if (!bgp_outbound_policy_exists(peer
, filter
)) {
2406 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
2407 NULL
) > FIFTEENMINUTE2USEC
||
2408 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
2410 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2411 monotime(&bgp
->ebgprequirespolicywarning
);
2416 /* draft-ietf-idr-deprecate-as-set-confed-set
2417 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2418 * Eventually, This document (if approved) updates RFC 4271
2419 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2420 * and obsoletes RFC 6472.
2422 if (peer
->bgp
->reject_as_sets
)
2423 if (aspath_check_as_sets(attr
->aspath
))
2426 /* If neighbor soo is configured, then check if the route has
2427 * SoO extended community and validate against the configured
2428 * one. If they match, do not announce, to prevent routing
2431 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) &&
2432 peer
->soo
[afi
][safi
]) {
2433 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
2434 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
2436 if ((ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS
,
2437 ECOMMUNITY_SITE_ORIGIN
) ||
2438 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS4
,
2439 ECOMMUNITY_SITE_ORIGIN
) ||
2440 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_IP
,
2441 ECOMMUNITY_SITE_ORIGIN
)) &&
2442 ecommunity_include(ecomm
, ecomm_soo
)) {
2443 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2445 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2446 peer
, p
, ecommunity_str(ecomm_soo
));
2451 /* Codification of AS 0 Processing */
2452 if (aspath_check_as_zero(attr
->aspath
))
2455 if (bgp_in_graceful_shutdown(bgp
)) {
2456 if (peer
->sort
== BGP_PEER_IBGP
2457 || peer
->sort
== BGP_PEER_CONFED
) {
2458 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2459 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2461 bgp_attr_add_gshut_community(attr
);
2465 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2466 * Capability" to a neighbor MUST perform the following upon receiving
2467 * a route from that neighbor with the "LLGR_STALE" community, or upon
2468 * attaching the "LLGR_STALE" community itself per Section 4.2:
2470 * The route SHOULD NOT be advertised to any neighbor from which the
2471 * Long-lived Graceful Restart Capability has not been received.
2473 if (bgp_attr_get_community(attr
) &&
2474 community_include(bgp_attr_get_community(attr
),
2475 COMMUNITY_LLGR_STALE
) &&
2476 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_RCV
) &&
2477 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_ADV
))
2480 /* After route-map has been applied, we check to see if the nexthop to
2481 * be carried in the attribute (that is used for the announcement) can
2482 * be cleared off or not. We do this in all cases where we would be
2483 * setting the nexthop to "ourselves". For IPv6, we only need to
2485 * the global nexthop here; the link-local nexthop would have been
2487 * already, and if not, it is required by the update formation code.
2488 * Also see earlier comments in this function.
2491 * If route-map has performed some operation on the nexthop or the peer
2492 * configuration says to pass it unchanged, we cannot reset the nexthop
2493 * here, so only attempt to do it if these aren't true. Note that the
2494 * route-map handler itself might have cleared the nexthop, if for
2496 * it is configured as 'peer-address'.
2498 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2499 piattr
->rmap_change_flags
)
2501 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2502 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2503 /* We can reset the nexthop, if setting (or forcing) it to
2505 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2506 PEER_FLAG_NEXTHOP_SELF
)
2507 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2508 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2510 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2511 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2512 subgroup_announce_reset_nhop(
2513 (peer_cap_enhe(peer
, afi
, safi
)
2519 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2520 /* Can also reset the nexthop if announcing to EBGP, but
2522 * no peer in the subgroup is on a shared subnet.
2523 * Note: 3rd party nexthop currently implemented for
2526 if ((p
->family
== AF_INET
) &&
2527 (!bgp_subgrp_multiaccess_check_v4(
2530 subgroup_announce_reset_nhop(
2531 (peer_cap_enhe(peer
, afi
, safi
)
2538 if ((p
->family
== AF_INET6
) &&
2539 (!bgp_subgrp_multiaccess_check_v6(
2540 piattr
->mp_nexthop_global
,
2542 subgroup_announce_reset_nhop(
2543 (peer_cap_enhe(peer
, afi
, safi
)
2552 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2554 * This flag is used for leaked vpn-vrf routes
2556 int family
= p
->family
;
2558 if (peer_cap_enhe(peer
, afi
, safi
))
2561 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2563 "%s: %pFX BGP_PATH_ANNC_NH_SELF, family=%s",
2564 __func__
, p
, family2str(family
));
2565 subgroup_announce_reset_nhop(family
, attr
);
2570 /* If IPv6/MP and nexthop does not have any override and happens
2572 * be a link-local address, reset it so that we don't pass along
2574 * source's link-local IPv6 address to recipients who may not be
2576 * the same interface.
2578 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2579 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2580 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2585 /* If this is an iBGP, send Origin Validation State (OVS)
2586 * extended community (rfc8097).
2588 if (peer
->sort
== BGP_PEER_IBGP
) {
2589 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
2591 rpki_state
= hook_call(bgp_rpki_prefix_status
, peer
, attr
, p
);
2593 if (rpki_state
!= RPKI_NOT_BEING_USED
)
2594 bgp_attr_set_ecommunity(
2595 attr
, ecommunity_add_origin_validation_state(
2597 bgp_attr_get_ecommunity(attr
)));
2601 * When the next hop is set to ourselves, if all multipaths have
2602 * link-bandwidth announce the cumulative bandwidth as that makes
2603 * the most sense. However, don't modify if the link-bandwidth has
2604 * been explicitly set by user policy.
2607 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2608 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2609 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2610 bgp_attr_set_ecommunity(
2612 ecommunity_replace_linkbw(
2613 bgp
->as
, bgp_attr_get_ecommunity(attr
), cum_bw
,
2616 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
)));
2621 static void bgp_route_select_timer_expire(struct thread
*thread
)
2623 struct afi_safi_info
*info
;
2628 info
= THREAD_ARG(thread
);
2633 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2634 XFREE(MTYPE_TMP
, info
);
2636 /* Best path selection */
2637 bgp_best_path_select_defer(bgp
, afi
, safi
);
2640 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2641 struct bgp_maxpaths_cfg
*mpath_cfg
,
2642 struct bgp_path_info_pair
*result
, afi_t afi
,
2645 struct bgp_path_info
*new_select
;
2646 struct bgp_path_info
*old_select
;
2647 struct bgp_path_info
*pi
;
2648 struct bgp_path_info
*pi1
;
2649 struct bgp_path_info
*pi2
;
2650 struct bgp_path_info
*nextpi
= NULL
;
2651 int paths_eq
, do_mpath
, debug
;
2652 struct list mp_list
;
2653 char pfx_buf
[PREFIX2STR_BUFFER
];
2654 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2656 bgp_mp_list_init(&mp_list
);
2658 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2660 debug
= bgp_debug_bestpath(dest
);
2663 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2665 dest
->reason
= bgp_path_selection_none
;
2666 /* bgp deterministic-med */
2668 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2670 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2671 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2673 bgp_path_info_unset_flag(dest
, pi1
,
2674 BGP_PATH_DMED_SELECTED
);
2676 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2678 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2680 if (BGP_PATH_HOLDDOWN(pi1
))
2682 if (pi1
->peer
!= bgp
->peer_self
&&
2683 !CHECK_FLAG(pi1
->peer
->sflags
,
2684 PEER_STATUS_NSF_WAIT
)) {
2685 if (!peer_established(pi1
->peer
))
2691 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2692 if (CHECK_FLAG(pi2
->flags
,
2693 BGP_PATH_DMED_CHECK
))
2695 if (BGP_PATH_HOLDDOWN(pi2
))
2697 if (pi2
->peer
!= bgp
->peer_self
2700 PEER_STATUS_NSF_WAIT
))
2701 if (pi2
->peer
->status
2705 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2707 && !aspath_cmp_left_confed(
2712 if (bgp_path_info_cmp(
2713 bgp
, pi2
, new_select
,
2714 &paths_eq
, mpath_cfg
, debug
,
2717 bgp_path_info_unset_flag(
2719 BGP_PATH_DMED_SELECTED
);
2723 bgp_path_info_set_flag(
2724 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2727 bgp_path_info_set_flag(dest
, new_select
,
2728 BGP_PATH_DMED_CHECK
);
2729 bgp_path_info_set_flag(dest
, new_select
,
2730 BGP_PATH_DMED_SELECTED
);
2733 bgp_path_info_path_with_addpath_rx_str(
2734 new_select
, path_buf
, sizeof(path_buf
));
2736 "%pBD(%s): %s is the bestpath from AS %u",
2737 dest
, bgp
->name_pretty
, path_buf
,
2738 aspath_get_first_as(
2739 new_select
->attr
->aspath
));
2744 /* Check old selected route and new selected route. */
2747 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2748 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2749 enum bgp_path_selection_reason reason
;
2751 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2754 if (BGP_PATH_HOLDDOWN(pi
)) {
2755 /* reap REMOVED routes, if needs be
2756 * selected route must stay for a while longer though
2758 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2759 && (pi
!= old_select
))
2760 bgp_path_info_reap(dest
, pi
);
2764 "%s: %pBD(%s) pi from %s in holddown",
2765 __func__
, dest
, bgp
->name_pretty
,
2771 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2772 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2773 if (!peer_established(pi
->peer
)) {
2777 "%s: %pBD(%s) non self peer %s not estab state",
2785 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2786 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2787 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2789 zlog_debug("%s: %pBD(%s) pi %s dmed", __func__
,
2790 dest
, bgp
->name_pretty
,
2795 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2797 reason
= dest
->reason
;
2798 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2799 debug
, pfx_buf
, afi
, safi
,
2801 if (new_select
== NULL
&&
2802 reason
!= bgp_path_selection_none
)
2803 dest
->reason
= reason
;
2808 /* Now that we know which path is the bestpath see if any of the other
2810 * qualify as multipaths
2814 bgp_path_info_path_with_addpath_rx_str(
2815 new_select
, path_buf
, sizeof(path_buf
));
2817 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2819 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2820 dest
, bgp
->name_pretty
, path_buf
,
2821 old_select
? old_select
->peer
->host
: "NONE");
2824 if (do_mpath
&& new_select
) {
2825 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2826 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2829 bgp_path_info_path_with_addpath_rx_str(
2830 pi
, path_buf
, sizeof(path_buf
));
2832 if (pi
== new_select
) {
2835 "%pBD(%s): %s is the bestpath, add to the multipath list",
2836 dest
, bgp
->name_pretty
,
2838 bgp_mp_list_add(&mp_list
, pi
);
2842 if (BGP_PATH_HOLDDOWN(pi
))
2845 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2846 && !CHECK_FLAG(pi
->peer
->sflags
,
2847 PEER_STATUS_NSF_WAIT
))
2848 if (!peer_established(pi
->peer
))
2851 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2854 "%pBD(%s): %s has the same nexthop as the bestpath, skip it",
2855 dest
, bgp
->name_pretty
,
2860 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2861 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2867 "%pBD(%s): %s is equivalent to the bestpath, add to the multipath list",
2868 dest
, bgp
->name_pretty
,
2870 bgp_mp_list_add(&mp_list
, pi
);
2875 bgp_path_info_mpath_update(bgp
, dest
, new_select
, old_select
, &mp_list
,
2877 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2878 bgp_mp_list_clear(&mp_list
);
2880 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2882 result
->old
= old_select
;
2883 result
->new = new_select
;
2889 * A new route/change in bestpath of an existing route. Evaluate the path
2890 * for advertisement to the subgroup.
2892 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2893 struct bgp_path_info
*selected
,
2894 struct bgp_dest
*dest
,
2895 uint32_t addpath_tx_id
)
2897 const struct prefix
*p
;
2898 struct peer
*onlypeer
;
2905 p
= bgp_dest_get_prefix(dest
);
2906 afi
= SUBGRP_AFI(subgrp
);
2907 safi
= SUBGRP_SAFI(subgrp
);
2908 bgp
= SUBGRP_INST(subgrp
);
2909 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2912 if (BGP_DEBUG(update
, UPDATE_OUT
))
2913 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2915 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2916 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2917 PEER_STATUS_ORF_WAIT_REFRESH
))
2920 memset(&attr
, 0, sizeof(attr
));
2921 /* It's initialized in bgp_announce_check() */
2923 /* Announcement to the subgroup. If the route is filtered withdraw it.
2924 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2925 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2928 advertise
= bgp_check_advertise(bgp
, dest
);
2931 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2933 /* Route is selected, if the route is already installed
2934 * in FIB, then it is advertised
2937 if (!bgp_check_withdrawal(bgp
, dest
)) {
2938 struct attr
*adv_attr
=
2939 bgp_attr_intern(&attr
);
2941 bgp_adj_out_set_subgroup(dest
, subgrp
,
2945 bgp_adj_out_unset_subgroup(
2946 dest
, subgrp
, 1, addpath_tx_id
);
2949 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2953 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2955 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2960 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2961 * This is called at the end of route processing.
2963 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2965 struct bgp_path_info
*pi
;
2967 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2968 if (BGP_PATH_HOLDDOWN(pi
))
2970 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2971 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2976 * Has the route changed from the RIB's perspective? This is invoked only
2977 * if the route selection returns the same best route as earlier - to
2978 * determine if we need to update zebra or not.
2980 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2982 struct bgp_path_info
*mpinfo
;
2984 /* If this is multipath, check all selected paths for any nexthop
2985 * change or attribute change. Some attribute changes (e.g., community)
2986 * aren't of relevance to the RIB, but we'll update zebra to ensure
2987 * we handle the case of BGP nexthop change. This is the behavior
2988 * when the best path has an attribute change anyway.
2990 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2991 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2992 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2996 * If this is multipath, check all selected paths for any nexthop change
2998 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2999 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
3000 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
3001 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
3005 /* Nothing has changed from the RIB's perspective. */
3009 struct bgp_process_queue
{
3011 STAILQ_HEAD(, bgp_dest
) pqueue
;
3012 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
3014 unsigned int queued
;
3017 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
3018 safi_t safi
, struct bgp_dest
*dest
,
3019 struct bgp_path_info
*new_select
,
3020 struct bgp_path_info
*old_select
)
3022 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3024 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
3027 if (advertise_type5_routes(bgp
, afi
) && new_select
3028 && is_route_injectable_into_evpn(new_select
)) {
3030 /* apply the route-map */
3031 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
3032 route_map_result_t ret
;
3033 struct bgp_path_info rmap_path
;
3034 struct bgp_path_info_extra rmap_path_extra
;
3035 struct attr dummy_attr
;
3037 dummy_attr
= *new_select
->attr
;
3039 /* Fill temp path_info */
3040 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
3041 new_select
, new_select
->peer
,
3044 RESET_FLAG(dummy_attr
.rmap_change_flags
);
3046 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
3049 if (ret
== RMAP_DENYMATCH
) {
3050 bgp_attr_flush(&dummy_attr
);
3051 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
3054 bgp_evpn_advertise_type5_route(
3055 bgp
, p
, &dummy_attr
, afi
, safi
);
3057 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
3060 } else if (advertise_type5_routes(bgp
, afi
) && old_select
3061 && is_route_injectable_into_evpn(old_select
))
3062 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
3066 * Utility to determine whether a particular path_info should use
3067 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3068 * in a path where we basically _know_ this is a BGP-LU route.
3070 static bool bgp_lu_need_imp_null(const struct bgp_path_info
*new_select
)
3072 /* Certain types get imp null; so do paths where the nexthop is
3075 if (new_select
->sub_type
== BGP_ROUTE_STATIC
3076 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3077 || new_select
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
3079 else if (new_select
->extra
== NULL
||
3080 !bgp_is_valid_label(&new_select
->extra
->label
[0]))
3081 /* TODO -- should be configurable? */
3088 * old_select = The old best path
3089 * new_select = the new best path
3091 * if (!old_select && new_select)
3092 * We are sending new information on.
3094 * if (old_select && new_select) {
3095 * if (new_select != old_select)
3096 * We have a new best path send a change
3098 * We've received a update with new attributes that needs
3102 * if (old_select && !new_select)
3103 * We have no eligible route that we can announce or the rn
3106 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
3107 afi_t afi
, safi_t safi
)
3109 struct bgp_path_info
*new_select
;
3110 struct bgp_path_info
*old_select
;
3111 struct bgp_path_info_pair old_and_new
;
3114 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
3116 debug
= bgp_debug_bestpath(dest
);
3119 "%s: bgp delete in progress, ignoring event, p=%pBD(%s)",
3120 __func__
, dest
, bgp
->name_pretty
);
3123 /* Is it end of initial update? (after startup) */
3125 frr_timestamp(3, bgp
->update_delay_zebra_resume_time
,
3126 sizeof(bgp
->update_delay_zebra_resume_time
));
3128 bgp
->main_zebra_update_hold
= 0;
3129 FOREACH_AFI_SAFI (afi
, safi
) {
3130 if (bgp_fibupd_safi(safi
))
3131 bgp_zebra_announce_table(bgp
, afi
, safi
);
3133 bgp
->main_peers_update_hold
= 0;
3135 bgp_start_routeadv(bgp
);
3139 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3141 debug
= bgp_debug_bestpath(dest
);
3143 zlog_debug("%s: p=%pBD(%s) afi=%s, safi=%s start", __func__
,
3144 dest
, bgp
->name_pretty
, afi2str(afi
),
3147 /* The best path calculation for the route is deferred if
3148 * BGP_NODE_SELECT_DEFER is set
3150 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3151 if (BGP_DEBUG(update
, UPDATE_OUT
))
3152 zlog_debug("SELECT_DEFER flag set for route %p(%s)",
3153 dest
, bgp
->name_pretty
);
3157 /* Best path selection. */
3158 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
3160 old_select
= old_and_new
.old
;
3161 new_select
= old_and_new
.new;
3163 /* Do we need to allocate or free labels?
3164 * Right now, since we only deal with per-prefix labels, it is not
3165 * necessary to do this upon changes to best path. Exceptions:
3166 * - label index has changed -> recalculate resulting label
3167 * - path_info sub_type changed -> switch to/from implicit-null
3168 * - no valid label (due to removed static label binding) -> get new one
3170 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
3173 || bgp_label_index_differs(new_select
, old_select
)
3174 || new_select
->sub_type
!= old_select
->sub_type
3175 || !bgp_is_valid_label(&dest
->local_label
)) {
3176 /* Enforced penultimate hop popping:
3177 * implicit-null for local routes, aggregate
3178 * and redistributed routes
3180 if (bgp_lu_need_imp_null(new_select
)) {
3183 BGP_NODE_REGISTERED_FOR_LABEL
)
3186 BGP_NODE_LABEL_REQUESTED
))
3187 bgp_unregister_for_label(dest
);
3188 dest
->local_label
= mpls_lse_encode(
3189 MPLS_LABEL_IMPLICIT_NULL
, 0, 0,
3191 bgp_set_valid_label(&dest
->local_label
);
3193 bgp_register_for_label(dest
,
3196 } else if (CHECK_FLAG(dest
->flags
,
3197 BGP_NODE_REGISTERED_FOR_LABEL
)
3198 || CHECK_FLAG(dest
->flags
,
3199 BGP_NODE_LABEL_REQUESTED
)) {
3200 bgp_unregister_for_label(dest
);
3202 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
3203 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
3204 bgp_unregister_for_label(dest
);
3209 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3210 __func__
, dest
, bgp
->name_pretty
, afi2str(afi
),
3211 safi2str(safi
), old_select
, new_select
);
3213 /* If best route remains the same and this is not due to user-initiated
3214 * clear, see exactly what needs to be done.
3216 if (old_select
&& old_select
== new_select
3217 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
3218 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3219 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
3220 if (bgp_zebra_has_route_changed(old_select
)) {
3221 #ifdef ENABLE_BGP_VNC
3222 vnc_import_bgp_add_route(bgp
, p
, old_select
);
3223 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
3225 if (bgp_fibupd_safi(safi
)
3226 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3228 if (BGP_SUPPRESS_FIB_ENABLED(bgp
)
3229 && new_select
->sub_type
== BGP_ROUTE_NORMAL
)
3230 SET_FLAG(dest
->flags
,
3231 BGP_NODE_FIB_INSTALL_PENDING
);
3233 if (new_select
->type
== ZEBRA_ROUTE_BGP
3234 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3235 || new_select
->sub_type
3236 == BGP_ROUTE_IMPORTED
))
3238 bgp_zebra_announce(dest
, p
, old_select
,
3243 /* If there is a change of interest to peers, reannounce the
3245 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3246 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3247 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
3248 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3250 /* unicast routes must also be annouced to
3251 * labeled-unicast update-groups */
3252 if (safi
== SAFI_UNICAST
)
3253 group_announce_route(bgp
, afi
,
3254 SAFI_LABELED_UNICAST
, dest
,
3257 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
3258 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
3261 /* advertise/withdraw type-5 routes */
3262 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3263 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
3264 bgp_process_evpn_route_injection(
3265 bgp
, afi
, safi
, dest
, old_select
, old_select
);
3267 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3268 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3269 bgp_zebra_clear_route_change_flags(dest
);
3270 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3274 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3276 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
3278 /* bestpath has changed; bump version */
3279 if (old_select
|| new_select
) {
3280 bgp_bump_version(dest
);
3282 if (!bgp
->t_rmap_def_originate_eval
) {
3286 update_group_refresh_default_originate_route_map
,
3287 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
3288 &bgp
->t_rmap_def_originate_eval
);
3293 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
3296 zlog_debug("%s: setting SELECTED flag", __func__
);
3297 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
3298 bgp_path_info_unset_flag(dest
, new_select
,
3299 BGP_PATH_ATTR_CHANGED
);
3300 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3301 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3304 #ifdef ENABLE_BGP_VNC
3305 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3306 if (old_select
!= new_select
) {
3308 vnc_import_bgp_exterior_del_route(bgp
, p
,
3310 vnc_import_bgp_del_route(bgp
, p
, old_select
);
3313 vnc_import_bgp_exterior_add_route(bgp
, p
,
3315 vnc_import_bgp_add_route(bgp
, p
, new_select
);
3321 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3323 /* unicast routes must also be annouced to labeled-unicast update-groups
3325 if (safi
== SAFI_UNICAST
)
3326 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
3330 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
3331 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3333 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
3334 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3335 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3336 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
3338 if (BGP_SUPPRESS_FIB_ENABLED(bgp
))
3339 SET_FLAG(dest
->flags
,
3340 BGP_NODE_FIB_INSTALL_PENDING
);
3342 /* if this is an evpn imported type-5 prefix,
3343 * we need to withdraw the route first to clear
3344 * the nh neigh and the RMAC entry.
3347 is_route_parent_evpn(old_select
))
3348 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3350 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
3352 /* Withdraw the route from the kernel. */
3353 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
3354 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
3355 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
3356 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
3358 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3362 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
3365 /* Clear any route change flags. */
3366 bgp_zebra_clear_route_change_flags(dest
);
3368 /* Reap old select bgp_path_info, if it has been removed */
3369 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
3370 bgp_path_info_reap(dest
, old_select
);
3372 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3376 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3377 void bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
3379 struct bgp_dest
*dest
;
3381 struct afi_safi_info
*thread_info
;
3383 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
3384 struct thread
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
3386 thread_info
= THREAD_ARG(t
);
3387 XFREE(MTYPE_TMP
, thread_info
);
3388 THREAD_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
3391 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
3392 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
3393 get_afi_safi_str(afi
, safi
, false),
3394 bgp
->gr_info
[afi
][safi
].gr_deferred
);
3397 /* Process the route list */
3398 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
3399 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0 &&
3400 cnt
< BGP_MAX_BEST_ROUTE_SELECT
;
3401 dest
= bgp_route_next(dest
)) {
3402 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
3405 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3406 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3407 bgp_process_main_one(bgp
, dest
, afi
, safi
);
3410 /* If iteration stopped before the entire table was traversed then the
3411 * node needs to be unlocked.
3414 bgp_dest_unlock_node(dest
);
3418 /* Send EOR message when all routes are processed */
3419 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
3420 bgp_send_delayed_eor(bgp
);
3421 /* Send route processing complete message to RIB */
3422 bgp_zebra_update(bgp
, afi
, safi
,
3423 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
3427 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3429 thread_info
->afi
= afi
;
3430 thread_info
->safi
= safi
;
3431 thread_info
->bgp
= bgp
;
3433 /* If there are more routes to be processed, start the
3436 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3437 BGP_ROUTE_SELECT_DELAY
,
3438 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3441 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3443 struct bgp_process_queue
*pqnode
= data
;
3444 struct bgp
*bgp
= pqnode
->bgp
;
3445 struct bgp_table
*table
;
3446 struct bgp_dest
*dest
;
3449 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3450 bgp_process_main_one(bgp
, NULL
, 0, 0);
3451 /* should always have dedicated wq call */
3452 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3456 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3457 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3458 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3459 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3460 table
= bgp_dest_table(dest
);
3461 /* note, new DESTs may be added as part of processing */
3462 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3464 bgp_dest_unlock_node(dest
);
3465 bgp_table_unlock(table
);
3471 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3473 struct bgp_process_queue
*pqnode
= data
;
3475 bgp_unlock(pqnode
->bgp
);
3477 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3480 void bgp_process_queue_init(struct bgp
*bgp
)
3482 if (!bgp
->process_queue
) {
3485 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3486 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3489 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3490 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3491 bgp
->process_queue
->spec
.max_retries
= 0;
3492 bgp
->process_queue
->spec
.hold
= 50;
3493 /* Use a higher yield value of 50ms for main queue processing */
3494 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3497 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3499 struct bgp_process_queue
*pqnode
;
3501 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3502 sizeof(struct bgp_process_queue
));
3504 /* unlocked in bgp_processq_del */
3505 pqnode
->bgp
= bgp_lock(bgp
);
3506 STAILQ_INIT(&pqnode
->pqueue
);
3511 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3513 #define ARBITRARY_PROCESS_QLEN 10000
3514 struct work_queue
*wq
= bgp
->process_queue
;
3515 struct bgp_process_queue
*pqnode
;
3516 int pqnode_reuse
= 0;
3518 /* already scheduled for processing? */
3519 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3522 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3525 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3526 if (BGP_DEBUG(update
, UPDATE_OUT
))
3527 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3532 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
)) {
3533 if (BGP_DEBUG(update
, UPDATE_OUT
))
3535 "Soft reconfigure table in progress for route %p",
3543 /* Add route nodes to an existing work queue item until reaching the
3544 limit only if is from the same BGP view and it's not an EOIU marker
3546 if (work_queue_item_count(wq
)) {
3547 struct work_queue_item
*item
= work_queue_last_item(wq
);
3548 pqnode
= item
->data
;
3550 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3551 || pqnode
->bgp
!= bgp
3552 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3553 pqnode
= bgp_processq_alloc(bgp
);
3557 pqnode
= bgp_processq_alloc(bgp
);
3558 /* all unlocked in bgp_process_wq */
3559 bgp_table_lock(bgp_dest_table(dest
));
3561 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3562 bgp_dest_lock_node(dest
);
3564 /* can't be enqueued twice */
3565 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3566 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3570 work_queue_add(wq
, pqnode
);
3575 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3577 struct bgp_process_queue
*pqnode
;
3579 if (bgp
->process_queue
== NULL
)
3582 pqnode
= bgp_processq_alloc(bgp
);
3584 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3585 work_queue_add(bgp
->process_queue
, pqnode
);
3588 static void bgp_maximum_prefix_restart_timer(struct thread
*thread
)
3592 peer
= THREAD_ARG(thread
);
3593 peer
->t_pmax_restart
= NULL
;
3595 if (bgp_debug_neighbor_events(peer
))
3597 "%s Maximum-prefix restart timer expired, restore peering",
3600 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3601 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3604 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3608 bool filtered
= false;
3609 struct bgp_dest
*dest
;
3610 struct bgp_adj_in
*ain
;
3611 struct attr attr
= {};
3612 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3614 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3615 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3616 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3620 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3624 if (bgp_input_modifier(
3625 peer
, rn_p
, &attr
, afi
, safi
,
3626 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3634 bgp_attr_flush(&attr
);
3641 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3645 iana_safi_t pkt_safi
;
3646 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3647 PEER_FLAG_MAX_PREFIX_FORCE
))
3648 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3649 + peer
->pcount
[afi
][safi
]
3650 : peer
->pcount
[afi
][safi
];
3652 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3655 if (pcount
> peer
->pmax
[afi
][safi
]) {
3656 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3657 PEER_STATUS_PREFIX_LIMIT
)
3662 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3663 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3664 peer
->pmax
[afi
][safi
]);
3665 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3667 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3668 PEER_FLAG_MAX_PREFIX_WARNING
))
3671 /* Convert AFI, SAFI to values for packet. */
3672 pkt_afi
= afi_int2iana(afi
);
3673 pkt_safi
= safi_int2iana(safi
);
3677 ndata
[0] = (pkt_afi
>> 8);
3679 ndata
[2] = pkt_safi
;
3680 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3681 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3682 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3683 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3685 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3686 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3687 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3691 /* Dynamic peers will just close their connection. */
3692 if (peer_dynamic_neighbor(peer
))
3695 /* restart timer start */
3696 if (peer
->pmax_restart
[afi
][safi
]) {
3697 peer
->v_pmax_restart
=
3698 peer
->pmax_restart
[afi
][safi
] * 60;
3700 if (bgp_debug_neighbor_events(peer
))
3702 "%pBP Maximum-prefix restart timer started for %d secs",
3703 peer
, peer
->v_pmax_restart
);
3705 BGP_TIMER_ON(peer
->t_pmax_restart
,
3706 bgp_maximum_prefix_restart_timer
,
3707 peer
->v_pmax_restart
);
3712 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3713 PEER_STATUS_PREFIX_LIMIT
);
3716 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3717 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3718 PEER_STATUS_PREFIX_THRESHOLD
)
3723 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3724 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3725 peer
->pmax
[afi
][safi
]);
3726 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3727 PEER_STATUS_PREFIX_THRESHOLD
);
3729 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3730 PEER_STATUS_PREFIX_THRESHOLD
);
3734 /* Unconditionally remove the route from the RIB, without taking
3735 * damping into consideration (eg, because the session went down)
3737 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3738 struct peer
*peer
, afi_t afi
, safi_t safi
)
3741 struct bgp
*bgp
= NULL
;
3742 bool delete_route
= false;
3744 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3747 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3748 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3750 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3753 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3754 delete_route
= true;
3755 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3756 delete_route
= true;
3758 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3759 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3760 bgp
= pi
->peer
->bgp
;
3761 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3766 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3767 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3770 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3771 struct peer
*peer
, afi_t afi
, safi_t safi
,
3772 struct prefix_rd
*prd
)
3774 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3776 /* apply dampening, if result is suppressed, we'll be retaining
3777 * the bgp_path_info in the RIB for historical reference.
3779 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3780 && peer
->sort
== BGP_PEER_EBGP
)
3781 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3782 == BGP_DAMP_SUPPRESSED
) {
3783 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3788 #ifdef ENABLE_BGP_VNC
3789 if (safi
== SAFI_MPLS_VPN
) {
3790 struct bgp_dest
*pdest
= NULL
;
3791 struct bgp_table
*table
= NULL
;
3793 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3794 (struct prefix
*)prd
);
3795 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3796 table
= bgp_dest_get_bgp_table_info(pdest
);
3798 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3799 peer
->bgp
, prd
, table
, p
, pi
);
3801 bgp_dest_unlock_node(pdest
);
3803 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3804 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3806 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3807 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3812 /* If this is an EVPN route, process for un-import. */
3813 if (safi
== SAFI_EVPN
)
3814 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3816 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3819 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3820 struct peer
*peer
, struct attr
*attr
,
3821 struct bgp_dest
*dest
)
3823 struct bgp_path_info
*new;
3825 /* Make new BGP info. */
3826 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3828 new->instance
= instance
;
3829 new->sub_type
= sub_type
;
3832 new->uptime
= monotime(NULL
);
3837 /* Check if received nexthop is valid or not. */
3838 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3839 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3840 struct bgp_dest
*dest
)
3843 bool is_bgp_static_route
=
3844 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
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
);
4271 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4273 * Suppress fib is enabled
4274 * BGP_OPT_NO_FIB is not enabled
4275 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4276 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4278 if (bgp_fibupd_safi(safi
) && BGP_SUPPRESS_FIB_ENABLED(bgp
)
4279 && (sub_type
== BGP_ROUTE_NORMAL
)
4280 && (!bgp_option_check(BGP_OPT_NO_FIB
))
4281 && (!CHECK_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALLED
)))
4282 SET_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALL_PENDING
);
4284 /* If neighbor soo is configured, tag all incoming routes with
4285 * this SoO tag and then filter out advertisements in
4286 * subgroup_announce_check() if it matches the configured SoO
4287 * on the other peer.
4289 if (peer
->soo
[afi
][safi
]) {
4290 struct ecommunity
*old_ecomm
=
4291 bgp_attr_get_ecommunity(&new_attr
);
4292 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
4293 struct ecommunity
*new_ecomm
;
4296 new_ecomm
= ecommunity_merge(ecommunity_dup(old_ecomm
),
4299 if (!old_ecomm
->refcnt
)
4300 ecommunity_free(&old_ecomm
);
4302 new_ecomm
= ecommunity_dup(ecomm_soo
);
4305 bgp_attr_set_ecommunity(&new_attr
, new_ecomm
);
4308 attr_new
= bgp_attr_intern(&new_attr
);
4310 /* If the update is implicit withdraw. */
4312 pi
->uptime
= monotime(NULL
);
4313 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
4315 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4317 /* Same attribute comes in. */
4318 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4320 && (!has_valid_label
4321 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
4322 num_labels
* sizeof(mpls_label_t
))
4324 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4325 BGP_CONFIG_DAMPENING
)
4326 && peer
->sort
== BGP_PEER_EBGP
4327 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4328 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4329 bgp_debug_rdpfxpath2str(
4330 afi
, safi
, prd
, p
, label
,
4331 num_labels
, addpath_id
? 1 : 0,
4332 addpath_id
, evpn
, pfx_buf
,
4334 zlog_debug("%pBP rcvd %s", peer
,
4338 if (bgp_damp_update(pi
, dest
, afi
, safi
)
4339 != BGP_DAMP_SUPPRESSED
) {
4340 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
4342 bgp_process(bgp
, dest
, afi
, safi
);
4344 } else /* Duplicate - odd */
4346 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4347 if (!peer
->rcvd_attr_printed
) {
4349 "%pBP rcvd UPDATE w/ attr: %s",
4351 peer
->rcvd_attr_str
);
4352 peer
->rcvd_attr_printed
= 1;
4355 bgp_debug_rdpfxpath2str(
4356 afi
, safi
, prd
, p
, label
,
4357 num_labels
, addpath_id
? 1 : 0,
4358 addpath_id
, evpn
, pfx_buf
,
4361 "%pBP rcvd %s...duplicate ignored",
4365 /* graceful restart STALE flag unset. */
4366 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4367 bgp_path_info_unset_flag(
4368 dest
, pi
, BGP_PATH_STALE
);
4369 bgp_dest_set_defer_flag(dest
, false);
4370 bgp_process(bgp
, dest
, afi
, safi
);
4374 bgp_dest_unlock_node(dest
);
4375 bgp_attr_unintern(&attr_new
);
4380 /* Withdraw/Announce before we fully processed the withdraw */
4381 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4382 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4383 bgp_debug_rdpfxpath2str(
4384 afi
, safi
, prd
, p
, label
, num_labels
,
4385 addpath_id
? 1 : 0, addpath_id
, evpn
,
4386 pfx_buf
, sizeof(pfx_buf
));
4388 "%pBP rcvd %s, flapped quicker than processing",
4392 bgp_path_info_restore(dest
, pi
);
4395 * If the BGP_PATH_REMOVED flag is set, then EVPN
4396 * routes would have been unimported already when a
4397 * prior BGP withdraw processing happened. Such routes
4398 * need to be imported again, so flag accordingly.
4400 force_evpn_import
= true;
4402 /* implicit withdraw, decrement aggregate and pcount
4403 * here. only if update is accepted, they'll increment
4406 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4409 /* Received Logging. */
4410 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4411 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
4412 num_labels
, addpath_id
? 1 : 0,
4413 addpath_id
, evpn
, pfx_buf
,
4415 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4418 /* graceful restart STALE flag unset. */
4419 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4420 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
4421 bgp_dest_set_defer_flag(dest
, false);
4424 /* The attribute is changed. */
4425 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
4427 /* Update bgp route dampening information. */
4428 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4429 && peer
->sort
== BGP_PEER_EBGP
) {
4430 /* This is implicit withdraw so we should update
4433 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
4434 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
4436 #ifdef ENABLE_BGP_VNC
4437 if (safi
== SAFI_MPLS_VPN
) {
4438 struct bgp_dest
*pdest
= NULL
;
4439 struct bgp_table
*table
= NULL
;
4441 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4442 (struct prefix
*)prd
);
4443 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4444 table
= bgp_dest_get_bgp_table_info(pdest
);
4446 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
4447 bgp
, prd
, table
, p
, pi
);
4449 bgp_dest_unlock_node(pdest
);
4451 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4452 && (safi
== SAFI_UNICAST
)) {
4453 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4455 * Implicit withdraw case.
4457 ++vnc_implicit_withdraw
;
4458 vnc_import_bgp_del_route(bgp
, p
, pi
);
4459 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
4464 /* Special handling for EVPN update of an existing route. If the
4465 * extended community attribute has changed, we need to
4467 * the route using its existing extended community. It will be
4468 * subsequently processed for import with the new extended
4471 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
4474 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
4476 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4479 cmp
= ecommunity_cmp(
4480 bgp_attr_get_ecommunity(pi
->attr
),
4481 bgp_attr_get_ecommunity(attr_new
));
4483 if (bgp_debug_update(peer
, p
, NULL
, 1))
4485 "Change in EXT-COMM, existing %s new %s",
4487 bgp_attr_get_ecommunity(
4490 bgp_attr_get_ecommunity(
4492 if (safi
== SAFI_EVPN
)
4493 bgp_evpn_unimport_route(
4494 bgp
, afi
, safi
, p
, pi
);
4495 else /* SAFI_MPLS_VPN */
4496 vpn_leak_to_vrf_withdraw(pi
);
4501 /* Update to new attribute. */
4502 bgp_attr_unintern(&pi
->attr
);
4503 pi
->attr
= attr_new
;
4505 /* Update MPLS label */
4506 if (has_valid_label
) {
4507 extra
= bgp_path_info_extra_get(pi
);
4508 if (extra
->label
!= label
) {
4509 memcpy(&extra
->label
, label
,
4510 num_labels
* sizeof(mpls_label_t
));
4511 extra
->num_labels
= num_labels
;
4513 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4514 bgp_set_valid_label(&extra
->label
[0]);
4517 /* Update SRv6 SID */
4518 if (attr
->srv6_l3vpn
) {
4519 extra
= bgp_path_info_extra_get(pi
);
4520 if (sid_diff(&extra
->sid
[0].sid
,
4521 &attr
->srv6_l3vpn
->sid
)) {
4522 sid_copy(&extra
->sid
[0].sid
,
4523 &attr
->srv6_l3vpn
->sid
);
4524 extra
->num_sids
= 1;
4526 extra
->sid
[0].loc_block_len
= 0;
4527 extra
->sid
[0].loc_node_len
= 0;
4528 extra
->sid
[0].func_len
= 0;
4529 extra
->sid
[0].arg_len
= 0;
4530 extra
->sid
[0].transposition_len
= 0;
4531 extra
->sid
[0].transposition_offset
= 0;
4533 if (attr
->srv6_l3vpn
->loc_block_len
!= 0) {
4534 extra
->sid
[0].loc_block_len
=
4535 attr
->srv6_l3vpn
->loc_block_len
;
4536 extra
->sid
[0].loc_node_len
=
4537 attr
->srv6_l3vpn
->loc_node_len
;
4538 extra
->sid
[0].func_len
=
4539 attr
->srv6_l3vpn
->func_len
;
4540 extra
->sid
[0].arg_len
=
4541 attr
->srv6_l3vpn
->arg_len
;
4542 extra
->sid
[0].transposition_len
=
4544 ->transposition_len
;
4545 extra
->sid
[0].transposition_offset
=
4547 ->transposition_offset
;
4550 } else if (attr
->srv6_vpn
) {
4551 extra
= bgp_path_info_extra_get(pi
);
4552 if (sid_diff(&extra
->sid
[0].sid
,
4553 &attr
->srv6_vpn
->sid
)) {
4554 sid_copy(&extra
->sid
[0].sid
,
4555 &attr
->srv6_vpn
->sid
);
4556 extra
->num_sids
= 1;
4560 #ifdef ENABLE_BGP_VNC
4561 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4562 && (safi
== SAFI_UNICAST
)) {
4563 if (vnc_implicit_withdraw
) {
4565 * Add back the route with its new attributes
4567 * The route is still selected, until the route
4569 * queued by bgp_process actually runs. We have
4571 * update to the VNC side immediately to avoid
4573 * configuration changes (e.g., route-map
4575 * trigger re-importation of the entire RIB.
4577 vnc_import_bgp_add_route(bgp
, p
, pi
);
4578 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4583 /* Update bgp route dampening information. */
4584 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4585 && peer
->sort
== BGP_PEER_EBGP
) {
4586 /* Now we do normal update dampening. */
4587 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4588 if (ret
== BGP_DAMP_SUPPRESSED
) {
4589 bgp_dest_unlock_node(dest
);
4594 /* Nexthop reachability check - for unicast and
4595 * labeled-unicast.. */
4596 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4597 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4598 || (safi
== SAFI_EVPN
&&
4599 bgp_evpn_is_prefix_nht_supported(p
))) {
4600 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4601 && peer
->ttl
== BGP_DEFAULT_TTL
4602 && !CHECK_FLAG(peer
->flags
,
4603 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4604 && !CHECK_FLAG(bgp
->flags
,
4605 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4610 struct bgp
*bgp_nexthop
= bgp
;
4612 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4613 bgp_nexthop
= pi
->extra
->bgp_orig
;
4615 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4617 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4618 safi
, pi
, NULL
, connected
,
4619 bgp_nht_param_prefix
) ||
4620 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4621 bgp_path_info_set_flag(dest
, pi
,
4624 if (BGP_DEBUG(nht
, NHT
)) {
4625 zlog_debug("%s(%pI4): NH unresolved",
4627 (in_addr_t
*)&attr_new
->nexthop
);
4629 bgp_path_info_unset_flag(dest
, pi
,
4634 bgp_path_info_set_flag(dest
, pi
,
4635 BGP_PATH_ACCEPT_OWN
);
4637 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4640 #ifdef ENABLE_BGP_VNC
4641 if (safi
== SAFI_MPLS_VPN
) {
4642 struct bgp_dest
*pdest
= NULL
;
4643 struct bgp_table
*table
= NULL
;
4645 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4646 (struct prefix
*)prd
);
4647 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4648 table
= bgp_dest_get_bgp_table_info(pdest
);
4650 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4651 bgp
, prd
, table
, p
, pi
);
4653 bgp_dest_unlock_node(pdest
);
4657 /* If this is an EVPN route and some attribute has changed,
4658 * or we are explicitly told to perform a route import, process
4659 * route for import. If the extended community has changed, we
4661 * have done the un-import earlier and the import would result
4663 * route getting injected into appropriate L2 VNIs. If it is
4665 * some other attribute change, the import will result in
4667 * the attributes for the route in the VNI(s).
4669 if (safi
== SAFI_EVPN
&&
4670 (!same_attr
|| force_evpn_import
) &&
4671 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4672 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4674 /* Process change. */
4675 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4677 bgp_process(bgp
, dest
, afi
, safi
);
4678 bgp_dest_unlock_node(dest
);
4680 if (SAFI_UNICAST
== safi
4681 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4682 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4684 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4686 if ((SAFI_MPLS_VPN
== safi
)
4687 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4688 leak_success
= vpn_leak_to_vrf_update(bgp
, pi
, prd
);
4691 #ifdef ENABLE_BGP_VNC
4692 if (SAFI_MPLS_VPN
== safi
) {
4693 mpls_label_t label_decoded
= decode_label(label
);
4695 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4696 type
, sub_type
, &label_decoded
);
4698 if (SAFI_ENCAP
== safi
) {
4699 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4700 type
, sub_type
, NULL
);
4703 if ((safi
== SAFI_MPLS_VPN
) &&
4704 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4705 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4707 bgp_unlink_nexthop(pi
);
4708 bgp_path_info_delete(dest
, pi
);
4711 } // End of implicit withdraw
4713 /* Received Logging. */
4714 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4715 if (!peer
->rcvd_attr_printed
) {
4716 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4717 peer
->rcvd_attr_str
);
4718 peer
->rcvd_attr_printed
= 1;
4721 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4722 addpath_id
? 1 : 0, addpath_id
, evpn
,
4723 pfx_buf
, sizeof(pfx_buf
));
4724 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4727 /* Make new BGP info. */
4728 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4730 /* Update MPLS label */
4731 if (has_valid_label
) {
4732 extra
= bgp_path_info_extra_get(new);
4733 if (extra
->label
!= label
) {
4734 memcpy(&extra
->label
, label
,
4735 num_labels
* sizeof(mpls_label_t
));
4736 extra
->num_labels
= num_labels
;
4738 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4739 bgp_set_valid_label(&extra
->label
[0]);
4742 /* Update SRv6 SID */
4743 if (safi
== SAFI_MPLS_VPN
) {
4744 extra
= bgp_path_info_extra_get(new);
4745 if (attr
->srv6_l3vpn
) {
4746 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_l3vpn
->sid
);
4747 extra
->num_sids
= 1;
4749 extra
->sid
[0].loc_block_len
=
4750 attr
->srv6_l3vpn
->loc_block_len
;
4751 extra
->sid
[0].loc_node_len
=
4752 attr
->srv6_l3vpn
->loc_node_len
;
4753 extra
->sid
[0].func_len
= attr
->srv6_l3vpn
->func_len
;
4754 extra
->sid
[0].arg_len
= attr
->srv6_l3vpn
->arg_len
;
4755 extra
->sid
[0].transposition_len
=
4756 attr
->srv6_l3vpn
->transposition_len
;
4757 extra
->sid
[0].transposition_offset
=
4758 attr
->srv6_l3vpn
->transposition_offset
;
4759 } else if (attr
->srv6_vpn
) {
4760 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_vpn
->sid
);
4761 extra
->num_sids
= 1;
4765 /* Nexthop reachability check. */
4766 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4767 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4768 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4769 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4770 && peer
->ttl
== BGP_DEFAULT_TTL
4771 && !CHECK_FLAG(peer
->flags
,
4772 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4773 && !CHECK_FLAG(bgp
->flags
,
4774 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4779 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4781 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4782 connected
, bgp_nht_param_prefix
) ||
4783 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4784 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4786 if (BGP_DEBUG(nht
, NHT
))
4787 zlog_debug("%s(%pI4): NH unresolved", __func__
,
4788 &attr_new
->nexthop
);
4789 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4793 bgp_path_info_set_flag(dest
, new, BGP_PATH_ACCEPT_OWN
);
4795 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4798 /* If maximum prefix count is configured and current prefix
4801 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0)) {
4802 reason
= "maximum-prefix overflow";
4803 bgp_attr_flush(&new_attr
);
4808 new->addpath_rx_id
= addpath_id
;
4810 /* Increment prefix */
4811 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4813 /* Register new BGP information. */
4814 bgp_path_info_add(dest
, new);
4816 /* route_node_get lock */
4817 bgp_dest_unlock_node(dest
);
4819 #ifdef ENABLE_BGP_VNC
4820 if (safi
== SAFI_MPLS_VPN
) {
4821 struct bgp_dest
*pdest
= NULL
;
4822 struct bgp_table
*table
= NULL
;
4824 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4825 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4826 table
= bgp_dest_get_bgp_table_info(pdest
);
4828 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4829 bgp
, prd
, table
, p
, new);
4831 bgp_dest_unlock_node(pdest
);
4835 /* If this is an EVPN route, process for import. */
4836 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4837 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4839 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4841 /* Process change. */
4842 bgp_process(bgp
, dest
, afi
, safi
);
4844 if (SAFI_UNICAST
== safi
4845 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4846 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4847 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4849 if ((SAFI_MPLS_VPN
== safi
)
4850 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4851 leak_success
= vpn_leak_to_vrf_update(bgp
, new, prd
);
4853 #ifdef ENABLE_BGP_VNC
4854 if (SAFI_MPLS_VPN
== safi
) {
4855 mpls_label_t label_decoded
= decode_label(label
);
4857 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4858 sub_type
, &label_decoded
);
4860 if (SAFI_ENCAP
== safi
) {
4861 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4865 if ((safi
== SAFI_MPLS_VPN
) &&
4866 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4867 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4869 bgp_unlink_nexthop(new);
4870 bgp_path_info_delete(dest
, new);
4875 /* This BGP update is filtered. Log the reason then update BGP
4879 bgp_unlink_nexthop(new);
4880 bgp_path_info_delete(dest
, new);
4881 bgp_path_info_extra_free(&new->extra
);
4882 XFREE(MTYPE_BGP_ROUTE
, new);
4885 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4887 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4888 if (!peer
->rcvd_attr_printed
) {
4889 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4890 peer
->rcvd_attr_str
);
4891 peer
->rcvd_attr_printed
= 1;
4894 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4895 addpath_id
? 1 : 0, addpath_id
, evpn
,
4896 pfx_buf
, sizeof(pfx_buf
));
4897 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4898 peer
, pfx_buf
, reason
);
4902 /* If this is an EVPN route, un-import it as it is now filtered.
4904 if (safi
== SAFI_EVPN
)
4905 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4907 if (SAFI_UNICAST
== safi
4908 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4909 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4911 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4913 if ((SAFI_MPLS_VPN
== safi
)
4914 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4916 vpn_leak_to_vrf_withdraw(pi
);
4919 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4922 bgp_dest_unlock_node(dest
);
4924 #ifdef ENABLE_BGP_VNC
4926 * Filtered update is treated as an implicit withdrawal (see
4928 * a few lines above)
4930 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4931 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4939 void bgp_withdraw(struct peer
*peer
, const struct prefix
*p
,
4940 uint32_t addpath_id
, afi_t afi
, safi_t safi
, int type
,
4941 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4942 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4945 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4946 struct bgp_dest
*dest
;
4947 struct bgp_path_info
*pi
;
4949 #ifdef ENABLE_BGP_VNC
4950 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4951 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4959 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4961 /* If peer is soft reconfiguration enabled. Record input packet for
4962 * further calculation.
4964 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4965 * routes that are filtered. This tanks out Quagga RS pretty badly due
4967 * the iteration over all RS clients.
4968 * Since we need to remove the entry from adj_in anyway, do that first
4970 * if there was no entry, we don't need to do anything more.
4972 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4973 && peer
!= bgp
->peer_self
)
4974 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4975 peer
->stat_pfx_dup_withdraw
++;
4977 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4978 bgp_debug_rdpfxpath2str(
4979 afi
, safi
, prd
, p
, label
, num_labels
,
4980 addpath_id
? 1 : 0, addpath_id
, NULL
,
4981 pfx_buf
, sizeof(pfx_buf
));
4983 "%s withdrawing route %s not in adj-in",
4984 peer
->host
, pfx_buf
);
4986 bgp_dest_unlock_node(dest
);
4990 /* Lookup withdrawn route. */
4991 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4992 if (pi
->peer
== peer
&& pi
->type
== type
4993 && pi
->sub_type
== sub_type
4994 && pi
->addpath_rx_id
== addpath_id
)
4998 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4999 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
5000 addpath_id
? 1 : 0, addpath_id
, NULL
,
5001 pfx_buf
, sizeof(pfx_buf
));
5002 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer
,
5006 /* Withdraw specified route from routing table. */
5007 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
5008 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
5009 if (SAFI_UNICAST
== safi
5010 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5011 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5012 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5014 if ((SAFI_MPLS_VPN
== safi
)
5015 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5017 vpn_leak_to_vrf_withdraw(pi
);
5019 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
5020 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
5021 addpath_id
? 1 : 0, addpath_id
, NULL
,
5022 pfx_buf
, sizeof(pfx_buf
));
5023 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
5026 /* Unlock bgp_node_get() lock. */
5027 bgp_dest_unlock_node(dest
);
5032 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
5035 struct update_subgroup
*subgrp
;
5036 subgrp
= peer_subgroup(peer
, afi
, safi
);
5037 subgroup_default_originate(subgrp
, withdraw
);
5042 * bgp_stop_announce_route_timer
5044 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
5046 if (!paf
->t_announce_route
)
5049 THREAD_OFF(paf
->t_announce_route
);
5053 * bgp_announce_route_timer_expired
5055 * Callback that is invoked when the route announcement timer for a
5058 static void bgp_announce_route_timer_expired(struct thread
*t
)
5060 struct peer_af
*paf
;
5063 paf
= THREAD_ARG(t
);
5066 if (!peer_established(peer
))
5069 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
5072 peer_af_announce_route(paf
, 1);
5074 /* Notify BGP conditional advertisement scanner percess */
5075 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
5079 * bgp_announce_route
5081 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
5083 * if force is true we will force an update even if the update
5084 * limiting code is attempted to kick in.
5086 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
, bool force
)
5088 struct peer_af
*paf
;
5089 struct update_subgroup
*subgrp
;
5091 paf
= peer_af_find(peer
, afi
, safi
);
5094 subgrp
= PAF_SUBGRP(paf
);
5097 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5098 * or a refresh has already been triggered.
5100 if (!subgrp
|| paf
->t_announce_route
)
5104 SET_FLAG(subgrp
->sflags
, SUBGRP_STATUS_FORCE_UPDATES
);
5107 * Start a timer to stagger/delay the announce. This serves
5108 * two purposes - announcement can potentially be combined for
5109 * multiple peers and the announcement doesn't happen in the
5112 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
5113 (subgrp
->peer_count
== 1)
5114 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5115 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
5116 &paf
->t_announce_route
);
5120 * Announce routes from all AF tables to a peer.
5122 * This should ONLY be called when there is a need to refresh the
5123 * routes to the peer based on a policy change for this peer alone
5124 * or a route refresh request received from the peer.
5125 * The operation will result in splitting the peer from its existing
5126 * subgroups and putting it in new subgroups.
5128 void bgp_announce_route_all(struct peer
*peer
)
5133 FOREACH_AFI_SAFI (afi
, safi
)
5134 bgp_announce_route(peer
, afi
, safi
, false);
5137 /* Flag or unflag bgp_dest to determine whether it should be treated by
5138 * bgp_soft_reconfig_table_task.
5139 * Flag if flag is true. Unflag if flag is false.
5141 static void bgp_soft_reconfig_table_flag(struct bgp_table
*table
, bool flag
)
5143 struct bgp_dest
*dest
;
5144 struct bgp_adj_in
*ain
;
5149 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5150 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5151 if (ain
->peer
!= NULL
)
5154 if (flag
&& ain
!= NULL
&& ain
->peer
!= NULL
)
5155 SET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5157 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5161 static void bgp_soft_reconfig_table_update(struct peer
*peer
,
5162 struct bgp_dest
*dest
,
5163 struct bgp_adj_in
*ain
, afi_t afi
,
5164 safi_t safi
, struct prefix_rd
*prd
)
5166 struct bgp_path_info
*pi
;
5167 uint32_t num_labels
= 0;
5168 mpls_label_t
*label_pnt
= NULL
;
5169 struct bgp_route_evpn evpn
;
5171 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5172 if (pi
->peer
== peer
)
5175 if (pi
&& pi
->extra
)
5176 num_labels
= pi
->extra
->num_labels
;
5178 label_pnt
= &pi
->extra
->label
[0];
5180 memcpy(&evpn
, bgp_attr_get_evpn_overlay(pi
->attr
),
5183 memset(&evpn
, 0, sizeof(evpn
));
5185 bgp_update(peer
, bgp_dest_get_prefix(dest
), ain
->addpath_rx_id
,
5186 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, prd
,
5187 label_pnt
, num_labels
, 1, &evpn
);
5190 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5191 struct bgp_table
*table
,
5192 struct prefix_rd
*prd
)
5194 struct bgp_dest
*dest
;
5195 struct bgp_adj_in
*ain
;
5198 table
= peer
->bgp
->rib
[afi
][safi
];
5200 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5201 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5202 if (ain
->peer
!= peer
)
5205 bgp_soft_reconfig_table_update(peer
, dest
, ain
, afi
,
5210 /* Do soft reconfig table per bgp table.
5211 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5212 * when BGP_NODE_SOFT_RECONFIG is set,
5213 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5214 * Schedule a new thread to continue the job.
5215 * Without splitting the full job into several part,
5216 * vtysh waits for the job to finish before responding to a BGP command
5218 static void bgp_soft_reconfig_table_task(struct thread
*thread
)
5220 uint32_t iter
, max_iter
;
5221 struct bgp_dest
*dest
;
5222 struct bgp_adj_in
*ain
;
5224 struct bgp_table
*table
;
5225 struct prefix_rd
*prd
;
5226 struct listnode
*node
, *nnode
;
5228 table
= THREAD_ARG(thread
);
5231 max_iter
= SOFT_RECONFIG_TASK_MAX_PREFIX
;
5232 if (table
->soft_reconfig_init
) {
5233 /* first call of the function with a new srta structure.
5234 * Don't do any treatment this time on nodes
5235 * in order vtysh to respond quickly
5240 for (iter
= 0, dest
= bgp_table_top(table
); (dest
&& iter
< max_iter
);
5241 dest
= bgp_route_next(dest
)) {
5242 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
))
5245 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5247 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5248 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
,
5250 if (ain
->peer
!= peer
)
5253 bgp_soft_reconfig_table_update(
5254 peer
, dest
, ain
, table
->afi
,
5261 /* we're either starting the initial iteration,
5262 * or we're going to continue an ongoing iteration
5264 if (dest
|| table
->soft_reconfig_init
) {
5265 table
->soft_reconfig_init
= false;
5266 thread_add_event(bm
->master
, bgp_soft_reconfig_table_task
,
5267 table
, 0, &table
->soft_reconfig_thread
);
5270 /* we're done, clean up the background iteration context info and
5271 schedule route annoucement
5273 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
, peer
)) {
5274 listnode_delete(table
->soft_reconfig_peers
, peer
);
5275 bgp_announce_route(peer
, table
->afi
, table
->safi
, false);
5278 list_delete(&table
->soft_reconfig_peers
);
5282 /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5284 * - bgp cannot be NULL
5285 * - if table and peer are NULL, cancel all threads within the bgp instance
5286 * - if table is NULL and peer is not,
5287 * remove peer in all threads within the bgp instance
5288 * - if peer is NULL, cancel all threads matching table within the bgp instance
5290 void bgp_soft_reconfig_table_task_cancel(const struct bgp
*bgp
,
5291 const struct bgp_table
*table
,
5292 const struct peer
*peer
)
5295 struct listnode
*node
, *nnode
;
5297 struct bgp_table
*ntable
;
5302 FOREACH_AFI_SAFI (afi
, safi
) {
5303 ntable
= bgp
->rib
[afi
][safi
];
5306 if (table
&& table
!= ntable
)
5309 for (ALL_LIST_ELEMENTS(ntable
->soft_reconfig_peers
, node
, nnode
,
5311 if (peer
&& peer
!= npeer
)
5313 listnode_delete(ntable
->soft_reconfig_peers
, npeer
);
5316 if (!ntable
->soft_reconfig_peers
5317 || !list_isempty(ntable
->soft_reconfig_peers
))
5320 list_delete(&ntable
->soft_reconfig_peers
);
5321 bgp_soft_reconfig_table_flag(ntable
, false);
5322 THREAD_OFF(ntable
->soft_reconfig_thread
);
5327 * Returns false if the peer is not configured for soft reconfig in
5329 bool bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5331 struct bgp_dest
*dest
;
5332 struct bgp_table
*table
;
5333 struct listnode
*node
, *nnode
;
5335 struct peer_af
*paf
;
5337 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
))
5340 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
5341 && (safi
!= SAFI_EVPN
)) {
5342 table
= peer
->bgp
->rib
[afi
][safi
];
5346 table
->soft_reconfig_init
= true;
5348 if (!table
->soft_reconfig_peers
)
5349 table
->soft_reconfig_peers
= list_new();
5351 /* add peer to the table soft_reconfig_peers if not already
5354 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
,
5360 listnode_add(table
->soft_reconfig_peers
, peer
);
5362 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5363 * on table would start back at the beginning.
5365 bgp_soft_reconfig_table_flag(table
, true);
5367 if (!table
->soft_reconfig_thread
)
5368 thread_add_event(bm
->master
,
5369 bgp_soft_reconfig_table_task
, table
, 0,
5370 &table
->soft_reconfig_thread
);
5371 /* Cancel bgp_announce_route_timer_expired threads.
5372 * bgp_announce_route_timer_expired threads have been scheduled
5373 * to announce routes as soon as the soft_reconfigure process
5375 * In this case, soft_reconfigure is also scheduled by using
5376 * a thread but is planned after the
5377 * bgp_announce_route_timer_expired threads. It means that,
5378 * without cancelling the threads, the route announcement task
5379 * would run before the soft reconfiguration one. That would
5380 * useless and would block vtysh during several seconds. Route
5381 * announcements are rescheduled as soon as the soft_reconfigure
5384 paf
= peer_af_find(peer
, afi
, safi
);
5386 bgp_stop_announce_route_timer(paf
);
5388 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5389 dest
= bgp_route_next(dest
)) {
5390 table
= bgp_dest_get_bgp_table_info(dest
);
5395 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5396 struct prefix_rd prd
;
5398 prd
.family
= AF_UNSPEC
;
5400 memcpy(&prd
.val
, p
->u
.val
, 8);
5402 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
5409 struct bgp_clear_node_queue
{
5410 struct bgp_dest
*dest
;
5413 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
5415 struct bgp_clear_node_queue
*cnq
= data
;
5416 struct bgp_dest
*dest
= cnq
->dest
;
5417 struct peer
*peer
= wq
->spec
.data
;
5418 struct bgp_path_info
*pi
;
5420 afi_t afi
= bgp_dest_table(dest
)->afi
;
5421 safi_t safi
= bgp_dest_table(dest
)->safi
;
5423 assert(dest
&& peer
);
5426 /* It is possible that we have multiple paths for a prefix from a peer
5427 * if that peer is using AddPath.
5429 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5430 if (pi
->peer
!= peer
)
5433 /* graceful restart STALE flag set. */
5434 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
5435 && peer
->nsf
[afi
][safi
])
5436 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5437 PEER_STATUS_ENHANCED_REFRESH
))
5438 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5439 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
5440 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
5442 /* If this is an EVPN route, process for
5444 if (safi
== SAFI_EVPN
)
5445 bgp_evpn_unimport_route(
5447 bgp_dest_get_prefix(dest
), pi
);
5448 /* Handle withdraw for VRF route-leaking and L3VPN */
5449 if (SAFI_UNICAST
== safi
5450 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
5451 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5452 vpn_leak_from_vrf_withdraw(bgp_get_default(),
5455 if (SAFI_MPLS_VPN
== safi
&&
5456 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5457 vpn_leak_to_vrf_withdraw(pi
);
5460 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5466 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
5468 struct bgp_clear_node_queue
*cnq
= data
;
5469 struct bgp_dest
*dest
= cnq
->dest
;
5470 struct bgp_table
*table
= bgp_dest_table(dest
);
5472 bgp_dest_unlock_node(dest
);
5473 bgp_table_unlock(table
);
5474 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
5477 static void bgp_clear_node_complete(struct work_queue
*wq
)
5479 struct peer
*peer
= wq
->spec
.data
;
5481 /* Tickle FSM to start moving again */
5482 BGP_EVENT_ADD(peer
, Clearing_Completed
);
5484 peer_unlock(peer
); /* bgp_clear_route */
5487 static void bgp_clear_node_queue_init(struct peer
*peer
)
5489 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5491 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
5492 #undef CLEAR_QUEUE_NAME_LEN
5494 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
5495 peer
->clear_node_queue
->spec
.hold
= 10;
5496 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
5497 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
5498 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
5499 peer
->clear_node_queue
->spec
.max_retries
= 0;
5501 /* we only 'lock' this peer reference when the queue is actually active
5503 peer
->clear_node_queue
->spec
.data
= peer
;
5506 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5507 struct bgp_table
*table
)
5509 struct bgp_dest
*dest
;
5510 int force
= peer
->bgp
->process_queue
? 0 : 1;
5513 table
= peer
->bgp
->rib
[afi
][safi
];
5515 /* If still no table => afi/safi isn't configured at all or smth. */
5519 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5520 struct bgp_path_info
*pi
, *next
;
5521 struct bgp_adj_in
*ain
;
5522 struct bgp_adj_in
*ain_next
;
5524 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5525 * queued for every clearing peer, regardless of whether it is
5526 * relevant to the peer at hand.
5528 * Overview: There are 3 different indices which need to be
5529 * scrubbed, potentially, when a peer is removed:
5531 * 1 peer's routes visible via the RIB (ie accepted routes)
5532 * 2 peer's routes visible by the (optional) peer's adj-in index
5533 * 3 other routes visible by the peer's adj-out index
5535 * 3 there is no hurry in scrubbing, once the struct peer is
5536 * removed from bgp->peer, we could just GC such deleted peer's
5537 * adj-outs at our leisure.
5539 * 1 and 2 must be 'scrubbed' in some way, at least made
5540 * invisible via RIB index before peer session is allowed to be
5541 * brought back up. So one needs to know when such a 'search' is
5546 * - there'd be a single global queue or a single RIB walker
5547 * - rather than tracking which route_nodes still need to be
5548 * examined on a peer basis, we'd track which peers still
5551 * Given that our per-peer prefix-counts now should be reliable,
5552 * this may actually be achievable. It doesn't seem to be a huge
5553 * problem at this time,
5555 * It is possible that we have multiple paths for a prefix from
5557 * if that peer is using AddPath.
5561 ain_next
= ain
->next
;
5563 if (ain
->peer
== peer
)
5564 bgp_adj_in_remove(dest
, ain
);
5569 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5571 if (pi
->peer
!= peer
)
5575 bgp_path_info_reap(dest
, pi
);
5577 struct bgp_clear_node_queue
*cnq
;
5579 /* both unlocked in bgp_clear_node_queue_del */
5580 bgp_table_lock(bgp_dest_table(dest
));
5581 bgp_dest_lock_node(dest
);
5583 MTYPE_BGP_CLEAR_NODE_QUEUE
,
5584 sizeof(struct bgp_clear_node_queue
));
5586 work_queue_add(peer
->clear_node_queue
, cnq
);
5594 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5596 struct bgp_dest
*dest
;
5597 struct bgp_table
*table
;
5599 if (peer
->clear_node_queue
== NULL
)
5600 bgp_clear_node_queue_init(peer
);
5602 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5603 * Idle until it receives a Clearing_Completed event. This protects
5604 * against peers which flap faster than we can we clear, which could
5607 * a) race with routes from the new session being installed before
5608 * clear_route_node visits the node (to delete the route of that
5610 * b) resource exhaustion, clear_route_node likely leads to an entry
5611 * on the process_main queue. Fast-flapping could cause that queue
5615 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5616 * the unlock will happen upon work-queue completion; other wise, the
5617 * unlock happens at the end of this function.
5619 if (!peer
->clear_node_queue
->thread
)
5622 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
5623 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
5625 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5626 dest
= bgp_route_next(dest
)) {
5627 table
= bgp_dest_get_bgp_table_info(dest
);
5631 bgp_clear_route_table(peer
, afi
, safi
, table
);
5634 /* unlock if no nodes got added to the clear-node-queue. */
5635 if (!peer
->clear_node_queue
->thread
)
5639 void bgp_clear_route_all(struct peer
*peer
)
5644 FOREACH_AFI_SAFI (afi
, safi
)
5645 bgp_clear_route(peer
, afi
, safi
);
5647 #ifdef ENABLE_BGP_VNC
5648 rfapiProcessPeerDown(peer
);
5652 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5654 struct bgp_table
*table
;
5655 struct bgp_dest
*dest
;
5656 struct bgp_adj_in
*ain
;
5657 struct bgp_adj_in
*ain_next
;
5659 table
= peer
->bgp
->rib
[afi
][safi
];
5661 /* It is possible that we have multiple paths for a prefix from a peer
5662 * if that peer is using AddPath.
5664 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5668 ain_next
= ain
->next
;
5670 if (ain
->peer
== peer
)
5671 bgp_adj_in_remove(dest
, ain
);
5678 /* If any of the routes from the peer have been marked with the NO_LLGR
5679 * community, either as sent by the peer, or as the result of a configured
5680 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5681 * operation of [RFC4271].
5683 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5685 struct bgp_dest
*dest
;
5686 struct bgp_path_info
*pi
;
5687 struct bgp_table
*table
;
5689 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5690 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5691 dest
= bgp_route_next(dest
)) {
5692 struct bgp_dest
*rm
;
5694 /* look for neighbor in tables */
5695 table
= bgp_dest_get_bgp_table_info(dest
);
5699 for (rm
= bgp_table_top(table
); rm
;
5700 rm
= bgp_route_next(rm
))
5701 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
5703 if (pi
->peer
!= peer
)
5706 peer
->af_sflags
[afi
][safi
],
5707 PEER_STATUS_LLGR_WAIT
) &&
5708 bgp_attr_get_community(pi
->attr
) &&
5710 bgp_attr_get_community(
5714 if (!CHECK_FLAG(pi
->flags
,
5719 * If this is VRF leaked route
5720 * process for withdraw.
5723 BGP_ROUTE_IMPORTED
&&
5724 peer
->bgp
->inst_type
==
5725 BGP_INSTANCE_TYPE_DEFAULT
)
5726 vpn_leak_to_vrf_withdraw(pi
);
5728 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
5733 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5734 dest
= bgp_route_next(dest
))
5735 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5737 if (pi
->peer
!= peer
)
5739 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5740 PEER_STATUS_LLGR_WAIT
) &&
5741 bgp_attr_get_community(pi
->attr
) &&
5743 bgp_attr_get_community(pi
->attr
),
5746 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
5748 if (safi
== SAFI_UNICAST
&&
5749 (peer
->bgp
->inst_type
==
5750 BGP_INSTANCE_TYPE_VRF
||
5751 peer
->bgp
->inst_type
==
5752 BGP_INSTANCE_TYPE_DEFAULT
))
5753 vpn_leak_from_vrf_withdraw(
5754 bgp_get_default(), peer
->bgp
,
5757 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5763 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5765 struct bgp_dest
*dest
, *ndest
;
5766 struct bgp_path_info
*pi
;
5767 struct bgp_table
*table
;
5769 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5770 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5771 dest
= bgp_route_next(dest
)) {
5772 table
= bgp_dest_get_bgp_table_info(dest
);
5776 for (ndest
= bgp_table_top(table
); ndest
;
5777 ndest
= bgp_route_next(ndest
)) {
5778 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5780 if (pi
->peer
!= peer
)
5784 peer
->af_sflags
[afi
][safi
],
5785 PEER_STATUS_ENHANCED_REFRESH
))
5786 && !CHECK_FLAG(pi
->flags
,
5790 BGP_PATH_UNUSEABLE
)) {
5791 if (bgp_debug_neighbor_events(
5794 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5798 bgp_dest_get_prefix(
5801 bgp_path_info_set_flag(
5809 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5810 dest
= bgp_route_next(dest
)) {
5811 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5813 if (pi
->peer
!= peer
)
5816 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5817 PEER_STATUS_ENHANCED_REFRESH
))
5818 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5819 && !CHECK_FLAG(pi
->flags
,
5820 BGP_PATH_UNUSEABLE
)) {
5821 if (bgp_debug_neighbor_events(peer
))
5823 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5826 bgp_dest_get_prefix(
5829 bgp_path_info_set_flag(dest
, pi
,
5837 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5839 if (peer
->sort
== BGP_PEER_IBGP
)
5842 if (peer
->sort
== BGP_PEER_EBGP
5843 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5844 || FILTER_LIST_OUT_NAME(filter
)
5845 || DISTRIBUTE_OUT_NAME(filter
)))
5850 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5852 if (peer
->sort
== BGP_PEER_IBGP
)
5855 if (peer
->sort
== BGP_PEER_EBGP
5856 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5857 || FILTER_LIST_IN_NAME(filter
)
5858 || DISTRIBUTE_IN_NAME(filter
)))
5863 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5866 struct bgp_dest
*dest
;
5867 struct bgp_path_info
*pi
;
5868 struct bgp_path_info
*next
;
5870 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5871 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5872 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5876 /* Unimport EVPN routes from VRFs */
5877 if (safi
== SAFI_EVPN
)
5878 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5881 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5882 && pi
->type
== ZEBRA_ROUTE_BGP
5883 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5884 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5885 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5887 if (bgp_fibupd_safi(safi
))
5888 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5891 bgp_path_info_reap(dest
, pi
);
5895 /* Delete all kernel routes. */
5896 void bgp_cleanup_routes(struct bgp
*bgp
)
5899 struct bgp_dest
*dest
;
5900 struct bgp_table
*table
;
5902 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5903 if (afi
== AFI_L2VPN
)
5905 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5908 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5910 if (afi
!= AFI_L2VPN
) {
5912 safi
= SAFI_MPLS_VPN
;
5913 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5914 dest
= bgp_route_next(dest
)) {
5915 table
= bgp_dest_get_bgp_table_info(dest
);
5916 if (table
!= NULL
) {
5917 bgp_cleanup_table(bgp
, table
, safi
);
5918 bgp_table_finish(&table
);
5919 bgp_dest_set_bgp_table_info(dest
, NULL
);
5920 bgp_dest_unlock_node(dest
);
5924 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); 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
);
5929 bgp_table_finish(&table
);
5930 bgp_dest_set_bgp_table_info(dest
, NULL
);
5931 bgp_dest_unlock_node(dest
);
5936 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5937 dest
= bgp_route_next(dest
)) {
5938 table
= bgp_dest_get_bgp_table_info(dest
);
5939 if (table
!= NULL
) {
5940 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5941 bgp_table_finish(&table
);
5942 bgp_dest_set_bgp_table_info(dest
, NULL
);
5943 bgp_dest_unlock_node(dest
);
5948 void bgp_reset(void)
5951 bgp_zclient_reset();
5952 access_list_reset();
5953 prefix_list_reset();
5956 bool bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5958 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5959 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5960 PEER_CAP_ADDPATH_AF_TX_RCV
));
5963 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5965 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5966 struct bgp_nlri
*packet
)
5974 bool addpath_capable
;
5975 uint32_t addpath_id
;
5978 lim
= pnt
+ packet
->length
;
5980 safi
= packet
->safi
;
5982 addpath_capable
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5984 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5985 syntactic validity. If the field is syntactically incorrect,
5986 then the Error Subcode is set to Invalid Network Field. */
5987 for (; pnt
< lim
; pnt
+= psize
) {
5988 /* Clear prefix structure. */
5989 memset(&p
, 0, sizeof(p
));
5991 if (addpath_capable
) {
5993 /* When packet overflow occurs return immediately. */
5994 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5995 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5997 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5998 addpath_id
= ntohl(addpath_id
);
5999 pnt
+= BGP_ADDPATH_ID_LEN
;
6002 /* Fetch prefix length. */
6003 p
.prefixlen
= *pnt
++;
6004 /* afi/safi validity already verified by caller,
6005 * bgp_update_receive */
6006 p
.family
= afi2family(afi
);
6008 /* Prefix length check. */
6009 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
6012 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
6013 peer
->host
, p
.prefixlen
, packet
->afi
);
6014 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
6017 /* Packet size overflow check. */
6018 psize
= PSIZE(p
.prefixlen
);
6020 /* When packet overflow occur return immediately. */
6021 if (pnt
+ psize
> lim
) {
6024 "%s [Error] Update packet error (prefix length %d overflows packet)",
6025 peer
->host
, p
.prefixlen
);
6026 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
6029 /* Defensive coding, double-check the psize fits in a struct
6030 * prefix for the v4 and v6 afi's and unicast/multicast */
6031 if (psize
> (ssize_t
)sizeof(p
.u
.val
)) {
6034 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
6035 peer
->host
, p
.prefixlen
, sizeof(p
.u
.val
));
6036 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6039 /* Fetch prefix from NLRI packet. */
6040 memcpy(p
.u
.val
, pnt
, psize
);
6042 /* Check address. */
6043 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
6044 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
6045 /* From RFC4271 Section 6.3:
6047 * If a prefix in the NLRI field is semantically
6049 * (e.g., an unexpected multicast IP address),
6051 * be logged locally, and the prefix SHOULD be
6056 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6057 peer
->host
, &p
.u
.prefix4
);
6062 /* Check address. */
6063 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
6064 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6067 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6068 peer
->host
, &p
.u
.prefix6
);
6072 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
6075 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6076 peer
->host
, &p
.u
.prefix6
);
6082 /* Normal process. */
6084 bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
6085 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
,
6088 bgp_withdraw(peer
, &p
, addpath_id
, afi
, safi
,
6089 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
,
6092 /* Do not send BGP notification twice when maximum-prefix count
6094 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
6095 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
6098 /* Packet length consistency check. */
6102 "%s [Error] Update packet error (prefix length mismatch with total length)",
6104 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6107 return BGP_NLRI_PARSE_OK
;
6110 static struct bgp_static
*bgp_static_new(void)
6112 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
6115 static void bgp_static_free(struct bgp_static
*bgp_static
)
6117 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6118 route_map_counter_decrement(bgp_static
->rmap
.map
);
6120 if (bgp_static
->prd_pretty
)
6121 XFREE(MTYPE_BGP
, bgp_static
->prd_pretty
);
6122 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
6123 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
6126 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
6127 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
6129 struct bgp_dest
*dest
;
6130 struct bgp_path_info
*pi
;
6131 struct bgp_path_info
*new;
6132 struct bgp_path_info rmap_path
;
6134 struct attr
*attr_new
;
6135 route_map_result_t ret
;
6136 #ifdef ENABLE_BGP_VNC
6137 int vnc_implicit_withdraw
= 0;
6142 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6144 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6146 attr
.nexthop
= bgp_static
->igpnexthop
;
6147 attr
.med
= bgp_static
->igpmetric
;
6148 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6151 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
6153 if (bgp_static
->igpmetric
)
6154 bgp_attr_set_aigp_metric(&attr
, bgp_static
->igpmetric
);
6156 if (bgp_static
->atomic
)
6157 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
6159 /* Store label index, if required. */
6160 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
6161 attr
.label_index
= bgp_static
->label_index
;
6162 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
6165 /* Apply route-map. */
6166 if (bgp_static
->rmap
.name
) {
6167 struct attr attr_tmp
= attr
;
6169 memset(&rmap_path
, 0, sizeof(rmap_path
));
6170 rmap_path
.peer
= bgp
->peer_self
;
6171 rmap_path
.attr
= &attr_tmp
;
6173 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6175 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6177 bgp
->peer_self
->rmap_type
= 0;
6179 if (ret
== RMAP_DENYMATCH
) {
6180 /* Free uninterned attribute. */
6181 bgp_attr_flush(&attr_tmp
);
6183 /* Unintern original. */
6184 aspath_unintern(&attr
.aspath
);
6185 bgp_static_withdraw(bgp
, p
, afi
, safi
);
6186 bgp_dest_unlock_node(dest
);
6190 if (bgp_in_graceful_shutdown(bgp
))
6191 bgp_attr_add_gshut_community(&attr_tmp
);
6193 attr_new
= bgp_attr_intern(&attr_tmp
);
6196 if (bgp_in_graceful_shutdown(bgp
))
6197 bgp_attr_add_gshut_community(&attr
);
6199 attr_new
= bgp_attr_intern(&attr
);
6202 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6203 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6204 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6208 if (attrhash_cmp(pi
->attr
, attr_new
)
6209 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
6210 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
6211 bgp_dest_unlock_node(dest
);
6212 bgp_attr_unintern(&attr_new
);
6213 aspath_unintern(&attr
.aspath
);
6216 /* The attribute is changed. */
6217 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6219 /* Rewrite BGP route information. */
6220 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6221 bgp_path_info_restore(dest
, pi
);
6223 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6224 #ifdef ENABLE_BGP_VNC
6225 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6226 && (safi
== SAFI_UNICAST
)) {
6227 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
6229 * Implicit withdraw case.
6230 * We have to do this before pi is
6233 ++vnc_implicit_withdraw
;
6234 vnc_import_bgp_del_route(bgp
, p
, pi
);
6235 vnc_import_bgp_exterior_del_route(
6240 bgp_attr_unintern(&pi
->attr
);
6241 pi
->attr
= attr_new
;
6242 pi
->uptime
= monotime(NULL
);
6243 #ifdef ENABLE_BGP_VNC
6244 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6245 && (safi
== SAFI_UNICAST
)) {
6246 if (vnc_implicit_withdraw
) {
6247 vnc_import_bgp_add_route(bgp
, p
, pi
);
6248 vnc_import_bgp_exterior_add_route(
6254 /* Nexthop reachability check. */
6255 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6256 && (safi
== SAFI_UNICAST
6257 || safi
== SAFI_LABELED_UNICAST
)) {
6259 struct bgp
*bgp_nexthop
= bgp
;
6261 if (pi
->extra
&& pi
->extra
->bgp_orig
)
6262 bgp_nexthop
= pi
->extra
->bgp_orig
;
6264 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
6265 afi
, safi
, pi
, NULL
,
6267 bgp_path_info_set_flag(dest
, pi
,
6270 if (BGP_DEBUG(nht
, NHT
)) {
6271 char buf1
[INET6_ADDRSTRLEN
];
6272 inet_ntop(p
->family
,
6276 "%s(%s): Route not in table, not advertising",
6279 bgp_path_info_unset_flag(
6280 dest
, pi
, BGP_PATH_VALID
);
6283 /* Delete the NHT structure if any, if we're
6285 * enabling/disabling import check. We
6286 * deregister the route
6287 * from NHT to avoid overloading NHT and the
6288 * process interaction
6290 bgp_unlink_nexthop(pi
);
6291 bgp_path_info_set_flag(dest
, pi
,
6294 /* Process change. */
6295 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6296 bgp_process(bgp
, dest
, afi
, safi
);
6298 if (SAFI_UNICAST
== safi
6299 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6301 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6302 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
6306 bgp_dest_unlock_node(dest
);
6307 aspath_unintern(&attr
.aspath
);
6312 /* Make new BGP info. */
6313 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6315 /* Nexthop reachability check. */
6316 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6317 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
6318 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0,
6320 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6322 if (BGP_DEBUG(nht
, NHT
)) {
6323 char buf1
[INET6_ADDRSTRLEN
];
6325 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
6328 "%s(%s): Route not in table, not advertising",
6331 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
6334 /* Delete the NHT structure if any, if we're toggling between
6335 * enabling/disabling import check. We deregister the route
6336 * from NHT to avoid overloading NHT and the process interaction
6338 bgp_unlink_nexthop(new);
6340 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6343 /* Aggregate address increment. */
6344 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6346 /* Register new BGP information. */
6347 bgp_path_info_add(dest
, new);
6349 /* route_node_get lock */
6350 bgp_dest_unlock_node(dest
);
6352 /* Process change. */
6353 bgp_process(bgp
, dest
, afi
, safi
);
6355 if (SAFI_UNICAST
== safi
6356 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6357 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6358 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6361 /* Unintern original. */
6362 aspath_unintern(&attr
.aspath
);
6365 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6368 struct bgp_dest
*dest
;
6369 struct bgp_path_info
*pi
;
6371 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6373 /* Check selected route and self inserted route. */
6374 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6375 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6376 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6379 /* Withdraw static BGP route from routing table. */
6381 if (SAFI_UNICAST
== safi
6382 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6383 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6384 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
6386 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6387 bgp_unlink_nexthop(pi
);
6388 bgp_path_info_delete(dest
, pi
);
6389 bgp_process(bgp
, dest
, afi
, safi
);
6392 /* Unlock bgp_node_lookup. */
6393 bgp_dest_unlock_node(dest
);
6397 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6399 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
6400 afi_t afi
, safi_t safi
,
6401 struct prefix_rd
*prd
)
6403 struct bgp_dest
*dest
;
6404 struct bgp_path_info
*pi
;
6406 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
6408 /* Check selected route and self inserted route. */
6409 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6410 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6411 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6414 /* Withdraw static BGP route from routing table. */
6416 #ifdef ENABLE_BGP_VNC
6417 rfapiProcessWithdraw(
6418 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
6419 1); /* Kill, since it is an administrative change */
6421 if (SAFI_MPLS_VPN
== safi
6422 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6423 vpn_leak_to_vrf_withdraw(pi
);
6425 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6426 bgp_path_info_delete(dest
, pi
);
6427 bgp_process(bgp
, dest
, afi
, safi
);
6430 /* Unlock bgp_node_lookup. */
6431 bgp_dest_unlock_node(dest
);
6434 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
6435 struct bgp_static
*bgp_static
, afi_t afi
,
6438 struct bgp_dest
*dest
;
6439 struct bgp_path_info
*new;
6440 struct attr
*attr_new
;
6441 struct attr attr
= {0};
6442 struct bgp_path_info
*pi
;
6443 #ifdef ENABLE_BGP_VNC
6444 mpls_label_t label
= 0;
6446 uint32_t num_labels
= 0;
6450 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
6452 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
6455 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6457 attr
.nexthop
= bgp_static
->igpnexthop
;
6458 attr
.med
= bgp_static
->igpmetric
;
6459 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6461 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
6462 || (safi
== SAFI_ENCAP
)) {
6463 if (afi
== AFI_IP
) {
6464 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
6465 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
6468 if (afi
== AFI_L2VPN
) {
6469 if (bgp_static
->gatewayIp
.family
== AF_INET
) {
6470 SET_IPADDR_V4(&attr
.evpn_overlay
.gw_ip
);
6471 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v4
,
6472 &bgp_static
->gatewayIp
.u
.prefix4
,
6474 } else if (bgp_static
->gatewayIp
.family
== AF_INET6
) {
6475 SET_IPADDR_V6(&attr
.evpn_overlay
.gw_ip
);
6476 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v6
,
6477 &bgp_static
->gatewayIp
.u
.prefix6
,
6480 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
6481 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
6482 struct bgp_encap_type_vxlan bet
;
6483 memset(&bet
, 0, sizeof(bet
));
6484 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
6485 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
6487 if (bgp_static
->router_mac
) {
6488 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
6491 /* Apply route-map. */
6492 if (bgp_static
->rmap
.name
) {
6493 struct attr attr_tmp
= attr
;
6494 struct bgp_path_info rmap_path
;
6495 route_map_result_t ret
;
6497 rmap_path
.peer
= bgp
->peer_self
;
6498 rmap_path
.attr
= &attr_tmp
;
6500 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6502 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6504 bgp
->peer_self
->rmap_type
= 0;
6506 if (ret
== RMAP_DENYMATCH
) {
6507 /* Free uninterned attribute. */
6508 bgp_attr_flush(&attr_tmp
);
6510 /* Unintern original. */
6511 aspath_unintern(&attr
.aspath
);
6512 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
6514 bgp_dest_unlock_node(dest
);
6518 attr_new
= bgp_attr_intern(&attr_tmp
);
6520 attr_new
= bgp_attr_intern(&attr
);
6523 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6524 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6525 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6529 if (attrhash_cmp(pi
->attr
, attr_new
)
6530 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
6531 bgp_dest_unlock_node(dest
);
6532 bgp_attr_unintern(&attr_new
);
6533 aspath_unintern(&attr
.aspath
);
6536 /* The attribute is changed. */
6537 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6539 /* Rewrite BGP route information. */
6540 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6541 bgp_path_info_restore(dest
, pi
);
6543 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6544 bgp_attr_unintern(&pi
->attr
);
6545 pi
->attr
= attr_new
;
6546 pi
->uptime
= monotime(NULL
);
6547 #ifdef ENABLE_BGP_VNC
6549 label
= decode_label(&pi
->extra
->label
[0]);
6552 /* Process change. */
6553 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6554 bgp_process(bgp
, dest
, afi
, safi
);
6556 if (SAFI_MPLS_VPN
== safi
6557 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6558 vpn_leak_to_vrf_update(bgp
, pi
,
6561 #ifdef ENABLE_BGP_VNC
6562 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
6563 pi
->attr
, afi
, safi
, pi
->type
,
6564 pi
->sub_type
, &label
);
6566 bgp_dest_unlock_node(dest
);
6567 aspath_unintern(&attr
.aspath
);
6573 /* Make new BGP info. */
6574 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6576 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6577 bgp_path_info_extra_get(new);
6579 new->extra
->label
[0] = bgp_static
->label
;
6580 new->extra
->num_labels
= num_labels
;
6582 #ifdef ENABLE_BGP_VNC
6583 label
= decode_label(&bgp_static
->label
);
6586 /* Aggregate address increment. */
6587 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6589 /* Register new BGP information. */
6590 bgp_path_info_add(dest
, new);
6591 /* route_node_get lock */
6592 bgp_dest_unlock_node(dest
);
6594 /* Process change. */
6595 bgp_process(bgp
, dest
, afi
, safi
);
6597 if (SAFI_MPLS_VPN
== safi
6598 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6599 vpn_leak_to_vrf_update(bgp
, new, &bgp_static
->prd
);
6601 #ifdef ENABLE_BGP_VNC
6602 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6603 safi
, new->type
, new->sub_type
, &label
);
6606 /* Unintern original. */
6607 aspath_unintern(&attr
.aspath
);
6610 /* Configure static BGP network. When user don't run zebra, static
6611 route should be installed as valid. */
6612 static int bgp_static_set(struct vty
*vty
, const char *negate
,
6613 const char *ip_str
, afi_t afi
, safi_t safi
,
6614 const char *rmap
, int backdoor
, uint32_t label_index
)
6616 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6619 struct bgp_static
*bgp_static
;
6620 struct bgp_dest
*dest
;
6621 uint8_t need_update
= 0;
6623 /* Convert IP prefix string to struct prefix. */
6624 ret
= str2prefix(ip_str
, &p
);
6626 vty_out(vty
, "%% Malformed prefix\n");
6627 return CMD_WARNING_CONFIG_FAILED
;
6629 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6630 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
6631 return CMD_WARNING_CONFIG_FAILED
;
6638 /* Set BGP static route configuration. */
6639 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6642 vty_out(vty
, "%% Can't find static route specified\n");
6643 return CMD_WARNING_CONFIG_FAILED
;
6646 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6648 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6649 && (label_index
!= bgp_static
->label_index
)) {
6651 "%% label-index doesn't match static route\n");
6652 bgp_dest_unlock_node(dest
);
6653 return CMD_WARNING_CONFIG_FAILED
;
6656 if ((rmap
&& bgp_static
->rmap
.name
)
6657 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6659 "%% route-map name doesn't match static route\n");
6660 bgp_dest_unlock_node(dest
);
6661 return CMD_WARNING_CONFIG_FAILED
;
6664 /* Update BGP RIB. */
6665 if (!bgp_static
->backdoor
)
6666 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6668 /* Clear configuration. */
6669 bgp_static_free(bgp_static
);
6670 bgp_dest_set_bgp_static_info(dest
, NULL
);
6671 bgp_dest_unlock_node(dest
);
6672 bgp_dest_unlock_node(dest
);
6675 /* Set BGP static route configuration. */
6676 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6677 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6679 /* Configuration change. */
6680 /* Label index cannot be changed. */
6681 if (bgp_static
->label_index
!= label_index
) {
6682 vty_out(vty
, "%% cannot change label-index\n");
6683 bgp_dest_unlock_node(dest
);
6684 return CMD_WARNING_CONFIG_FAILED
;
6687 /* Check previous routes are installed into BGP. */
6688 if (bgp_static
->valid
6689 && bgp_static
->backdoor
!= backdoor
)
6692 bgp_static
->backdoor
= backdoor
;
6695 XFREE(MTYPE_ROUTE_MAP_NAME
,
6696 bgp_static
->rmap
.name
);
6697 route_map_counter_decrement(
6698 bgp_static
->rmap
.map
);
6699 bgp_static
->rmap
.name
=
6700 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6701 bgp_static
->rmap
.map
=
6702 route_map_lookup_by_name(rmap
);
6703 route_map_counter_increment(
6704 bgp_static
->rmap
.map
);
6706 XFREE(MTYPE_ROUTE_MAP_NAME
,
6707 bgp_static
->rmap
.name
);
6708 route_map_counter_decrement(
6709 bgp_static
->rmap
.map
);
6710 bgp_static
->rmap
.map
= NULL
;
6711 bgp_static
->valid
= 0;
6713 bgp_dest_unlock_node(dest
);
6715 /* New configuration. */
6716 bgp_static
= bgp_static_new();
6717 bgp_static
->backdoor
= backdoor
;
6718 bgp_static
->valid
= 0;
6719 bgp_static
->igpmetric
= 0;
6720 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6721 bgp_static
->label_index
= label_index
;
6724 XFREE(MTYPE_ROUTE_MAP_NAME
,
6725 bgp_static
->rmap
.name
);
6726 route_map_counter_decrement(
6727 bgp_static
->rmap
.map
);
6728 bgp_static
->rmap
.name
=
6729 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6730 bgp_static
->rmap
.map
=
6731 route_map_lookup_by_name(rmap
);
6732 route_map_counter_increment(
6733 bgp_static
->rmap
.map
);
6735 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6738 bgp_static
->valid
= 1;
6740 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6742 if (!bgp_static
->backdoor
)
6743 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6749 void bgp_static_add(struct bgp
*bgp
)
6753 struct bgp_dest
*dest
;
6754 struct bgp_dest
*rm
;
6755 struct bgp_table
*table
;
6756 struct bgp_static
*bgp_static
;
6758 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6759 FOREACH_AFI_SAFI (afi
, safi
)
6760 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6761 dest
= bgp_route_next(dest
)) {
6762 if (!bgp_dest_has_bgp_path_info_data(dest
))
6765 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6766 || (safi
== SAFI_EVPN
)) {
6767 table
= bgp_dest_get_bgp_table_info(dest
);
6769 for (rm
= bgp_table_top(table
); rm
;
6770 rm
= bgp_route_next(rm
)) {
6772 bgp_dest_get_bgp_static_info(
6774 bgp_static_update_safi(
6775 bgp
, bgp_dest_get_prefix(rm
),
6776 bgp_static
, afi
, safi
);
6780 bgp
, bgp_dest_get_prefix(dest
),
6781 bgp_dest_get_bgp_static_info(dest
), afi
,
6785 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6788 /* Called from bgp_delete(). Delete all static routes from the BGP
6790 void bgp_static_delete(struct bgp
*bgp
)
6794 struct bgp_dest
*dest
;
6795 struct bgp_dest
*rm
;
6796 struct bgp_table
*table
;
6797 struct bgp_static
*bgp_static
;
6799 FOREACH_AFI_SAFI (afi
, safi
)
6800 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6801 dest
= bgp_route_next(dest
)) {
6802 if (!bgp_dest_has_bgp_path_info_data(dest
))
6805 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6806 || (safi
== SAFI_EVPN
)) {
6807 table
= bgp_dest_get_bgp_table_info(dest
);
6809 for (rm
= bgp_table_top(table
); rm
;
6810 rm
= bgp_route_next(rm
)) {
6812 bgp_dest_get_bgp_static_info(
6817 bgp_static_withdraw_safi(
6818 bgp
, bgp_dest_get_prefix(rm
),
6820 (struct prefix_rd
*)
6821 bgp_dest_get_prefix(
6823 bgp_static_free(bgp_static
);
6824 bgp_dest_set_bgp_static_info(rm
,
6826 bgp_dest_unlock_node(rm
);
6829 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6830 bgp_static_withdraw(bgp
,
6831 bgp_dest_get_prefix(dest
),
6833 bgp_static_free(bgp_static
);
6834 bgp_dest_set_bgp_static_info(dest
, NULL
);
6835 bgp_dest_unlock_node(dest
);
6840 void bgp_static_redo_import_check(struct bgp
*bgp
)
6844 struct bgp_dest
*dest
;
6845 struct bgp_dest
*rm
;
6846 struct bgp_table
*table
;
6847 struct bgp_static
*bgp_static
;
6849 /* Use this flag to force reprocessing of the route */
6850 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6851 FOREACH_AFI_SAFI (afi
, safi
) {
6852 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6853 dest
= bgp_route_next(dest
)) {
6854 if (!bgp_dest_has_bgp_path_info_data(dest
))
6857 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6858 || (safi
== SAFI_EVPN
)) {
6859 table
= bgp_dest_get_bgp_table_info(dest
);
6861 for (rm
= bgp_table_top(table
); rm
;
6862 rm
= bgp_route_next(rm
)) {
6864 bgp_dest_get_bgp_static_info(
6866 bgp_static_update_safi(
6867 bgp
, bgp_dest_get_prefix(rm
),
6868 bgp_static
, afi
, safi
);
6871 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6872 bgp_static_update(bgp
,
6873 bgp_dest_get_prefix(dest
),
6874 bgp_static
, afi
, safi
);
6878 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6881 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6884 struct bgp_table
*table
;
6885 struct bgp_dest
*dest
;
6886 struct bgp_path_info
*pi
;
6888 /* Do not install the aggregate route if BGP is in the
6889 * process of termination.
6891 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6892 || (bgp
->peer_self
== NULL
))
6895 table
= bgp
->rib
[afi
][safi
];
6896 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6897 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6898 if (pi
->peer
== bgp
->peer_self
6899 && ((pi
->type
== ZEBRA_ROUTE_BGP
6900 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6901 || (pi
->type
!= ZEBRA_ROUTE_BGP
6903 == BGP_ROUTE_REDISTRIBUTE
))) {
6904 bgp_aggregate_decrement(
6905 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6907 bgp_unlink_nexthop(pi
);
6908 bgp_path_info_delete(dest
, pi
);
6909 bgp_process(bgp
, dest
, afi
, safi
);
6916 * Purge all networks and redistributed routes from routing table.
6917 * Invoked upon the instance going down.
6919 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6924 FOREACH_AFI_SAFI (afi
, safi
)
6925 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6930 * Currently this is used to set static routes for VPN and ENCAP.
6931 * I think it can probably be factored with bgp_static_set.
6933 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6934 const char *ip_str
, const char *rd_str
,
6935 const char *label_str
, const char *rmap_str
,
6936 int evpn_type
, const char *esi
, const char *gwip
,
6937 const char *ethtag
, const char *routermac
)
6939 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6942 struct prefix_rd prd
;
6943 struct bgp_dest
*pdest
;
6944 struct bgp_dest
*dest
;
6945 struct bgp_table
*table
;
6946 struct bgp_static
*bgp_static
;
6947 mpls_label_t label
= MPLS_INVALID_LABEL
;
6948 struct prefix gw_ip
;
6950 /* validate ip prefix */
6951 ret
= str2prefix(ip_str
, &p
);
6953 vty_out(vty
, "%% Malformed prefix\n");
6954 return CMD_WARNING_CONFIG_FAILED
;
6957 if ((afi
== AFI_L2VPN
)
6958 && (bgp_build_evpn_prefix(evpn_type
,
6959 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6960 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6961 return CMD_WARNING_CONFIG_FAILED
;
6964 ret
= str2prefix_rd(rd_str
, &prd
);
6966 vty_out(vty
, "%% Malformed rd\n");
6967 return CMD_WARNING_CONFIG_FAILED
;
6971 unsigned long label_val
;
6972 label_val
= strtoul(label_str
, NULL
, 10);
6973 encode_label(label_val
, &label
);
6976 if (safi
== SAFI_EVPN
) {
6977 if (esi
&& str2esi(esi
, NULL
) == 0) {
6978 vty_out(vty
, "%% Malformed ESI\n");
6979 return CMD_WARNING_CONFIG_FAILED
;
6981 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6982 vty_out(vty
, "%% Malformed Router MAC\n");
6983 return CMD_WARNING_CONFIG_FAILED
;
6986 memset(&gw_ip
, 0, sizeof(gw_ip
));
6987 ret
= str2prefix(gwip
, &gw_ip
);
6989 vty_out(vty
, "%% Malformed GatewayIp\n");
6990 return CMD_WARNING_CONFIG_FAILED
;
6992 if ((gw_ip
.family
== AF_INET
6993 && is_evpn_prefix_ipaddr_v6(
6994 (struct prefix_evpn
*)&p
))
6995 || (gw_ip
.family
== AF_INET6
6996 && is_evpn_prefix_ipaddr_v4(
6997 (struct prefix_evpn
*)&p
))) {
6999 "%% GatewayIp family differs with IP prefix\n");
7000 return CMD_WARNING_CONFIG_FAILED
;
7004 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7005 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7006 bgp_dest_set_bgp_table_info(pdest
,
7007 bgp_table_init(bgp
, afi
, safi
));
7008 table
= bgp_dest_get_bgp_table_info(pdest
);
7010 dest
= bgp_node_get(table
, &p
);
7012 if (bgp_dest_has_bgp_path_info_data(dest
)) {
7013 vty_out(vty
, "%% Same network configuration exists\n");
7014 bgp_dest_unlock_node(dest
);
7016 /* New configuration. */
7017 bgp_static
= bgp_static_new();
7018 bgp_static
->backdoor
= 0;
7019 bgp_static
->valid
= 0;
7020 bgp_static
->igpmetric
= 0;
7021 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
7022 bgp_static
->label
= label
;
7023 bgp_static
->prd
= prd
;
7026 bgp_static
->prd_pretty
= XSTRDUP(MTYPE_BGP
, rd_str
);
7028 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
7029 route_map_counter_decrement(bgp_static
->rmap
.map
);
7030 bgp_static
->rmap
.name
=
7031 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
7032 bgp_static
->rmap
.map
=
7033 route_map_lookup_by_name(rmap_str
);
7034 route_map_counter_increment(bgp_static
->rmap
.map
);
7037 if (safi
== SAFI_EVPN
) {
7039 bgp_static
->eth_s_id
=
7042 str2esi(esi
, bgp_static
->eth_s_id
);
7045 bgp_static
->router_mac
=
7046 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
7047 (void)prefix_str2mac(routermac
,
7048 bgp_static
->router_mac
);
7051 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
7053 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
7055 bgp_static
->valid
= 1;
7056 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
7062 /* Configure static BGP network. */
7063 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
7064 const char *ip_str
, const char *rd_str
,
7065 const char *label_str
, int evpn_type
, const char *esi
,
7066 const char *gwip
, const char *ethtag
)
7068 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7071 struct prefix_rd prd
;
7072 struct bgp_dest
*pdest
;
7073 struct bgp_dest
*dest
;
7074 struct bgp_table
*table
;
7075 struct bgp_static
*bgp_static
;
7076 mpls_label_t label
= MPLS_INVALID_LABEL
;
7078 /* Convert IP prefix string to struct prefix. */
7079 ret
= str2prefix(ip_str
, &p
);
7081 vty_out(vty
, "%% Malformed prefix\n");
7082 return CMD_WARNING_CONFIG_FAILED
;
7085 if ((afi
== AFI_L2VPN
)
7086 && (bgp_build_evpn_prefix(evpn_type
,
7087 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
7088 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
7089 return CMD_WARNING_CONFIG_FAILED
;
7091 ret
= str2prefix_rd(rd_str
, &prd
);
7093 vty_out(vty
, "%% Malformed rd\n");
7094 return CMD_WARNING_CONFIG_FAILED
;
7098 unsigned long label_val
;
7099 label_val
= strtoul(label_str
, NULL
, 10);
7100 encode_label(label_val
, &label
);
7103 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7104 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7105 bgp_dest_set_bgp_table_info(pdest
,
7106 bgp_table_init(bgp
, afi
, safi
));
7108 bgp_dest_unlock_node(pdest
);
7109 table
= bgp_dest_get_bgp_table_info(pdest
);
7111 dest
= bgp_node_lookup(table
, &p
);
7114 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
7116 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
7117 bgp_static_free(bgp_static
);
7118 bgp_dest_set_bgp_static_info(dest
, NULL
);
7119 bgp_dest_unlock_node(dest
);
7120 bgp_dest_unlock_node(dest
);
7122 vty_out(vty
, "%% Can't find the route\n");
7127 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
7128 const char *rmap_name
)
7130 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7131 struct bgp_rmap
*rmap
;
7133 rmap
= &bgp
->table_map
[afi
][safi
];
7135 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7136 route_map_counter_decrement(rmap
->map
);
7137 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
7138 rmap
->map
= route_map_lookup_by_name(rmap_name
);
7139 route_map_counter_increment(rmap
->map
);
7141 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7142 route_map_counter_decrement(rmap
->map
);
7146 if (bgp_fibupd_safi(safi
))
7147 bgp_zebra_announce_table(bgp
, afi
, safi
);
7152 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
7153 const char *rmap_name
)
7155 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7156 struct bgp_rmap
*rmap
;
7158 rmap
= &bgp
->table_map
[afi
][safi
];
7159 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7160 route_map_counter_decrement(rmap
->map
);
7163 if (bgp_fibupd_safi(safi
))
7164 bgp_zebra_announce_table(bgp
, afi
, safi
);
7169 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
7172 if (bgp
->table_map
[afi
][safi
].name
) {
7173 vty_out(vty
, " table-map %s\n",
7174 bgp
->table_map
[afi
][safi
].name
);
7178 DEFUN (bgp_table_map
,
7181 "BGP table to RIB route download filter\n"
7182 "Name of the route map\n")
7185 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7186 argv
[idx_word
]->arg
);
7188 DEFUN (no_bgp_table_map
,
7189 no_bgp_table_map_cmd
,
7190 "no table-map WORD",
7192 "BGP table to RIB route download filter\n"
7193 "Name of the route map\n")
7196 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7197 argv
[idx_word
]->arg
);
7203 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
7204 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
7205 backdoor$backdoor}]",
7207 "Specify a network to announce via BGP\n"
7212 "Route-map to modify the attributes\n"
7213 "Name of the route map\n"
7214 "Label index to associate with the prefix\n"
7215 "Label index value\n"
7216 "Specify a BGP backdoor route\n")
7218 char addr_prefix_str
[BUFSIZ
];
7223 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
7225 sizeof(addr_prefix_str
));
7227 vty_out(vty
, "%% Inconsistent address and mask\n");
7228 return CMD_WARNING_CONFIG_FAILED
;
7232 return bgp_static_set(
7233 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
7234 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
7235 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7238 DEFPY(ipv6_bgp_network
,
7239 ipv6_bgp_network_cmd
,
7240 "[no] network X:X::X:X/M$prefix \
7241 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
7243 "Specify a network to announce via BGP\n"
7245 "Route-map to modify the attributes\n"
7246 "Name of the route map\n"
7247 "Label index to associate with the prefix\n"
7248 "Label index value\n")
7250 return bgp_static_set(
7251 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
7252 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7255 static struct bgp_aggregate
*bgp_aggregate_new(void)
7257 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
7260 void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
7262 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7263 route_map_counter_decrement(aggregate
->suppress_map
);
7264 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7265 route_map_counter_decrement(aggregate
->rmap
.map
);
7266 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
7270 * Helper function to avoid repeated code: prepare variables for a
7271 * `route_map_apply` call.
7273 * \returns `true` on route map match, otherwise `false`.
7275 static bool aggr_suppress_map_test(struct bgp
*bgp
,
7276 struct bgp_aggregate
*aggregate
,
7277 struct bgp_path_info
*pi
)
7279 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
7280 route_map_result_t rmr
= RMAP_DENYMATCH
;
7281 struct bgp_path_info rmap_path
= {};
7282 struct attr attr
= {};
7284 /* No route map entries created, just don't match. */
7285 if (aggregate
->suppress_map
== NULL
)
7288 /* Call route map matching and return result. */
7289 attr
.aspath
= aspath_empty(bgp
->asnotation
);
7290 rmap_path
.peer
= bgp
->peer_self
;
7291 rmap_path
.attr
= &attr
;
7293 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
7294 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
7295 bgp
->peer_self
->rmap_type
= 0;
7297 bgp_attr_flush(&attr
);
7298 aspath_unintern(&attr
.aspath
);
7300 return rmr
== RMAP_PERMITMATCH
;
7303 /** Test whether the aggregation has suppressed this path or not. */
7304 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
7305 struct bgp_path_info
*pi
)
7307 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
7310 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
7314 * Suppress this path and keep the reference.
7316 * \returns `true` if needs processing otherwise `false`.
7318 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
7319 struct bgp_path_info
*pi
)
7321 struct bgp_path_info_extra
*pie
;
7323 /* Path is already suppressed by this aggregation. */
7324 if (aggr_suppress_exists(aggregate
, pi
))
7327 pie
= bgp_path_info_extra_get(pi
);
7329 /* This is the first suppression, allocate memory and list it. */
7330 if (pie
->aggr_suppressors
== NULL
)
7331 pie
->aggr_suppressors
= list_new();
7333 listnode_add(pie
->aggr_suppressors
, aggregate
);
7335 /* Only mark for processing if suppressed. */
7336 if (listcount(pie
->aggr_suppressors
) == 1) {
7337 if (BGP_DEBUG(update
, UPDATE_OUT
))
7338 zlog_debug("aggregate-address suppressing: %pFX",
7339 bgp_dest_get_prefix(pi
->net
));
7341 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7349 * Unsuppress this path and remove the reference.
7351 * \returns `true` if needs processing otherwise `false`.
7353 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
7354 struct bgp_path_info
*pi
)
7356 /* Path wasn't suppressed. */
7357 if (!aggr_suppress_exists(aggregate
, pi
))
7360 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
7362 /* Unsuppress and free extra memory if last item. */
7363 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
7364 if (BGP_DEBUG(update
, UPDATE_OUT
))
7365 zlog_debug("aggregate-address unsuppressing: %pFX",
7366 bgp_dest_get_prefix(pi
->net
));
7368 list_delete(&pi
->extra
->aggr_suppressors
);
7369 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7376 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
7377 struct aspath
*aspath
,
7378 struct community
*comm
,
7379 struct ecommunity
*ecomm
,
7380 struct lcommunity
*lcomm
)
7382 static struct aspath
*ae
= NULL
;
7383 enum asnotation_mode asnotation
;
7385 asnotation
= bgp_get_asnotation(NULL
);
7388 ae
= aspath_empty(asnotation
);
7393 if (origin
!= pi
->attr
->origin
)
7396 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
7399 if (!community_cmp(bgp_attr_get_community(pi
->attr
), comm
))
7402 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi
->attr
), ecomm
))
7405 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi
->attr
), lcomm
))
7408 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
7414 static void bgp_aggregate_install(
7415 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
7416 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
7417 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
7418 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
7420 struct bgp_dest
*dest
;
7421 struct bgp_table
*table
;
7422 struct bgp_path_info
*pi
, *orig
, *new;
7425 table
= bgp
->rib
[afi
][safi
];
7427 dest
= bgp_node_get(table
, p
);
7429 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7430 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
7431 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7435 * If we have paths with different MEDs, then don't install
7436 * (or uninstall) the aggregate route.
7438 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
7439 goto uninstall_aggregate_route
;
7441 if (aggregate
->count
> 0) {
7443 * If the aggregate information has not changed
7444 * no need to re-install it again.
7446 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
7447 ecommunity
, lcommunity
)) {
7448 bgp_dest_unlock_node(dest
);
7451 aspath_free(aspath
);
7453 community_free(&community
);
7455 ecommunity_free(&ecommunity
);
7457 lcommunity_free(&lcommunity
);
7463 * Mark the old as unusable
7466 bgp_path_info_delete(dest
, pi
);
7468 attr
= bgp_attr_aggregate_intern(
7469 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
7470 aggregate
, atomic_aggregate
, p
);
7473 aspath_free(aspath
);
7474 community_free(&community
);
7475 ecommunity_free(&ecommunity
);
7476 lcommunity_free(&lcommunity
);
7477 bgp_dest_unlock_node(dest
);
7478 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
7479 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
7480 zlog_debug("%s: %pFX null attribute", __func__
,
7485 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
7486 bgp
->peer_self
, attr
, dest
);
7488 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7490 bgp_path_info_add(dest
, new);
7491 bgp_process(bgp
, dest
, afi
, safi
);
7493 uninstall_aggregate_route
:
7494 for (pi
= orig
; pi
; pi
= pi
->next
)
7495 if (pi
->peer
== bgp
->peer_self
7496 && pi
->type
== ZEBRA_ROUTE_BGP
7497 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7500 /* Withdraw static BGP route from routing table. */
7502 bgp_path_info_delete(dest
, pi
);
7503 bgp_process(bgp
, dest
, afi
, safi
);
7507 bgp_dest_unlock_node(dest
);
7511 * Check if the current path has different MED than other known paths.
7513 * \returns `true` if the MED matched the others else `false`.
7515 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
7516 struct bgp
*bgp
, struct bgp_path_info
*pi
)
7518 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
7520 /* This is the first route being analyzed. */
7521 if (!aggregate
->med_initialized
) {
7522 aggregate
->med_initialized
= true;
7523 aggregate
->med_mismatched
= false;
7524 aggregate
->med_matched_value
= cur_med
;
7526 /* Check if routes with different MED showed up. */
7527 if (cur_med
!= aggregate
->med_matched_value
)
7528 aggregate
->med_mismatched
= true;
7531 return !aggregate
->med_mismatched
;
7535 * Initializes and tests all routes in the aggregate address path for MED
7538 * \returns `true` if all MEDs are the same otherwise `false`.
7540 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
7541 struct bgp
*bgp
, const struct prefix
*p
,
7542 afi_t afi
, safi_t safi
)
7544 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7545 const struct prefix
*dest_p
;
7546 struct bgp_dest
*dest
, *top
;
7547 struct bgp_path_info
*pi
;
7548 bool med_matched
= true;
7550 aggregate
->med_initialized
= false;
7552 top
= bgp_node_get(table
, p
);
7553 for (dest
= bgp_node_get(table
, p
); dest
;
7554 dest
= bgp_route_next_until(dest
, top
)) {
7555 dest_p
= bgp_dest_get_prefix(dest
);
7556 if (dest_p
->prefixlen
<= p
->prefixlen
)
7559 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7560 if (BGP_PATH_HOLDDOWN(pi
))
7562 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7564 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
7565 med_matched
= false;
7572 bgp_dest_unlock_node(top
);
7578 * Toggles the route suppression status for this aggregate address
7581 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
7582 struct bgp
*bgp
, const struct prefix
*p
,
7583 afi_t afi
, safi_t safi
, bool suppress
)
7585 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7586 const struct prefix
*dest_p
;
7587 struct bgp_dest
*dest
, *top
;
7588 struct bgp_path_info
*pi
;
7589 bool toggle_suppression
;
7591 /* We've found a different MED we must revert any suppressed routes. */
7592 top
= bgp_node_get(table
, p
);
7593 for (dest
= bgp_node_get(table
, p
); dest
;
7594 dest
= bgp_route_next_until(dest
, top
)) {
7595 dest_p
= bgp_dest_get_prefix(dest
);
7596 if (dest_p
->prefixlen
<= p
->prefixlen
)
7599 toggle_suppression
= false;
7600 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7601 if (BGP_PATH_HOLDDOWN(pi
))
7603 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7606 /* We are toggling suppression back. */
7608 /* Suppress route if not suppressed already. */
7609 if (aggr_suppress_path(aggregate
, pi
))
7610 toggle_suppression
= true;
7614 /* Install route if there is no more suppression. */
7615 if (aggr_unsuppress_path(aggregate
, pi
))
7616 toggle_suppression
= true;
7619 if (toggle_suppression
)
7620 bgp_process(bgp
, dest
, afi
, safi
);
7622 bgp_dest_unlock_node(top
);
7626 * Aggregate address MED matching incremental test: this function is called
7627 * when the initial aggregation occurred and we are only testing a single
7630 * In addition to testing and setting the MED validity it also installs back
7631 * suppressed routes (if summary is configured).
7633 * Must not be called in `bgp_aggregate_route`.
7635 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7636 struct bgp
*bgp
, const struct prefix
*p
,
7637 afi_t afi
, safi_t safi
,
7638 struct bgp_path_info
*pi
)
7640 /* MED matching disabled. */
7641 if (!aggregate
->match_med
)
7644 /* Aggregation with different MED, recheck if we have got equal MEDs
7647 if (aggregate
->med_mismatched
&&
7648 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
) &&
7649 aggregate
->summary_only
)
7650 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
,
7653 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7655 /* No mismatches, just quit. */
7656 if (!aggregate
->med_mismatched
)
7659 /* Route summarization is disabled. */
7660 if (!aggregate
->summary_only
)
7663 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7666 /* Update an aggregate as routes are added/removed from the BGP table */
7667 bool bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7668 safi_t safi
, struct bgp_aggregate
*aggregate
)
7670 struct bgp_table
*table
;
7671 struct bgp_dest
*top
;
7672 struct bgp_dest
*dest
;
7674 struct aspath
*aspath
= NULL
;
7675 struct community
*community
= NULL
;
7676 struct ecommunity
*ecommunity
= NULL
;
7677 struct lcommunity
*lcommunity
= NULL
;
7678 struct bgp_path_info
*pi
;
7679 unsigned long match
= 0;
7680 uint8_t atomic_aggregate
= 0;
7682 /* If the bgp instance is being deleted or self peer is deleted
7683 * then do not create aggregate route
7685 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
7686 bgp
->peer_self
== NULL
)
7689 /* Initialize and test routes for MED difference. */
7690 if (aggregate
->match_med
)
7691 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7694 * Reset aggregate count: we might've been called from route map
7695 * update so in that case we must retest all more specific routes.
7697 * \see `bgp_route_map_process_update`.
7699 aggregate
->count
= 0;
7700 aggregate
->incomplete_origin_count
= 0;
7701 aggregate
->incomplete_origin_count
= 0;
7702 aggregate
->egp_origin_count
= 0;
7704 /* ORIGIN attribute: If at least one route among routes that are
7705 aggregated has ORIGIN with the value INCOMPLETE, then the
7706 aggregated route must have the ORIGIN attribute with the value
7707 INCOMPLETE. Otherwise, if at least one route among routes that
7708 are aggregated has ORIGIN with the value EGP, then the aggregated
7709 route must have the origin attribute with the value EGP. In all
7710 other case the value of the ORIGIN attribute of the aggregated
7711 route is INTERNAL. */
7712 origin
= BGP_ORIGIN_IGP
;
7714 table
= bgp
->rib
[afi
][safi
];
7716 top
= bgp_node_get(table
, p
);
7717 for (dest
= bgp_node_get(table
, p
); dest
;
7718 dest
= bgp_route_next_until(dest
, top
)) {
7719 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7721 if (dest_p
->prefixlen
<= p
->prefixlen
)
7724 /* If suppress fib is enabled and route not installed
7725 * in FIB, skip the route
7727 if (!bgp_check_advertise(bgp
, dest
))
7732 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7733 if (BGP_PATH_HOLDDOWN(pi
))
7737 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7738 atomic_aggregate
= 1;
7740 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7744 * summary-only aggregate route suppress
7745 * aggregated route announcements.
7748 * Don't create summaries if MED didn't match
7749 * otherwise neither the specific routes and the
7750 * aggregation will be announced.
7752 if (aggregate
->summary_only
7753 && AGGREGATE_MED_VALID(aggregate
)) {
7754 if (aggr_suppress_path(aggregate
, pi
))
7759 * Suppress more specific routes that match the route
7763 * Don't suppress routes if MED matching is enabled and
7764 * it mismatched otherwise we might end up with no
7765 * routes for this path.
7767 if (aggregate
->suppress_map_name
7768 && AGGREGATE_MED_VALID(aggregate
)
7769 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7770 if (aggr_suppress_path(aggregate
, pi
))
7777 * If at least one route among routes that are
7778 * aggregated has ORIGIN with the value INCOMPLETE,
7779 * then the aggregated route MUST have the ORIGIN
7780 * attribute with the value INCOMPLETE. Otherwise, if
7781 * at least one route among routes that are aggregated
7782 * has ORIGIN with the value EGP, then the aggregated
7783 * route MUST have the ORIGIN attribute with the value
7786 switch (pi
->attr
->origin
) {
7787 case BGP_ORIGIN_INCOMPLETE
:
7788 aggregate
->incomplete_origin_count
++;
7790 case BGP_ORIGIN_EGP
:
7791 aggregate
->egp_origin_count
++;
7799 if (!aggregate
->as_set
)
7803 * as-set aggregate route generate origin, as path,
7804 * and community aggregation.
7806 /* Compute aggregate route's as-path.
7808 bgp_compute_aggregate_aspath_hash(aggregate
,
7811 /* Compute aggregate route's community.
7813 if (bgp_attr_get_community(pi
->attr
))
7814 bgp_compute_aggregate_community_hash(
7816 bgp_attr_get_community(pi
->attr
));
7818 /* Compute aggregate route's extended community.
7820 if (bgp_attr_get_ecommunity(pi
->attr
))
7821 bgp_compute_aggregate_ecommunity_hash(
7823 bgp_attr_get_ecommunity(pi
->attr
));
7825 /* Compute aggregate route's large community.
7827 if (bgp_attr_get_lcommunity(pi
->attr
))
7828 bgp_compute_aggregate_lcommunity_hash(
7830 bgp_attr_get_lcommunity(pi
->attr
));
7833 bgp_process(bgp
, dest
, afi
, safi
);
7835 if (aggregate
->as_set
) {
7836 bgp_compute_aggregate_aspath_val(aggregate
);
7837 bgp_compute_aggregate_community_val(aggregate
);
7838 bgp_compute_aggregate_ecommunity_val(aggregate
);
7839 bgp_compute_aggregate_lcommunity_val(aggregate
);
7843 bgp_dest_unlock_node(top
);
7846 if (aggregate
->incomplete_origin_count
> 0)
7847 origin
= BGP_ORIGIN_INCOMPLETE
;
7848 else if (aggregate
->egp_origin_count
> 0)
7849 origin
= BGP_ORIGIN_EGP
;
7851 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7852 origin
= aggregate
->origin
;
7854 if (aggregate
->as_set
) {
7855 if (aggregate
->aspath
)
7856 /* Retrieve aggregate route's as-path.
7858 aspath
= aspath_dup(aggregate
->aspath
);
7860 if (aggregate
->community
)
7861 /* Retrieve aggregate route's community.
7863 community
= community_dup(aggregate
->community
);
7865 if (aggregate
->ecommunity
)
7866 /* Retrieve aggregate route's ecommunity.
7868 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7870 if (aggregate
->lcommunity
)
7871 /* Retrieve aggregate route's lcommunity.
7873 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7876 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7877 ecommunity
, lcommunity
, atomic_aggregate
,
7883 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7884 safi_t safi
, struct bgp_aggregate
*aggregate
)
7886 struct bgp_table
*table
;
7887 struct bgp_dest
*top
;
7888 struct bgp_dest
*dest
;
7889 struct bgp_path_info
*pi
;
7890 unsigned long match
;
7892 table
= bgp
->rib
[afi
][safi
];
7894 /* If routes exists below this node, generate aggregate routes. */
7895 top
= bgp_node_get(table
, p
);
7896 for (dest
= bgp_node_get(table
, p
); dest
;
7897 dest
= bgp_route_next_until(dest
, top
)) {
7898 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7900 if (dest_p
->prefixlen
<= p
->prefixlen
)
7904 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7905 if (BGP_PATH_HOLDDOWN(pi
))
7908 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7912 * This route is suppressed: attempt to unsuppress it.
7914 * `aggr_unsuppress_path` will fail if this particular
7915 * aggregate route was not the suppressor.
7917 if (pi
->extra
&& pi
->extra
->aggr_suppressors
&&
7918 listcount(pi
->extra
->aggr_suppressors
)) {
7919 if (aggr_unsuppress_path(aggregate
, pi
))
7925 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7926 aggregate
->incomplete_origin_count
--;
7927 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7928 aggregate
->egp_origin_count
--;
7930 if (aggregate
->as_set
) {
7931 /* Remove as-path from aggregate.
7933 bgp_remove_aspath_from_aggregate_hash(
7937 if (bgp_attr_get_community(pi
->attr
))
7938 /* Remove community from aggregate.
7940 bgp_remove_comm_from_aggregate_hash(
7942 bgp_attr_get_community(
7945 if (bgp_attr_get_ecommunity(pi
->attr
))
7946 /* Remove ecommunity from aggregate.
7948 bgp_remove_ecomm_from_aggregate_hash(
7950 bgp_attr_get_ecommunity(
7953 if (bgp_attr_get_lcommunity(pi
->attr
))
7954 /* Remove lcommunity from aggregate.
7956 bgp_remove_lcomm_from_aggregate_hash(
7958 bgp_attr_get_lcommunity(
7963 /* If this node was suppressed, process the change. */
7965 bgp_process(bgp
, dest
, afi
, safi
);
7967 if (aggregate
->as_set
) {
7968 aspath_free(aggregate
->aspath
);
7969 aggregate
->aspath
= NULL
;
7970 if (aggregate
->community
)
7971 community_free(&aggregate
->community
);
7972 if (aggregate
->ecommunity
)
7973 ecommunity_free(&aggregate
->ecommunity
);
7974 if (aggregate
->lcommunity
)
7975 lcommunity_free(&aggregate
->lcommunity
);
7978 bgp_dest_unlock_node(top
);
7981 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7982 const struct prefix
*aggr_p
,
7983 struct bgp_path_info
*pinew
, afi_t afi
,
7985 struct bgp_aggregate
*aggregate
)
7988 struct aspath
*aspath
= NULL
;
7989 uint8_t atomic_aggregate
= 0;
7990 struct community
*community
= NULL
;
7991 struct ecommunity
*ecommunity
= NULL
;
7992 struct lcommunity
*lcommunity
= NULL
;
7994 /* If the bgp instance is being deleted or self peer is deleted
7995 * then do not create aggregate route
7997 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7998 || (bgp
->peer_self
== NULL
))
8001 /* ORIGIN attribute: If at least one route among routes that are
8002 * aggregated has ORIGIN with the value INCOMPLETE, then the
8003 * aggregated route must have the ORIGIN attribute with the value
8004 * INCOMPLETE. Otherwise, if at least one route among routes that
8005 * are aggregated has ORIGIN with the value EGP, then the aggregated
8006 * route must have the origin attribute with the value EGP. In all
8007 * other case the value of the ORIGIN attribute of the aggregated
8008 * route is INTERNAL.
8010 origin
= BGP_ORIGIN_IGP
;
8015 * This must be called before `summary` check to avoid
8016 * "suppressing" twice.
8018 if (aggregate
->match_med
)
8019 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
8022 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8023 aggr_suppress_path(aggregate
, pinew
);
8025 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8026 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
8027 aggr_suppress_path(aggregate
, pinew
);
8029 switch (pinew
->attr
->origin
) {
8030 case BGP_ORIGIN_INCOMPLETE
:
8031 aggregate
->incomplete_origin_count
++;
8033 case BGP_ORIGIN_EGP
:
8034 aggregate
->egp_origin_count
++;
8042 if (aggregate
->incomplete_origin_count
> 0)
8043 origin
= BGP_ORIGIN_INCOMPLETE
;
8044 else if (aggregate
->egp_origin_count
> 0)
8045 origin
= BGP_ORIGIN_EGP
;
8047 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8048 origin
= aggregate
->origin
;
8050 if (aggregate
->as_set
) {
8051 /* Compute aggregate route's as-path.
8053 bgp_compute_aggregate_aspath(aggregate
,
8054 pinew
->attr
->aspath
);
8056 /* Compute aggregate route's community.
8058 if (bgp_attr_get_community(pinew
->attr
))
8059 bgp_compute_aggregate_community(
8060 aggregate
, bgp_attr_get_community(pinew
->attr
));
8062 /* Compute aggregate route's extended community.
8064 if (bgp_attr_get_ecommunity(pinew
->attr
))
8065 bgp_compute_aggregate_ecommunity(
8067 bgp_attr_get_ecommunity(pinew
->attr
));
8069 /* Compute aggregate route's large community.
8071 if (bgp_attr_get_lcommunity(pinew
->attr
))
8072 bgp_compute_aggregate_lcommunity(
8074 bgp_attr_get_lcommunity(pinew
->attr
));
8076 /* Retrieve aggregate route's as-path.
8078 if (aggregate
->aspath
)
8079 aspath
= aspath_dup(aggregate
->aspath
);
8081 /* Retrieve aggregate route's community.
8083 if (aggregate
->community
)
8084 community
= community_dup(aggregate
->community
);
8086 /* Retrieve aggregate route's ecommunity.
8088 if (aggregate
->ecommunity
)
8089 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8091 /* Retrieve aggregate route's lcommunity.
8093 if (aggregate
->lcommunity
)
8094 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8097 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8098 aspath
, community
, ecommunity
,
8099 lcommunity
, atomic_aggregate
, aggregate
);
8102 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
8104 struct bgp_path_info
*pi
,
8105 struct bgp_aggregate
*aggregate
,
8106 const struct prefix
*aggr_p
)
8109 struct aspath
*aspath
= NULL
;
8110 uint8_t atomic_aggregate
= 0;
8111 struct community
*community
= NULL
;
8112 struct ecommunity
*ecommunity
= NULL
;
8113 struct lcommunity
*lcommunity
= NULL
;
8114 unsigned long match
= 0;
8116 /* If the bgp instance is being deleted or self peer is deleted
8117 * then do not create aggregate route
8119 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
8120 || (bgp
->peer_self
== NULL
))
8123 if (BGP_PATH_HOLDDOWN(pi
))
8126 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
8129 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8130 if (aggr_unsuppress_path(aggregate
, pi
))
8133 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8134 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
8135 if (aggr_unsuppress_path(aggregate
, pi
))
8139 * This must be called after `summary`, `suppress-map` check to avoid
8140 * "unsuppressing" twice.
8142 if (aggregate
->match_med
)
8143 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
);
8145 if (aggregate
->count
> 0)
8148 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
8149 aggregate
->incomplete_origin_count
--;
8150 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
8151 aggregate
->egp_origin_count
--;
8153 if (aggregate
->as_set
) {
8154 /* Remove as-path from aggregate.
8156 bgp_remove_aspath_from_aggregate(aggregate
,
8159 if (bgp_attr_get_community(pi
->attr
))
8160 /* Remove community from aggregate.
8162 bgp_remove_community_from_aggregate(
8163 aggregate
, bgp_attr_get_community(pi
->attr
));
8165 if (bgp_attr_get_ecommunity(pi
->attr
))
8166 /* Remove ecommunity from aggregate.
8168 bgp_remove_ecommunity_from_aggregate(
8169 aggregate
, bgp_attr_get_ecommunity(pi
->attr
));
8171 if (bgp_attr_get_lcommunity(pi
->attr
))
8172 /* Remove lcommunity from aggregate.
8174 bgp_remove_lcommunity_from_aggregate(
8175 aggregate
, bgp_attr_get_lcommunity(pi
->attr
));
8178 /* If this node was suppressed, process the change. */
8180 bgp_process(bgp
, pi
->net
, afi
, safi
);
8182 origin
= BGP_ORIGIN_IGP
;
8183 if (aggregate
->incomplete_origin_count
> 0)
8184 origin
= BGP_ORIGIN_INCOMPLETE
;
8185 else if (aggregate
->egp_origin_count
> 0)
8186 origin
= BGP_ORIGIN_EGP
;
8188 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8189 origin
= aggregate
->origin
;
8191 if (aggregate
->as_set
) {
8192 /* Retrieve aggregate route's as-path.
8194 if (aggregate
->aspath
)
8195 aspath
= aspath_dup(aggregate
->aspath
);
8197 /* Retrieve aggregate route's community.
8199 if (aggregate
->community
)
8200 community
= community_dup(aggregate
->community
);
8202 /* Retrieve aggregate route's ecommunity.
8204 if (aggregate
->ecommunity
)
8205 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8207 /* Retrieve aggregate route's lcommunity.
8209 if (aggregate
->lcommunity
)
8210 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8213 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8214 aspath
, community
, ecommunity
,
8215 lcommunity
, atomic_aggregate
, aggregate
);
8218 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
8219 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
8221 struct bgp_dest
*child
;
8222 struct bgp_dest
*dest
;
8223 struct bgp_aggregate
*aggregate
;
8224 struct bgp_table
*table
;
8226 table
= bgp
->aggregate
[afi
][safi
];
8228 /* No aggregates configured. */
8229 if (bgp_table_top_nolock(table
) == NULL
)
8232 if (p
->prefixlen
== 0)
8235 if (BGP_PATH_HOLDDOWN(pi
))
8238 /* If suppress fib is enabled and route not installed
8239 * in FIB, do not update the aggregate route
8241 if (!bgp_check_advertise(bgp
, pi
->net
))
8244 child
= bgp_node_get(table
, p
);
8246 /* Aggregate address configuration check. */
8247 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8248 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8250 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8251 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8252 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
8256 bgp_dest_unlock_node(child
);
8259 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
8260 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
8262 struct bgp_dest
*child
;
8263 struct bgp_dest
*dest
;
8264 struct bgp_aggregate
*aggregate
;
8265 struct bgp_table
*table
;
8267 table
= bgp
->aggregate
[afi
][safi
];
8269 /* No aggregates configured. */
8270 if (bgp_table_top_nolock(table
) == NULL
)
8273 if (p
->prefixlen
== 0)
8276 child
= bgp_node_get(table
, p
);
8278 /* Aggregate address configuration check. */
8279 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8280 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8282 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8283 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8284 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
8288 bgp_dest_unlock_node(child
);
8291 /* Aggregate route attribute. */
8292 #define AGGREGATE_SUMMARY_ONLY 1
8293 #define AGGREGATE_AS_SET 1
8294 #define AGGREGATE_AS_UNSET 0
8296 static const char *bgp_origin2str(uint8_t origin
)
8299 case BGP_ORIGIN_IGP
:
8301 case BGP_ORIGIN_EGP
:
8303 case BGP_ORIGIN_INCOMPLETE
:
8304 return "incomplete";
8309 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
8312 case RPKI_NOT_BEING_USED
:
8322 assert(!"We should never get here this is a dev escape");
8326 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
8327 afi_t afi
, safi_t safi
)
8329 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8332 struct bgp_dest
*dest
;
8333 struct bgp_aggregate
*aggregate
;
8335 /* Convert string to prefix structure. */
8336 ret
= str2prefix(prefix_str
, &p
);
8338 vty_out(vty
, "Malformed prefix\n");
8339 return CMD_WARNING_CONFIG_FAILED
;
8343 /* Old configuration check. */
8344 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
8347 "%% There is no aggregate-address configuration.\n");
8348 return CMD_WARNING_CONFIG_FAILED
;
8351 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8352 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
8353 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
8354 NULL
, NULL
, 0, aggregate
);
8356 /* Unlock aggregate address configuration. */
8357 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
8359 if (aggregate
->community
)
8360 community_free(&aggregate
->community
);
8362 hash_clean_and_free(&aggregate
->community_hash
,
8363 bgp_aggr_community_remove
);
8365 if (aggregate
->ecommunity
)
8366 ecommunity_free(&aggregate
->ecommunity
);
8368 hash_clean_and_free(&aggregate
->ecommunity_hash
,
8369 bgp_aggr_ecommunity_remove
);
8371 if (aggregate
->lcommunity
)
8372 lcommunity_free(&aggregate
->lcommunity
);
8374 hash_clean_and_free(&aggregate
->lcommunity_hash
,
8375 bgp_aggr_lcommunity_remove
);
8377 if (aggregate
->aspath
)
8378 aspath_free(aggregate
->aspath
);
8380 hash_clean_and_free(&aggregate
->aspath_hash
, bgp_aggr_aspath_remove
);
8382 bgp_aggregate_free(aggregate
);
8383 bgp_dest_unlock_node(dest
);
8384 bgp_dest_unlock_node(dest
);
8389 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
8390 safi_t safi
, const char *rmap
,
8391 uint8_t summary_only
, uint8_t as_set
,
8392 uint8_t origin
, bool match_med
,
8393 const char *suppress_map
)
8395 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8398 struct bgp_dest
*dest
;
8399 struct bgp_aggregate
*aggregate
;
8400 uint8_t as_set_new
= as_set
;
8402 if (suppress_map
&& summary_only
) {
8404 "'summary-only' and 'suppress-map' can't be used at the same time\n");
8405 return CMD_WARNING_CONFIG_FAILED
;
8408 /* Convert string to prefix structure. */
8409 ret
= str2prefix(prefix_str
, &p
);
8411 vty_out(vty
, "Malformed prefix\n");
8412 return CMD_WARNING_CONFIG_FAILED
;
8416 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
8417 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
8418 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8420 return CMD_WARNING_CONFIG_FAILED
;
8423 /* Old configuration check. */
8424 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
8425 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8428 vty_out(vty
, "There is already same aggregate network.\n");
8429 /* try to remove the old entry */
8430 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
8432 vty_out(vty
, "Error deleting aggregate.\n");
8433 bgp_dest_unlock_node(dest
);
8434 return CMD_WARNING_CONFIG_FAILED
;
8438 /* Make aggregate address structure. */
8439 aggregate
= bgp_aggregate_new();
8440 aggregate
->summary_only
= summary_only
;
8441 aggregate
->match_med
= match_med
;
8443 /* Network operators MUST NOT locally generate any new
8444 * announcements containing AS_SET or AS_CONFED_SET. If they have
8445 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8446 * SHOULD withdraw those routes and re-announce routes for the
8447 * aggregate or component prefixes (i.e., the more-specific routes
8448 * subsumed by the previously aggregated route) without AS_SET
8449 * or AS_CONFED_SET in the updates.
8451 if (bgp
->reject_as_sets
) {
8452 if (as_set
== AGGREGATE_AS_SET
) {
8453 as_set_new
= AGGREGATE_AS_UNSET
;
8455 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8458 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8462 aggregate
->as_set
= as_set_new
;
8463 aggregate
->safi
= safi
;
8464 /* Override ORIGIN attribute if defined.
8465 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8466 * to IGP which is not what rfc4271 says.
8467 * This enables the same behavior, optionally.
8469 aggregate
->origin
= origin
;
8472 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
8473 route_map_counter_decrement(aggregate
->rmap
.map
);
8474 aggregate
->rmap
.name
=
8475 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
8476 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
8477 route_map_counter_increment(aggregate
->rmap
.map
);
8481 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
8482 route_map_counter_decrement(aggregate
->suppress_map
);
8484 aggregate
->suppress_map_name
=
8485 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
8486 aggregate
->suppress_map
=
8487 route_map_lookup_by_name(aggregate
->suppress_map_name
);
8488 route_map_counter_increment(aggregate
->suppress_map
);
8491 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
8493 /* Aggregate address insert into BGP routing table. */
8494 if (!bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
)) {
8495 bgp_aggregate_free(aggregate
);
8496 bgp_dest_unlock_node(dest
);
8502 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
8503 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8505 "|summary-only$summary_only"
8506 "|route-map RMAP_NAME$rmap_name"
8507 "|origin <egp|igp|incomplete>$origin_s"
8508 "|matching-MED-only$match_med"
8509 "|suppress-map RMAP_NAME$suppress_map"
8512 "Configure BGP aggregate entries\n"
8513 "Aggregate prefix\n"
8514 "Aggregate address\n"
8516 "Generate AS set path information\n"
8517 "Filter more specific routes from updates\n"
8518 "Apply route map to aggregate network\n"
8523 "Unknown heritage\n"
8524 "Only aggregate routes with matching MED\n"
8525 "Suppress the selected more specific routes\n"
8526 "Route map with the route selectors\n")
8528 const char *prefix_s
= NULL
;
8529 safi_t safi
= bgp_node_safi(vty
);
8530 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8531 int as_set
= AGGREGATE_AS_UNSET
;
8532 char prefix_buf
[PREFIX2STR_BUFFER
];
8535 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8538 vty_out(vty
, "%% Inconsistent address and mask\n");
8539 return CMD_WARNING_CONFIG_FAILED
;
8541 prefix_s
= prefix_buf
;
8543 prefix_s
= prefix_str
;
8546 if (strcmp(origin_s
, "egp") == 0)
8547 origin
= BGP_ORIGIN_EGP
;
8548 else if (strcmp(origin_s
, "igp") == 0)
8549 origin
= BGP_ORIGIN_IGP
;
8550 else if (strcmp(origin_s
, "incomplete") == 0)
8551 origin
= BGP_ORIGIN_INCOMPLETE
;
8555 as_set
= AGGREGATE_AS_SET
;
8557 /* Handle configuration removal, otherwise installation. */
8559 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8561 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8562 summary_only
!= NULL
, as_set
, origin
,
8563 match_med
!= NULL
, suppress_map
);
8566 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8567 "[no] aggregate-address X:X::X:X/M$prefix [{"
8569 "|summary-only$summary_only"
8570 "|route-map RMAP_NAME$rmap_name"
8571 "|origin <egp|igp|incomplete>$origin_s"
8572 "|matching-MED-only$match_med"
8573 "|suppress-map RMAP_NAME$suppress_map"
8576 "Configure BGP aggregate entries\n"
8577 "Aggregate prefix\n"
8578 "Generate AS set path information\n"
8579 "Filter more specific routes from updates\n"
8580 "Apply route map to aggregate network\n"
8585 "Unknown heritage\n"
8586 "Only aggregate routes with matching MED\n"
8587 "Suppress the selected more specific routes\n"
8588 "Route map with the route selectors\n")
8590 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8591 int as_set
= AGGREGATE_AS_UNSET
;
8594 if (strcmp(origin_s
, "egp") == 0)
8595 origin
= BGP_ORIGIN_EGP
;
8596 else if (strcmp(origin_s
, "igp") == 0)
8597 origin
= BGP_ORIGIN_IGP
;
8598 else if (strcmp(origin_s
, "incomplete") == 0)
8599 origin
= BGP_ORIGIN_INCOMPLETE
;
8603 as_set
= AGGREGATE_AS_SET
;
8605 /* Handle configuration removal, otherwise installation. */
8607 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8610 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8611 rmap_name
, summary_only
!= NULL
, as_set
,
8612 origin
, match_med
!= NULL
, suppress_map
);
8615 /* Redistribute route treatment. */
8616 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8617 const union g_addr
*nexthop
, ifindex_t ifindex
,
8618 enum nexthop_types_t nhtype
, uint8_t distance
,
8619 enum blackhole_type bhtype
, uint32_t metric
,
8620 uint8_t type
, unsigned short instance
,
8623 struct bgp_path_info
*new;
8624 struct bgp_path_info
*bpi
;
8625 struct bgp_path_info rmap_path
;
8626 struct bgp_dest
*bn
;
8628 struct attr
*new_attr
;
8630 route_map_result_t ret
;
8631 struct bgp_redist
*red
;
8633 /* Make default attribute. */
8634 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
8636 * This must not be NULL to satisfy Coverity SA
8638 assert(attr
.aspath
);
8641 case NEXTHOP_TYPE_IFINDEX
:
8642 switch (p
->family
) {
8644 attr
.nexthop
.s_addr
= INADDR_ANY
;
8645 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8648 memset(&attr
.mp_nexthop_global
, 0,
8649 sizeof(attr
.mp_nexthop_global
));
8650 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8654 case NEXTHOP_TYPE_IPV4
:
8655 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8656 attr
.nexthop
= nexthop
->ipv4
;
8657 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8659 case NEXTHOP_TYPE_IPV6
:
8660 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8661 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8662 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8664 case NEXTHOP_TYPE_BLACKHOLE
:
8665 switch (p
->family
) {
8667 attr
.nexthop
.s_addr
= INADDR_ANY
;
8668 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8671 memset(&attr
.mp_nexthop_global
, 0,
8672 sizeof(attr
.mp_nexthop_global
));
8673 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8676 attr
.bh_type
= bhtype
;
8679 attr
.nh_type
= nhtype
;
8680 attr
.nh_ifindex
= ifindex
;
8683 attr
.distance
= distance
;
8684 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8688 bgp_attr_set_aigp_metric(&attr
, metric
);
8690 afi
= family2afi(p
->family
);
8692 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8694 struct attr attr_new
;
8696 /* Copy attribute for modification. */
8699 if (red
->redist_metric_flag
) {
8700 attr_new
.med
= red
->redist_metric
;
8701 bgp_attr_set_aigp_metric(&attr_new
, red
->redist_metric
);
8704 /* Apply route-map. */
8705 if (red
->rmap
.name
) {
8706 memset(&rmap_path
, 0, sizeof(rmap_path
));
8707 rmap_path
.peer
= bgp
->peer_self
;
8708 rmap_path
.attr
= &attr_new
;
8710 SET_FLAG(bgp
->peer_self
->rmap_type
,
8711 PEER_RMAP_TYPE_REDISTRIBUTE
);
8713 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8715 bgp
->peer_self
->rmap_type
= 0;
8717 if (ret
== RMAP_DENYMATCH
) {
8718 /* Free uninterned attribute. */
8719 bgp_attr_flush(&attr_new
);
8721 /* Unintern original. */
8722 aspath_unintern(&attr
.aspath
);
8723 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8728 if (bgp_in_graceful_shutdown(bgp
))
8729 bgp_attr_add_gshut_community(&attr_new
);
8731 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8732 SAFI_UNICAST
, p
, NULL
);
8734 new_attr
= bgp_attr_intern(&attr_new
);
8736 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8737 if (bpi
->peer
== bgp
->peer_self
8738 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8742 /* Ensure the (source route) type is updated. */
8744 if (attrhash_cmp(bpi
->attr
, new_attr
)
8745 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8746 bgp_attr_unintern(&new_attr
);
8747 aspath_unintern(&attr
.aspath
);
8748 bgp_dest_unlock_node(bn
);
8751 /* The attribute is changed. */
8752 bgp_path_info_set_flag(bn
, bpi
,
8753 BGP_PATH_ATTR_CHANGED
);
8755 /* Rewrite BGP route information. */
8756 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8757 bgp_path_info_restore(bn
, bpi
);
8759 bgp_aggregate_decrement(
8760 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8761 bgp_attr_unintern(&bpi
->attr
);
8762 bpi
->attr
= new_attr
;
8763 bpi
->uptime
= monotime(NULL
);
8765 /* Process change. */
8766 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8768 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8769 bgp_dest_unlock_node(bn
);
8770 aspath_unintern(&attr
.aspath
);
8772 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8774 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8776 vpn_leak_from_vrf_update(
8777 bgp_get_default(), bgp
, bpi
);
8783 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8784 bgp
->peer_self
, new_attr
, bn
);
8785 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8787 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8788 bgp_path_info_add(bn
, new);
8789 bgp_dest_unlock_node(bn
);
8790 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8791 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8793 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8794 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8796 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8800 /* Unintern original. */
8801 aspath_unintern(&attr
.aspath
);
8804 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8805 unsigned short instance
)
8808 struct bgp_dest
*dest
;
8809 struct bgp_path_info
*pi
;
8810 struct bgp_redist
*red
;
8812 afi
= family2afi(p
->family
);
8814 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8816 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8817 SAFI_UNICAST
, p
, NULL
);
8819 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8820 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8824 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8825 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8827 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8830 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8831 bgp_path_info_delete(dest
, pi
);
8832 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8834 bgp_dest_unlock_node(dest
);
8838 /* Withdraw specified route type's route. */
8839 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8840 unsigned short instance
)
8842 struct bgp_dest
*dest
;
8843 struct bgp_path_info
*pi
;
8844 struct bgp_table
*table
;
8846 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8848 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8849 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8850 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8851 && pi
->instance
== instance
)
8855 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8856 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8858 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8861 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8862 pi
, afi
, SAFI_UNICAST
);
8863 bgp_path_info_delete(dest
, pi
);
8864 if (!CHECK_FLAG(bgp
->flags
,
8865 BGP_FLAG_DELETE_IN_PROGRESS
))
8866 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8868 bgp_path_info_reap(dest
, pi
);
8873 /* Static function to display route. */
8874 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8875 struct vty
*vty
, json_object
*json
, bool wide
)
8878 char buf
[INET6_ADDRSTRLEN
];
8880 if (p
->family
== AF_INET
) {
8882 len
= vty_out(vty
, "%pFX", p
);
8884 json_object_string_add(json
, "prefix",
8885 inet_ntop(p
->family
,
8888 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8889 json_object_string_addf(json
, "network", "%pFX", p
);
8890 json_object_int_add(json
, "version", dest
->version
);
8892 } else if (p
->family
== AF_ETHERNET
) {
8893 len
= vty_out(vty
, "%pFX", p
);
8894 } else if (p
->family
== AF_EVPN
) {
8896 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8898 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8899 } else if (p
->family
== AF_FLOWSPEC
) {
8900 route_vty_out_flowspec(vty
, p
, NULL
,
8902 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8903 NLRI_STRING_FORMAT_MIN
, json
);
8906 len
= vty_out(vty
, "%pFX", p
);
8908 json_object_string_add(json
, "prefix",
8909 inet_ntop(p
->family
,
8912 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8913 json_object_string_addf(json
, "network", "%pFX", p
);
8914 json_object_int_add(json
, "version", dest
->version
);
8919 len
= wide
? (45 - len
) : (17 - len
);
8921 vty_out(vty
, "\n%*s", 20, " ");
8923 vty_out(vty
, "%*s", len
, " ");
8927 enum bgp_display_type
{
8931 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8934 case bgp_path_selection_none
:
8935 return "Nothing to Select";
8936 case bgp_path_selection_first
:
8937 return "First path received";
8938 case bgp_path_selection_evpn_sticky_mac
:
8939 return "EVPN Sticky Mac";
8940 case bgp_path_selection_evpn_seq
:
8941 return "EVPN sequence number";
8942 case bgp_path_selection_evpn_lower_ip
:
8943 return "EVPN lower IP";
8944 case bgp_path_selection_evpn_local_path
:
8945 return "EVPN local ES path";
8946 case bgp_path_selection_evpn_non_proxy
:
8947 return "EVPN non proxy";
8948 case bgp_path_selection_weight
:
8950 case bgp_path_selection_local_pref
:
8951 return "Local Pref";
8952 case bgp_path_selection_accept_own
:
8953 return "Accept Own";
8954 case bgp_path_selection_local_route
:
8955 return "Local Route";
8956 case bgp_path_selection_aigp
:
8958 case bgp_path_selection_confed_as_path
:
8959 return "Confederation based AS Path";
8960 case bgp_path_selection_as_path
:
8962 case bgp_path_selection_origin
:
8964 case bgp_path_selection_med
:
8966 case bgp_path_selection_peer
:
8968 case bgp_path_selection_confed
:
8969 return "Confed Peer Type";
8970 case bgp_path_selection_igp_metric
:
8971 return "IGP Metric";
8972 case bgp_path_selection_older
:
8973 return "Older Path";
8974 case bgp_path_selection_router_id
:
8976 case bgp_path_selection_cluster_length
:
8977 return "Cluster length";
8978 case bgp_path_selection_stale
:
8979 return "Path Staleness";
8980 case bgp_path_selection_local_configured
:
8981 return "Locally configured route";
8982 case bgp_path_selection_neighbor_ip
:
8983 return "Neighbor IP";
8984 case bgp_path_selection_default
:
8985 return "Nothing left to compare";
8987 return "Invalid (internal error)";
8990 /* Print the short form route status for a bgp_path_info */
8991 static void route_vty_short_status_out(struct vty
*vty
,
8992 struct bgp_path_info
*path
,
8993 const struct prefix
*p
,
8994 json_object
*json_path
)
8996 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
9000 /* Route status display. */
9001 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9002 json_object_boolean_true_add(json_path
, "removed");
9004 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9005 json_object_boolean_true_add(json_path
, "stale");
9007 if (path
->extra
&& bgp_path_suppressed(path
))
9008 json_object_boolean_true_add(json_path
, "suppressed");
9010 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9011 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9012 json_object_boolean_true_add(json_path
, "valid");
9015 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9016 json_object_boolean_true_add(json_path
, "history");
9018 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9019 json_object_boolean_true_add(json_path
, "damped");
9021 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9022 json_object_boolean_true_add(json_path
, "bestpath");
9023 json_object_string_add(json_path
, "selectionReason",
9024 bgp_path_selection_reason2str(
9025 path
->net
->reason
));
9028 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9029 json_object_boolean_true_add(json_path
, "multipath");
9031 /* Internal route. */
9032 if ((path
->peer
->as
)
9033 && (path
->peer
->as
== path
->peer
->local_as
))
9034 json_object_string_add(json_path
, "pathFrom",
9037 json_object_string_add(json_path
, "pathFrom",
9043 /* RPKI validation state */
9045 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
9047 if (rpki_state
== RPKI_VALID
)
9049 else if (rpki_state
== RPKI_INVALID
)
9051 else if (rpki_state
== RPKI_NOTFOUND
)
9056 /* Route status display. */
9057 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9059 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9061 else if (bgp_path_suppressed(path
))
9063 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9064 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9070 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9072 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9074 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
9076 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9081 /* Internal route. */
9082 if (path
->peer
&& (path
->peer
->as
)
9083 && (path
->peer
->as
== path
->peer
->local_as
))
9089 static char *bgp_nexthop_hostname(struct peer
*peer
,
9090 struct bgp_nexthop_cache
*bnc
)
9093 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
9094 return peer
->hostname
;
9098 /* called from terminal list command */
9099 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9100 struct bgp_path_info
*path
, int display
, safi_t safi
,
9101 json_object
*json_paths
, bool wide
)
9104 struct attr
*attr
= path
->attr
;
9105 json_object
*json_path
= NULL
;
9106 json_object
*json_nexthops
= NULL
;
9107 json_object
*json_nexthop_global
= NULL
;
9108 json_object
*json_nexthop_ll
= NULL
;
9109 json_object
*json_ext_community
= NULL
;
9110 char vrf_id_str
[VRF_NAMSIZ
] = {0};
9112 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9113 bool nexthop_othervrf
= false;
9114 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
9115 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
9116 char *nexthop_hostname
=
9117 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9118 char esi_buf
[ESI_STR_LEN
];
9121 json_path
= json_object_new_object();
9123 /* short status lead text */
9124 route_vty_short_status_out(vty
, path
, p
, json_path
);
9127 /* print prefix and mask */
9129 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9131 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
9133 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9137 * If vrf id of nexthop is different from that of prefix,
9138 * set up printable string to append
9140 if (path
->extra
&& path
->extra
->bgp_orig
) {
9141 const char *self
= "";
9146 nexthop_othervrf
= true;
9147 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9149 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
9150 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
9151 "@%s%s", VRFID_NONE_STR
, self
);
9153 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
9154 path
->extra
->bgp_orig
->vrf_id
, self
);
9156 if (path
->extra
->bgp_orig
->inst_type
9157 != BGP_INSTANCE_TYPE_DEFAULT
)
9159 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
9161 const char *self
= "";
9166 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
9170 * For ENCAP and EVPN routes, nexthop address family is not
9171 * neccessarily the same as the prefix address family.
9172 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9173 * EVPN routes are also exchanged with a MP nexthop. Currently,
9175 * is only IPv4, the value will be present in either
9177 * attr->mp_nexthop_global_in
9179 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
9181 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9185 snprintfrr(nexthop
, sizeof(nexthop
), "%pI4",
9186 &attr
->mp_nexthop_global_in
);
9189 snprintfrr(nexthop
, sizeof(nexthop
), "%pI6",
9190 &attr
->mp_nexthop_global
);
9193 snprintf(nexthop
, sizeof(nexthop
), "?");
9198 json_nexthop_global
= json_object_new_object();
9200 json_object_string_add(json_nexthop_global
, "ip",
9203 if (path
->peer
->hostname
)
9204 json_object_string_add(json_nexthop_global
,
9206 path
->peer
->hostname
);
9208 json_object_string_add(json_nexthop_global
, "afi",
9209 (af
== AF_INET
) ? "ipv4"
9211 json_object_boolean_true_add(json_nexthop_global
,
9214 if (nexthop_hostname
)
9215 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
9216 nexthop_hostname
, vrf_id_str
);
9218 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
9220 len
= wide
? (41 - len
) : (16 - len
);
9222 vty_out(vty
, "\n%*s", 36, " ");
9224 vty_out(vty
, "%*s", len
, " ");
9226 } else if (safi
== SAFI_EVPN
) {
9228 json_nexthop_global
= json_object_new_object();
9230 json_object_string_addf(json_nexthop_global
, "ip",
9232 &attr
->mp_nexthop_global_in
);
9234 if (path
->peer
->hostname
)
9235 json_object_string_add(json_nexthop_global
,
9237 path
->peer
->hostname
);
9239 json_object_string_add(json_nexthop_global
, "afi",
9241 json_object_boolean_true_add(json_nexthop_global
,
9244 if (nexthop_hostname
)
9245 len
= vty_out(vty
, "%pI4(%s)%s",
9246 &attr
->mp_nexthop_global_in
,
9247 nexthop_hostname
, vrf_id_str
);
9249 len
= vty_out(vty
, "%pI4%s",
9250 &attr
->mp_nexthop_global_in
,
9253 len
= wide
? (41 - len
) : (16 - len
);
9255 vty_out(vty
, "\n%*s", 36, " ");
9257 vty_out(vty
, "%*s", len
, " ");
9259 } else if (safi
== SAFI_FLOWSPEC
) {
9260 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
9262 json_nexthop_global
= json_object_new_object();
9264 json_object_string_add(json_nexthop_global
,
9266 json_object_string_addf(json_nexthop_global
,
9270 if (path
->peer
->hostname
)
9271 json_object_string_add(
9272 json_nexthop_global
, "hostname",
9273 path
->peer
->hostname
);
9275 json_object_boolean_true_add(
9276 json_nexthop_global
,
9279 if (nexthop_hostname
)
9280 len
= vty_out(vty
, "%pI4(%s)%s",
9285 len
= vty_out(vty
, "%pI4%s",
9289 len
= wide
? (41 - len
) : (16 - len
);
9291 vty_out(vty
, "\n%*s", 36, " ");
9293 vty_out(vty
, "%*s", len
, " ");
9296 } else if (p
->family
== AF_INET
&& !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9298 json_nexthop_global
= json_object_new_object();
9300 json_object_string_addf(json_nexthop_global
, "ip",
9301 "%pI4", &attr
->nexthop
);
9303 if (path
->peer
->hostname
)
9304 json_object_string_add(json_nexthop_global
,
9306 path
->peer
->hostname
);
9308 json_object_string_add(json_nexthop_global
, "afi",
9310 json_object_boolean_true_add(json_nexthop_global
,
9313 if (nexthop_hostname
)
9314 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
9315 nexthop_hostname
, vrf_id_str
);
9317 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
9320 len
= wide
? (41 - len
) : (16 - len
);
9322 vty_out(vty
, "\n%*s", 36, " ");
9324 vty_out(vty
, "%*s", len
, " ");
9329 else if (p
->family
== AF_INET6
|| BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9331 json_nexthop_global
= json_object_new_object();
9332 json_object_string_addf(json_nexthop_global
, "ip",
9334 &attr
->mp_nexthop_global
);
9336 if (path
->peer
->hostname
)
9337 json_object_string_add(json_nexthop_global
,
9339 path
->peer
->hostname
);
9341 json_object_string_add(json_nexthop_global
, "afi",
9343 json_object_string_add(json_nexthop_global
, "scope",
9346 /* We display both LL & GL if both have been
9348 if ((attr
->mp_nexthop_len
9349 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9350 || (path
->peer
->conf_if
)) {
9351 json_nexthop_ll
= json_object_new_object();
9352 json_object_string_addf(
9353 json_nexthop_ll
, "ip", "%pI6",
9354 &attr
->mp_nexthop_local
);
9356 if (path
->peer
->hostname
)
9357 json_object_string_add(
9358 json_nexthop_ll
, "hostname",
9359 path
->peer
->hostname
);
9361 json_object_string_add(json_nexthop_ll
, "afi",
9363 json_object_string_add(json_nexthop_ll
, "scope",
9366 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9367 &attr
->mp_nexthop_local
)
9369 && !attr
->mp_nexthop_prefer_global
)
9370 json_object_boolean_true_add(
9371 json_nexthop_ll
, "used");
9373 json_object_boolean_true_add(
9374 json_nexthop_global
, "used");
9376 json_object_boolean_true_add(
9377 json_nexthop_global
, "used");
9379 /* Display LL if LL/Global both in table unless
9380 * prefer-global is set */
9381 if (((attr
->mp_nexthop_len
9382 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9383 && !attr
->mp_nexthop_prefer_global
)
9384 || (path
->peer
->conf_if
)) {
9385 if (path
->peer
->conf_if
) {
9386 len
= vty_out(vty
, "%s",
9387 path
->peer
->conf_if
);
9388 /* len of IPv6 addr + max len of def
9390 len
= wide
? (41 - len
) : (16 - len
);
9393 vty_out(vty
, "\n%*s", 36, " ");
9395 vty_out(vty
, "%*s", len
, " ");
9397 if (nexthop_hostname
)
9400 &attr
->mp_nexthop_local
,
9406 &attr
->mp_nexthop_local
,
9409 len
= wide
? (41 - len
) : (16 - len
);
9412 vty_out(vty
, "\n%*s", 36, " ");
9414 vty_out(vty
, "%*s", len
, " ");
9417 if (nexthop_hostname
)
9418 len
= vty_out(vty
, "%pI6(%s)%s",
9419 &attr
->mp_nexthop_global
,
9423 len
= vty_out(vty
, "%pI6%s",
9424 &attr
->mp_nexthop_global
,
9427 len
= wide
? (41 - len
) : (16 - len
);
9430 vty_out(vty
, "\n%*s", 36, " ");
9432 vty_out(vty
, "%*s", len
, " ");
9438 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9440 json_object_int_add(json_path
, "metric", attr
->med
);
9442 vty_out(vty
, "%7u", attr
->med
);
9444 vty_out(vty
, "%10u", attr
->med
);
9445 else if (!json_paths
) {
9447 vty_out(vty
, "%*s", 7, " ");
9449 vty_out(vty
, "%*s", 10, " ");
9453 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9455 json_object_int_add(json_path
, "locPrf",
9458 vty_out(vty
, "%7u", attr
->local_pref
);
9459 else if (!json_paths
)
9463 json_object_int_add(json_path
, "weight", attr
->weight
);
9465 vty_out(vty
, "%7u ", attr
->weight
);
9468 json_object_string_addf(json_path
, "peerId", "%pSU",
9474 json_object_string_add(json_path
, "path",
9477 aspath_print_vty(vty
, attr
->aspath
);
9482 json_object_string_add(json_path
, "origin",
9483 bgp_origin_long_str
[attr
->origin
]);
9485 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9488 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9489 json_object_string_add(json_path
, "esi",
9490 esi_to_str(&attr
->esi
,
9491 esi_buf
, sizeof(esi_buf
)));
9493 if (safi
== SAFI_EVPN
&&
9494 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9495 json_ext_community
= json_object_new_object();
9496 json_object_string_add(
9497 json_ext_community
, "string",
9498 bgp_attr_get_ecommunity(attr
)->str
);
9499 json_object_object_add(json_path
,
9500 "extendedCommunity",
9501 json_ext_community
);
9505 json_object_boolean_true_add(json_path
,
9506 "announceNexthopSelf");
9507 if (nexthop_othervrf
) {
9508 json_object_string_add(json_path
, "nhVrfName",
9511 json_object_int_add(json_path
, "nhVrfId",
9512 ((nexthop_vrfid
== VRF_UNKNOWN
)
9514 : (int)nexthop_vrfid
));
9519 if (json_nexthop_global
|| json_nexthop_ll
) {
9520 json_nexthops
= json_object_new_array();
9522 if (json_nexthop_global
)
9523 json_object_array_add(json_nexthops
,
9524 json_nexthop_global
);
9526 if (json_nexthop_ll
)
9527 json_object_array_add(json_nexthops
,
9530 json_object_object_add(json_path
, "nexthops",
9534 json_object_array_add(json_paths
, json_path
);
9538 if (safi
== SAFI_EVPN
) {
9539 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9540 /* XXX - add these params to the json out */
9541 vty_out(vty
, "%*s", 20, " ");
9542 vty_out(vty
, "ESI:%s",
9543 esi_to_str(&attr
->esi
, esi_buf
,
9549 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9550 vty_out(vty
, "%*s", 20, " ");
9551 vty_out(vty
, "%s\n",
9552 bgp_attr_get_ecommunity(attr
)->str
);
9556 #ifdef ENABLE_BGP_VNC
9557 /* prints an additional line, indented, with VNC info, if
9559 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9560 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9565 /* called from terminal list command */
9566 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9567 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9568 bool use_json
, json_object
*json_ar
, bool wide
)
9570 json_object
*json_status
= NULL
;
9571 json_object
*json_net
= NULL
;
9575 /* Route status display. */
9577 json_status
= json_object_new_object();
9578 json_net
= json_object_new_object();
9585 /* print prefix and mask */
9587 if (safi
== SAFI_EVPN
)
9588 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9589 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9590 json_object_string_add(
9591 json_net
, "addrPrefix",
9592 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9594 json_object_int_add(json_net
, "prefixLen",
9596 json_object_string_addf(json_net
, "network", "%pFX", p
);
9599 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9601 /* Print attribute */
9604 if (p
->family
== AF_INET
&&
9605 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9606 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9607 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9608 json_object_string_addf(
9609 json_net
, "nextHop", "%pI4",
9610 &attr
->mp_nexthop_global_in
);
9612 json_object_string_addf(
9613 json_net
, "nextHop", "%pI4",
9615 } else if (p
->family
== AF_INET6
||
9616 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9617 json_object_string_addf(
9618 json_net
, "nextHopGlobal", "%pI6",
9619 &attr
->mp_nexthop_global
);
9620 } else if (p
->family
== AF_EVPN
&&
9621 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9622 json_object_string_addf(
9623 json_net
, "nextHop", "%pI4",
9624 &attr
->mp_nexthop_global_in
);
9628 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9629 json_object_int_add(json_net
, "metric",
9632 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9633 json_object_int_add(json_net
, "locPrf",
9636 json_object_int_add(json_net
, "weight", attr
->weight
);
9640 json_object_string_add(json_net
, "path",
9644 #if CONFDATE > 20231208
9645 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9647 json_object_string_add(json_net
, "bgpOriginCode",
9648 bgp_origin_str
[attr
->origin
]);
9649 json_object_string_add(
9651 bgp_origin_long_str
[attr
->origin
]);
9653 if (p
->family
== AF_INET
&&
9654 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9655 safi
== SAFI_EVPN
||
9656 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9657 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9658 || safi
== SAFI_EVPN
)
9659 vty_out(vty
, "%-16pI4",
9660 &attr
->mp_nexthop_global_in
);
9662 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9664 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9665 } else if (p
->family
== AF_INET6
||
9666 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9667 len
= vty_out(vty
, "%pI6",
9668 &attr
->mp_nexthop_global
);
9669 len
= wide
? (41 - len
) : (16 - len
);
9671 vty_out(vty
, "\n%*s", 36, " ");
9673 vty_out(vty
, "%*s", len
, " ");
9676 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9678 vty_out(vty
, "%7u", attr
->med
);
9680 vty_out(vty
, "%10u", attr
->med
);
9686 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9687 vty_out(vty
, "%7u", attr
->local_pref
);
9691 vty_out(vty
, "%7u ", attr
->weight
);
9695 aspath_print_vty(vty
, attr
->aspath
);
9698 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9702 struct bgp_path_info
*bpi
= bgp_dest_get_bgp_path_info(dest
);
9704 #if CONFDATE > 20231208
9705 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9707 json_object_boolean_true_add(json_status
, "*");
9708 json_object_boolean_true_add(json_status
, ">");
9709 json_object_boolean_true_add(json_net
, "valid");
9710 json_object_boolean_true_add(json_net
, "best");
9712 if (bpi
&& CHECK_FLAG(bpi
->flags
, BGP_PATH_MULTIPATH
)) {
9713 json_object_boolean_true_add(json_status
, "=");
9714 json_object_boolean_true_add(json_net
, "multipath");
9716 json_object_object_add(json_net
, "appliedStatusSymbols",
9718 json_object_object_addf(json_ar
, json_net
, "%pFX", p
);
9723 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9724 struct bgp_path_info
*path
, int display
, safi_t safi
,
9727 json_object
*json_out
= NULL
;
9729 mpls_label_t label
= MPLS_INVALID_LABEL
;
9735 json_out
= json_object_new_object();
9737 /* short status lead text */
9738 route_vty_short_status_out(vty
, path
, p
, json_out
);
9740 /* print prefix and mask */
9743 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9745 vty_out(vty
, "%*s", 17, " ");
9748 /* Print attribute */
9750 if (((p
->family
== AF_INET
) &&
9751 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9752 (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) ||
9753 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9754 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9755 || safi
== SAFI_EVPN
) {
9757 json_object_string_addf(
9758 json_out
, "mpNexthopGlobalIn", "%pI4",
9759 &attr
->mp_nexthop_global_in
);
9761 vty_out(vty
, "%-16pI4",
9762 &attr
->mp_nexthop_global_in
);
9765 json_object_string_addf(json_out
, "nexthop",
9766 "%pI4", &attr
->nexthop
);
9768 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9770 } else if (((p
->family
== AF_INET6
) &&
9771 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9772 (safi
== SAFI_EVPN
&& BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) ||
9773 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9776 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9778 json_object_string_addf(
9779 json_out
, "mpNexthopGlobalIn", "%pI6",
9780 &attr
->mp_nexthop_global
);
9784 &attr
->mp_nexthop_global
,
9785 buf_a
, sizeof(buf_a
)));
9786 } else if (attr
->mp_nexthop_len
9787 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9788 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9789 &attr
->mp_nexthop_global
,
9790 &attr
->mp_nexthop_local
);
9792 json_object_string_add(json_out
,
9793 "mpNexthopGlobalLocal",
9796 vty_out(vty
, "%s", buf_a
);
9800 label
= decode_label(&path
->extra
->label
[0]);
9802 if (bgp_is_valid_label(&label
)) {
9804 json_object_int_add(json_out
, "notag", label
);
9805 json_object_array_add(json
, json_out
);
9807 vty_out(vty
, "notag/%d", label
);
9814 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9815 struct bgp_path_info
*path
, int display
,
9816 json_object
*json_paths
)
9819 json_object
*json_path
= NULL
;
9820 json_object
*json_nexthop
= NULL
;
9821 json_object
*json_overlay
= NULL
;
9827 json_path
= json_object_new_object();
9828 json_overlay
= json_object_new_object();
9829 json_nexthop
= json_object_new_object();
9832 /* short status lead text */
9833 route_vty_short_status_out(vty
, path
, p
, json_path
);
9835 /* print prefix and mask */
9837 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9839 vty_out(vty
, "%*s", 17, " ");
9841 /* Print attribute */
9843 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9848 vty_out(vty
, "%-16pI4", &attr
->mp_nexthop_global_in
);
9850 json_object_string_addf(json_nexthop
, "ip", "%pI4",
9851 &attr
->mp_nexthop_global_in
);
9853 json_object_string_add(json_nexthop
, "afi", "ipv4");
9855 json_object_object_add(json_path
, "nexthop",
9861 vty_out(vty
, "%pI6(%pI6)", &attr
->mp_nexthop_global
,
9862 &attr
->mp_nexthop_local
);
9864 json_object_string_addf(json_nexthop
, "ipv6Global",
9866 &attr
->mp_nexthop_global
);
9868 json_object_string_addf(json_nexthop
, "ipv6LinkLocal",
9870 &attr
->mp_nexthop_local
);
9872 json_object_string_add(json_nexthop
, "afi", "ipv6");
9874 json_object_object_add(json_path
, "nexthop",
9882 json_object_string_add(json_nexthop
, "error",
9883 "Unsupported address-family");
9887 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9890 vty_out(vty
, "/%pIA", &eo
->gw_ip
);
9892 json_object_string_addf(json_overlay
, "gw", "%pIA", &eo
->gw_ip
);
9894 if (bgp_attr_get_ecommunity(attr
)) {
9896 struct ecommunity_val
*routermac
= ecommunity_lookup(
9897 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9898 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9901 mac
= ecom_mac2str((char *)routermac
->val
);
9904 vty_out(vty
, "/%s", mac
);
9906 json_object_string_add(json_overlay
, "rmac",
9909 XFREE(MTYPE_TMP
, mac
);
9916 json_object_object_add(json_path
, "overlay", json_overlay
);
9918 json_object_array_add(json_paths
, json_path
);
9922 /* dampening route */
9923 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9924 struct bgp_path_info
*path
, int display
,
9925 afi_t afi
, safi_t safi
, bool use_json
,
9926 json_object
*json_paths
)
9928 struct attr
*attr
= path
->attr
;
9930 char timebuf
[BGP_UPTIME_LEN
];
9931 json_object
*json_path
= NULL
;
9934 json_path
= json_object_new_object();
9936 /* short status lead text */
9937 route_vty_short_status_out(vty
, path
, p
, json_path
);
9939 /* print prefix and mask */
9942 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9944 vty_out(vty
, "%*s", 17, " ");
9946 len
= vty_out(vty
, "%s", path
->peer
->host
);
9950 vty_out(vty
, "\n%*s", 34, " ");
9952 vty_out(vty
, "%*s", len
, " ");
9955 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9956 BGP_UPTIME_LEN
, afi
, safi
,
9960 aspath_print_vty(vty
, attr
->aspath
);
9962 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9966 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9967 safi
, use_json
, json_path
);
9970 json_object_string_add(json_path
, "asPath",
9973 json_object_string_add(json_path
, "origin",
9974 bgp_origin_str
[attr
->origin
]);
9975 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9977 json_object_array_add(json_paths
, json_path
);
9982 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9983 struct bgp_path_info
*path
, int display
,
9984 afi_t afi
, safi_t safi
, bool use_json
,
9985 json_object
*json_paths
)
9987 struct attr
*attr
= path
->attr
;
9988 struct bgp_damp_info
*bdi
;
9989 char timebuf
[BGP_UPTIME_LEN
];
9991 json_object
*json_path
= NULL
;
9997 json_path
= json_object_new_object();
9999 bdi
= path
->extra
->damp_info
;
10001 /* short status lead text */
10002 route_vty_short_status_out(vty
, path
, p
, json_path
);
10006 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
10008 vty_out(vty
, "%*s", 17, " ");
10010 len
= vty_out(vty
, "%s", path
->peer
->host
);
10013 vty_out(vty
, "\n%*s", 33, " ");
10015 vty_out(vty
, "%*s", len
, " ");
10017 len
= vty_out(vty
, "%d", bdi
->flap
);
10022 vty_out(vty
, "%*s", len
, " ");
10024 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
10025 BGP_UPTIME_LEN
, 0, NULL
));
10027 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10028 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10029 vty_out(vty
, "%s ",
10030 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10031 BGP_UPTIME_LEN
, afi
,
10032 safi
, use_json
, NULL
));
10034 vty_out(vty
, "%*s ", 8, " ");
10037 aspath_print_vty(vty
, attr
->aspath
);
10039 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10041 vty_out(vty
, "\n");
10043 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10044 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
10046 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
10049 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10050 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10051 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10052 BGP_UPTIME_LEN
, afi
, safi
,
10053 use_json
, json_path
);
10056 json_object_string_add(json_path
, "asPath",
10057 attr
->aspath
->str
);
10059 json_object_string_add(json_path
, "origin",
10060 bgp_origin_str
[attr
->origin
]);
10062 json_object_array_add(json_paths
, json_path
);
10066 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
10067 int *first
, const char *header
,
10068 json_object
*json_adv_to
)
10070 json_object
*json_peer
= NULL
;
10073 /* 'advertised-to' is a dictionary of peers we have advertised
10075 * prefix too. The key is the peer's IP or swpX, the value is
10077 * hostname if we know it and "" if not.
10079 json_peer
= json_object_new_object();
10081 if (peer
->hostname
)
10082 json_object_string_add(json_peer
, "hostname",
10086 json_object_object_add(json_adv_to
, peer
->conf_if
,
10089 json_object_object_addf(json_adv_to
, json_peer
, "%pSU",
10093 vty_out(vty
, "%s", header
);
10098 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
10100 vty_out(vty
, " %s(%s)", peer
->hostname
,
10103 vty_out(vty
, " %s(%pSU)", peer
->hostname
,
10107 vty_out(vty
, " %s", peer
->conf_if
);
10109 vty_out(vty
, " %pSU", &peer
->su
);
10114 static void route_vty_out_tx_ids(struct vty
*vty
,
10115 struct bgp_addpath_info_data
*d
)
10119 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10120 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
10121 d
->addpath_tx_id
[i
],
10122 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
10126 static void route_vty_out_detail_es_info(struct vty
*vty
,
10127 struct bgp_path_info
*pi
,
10129 json_object
*json_path
)
10131 char esi_buf
[ESI_STR_LEN
];
10132 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
10133 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
10134 ATTR_ES_PEER_ROUTER
);
10135 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
10136 ATTR_ES_PEER_ACTIVE
);
10137 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
10138 ATTR_ES_PEER_PROXY
);
10139 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
10141 json_object
*json_es_info
= NULL
;
10143 json_object_string_add(
10146 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
10147 json_es_info
= json_object_new_object();
10149 json_object_boolean_true_add(
10150 json_es_info
, "localEs");
10152 json_object_boolean_true_add(
10153 json_es_info
, "peerActive");
10155 json_object_boolean_true_add(
10156 json_es_info
, "peerProxy");
10158 json_object_boolean_true_add(
10159 json_es_info
, "peerRouter");
10160 if (attr
->mm_sync_seqnum
)
10161 json_object_int_add(
10162 json_es_info
, "peerSeq",
10163 attr
->mm_sync_seqnum
);
10164 json_object_object_add(
10165 json_path
, "es_info",
10169 if (bgp_evpn_attr_is_sync(attr
))
10171 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10173 es_local
? "local-es":"",
10174 peer_proxy
? "proxy " : "",
10175 peer_active
? "active ":"",
10176 peer_router
? "router ":"",
10177 attr
->mm_sync_seqnum
);
10179 vty_out(vty
, " ESI %s %s\n",
10181 es_local
? "local-es":"");
10185 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
10186 const struct prefix
*p
, struct bgp_path_info
*path
,
10187 afi_t afi
, safi_t safi
,
10188 enum rpki_states rpki_curr_state
,
10189 json_object
*json_paths
)
10191 char buf
[INET6_ADDRSTRLEN
];
10193 struct attr
*attr
= path
->attr
;
10195 json_object
*json_bestpath
= NULL
;
10196 json_object
*json_cluster_list
= NULL
;
10197 json_object
*json_cluster_list_list
= NULL
;
10198 json_object
*json_ext_community
= NULL
;
10199 json_object
*json_last_update
= NULL
;
10200 json_object
*json_pmsi
= NULL
;
10201 json_object
*json_nexthop_global
= NULL
;
10202 json_object
*json_nexthop_ll
= NULL
;
10203 json_object
*json_nexthops
= NULL
;
10204 json_object
*json_path
= NULL
;
10205 json_object
*json_peer
= NULL
;
10206 json_object
*json_string
= NULL
;
10207 json_object
*json_adv_to
= NULL
;
10209 struct listnode
*node
, *nnode
;
10211 bool addpath_capable
;
10213 unsigned int first_as
;
10214 bool nexthop_self
=
10215 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
10217 char *nexthop_hostname
=
10218 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
10222 mpls_label_t label
= MPLS_INVALID_LABEL
;
10224 struct bgp_path_info
*bpi_ultimate
=
10225 bgp_get_imported_bpi_ultimate(path
);
10228 json_path
= json_object_new_object();
10229 json_peer
= json_object_new_object();
10230 json_nexthop_global
= json_object_new_object();
10233 if (safi
== SAFI_EVPN
) {
10235 vty_out(vty
, " Route %pFX", p
);
10239 if (path
->extra
&& path
->extra
->num_labels
) {
10240 bgp_evpn_label2str(path
->extra
->label
,
10241 path
->extra
->num_labels
, tag_buf
,
10244 if (safi
== SAFI_EVPN
) {
10246 if (tag_buf
[0] != '\0')
10247 vty_out(vty
, " VNI %s", tag_buf
);
10250 json_object_string_add(json_path
, "vni",
10256 if (safi
== SAFI_EVPN
10257 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
10258 char gwip_buf
[INET6_ADDRSTRLEN
];
10260 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
10264 json_object_string_add(json_path
, "gatewayIP",
10267 vty_out(vty
, " Gateway IP %s", gwip_buf
);
10270 if (safi
== SAFI_EVPN
&& !json_path
)
10271 vty_out(vty
, "\n");
10274 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
10275 struct bgp_path_info
*parent_ri
;
10276 struct bgp_dest
*dest
, *pdest
;
10278 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
10279 dest
= parent_ri
->net
;
10280 if (dest
&& dest
->pdest
) {
10281 pdest
= dest
->pdest
;
10282 if (is_pi_family_evpn(parent_ri
)) {
10283 vty_out(vty
, " Imported from ");
10284 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
10285 (struct prefix_rd
*)bgp_dest_get_prefix(
10287 vty_out(vty
, ":%pFX, VNI %s",
10288 (struct prefix_evpn
*)
10289 bgp_dest_get_prefix(dest
),
10291 if (CHECK_FLAG(attr
->es_flags
, ATTR_ES_L3_NHG
))
10292 vty_out(vty
, ", L3NHG %s",
10295 ATTR_ES_L3_NHG_ACTIVE
)
10298 vty_out(vty
, "\n");
10301 vty_out(vty
, " Imported from ");
10302 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
10303 (struct prefix_rd
*)bgp_dest_get_prefix(
10305 vty_out(vty
, ":%pFX\n",
10306 (struct prefix_evpn
*)
10307 bgp_dest_get_prefix(dest
));
10312 /* Line1 display AS-path, Aggregator */
10313 if (attr
->aspath
) {
10315 if (!attr
->aspath
->json
)
10316 aspath_str_update(attr
->aspath
, true);
10317 json_object_lock(attr
->aspath
->json
);
10318 json_object_object_add(json_path
, "aspath",
10319 attr
->aspath
->json
);
10321 if (attr
->aspath
->segments
)
10322 vty_out(vty
, " %s", attr
->aspath
->str
);
10324 vty_out(vty
, " Local");
10328 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
10330 json_object_boolean_true_add(json_path
, "removed");
10332 vty_out(vty
, ", (removed)");
10335 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10337 json_object_boolean_true_add(json_path
, "stale");
10339 vty_out(vty
, ", (stale)");
10342 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
10344 json_object_int_add(json_path
, "aggregatorAs",
10345 attr
->aggregator_as
);
10346 json_object_string_addf(json_path
, "aggregatorId",
10347 "%pI4", &attr
->aggregator_addr
);
10349 vty_out(vty
, ", (aggregated by %u %pI4)",
10350 attr
->aggregator_as
, &attr
->aggregator_addr
);
10354 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10355 PEER_FLAG_REFLECTOR_CLIENT
)) {
10357 json_object_boolean_true_add(json_path
,
10358 "rxedFromRrClient");
10360 vty_out(vty
, ", (Received from a RR-client)");
10363 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10364 PEER_FLAG_RSERVER_CLIENT
)) {
10366 json_object_boolean_true_add(json_path
,
10367 "rxedFromRsClient");
10369 vty_out(vty
, ", (Received from a RS-client)");
10372 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10374 json_object_boolean_true_add(json_path
,
10375 "dampeningHistoryEntry");
10377 vty_out(vty
, ", (history entry)");
10378 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10380 json_object_boolean_true_add(json_path
,
10381 "dampeningSuppressed");
10383 vty_out(vty
, ", (suppressed due to dampening)");
10387 vty_out(vty
, "\n");
10389 /* Line2 display Next-hop, Neighbor, Router-id */
10390 /* Display the nexthop */
10392 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
||
10393 p
->family
== AF_EVPN
) &&
10394 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
||
10395 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10396 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10397 || safi
== SAFI_EVPN
) {
10399 json_object_string_addf(
10400 json_nexthop_global
, "ip", "%pI4",
10401 &attr
->mp_nexthop_global_in
);
10403 if (path
->peer
->hostname
)
10404 json_object_string_add(
10405 json_nexthop_global
, "hostname",
10406 path
->peer
->hostname
);
10408 if (nexthop_hostname
)
10409 vty_out(vty
, " %pI4(%s)",
10410 &attr
->mp_nexthop_global_in
,
10413 vty_out(vty
, " %pI4",
10414 &attr
->mp_nexthop_global_in
);
10418 json_object_string_addf(json_nexthop_global
,
10422 if (path
->peer
->hostname
)
10423 json_object_string_add(
10424 json_nexthop_global
, "hostname",
10425 path
->peer
->hostname
);
10427 if (nexthop_hostname
)
10428 vty_out(vty
, " %pI4(%s)",
10432 vty_out(vty
, " %pI4",
10438 json_object_string_add(json_nexthop_global
, "afi",
10442 json_object_string_addf(json_nexthop_global
, "ip",
10444 &attr
->mp_nexthop_global
);
10446 if (path
->peer
->hostname
)
10447 json_object_string_add(json_nexthop_global
,
10449 path
->peer
->hostname
);
10451 json_object_string_add(json_nexthop_global
, "afi",
10453 json_object_string_add(json_nexthop_global
, "scope",
10456 if (nexthop_hostname
)
10457 vty_out(vty
, " %pI6(%s)",
10458 &attr
->mp_nexthop_global
,
10461 vty_out(vty
, " %pI6",
10462 &attr
->mp_nexthop_global
);
10466 /* Display the IGP cost or 'inaccessible' */
10467 if (!CHECK_FLAG(bpi_ultimate
->flags
, BGP_PATH_VALID
)) {
10468 bool import
= CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
);
10471 json_object_boolean_false_add(json_nexthop_global
,
10473 json_object_boolean_add(json_nexthop_global
,
10474 "importCheckEnabled", import
);
10476 vty_out(vty
, " (inaccessible%s)",
10477 import
? ", import-check enabled" : "");
10480 if (bpi_ultimate
->extra
&& bpi_ultimate
->extra
->igpmetric
) {
10482 json_object_int_add(
10483 json_nexthop_global
, "metric",
10484 bpi_ultimate
->extra
->igpmetric
);
10486 vty_out(vty
, " (metric %u)",
10487 bpi_ultimate
->extra
->igpmetric
);
10490 /* IGP cost is 0, display this only for json */
10493 json_object_int_add(json_nexthop_global
,
10498 json_object_boolean_true_add(json_nexthop_global
,
10502 /* Display peer "from" output */
10503 /* This path was originated locally */
10504 if (path
->peer
== bgp
->peer_self
) {
10506 if (safi
== SAFI_EVPN
|| (p
->family
== AF_INET
&&
10507 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10509 json_object_string_add(json_peer
, "peerId",
10512 vty_out(vty
, " from 0.0.0.0 ");
10515 json_object_string_add(json_peer
, "peerId",
10518 vty_out(vty
, " from :: ");
10522 json_object_string_addf(json_peer
, "routerId", "%pI4",
10525 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10528 /* We RXed this path from one of our peers */
10532 json_object_string_addf(json_peer
, "peerId", "%pSU",
10534 json_object_string_addf(json_peer
, "routerId", "%pI4",
10535 &path
->peer
->remote_id
);
10537 if (path
->peer
->hostname
)
10538 json_object_string_add(json_peer
, "hostname",
10539 path
->peer
->hostname
);
10541 if (path
->peer
->domainname
)
10542 json_object_string_add(json_peer
, "domainname",
10543 path
->peer
->domainname
);
10545 if (path
->peer
->conf_if
)
10546 json_object_string_add(json_peer
, "interface",
10547 path
->peer
->conf_if
);
10549 if (path
->peer
->conf_if
) {
10550 if (path
->peer
->hostname
10551 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10552 BGP_FLAG_SHOW_HOSTNAME
))
10553 vty_out(vty
, " from %s(%s)",
10554 path
->peer
->hostname
,
10555 path
->peer
->conf_if
);
10557 vty_out(vty
, " from %s",
10558 path
->peer
->conf_if
);
10560 if (path
->peer
->hostname
10561 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10562 BGP_FLAG_SHOW_HOSTNAME
))
10563 vty_out(vty
, " from %s(%s)",
10564 path
->peer
->hostname
,
10567 vty_out(vty
, " from %pSU",
10571 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10572 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10574 vty_out(vty
, " (%pI4)", &path
->peer
->remote_id
);
10579 * Note when vrfid of nexthop is different from that of prefix
10581 if (path
->extra
&& path
->extra
->bgp_orig
) {
10582 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10587 if (path
->extra
->bgp_orig
->inst_type
10588 == BGP_INSTANCE_TYPE_DEFAULT
)
10589 vn
= VRF_DEFAULT_NAME
;
10591 vn
= path
->extra
->bgp_orig
->name
;
10593 json_object_string_add(json_path
, "nhVrfName", vn
);
10595 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10596 json_object_int_add(json_path
, "nhVrfId", -1);
10598 json_object_int_add(json_path
, "nhVrfId",
10599 (int)nexthop_vrfid
);
10602 if (nexthop_vrfid
== VRF_UNKNOWN
)
10603 vty_out(vty
, " vrf ?");
10607 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10608 vty_out(vty
, " vrf %s(%u)",
10609 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10614 if (nexthop_self
) {
10616 json_object_boolean_true_add(json_path
,
10617 "announceNexthopSelf");
10619 vty_out(vty
, " announce-nh-self");
10624 vty_out(vty
, "\n");
10626 /* display the link-local nexthop */
10627 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10629 json_nexthop_ll
= json_object_new_object();
10630 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10631 &attr
->mp_nexthop_local
);
10633 if (path
->peer
->hostname
)
10634 json_object_string_add(json_nexthop_ll
,
10636 path
->peer
->hostname
);
10638 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10639 json_object_string_add(json_nexthop_ll
, "scope",
10642 json_object_boolean_true_add(json_nexthop_ll
,
10645 if (!attr
->mp_nexthop_prefer_global
)
10646 json_object_boolean_true_add(json_nexthop_ll
,
10649 json_object_boolean_true_add(
10650 json_nexthop_global
, "used");
10652 vty_out(vty
, " (%s) %s\n",
10653 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10654 buf
, INET6_ADDRSTRLEN
),
10655 attr
->mp_nexthop_prefer_global
10656 ? "(prefer-global)"
10660 /* If we do not have a link-local nexthop then we must flag the
10661 global as "used" */
10664 json_object_boolean_true_add(json_nexthop_global
,
10668 if (safi
== SAFI_EVPN
&&
10669 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10670 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10673 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10674 * Int/Ext/Local, Atomic, best */
10676 json_object_string_add(json_path
, "origin",
10677 bgp_origin_long_str
[attr
->origin
]);
10679 vty_out(vty
, " Origin %s",
10680 bgp_origin_long_str
[attr
->origin
]);
10682 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10684 json_object_int_add(json_path
, "metric", attr
->med
);
10686 vty_out(vty
, ", metric %u", attr
->med
);
10689 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10691 json_object_int_add(json_path
, "locPrf",
10694 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10697 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
10699 json_object_int_add(json_path
, "aigpMetric",
10700 bgp_attr_get_aigp_metric(attr
));
10702 vty_out(vty
, ", aigp-metric %" PRIu64
,
10703 bgp_attr_get_aigp_metric(attr
));
10706 if (attr
->weight
!= 0) {
10708 json_object_int_add(json_path
, "weight", attr
->weight
);
10710 vty_out(vty
, ", weight %u", attr
->weight
);
10713 if (attr
->tag
!= 0) {
10715 json_object_int_add(json_path
, "tag", attr
->tag
);
10717 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10720 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10722 json_object_boolean_false_add(json_path
, "valid");
10724 vty_out(vty
, ", invalid");
10725 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10727 json_object_boolean_true_add(json_path
, "valid");
10729 vty_out(vty
, ", valid");
10733 json_object_int_add(json_path
, "version", bn
->version
);
10735 if (path
->peer
!= bgp
->peer_self
) {
10736 if (path
->peer
->as
== path
->peer
->local_as
) {
10737 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10739 json_object_string_add(
10741 "confed-internal");
10743 vty_out(vty
, ", confed-internal");
10746 json_object_string_add(
10747 json_peer
, "type", "internal");
10749 vty_out(vty
, ", internal");
10752 if (bgp_confederation_peers_check(bgp
,
10755 json_object_string_add(
10757 "confed-external");
10759 vty_out(vty
, ", confed-external");
10762 json_object_string_add(
10763 json_peer
, "type", "external");
10765 vty_out(vty
, ", external");
10768 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10770 json_object_boolean_true_add(json_path
, "aggregated");
10771 json_object_boolean_true_add(json_path
, "local");
10773 vty_out(vty
, ", aggregated, local");
10775 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10777 json_object_boolean_true_add(json_path
, "sourced");
10779 vty_out(vty
, ", sourced");
10782 json_object_boolean_true_add(json_path
, "sourced");
10783 json_object_boolean_true_add(json_path
, "local");
10785 vty_out(vty
, ", sourced, local");
10789 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10791 json_object_boolean_true_add(json_path
,
10792 "atomicAggregate");
10794 vty_out(vty
, ", atomic-aggregate");
10797 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
10799 json_object_int_add(json_path
, "otc", attr
->otc
);
10801 vty_out(vty
, ", otc %u", attr
->otc
);
10804 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10805 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10806 && bgp_path_info_mpath_count(path
))) {
10808 json_object_boolean_true_add(json_path
, "multipath");
10810 vty_out(vty
, ", multipath");
10813 // Mark the bestpath(s)
10814 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10815 first_as
= aspath_get_first_as(attr
->aspath
);
10818 if (!json_bestpath
)
10819 json_bestpath
= json_object_new_object();
10820 json_object_int_add(json_bestpath
, "bestpathFromAs",
10824 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10826 vty_out(vty
, ", bestpath-from-AS Local");
10830 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10832 if (!json_bestpath
)
10833 json_bestpath
= json_object_new_object();
10834 json_object_boolean_true_add(json_bestpath
, "overall");
10835 json_object_string_add(
10836 json_bestpath
, "selectionReason",
10837 bgp_path_selection_reason2str(bn
->reason
));
10839 vty_out(vty
, ", best");
10840 vty_out(vty
, " (%s)",
10841 bgp_path_selection_reason2str(bn
->reason
));
10845 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10847 json_object_string_add(
10848 json_path
, "rpkiValidationState",
10849 bgp_rpki_validation2str(rpki_curr_state
));
10851 vty_out(vty
, ", rpki validation-state: %s",
10852 bgp_rpki_validation2str(rpki_curr_state
));
10856 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10859 vty_out(vty
, "\n");
10861 /* Line 4 display Community */
10862 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10864 if (!bgp_attr_get_community(attr
)->json
)
10865 community_str(bgp_attr_get_community(attr
),
10867 json_object_lock(bgp_attr_get_community(attr
)->json
);
10868 json_object_object_add(
10869 json_path
, "community",
10870 bgp_attr_get_community(attr
)->json
);
10872 vty_out(vty
, " Community: %s\n",
10873 bgp_attr_get_community(attr
)->str
);
10877 /* Line 5 display Extended-community */
10878 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10880 json_ext_community
= json_object_new_object();
10881 json_object_string_add(
10882 json_ext_community
, "string",
10883 bgp_attr_get_ecommunity(attr
)->str
);
10884 json_object_object_add(json_path
, "extendedCommunity",
10885 json_ext_community
);
10887 vty_out(vty
, " Extended Community: %s\n",
10888 bgp_attr_get_ecommunity(attr
)->str
);
10892 /* Line 6 display Large community */
10893 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10895 if (!bgp_attr_get_lcommunity(attr
)->json
)
10896 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10898 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10899 json_object_object_add(
10900 json_path
, "largeCommunity",
10901 bgp_attr_get_lcommunity(attr
)->json
);
10903 vty_out(vty
, " Large Community: %s\n",
10904 bgp_attr_get_lcommunity(attr
)->str
);
10908 /* Line 7 display Originator, Cluster-id */
10909 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10910 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10911 char buf
[BUFSIZ
] = {0};
10913 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10915 json_object_string_addf(json_path
,
10916 "originatorId", "%pI4",
10917 &attr
->originator_id
);
10919 vty_out(vty
, " Originator: %pI4",
10920 &attr
->originator_id
);
10923 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10924 struct cluster_list
*cluster
=
10925 bgp_attr_get_cluster(attr
);
10929 json_cluster_list
= json_object_new_object();
10930 json_cluster_list_list
=
10931 json_object_new_array();
10933 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10934 json_string
= json_object_new_string(
10937 buf
, sizeof(buf
)));
10938 json_object_array_add(
10939 json_cluster_list_list
,
10944 * struct cluster_list does not have
10945 * "str" variable like aspath and community
10946 * do. Add this someday if someone asks
10948 * json_object_string_add(json_cluster_list,
10949 * "string", cluster->str);
10951 json_object_object_add(json_cluster_list
,
10953 json_cluster_list_list
);
10954 json_object_object_add(json_path
, "clusterList",
10955 json_cluster_list
);
10957 vty_out(vty
, ", Cluster list: ");
10959 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10960 vty_out(vty
, "%pI4 ",
10961 &cluster
->list
[i
]);
10967 vty_out(vty
, "\n");
10970 if (path
->extra
&& path
->extra
->damp_info
)
10971 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
10974 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10975 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10976 mpls_lse_decode(path
->extra
->label
[0], &label
, &ttl
, &exp
,
10980 json_object_int_add(json_path
, "remoteLabel", label
);
10982 vty_out(vty
, " Remote label: %d\n", label
);
10986 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10988 json_object_string_addf(json_path
, "remoteSid", "%pI6",
10989 &path
->extra
->sid
[0].sid
);
10991 vty_out(vty
, " Remote SID: %pI6\n",
10992 &path
->extra
->sid
[0].sid
);
10996 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
10998 json_object_int_add(json_path
, "labelIndex",
10999 attr
->label_index
);
11001 vty_out(vty
, " Label Index: %d\n",
11002 attr
->label_index
);
11005 /* Line 8 display Addpath IDs */
11006 if (path
->addpath_rx_id
11007 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
11009 json_object_int_add(json_path
, "addpathRxId",
11010 path
->addpath_rx_id
);
11012 /* Keep backwards compatibility with the old API
11013 * by putting TX All's ID in the old field
11015 json_object_int_add(
11016 json_path
, "addpathTxId",
11018 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
11020 /* ... but create a specific field for each
11023 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
11024 json_object_int_add(
11026 bgp_addpath_names(i
)->id_json_name
,
11027 path
->tx_addpath
.addpath_tx_id
[i
]);
11030 vty_out(vty
, " AddPath ID: RX %u, ",
11031 path
->addpath_rx_id
);
11033 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
11037 /* If we used addpath to TX a non-bestpath we need to display
11038 * "Advertised to" on a path-by-path basis
11040 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11043 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11045 bgp_addpath_encode_tx(peer
, afi
, safi
);
11046 has_adj
= bgp_adj_out_lookup(
11048 bgp_addpath_id_for_peer(peer
, afi
, safi
,
11049 &path
->tx_addpath
));
11051 if ((addpath_capable
&& has_adj
)
11052 || (!addpath_capable
&& has_adj
11053 && CHECK_FLAG(path
->flags
,
11054 BGP_PATH_SELECTED
))) {
11055 if (json_path
&& !json_adv_to
)
11056 json_adv_to
= json_object_new_object();
11058 route_vty_out_advertised_to(
11060 " Advertised to:", json_adv_to
);
11066 json_object_object_add(
11067 json_path
, "advertisedTo", json_adv_to
);
11071 vty_out(vty
, "\n");
11076 /* Line 9 display Uptime */
11077 tbuf
= time(NULL
) - (monotime(NULL
) - path
->uptime
);
11079 json_last_update
= json_object_new_object();
11080 json_object_int_add(json_last_update
, "epoch", tbuf
);
11081 json_object_string_add(json_last_update
, "string",
11083 json_object_object_add(json_path
, "lastUpdate",
11086 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
11088 /* Line 10 display PMSI tunnel attribute, if present */
11089 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
11090 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
11091 bgp_attr_get_pmsi_tnl_type(attr
),
11092 PMSI_TNLTYPE_STR_DEFAULT
);
11095 json_pmsi
= json_object_new_object();
11096 json_object_string_add(json_pmsi
, "tunnelType", str
);
11097 json_object_int_add(json_pmsi
, "label",
11098 label2vni(&attr
->label
));
11099 json_object_object_add(json_path
, "pmsi", json_pmsi
);
11101 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
11102 str
, label2vni(&attr
->label
));
11105 if (path
->peer
->t_gr_restart
&&
11106 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
11107 unsigned long gr_remaining
=
11108 thread_timer_remain_second(path
->peer
->t_gr_restart
);
11111 json_object_int_add(json_path
,
11112 "gracefulRestartSecondsRemaining",
11116 " Time until Graceful Restart stale route deleted: %lu\n",
11120 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
11121 bgp_attr_get_community(attr
) &&
11122 community_include(bgp_attr_get_community(attr
),
11123 COMMUNITY_LLGR_STALE
)) {
11124 unsigned long llgr_remaining
= thread_timer_remain_second(
11125 path
->peer
->t_llgr_stale
[afi
][safi
]);
11128 json_object_int_add(json_path
, "llgrSecondsRemaining",
11132 " Time until Long-lived stale route deleted: %lu\n",
11136 /* Output some debug about internal state of the dest flags */
11138 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
11139 json_object_boolean_true_add(json_path
, "processScheduled");
11140 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
11141 json_object_boolean_true_add(json_path
, "userCleared");
11142 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
11143 json_object_boolean_true_add(json_path
, "labelChanged");
11144 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
11145 json_object_boolean_true_add(json_path
, "registeredForLabel");
11146 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
11147 json_object_boolean_true_add(json_path
, "selectDefered");
11148 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
11149 json_object_boolean_true_add(json_path
, "fibInstalled");
11150 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
11151 json_object_boolean_true_add(json_path
, "fibPending");
11153 if (json_nexthop_global
|| json_nexthop_ll
) {
11154 json_nexthops
= json_object_new_array();
11156 if (json_nexthop_global
)
11157 json_object_array_add(json_nexthops
,
11158 json_nexthop_global
);
11160 if (json_nexthop_ll
)
11161 json_object_array_add(json_nexthops
,
11164 json_object_object_add(json_path
, "nexthops",
11168 json_object_object_add(json_path
, "peer", json_peer
);
11169 json_object_array_add(json_paths
, json_path
);
11173 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
11174 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11175 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
11177 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11178 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11180 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11181 const char *comstr
, int exact
, afi_t afi
,
11182 safi_t safi
, uint16_t show_flags
);
11184 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11185 struct bgp_table
*table
, enum bgp_show_type type
,
11186 void *output_arg
, const char *rd
, int is_last
,
11187 unsigned long *output_cum
, unsigned long *total_cum
,
11188 unsigned long *json_header_depth
, uint16_t show_flags
,
11189 enum rpki_states rpki_target_state
)
11191 struct bgp_path_info
*pi
;
11192 struct bgp_dest
*dest
;
11193 bool header
= true;
11194 bool json_detail_header
= false;
11196 unsigned long output_count
= 0;
11197 unsigned long total_count
= 0;
11199 json_object
*json_paths
= NULL
;
11201 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11202 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11203 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11204 bool detail_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
11205 bool detail_routes
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
11207 if (output_cum
&& *output_cum
!= 0)
11210 if (use_json
&& !*json_header_depth
) {
11212 *json_header_depth
= 1;
11214 vty_out(vty
, "{\n");
11215 *json_header_depth
= 2;
11218 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11219 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
11221 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
11222 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
11225 table
->version
, &bgp
->router_id
,
11226 bgp
->default_local_pref
);
11227 if ((bgp
->asnotation
== ASNOTATION_PLAIN
) ||
11228 ((bgp
->asnotation
== ASNOTATION_DOT
) &&
11229 (bgp
->as
< UINT16_MAX
)))
11230 vty_out(vty
, "%u", bgp
->as
);
11232 vty_out(vty
, "\"");
11233 vty_out(vty
, ASN_FORMAT(bgp
->asnotation
), &bgp
->as
);
11234 vty_out(vty
, "\"");
11236 vty_out(vty
, ",\n \"routes\": { ");
11238 vty_out(vty
, " \"routeDistinguishers\" : {");
11239 ++*json_header_depth
;
11243 if (use_json
&& rd
) {
11244 vty_out(vty
, " \"%s\" : { ", rd
);
11247 /* Check for 'json detail', where we need header output once per dest */
11248 if (use_json
&& detail_json
&& type
!= bgp_show_type_dampend_paths
&&
11249 type
!= bgp_show_type_damp_neighbor
&&
11250 type
!= bgp_show_type_flap_statistics
&&
11251 type
!= bgp_show_type_flap_neighbor
)
11252 json_detail_header
= true;
11254 /* Start processing of routes. */
11255 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
11256 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11257 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11258 bool json_detail_header_used
= false;
11260 pi
= bgp_dest_get_bgp_path_info(dest
);
11266 json_paths
= json_object_new_array();
11270 for (; pi
; pi
= pi
->next
) {
11271 struct community
*picomm
= NULL
;
11273 picomm
= bgp_attr_get_community(pi
->attr
);
11277 if (type
== bgp_show_type_prefix_version
) {
11279 strtoul(output_arg
, NULL
, 10);
11280 if (dest
->version
< version
)
11284 if (type
== bgp_show_type_community_alias
) {
11285 char *alias
= output_arg
;
11286 char **communities
;
11288 bool found
= false;
11291 frrstr_split(picomm
->str
, " ",
11292 &communities
, &num
);
11293 for (int i
= 0; i
< num
; i
++) {
11294 const char *com2alias
=
11295 bgp_community2alias(
11298 && strcmp(alias
, com2alias
)
11304 XFREE(MTYPE_TMP
, communities
);
11308 bgp_attr_get_lcommunity(pi
->attr
)) {
11309 frrstr_split(bgp_attr_get_lcommunity(
11312 " ", &communities
, &num
);
11313 for (int i
= 0; i
< num
; i
++) {
11314 const char *com2alias
=
11315 bgp_community2alias(
11318 && strcmp(alias
, com2alias
)
11324 XFREE(MTYPE_TMP
, communities
);
11331 if (type
== bgp_show_type_rpki
) {
11332 if (dest_p
->family
== AF_INET
11333 || dest_p
->family
== AF_INET6
)
11334 rpki_curr_state
= hook_call(
11335 bgp_rpki_prefix_status
,
11336 pi
->peer
, pi
->attr
, dest_p
);
11337 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11338 && rpki_curr_state
!= rpki_target_state
)
11342 if (type
== bgp_show_type_flap_statistics
11343 || type
== bgp_show_type_flap_neighbor
11344 || type
== bgp_show_type_dampend_paths
11345 || type
== bgp_show_type_damp_neighbor
) {
11346 if (!(pi
->extra
&& pi
->extra
->damp_info
))
11349 if (type
== bgp_show_type_regexp
) {
11350 regex_t
*regex
= output_arg
;
11352 if (bgp_regexec(regex
, pi
->attr
->aspath
)
11356 if (type
== bgp_show_type_prefix_list
) {
11357 struct prefix_list
*plist
= output_arg
;
11359 if (prefix_list_apply(plist
, dest_p
)
11363 if (type
== bgp_show_type_access_list
) {
11364 struct access_list
*alist
= output_arg
;
11366 if (access_list_apply(alist
, dest_p
) !=
11370 if (type
== bgp_show_type_filter_list
) {
11371 struct as_list
*as_list
= output_arg
;
11373 if (as_list_apply(as_list
, pi
->attr
->aspath
)
11374 != AS_FILTER_PERMIT
)
11377 if (type
== bgp_show_type_route_map
) {
11378 struct route_map
*rmap
= output_arg
;
11379 struct bgp_path_info path
;
11380 struct bgp_path_info_extra extra
;
11381 struct attr dummy_attr
= {};
11382 route_map_result_t ret
;
11384 dummy_attr
= *pi
->attr
;
11386 prep_for_rmap_apply(&path
, &extra
, dest
, pi
,
11387 pi
->peer
, &dummy_attr
);
11389 ret
= route_map_apply(rmap
, dest_p
, &path
);
11390 bgp_attr_flush(&dummy_attr
);
11391 if (ret
== RMAP_DENYMATCH
)
11394 if (type
== bgp_show_type_neighbor
11395 || type
== bgp_show_type_flap_neighbor
11396 || type
== bgp_show_type_damp_neighbor
) {
11397 union sockunion
*su
= output_arg
;
11399 if (pi
->peer
== NULL
11400 || pi
->peer
->su_remote
== NULL
11401 || !sockunion_same(pi
->peer
->su_remote
, su
))
11404 if (type
== bgp_show_type_cidr_only
) {
11405 uint32_t destination
;
11407 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11408 if (IN_CLASSC(destination
)
11409 && dest_p
->prefixlen
== 24)
11411 if (IN_CLASSB(destination
)
11412 && dest_p
->prefixlen
== 16)
11414 if (IN_CLASSA(destination
)
11415 && dest_p
->prefixlen
== 8)
11418 if (type
== bgp_show_type_prefix_longer
) {
11420 if (!prefix_match(p
, dest_p
))
11423 if (type
== bgp_show_type_community_all
) {
11427 if (type
== bgp_show_type_community
) {
11428 struct community
*com
= output_arg
;
11430 if (!picomm
|| !community_match(picomm
, com
))
11433 if (type
== bgp_show_type_community_exact
) {
11434 struct community
*com
= output_arg
;
11436 if (!picomm
|| !community_cmp(picomm
, com
))
11439 if (type
== bgp_show_type_community_list
) {
11440 struct community_list
*list
= output_arg
;
11442 if (!community_list_match(picomm
, list
))
11445 if (type
== bgp_show_type_community_list_exact
) {
11446 struct community_list
*list
= output_arg
;
11448 if (!community_list_exact_match(picomm
, list
))
11451 if (type
== bgp_show_type_lcommunity
) {
11452 struct lcommunity
*lcom
= output_arg
;
11454 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11456 bgp_attr_get_lcommunity(pi
->attr
),
11461 if (type
== bgp_show_type_lcommunity_exact
) {
11462 struct lcommunity
*lcom
= output_arg
;
11464 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11466 bgp_attr_get_lcommunity(pi
->attr
),
11470 if (type
== bgp_show_type_lcommunity_list
) {
11471 struct community_list
*list
= output_arg
;
11473 if (!lcommunity_list_match(
11474 bgp_attr_get_lcommunity(pi
->attr
),
11479 == bgp_show_type_lcommunity_list_exact
) {
11480 struct community_list
*list
= output_arg
;
11482 if (!lcommunity_list_exact_match(
11483 bgp_attr_get_lcommunity(pi
->attr
),
11487 if (type
== bgp_show_type_lcommunity_all
) {
11488 if (!bgp_attr_get_lcommunity(pi
->attr
))
11491 if (type
== bgp_show_type_dampend_paths
11492 || type
== bgp_show_type_damp_neighbor
) {
11493 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11494 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11497 if (type
== bgp_show_type_self_originated
) {
11498 if (pi
->peer
!= bgp
->peer_self
)
11502 if (!use_json
&& header
) {
11504 "BGP table version is %" PRIu64
11505 ", local router ID is %pI4, vrf id ",
11506 table
->version
, &bgp
->router_id
);
11507 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11508 vty_out(vty
, "%s", VRFID_NONE_STR
);
11510 vty_out(vty
, "%u", bgp
->vrf_id
);
11511 vty_out(vty
, "\n");
11512 vty_out(vty
, "Default local pref %u, ",
11513 bgp
->default_local_pref
);
11514 vty_out(vty
, "local AS ");
11515 vty_out(vty
, ASN_FORMAT(bgp
->asnotation
),
11517 vty_out(vty
, "\n");
11518 if (!detail_routes
) {
11519 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11520 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11521 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11522 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11524 if (type
== bgp_show_type_dampend_paths
11525 || type
== bgp_show_type_damp_neighbor
)
11526 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11527 else if (type
== bgp_show_type_flap_statistics
11528 || type
== bgp_show_type_flap_neighbor
)
11529 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11530 else if (!detail_routes
)
11531 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11532 : BGP_SHOW_HEADER
));
11536 if (rd
!= NULL
&& !display
&& !output_count
) {
11539 "Route Distinguisher: %s\n",
11542 if (type
== bgp_show_type_dampend_paths
11543 || type
== bgp_show_type_damp_neighbor
)
11544 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11545 AFI_IP
, safi
, use_json
,
11547 else if (type
== bgp_show_type_flap_statistics
11548 || type
== bgp_show_type_flap_neighbor
)
11549 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11550 AFI_IP
, safi
, use_json
,
11553 if (detail_routes
|| detail_json
) {
11554 const struct prefix_rd
*prd
= NULL
;
11557 prd
= bgp_rd_from_dest(
11558 dest
->pdest
, safi
);
11561 route_vty_out_detail_header(
11563 bgp_dest_get_prefix(
11565 prd
, table
->afi
, safi
,
11568 route_vty_out_detail(
11569 vty
, bgp
, dest
, dest_p
, pi
,
11570 family2afi(dest_p
->family
),
11571 safi
, RPKI_NOT_BEING_USED
,
11574 route_vty_out(vty
, dest_p
, pi
, display
,
11575 safi
, json_paths
, wide
);
11586 /* encode prefix */
11587 if (dest_p
->family
== AF_FLOWSPEC
) {
11588 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11591 bgp_fs_nlri_get_string(
11593 dest_p
->u
.prefix_flowspec
.ptr
,
11594 dest_p
->u
.prefix_flowspec
.prefixlen
,
11595 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11596 family2afi(dest_p
->u
11597 .prefix_flowspec
.family
));
11599 vty_out(vty
, "\"%s/%d\": ", retstr
,
11600 dest_p
->u
.prefix_flowspec
11603 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11604 dest_p
->u
.prefix_flowspec
11608 vty_out(vty
, "\"%pFX\": ", dest_p
);
11610 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11613 if (json_detail_header
&& json_paths
!= NULL
) {
11614 const struct prefix_rd
*prd
;
11616 vty_out(vty
, "{\n");
11618 prd
= bgp_rd_from_dest(dest
, safi
);
11620 route_vty_out_detail_header(
11622 bgp_dest_get_prefix(dest
), prd
,
11623 table
->afi
, safi
, json_paths
, true);
11625 vty_out(vty
, "\"paths\": ");
11626 json_detail_header_used
= true;
11630 * We are using no_pretty here because under
11631 * extremely high settings( say lots and lots of
11632 * routes with lots and lots of ways to reach
11633 * that route via different paths ) this can
11634 * save several minutes of output when FRR
11635 * is run on older cpu's or more underperforming
11636 * routers out there
11638 vty_json_no_pretty(vty
, json_paths
);
11640 if (json_detail_header_used
)
11641 vty_out(vty
, "} ");
11646 json_object_free(json_paths
);
11650 output_count
+= *output_cum
;
11651 *output_cum
= output_count
;
11654 total_count
+= *total_cum
;
11655 *total_cum
= total_count
;
11659 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11663 for (i
= 0; i
< *json_header_depth
; ++i
)
11664 vty_out(vty
, " } ");
11666 vty_out(vty
, "\n");
11670 /* No route is displayed */
11671 if (output_count
== 0) {
11672 if (type
== bgp_show_type_normal
)
11674 "No BGP prefixes displayed, %ld exist\n",
11678 "\nDisplayed %ld routes and %ld total paths\n",
11679 output_count
, total_count
);
11683 return CMD_SUCCESS
;
11686 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11687 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11688 enum bgp_show_type type
, void *output_arg
,
11689 uint16_t show_flags
)
11691 struct bgp_dest
*dest
, *next
;
11692 unsigned long output_cum
= 0;
11693 unsigned long total_cum
= 0;
11694 unsigned long json_header_depth
= 0;
11695 struct bgp_table
*itable
;
11697 bool use_json
= !!CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11699 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11701 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11702 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11704 next
= bgp_route_next(dest
);
11705 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11708 itable
= bgp_dest_get_bgp_table_info(dest
);
11709 if (itable
!= NULL
) {
11710 struct prefix_rd prd
;
11711 char rd
[RD_ADDRSTRLEN
];
11713 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11714 prefix_rd2str(&prd
, rd
, sizeof(rd
), bgp
->asnotation
);
11715 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11716 rd
, next
== NULL
, &output_cum
,
11717 &total_cum
, &json_header_depth
,
11718 show_flags
, RPKI_NOT_BEING_USED
);
11724 if (output_cum
== 0)
11725 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11729 "\nDisplayed %ld routes and %ld total paths\n",
11730 output_cum
, total_cum
);
11732 if (use_json
&& output_cum
== 0)
11733 vty_out(vty
, "{}\n");
11735 return CMD_SUCCESS
;
11738 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11739 enum bgp_show_type type
, void *output_arg
,
11740 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11742 struct bgp_table
*table
;
11743 unsigned long json_header_depth
= 0;
11744 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11747 bgp
= bgp_get_default();
11752 vty_out(vty
, "No BGP process is configured\n");
11754 vty_out(vty
, "{}\n");
11755 return CMD_WARNING
;
11758 /* Labeled-unicast routes live in the unicast table. */
11759 if (safi
== SAFI_LABELED_UNICAST
)
11760 safi
= SAFI_UNICAST
;
11762 table
= bgp
->rib
[afi
][safi
];
11763 /* use MPLS and ENCAP specific shows until they are merged */
11764 if (safi
== SAFI_MPLS_VPN
) {
11765 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11766 output_arg
, show_flags
);
11769 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11770 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11771 output_arg
, use_json
,
11775 if (safi
== SAFI_EVPN
)
11776 return bgp_evpn_show_all_routes(vty
, bgp
, type
, use_json
, 0);
11778 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11779 NULL
, NULL
, &json_header_depth
, show_flags
,
11780 rpki_target_state
);
11783 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11784 safi_t safi
, uint16_t show_flags
)
11786 struct listnode
*node
, *nnode
;
11789 bool route_output
= false;
11790 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11793 vty_out(vty
, "{\n");
11795 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11796 route_output
= true;
11799 vty_out(vty
, ",\n");
11803 vty_out(vty
, "\"%s\":",
11804 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11808 vty_out(vty
, "\nInstance %s:\n",
11809 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11813 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11814 show_flags
, RPKI_NOT_BEING_USED
);
11818 vty_out(vty
, "}\n");
11819 else if (!route_output
)
11820 vty_out(vty
, "%% BGP instance not found\n");
11823 /* Header of detailed BGP route information */
11824 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11825 struct bgp_dest
*dest
, const struct prefix
*p
,
11826 const struct prefix_rd
*prd
, afi_t afi
,
11827 safi_t safi
, json_object
*json
,
11828 bool incremental_print
)
11830 struct bgp_path_info
*pi
;
11832 struct listnode
*node
, *nnode
;
11833 char buf1
[RD_ADDRSTRLEN
];
11837 int accept_own
= 0;
11838 int route_filter_translated_v4
= 0;
11839 int route_filter_v4
= 0;
11840 int route_filter_translated_v6
= 0;
11841 int route_filter_v6
= 0;
11842 int llgr_stale
= 0;
11844 int accept_own_nexthop
= 0;
11847 int no_advertise
= 0;
11851 int has_valid_label
= 0;
11852 mpls_label_t label
= 0;
11853 json_object
*json_adv_to
= NULL
;
11858 mpls_lse_decode(dest
->local_label
, &label
, &ttl
, &exp
, &bos
);
11860 has_valid_label
= bgp_is_valid_label(&label
);
11862 if (safi
== SAFI_EVPN
) {
11864 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11865 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
),
11868 prd
? ":" : "", (struct prefix_evpn
*)p
);
11870 json_object_string_add(
11872 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
),
11875 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11880 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11882 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11883 ? prefix_rd2str(prd
, buf1
,
11887 safi
== SAFI_MPLS_VPN
? ":" : "", p
,
11891 if (incremental_print
) {
11892 vty_out(vty
, "\"prefix\": \"%pFX\",\n", p
);
11893 vty_out(vty
, "\"version\": \"%" PRIu64
"\",\n",
11896 json_object_string_addf(json
, "prefix", "%pFX",
11898 json_object_int_add(json
, "version",
11904 if (has_valid_label
) {
11906 if (incremental_print
)
11907 vty_out(vty
, "\"localLabel\": \"%u\",\n",
11910 json_object_int_add(json
, "localLabel", label
);
11912 vty_out(vty
, "Local label: %d\n", label
);
11916 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11917 vty_out(vty
, "not allocated\n");
11919 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11920 struct community
*picomm
= NULL
;
11922 picomm
= bgp_attr_get_community(pi
->attr
);
11925 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11927 if (bgp_path_suppressed(pi
))
11933 no_advertise
+= community_include(
11934 picomm
, COMMUNITY_NO_ADVERTISE
);
11936 community_include(picomm
, COMMUNITY_NO_EXPORT
);
11938 community_include(picomm
, COMMUNITY_LOCAL_AS
);
11940 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
11941 route_filter_translated_v4
+= community_include(
11942 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11943 route_filter_translated_v6
+= community_include(
11944 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11945 route_filter_v4
+= community_include(
11946 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
11947 route_filter_v6
+= community_include(
11948 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
11950 community_include(picomm
, COMMUNITY_LLGR_STALE
);
11951 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
11952 accept_own_nexthop
+= community_include(
11953 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11955 community_include(picomm
, COMMUNITY_BLACKHOLE
);
11956 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
11961 vty_out(vty
, "Paths: (%d available", count
);
11963 vty_out(vty
, ", best #%d", best
);
11964 if (safi
== SAFI_UNICAST
) {
11965 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11966 vty_out(vty
, ", table %s",
11969 vty_out(vty
, ", vrf %s",
11973 vty_out(vty
, ", no best path");
11977 ", accept own local route exported and imported in different VRF");
11978 else if (route_filter_translated_v4
)
11980 ", mark translated RTs for VPNv4 route filtering");
11981 else if (route_filter_v4
)
11983 ", attach RT as-is for VPNv4 route filtering");
11984 else if (route_filter_translated_v6
)
11986 ", mark translated RTs for VPNv6 route filtering");
11987 else if (route_filter_v6
)
11989 ", attach RT as-is for VPNv6 route filtering");
11990 else if (llgr_stale
)
11992 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
11995 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11996 else if (accept_own_nexthop
)
11998 ", accept local nexthop");
11999 else if (blackhole
)
12000 vty_out(vty
, ", inform peer to blackhole prefix");
12001 else if (no_export
)
12002 vty_out(vty
, ", not advertised to EBGP peer");
12003 else if (no_advertise
)
12004 vty_out(vty
, ", not advertised to any peer");
12006 vty_out(vty
, ", not advertised outside local AS");
12009 ", inform EBGP peer not to advertise to their EBGP peers");
12013 ", Advertisements suppressed by an aggregate.");
12014 vty_out(vty
, ")\n");
12017 /* If we are not using addpath then we can display Advertised to and
12019 * show what peers we advertised the bestpath to. If we are using
12021 * though then we must display Advertised to on a path-by-path basis. */
12022 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
12023 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
12024 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
12025 if (json
&& !json_adv_to
)
12026 json_adv_to
= json_object_new_object();
12028 route_vty_out_advertised_to(
12030 " Advertised to non peer-group peers:\n ",
12035 if (json
&& json_adv_to
) {
12036 if (incremental_print
) {
12037 vty_out(vty
, "\"advertisedTo\": ");
12038 vty_json(vty
, json_adv_to
);
12041 json_object_object_add(json
, "advertisedTo",
12044 if (!json
&& first
)
12045 vty_out(vty
, " Not advertised to any peer");
12046 vty_out(vty
, "\n");
12051 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
12052 struct bgp_dest
*bgp_node
, struct vty
*vty
,
12053 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
12054 json_object
*json
, enum bgp_path_type pathtype
,
12055 int *display
, enum rpki_states rpki_target_state
)
12057 struct bgp_path_info
*pi
;
12059 json_object
*json_header
= NULL
;
12060 json_object
*json_paths
= NULL
;
12061 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
12063 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
12064 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
12066 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
12067 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
12068 pi
->peer
, pi
->attr
, p
);
12070 if (rpki_target_state
!= RPKI_NOT_BEING_USED
12071 && rpki_curr_state
!= rpki_target_state
)
12074 if (json
&& !json_paths
) {
12075 /* Instantiate json_paths only if path is valid */
12076 json_paths
= json_object_new_array();
12078 json_header
= json_object_new_object();
12080 json_header
= json
;
12084 route_vty_out_detail_header(
12085 vty
, bgp
, bgp_node
,
12086 bgp_dest_get_prefix(bgp_node
), pfx_rd
, AFI_IP
,
12087 safi
, json_header
, false);
12092 if (pathtype
== BGP_PATH_SHOW_ALL
12093 || (pathtype
== BGP_PATH_SHOW_BESTPATH
12094 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12095 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
12096 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
12097 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
12098 route_vty_out_detail(vty
, bgp
, bgp_node
,
12099 bgp_dest_get_prefix(bgp_node
), pi
,
12100 AFI_IP
, safi
, rpki_curr_state
,
12104 if (json
&& json_paths
) {
12105 json_object_object_add(json_header
, "paths", json_paths
);
12108 json_object_object_addf(
12110 BGP_RD_AS_FORMAT(bgp
->asnotation
), pfx_rd
);
12115 * Return rd based on safi
12117 const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
12121 case SAFI_MPLS_VPN
:
12124 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
12127 case SAFI_MULTICAST
:
12128 case SAFI_LABELED_UNICAST
:
12129 case SAFI_FLOWSPEC
:
12134 assert(!"Reached end of function when we were not expecting it");
12137 /* Display specified route of BGP table. */
12138 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
12139 struct bgp_table
*rib
, const char *ip_str
,
12140 afi_t afi
, safi_t safi
,
12141 enum rpki_states rpki_target_state
,
12142 struct prefix_rd
*prd
, int prefix_check
,
12143 enum bgp_path_type pathtype
, bool use_json
)
12147 struct prefix match
;
12148 struct bgp_dest
*dest
;
12149 struct bgp_dest
*rm
;
12150 struct bgp_table
*table
;
12151 json_object
*json
= NULL
;
12152 json_object
*json_paths
= NULL
;
12154 /* Check IP address argument. */
12155 ret
= str2prefix(ip_str
, &match
);
12157 vty_out(vty
, "address is malformed\n");
12158 return CMD_WARNING
;
12161 match
.family
= afi2family(afi
);
12164 json
= json_object_new_object();
12166 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
12167 for (dest
= bgp_table_top(rib
); dest
;
12168 dest
= bgp_route_next(dest
)) {
12169 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12171 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
12173 table
= bgp_dest_get_bgp_table_info(dest
);
12177 rm
= bgp_node_match(table
, &match
);
12181 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
12183 && rm_p
->prefixlen
!= match
.prefixlen
) {
12184 bgp_dest_unlock_node(rm
);
12188 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12189 bgp
, afi
, safi
, json
, pathtype
,
12190 &display
, rpki_target_state
);
12192 bgp_dest_unlock_node(rm
);
12194 } else if (safi
== SAFI_EVPN
) {
12195 struct bgp_dest
*longest_pfx
;
12196 bool is_exact_pfxlen_match
= false;
12198 for (dest
= bgp_table_top(rib
); dest
;
12199 dest
= bgp_route_next(dest
)) {
12200 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12202 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
12204 table
= bgp_dest_get_bgp_table_info(dest
);
12208 longest_pfx
= NULL
;
12209 is_exact_pfxlen_match
= false;
12211 * Search through all the prefixes for a match. The
12212 * pfx's are enumerated in ascending order of pfxlens.
12213 * So, the last pfx match is the longest match. Set
12214 * is_exact_pfxlen_match when we get exact pfxlen match
12216 for (rm
= bgp_table_top(table
); rm
;
12217 rm
= bgp_route_next(rm
)) {
12218 const struct prefix
*rm_p
=
12219 bgp_dest_get_prefix(rm
);
12221 * Get prefixlen of the ip-prefix within type5
12224 if (evpn_type5_prefix_match(rm_p
, &match
)
12228 bgp_evpn_get_type5_prefixlen(
12230 if (type5_pfxlen
== match
.prefixlen
) {
12231 is_exact_pfxlen_match
= true;
12232 bgp_dest_unlock_node(rm
);
12241 if (prefix_check
&& !is_exact_pfxlen_match
)
12245 bgp_dest_lock_node(rm
);
12247 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12248 bgp
, afi
, safi
, json
, pathtype
,
12249 &display
, rpki_target_state
);
12251 bgp_dest_unlock_node(rm
);
12253 } else if (safi
== SAFI_FLOWSPEC
) {
12255 json_paths
= json_object_new_array();
12257 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
12258 &match
, prefix_check
,
12264 json_object_object_add(json
, "paths",
12267 json_object_free(json_paths
);
12270 dest
= bgp_node_match(rib
, &match
);
12271 if (dest
!= NULL
) {
12272 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12274 || dest_p
->prefixlen
== match
.prefixlen
) {
12275 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
12276 safi
, json
, pathtype
,
12277 &display
, rpki_target_state
);
12280 bgp_dest_unlock_node(dest
);
12285 vty_json(vty
, json
);
12288 vty_out(vty
, "%% Network not in table\n");
12289 return CMD_WARNING
;
12293 return CMD_SUCCESS
;
12296 /* Display specified route of Main RIB */
12297 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
12298 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
12299 int prefix_check
, enum bgp_path_type pathtype
,
12300 enum rpki_states rpki_target_state
, bool use_json
)
12303 bgp
= bgp_get_default();
12306 vty_out(vty
, "No BGP process is configured\n");
12308 vty_out(vty
, "{}\n");
12309 return CMD_WARNING
;
12313 /* labeled-unicast routes live in the unicast table */
12314 if (safi
== SAFI_LABELED_UNICAST
)
12315 safi
= SAFI_UNICAST
;
12317 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
12318 afi
, safi
, rpki_target_state
, prd
,
12319 prefix_check
, pathtype
, use_json
);
12322 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
12323 struct cmd_token
**argv
, bool exact
, afi_t afi
,
12324 safi_t safi
, bool uj
)
12326 struct lcommunity
*lcom
;
12331 uint16_t show_flags
= 0;
12335 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12337 b
= buffer_new(1024);
12338 for (i
= 0; i
< argc
; i
++) {
12340 buffer_putc(b
, ' ');
12342 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
12344 buffer_putstr(b
, argv
[i
]->arg
);
12348 buffer_putc(b
, '\0');
12350 str
= buffer_getstr(b
);
12353 lcom
= lcommunity_str2com(str
);
12354 XFREE(MTYPE_TMP
, str
);
12356 vty_out(vty
, "%% Large-community malformed\n");
12357 return CMD_WARNING
;
12360 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12361 (exact
? bgp_show_type_lcommunity_exact
12362 : bgp_show_type_lcommunity
),
12363 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
12365 lcommunity_free(&lcom
);
12369 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
12370 const char *lcom
, bool exact
, afi_t afi
,
12371 safi_t safi
, bool uj
)
12373 struct community_list
*list
;
12374 uint16_t show_flags
= 0;
12377 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12380 list
= community_list_lookup(bgp_clist
, lcom
, 0,
12381 LARGE_COMMUNITY_LIST_MASTER
);
12382 if (list
== NULL
) {
12383 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
12385 return CMD_WARNING
;
12388 return bgp_show(vty
, bgp
, afi
, safi
,
12389 (exact
? bgp_show_type_lcommunity_list_exact
12390 : bgp_show_type_lcommunity_list
),
12391 list
, show_flags
, RPKI_NOT_BEING_USED
);
12394 DEFUN (show_ip_bgp_large_community_list
,
12395 show_ip_bgp_large_community_list_cmd
,
12396 "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]",
12400 BGP_INSTANCE_HELP_STR
12402 BGP_SAFI_WITH_LABEL_HELP_STR
12403 "Display routes matching the large-community-list\n"
12404 "large-community-list number\n"
12405 "large-community-list name\n"
12406 "Exact match of the large-communities\n"
12409 afi_t afi
= AFI_IP6
;
12410 safi_t safi
= SAFI_UNICAST
;
12412 bool exact_match
= 0;
12413 struct bgp
*bgp
= NULL
;
12414 bool uj
= use_json(argc
, argv
);
12419 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12422 return CMD_WARNING
;
12424 argv_find(argv
, argc
, "large-community-list", &idx
);
12426 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12428 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
12431 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
12432 exact_match
, afi
, safi
, uj
);
12434 DEFUN (show_ip_bgp_large_community
,
12435 show_ip_bgp_large_community_cmd
,
12436 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
12440 BGP_INSTANCE_HELP_STR
12442 BGP_SAFI_WITH_LABEL_HELP_STR
12443 "Display routes matching the large-communities\n"
12444 "List of large-community numbers\n"
12445 "Exact match of the large-communities\n"
12448 afi_t afi
= AFI_IP6
;
12449 safi_t safi
= SAFI_UNICAST
;
12451 bool exact_match
= 0;
12452 struct bgp
*bgp
= NULL
;
12453 bool uj
= use_json(argc
, argv
);
12454 uint16_t show_flags
= 0;
12458 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12461 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12464 return CMD_WARNING
;
12466 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12467 if (argv_find(argv
, argc
, "exact-match", &idx
)) {
12471 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12472 exact_match
, afi
, safi
, uj
);
12474 return bgp_show(vty
, bgp
, afi
, safi
,
12475 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12476 RPKI_NOT_BEING_USED
);
12479 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12480 safi_t safi
, struct json_object
*json_array
);
12481 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12482 safi_t safi
, struct json_object
*json
);
12485 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12486 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12487 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12488 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12490 bool uj
= use_json(argc
, argv
);
12491 struct bgp
*bgp
= NULL
;
12492 safi_t safi
= SAFI_UNICAST
;
12493 afi_t afi
= AFI_IP6
;
12495 struct json_object
*json_all
= NULL
;
12496 struct json_object
*json_afi_safi
= NULL
;
12498 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12501 return CMD_WARNING
;
12504 json_all
= json_object_new_object();
12506 FOREACH_AFI_SAFI (afi
, safi
) {
12508 * So limit output to those afi/safi pairs that
12509 * actually have something interesting in them
12511 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12516 json_afi_safi
= json_object_new_array();
12517 json_object_object_add(
12519 get_afi_safi_str(afi
, safi
, true),
12522 json_afi_safi
= NULL
;
12525 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12529 vty_json(vty
, json_all
);
12531 return CMD_SUCCESS
;
12534 /* BGP route print out function without JSON */
12535 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12536 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12537 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12541 BGP_INSTANCE_HELP_STR
12544 "BGP RIB advertisement statistics\n"
12547 afi_t afi
= AFI_IP6
;
12548 safi_t safi
= SAFI_UNICAST
;
12549 struct bgp
*bgp
= NULL
;
12551 bool uj
= use_json(argc
, argv
);
12552 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12554 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12557 return CMD_WARNING
;
12560 json_afi_safi
= json_object_new_array();
12562 json_afi_safi
= NULL
;
12564 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12567 json
= json_object_new_object();
12568 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12570 vty_json(vty
, json
);
12575 /* BGP route print out function without JSON */
12576 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12577 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12578 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12580 statistics [json]",
12581 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12582 BGP_SAFI_WITH_LABEL_HELP_STR
12583 "BGP RIB advertisement statistics\n" JSON_STR
)
12585 afi_t afi
= AFI_IP6
;
12586 safi_t safi
= SAFI_UNICAST
;
12587 struct bgp
*bgp
= NULL
;
12589 bool uj
= use_json(argc
, argv
);
12590 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12592 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12595 return CMD_WARNING
;
12598 json_afi_safi
= json_object_new_array();
12600 json_afi_safi
= NULL
;
12602 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12605 json
= json_object_new_object();
12606 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12608 vty_json(vty
, json
);
12613 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12614 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12615 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12616 "]] [all$all] dampening parameters [json]",
12617 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12618 BGP_SAFI_WITH_LABEL_HELP_STR
12619 "Display the entries for all address families\n"
12620 "Display detailed information about dampening\n"
12621 "Display detail of configured dampening parameters\n"
12624 afi_t afi
= AFI_IP6
;
12625 safi_t safi
= SAFI_UNICAST
;
12626 struct bgp
*bgp
= NULL
;
12628 uint16_t show_flags
= 0;
12629 bool uj
= use_json(argc
, argv
);
12633 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12636 /* [<ipv4|ipv6> [all]] */
12638 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12639 if (argv_find(argv
, argc
, "ipv4", &idx
))
12640 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12642 if (argv_find(argv
, argc
, "ipv6", &idx
))
12643 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12646 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12649 return CMD_WARNING
;
12651 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12654 /* BGP route print out function */
12655 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12656 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12657 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12661 |dampening <flap-statistics|dampened-paths>\
12662 |community [AA:NN|local-AS|no-advertise|no-export\
12663 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12664 |accept-own|accept-own-nexthop|route-filter-v6\
12665 |route-filter-v4|route-filter-translated-v6\
12666 |route-filter-translated-v4] [exact-match]\
12667 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12668 |filter-list AS_PATH_FILTER_NAME\
12670 |access-list ACCESSLIST_NAME\
12671 |route-map RMAP_NAME\
12672 |rpki <invalid|valid|notfound>\
12673 |version (1-4294967295)\
12675 |A.B.C.D/M longer-prefixes\
12676 |X:X::X:X/M longer-prefixes\
12677 |"BGP_SELF_ORIG_CMD_STR
"\
12678 |detail-routes$detail_routes\
12679 ] [json$uj [detail$detail_json] | wide$wide]",
12680 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12681 BGP_SAFI_WITH_LABEL_HELP_STR
12682 "Display the entries for all address families\n"
12683 "Display only routes with non-natural netmasks\n"
12684 "Display detailed information about dampening\n"
12685 "Display flap statistics of routes\n"
12686 "Display paths suppressed due to dampening\n"
12687 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12688 "Do not send outside local AS (well-known community)\n"
12689 "Do not advertise to any peer (well-known community)\n"
12690 "Do not export to next AS (well-known community)\n"
12691 "Graceful shutdown (well-known community)\n"
12692 "Do not export to any peer (well-known community)\n"
12693 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12694 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12695 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12696 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12697 "Should accept VPN route with local nexthop (well-known community)\n"
12698 "RT VPNv6 route filtering (well-known community)\n"
12699 "RT VPNv4 route filtering (well-known community)\n"
12700 "RT translated VPNv6 route filtering (well-known community)\n"
12701 "RT translated VPNv4 route filtering (well-known community)\n"
12702 "Exact match of the communities\n"
12703 "Community-list number\n"
12704 "Community-list name\n"
12705 "Display routes matching the community-list\n"
12706 "Exact match of the communities\n"
12707 "Display routes conforming to the filter-list\n"
12708 "Regular expression access list name\n"
12709 "Display routes conforming to the prefix-list\n"
12710 "Prefix-list name\n"
12711 "Display routes conforming to the access-list\n"
12712 "Access-list name\n"
12713 "Display routes matching the route-map\n"
12714 "A route-map to match on\n"
12715 "RPKI route types\n"
12716 "A valid path as determined by rpki\n"
12717 "A invalid path as determined by rpki\n"
12718 "A path that has no rpki data\n"
12719 "Display prefixes with matching version numbers\n"
12720 "Version number and above\n"
12721 "Display prefixes with matching BGP community alias\n"
12722 "BGP community alias\n"
12724 "Display route and more specific routes\n"
12726 "Display route and more specific routes\n"
12727 BGP_SELF_ORIG_HELP_STR
12728 "Display detailed version of all routes\n"
12730 "Display detailed version of JSON output\n"
12731 "Increase table width for longer prefixes\n")
12733 afi_t afi
= AFI_IP6
;
12734 safi_t safi
= SAFI_UNICAST
;
12735 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12736 void *output_arg
= NULL
;
12737 struct bgp
*bgp
= NULL
;
12739 int exact_match
= 0;
12740 char *community
= NULL
;
12742 uint16_t show_flags
= 0;
12743 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12748 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12752 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
12755 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
12757 /* [<ipv4|ipv6> [all]] */
12759 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12761 if (argv_find(argv
, argc
, "ipv4", &idx
))
12762 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12764 if (argv_find(argv
, argc
, "ipv6", &idx
))
12765 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12769 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12771 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12774 return CMD_WARNING
;
12776 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12777 sh_type
= bgp_show_type_cidr_only
;
12779 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12780 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12781 sh_type
= bgp_show_type_dampend_paths
;
12782 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12783 sh_type
= bgp_show_type_flap_statistics
;
12786 if (argv_find(argv
, argc
, "community", &idx
)) {
12787 char *maybecomm
= NULL
;
12789 if (idx
+ 1 < argc
) {
12790 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12791 maybecomm
= argv
[idx
+ 1]->arg
;
12793 maybecomm
= argv
[idx
+ 1]->text
;
12796 if (maybecomm
&& !strmatch(maybecomm
, "json")
12797 && !strmatch(maybecomm
, "exact-match"))
12798 community
= maybecomm
;
12800 if (argv_find(argv
, argc
, "exact-match", &idx
))
12804 sh_type
= bgp_show_type_community_all
;
12807 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12808 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12809 struct community_list
*list
;
12811 if (argv_find(argv
, argc
, "exact-match", &idx
))
12814 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12815 COMMUNITY_LIST_MASTER
);
12816 if (list
== NULL
) {
12817 vty_out(vty
, "%% %s community-list not found\n",
12818 clist_number_or_name
);
12819 return CMD_WARNING
;
12823 sh_type
= bgp_show_type_community_list_exact
;
12825 sh_type
= bgp_show_type_community_list
;
12829 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12830 const char *filter
= argv
[++idx
]->arg
;
12831 struct as_list
*as_list
;
12833 as_list
= as_list_lookup(filter
);
12834 if (as_list
== NULL
) {
12835 vty_out(vty
, "%% %s AS-path access-list not found\n",
12837 return CMD_WARNING
;
12840 sh_type
= bgp_show_type_filter_list
;
12841 output_arg
= as_list
;
12844 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12845 const char *prefix_list_str
= argv
[++idx
]->arg
;
12846 struct prefix_list
*plist
;
12848 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12849 if (plist
== NULL
) {
12850 vty_out(vty
, "%% %s prefix-list not found\n",
12852 return CMD_WARNING
;
12855 sh_type
= bgp_show_type_prefix_list
;
12856 output_arg
= plist
;
12859 if (argv_find(argv
, argc
, "access-list", &idx
)) {
12860 const char *access_list_str
= argv
[++idx
]->arg
;
12861 struct access_list
*alist
;
12863 alist
= access_list_lookup(afi
, access_list_str
);
12865 vty_out(vty
, "%% %s access-list not found\n",
12867 return CMD_WARNING
;
12870 sh_type
= bgp_show_type_access_list
;
12871 output_arg
= alist
;
12874 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12875 const char *rmap_str
= argv
[++idx
]->arg
;
12876 struct route_map
*rmap
;
12878 rmap
= route_map_lookup_by_name(rmap_str
);
12880 vty_out(vty
, "%% %s route-map not found\n", rmap_str
);
12881 return CMD_WARNING
;
12884 sh_type
= bgp_show_type_route_map
;
12888 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12889 sh_type
= bgp_show_type_rpki
;
12890 if (argv_find(argv
, argc
, "valid", &idx
))
12891 rpki_target_state
= RPKI_VALID
;
12892 else if (argv_find(argv
, argc
, "invalid", &idx
))
12893 rpki_target_state
= RPKI_INVALID
;
12896 /* Display prefixes with matching version numbers */
12897 if (argv_find(argv
, argc
, "version", &idx
)) {
12898 sh_type
= bgp_show_type_prefix_version
;
12899 output_arg
= argv
[idx
+ 1]->arg
;
12902 /* Display prefixes with matching BGP community alias */
12903 if (argv_find(argv
, argc
, "alias", &idx
)) {
12904 sh_type
= bgp_show_type_community_alias
;
12905 output_arg
= argv
[idx
+ 1]->arg
;
12908 /* prefix-longer */
12909 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12910 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12911 const char *prefix_str
= argv
[idx
]->arg
;
12913 if (!str2prefix(prefix_str
, &p
)) {
12914 vty_out(vty
, "%% Malformed Prefix\n");
12915 return CMD_WARNING
;
12918 sh_type
= bgp_show_type_prefix_longer
;
12922 /* self originated only */
12923 if (argv_find(argv
, argc
, BGP_SELF_ORIG_CMD_STR
, &idx
))
12924 sh_type
= bgp_show_type_self_originated
;
12927 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12929 return bgp_show_community(vty
, bgp
, community
,
12930 exact_match
, afi
, safi
,
12933 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12934 output_arg
, show_flags
,
12935 rpki_target_state
);
12937 struct listnode
*node
;
12939 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12943 vty_out(vty
, "{\n");
12945 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12946 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12947 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12950 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12951 FOREACH_SAFI (safi
) {
12952 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12960 vty_out(vty
, ",\n");
12961 vty_out(vty
, "\"%s\":{\n",
12962 get_afi_safi_str(afi
,
12967 "\nFor address family: %s\n",
12973 bgp_show_community(
12974 vty
, abgp
, community
,
12975 exact_match
, afi
, safi
,
12978 bgp_show(vty
, abgp
, afi
, safi
,
12979 sh_type
, output_arg
,
12981 rpki_target_state
);
12983 vty_out(vty
, "}\n");
12987 /* show <ip> bgp all: for each AFI and SAFI*/
12988 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12989 FOREACH_AFI_SAFI (afi
, safi
) {
12990 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12998 vty_out(vty
, ",\n");
13000 vty_out(vty
, "\"%s\":{\n",
13001 get_afi_safi_str(afi
,
13006 "\nFor address family: %s\n",
13012 bgp_show_community(
13013 vty
, abgp
, community
,
13014 exact_match
, afi
, safi
,
13017 bgp_show(vty
, abgp
, afi
, safi
,
13018 sh_type
, output_arg
,
13020 rpki_target_state
);
13022 vty_out(vty
, "}\n");
13027 vty_out(vty
, "}\n");
13029 return CMD_SUCCESS
;
13032 DEFUN (show_ip_bgp_route
,
13033 show_ip_bgp_route_cmd
,
13034 "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]",
13038 BGP_INSTANCE_HELP_STR
13040 BGP_SAFI_WITH_LABEL_HELP_STR
13041 "Network in the BGP routing table to display\n"
13043 "Network in the BGP routing table to display\n"
13045 "Display only the bestpath\n"
13046 "Display only multipaths\n"
13047 "Display only paths that match the specified rpki state\n"
13048 "A valid path as determined by rpki\n"
13049 "A invalid path as determined by rpki\n"
13050 "A path that has no rpki data\n"
13053 int prefix_check
= 0;
13055 afi_t afi
= AFI_IP6
;
13056 safi_t safi
= SAFI_UNICAST
;
13057 char *prefix
= NULL
;
13058 struct bgp
*bgp
= NULL
;
13059 enum bgp_path_type path_type
;
13060 bool uj
= use_json(argc
, argv
);
13064 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13067 return CMD_WARNING
;
13071 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13072 return CMD_WARNING
;
13075 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13076 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
13077 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
13079 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
13080 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
13083 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
13084 && afi
!= AFI_IP6
) {
13086 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13087 return CMD_WARNING
;
13089 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
13090 && afi
!= AFI_IP
) {
13092 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13093 return CMD_WARNING
;
13096 prefix
= argv
[idx
]->arg
;
13098 /* [<bestpath|multipath>] */
13099 if (argv_find(argv
, argc
, "bestpath", &idx
))
13100 path_type
= BGP_PATH_SHOW_BESTPATH
;
13101 else if (argv_find(argv
, argc
, "multipath", &idx
))
13102 path_type
= BGP_PATH_SHOW_MULTIPATH
;
13104 path_type
= BGP_PATH_SHOW_ALL
;
13106 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
13107 path_type
, RPKI_NOT_BEING_USED
, uj
);
13110 DEFUN (show_ip_bgp_regexp
,
13111 show_ip_bgp_regexp_cmd
,
13112 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
13116 BGP_INSTANCE_HELP_STR
13118 BGP_SAFI_WITH_LABEL_HELP_STR
13119 "Display routes matching the AS path regular expression\n"
13120 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13123 afi_t afi
= AFI_IP6
;
13124 safi_t safi
= SAFI_UNICAST
;
13125 struct bgp
*bgp
= NULL
;
13126 bool uj
= use_json(argc
, argv
);
13127 char *regstr
= NULL
;
13130 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13133 return CMD_WARNING
;
13135 // get index of regex
13136 if (argv_find(argv
, argc
, "REGEX", &idx
))
13137 regstr
= argv
[idx
]->arg
;
13140 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
13141 bgp_show_type_regexp
, uj
);
13144 DEFPY (show_ip_bgp_instance_all
,
13145 show_ip_bgp_instance_all_cmd
,
13146 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
13150 BGP_INSTANCE_ALL_HELP_STR
13152 BGP_SAFI_WITH_LABEL_HELP_STR
13154 "Increase table width for longer prefixes\n")
13156 afi_t afi
= AFI_IP6
;
13157 safi_t safi
= SAFI_UNICAST
;
13158 struct bgp
*bgp
= NULL
;
13160 uint16_t show_flags
= 0;
13164 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13168 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13170 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13173 return CMD_WARNING
;
13175 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
13176 return CMD_SUCCESS
;
13179 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
13180 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
13185 uint16_t show_flags
= 0;
13188 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13190 if (!config_bgp_aspath_validate(regstr
)) {
13191 vty_out(vty
, "Invalid character in REGEX %s\n",
13193 return CMD_WARNING_CONFIG_FAILED
;
13196 regex
= bgp_regcomp(regstr
);
13198 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
13199 return CMD_WARNING
;
13202 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
13203 RPKI_NOT_BEING_USED
);
13204 bgp_regex_free(regex
);
13208 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
13209 const char *comstr
, int exact
, afi_t afi
,
13210 safi_t safi
, uint16_t show_flags
)
13212 struct community
*com
;
13215 com
= community_str2com(comstr
);
13217 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
13218 return CMD_WARNING
;
13221 ret
= bgp_show(vty
, bgp
, afi
, safi
,
13222 (exact
? bgp_show_type_community_exact
13223 : bgp_show_type_community
),
13224 com
, show_flags
, RPKI_NOT_BEING_USED
);
13225 community_free(&com
);
13231 BGP_STATS_MAXBITLEN
= 0,
13233 BGP_STATS_PREFIXES
,
13235 BGP_STATS_UNAGGREGATEABLE
,
13236 BGP_STATS_MAX_AGGREGATEABLE
,
13237 BGP_STATS_AGGREGATES
,
13239 BGP_STATS_ASPATH_COUNT
,
13240 BGP_STATS_ASPATH_MAXHOPS
,
13241 BGP_STATS_ASPATH_TOTHOPS
,
13242 BGP_STATS_ASPATH_MAXSIZE
,
13243 BGP_STATS_ASPATH_TOTSIZE
,
13244 BGP_STATS_ASN_HIGHEST
,
13248 #define TABLE_STATS_IDX_VTY 0
13249 #define TABLE_STATS_IDX_JSON 1
13251 static const char *table_stats_strs
[][2] = {
13252 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
13253 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
13254 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
13255 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
13256 "unaggregateablePrefixes"},
13257 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
13258 "maximumAggregateablePrefixes"},
13259 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
13260 "bgpAggregateAdvertisements"},
13261 [BGP_STATS_SPACE
] = {"Address space advertised",
13262 "addressSpaceAdvertised"},
13263 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
13264 "advertisementsWithPaths"},
13265 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
13267 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
13269 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
13270 "averageAsPathLengthHops"},
13271 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
13272 "averageAsPathSizeBytes"},
13273 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
13274 [BGP_STATS_MAX
] = {NULL
, NULL
}
13277 struct bgp_table_stats
{
13278 struct bgp_table
*table
;
13279 unsigned long long counts
[BGP_STATS_MAX
];
13282 prefix_len_count
[MAX(EVPN_ROUTE_PREFIXLEN
, IPV6_MAX_BITLEN
) +
13285 double total_space
;
13288 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
13289 struct bgp_table_stats
*ts
, unsigned int space
)
13291 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
13292 struct bgp_path_info
*pi
;
13293 const struct prefix
*rn_p
;
13295 if (!bgp_dest_has_bgp_path_info_data(dest
))
13298 rn_p
= bgp_dest_get_prefix(dest
);
13299 ts
->counts
[BGP_STATS_PREFIXES
]++;
13300 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
13302 ts
->prefix_len_count
[rn_p
->prefixlen
]++;
13303 /* check if the prefix is included by any other announcements */
13304 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
13305 pdest
= bgp_dest_parent_nolock(pdest
);
13307 if (pdest
== NULL
|| pdest
== top
) {
13308 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
13309 /* announced address space */
13311 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
13312 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
13313 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
13316 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
13317 ts
->counts
[BGP_STATS_RIB
]++;
13319 if (CHECK_FLAG(pi
->attr
->flag
,
13320 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
13321 ts
->counts
[BGP_STATS_AGGREGATES
]++;
13323 /* as-path stats */
13324 if (pi
->attr
->aspath
) {
13325 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
13326 unsigned int size
= aspath_size(pi
->attr
->aspath
);
13327 as_t highest
= aspath_highest(pi
->attr
->aspath
);
13329 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
13331 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
13332 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
13334 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
13335 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
13337 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
13338 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
13339 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
13340 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
13345 static void bgp_table_stats_walker(struct thread
*t
)
13347 struct bgp_dest
*dest
, *ndest
;
13348 struct bgp_dest
*top
;
13349 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
13350 unsigned int space
= 0;
13352 if (!(top
= bgp_table_top(ts
->table
)))
13355 switch (ts
->table
->afi
) {
13357 space
= IPV4_MAX_BITLEN
;
13360 space
= IPV6_MAX_BITLEN
;
13363 space
= EVPN_ROUTE_PREFIXLEN
;
13370 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
13372 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
13373 if (ts
->table
->safi
== SAFI_MPLS_VPN
13374 || ts
->table
->safi
== SAFI_ENCAP
13375 || ts
->table
->safi
== SAFI_EVPN
) {
13376 struct bgp_table
*table
;
13378 table
= bgp_dest_get_bgp_table_info(dest
);
13382 top
= bgp_table_top(table
);
13383 for (ndest
= bgp_table_top(table
); ndest
;
13384 ndest
= bgp_route_next(ndest
))
13385 bgp_table_stats_rn(ndest
, top
, ts
, space
);
13387 bgp_table_stats_rn(dest
, top
, ts
, space
);
13392 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
13393 struct json_object
*json_array
)
13395 struct listnode
*node
, *nnode
;
13398 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
13399 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13402 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13403 safi_t safi
, struct json_object
*json_array
)
13405 struct bgp_table_stats ts
;
13407 int ret
= CMD_SUCCESS
;
13409 struct json_object
*json
= NULL
;
13410 uint32_t bitlen
= 0;
13411 struct json_object
*json_bitlen
;
13414 json
= json_object_new_object();
13416 if (!bgp
->rib
[afi
][safi
]) {
13417 char warning_msg
[50];
13419 snprintf(warning_msg
, sizeof(warning_msg
),
13420 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
13424 vty_out(vty
, "%s\n", warning_msg
);
13426 json_object_string_add(json
, "warning", warning_msg
);
13429 goto end_table_stats
;
13433 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
13434 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
13436 json_object_string_add(json
, "instance", bgp
->name_pretty
);
13438 /* labeled-unicast routes live in the unicast table */
13439 if (safi
== SAFI_LABELED_UNICAST
)
13440 safi
= SAFI_UNICAST
;
13442 memset(&ts
, 0, sizeof(ts
));
13443 ts
.table
= bgp
->rib
[afi
][safi
];
13444 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
13446 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
13447 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
13448 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
13452 case BGP_STATS_ASPATH_TOTHOPS
:
13453 case BGP_STATS_ASPATH_TOTSIZE
:
13456 temp_buf
, sizeof(temp_buf
), "%12.2f",
13458 ? (float)ts
.counts
[i
]
13460 [BGP_STATS_ASPATH_COUNT
]
13462 vty_out(vty
, "%-30s: %s",
13463 table_stats_strs
[i
]
13464 [TABLE_STATS_IDX_VTY
],
13467 json_object_double_add(
13469 table_stats_strs
[i
]
13470 [TABLE_STATS_IDX_JSON
],
13472 ? (double)ts
.counts
[i
]
13473 / (double)ts
.counts
13474 [BGP_STATS_ASPATH_COUNT
]
13478 case BGP_STATS_TOTPLEN
:
13481 temp_buf
, sizeof(temp_buf
), "%12.2f",
13483 ? (float)ts
.counts
[i
]
13485 [BGP_STATS_PREFIXES
]
13487 vty_out(vty
, "%-30s: %s",
13488 table_stats_strs
[i
]
13489 [TABLE_STATS_IDX_VTY
],
13492 json_object_double_add(
13494 table_stats_strs
[i
]
13495 [TABLE_STATS_IDX_JSON
],
13497 ? (double)ts
.counts
[i
]
13498 / (double)ts
.counts
13499 [BGP_STATS_PREFIXES
]
13503 case BGP_STATS_SPACE
:
13505 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13507 vty_out(vty
, "%-30s: %s\n",
13508 table_stats_strs
[i
]
13509 [TABLE_STATS_IDX_VTY
],
13512 json_object_double_add(
13514 table_stats_strs
[i
]
13515 [TABLE_STATS_IDX_JSON
],
13516 (double)ts
.total_space
);
13518 if (afi
== AFI_IP6
) {
13520 snprintf(temp_buf
, sizeof(temp_buf
),
13523 * pow(2.0, -128 + 32));
13524 vty_out(vty
, "%30s: %s\n",
13525 "/32 equivalent %s\n",
13528 json_object_double_add(
13529 json
, "/32equivalent",
13530 (double)(ts
.total_space
13535 snprintf(temp_buf
, sizeof(temp_buf
),
13538 * pow(2.0, -128 + 48));
13539 vty_out(vty
, "%30s: %s\n",
13540 "/48 equivalent %s\n",
13543 json_object_double_add(
13544 json
, "/48equivalent",
13545 (double)(ts
.total_space
13551 snprintf(temp_buf
, sizeof(temp_buf
),
13553 ts
.total_space
* 100.
13555 vty_out(vty
, "%30s: %s\n",
13556 "% announced ", temp_buf
);
13558 json_object_double_add(
13559 json
, "%announced",
13560 (double)(ts
.total_space
* 100.
13564 snprintf(temp_buf
, sizeof(temp_buf
),
13567 * pow(2.0, -32 + 8));
13568 vty_out(vty
, "%30s: %s\n",
13569 "/8 equivalent ", temp_buf
);
13571 json_object_double_add(
13572 json
, "/8equivalent",
13573 (double)(ts
.total_space
13574 * pow(2.0, -32 + 8)));
13577 snprintf(temp_buf
, sizeof(temp_buf
),
13580 * pow(2.0, -32 + 24));
13581 vty_out(vty
, "%30s: %s\n",
13582 "/24 equivalent ", temp_buf
);
13584 json_object_double_add(
13585 json
, "/24equivalent",
13586 (double)(ts
.total_space
13587 * pow(2.0, -32 + 24)));
13593 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13595 vty_out(vty
, "%-30s: %s",
13596 table_stats_strs
[i
]
13597 [TABLE_STATS_IDX_VTY
],
13600 json_object_int_add(
13602 table_stats_strs
[i
]
13603 [TABLE_STATS_IDX_JSON
],
13608 vty_out(vty
, "\n");
13613 bitlen
= IPV4_MAX_BITLEN
;
13616 bitlen
= IPV6_MAX_BITLEN
;
13619 bitlen
= EVPN_ROUTE_PREFIXLEN
;
13627 json_bitlen
= json_object_new_array();
13629 for (i
= 0; i
<= bitlen
; i
++) {
13630 struct json_object
*ind_bit
= json_object_new_object();
13632 if (!ts
.prefix_len_count
[i
])
13635 snprintf(temp_buf
, sizeof(temp_buf
), "%u", i
);
13636 json_object_int_add(ind_bit
, temp_buf
,
13637 ts
.prefix_len_count
[i
]);
13638 json_object_array_add(json_bitlen
, ind_bit
);
13640 json_object_object_add(json
, "prefixLength", json_bitlen
);
13645 json_object_array_add(json_array
, json
);
13649 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13650 safi_t safi
, struct json_object
*json_array
)
13653 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13654 return CMD_SUCCESS
;
13657 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13669 PCOUNT_BPATH_SELECTED
,
13670 PCOUNT_PFCNT
, /* the figure we display to users */
13674 static const char *const pcount_strs
[] = {
13675 [PCOUNT_ADJ_IN
] = "Adj-in",
13676 [PCOUNT_DAMPED
] = "Damped",
13677 [PCOUNT_REMOVED
] = "Removed",
13678 [PCOUNT_HISTORY
] = "History",
13679 [PCOUNT_STALE
] = "Stale",
13680 [PCOUNT_VALID
] = "Valid",
13681 [PCOUNT_ALL
] = "All RIB",
13682 [PCOUNT_COUNTED
] = "PfxCt counted",
13683 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13684 [PCOUNT_PFCNT
] = "Useable",
13685 [PCOUNT_MAX
] = NULL
,
13688 struct peer_pcounts
{
13689 unsigned int count
[PCOUNT_MAX
];
13690 const struct peer
*peer
;
13691 const struct bgp_table
*table
;
13695 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13697 const struct bgp_adj_in
*ain
;
13698 const struct bgp_path_info
*pi
;
13699 const struct peer
*peer
= pc
->peer
;
13701 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13702 if (ain
->peer
== peer
)
13703 pc
->count
[PCOUNT_ADJ_IN
]++;
13705 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13707 if (pi
->peer
!= peer
)
13710 pc
->count
[PCOUNT_ALL
]++;
13712 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13713 pc
->count
[PCOUNT_DAMPED
]++;
13714 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13715 pc
->count
[PCOUNT_HISTORY
]++;
13716 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13717 pc
->count
[PCOUNT_REMOVED
]++;
13718 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13719 pc
->count
[PCOUNT_STALE
]++;
13720 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13721 pc
->count
[PCOUNT_VALID
]++;
13722 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13723 pc
->count
[PCOUNT_PFCNT
]++;
13724 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13725 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13727 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13728 pc
->count
[PCOUNT_COUNTED
]++;
13729 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13731 EC_LIB_DEVELOPMENT
,
13732 "Attempting to count but flags say it is unusable");
13734 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13736 EC_LIB_DEVELOPMENT
,
13737 "Not counted but flags say we should");
13742 static void bgp_peer_count_walker(struct thread
*t
)
13744 struct bgp_dest
*rn
, *rm
;
13745 const struct bgp_table
*table
;
13746 struct peer_pcounts
*pc
= THREAD_ARG(t
);
13748 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13749 || pc
->safi
== SAFI_EVPN
) {
13750 /* Special handling for 2-level routing tables. */
13751 for (rn
= bgp_table_top(pc
->table
); rn
;
13752 rn
= bgp_route_next(rn
)) {
13753 table
= bgp_dest_get_bgp_table_info(rn
);
13755 for (rm
= bgp_table_top(table
); rm
;
13756 rm
= bgp_route_next(rm
))
13757 bgp_peer_count_proc(rm
, pc
);
13760 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13761 bgp_peer_count_proc(rn
, pc
);
13764 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13765 safi_t safi
, bool use_json
)
13767 struct peer_pcounts pcounts
= {.peer
= peer
};
13769 json_object
*json
= NULL
;
13770 json_object
*json_loop
= NULL
;
13773 json
= json_object_new_object();
13774 json_loop
= json_object_new_object();
13777 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13778 || !peer
->bgp
->rib
[afi
][safi
]) {
13780 json_object_string_add(
13782 "No such neighbor or address family");
13783 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13784 json_object_free(json
);
13785 json_object_free(json_loop
);
13787 vty_out(vty
, "%% No such neighbor or address family\n");
13789 return CMD_WARNING
;
13792 memset(&pcounts
, 0, sizeof(pcounts
));
13793 pcounts
.peer
= peer
;
13794 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13795 pcounts
.safi
= safi
;
13797 /* in-place call via thread subsystem so as to record execution time
13798 * stats for the thread-walk (i.e. ensure this can't be blamed on
13799 * on just vty_read()).
13801 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13804 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13805 json_object_string_add(json
, "multiProtocol",
13806 get_afi_safi_str(afi
, safi
, true));
13807 json_object_int_add(json
, "pfxCounter",
13808 peer
->pcount
[afi
][safi
]);
13810 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13811 json_object_int_add(json_loop
, pcount_strs
[i
],
13814 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13816 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13817 json_object_string_add(json
, "pfxctDriftFor",
13819 json_object_string_add(
13820 json
, "recommended",
13821 "Please report this bug, with the above command output");
13823 vty_json(vty
, json
);
13827 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13828 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13829 peer
->hostname
, peer
->host
,
13830 get_afi_safi_str(afi
, safi
, false));
13832 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13833 get_afi_safi_str(afi
, safi
, false));
13836 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13837 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13839 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13840 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13843 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13844 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13846 "Please report this bug, with the above command output\n");
13850 return CMD_SUCCESS
;
13853 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13854 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13855 "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]",
13859 BGP_INSTANCE_HELP_STR
13862 "Detailed information on TCP and BGP neighbor connections\n"
13863 "Neighbor to display information about\n"
13864 "Neighbor to display information about\n"
13865 "Neighbor on BGP configured interface\n"
13866 "Display detailed prefix count information\n"
13869 afi_t afi
= AFI_IP6
;
13870 safi_t safi
= SAFI_UNICAST
;
13873 struct bgp
*bgp
= NULL
;
13874 bool uj
= use_json(argc
, argv
);
13879 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13882 return CMD_WARNING
;
13884 argv_find(argv
, argc
, "neighbors", &idx
);
13885 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13887 return CMD_WARNING
;
13889 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13892 #ifdef KEEP_OLD_VPN_COMMANDS
13893 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13894 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13895 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13900 "Display information about all VPNv4 NLRIs\n"
13901 "Detailed information on TCP and BGP neighbor connections\n"
13902 "Neighbor to display information about\n"
13903 "Neighbor to display information about\n"
13904 "Neighbor on BGP configured interface\n"
13905 "Display detailed prefix count information\n"
13910 bool uj
= use_json(argc
, argv
);
13912 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13914 return CMD_WARNING
;
13916 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13919 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13920 show_ip_bgp_vpn_all_route_prefix_cmd
,
13921 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13926 "Display information about all VPNv4 NLRIs\n"
13927 "Network in the BGP routing table to display\n"
13928 "Network in the BGP routing table to display\n"
13932 char *network
= NULL
;
13933 struct bgp
*bgp
= bgp_get_default();
13935 vty_out(vty
, "Can't find default instance\n");
13936 return CMD_WARNING
;
13939 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13940 network
= argv
[idx
]->arg
;
13941 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13942 network
= argv
[idx
]->arg
;
13944 vty_out(vty
, "Unable to figure out Network\n");
13945 return CMD_WARNING
;
13948 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13949 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13950 use_json(argc
, argv
));
13952 #endif /* KEEP_OLD_VPN_COMMANDS */
13954 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13955 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13956 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13961 "Network in the BGP routing table to display\n"
13962 "Network in the BGP routing table to display\n"
13963 "Network in the BGP routing table to display\n"
13964 "Network in the BGP routing table to display\n"
13968 char *network
= NULL
;
13969 int prefix_check
= 0;
13971 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13972 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13973 network
= argv
[idx
]->arg
;
13974 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13975 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
13976 network
= argv
[idx
]->arg
;
13979 vty_out(vty
, "Unable to figure out Network\n");
13980 return CMD_WARNING
;
13982 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13983 prefix_check
, BGP_PATH_SHOW_ALL
,
13984 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
13987 static void show_adj_route_header(struct vty
*vty
, struct peer
*peer
,
13988 struct bgp_table
*table
, int *header1
,
13989 int *header2
, json_object
*json
,
13990 json_object
*json_scode
,
13991 json_object
*json_ocode
, bool wide
,
13994 uint64_t version
= table
? table
->version
: 0;
13998 json_object_int_add(json
, "bgpTableVersion", version
);
13999 json_object_string_addf(json
, "bgpLocalRouterId",
14000 "%pI4", &peer
->bgp
->router_id
);
14001 json_object_int_add(json
, "defaultLocPrf",
14002 peer
->bgp
->default_local_pref
);
14003 json_object_int_add(json
, "localAS",
14004 peer
->change_local_as
14005 ? peer
->change_local_as
14007 json_object_object_add(json
, "bgpStatusCodes",
14009 json_object_object_add(json
, "bgpOriginCodes",
14013 "BGP table version is %" PRIu64
14014 ", local router ID is %pI4, vrf id ",
14015 version
, &peer
->bgp
->router_id
);
14016 if (peer
->bgp
->vrf_id
== VRF_UNKNOWN
)
14017 vty_out(vty
, "%s", VRFID_NONE_STR
);
14019 vty_out(vty
, "%u", peer
->bgp
->vrf_id
);
14020 vty_out(vty
, "\n");
14021 vty_out(vty
, "Default local pref %u, ",
14022 peer
->bgp
->default_local_pref
);
14023 vty_out(vty
, "local AS %u\n",
14024 peer
->change_local_as
? peer
->change_local_as
14027 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14028 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14029 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14030 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14036 if (!json
&& !detail
)
14037 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
14038 : BGP_SHOW_HEADER
));
14044 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
14045 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
14046 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
14047 json_object
*json_scode
, json_object
*json_ocode
,
14048 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
14049 const struct prefix
*match
, unsigned long *output_count
,
14050 unsigned long *filtered_count
)
14052 struct bgp_adj_in
*ain
= NULL
;
14053 struct bgp_adj_out
*adj
= NULL
;
14054 struct bgp_dest
*dest
;
14058 struct update_subgroup
*subgrp
;
14059 struct peer_af
*paf
= NULL
;
14060 bool route_filtered
;
14061 bool detail
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14062 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14063 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14064 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14065 || (safi
== SAFI_EVPN
))
14069 json_object
*json_net
= NULL
;
14073 /* If the user supplied a prefix, look for a matching route instead
14074 * of walking the whole table.
14077 dest
= bgp_node_match(table
, match
);
14080 vty_out(vty
, "Network not in table\n");
14084 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
14086 if (rn_p
->prefixlen
!= match
->prefixlen
) {
14088 vty_out(vty
, "Network not in table\n");
14089 bgp_dest_unlock_node(dest
);
14093 if (type
== bgp_show_adj_route_received
||
14094 type
== bgp_show_adj_route_filtered
) {
14095 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14096 if (ain
->peer
== peer
) {
14101 /* bail out if if adj_out is empty, or
14102 * if the prefix isn't in this peer's
14105 if (!ain
|| ain
->peer
!= peer
) {
14107 vty_out(vty
, "Network not in table\n");
14108 bgp_dest_unlock_node(dest
);
14111 } else if (type
== bgp_show_adj_route_advertised
) {
14112 bool peer_found
= false;
14114 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
) {
14115 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14116 if (paf
->peer
== peer
&& adj
->attr
) {
14125 /* bail out if if adj_out is empty, or
14126 * if the prefix isn't in this peer's
14129 if (!paf
|| !peer_found
) {
14131 vty_out(vty
, "Network not in table\n");
14132 bgp_dest_unlock_node(dest
);
14137 ret
= bgp_output_modifier(peer
, rn_p
, &attr
, afi
, safi
,
14140 if (ret
!= RMAP_DENY
) {
14141 show_adj_route_header(vty
, peer
, table
, header1
,
14142 header2
, json
, json_scode
,
14143 json_ocode
, wide
, detail
);
14146 json_net
= json_object_new_object();
14148 bgp_show_path_info(NULL
/* prefix_rd */, dest
, vty
, bgp
,
14149 afi
, safi
, json_net
,
14150 BGP_PATH_SHOW_ALL
, &display
,
14151 RPKI_NOT_BEING_USED
);
14153 json_object_object_addf(json_ar
, json_net
,
14157 (*filtered_count
)++;
14159 bgp_attr_flush(&attr
);
14160 bgp_dest_unlock_node(dest
);
14165 subgrp
= peer_subgroup(peer
, afi
, safi
);
14167 if (type
== bgp_show_adj_route_advertised
&& subgrp
14168 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
14170 json_object_int_add(json
, "bgpTableVersion",
14172 json_object_string_addf(json
, "bgpLocalRouterId",
14173 "%pI4", &bgp
->router_id
);
14174 json_object_int_add(json
, "defaultLocPrf",
14175 bgp
->default_local_pref
);
14176 json_object_int_add(json
, "localAS",
14177 peer
->change_local_as
14178 ? peer
->change_local_as
14180 json_object_object_add(json
, "bgpStatusCodes",
14182 json_object_object_add(json
, "bgpOriginCodes",
14184 json_object_string_add(
14185 json
, "bgpOriginatingDefaultNetwork",
14186 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14189 "BGP table version is %" PRIu64
14190 ", local router ID is %pI4, vrf id ",
14191 table
->version
, &bgp
->router_id
);
14192 if (bgp
->vrf_id
== VRF_UNKNOWN
)
14193 vty_out(vty
, "%s", VRFID_NONE_STR
);
14195 vty_out(vty
, "%u", bgp
->vrf_id
);
14196 vty_out(vty
, "\n");
14197 vty_out(vty
, "Default local pref %u, ",
14198 bgp
->default_local_pref
);
14199 vty_out(vty
, "local AS %u\n",
14200 peer
->change_local_as
? peer
->change_local_as
14203 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14204 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14205 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14206 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14209 vty_out(vty
, "Originating default network %s\n\n",
14210 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14216 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
14217 if (type
== bgp_show_adj_route_received
14218 || type
== bgp_show_adj_route_filtered
) {
14219 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14220 if (ain
->peer
!= peer
)
14223 show_adj_route_header(vty
, peer
, table
, header1
,
14224 header2
, json
, json_scode
,
14225 json_ocode
, wide
, detail
);
14227 if ((safi
== SAFI_MPLS_VPN
)
14228 || (safi
== SAFI_ENCAP
)
14229 || (safi
== SAFI_EVPN
)) {
14231 json_object_string_add(
14232 json_ar
, "rd", rd_str
);
14233 else if (show_rd
&& rd_str
) {
14235 "Route Distinguisher: %s\n",
14242 route_filtered
= false;
14244 /* Filter prefix using distribute list,
14245 * filter list or prefix list
14247 const struct prefix
*rn_p
=
14248 bgp_dest_get_prefix(dest
);
14249 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
14252 route_filtered
= true;
14254 /* Filter prefix using route-map */
14255 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
14256 safi
, rmap_name
, NULL
,
14259 if (type
== bgp_show_adj_route_filtered
&&
14260 !route_filtered
&& ret
!= RMAP_DENY
) {
14261 bgp_attr_flush(&attr
);
14265 if (type
== bgp_show_adj_route_received
14266 && (route_filtered
|| ret
== RMAP_DENY
))
14267 (*filtered_count
)++;
14272 json_object_new_object();
14273 bgp_show_path_info(
14274 NULL
/* prefix_rd */, dest
, vty
,
14275 bgp
, afi
, safi
, json_net
,
14276 BGP_PATH_SHOW_ALL
, &display
,
14277 RPKI_NOT_BEING_USED
);
14279 json_object_object_addf(
14283 route_vty_out_tmp(vty
, dest
, rn_p
,
14284 &attr
, safi
, use_json
,
14286 bgp_attr_flush(&attr
);
14289 } else if (type
== bgp_show_adj_route_advertised
) {
14290 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
14291 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14292 if (paf
->peer
!= peer
|| !adj
->attr
)
14295 show_adj_route_header(
14296 vty
, peer
, table
, header1
,
14297 header2
, json
, json_scode
,
14298 json_ocode
, wide
, detail
);
14300 const struct prefix
*rn_p
=
14301 bgp_dest_get_prefix(dest
);
14304 ret
= bgp_output_modifier(
14305 peer
, rn_p
, &attr
, afi
, safi
,
14308 if (ret
!= RMAP_DENY
) {
14309 if ((safi
== SAFI_MPLS_VPN
)
14310 || (safi
== SAFI_ENCAP
)
14311 || (safi
== SAFI_EVPN
)) {
14313 json_object_string_add(
14320 "Route Distinguisher: %s\n",
14328 json_object_new_object();
14329 bgp_show_path_info(
14338 RPKI_NOT_BEING_USED
);
14340 json_object_object_addf(
14353 (*filtered_count
)++;
14356 bgp_attr_flush(&attr
);
14358 } else if (type
== bgp_show_adj_route_bestpath
) {
14359 struct bgp_path_info
*pi
;
14361 show_adj_route_header(vty
, peer
, table
, header1
,
14362 header2
, json
, json_scode
,
14363 json_ocode
, wide
, detail
);
14365 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
14367 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
14369 if (pi
->peer
!= peer
)
14372 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
14378 json_object_new_object();
14379 bgp_show_path_info(
14380 NULL
/* prefix_rd */, dest
, vty
,
14381 bgp
, afi
, safi
, json_net
,
14382 BGP_PATH_SHOW_BESTPATH
,
14383 &display
, RPKI_NOT_BEING_USED
);
14385 json_object_object_addf(
14390 vty
, dest
, rn_p
, pi
->attr
, safi
,
14391 use_json
, json_ar
, wide
);
14398 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
14399 safi_t safi
, enum bgp_show_adj_route_type type
,
14400 const char *rmap_name
, const struct prefix
*match
,
14401 uint16_t show_flags
)
14404 struct bgp_table
*table
;
14405 json_object
*json
= NULL
;
14406 json_object
*json_scode
= NULL
;
14407 json_object
*json_ocode
= NULL
;
14408 json_object
*json_ar
= NULL
;
14409 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14411 /* Init BGP headers here so they're only displayed once
14412 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14418 * Initialize variables for each RD
14419 * All prefixes under an RD is aggregated within "json_routes"
14421 char rd_str
[BUFSIZ
] = {0};
14422 json_object
*json_routes
= NULL
;
14425 /* For 2-tier tables, prefix counts need to be
14426 * maintained across multiple runs of show_adj_route()
14428 unsigned long output_count_per_rd
;
14429 unsigned long filtered_count_per_rd
;
14430 unsigned long output_count
= 0;
14431 unsigned long filtered_count
= 0;
14434 json
= json_object_new_object();
14435 json_ar
= json_object_new_object();
14436 json_scode
= json_object_new_object();
14437 json_ocode
= json_object_new_object();
14438 #if CONFDATE > 20231208
14439 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14441 json_object_string_add(json_scode
, "suppressed", "s");
14442 json_object_string_add(json_scode
, "damped", "d");
14443 json_object_string_add(json_scode
, "history", "h");
14444 json_object_string_add(json_scode
, "valid", "*");
14445 json_object_string_add(json_scode
, "best", ">");
14446 json_object_string_add(json_scode
, "multipath", "=");
14447 json_object_string_add(json_scode
, "internal", "i");
14448 json_object_string_add(json_scode
, "ribFailure", "r");
14449 json_object_string_add(json_scode
, "stale", "S");
14450 json_object_string_add(json_scode
, "removed", "R");
14452 #if CONFDATE > 20231208
14453 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14455 json_object_string_add(json_ocode
, "igp", "i");
14456 json_object_string_add(json_ocode
, "egp", "e");
14457 json_object_string_add(json_ocode
, "incomplete", "?");
14460 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14462 json_object_string_add(
14464 "No such neighbor or address family");
14465 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14466 json_object_free(json
);
14467 json_object_free(json_ar
);
14468 json_object_free(json_scode
);
14469 json_object_free(json_ocode
);
14471 vty_out(vty
, "%% No such neighbor or address family\n");
14473 return CMD_WARNING
;
14476 if ((type
== bgp_show_adj_route_received
14477 || type
== bgp_show_adj_route_filtered
)
14478 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
14479 PEER_FLAG_SOFT_RECONFIG
)) {
14481 json_object_string_add(
14483 "Inbound soft reconfiguration not enabled");
14484 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14485 json_object_free(json
);
14486 json_object_free(json_ar
);
14487 json_object_free(json_scode
);
14488 json_object_free(json_ocode
);
14491 "%% Inbound soft reconfiguration not enabled\n");
14493 return CMD_WARNING
;
14498 /* labeled-unicast routes live in the unicast table */
14499 if (safi
== SAFI_LABELED_UNICAST
)
14500 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
14502 table
= bgp
->rib
[afi
][safi
];
14504 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14505 || (safi
== SAFI_EVPN
)) {
14507 struct bgp_dest
*dest
;
14509 for (dest
= bgp_table_top(table
); dest
;
14510 dest
= bgp_route_next(dest
)) {
14511 table
= bgp_dest_get_bgp_table_info(dest
);
14515 output_count_per_rd
= 0;
14516 filtered_count_per_rd
= 0;
14519 json_routes
= json_object_new_object();
14521 const struct prefix_rd
*prd
;
14522 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14525 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
),
14529 vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14530 json
, json_routes
, json_scode
, json_ocode
,
14531 show_flags
, &header1
, &header2
, rd_str
, match
,
14532 &output_count_per_rd
, &filtered_count_per_rd
);
14534 /* Don't include an empty RD in the output! */
14535 if (json_routes
&& (output_count_per_rd
> 0))
14536 json_object_object_add(json_ar
, rd_str
,
14539 output_count
+= output_count_per_rd
;
14540 filtered_count
+= filtered_count_per_rd
;
14543 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14544 json
, json_ar
, json_scode
, json_ocode
,
14545 show_flags
, &header1
, &header2
, rd_str
, match
,
14546 &output_count
, &filtered_count
);
14549 if (type
== bgp_show_adj_route_advertised
)
14550 json_object_object_add(json
, "advertisedRoutes",
14553 json_object_object_add(json
, "receivedRoutes", json_ar
);
14554 json_object_int_add(json
, "totalPrefixCounter", output_count
);
14555 json_object_int_add(json
, "filteredPrefixCounter",
14559 * These fields only give up ownership to `json` when `header1`
14560 * is used (set to zero). See code in `show_adj_route` and
14561 * `show_adj_route_header`.
14563 if (header1
== 1) {
14564 json_object_free(json_scode
);
14565 json_object_free(json_ocode
);
14568 vty_json(vty
, json
);
14569 } else if (output_count
> 0) {
14570 if (!match
&& filtered_count
> 0)
14572 "\nTotal number of prefixes %ld (%ld filtered)\n",
14573 output_count
, filtered_count
);
14575 vty_out(vty
, "\nTotal number of prefixes %ld\n",
14579 return CMD_SUCCESS
;
14582 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
14583 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
14584 "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]",
14588 BGP_INSTANCE_HELP_STR
14590 BGP_SAFI_WITH_LABEL_HELP_STR
14591 "Detailed information on TCP and BGP neighbor connections\n"
14592 "Neighbor to display information about\n"
14593 "Neighbor to display information about\n"
14594 "Neighbor on BGP configured interface\n"
14595 "Display the routes selected by best path\n"
14596 "Display detailed version of routes\n"
14598 "Increase table width for longer prefixes\n")
14600 afi_t afi
= AFI_IP6
;
14601 safi_t safi
= SAFI_UNICAST
;
14602 char *rmap_name
= NULL
;
14603 char *peerstr
= NULL
;
14604 struct bgp
*bgp
= NULL
;
14606 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
14608 uint16_t show_flags
= 0;
14611 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14614 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14617 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14619 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14623 return CMD_WARNING
;
14625 argv_find(argv
, argc
, "neighbors", &idx
);
14626 peerstr
= argv
[++idx
]->arg
;
14628 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14630 return CMD_WARNING
;
14632 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, NULL
,
14636 DEFPY(show_ip_bgp_instance_neighbor_advertised_route
,
14637 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
14638 "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]",
14642 BGP_INSTANCE_HELP_STR
14644 BGP_SAFI_WITH_LABEL_HELP_STR
14645 "Display the entries for all address families\n"
14646 "Detailed information on TCP and BGP neighbor connections\n"
14647 "Neighbor to display information about\n"
14648 "Neighbor to display information about\n"
14649 "Neighbor on BGP configured interface\n"
14650 "Display the routes advertised to a BGP neighbor\n"
14651 "Display the received routes from neighbor\n"
14652 "Display the filtered routes received from neighbor\n"
14653 "Route-map to modify the attributes\n"
14654 "Name of the route map\n"
14657 "Display detailed version of routes\n"
14659 "Increase table width for longer prefixes\n")
14661 afi_t afi
= AFI_IP6
;
14662 safi_t safi
= SAFI_UNICAST
;
14663 char *peerstr
= NULL
;
14664 struct bgp
*bgp
= NULL
;
14666 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
14669 uint16_t show_flags
= 0;
14670 struct listnode
*node
;
14673 if (detail
|| prefix_str
)
14674 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14678 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14682 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
14683 if (argv_find(argv
, argc
, "ipv4", &idx
))
14684 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
14686 if (argv_find(argv
, argc
, "ipv6", &idx
))
14687 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
14691 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14693 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14696 return CMD_WARNING
;
14698 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14699 argv_find(argv
, argc
, "neighbors", &idx
);
14700 peerstr
= argv
[++idx
]->arg
;
14702 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14704 return CMD_WARNING
;
14706 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
14707 type
= bgp_show_adj_route_advertised
;
14708 else if (argv_find(argv
, argc
, "received-routes", &idx
))
14709 type
= bgp_show_adj_route_received
;
14710 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
14711 type
= bgp_show_adj_route_filtered
;
14714 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, route_map
,
14715 prefix_str
? prefix
: NULL
, show_flags
);
14717 vty_out(vty
, "{\n");
14719 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14720 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14721 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14723 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14724 FOREACH_SAFI (safi
) {
14725 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14732 vty_out(vty
, ",\n");
14733 vty_out(vty
, "\"%s\":",
14734 get_afi_safi_str(afi
, safi
,
14738 "\nFor address family: %s\n",
14739 get_afi_safi_str(afi
, safi
,
14742 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14743 route_map
, prefix
, show_flags
);
14747 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14748 FOREACH_AFI_SAFI (afi
, safi
) {
14749 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14756 vty_out(vty
, ",\n");
14757 vty_out(vty
, "\"%s\":",
14758 get_afi_safi_str(afi
, safi
,
14762 "\nFor address family: %s\n",
14763 get_afi_safi_str(afi
, safi
,
14766 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14767 route_map
, prefix
, show_flags
);
14772 vty_out(vty
, "}\n");
14774 return CMD_SUCCESS
;
14777 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14778 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14779 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14783 BGP_INSTANCE_HELP_STR
14786 BGP_AF_MODIFIER_STR
14787 "Detailed information on TCP and BGP neighbor connections\n"
14788 "Neighbor to display information about\n"
14789 "Neighbor to display information about\n"
14790 "Neighbor on BGP configured interface\n"
14791 "Display information received from a BGP neighbor\n"
14792 "Display the prefixlist filter\n"
14795 afi_t afi
= AFI_IP6
;
14796 safi_t safi
= SAFI_UNICAST
;
14797 char *peerstr
= NULL
;
14802 struct bgp
*bgp
= NULL
;
14803 bool uj
= use_json(argc
, argv
);
14808 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14811 return CMD_WARNING
;
14813 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14814 argv_find(argv
, argc
, "neighbors", &idx
);
14815 peerstr
= argv
[++idx
]->arg
;
14817 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14819 return CMD_WARNING
;
14821 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14822 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14825 vty_out(vty
, "Address Family: %s\n",
14826 get_afi_safi_str(afi
, safi
, false));
14827 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14830 vty_out(vty
, "{}\n");
14832 vty_out(vty
, "No functional output\n");
14835 return CMD_SUCCESS
;
14838 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14839 afi_t afi
, safi_t safi
,
14840 enum bgp_show_type type
, bool use_json
)
14842 uint16_t show_flags
= 0;
14845 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14847 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14849 json_object
*json_no
= NULL
;
14850 json_no
= json_object_new_object();
14851 json_object_string_add(
14852 json_no
, "warning",
14853 "No such neighbor or address family");
14854 vty_out(vty
, "%s\n",
14855 json_object_to_json_string(json_no
));
14856 json_object_free(json_no
);
14858 vty_out(vty
, "%% No such neighbor or address family\n");
14859 return CMD_WARNING
;
14862 /* labeled-unicast routes live in the unicast table */
14863 if (safi
== SAFI_LABELED_UNICAST
)
14864 safi
= SAFI_UNICAST
;
14866 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14867 RPKI_NOT_BEING_USED
);
14870 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14871 show_ip_bgp_flowspec_routes_detailed_cmd
,
14872 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14876 BGP_INSTANCE_HELP_STR
14879 "Detailed information on flowspec entries\n"
14882 afi_t afi
= AFI_IP6
;
14883 safi_t safi
= SAFI_UNICAST
;
14884 struct bgp
*bgp
= NULL
;
14886 bool uj
= use_json(argc
, argv
);
14887 uint16_t show_flags
= BGP_SHOW_OPT_ROUTES_DETAIL
;
14891 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14894 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14897 return CMD_WARNING
;
14899 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14900 show_flags
, RPKI_NOT_BEING_USED
);
14903 DEFUN (show_ip_bgp_neighbor_routes
,
14904 show_ip_bgp_neighbor_routes_cmd
,
14905 "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]",
14909 BGP_INSTANCE_HELP_STR
14911 BGP_SAFI_WITH_LABEL_HELP_STR
14912 "Detailed information on TCP and BGP neighbor connections\n"
14913 "Neighbor to display information about\n"
14914 "Neighbor to display information about\n"
14915 "Neighbor on BGP configured interface\n"
14916 "Display flap statistics of the routes learned from neighbor\n"
14917 "Display the dampened routes received from neighbor\n"
14918 "Display routes learned from neighbor\n"
14921 char *peerstr
= NULL
;
14922 struct bgp
*bgp
= NULL
;
14923 afi_t afi
= AFI_IP6
;
14924 safi_t safi
= SAFI_UNICAST
;
14926 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14928 bool uj
= use_json(argc
, argv
);
14933 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14936 return CMD_WARNING
;
14938 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14939 argv_find(argv
, argc
, "neighbors", &idx
);
14940 peerstr
= argv
[++idx
]->arg
;
14942 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14944 return CMD_WARNING
;
14946 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14947 sh_type
= bgp_show_type_flap_neighbor
;
14948 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14949 sh_type
= bgp_show_type_damp_neighbor
;
14950 else if (argv_find(argv
, argc
, "routes", &idx
))
14951 sh_type
= bgp_show_type_neighbor
;
14953 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14956 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14958 struct bgp_distance
{
14959 /* Distance value for the IP source prefix. */
14962 /* Name of the access-list to be matched. */
14966 DEFUN (show_bgp_afi_vpn_rd_route
,
14967 show_bgp_afi_vpn_rd_route_cmd
,
14968 "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]",
14972 BGP_AF_MODIFIER_STR
14973 "Display information for a route distinguisher\n"
14974 "Route Distinguisher\n"
14975 "All Route Distinguishers\n"
14976 "Network in the BGP routing table to display\n"
14977 "Network in the BGP routing table to display\n"
14981 struct prefix_rd prd
;
14982 afi_t afi
= AFI_MAX
;
14985 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
14986 vty_out(vty
, "%% Malformed Address Family\n");
14987 return CMD_WARNING
;
14990 if (!strcmp(argv
[5]->arg
, "all"))
14991 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
14992 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
14993 RPKI_NOT_BEING_USED
,
14994 use_json(argc
, argv
));
14996 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
14998 vty_out(vty
, "%% Malformed Route Distinguisher\n");
14999 return CMD_WARNING
;
15002 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
15003 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
15004 use_json(argc
, argv
));
15007 static struct bgp_distance
*bgp_distance_new(void)
15009 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
15012 static void bgp_distance_free(struct bgp_distance
*bdistance
)
15014 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
15017 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
15018 const char *ip_str
, const char *access_list_str
)
15025 struct bgp_dest
*dest
;
15026 struct bgp_distance
*bdistance
;
15028 afi
= bgp_node_afi(vty
);
15029 safi
= bgp_node_safi(vty
);
15031 ret
= str2prefix(ip_str
, &p
);
15033 vty_out(vty
, "Malformed prefix\n");
15034 return CMD_WARNING_CONFIG_FAILED
;
15037 distance
= atoi(distance_str
);
15039 /* Get BGP distance node. */
15040 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
15041 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15043 bgp_dest_unlock_node(dest
);
15045 bdistance
= bgp_distance_new();
15046 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
15049 /* Set distance value. */
15050 bdistance
->distance
= distance
;
15052 /* Reset access-list configuration. */
15053 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
15054 if (access_list_str
)
15055 bdistance
->access_list
=
15056 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
15058 return CMD_SUCCESS
;
15061 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
15062 const char *ip_str
, const char *access_list_str
)
15069 struct bgp_dest
*dest
;
15070 struct bgp_distance
*bdistance
;
15072 afi
= bgp_node_afi(vty
);
15073 safi
= bgp_node_safi(vty
);
15075 ret
= str2prefix(ip_str
, &p
);
15077 vty_out(vty
, "Malformed prefix\n");
15078 return CMD_WARNING_CONFIG_FAILED
;
15081 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
15083 vty_out(vty
, "Can't find specified prefix\n");
15084 return CMD_WARNING_CONFIG_FAILED
;
15087 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15088 distance
= atoi(distance_str
);
15090 if (bdistance
->distance
!= distance
) {
15091 vty_out(vty
, "Distance does not match configured\n");
15092 bgp_dest_unlock_node(dest
);
15093 return CMD_WARNING_CONFIG_FAILED
;
15096 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
15097 bgp_distance_free(bdistance
);
15099 bgp_dest_set_bgp_path_info(dest
, NULL
);
15100 bgp_dest_unlock_node(dest
);
15101 bgp_dest_unlock_node(dest
);
15103 return CMD_SUCCESS
;
15106 /* Apply BGP information to distance method. */
15107 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
15108 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
15110 struct bgp_dest
*dest
;
15111 struct prefix q
= {0};
15113 struct bgp_distance
*bdistance
;
15114 struct access_list
*alist
;
15115 struct bgp_static
*bgp_static
;
15116 struct bgp_path_info
*bpi_ultimate
;
15121 peer
= pinfo
->peer
;
15123 if (pinfo
->attr
->distance
)
15124 return pinfo
->attr
->distance
;
15126 /* get peer origin to calculate appropriate distance */
15127 if (pinfo
->sub_type
== BGP_ROUTE_IMPORTED
) {
15128 bpi_ultimate
= bgp_get_imported_bpi_ultimate(pinfo
);
15129 peer
= bpi_ultimate
->peer
;
15132 /* Check source address.
15133 * Note: for aggregate route, peer can have unspec af type.
15135 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
15136 && !sockunion2hostprefix(&peer
->su
, &q
))
15139 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
15141 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15142 bgp_dest_unlock_node(dest
);
15144 if (bdistance
->access_list
) {
15145 alist
= access_list_lookup(afi
, bdistance
->access_list
);
15147 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
15148 return bdistance
->distance
;
15150 return bdistance
->distance
;
15153 /* Backdoor check. */
15154 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
15156 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15157 bgp_dest_unlock_node(dest
);
15159 if (bgp_static
->backdoor
) {
15160 if (bgp
->distance_local
[afi
][safi
])
15161 return bgp
->distance_local
[afi
][safi
];
15163 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15167 if (peer
->sort
== BGP_PEER_EBGP
) {
15168 if (bgp
->distance_ebgp
[afi
][safi
])
15169 return bgp
->distance_ebgp
[afi
][safi
];
15170 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
15171 } else if (peer
->sort
== BGP_PEER_IBGP
) {
15172 if (bgp
->distance_ibgp
[afi
][safi
])
15173 return bgp
->distance_ibgp
[afi
][safi
];
15174 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15176 if (bgp
->distance_local
[afi
][safi
])
15177 return bgp
->distance_local
[afi
][safi
];
15178 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15182 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15183 * we should tell ZEBRA update the routes for a specific
15184 * AFI/SAFI to reflect changes in RIB.
15186 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
15188 safi_t update_safi
)
15193 FOREACH_AFI_SAFI (afi
, safi
) {
15194 if (!bgp_fibupd_safi(safi
))
15197 if (afi
!= update_afi
&& safi
!= update_safi
)
15200 if (BGP_DEBUG(zebra
, ZEBRA
))
15202 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15203 __func__
, afi
, safi
);
15204 bgp_zebra_announce_table(bgp
, afi
, safi
);
15208 DEFUN (bgp_distance
,
15210 "distance bgp (1-255) (1-255) (1-255)",
15211 "Define an administrative distance\n"
15213 "Distance for routes external to the AS\n"
15214 "Distance for routes internal to the AS\n"
15215 "Distance for local routes\n")
15217 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15218 int idx_number
= 2;
15219 int idx_number_2
= 3;
15220 int idx_number_3
= 4;
15221 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
15222 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
15223 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
15227 afi
= bgp_node_afi(vty
);
15228 safi
= bgp_node_safi(vty
);
15230 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
15231 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
15232 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
15233 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
15234 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
15235 bgp
->distance_local
[afi
][safi
] = distance_local
;
15236 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15238 return CMD_SUCCESS
;
15241 DEFUN (no_bgp_distance
,
15242 no_bgp_distance_cmd
,
15243 "no distance bgp [(1-255) (1-255) (1-255)]",
15245 "Define an administrative distance\n"
15247 "Distance for routes external to the AS\n"
15248 "Distance for routes internal to the AS\n"
15249 "Distance for local routes\n")
15251 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15255 afi
= bgp_node_afi(vty
);
15256 safi
= bgp_node_safi(vty
);
15258 if (bgp
->distance_ebgp
[afi
][safi
] != 0
15259 || bgp
->distance_ibgp
[afi
][safi
] != 0
15260 || bgp
->distance_local
[afi
][safi
] != 0) {
15261 bgp
->distance_ebgp
[afi
][safi
] = 0;
15262 bgp
->distance_ibgp
[afi
][safi
] = 0;
15263 bgp
->distance_local
[afi
][safi
] = 0;
15264 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15266 return CMD_SUCCESS
;
15270 DEFUN (bgp_distance_source
,
15271 bgp_distance_source_cmd
,
15272 "distance (1-255) A.B.C.D/M",
15273 "Define an administrative distance\n"
15274 "Administrative distance\n"
15275 "IP source prefix\n")
15277 int idx_number
= 1;
15278 int idx_ipv4_prefixlen
= 2;
15279 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15280 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15281 return CMD_SUCCESS
;
15284 DEFUN (no_bgp_distance_source
,
15285 no_bgp_distance_source_cmd
,
15286 "no distance (1-255) A.B.C.D/M",
15288 "Define an administrative distance\n"
15289 "Administrative distance\n"
15290 "IP source prefix\n")
15292 int idx_number
= 2;
15293 int idx_ipv4_prefixlen
= 3;
15294 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15295 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15296 return CMD_SUCCESS
;
15299 DEFUN (bgp_distance_source_access_list
,
15300 bgp_distance_source_access_list_cmd
,
15301 "distance (1-255) A.B.C.D/M WORD",
15302 "Define an administrative distance\n"
15303 "Administrative distance\n"
15304 "IP source prefix\n"
15305 "Access list name\n")
15307 int idx_number
= 1;
15308 int idx_ipv4_prefixlen
= 2;
15310 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15311 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15312 return CMD_SUCCESS
;
15315 DEFUN (no_bgp_distance_source_access_list
,
15316 no_bgp_distance_source_access_list_cmd
,
15317 "no distance (1-255) A.B.C.D/M WORD",
15319 "Define an administrative distance\n"
15320 "Administrative distance\n"
15321 "IP source prefix\n"
15322 "Access list name\n")
15324 int idx_number
= 2;
15325 int idx_ipv4_prefixlen
= 3;
15327 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15328 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15329 return CMD_SUCCESS
;
15332 DEFUN (ipv6_bgp_distance_source
,
15333 ipv6_bgp_distance_source_cmd
,
15334 "distance (1-255) X:X::X:X/M",
15335 "Define an administrative distance\n"
15336 "Administrative distance\n"
15337 "IP source prefix\n")
15339 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
15340 return CMD_SUCCESS
;
15343 DEFUN (no_ipv6_bgp_distance_source
,
15344 no_ipv6_bgp_distance_source_cmd
,
15345 "no distance (1-255) X:X::X:X/M",
15347 "Define an administrative distance\n"
15348 "Administrative distance\n"
15349 "IP source prefix\n")
15351 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
15352 return CMD_SUCCESS
;
15355 DEFUN (ipv6_bgp_distance_source_access_list
,
15356 ipv6_bgp_distance_source_access_list_cmd
,
15357 "distance (1-255) X:X::X:X/M WORD",
15358 "Define an administrative distance\n"
15359 "Administrative distance\n"
15360 "IP source prefix\n"
15361 "Access list name\n")
15363 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
15364 return CMD_SUCCESS
;
15367 DEFUN (no_ipv6_bgp_distance_source_access_list
,
15368 no_ipv6_bgp_distance_source_access_list_cmd
,
15369 "no distance (1-255) X:X::X:X/M WORD",
15371 "Define an administrative distance\n"
15372 "Administrative distance\n"
15373 "IP source prefix\n"
15374 "Access list name\n")
15376 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
15377 return CMD_SUCCESS
;
15380 DEFUN (bgp_damp_set
,
15382 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15383 "BGP Specific commands\n"
15384 "Enable route-flap dampening\n"
15385 "Half-life time for the penalty\n"
15386 "Value to start reusing a route\n"
15387 "Value to start suppressing a route\n"
15388 "Maximum duration to suppress a stable route\n")
15390 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15391 int idx_half_life
= 2;
15393 int idx_suppress
= 4;
15394 int idx_max_suppress
= 5;
15395 int half
= DEFAULT_HALF_LIFE
* 60;
15396 int reuse
= DEFAULT_REUSE
;
15397 int suppress
= DEFAULT_SUPPRESS
;
15398 int max
= 4 * half
;
15401 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15402 reuse
= atoi(argv
[idx_reuse
]->arg
);
15403 suppress
= atoi(argv
[idx_suppress
]->arg
);
15404 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
15405 } else if (argc
== 3) {
15406 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15411 * These can't be 0 but our SA doesn't understand the
15412 * way our cli is constructed
15416 if (suppress
< reuse
) {
15418 "Suppress value cannot be less than reuse value \n");
15422 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
15423 reuse
, suppress
, max
);
15426 DEFUN (bgp_damp_unset
,
15427 bgp_damp_unset_cmd
,
15428 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15430 "BGP Specific commands\n"
15431 "Enable route-flap dampening\n"
15432 "Half-life time for the penalty\n"
15433 "Value to start reusing a route\n"
15434 "Value to start suppressing a route\n"
15435 "Maximum duration to suppress a stable route\n")
15437 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15438 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
15441 /* Display specified route of BGP table. */
15442 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
15443 const char *ip_str
, afi_t afi
, safi_t safi
,
15444 struct prefix_rd
*prd
, int prefix_check
)
15447 struct prefix match
;
15448 struct bgp_dest
*dest
;
15449 struct bgp_dest
*rm
;
15450 struct bgp_path_info
*pi
;
15451 struct bgp_path_info
*pi_temp
;
15453 struct bgp_table
*table
;
15455 /* BGP structure lookup. */
15457 bgp
= bgp_lookup_by_name(view_name
);
15459 vty_out(vty
, "%% Can't find BGP instance %s\n",
15461 return CMD_WARNING
;
15464 bgp
= bgp_get_default();
15466 vty_out(vty
, "%% No BGP process is configured\n");
15467 return CMD_WARNING
;
15471 /* Check IP address argument. */
15472 ret
= str2prefix(ip_str
, &match
);
15474 vty_out(vty
, "%% address is malformed\n");
15475 return CMD_WARNING
;
15478 match
.family
= afi2family(afi
);
15480 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
15481 || (safi
== SAFI_EVPN
)) {
15482 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
15483 dest
= bgp_route_next(dest
)) {
15484 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15486 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
15488 table
= bgp_dest_get_bgp_table_info(dest
);
15491 rm
= bgp_node_match(table
, &match
);
15495 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
15498 || rm_p
->prefixlen
== match
.prefixlen
) {
15499 pi
= bgp_dest_get_bgp_path_info(rm
);
15501 if (pi
->extra
&& pi
->extra
->damp_info
) {
15502 pi_temp
= pi
->next
;
15503 bgp_damp_info_free(
15504 pi
->extra
->damp_info
,
15512 bgp_dest_unlock_node(rm
);
15515 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
15516 if (dest
!= NULL
) {
15517 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15520 || dest_p
->prefixlen
== match
.prefixlen
) {
15521 pi
= bgp_dest_get_bgp_path_info(dest
);
15523 if (pi
->extra
&& pi
->extra
->damp_info
) {
15524 pi_temp
= pi
->next
;
15525 bgp_damp_info_free(
15526 pi
->extra
->damp_info
,
15534 bgp_dest_unlock_node(dest
);
15538 return CMD_SUCCESS
;
15541 DEFUN (clear_ip_bgp_dampening
,
15542 clear_ip_bgp_dampening_cmd
,
15543 "clear ip bgp dampening",
15547 "Clear route flap dampening information\n")
15549 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
15550 return CMD_SUCCESS
;
15553 DEFUN (clear_ip_bgp_dampening_prefix
,
15554 clear_ip_bgp_dampening_prefix_cmd
,
15555 "clear ip bgp dampening A.B.C.D/M",
15559 "Clear route flap dampening information\n"
15562 int idx_ipv4_prefixlen
= 4;
15563 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
15564 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
15567 DEFUN (clear_ip_bgp_dampening_address
,
15568 clear_ip_bgp_dampening_address_cmd
,
15569 "clear ip bgp dampening A.B.C.D",
15573 "Clear route flap dampening information\n"
15574 "Network to clear damping information\n")
15577 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
15578 SAFI_UNICAST
, NULL
, 0);
15581 DEFUN (clear_ip_bgp_dampening_address_mask
,
15582 clear_ip_bgp_dampening_address_mask_cmd
,
15583 "clear ip bgp dampening A.B.C.D A.B.C.D",
15587 "Clear route flap dampening information\n"
15588 "Network to clear damping information\n"
15592 int idx_ipv4_2
= 5;
15594 char prefix_str
[BUFSIZ
];
15596 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
15597 prefix_str
, sizeof(prefix_str
));
15599 vty_out(vty
, "%% Inconsistent address and mask\n");
15600 return CMD_WARNING
;
15603 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
15607 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
15609 struct vty
*vty
= arg
;
15610 struct peer
*peer
= bucket
->data
;
15612 vty_out(vty
, "\tPeer: %s %pSU\n", peer
->host
, &peer
->su
);
15615 DEFUN (show_bgp_listeners
,
15616 show_bgp_listeners_cmd
,
15617 "show bgp listeners",
15620 "Display Listen Sockets and who created them\n")
15622 bgp_dump_listener_info(vty
);
15624 return CMD_SUCCESS
;
15627 DEFUN (show_bgp_peerhash
,
15628 show_bgp_peerhash_cmd
,
15629 "show bgp peerhash",
15632 "Display information about the BGP peerhash\n")
15634 struct list
*instances
= bm
->bgp
;
15635 struct listnode
*node
;
15638 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
15639 vty_out(vty
, "BGP: %s\n", bgp
->name
);
15640 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
15644 return CMD_SUCCESS
;
15647 /* also used for encap safi */
15648 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
15649 afi_t afi
, safi_t safi
)
15651 struct bgp_dest
*pdest
;
15652 struct bgp_dest
*dest
;
15653 struct bgp_table
*table
;
15654 const struct prefix
*p
;
15655 struct bgp_static
*bgp_static
;
15656 mpls_label_t label
;
15658 /* Network configuration. */
15659 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15660 pdest
= bgp_route_next(pdest
)) {
15661 table
= bgp_dest_get_bgp_table_info(pdest
);
15665 for (dest
= bgp_table_top(table
); dest
;
15666 dest
= bgp_route_next(dest
)) {
15667 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15668 if (bgp_static
== NULL
)
15671 p
= bgp_dest_get_prefix(dest
);
15673 /* "network" configuration display. */
15674 label
= decode_label(&bgp_static
->label
);
15676 vty_out(vty
, " network %pFX rd %s", p
,
15677 bgp_static
->prd_pretty
);
15678 if (safi
== SAFI_MPLS_VPN
)
15679 vty_out(vty
, " label %u", label
);
15681 if (bgp_static
->rmap
.name
)
15682 vty_out(vty
, " route-map %s",
15683 bgp_static
->rmap
.name
);
15685 if (bgp_static
->backdoor
)
15686 vty_out(vty
, " backdoor");
15688 vty_out(vty
, "\n");
15693 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
15694 afi_t afi
, safi_t safi
)
15696 struct bgp_dest
*pdest
;
15697 struct bgp_dest
*dest
;
15698 struct bgp_table
*table
;
15699 const struct prefix
*p
;
15700 struct bgp_static
*bgp_static
;
15701 char buf
[PREFIX_STRLEN
* 2];
15702 char buf2
[SU_ADDRSTRLEN
];
15703 char esi_buf
[ESI_STR_LEN
];
15705 /* Network configuration. */
15706 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15707 pdest
= bgp_route_next(pdest
)) {
15708 table
= bgp_dest_get_bgp_table_info(pdest
);
15712 for (dest
= bgp_table_top(table
); dest
;
15713 dest
= bgp_route_next(dest
)) {
15714 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15715 if (bgp_static
== NULL
)
15718 char *macrouter
= NULL
;
15720 if (bgp_static
->router_mac
)
15721 macrouter
= prefix_mac2str(
15722 bgp_static
->router_mac
, NULL
, 0);
15723 if (bgp_static
->eth_s_id
)
15724 esi_to_str(bgp_static
->eth_s_id
,
15725 esi_buf
, sizeof(esi_buf
));
15726 p
= bgp_dest_get_prefix(dest
);
15728 /* "network" configuration display. */
15729 if (p
->u
.prefix_evpn
.route_type
== 5) {
15730 char local_buf
[PREFIX_STRLEN
];
15732 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15733 struct prefix_evpn
*)p
)
15737 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
15739 local_buf
, sizeof(local_buf
));
15740 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15741 p
->u
.prefix_evpn
.prefix_addr
15742 .ip_prefix_length
);
15744 prefix2str(p
, buf
, sizeof(buf
));
15747 if (bgp_static
->gatewayIp
.family
== AF_INET
15748 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15749 inet_ntop(bgp_static
->gatewayIp
.family
,
15750 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15753 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15754 buf
, bgp_static
->prd_pretty
,
15755 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15756 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15759 XFREE(MTYPE_TMP
, macrouter
);
15764 /* Configuration of static route announcement and aggregate
15766 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15769 struct bgp_dest
*dest
;
15770 const struct prefix
*p
;
15771 struct bgp_static
*bgp_static
;
15772 struct bgp_aggregate
*bgp_aggregate
;
15774 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15775 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15779 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15780 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15784 /* Network configuration. */
15785 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15786 dest
= bgp_route_next(dest
)) {
15787 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15788 if (bgp_static
== NULL
)
15791 p
= bgp_dest_get_prefix(dest
);
15793 vty_out(vty
, " network %pFX", p
);
15795 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15796 vty_out(vty
, " label-index %u",
15797 bgp_static
->label_index
);
15799 if (bgp_static
->rmap
.name
)
15800 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15802 if (bgp_static
->backdoor
)
15803 vty_out(vty
, " backdoor");
15805 vty_out(vty
, "\n");
15808 /* Aggregate-address configuration. */
15809 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15810 dest
= bgp_route_next(dest
)) {
15811 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15812 if (bgp_aggregate
== NULL
)
15815 p
= bgp_dest_get_prefix(dest
);
15817 vty_out(vty
, " aggregate-address %pFX", p
);
15819 if (bgp_aggregate
->as_set
)
15820 vty_out(vty
, " as-set");
15822 if (bgp_aggregate
->summary_only
)
15823 vty_out(vty
, " summary-only");
15825 if (bgp_aggregate
->rmap
.name
)
15826 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15828 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15829 vty_out(vty
, " origin %s",
15830 bgp_origin2str(bgp_aggregate
->origin
));
15832 if (bgp_aggregate
->match_med
)
15833 vty_out(vty
, " matching-MED-only");
15835 if (bgp_aggregate
->suppress_map_name
)
15836 vty_out(vty
, " suppress-map %s",
15837 bgp_aggregate
->suppress_map_name
);
15839 vty_out(vty
, "\n");
15843 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15846 struct bgp_dest
*dest
;
15847 struct bgp_distance
*bdistance
;
15849 /* Distance configuration. */
15850 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15851 && bgp
->distance_local
[afi
][safi
]
15852 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15853 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15854 || bgp
->distance_local
[afi
][safi
]
15855 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15856 vty_out(vty
, " distance bgp %d %d %d\n",
15857 bgp
->distance_ebgp
[afi
][safi
],
15858 bgp
->distance_ibgp
[afi
][safi
],
15859 bgp
->distance_local
[afi
][safi
]);
15862 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15863 dest
= bgp_route_next(dest
)) {
15864 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15865 if (bdistance
!= NULL
)
15866 vty_out(vty
, " distance %d %pBD %s\n",
15867 bdistance
->distance
, dest
,
15868 bdistance
->access_list
? bdistance
->access_list
15873 /* Allocate routing table structure and install commands. */
15874 void bgp_route_init(void)
15879 /* Init BGP distance table. */
15880 FOREACH_AFI_SAFI (afi
, safi
)
15881 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15883 /* IPv4 BGP commands. */
15884 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15885 install_element(BGP_NODE
, &bgp_network_cmd
);
15886 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15888 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15890 /* IPv4 unicast configuration. */
15891 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15892 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15893 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15895 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15897 /* IPv4 multicast configuration. */
15898 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15899 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15900 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15901 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15903 /* IPv4 labeled-unicast configuration. */
15904 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15905 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15907 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15908 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15909 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15910 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15911 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15912 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15913 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15914 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15916 install_element(VIEW_NODE
,
15917 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15918 install_element(VIEW_NODE
,
15919 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15920 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15921 install_element(VIEW_NODE
,
15922 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15923 #ifdef KEEP_OLD_VPN_COMMANDS
15924 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15925 #endif /* KEEP_OLD_VPN_COMMANDS */
15926 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15927 install_element(VIEW_NODE
,
15928 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15930 /* BGP dampening clear commands */
15931 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15932 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15934 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15935 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15938 install_element(ENABLE_NODE
,
15939 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15940 #ifdef KEEP_OLD_VPN_COMMANDS
15941 install_element(ENABLE_NODE
,
15942 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15943 #endif /* KEEP_OLD_VPN_COMMANDS */
15945 /* New config IPv6 BGP commands. */
15946 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15947 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15948 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15950 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15952 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15954 /* IPv6 labeled unicast address family. */
15955 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15956 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15958 install_element(BGP_NODE
, &bgp_distance_cmd
);
15959 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15960 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15961 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
15962 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
15963 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
15964 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15965 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15966 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15967 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
15968 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
15969 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
15970 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15971 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15972 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
15973 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
15974 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
15975 install_element(BGP_IPV4M_NODE
,
15976 &no_bgp_distance_source_access_list_cmd
);
15977 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
15978 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
15979 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
15980 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15981 install_element(BGP_IPV6_NODE
,
15982 &ipv6_bgp_distance_source_access_list_cmd
);
15983 install_element(BGP_IPV6_NODE
,
15984 &no_ipv6_bgp_distance_source_access_list_cmd
);
15985 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
15986 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
15987 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
15988 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15989 install_element(BGP_IPV6M_NODE
,
15990 &ipv6_bgp_distance_source_access_list_cmd
);
15991 install_element(BGP_IPV6M_NODE
,
15992 &no_ipv6_bgp_distance_source_access_list_cmd
);
15994 /* BGP dampening */
15995 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
15996 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
15997 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
15998 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
15999 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
16000 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
16001 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
16002 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
16003 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
16004 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
16005 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
16006 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
16007 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
16008 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
16010 /* Large Communities */
16011 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
16012 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
16014 /* show bgp ipv4 flowspec detailed */
16015 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
16017 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
16018 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
16021 void bgp_route_finish(void)
16026 FOREACH_AFI_SAFI (afi
, safi
) {
16027 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
16028 bgp_distance_table
[afi
][safi
] = NULL
;