1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* BGP routing information
3 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
4 * Copyright (C) 2016 Job Snijders <job@instituut.net>
21 #include "sockunion.h"
24 #include "workqueue.h"
29 #include "lib_errors.h"
31 #include "bgpd/bgpd.h"
32 #include "bgpd/bgp_table.h"
33 #include "bgpd/bgp_route.h"
34 #include "bgpd/bgp_attr.h"
35 #include "bgpd/bgp_debug.h"
36 #include "bgpd/bgp_errors.h"
37 #include "bgpd/bgp_aspath.h"
38 #include "bgpd/bgp_regex.h"
39 #include "bgpd/bgp_community.h"
40 #include "bgpd/bgp_community_alias.h"
41 #include "bgpd/bgp_ecommunity.h"
42 #include "bgpd/bgp_lcommunity.h"
43 #include "bgpd/bgp_clist.h"
44 #include "bgpd/bgp_packet.h"
45 #include "bgpd/bgp_filter.h"
46 #include "bgpd/bgp_fsm.h"
47 #include "bgpd/bgp_mplsvpn.h"
48 #include "bgpd/bgp_nexthop.h"
49 #include "bgpd/bgp_damp.h"
50 #include "bgpd/bgp_advertise.h"
51 #include "bgpd/bgp_zebra.h"
52 #include "bgpd/bgp_vty.h"
53 #include "bgpd/bgp_mpath.h"
54 #include "bgpd/bgp_nht.h"
55 #include "bgpd/bgp_updgrp.h"
56 #include "bgpd/bgp_label.h"
57 #include "bgpd/bgp_addpath.h"
58 #include "bgpd/bgp_mac.h"
59 #include "bgpd/bgp_network.h"
60 #include "bgpd/bgp_trace.h"
61 #include "bgpd/bgp_rpki.h"
64 #include "bgpd/rfapi/rfapi_backend.h"
65 #include "bgpd/rfapi/vnc_import_bgp.h"
66 #include "bgpd/rfapi/vnc_export_bgp.h"
68 #include "bgpd/bgp_encap_types.h"
69 #include "bgpd/bgp_encap_tlv.h"
70 #include "bgpd/bgp_evpn.h"
71 #include "bgpd/bgp_evpn_mh.h"
72 #include "bgpd/bgp_evpn_vty.h"
73 #include "bgpd/bgp_flowspec.h"
74 #include "bgpd/bgp_flowspec_util.h"
75 #include "bgpd/bgp_pbr.h"
77 #include "bgpd/bgp_route_clippy.c"
79 DEFINE_HOOK(bgp_snmp_update_stats
,
80 (struct bgp_node
*rn
, struct bgp_path_info
*pi
, bool added
),
83 DEFINE_HOOK(bgp_rpki_prefix_status
,
84 (struct peer
*peer
, struct attr
*attr
,
85 const struct prefix
*prefix
),
86 (peer
, attr
, prefix
));
88 /* Extern from bgp_dump.c */
89 extern const char *bgp_origin_str
[];
90 extern const char *bgp_origin_long_str
[];
93 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
94 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
95 static const struct message bgp_pmsi_tnltype_str
[] = {
96 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
97 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
98 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
99 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
100 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
101 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
102 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
103 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
107 #define VRFID_NONE_STR "-"
108 #define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
110 DEFINE_HOOK(bgp_process
,
111 (struct bgp
* bgp
, afi_t afi
, safi_t safi
, struct bgp_dest
*bn
,
112 struct peer
*peer
, bool withdraw
),
113 (bgp
, afi
, safi
, bn
, peer
, withdraw
));
115 /** Test if path is suppressed. */
116 static bool bgp_path_suppressed(struct bgp_path_info
*pi
)
118 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
121 return listcount(pi
->extra
->aggr_suppressors
) > 0;
124 struct bgp_dest
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
125 safi_t safi
, const struct prefix
*p
,
126 struct prefix_rd
*prd
)
128 struct bgp_dest
*dest
;
129 struct bgp_dest
*pdest
= NULL
;
133 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
134 || (safi
== SAFI_EVPN
)) {
135 pdest
= bgp_node_get(table
, (struct prefix
*)prd
);
137 if (!bgp_dest_has_bgp_path_info_data(pdest
))
138 bgp_dest_set_bgp_table_info(
139 pdest
, bgp_table_init(table
->bgp
, afi
, safi
));
141 bgp_dest_unlock_node(pdest
);
142 table
= bgp_dest_get_bgp_table_info(pdest
);
145 dest
= bgp_node_get(table
, p
);
147 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
148 || (safi
== SAFI_EVPN
))
154 struct bgp_dest
*bgp_safi_node_lookup(struct bgp_table
*table
, safi_t safi
,
155 const struct prefix
*p
,
156 struct prefix_rd
*prd
)
158 struct bgp_dest
*dest
;
159 struct bgp_dest
*pdest
= NULL
;
164 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
165 || (safi
== SAFI_EVPN
)) {
166 pdest
= bgp_node_lookup(table
, (struct prefix
*)prd
);
170 if (!bgp_dest_has_bgp_path_info_data(pdest
)) {
171 bgp_dest_unlock_node(pdest
);
175 table
= bgp_dest_get_bgp_table_info(pdest
);
178 dest
= bgp_node_lookup(table
, p
);
183 /* Allocate bgp_path_info_extra */
184 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
186 struct bgp_path_info_extra
*new;
187 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
188 sizeof(struct bgp_path_info_extra
));
189 new->label
[0] = MPLS_INVALID_LABEL
;
191 new->bgp_fs_pbr
= NULL
;
192 new->bgp_fs_iprule
= NULL
;
196 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
198 struct bgp_path_info_extra
*e
;
200 if (!extra
|| !*extra
)
205 bgp_damp_info_free(e
->damp_info
, 0, e
->damp_info
->afi
,
210 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
213 /* FIXME: since multiple e may have the same e->parent
214 * and e->parent->net is holding a refcount for each
215 * of them, we need to do some fudging here.
217 * WARNING: if bpi->net->lock drops to 0, bpi may be
218 * freed as well (because bpi->net was holding the
219 * last reference to bpi) => write after free!
223 bpi
= bgp_path_info_lock(bpi
);
224 refcount
= bgp_dest_get_lock_count(bpi
->net
) - 1;
225 bgp_dest_unlock_node((struct bgp_dest
*)bpi
->net
);
228 bgp_path_info_unlock(bpi
);
230 bgp_path_info_unlock(e
->parent
);
235 bgp_unlock(e
->bgp_orig
);
238 peer_unlock(e
->peer_orig
);
240 if (e
->aggr_suppressors
)
241 list_delete(&e
->aggr_suppressors
);
244 bgp_evpn_path_mh_info_free(e
->mh_info
);
246 if ((*extra
)->bgp_fs_iprule
)
247 list_delete(&((*extra
)->bgp_fs_iprule
));
248 if ((*extra
)->bgp_fs_pbr
)
249 list_delete(&((*extra
)->bgp_fs_pbr
));
250 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
253 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
254 * allocated if required.
256 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
259 pi
->extra
= bgp_path_info_extra_new();
263 /* Free bgp route information. */
264 void bgp_path_info_free_with_caller(const char *name
,
265 struct bgp_path_info
*path
)
267 frrtrace(2, frr_bgp
, bgp_path_info_free
, path
, name
);
268 bgp_attr_unintern(&path
->attr
);
270 bgp_unlink_nexthop(path
);
271 bgp_path_info_extra_free(&path
->extra
);
272 bgp_path_info_mpath_free(&path
->mpath
);
274 bgp_addpath_free_info_data(&path
->tx_addpath
,
275 &path
->net
->tx_addpath
);
277 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
279 XFREE(MTYPE_BGP_ROUTE
, path
);
282 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
288 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
290 assert(path
&& path
->lock
> 0);
293 if (path
->lock
== 0) {
294 bgp_path_info_free(path
);
301 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
302 static int bgp_dest_set_defer_flag(struct bgp_dest
*dest
, bool delete)
305 struct bgp_path_info
*old_pi
, *nextpi
;
306 bool set_flag
= false;
307 struct bgp
*bgp
= NULL
;
308 struct bgp_table
*table
= NULL
;
312 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
313 * then the route selection is deferred
315 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
318 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
319 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
320 table
= bgp_dest_table(dest
);
325 "Route %pBD(%s) is in workqueue and being processed, not deferred.",
326 dest
, bgp
? bgp
->name_pretty
: "(Unknown)");
332 table
= bgp_dest_table(dest
);
339 for (old_pi
= bgp_dest_get_bgp_path_info(dest
);
340 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
341 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
344 /* Route selection is deferred if there is a stale path which
345 * which indicates peer is in restart mode
347 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
348 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
351 /* If the peer is graceful restart capable and peer is
352 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
355 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
356 && BGP_PEER_RESTARTING_MODE(peer
)
358 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
366 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
369 if (set_flag
&& table
) {
370 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
371 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
372 bgp
->gr_info
[afi
][safi
].gr_deferred
++;
373 SET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
374 if (BGP_DEBUG(update
, UPDATE_OUT
))
375 zlog_debug("DEFER route %pBD(%s), dest %p",
376 dest
, bgp
->name_pretty
, dest
);
383 void bgp_path_info_add_with_caller(const char *name
, struct bgp_dest
*dest
,
384 struct bgp_path_info
*pi
)
386 frrtrace(3, frr_bgp
, bgp_path_info_add
, dest
, pi
, name
);
387 struct bgp_path_info
*top
;
389 top
= bgp_dest_get_bgp_path_info(dest
);
395 bgp_dest_set_bgp_path_info(dest
, pi
);
397 bgp_path_info_lock(pi
);
398 bgp_dest_lock_node(dest
);
399 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
400 bgp_dest_set_defer_flag(dest
, false);
401 hook_call(bgp_snmp_update_stats
, dest
, pi
, true);
404 /* Do the actual removal of info from RIB, for use by bgp_process
405 completion callback *only* */
406 void bgp_path_info_reap(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
409 pi
->next
->prev
= pi
->prev
;
411 pi
->prev
->next
= pi
->next
;
413 bgp_dest_set_bgp_path_info(dest
, pi
->next
);
415 bgp_path_info_mpath_dequeue(pi
);
416 bgp_path_info_unlock(pi
);
417 hook_call(bgp_snmp_update_stats
, dest
, pi
, false);
418 bgp_dest_unlock_node(dest
);
421 void bgp_path_info_delete(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
423 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_REMOVED
);
424 /* set of previous already took care of pcount */
425 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
428 /* undo the effects of a previous call to bgp_path_info_delete; typically
429 called when a route is deleted and then quickly re-added before the
430 deletion has been processed */
431 void bgp_path_info_restore(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
433 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_REMOVED
);
434 /* unset of previous already took care of pcount */
435 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
438 /* Adjust pcount as required */
439 static void bgp_pcount_adjust(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
441 struct bgp_table
*table
;
443 assert(dest
&& bgp_dest_table(dest
));
444 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
446 table
= bgp_dest_table(dest
);
448 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
451 if (!BGP_PATH_COUNTABLE(pi
)
452 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
454 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
456 /* slight hack, but more robust against errors. */
457 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
458 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
460 flog_err(EC_LIB_DEVELOPMENT
,
461 "Asked to decrement 0 prefix count for peer");
462 } else if (BGP_PATH_COUNTABLE(pi
)
463 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
464 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
465 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
469 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
470 struct bgp_path_info
*pi2
)
472 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
475 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
476 * This is here primarily to keep prefix-count in check.
478 void bgp_path_info_set_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
481 SET_FLAG(pi
->flags
, flag
);
483 /* early bath if we know it's not a flag that changes countability state
485 if (!CHECK_FLAG(flag
,
486 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
489 bgp_pcount_adjust(dest
, pi
);
492 void bgp_path_info_unset_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
495 UNSET_FLAG(pi
->flags
, flag
);
497 /* early bath if we know it's not a flag that changes countability state
499 if (!CHECK_FLAG(flag
,
500 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
503 bgp_pcount_adjust(dest
, pi
);
506 /* Get MED value. If MED value is missing and "bgp bestpath
507 missing-as-worst" is specified, treat it as the worst value. */
508 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
510 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
513 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
520 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
,
525 if (pi
->sub_type
== BGP_ROUTE_IMPORTED
&&
526 bgp_get_imported_bpi_ultimate(pi
))
527 peer
= bgp_get_imported_bpi_ultimate(pi
)->peer
;
531 if (pi
->addpath_rx_id
)
532 snprintf(buf
, buf_len
, "path %s (addpath rxid %d)", peer
->host
,
535 snprintf(buf
, buf_len
, "path %s", peer
->host
);
540 * Get the ultimate path info.
542 struct bgp_path_info
*bgp_get_imported_bpi_ultimate(struct bgp_path_info
*info
)
544 struct bgp_path_info
*bpi_ultimate
;
546 if (info
->sub_type
!= BGP_ROUTE_IMPORTED
)
549 for (bpi_ultimate
= info
;
550 bpi_ultimate
->extra
&& bpi_ultimate
->extra
->parent
;
551 bpi_ultimate
= bpi_ultimate
->extra
->parent
)
557 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
559 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
560 struct bgp_path_info
*exist
, int *paths_eq
,
561 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
562 char *pfx_buf
, afi_t afi
, safi_t safi
,
563 enum bgp_path_selection_reason
*reason
)
565 const struct prefix
*new_p
;
566 struct attr
*newattr
, *existattr
;
567 enum bgp_peer_sort new_sort
;
568 enum bgp_peer_sort exist_sort
;
574 uint32_t exist_weight
;
575 uint32_t newm
, existm
;
576 struct in_addr new_id
;
577 struct in_addr exist_id
;
580 int internal_as_route
;
583 int igp_metric_ret
= 0;
584 int peer_sort_ret
= -1;
585 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
586 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
588 uint32_t exist_mm_seq
;
595 bool new_origin
, exist_origin
;
596 struct bgp_path_info
*bpi_ultimate
;
597 struct peer
*peer_new
, *peer_exist
;
603 *reason
= bgp_path_selection_none
;
605 zlog_debug("%s: new is NULL", pfx_buf
);
610 bpi_ultimate
= bgp_get_imported_bpi_ultimate(new);
611 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, new_buf
,
616 *reason
= bgp_path_selection_first
;
618 zlog_debug("%s(%s): %s is the initial bestpath",
619 pfx_buf
, bgp
->name_pretty
, new_buf
);
624 bpi_ultimate
= bgp_get_imported_bpi_ultimate(exist
);
625 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, exist_buf
,
627 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
628 pfx_buf
, bgp
->name_pretty
, new_buf
, new->flags
,
629 exist_buf
, exist
->flags
);
633 existattr
= exist
->attr
;
635 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
636 * Capability" to a neighbor MUST perform the following upon receiving
637 * a route from that neighbor with the "LLGR_STALE" community, or upon
638 * attaching the "LLGR_STALE" community itself per Section 4.2:
640 * Treat the route as the least-preferred in route selection (see
641 * below). See the Risks of Depreferencing Routes section (Section 5.2)
642 * for a discussion of potential risks inherent in doing this.
644 if (bgp_attr_get_community(newattr
) &&
645 community_include(bgp_attr_get_community(newattr
),
646 COMMUNITY_LLGR_STALE
)) {
649 "%s: %s wins over %s due to LLGR_STALE community",
650 pfx_buf
, new_buf
, exist_buf
);
654 if (bgp_attr_get_community(existattr
) &&
655 community_include(bgp_attr_get_community(existattr
),
656 COMMUNITY_LLGR_STALE
)) {
659 "%s: %s loses to %s due to LLGR_STALE community",
660 pfx_buf
, new_buf
, exist_buf
);
664 new_p
= bgp_dest_get_prefix(new->net
);
666 /* For EVPN routes, we cannot just go by local vs remote, we have to
667 * look at the MAC mobility sequence number, if present.
669 if ((safi
== SAFI_EVPN
)
670 && (new_p
->u
.prefix_evpn
.route_type
== BGP_EVPN_MAC_IP_ROUTE
)) {
671 /* This is an error condition described in RFC 7432 Section
673 * states that in this scenario "the PE MUST alert the operator"
675 * does not state what other action to take. In order to provide
677 * consistency in this scenario we are going to prefer the path
681 if (newattr
->sticky
!= existattr
->sticky
) {
683 prefix2str(new_p
, pfx_buf
,
685 * PREFIX2STR_BUFFER
);
686 bgp_path_info_path_with_addpath_rx_str(
687 new, new_buf
, sizeof(new_buf
));
688 bgp_path_info_path_with_addpath_rx_str(
689 exist
, exist_buf
, sizeof(exist_buf
));
692 if (newattr
->sticky
&& !existattr
->sticky
) {
693 *reason
= bgp_path_selection_evpn_sticky_mac
;
696 "%s: %s wins over %s due to sticky MAC flag",
697 pfx_buf
, new_buf
, exist_buf
);
701 if (!newattr
->sticky
&& existattr
->sticky
) {
702 *reason
= bgp_path_selection_evpn_sticky_mac
;
705 "%s: %s loses to %s due to sticky MAC flag",
706 pfx_buf
, new_buf
, exist_buf
);
711 new_esi
= bgp_evpn_attr_get_esi(newattr
);
712 exist_esi
= bgp_evpn_attr_get_esi(existattr
);
713 if (bgp_evpn_is_esi_valid(new_esi
) &&
714 !memcmp(new_esi
, exist_esi
, sizeof(esi_t
))) {
720 /* If both paths have the same non-zero ES and
721 * one path is local it wins.
722 * PS: Note the local path wins even if the remote
723 * has the higher MM seq. The local path's
724 * MM seq will be fixed up to match the highest
725 * rem seq, subsequently.
728 char esi_buf
[ESI_STR_LEN
];
730 if (bgp_evpn_is_path_local(bgp
, new)) {
731 *reason
= bgp_path_selection_evpn_local_path
;
734 "%s: %s wins over %s as ES %s is same and local",
735 pfx_buf
, new_buf
, exist_buf
,
736 esi_to_str(new_esi
, esi_buf
,
740 if (bgp_evpn_is_path_local(bgp
, exist
)) {
741 *reason
= bgp_path_selection_evpn_local_path
;
744 "%s: %s loses to %s as ES %s is same and local",
745 pfx_buf
, new_buf
, exist_buf
,
746 esi_to_str(new_esi
, esi_buf
,
752 new_mm_seq
= mac_mobility_seqnum(newattr
);
753 exist_mm_seq
= mac_mobility_seqnum(existattr
);
755 if (new_mm_seq
> exist_mm_seq
) {
756 *reason
= bgp_path_selection_evpn_seq
;
759 "%s: %s wins over %s due to MM seq %u > %u",
760 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
765 if (new_mm_seq
< exist_mm_seq
) {
766 *reason
= bgp_path_selection_evpn_seq
;
769 "%s: %s loses to %s due to MM seq %u < %u",
770 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
775 /* if the sequence numbers and ESI are the same and one path
776 * is non-proxy it wins (over proxy)
778 new_proxy
= bgp_evpn_attr_is_proxy(newattr
);
779 old_proxy
= bgp_evpn_attr_is_proxy(existattr
);
780 if (same_esi
&& bgp_evpn_attr_is_local_es(newattr
) &&
781 old_proxy
!= new_proxy
) {
783 *reason
= bgp_path_selection_evpn_non_proxy
;
786 "%s: %s wins over %s, same seq/es and non-proxy",
787 pfx_buf
, new_buf
, exist_buf
);
791 *reason
= bgp_path_selection_evpn_non_proxy
;
794 "%s: %s loses to %s, same seq/es and non-proxy",
795 pfx_buf
, new_buf
, exist_buf
);
800 * if sequence numbers are the same path with the lowest IP
803 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
805 *reason
= bgp_path_selection_evpn_lower_ip
;
808 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
809 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
810 &new->attr
->nexthop
);
814 *reason
= bgp_path_selection_evpn_lower_ip
;
817 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
818 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
819 &new->attr
->nexthop
);
824 /* 1. Weight check. */
825 new_weight
= newattr
->weight
;
826 exist_weight
= existattr
->weight
;
828 if (new_weight
> exist_weight
) {
829 *reason
= bgp_path_selection_weight
;
831 zlog_debug("%s: %s wins over %s due to weight %d > %d",
832 pfx_buf
, new_buf
, exist_buf
, new_weight
,
837 if (new_weight
< exist_weight
) {
838 *reason
= bgp_path_selection_weight
;
840 zlog_debug("%s: %s loses to %s due to weight %d < %d",
841 pfx_buf
, new_buf
, exist_buf
, new_weight
,
846 /* 2. Local preference check. */
847 new_pref
= exist_pref
= bgp
->default_local_pref
;
849 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
850 new_pref
= newattr
->local_pref
;
851 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
852 exist_pref
= existattr
->local_pref
;
854 if (new_pref
> exist_pref
) {
855 *reason
= bgp_path_selection_local_pref
;
858 "%s: %s wins over %s due to localpref %d > %d",
859 pfx_buf
, new_buf
, exist_buf
, new_pref
,
864 if (new_pref
< exist_pref
) {
865 *reason
= bgp_path_selection_local_pref
;
868 "%s: %s loses to %s due to localpref %d < %d",
869 pfx_buf
, new_buf
, exist_buf
, new_pref
,
874 /* If a BGP speaker supports ACCEPT_OWN and is configured for the
875 * extensions defined in this document, the following step is inserted
876 * after the LOCAL_PREF comparison step in the BGP decision process:
877 * When comparing a pair of routes for a BGP destination, the
878 * route with the ACCEPT_OWN community attached is preferred over
879 * the route that does not have the community.
880 * This extra step MUST only be invoked during the best path selection
881 * process of VPN-IP routes.
883 if (safi
== SAFI_MPLS_VPN
&&
884 (CHECK_FLAG(new->peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
) ||
885 CHECK_FLAG(exist
->peer
->af_flags
[afi
][safi
],
886 PEER_FLAG_ACCEPT_OWN
))) {
887 bool new_accept_own
= false;
888 bool exist_accept_own
= false;
889 uint32_t accept_own
= COMMUNITY_ACCEPT_OWN
;
891 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))
892 new_accept_own
= community_include(
893 bgp_attr_get_community(newattr
), accept_own
);
894 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))
895 exist_accept_own
= community_include(
896 bgp_attr_get_community(existattr
), accept_own
);
898 if (new_accept_own
&& !exist_accept_own
) {
899 *reason
= bgp_path_selection_accept_own
;
902 "%s: %s wins over %s due to accept-own",
903 pfx_buf
, new_buf
, exist_buf
);
907 if (!new_accept_own
&& exist_accept_own
) {
908 *reason
= bgp_path_selection_accept_own
;
911 "%s: %s loses to %s due to accept-own",
912 pfx_buf
, new_buf
, exist_buf
);
917 /* Tie-breaker - AIGP (Metric TLV) attribute */
918 if (CHECK_FLAG(newattr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) &&
919 CHECK_FLAG(existattr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) &&
920 CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_AIGP
)) {
921 uint64_t new_aigp
= bgp_attr_get_aigp_metric(newattr
);
922 uint64_t exist_aigp
= bgp_attr_get_aigp_metric(existattr
);
924 if (new_aigp
< exist_aigp
) {
925 *reason
= bgp_path_selection_aigp
;
928 "%s: %s wins over %s due to AIGP %" PRIu64
930 pfx_buf
, new_buf
, exist_buf
, new_aigp
,
935 if (new_aigp
> exist_aigp
) {
936 *reason
= bgp_path_selection_aigp
;
939 "%s: %s loses to %s due to AIGP %" PRIu64
941 pfx_buf
, new_buf
, exist_buf
, new_aigp
,
947 /* 3. Local route check. We prefer:
949 * - BGP_ROUTE_AGGREGATE
950 * - BGP_ROUTE_REDISTRIBUTE
952 new_origin
= !(new->sub_type
== BGP_ROUTE_NORMAL
||
953 new->sub_type
== BGP_ROUTE_IMPORTED
);
954 exist_origin
= !(exist
->sub_type
== BGP_ROUTE_NORMAL
||
955 exist
->sub_type
== BGP_ROUTE_IMPORTED
);
957 if (new_origin
&& !exist_origin
) {
958 *reason
= bgp_path_selection_local_route
;
961 "%s: %s wins over %s due to preferred BGP_ROUTE type",
962 pfx_buf
, new_buf
, exist_buf
);
966 if (!new_origin
&& exist_origin
) {
967 *reason
= bgp_path_selection_local_route
;
970 "%s: %s loses to %s due to preferred BGP_ROUTE type",
971 pfx_buf
, new_buf
, exist_buf
);
975 /* Here if these are imported routes then get ultimate pi for
978 new = bgp_get_imported_bpi_ultimate(new);
979 exist
= bgp_get_imported_bpi_ultimate(exist
);
981 existattr
= exist
->attr
;
983 /* 4. AS path length check. */
984 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
985 int exist_hops
= aspath_count_hops(existattr
->aspath
);
986 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
988 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
991 aspath_hops
= aspath_count_hops(newattr
->aspath
);
992 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
994 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
995 *reason
= bgp_path_selection_confed_as_path
;
998 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
999 pfx_buf
, new_buf
, exist_buf
,
1001 (exist_hops
+ exist_confeds
));
1005 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
1006 *reason
= bgp_path_selection_confed_as_path
;
1009 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
1010 pfx_buf
, new_buf
, exist_buf
,
1012 (exist_hops
+ exist_confeds
));
1016 int newhops
= aspath_count_hops(newattr
->aspath
);
1018 if (newhops
< exist_hops
) {
1019 *reason
= bgp_path_selection_as_path
;
1022 "%s: %s wins over %s due to aspath hopcount %d < %d",
1023 pfx_buf
, new_buf
, exist_buf
,
1024 newhops
, exist_hops
);
1028 if (newhops
> exist_hops
) {
1029 *reason
= bgp_path_selection_as_path
;
1032 "%s: %s loses to %s due to aspath hopcount %d > %d",
1033 pfx_buf
, new_buf
, exist_buf
,
1034 newhops
, exist_hops
);
1040 /* 5. Origin check. */
1041 if (newattr
->origin
< existattr
->origin
) {
1042 *reason
= bgp_path_selection_origin
;
1044 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
1045 pfx_buf
, new_buf
, exist_buf
,
1046 bgp_origin_long_str
[newattr
->origin
],
1047 bgp_origin_long_str
[existattr
->origin
]);
1051 if (newattr
->origin
> existattr
->origin
) {
1052 *reason
= bgp_path_selection_origin
;
1054 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
1055 pfx_buf
, new_buf
, exist_buf
,
1056 bgp_origin_long_str
[newattr
->origin
],
1057 bgp_origin_long_str
[existattr
->origin
]);
1062 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
1063 && aspath_count_hops(existattr
->aspath
) == 0);
1064 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
1065 && aspath_count_confeds(existattr
->aspath
) > 0
1066 && aspath_count_hops(newattr
->aspath
) == 0
1067 && aspath_count_hops(existattr
->aspath
) == 0);
1069 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
1070 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
1071 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
1072 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
1073 || internal_as_route
) {
1074 new_med
= bgp_med_value(new->attr
, bgp
);
1075 exist_med
= bgp_med_value(exist
->attr
, bgp
);
1077 if (new_med
< exist_med
) {
1078 *reason
= bgp_path_selection_med
;
1081 "%s: %s wins over %s due to MED %d < %d",
1082 pfx_buf
, new_buf
, exist_buf
, new_med
,
1087 if (new_med
> exist_med
) {
1088 *reason
= bgp_path_selection_med
;
1091 "%s: %s loses to %s due to MED %d > %d",
1092 pfx_buf
, new_buf
, exist_buf
, new_med
,
1098 if (exist
->sub_type
== BGP_ROUTE_IMPORTED
) {
1099 bpi_ultimate
= bgp_get_imported_bpi_ultimate(exist
);
1100 peer_exist
= bpi_ultimate
->peer
;
1102 peer_exist
= exist
->peer
;
1104 if (new->sub_type
== BGP_ROUTE_IMPORTED
) {
1105 bpi_ultimate
= bgp_get_imported_bpi_ultimate(new);
1106 peer_new
= bpi_ultimate
->peer
;
1108 peer_new
= new->peer
;
1110 /* 7. Peer type check. */
1111 new_sort
= peer_new
->sort
;
1112 exist_sort
= peer_exist
->sort
;
1114 if (new_sort
== BGP_PEER_EBGP
1115 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
1116 *reason
= bgp_path_selection_peer
;
1119 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1120 pfx_buf
, new_buf
, exist_buf
);
1121 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1126 if (exist_sort
== BGP_PEER_EBGP
1127 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
1128 *reason
= bgp_path_selection_peer
;
1131 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1132 pfx_buf
, new_buf
, exist_buf
);
1133 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1138 /* 8. IGP metric check. */
1142 newm
= new->extra
->igpmetric
;
1144 existm
= exist
->extra
->igpmetric
;
1146 if (newm
< existm
) {
1147 if (debug
&& peer_sort_ret
< 0)
1149 "%s: %s wins over %s due to IGP metric %u < %u",
1150 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1154 if (newm
> existm
) {
1155 if (debug
&& peer_sort_ret
< 0)
1157 "%s: %s loses to %s due to IGP metric %u > %u",
1158 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1162 /* 9. Same IGP metric. Compare the cluster list length as
1163 representative of IGP hops metric. Rewrite the metric value
1164 pair (newm, existm) with the cluster list length. Prefer the
1165 path with smaller cluster list length. */
1166 if (newm
== existm
) {
1167 if (peer_sort_lookup(peer_new
) == BGP_PEER_IBGP
&&
1168 peer_sort_lookup(peer_exist
) == BGP_PEER_IBGP
&&
1169 (mpath_cfg
== NULL
|| mpath_cfg
->same_clusterlen
)) {
1170 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1171 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1173 if (newm
< existm
) {
1174 if (debug
&& peer_sort_ret
< 0)
1176 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
1177 pfx_buf
, new_buf
, exist_buf
,
1182 if (newm
> existm
) {
1183 if (debug
&& peer_sort_ret
< 0)
1185 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
1186 pfx_buf
, new_buf
, exist_buf
,
1193 /* 10. confed-external vs. confed-internal */
1194 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1195 if (new_sort
== BGP_PEER_CONFED
1196 && exist_sort
== BGP_PEER_IBGP
) {
1197 *reason
= bgp_path_selection_confed
;
1200 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1201 pfx_buf
, new_buf
, exist_buf
);
1202 if (!CHECK_FLAG(bgp
->flags
,
1203 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1208 if (exist_sort
== BGP_PEER_CONFED
1209 && new_sort
== BGP_PEER_IBGP
) {
1210 *reason
= bgp_path_selection_confed
;
1213 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1214 pfx_buf
, new_buf
, exist_buf
);
1215 if (!CHECK_FLAG(bgp
->flags
,
1216 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1222 /* 11. Maximum path check. */
1223 if (newm
== existm
) {
1224 /* If one path has a label but the other does not, do not treat
1225 * them as equals for multipath
1232 newl
= new->extra
->num_labels
;
1234 existl
= exist
->extra
->num_labels
;
1235 if (((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0])) !=
1237 bgp_is_valid_label(&exist
->extra
->label
[0]))) ||
1241 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1242 pfx_buf
, new_buf
, exist_buf
);
1243 } else if (CHECK_FLAG(bgp
->flags
,
1244 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
1247 * For the two paths, all comparison steps till IGP
1249 * have succeeded - including AS_PATH hop count. Since
1251 * bestpath as-path multipath-relax' knob is on, we
1253 * an exact match of AS_PATH. Thus, mark the paths are
1255 * That will trigger both these paths to get into the
1263 "%s: %s and %s are equal via multipath-relax",
1264 pfx_buf
, new_buf
, exist_buf
);
1265 } else if (peer_new
->sort
== BGP_PEER_IBGP
) {
1266 if (aspath_cmp(new->attr
->aspath
,
1267 exist
->attr
->aspath
)) {
1272 "%s: %s and %s are equal via matching aspaths",
1273 pfx_buf
, new_buf
, exist_buf
);
1275 } else if (peer_new
->as
== peer_exist
->as
) {
1280 "%s: %s and %s are equal via same remote-as",
1281 pfx_buf
, new_buf
, exist_buf
);
1285 * TODO: If unequal cost ibgp multipath is enabled we can
1286 * mark the paths as equal here instead of returning
1289 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1290 * if either step 7 or 10 (peer type checks) yielded a winner,
1291 * that result was returned immediately. Returning from step 10
1292 * ignored the return value computed in steps 8 and 9 (IGP
1293 * metric checks). In order to preserve that behavior, if
1294 * peer_sort_ret is set, return that rather than igp_metric_ret.
1296 ret
= peer_sort_ret
;
1297 if (peer_sort_ret
< 0) {
1298 ret
= igp_metric_ret
;
1302 "%s: %s wins over %s after IGP metric comparison",
1303 pfx_buf
, new_buf
, exist_buf
);
1306 "%s: %s loses to %s after IGP metric comparison",
1307 pfx_buf
, new_buf
, exist_buf
);
1309 *reason
= bgp_path_selection_igp_metric
;
1315 * At this point, the decision whether to set *paths_eq = 1 has been
1316 * completed. If we deferred returning because of bestpath peer-type
1317 * relax configuration, return now.
1319 if (peer_sort_ret
>= 0)
1320 return peer_sort_ret
;
1322 /* 12. If both paths are external, prefer the path that was received
1323 first (the oldest one). This step minimizes route-flap, since a
1324 newer path won't displace an older one, even if it was the
1325 preferred route based on the additional decision criteria below. */
1326 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1327 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1328 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1329 *reason
= bgp_path_selection_older
;
1332 "%s: %s wins over %s due to oldest external",
1333 pfx_buf
, new_buf
, exist_buf
);
1337 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1338 *reason
= bgp_path_selection_older
;
1341 "%s: %s loses to %s due to oldest external",
1342 pfx_buf
, new_buf
, exist_buf
);
1347 /* 13. Router-ID comparison. */
1348 /* If one of the paths is "stale", the corresponding peer router-id will
1349 * be 0 and would always win over the other path. If originator id is
1350 * used for the comparison, it will decide which path is better.
1352 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1353 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1355 new_id
.s_addr
= peer_new
->remote_id
.s_addr
;
1356 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1357 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1359 exist_id
.s_addr
= peer_exist
->remote_id
.s_addr
;
1361 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1362 *reason
= bgp_path_selection_router_id
;
1365 "%s: %s wins over %s due to Router-ID comparison",
1366 pfx_buf
, new_buf
, exist_buf
);
1370 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1371 *reason
= bgp_path_selection_router_id
;
1374 "%s: %s loses to %s due to Router-ID comparison",
1375 pfx_buf
, new_buf
, exist_buf
);
1379 /* 14. Cluster length comparison. */
1380 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1381 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1383 if (new_cluster
< exist_cluster
) {
1384 *reason
= bgp_path_selection_cluster_length
;
1387 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1388 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1393 if (new_cluster
> exist_cluster
) {
1394 *reason
= bgp_path_selection_cluster_length
;
1397 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1398 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1403 /* 15. Neighbor address comparison. */
1404 /* Do this only if neither path is "stale" as stale paths do not have
1405 * valid peer information (as the connection may or may not be up).
1407 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1408 *reason
= bgp_path_selection_stale
;
1411 "%s: %s wins over %s due to latter path being STALE",
1412 pfx_buf
, new_buf
, exist_buf
);
1416 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1417 *reason
= bgp_path_selection_stale
;
1420 "%s: %s loses to %s due to former path being STALE",
1421 pfx_buf
, new_buf
, exist_buf
);
1425 /* locally configured routes to advertise do not have su_remote */
1426 if (peer_new
->su_remote
== NULL
) {
1427 *reason
= bgp_path_selection_local_configured
;
1431 if (peer_exist
->su_remote
== NULL
) {
1432 *reason
= bgp_path_selection_local_configured
;
1436 ret
= sockunion_cmp(peer_new
->su_remote
, peer_exist
->su_remote
);
1439 *reason
= bgp_path_selection_neighbor_ip
;
1442 "%s: %s loses to %s due to Neighor IP comparison",
1443 pfx_buf
, new_buf
, exist_buf
);
1448 *reason
= bgp_path_selection_neighbor_ip
;
1451 "%s: %s wins over %s due to Neighor IP comparison",
1452 pfx_buf
, new_buf
, exist_buf
);
1456 *reason
= bgp_path_selection_default
;
1458 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1459 pfx_buf
, new_buf
, exist_buf
);
1465 int bgp_evpn_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
1466 struct bgp_path_info
*exist
, int *paths_eq
)
1468 enum bgp_path_selection_reason reason
;
1469 char pfx_buf
[PREFIX2STR_BUFFER
];
1471 return bgp_path_info_cmp(bgp
, new, exist
, paths_eq
, NULL
, 0, pfx_buf
,
1472 AFI_L2VPN
, SAFI_EVPN
, &reason
);
1475 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1476 * is preferred, or 0 if they are the same (usually will only occur if
1477 * multipath is enabled
1478 * This version is compatible with */
1479 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1480 struct bgp_path_info
*exist
, char *pfx_buf
,
1481 afi_t afi
, safi_t safi
,
1482 enum bgp_path_selection_reason
*reason
)
1486 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1500 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1501 const struct prefix
*p
,
1502 struct attr
*attr
, afi_t afi
,
1505 struct bgp_filter
*filter
;
1506 enum filter_type ret
= FILTER_PERMIT
;
1508 filter
= &peer
->filter
[afi
][safi
];
1510 #define FILTER_EXIST_WARN(F, f, filter) \
1511 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1512 zlog_debug("%s: Could not find configured input %s-list %s!", \
1513 peer->host, #f, F##_IN_NAME(filter));
1515 if (DISTRIBUTE_IN_NAME(filter
)) {
1516 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1518 if (access_list_apply(DISTRIBUTE_IN(filter
), p
)
1525 if (PREFIX_LIST_IN_NAME(filter
)) {
1526 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1528 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
)
1535 if (FILTER_LIST_IN_NAME(filter
)) {
1536 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1538 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1539 == AS_FILTER_DENY
) {
1546 if (frrtrace_enabled(frr_bgp
, input_filter
)) {
1547 char pfxprint
[PREFIX2STR_BUFFER
];
1549 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1550 frrtrace(5, frr_bgp
, input_filter
, peer
, pfxprint
, afi
, safi
,
1551 ret
== FILTER_PERMIT
? "permit" : "deny");
1555 #undef FILTER_EXIST_WARN
1558 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1559 const struct prefix
*p
,
1560 struct attr
*attr
, afi_t afi
,
1563 struct bgp_filter
*filter
;
1564 enum filter_type ret
= FILTER_PERMIT
;
1566 filter
= &peer
->filter
[afi
][safi
];
1568 #define FILTER_EXIST_WARN(F, f, filter) \
1569 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1570 zlog_debug("%s: Could not find configured output %s-list %s!", \
1571 peer->host, #f, F##_OUT_NAME(filter));
1573 if (DISTRIBUTE_OUT_NAME(filter
)) {
1574 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1576 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
)
1583 if (PREFIX_LIST_OUT_NAME(filter
)) {
1584 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1586 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1593 if (FILTER_LIST_OUT_NAME(filter
)) {
1594 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1596 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1597 == AS_FILTER_DENY
) {
1603 if (frrtrace_enabled(frr_bgp
, output_filter
)) {
1604 char pfxprint
[PREFIX2STR_BUFFER
];
1606 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1607 frrtrace(5, frr_bgp
, output_filter
, peer
, pfxprint
, afi
, safi
,
1608 ret
== FILTER_PERMIT
? "permit" : "deny");
1613 #undef FILTER_EXIST_WARN
1616 /* If community attribute includes no_export then return 1. */
1617 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1619 if (bgp_attr_get_community(attr
)) {
1620 /* NO_ADVERTISE check. */
1621 if (community_include(bgp_attr_get_community(attr
),
1622 COMMUNITY_NO_ADVERTISE
))
1625 /* NO_EXPORT check. */
1626 if (peer
->sort
== BGP_PEER_EBGP
&&
1627 community_include(bgp_attr_get_community(attr
),
1628 COMMUNITY_NO_EXPORT
))
1631 /* NO_EXPORT_SUBCONFED check. */
1632 if (peer
->sort
== BGP_PEER_EBGP
1633 || peer
->sort
== BGP_PEER_CONFED
)
1634 if (community_include(bgp_attr_get_community(attr
),
1635 COMMUNITY_NO_EXPORT_SUBCONFED
))
1641 /* Route reflection loop check. */
1642 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1644 struct in_addr cluster_id
;
1645 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1648 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1649 cluster_id
= peer
->bgp
->cluster_id
;
1651 cluster_id
= peer
->bgp
->router_id
;
1653 if (cluster_loop_check(cluster
, cluster_id
))
1659 static bool bgp_otc_filter(struct peer
*peer
, struct attr
*attr
)
1661 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1662 if (peer
->local_role
== ROLE_PROVIDER
||
1663 peer
->local_role
== ROLE_RS_SERVER
)
1665 if (peer
->local_role
== ROLE_PEER
&& attr
->otc
!= peer
->as
)
1669 if (peer
->local_role
== ROLE_CUSTOMER
||
1670 peer
->local_role
== ROLE_PEER
||
1671 peer
->local_role
== ROLE_RS_CLIENT
) {
1672 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1673 attr
->otc
= peer
->as
;
1678 static bool bgp_otc_egress(struct peer
*peer
, struct attr
*attr
)
1680 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1681 if (peer
->local_role
== ROLE_CUSTOMER
||
1682 peer
->local_role
== ROLE_RS_CLIENT
||
1683 peer
->local_role
== ROLE_PEER
)
1687 if (peer
->local_role
== ROLE_PROVIDER
||
1688 peer
->local_role
== ROLE_PEER
||
1689 peer
->local_role
== ROLE_RS_SERVER
) {
1690 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1691 attr
->otc
= peer
->bgp
->as
;
1696 static bool bgp_check_role_applicability(afi_t afi
, safi_t safi
)
1698 return ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_UNICAST
);
1701 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1702 struct attr
*attr
, afi_t afi
, safi_t safi
,
1703 const char *rmap_name
, mpls_label_t
*label
,
1704 uint32_t num_labels
, struct bgp_dest
*dest
)
1706 struct bgp_filter
*filter
;
1707 struct bgp_path_info rmap_path
= { 0 };
1708 struct bgp_path_info_extra extra
= { 0 };
1709 route_map_result_t ret
;
1710 struct route_map
*rmap
= NULL
;
1712 filter
= &peer
->filter
[afi
][safi
];
1714 /* Apply default weight value. */
1715 if (peer
->weight
[afi
][safi
])
1716 attr
->weight
= peer
->weight
[afi
][safi
];
1719 rmap
= route_map_lookup_by_name(rmap_name
);
1724 if (ROUTE_MAP_IN_NAME(filter
)) {
1725 rmap
= ROUTE_MAP_IN(filter
);
1732 /* Route map apply. */
1734 memset(&rmap_path
, 0, sizeof(rmap_path
));
1735 /* Duplicate current value to new structure for modification. */
1736 rmap_path
.peer
= peer
;
1737 rmap_path
.attr
= attr
;
1738 rmap_path
.extra
= &extra
;
1739 rmap_path
.net
= dest
;
1741 extra
.num_labels
= num_labels
;
1742 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1743 memcpy(extra
.label
, label
,
1744 num_labels
* sizeof(mpls_label_t
));
1746 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1748 /* Apply BGP route map to the attribute. */
1749 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1751 peer
->rmap_type
= 0;
1753 if (ret
== RMAP_DENYMATCH
)
1759 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1760 struct attr
*attr
, afi_t afi
, safi_t safi
,
1761 const char *rmap_name
)
1763 struct bgp_path_info rmap_path
;
1764 route_map_result_t ret
;
1765 struct route_map
*rmap
= NULL
;
1769 * So if we get to this point and have no rmap_name
1770 * we want to just show the output as it currently
1776 /* Apply default weight value. */
1777 if (peer
->weight
[afi
][safi
])
1778 attr
->weight
= peer
->weight
[afi
][safi
];
1780 rmap
= route_map_lookup_by_name(rmap_name
);
1783 * If we have a route map name and we do not find
1784 * the routemap that means we have an implicit
1790 memset(&rmap_path
, 0, sizeof(rmap_path
));
1791 /* Route map apply. */
1792 /* Duplicate current value to new structure for modification. */
1793 rmap_path
.peer
= peer
;
1794 rmap_path
.attr
= attr
;
1796 rmap_type
= peer
->rmap_type
;
1797 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1799 /* Apply BGP route map to the attribute. */
1800 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1802 peer
->rmap_type
= rmap_type
;
1804 if (ret
== RMAP_DENYMATCH
)
1806 * caller has multiple error paths with bgp_attr_flush()
1813 /* If this is an EBGP peer with remove-private-AS */
1814 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1815 struct peer
*peer
, struct attr
*attr
)
1817 if (peer
->sort
== BGP_PEER_EBGP
1818 && (peer_af_flag_check(peer
, afi
, safi
,
1819 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1820 || peer_af_flag_check(peer
, afi
, safi
,
1821 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1822 || peer_af_flag_check(peer
, afi
, safi
,
1823 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1824 || peer_af_flag_check(peer
, afi
, safi
,
1825 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1826 // Take action on the entire aspath
1827 if (peer_af_flag_check(peer
, afi
, safi
,
1828 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1829 || peer_af_flag_check(peer
, afi
, safi
,
1830 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1831 if (peer_af_flag_check(
1833 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1834 attr
->aspath
= aspath_replace_private_asns(
1835 attr
->aspath
, bgp
->as
, peer
->as
);
1838 * Even if the aspath consists of just private ASNs we
1839 * need to walk the AS-Path to maintain all instances
1840 * of the peer's ASN to break possible loops.
1843 attr
->aspath
= aspath_remove_private_asns(
1844 attr
->aspath
, peer
->as
);
1847 // 'all' was not specified so the entire aspath must be private
1849 // for us to do anything
1850 else if (aspath_private_as_check(attr
->aspath
)) {
1851 if (peer_af_flag_check(
1853 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1854 attr
->aspath
= aspath_replace_private_asns(
1855 attr
->aspath
, bgp
->as
, peer
->as
);
1858 * Walk the aspath to retain any instances of
1861 attr
->aspath
= aspath_remove_private_asns(
1862 attr
->aspath
, peer
->as
);
1867 /* If this is an EBGP peer with as-override */
1868 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1869 struct peer
*peer
, struct attr
*attr
)
1871 struct aspath
*aspath
;
1873 if (peer
->sort
== BGP_PEER_EBGP
&&
1874 peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1875 if (attr
->aspath
->refcnt
)
1876 aspath
= aspath_dup(attr
->aspath
);
1878 aspath
= attr
->aspath
;
1880 attr
->aspath
= aspath_intern(
1881 aspath_replace_specific_asn(aspath
, peer
->as
, bgp
->as
));
1883 aspath_free(aspath
);
1887 void bgp_attr_add_llgr_community(struct attr
*attr
)
1889 struct community
*old
;
1890 struct community
*new;
1891 struct community
*merge
;
1892 struct community
*llgr
;
1894 old
= bgp_attr_get_community(attr
);
1895 llgr
= community_str2com("llgr-stale");
1900 merge
= community_merge(community_dup(old
), llgr
);
1902 if (old
->refcnt
== 0)
1903 community_free(&old
);
1905 new = community_uniq_sort(merge
);
1906 community_free(&merge
);
1908 new = community_dup(llgr
);
1911 community_free(&llgr
);
1913 bgp_attr_set_community(attr
, new);
1916 void bgp_attr_add_gshut_community(struct attr
*attr
)
1918 struct community
*old
;
1919 struct community
*new;
1920 struct community
*merge
;
1921 struct community
*gshut
;
1923 old
= bgp_attr_get_community(attr
);
1924 gshut
= community_str2com("graceful-shutdown");
1929 merge
= community_merge(community_dup(old
), gshut
);
1931 if (old
->refcnt
== 0)
1932 community_free(&old
);
1934 new = community_uniq_sort(merge
);
1935 community_free(&merge
);
1937 new = community_dup(gshut
);
1940 community_free(&gshut
);
1941 bgp_attr_set_community(attr
, new);
1943 /* When we add the graceful-shutdown community we must also
1944 * lower the local-preference */
1945 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1946 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1950 /* Notify BGP Conditional advertisement scanner process. */
1951 void bgp_notify_conditional_adv_scanner(struct update_subgroup
*subgrp
)
1953 struct peer
*peer
= SUBGRP_PEER(subgrp
);
1954 afi_t afi
= SUBGRP_AFI(subgrp
);
1955 safi_t safi
= SUBGRP_SAFI(subgrp
);
1956 struct bgp_filter
*filter
= &peer
->filter
[afi
][safi
];
1958 if (!ADVERTISE_MAP_NAME(filter
))
1961 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
))
1964 peer
->advmap_table_change
= true;
1968 void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1970 if (family
== AF_INET
) {
1971 attr
->nexthop
.s_addr
= INADDR_ANY
;
1972 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1974 if (family
== AF_INET6
)
1975 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1976 if (family
== AF_EVPN
)
1977 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1980 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
1981 struct update_subgroup
*subgrp
,
1982 const struct prefix
*p
, struct attr
*attr
,
1983 struct attr
*post_attr
)
1985 struct bgp_filter
*filter
;
1988 struct peer
*onlypeer
;
1990 struct attr
*piattr
;
1991 route_map_result_t ret
;
1996 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1997 bool nh_reset
= false;
2000 if (DISABLE_BGP_ANNOUNCE
)
2003 afi
= SUBGRP_AFI(subgrp
);
2004 safi
= SUBGRP_SAFI(subgrp
);
2005 peer
= SUBGRP_PEER(subgrp
);
2007 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
2008 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
2011 filter
= &peer
->filter
[afi
][safi
];
2012 bgp
= SUBGRP_INST(subgrp
);
2013 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
2016 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX_OUT
) &&
2017 peer
->pmax_out
[afi
][safi
] != 0 &&
2018 subgrp
->pscount
>= peer
->pmax_out
[afi
][safi
]) {
2019 if (BGP_DEBUG(update
, UPDATE_OUT
) ||
2020 BGP_DEBUG(update
, UPDATE_PREFIX
)) {
2021 zlog_debug("%s reached maximum prefix to be send (%u)",
2022 peer
->host
, peer
->pmax_out
[afi
][safi
]);
2027 #ifdef ENABLE_BGP_VNC
2028 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
2029 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
2030 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
2033 * direct and direct_ext type routes originate internally even
2034 * though they can have peer pointers that reference other
2037 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
2043 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
2044 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
2045 && (pi
->type
== ZEBRA_ROUTE_BGP
)
2046 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2048 /* Applies to routes leaked vpn->vrf and vrf->vpn */
2053 /* With addpath we may be asked to TX all kinds of paths so make sure
2055 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
2056 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
2057 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
2061 /* If this is not the bestpath then check to see if there is an enabled
2063 * feature that requires us to advertise it */
2064 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2065 if (!bgp_addpath_capable(pi
, peer
, afi
, safi
))
2068 /* Aggregate-address suppress check. */
2069 if (bgp_path_suppressed(pi
) && !UNSUPPRESS_MAP_NAME(filter
))
2073 * If we are doing VRF 2 VRF leaking via the import
2074 * statement, we want to prevent the route going
2075 * off box as that the RT and RD created are localy
2076 * significant and globaly useless.
2078 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
2079 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
2082 /* If it's labeled safi, make sure the route has a valid label. */
2083 if (safi
== SAFI_LABELED_UNICAST
) {
2084 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
2085 if (!bgp_is_valid_label(&label
)) {
2086 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2087 zlog_debug("u%" PRIu64
":s%" PRIu64
2088 " %pFX is filtered - no label (%p)",
2089 subgrp
->update_group
->id
, subgrp
->id
,
2095 /* Do not send back route to sender. */
2096 if (onlypeer
&& from
== onlypeer
) {
2100 /* Do not send the default route in the BGP table if the neighbor is
2101 * configured for default-originate */
2102 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2103 PEER_FLAG_DEFAULT_ORIGINATE
)) {
2104 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
2106 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
2110 /* Transparency check. */
2111 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
2112 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
2117 /* If community is not disabled check the no-export and local. */
2118 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
2119 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2120 zlog_debug("%s: community filter check fail for %pFX",
2125 /* If the attribute has originator-id and it is same as remote
2127 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2128 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
2129 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2131 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2136 /* ORF prefix-list filter check */
2137 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
2138 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
2139 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
2140 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
2141 if (peer
->orf_plist
[afi
][safi
]) {
2142 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
2144 if (bgp_debug_update(NULL
, p
,
2145 subgrp
->update_group
, 0))
2147 "%pBP [Update:SEND] %pFX is filtered via ORF",
2153 /* Output filter check. */
2154 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
2155 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2156 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer
,
2161 /* AS path loop check. */
2162 if (peer
->as_path_loop_detection
&&
2163 aspath_loop_check(piattr
->aspath
, peer
->as
)) {
2164 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2166 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2171 /* If we're a CONFED we need to loop check the CONFED ID too */
2172 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
2173 if (aspath_loop_check_confed(piattr
->aspath
, bgp
->confed_id
)) {
2174 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2176 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2177 peer
, bgp
->confed_id
);
2182 /* Route-Reflect check. */
2183 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2188 /* IBGP reflection check. */
2189 if (reflect
&& !samepeer_safe
) {
2190 /* A route from a Client peer. */
2191 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
2192 PEER_FLAG_REFLECTOR_CLIENT
)) {
2193 /* Reflect to all the Non-Client peers and also to the
2194 Client peers other than the originator. Originator
2196 is already done. So there is noting to do. */
2197 /* no bgp client-to-client reflection check. */
2198 if (CHECK_FLAG(bgp
->flags
,
2199 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
2200 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2201 PEER_FLAG_REFLECTOR_CLIENT
))
2204 /* A route from a Non-client peer. Reflect to all other
2206 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2207 PEER_FLAG_REFLECTOR_CLIENT
))
2212 /* For modify attribute, copy it to temporary structure.
2213 * post_attr comes from BGP conditional advertisements, where
2214 * attributes are already processed by advertise-map route-map,
2215 * and this needs to be saved instead of overwriting from the
2223 /* If local-preference is not set. */
2224 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
2225 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
2226 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2227 attr
->local_pref
= bgp
->default_local_pref
;
2230 /* If originator-id is not set and the route is to be reflected,
2231 set the originator id */
2233 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
2234 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
2235 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
2238 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2240 if (peer
->sort
== BGP_PEER_EBGP
2241 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
2242 if (from
!= bgp
->peer_self
&& !transparent
2243 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2244 PEER_FLAG_MED_UNCHANGED
))
2246 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
2249 /* Since the nexthop attribute can vary per peer, it is not explicitly
2251 * in announce check, only certain flags and length (or number of
2253 * -- for IPv6/MP_REACH) are set here in order to guide the update
2255 * code in setting the nexthop(s) on a per peer basis in
2257 * Typically, the source nexthop in the attribute is preserved but in
2259 * scenarios where we know it will always be overwritten, we reset the
2260 * nexthop to "0" in an attempt to achieve better Update packing. An
2261 * example of this is when a prefix from each of 2 IBGP peers needs to
2263 * announced to an EBGP peer (and they have the same attributes barring
2267 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
2269 #define NEXTHOP_IS_V6 \
2270 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2271 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2272 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2273 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2275 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2277 * the peer (group) is configured to receive link-local nexthop
2279 * and it is available in the prefix OR we're not reflecting the route,
2280 * link-local nexthop address is valid and
2281 * the peer (group) to whom we're going to announce is on a shared
2283 * and this is either a self-originated route or the peer is EBGP.
2284 * By checking if nexthop LL address is valid we are sure that
2285 * we do not announce LL address as `::`.
2287 if (NEXTHOP_IS_V6
) {
2288 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2289 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2290 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
2291 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
2292 || (!reflect
&& !transparent
2293 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
2294 && peer
->shared_network
2295 && (from
== bgp
->peer_self
2296 || peer
->sort
== BGP_PEER_EBGP
))) {
2297 if (safi
== SAFI_MPLS_VPN
)
2298 attr
->mp_nexthop_len
=
2299 BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
;
2301 attr
->mp_nexthop_len
=
2302 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2305 /* Clear off link-local nexthop in source, whenever it is not
2307 * ensure more prefixes share the same attribute for
2310 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2311 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
2312 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
2315 if (bgp_check_role_applicability(afi
, safi
) &&
2316 bgp_otc_egress(peer
, attr
))
2319 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
2320 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
2322 if (filter
->advmap
.update_type
== UPDATE_TYPE_WITHDRAW
&&
2323 filter
->advmap
.aname
&&
2324 route_map_lookup_by_name(filter
->advmap
.aname
)) {
2325 struct bgp_path_info rmap_path
= {0};
2326 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2327 struct attr dummy_attr
= *attr
;
2329 /* Fill temp path_info */
2330 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2331 pi
, peer
, &dummy_attr
);
2333 struct route_map
*amap
=
2334 route_map_lookup_by_name(filter
->advmap
.aname
);
2336 ret
= route_map_apply(amap
, p
, &rmap_path
);
2338 bgp_attr_flush(&dummy_attr
);
2341 * The conditional advertisement mode is Withdraw and this
2342 * prefix is a conditional prefix. Don't advertise it
2344 if (ret
== RMAP_PERMITMATCH
)
2348 /* Route map & unsuppress-map apply. */
2350 (ROUTE_MAP_OUT_NAME(filter
) || bgp_path_suppressed(pi
))) {
2351 struct bgp_path_info rmap_path
= {0};
2352 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2353 struct attr dummy_attr
= {0};
2355 /* Fill temp path_info */
2356 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2359 /* don't confuse inbound and outbound setting */
2360 RESET_FLAG(attr
->rmap_change_flags
);
2363 * The route reflector is not allowed to modify the attributes
2364 * of the reflected IBGP routes unless explicitly allowed.
2366 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2367 && !CHECK_FLAG(bgp
->flags
,
2368 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
2370 rmap_path
.attr
= &dummy_attr
;
2373 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
2375 if (bgp_path_suppressed(pi
))
2376 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
2379 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
2382 bgp_attr_flush(&dummy_attr
);
2383 peer
->rmap_type
= 0;
2385 if (ret
== RMAP_DENYMATCH
) {
2386 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2388 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2390 bgp_path_suppressed(pi
)
2391 ? UNSUPPRESS_MAP_NAME(filter
)
2392 : ROUTE_MAP_OUT_NAME(filter
));
2393 bgp_attr_flush(rmap_path
.attr
);
2398 /* RFC 8212 to prevent route leaks.
2399 * This specification intends to improve this situation by requiring the
2400 * explicit configuration of both BGP Import and Export Policies for any
2401 * External BGP (EBGP) session such as customers, peers, or
2402 * confederation boundaries for all enabled address families. Through
2403 * codification of the aforementioned requirement, operators will
2404 * benefit from consistent behavior across different BGP
2407 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2408 if (!bgp_outbound_policy_exists(peer
, filter
)) {
2409 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
2410 NULL
) > FIFTEENMINUTE2USEC
||
2411 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
2413 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2414 monotime(&bgp
->ebgprequirespolicywarning
);
2419 /* draft-ietf-idr-deprecate-as-set-confed-set
2420 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2421 * Eventually, This document (if approved) updates RFC 4271
2422 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2423 * and obsoletes RFC 6472.
2425 if (peer
->bgp
->reject_as_sets
)
2426 if (aspath_check_as_sets(attr
->aspath
))
2429 /* If neighbor soo is configured, then check if the route has
2430 * SoO extended community and validate against the configured
2431 * one. If they match, do not announce, to prevent routing
2434 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) &&
2435 peer
->soo
[afi
][safi
]) {
2436 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
2437 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
2439 if ((ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS
,
2440 ECOMMUNITY_SITE_ORIGIN
) ||
2441 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS4
,
2442 ECOMMUNITY_SITE_ORIGIN
) ||
2443 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_IP
,
2444 ECOMMUNITY_SITE_ORIGIN
)) &&
2445 ecommunity_include(ecomm
, ecomm_soo
)) {
2446 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2448 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2449 peer
, p
, ecommunity_str(ecomm_soo
));
2454 /* Codification of AS 0 Processing */
2455 if (aspath_check_as_zero(attr
->aspath
))
2458 if (bgp_in_graceful_shutdown(bgp
)) {
2459 if (peer
->sort
== BGP_PEER_IBGP
2460 || peer
->sort
== BGP_PEER_CONFED
) {
2461 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2462 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2464 bgp_attr_add_gshut_community(attr
);
2468 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2469 * Capability" to a neighbor MUST perform the following upon receiving
2470 * a route from that neighbor with the "LLGR_STALE" community, or upon
2471 * attaching the "LLGR_STALE" community itself per Section 4.2:
2473 * The route SHOULD NOT be advertised to any neighbor from which the
2474 * Long-lived Graceful Restart Capability has not been received.
2476 if (bgp_attr_get_community(attr
) &&
2477 community_include(bgp_attr_get_community(attr
),
2478 COMMUNITY_LLGR_STALE
) &&
2479 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_RCV
) &&
2480 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_ADV
))
2483 /* After route-map has been applied, we check to see if the nexthop to
2484 * be carried in the attribute (that is used for the announcement) can
2485 * be cleared off or not. We do this in all cases where we would be
2486 * setting the nexthop to "ourselves". For IPv6, we only need to
2488 * the global nexthop here; the link-local nexthop would have been
2490 * already, and if not, it is required by the update formation code.
2491 * Also see earlier comments in this function.
2494 * If route-map has performed some operation on the nexthop or the peer
2495 * configuration says to pass it unchanged, we cannot reset the nexthop
2496 * here, so only attempt to do it if these aren't true. Note that the
2497 * route-map handler itself might have cleared the nexthop, if for
2499 * it is configured as 'peer-address'.
2501 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2502 piattr
->rmap_change_flags
)
2504 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2505 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2506 /* We can reset the nexthop, if setting (or forcing) it to
2508 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2509 PEER_FLAG_NEXTHOP_SELF
)
2510 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2511 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2513 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2514 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2515 subgroup_announce_reset_nhop(
2516 (peer_cap_enhe(peer
, afi
, safi
)
2522 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2523 /* Can also reset the nexthop if announcing to EBGP, but
2525 * no peer in the subgroup is on a shared subnet.
2526 * Note: 3rd party nexthop currently implemented for
2529 if ((p
->family
== AF_INET
) &&
2530 (!bgp_subgrp_multiaccess_check_v4(
2533 subgroup_announce_reset_nhop(
2534 (peer_cap_enhe(peer
, afi
, safi
)
2541 if ((p
->family
== AF_INET6
) &&
2542 (!bgp_subgrp_multiaccess_check_v6(
2543 piattr
->mp_nexthop_global
,
2545 subgroup_announce_reset_nhop(
2546 (peer_cap_enhe(peer
, afi
, safi
)
2555 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2557 * This flag is used for leaked vpn-vrf routes
2559 int family
= p
->family
;
2561 if (peer_cap_enhe(peer
, afi
, safi
))
2564 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2566 "%s: %pFX BGP_PATH_ANNC_NH_SELF, family=%s",
2567 __func__
, p
, family2str(family
));
2568 subgroup_announce_reset_nhop(family
, attr
);
2573 /* If IPv6/MP and nexthop does not have any override and happens
2575 * be a link-local address, reset it so that we don't pass along
2577 * source's link-local IPv6 address to recipients who may not be
2579 * the same interface.
2581 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2582 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2583 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2588 /* If this is an iBGP, send Origin Validation State (OVS)
2589 * extended community (rfc8097).
2591 if (peer
->sort
== BGP_PEER_IBGP
) {
2592 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
2594 rpki_state
= hook_call(bgp_rpki_prefix_status
, peer
, attr
, p
);
2596 if (rpki_state
!= RPKI_NOT_BEING_USED
)
2597 bgp_attr_set_ecommunity(
2598 attr
, ecommunity_add_origin_validation_state(
2600 bgp_attr_get_ecommunity(attr
)));
2604 * When the next hop is set to ourselves, if all multipaths have
2605 * link-bandwidth announce the cumulative bandwidth as that makes
2606 * the most sense. However, don't modify if the link-bandwidth has
2607 * been explicitly set by user policy.
2610 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2611 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2612 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2613 bgp_attr_set_ecommunity(
2615 ecommunity_replace_linkbw(
2616 bgp
->as
, bgp_attr_get_ecommunity(attr
), cum_bw
,
2619 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
)));
2624 static void bgp_route_select_timer_expire(struct event
*thread
)
2626 struct afi_safi_info
*info
;
2631 info
= EVENT_ARG(thread
);
2636 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2637 XFREE(MTYPE_TMP
, info
);
2639 /* Best path selection */
2640 bgp_best_path_select_defer(bgp
, afi
, safi
);
2643 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2644 struct bgp_maxpaths_cfg
*mpath_cfg
,
2645 struct bgp_path_info_pair
*result
, afi_t afi
,
2648 struct bgp_path_info
*new_select
;
2649 struct bgp_path_info
*old_select
;
2650 struct bgp_path_info
*pi
;
2651 struct bgp_path_info
*pi1
;
2652 struct bgp_path_info
*pi2
;
2653 struct bgp_path_info
*nextpi
= NULL
;
2654 int paths_eq
, do_mpath
, debug
;
2655 struct list mp_list
;
2656 char pfx_buf
[PREFIX2STR_BUFFER
];
2657 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2659 bgp_mp_list_init(&mp_list
);
2661 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2663 debug
= bgp_debug_bestpath(dest
);
2666 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2668 dest
->reason
= bgp_path_selection_none
;
2669 /* bgp deterministic-med */
2671 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2673 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2674 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2676 bgp_path_info_unset_flag(dest
, pi1
,
2677 BGP_PATH_DMED_SELECTED
);
2679 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2681 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2683 if (BGP_PATH_HOLDDOWN(pi1
))
2685 if (pi1
->peer
!= bgp
->peer_self
&&
2686 !CHECK_FLAG(pi1
->peer
->sflags
,
2687 PEER_STATUS_NSF_WAIT
)) {
2688 if (!peer_established(pi1
->peer
))
2694 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2695 if (CHECK_FLAG(pi2
->flags
,
2696 BGP_PATH_DMED_CHECK
))
2698 if (BGP_PATH_HOLDDOWN(pi2
))
2700 if (pi2
->peer
!= bgp
->peer_self
2703 PEER_STATUS_NSF_WAIT
))
2704 if (pi2
->peer
->status
2708 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2710 && !aspath_cmp_left_confed(
2715 if (bgp_path_info_cmp(
2716 bgp
, pi2
, new_select
,
2717 &paths_eq
, mpath_cfg
, debug
,
2720 bgp_path_info_unset_flag(
2722 BGP_PATH_DMED_SELECTED
);
2726 bgp_path_info_set_flag(
2727 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2730 bgp_path_info_set_flag(dest
, new_select
,
2731 BGP_PATH_DMED_CHECK
);
2732 bgp_path_info_set_flag(dest
, new_select
,
2733 BGP_PATH_DMED_SELECTED
);
2736 bgp_path_info_path_with_addpath_rx_str(
2737 new_select
, path_buf
, sizeof(path_buf
));
2739 "%pBD(%s): %s is the bestpath from AS %u",
2740 dest
, bgp
->name_pretty
, path_buf
,
2741 aspath_get_first_as(
2742 new_select
->attr
->aspath
));
2747 /* Check old selected route and new selected route. */
2750 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2751 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2752 enum bgp_path_selection_reason reason
;
2754 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2757 if (BGP_PATH_HOLDDOWN(pi
)) {
2758 /* reap REMOVED routes, if needs be
2759 * selected route must stay for a while longer though
2761 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2762 && (pi
!= old_select
))
2763 bgp_path_info_reap(dest
, pi
);
2767 "%s: %pBD(%s) pi from %s in holddown",
2768 __func__
, dest
, bgp
->name_pretty
,
2774 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2775 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2776 if (!peer_established(pi
->peer
)) {
2780 "%s: %pBD(%s) non self peer %s not estab state",
2788 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2789 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2790 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2792 zlog_debug("%s: %pBD(%s) pi %s dmed", __func__
,
2793 dest
, bgp
->name_pretty
,
2798 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2800 reason
= dest
->reason
;
2801 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2802 debug
, pfx_buf
, afi
, safi
,
2804 if (new_select
== NULL
&&
2805 reason
!= bgp_path_selection_none
)
2806 dest
->reason
= reason
;
2811 /* Now that we know which path is the bestpath see if any of the other
2813 * qualify as multipaths
2817 bgp_path_info_path_with_addpath_rx_str(
2818 new_select
, path_buf
, sizeof(path_buf
));
2820 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2822 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2823 dest
, bgp
->name_pretty
, path_buf
,
2824 old_select
? old_select
->peer
->host
: "NONE");
2827 if (do_mpath
&& new_select
) {
2828 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2829 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2832 bgp_path_info_path_with_addpath_rx_str(
2833 pi
, path_buf
, sizeof(path_buf
));
2835 if (pi
== new_select
) {
2838 "%pBD(%s): %s is the bestpath, add to the multipath list",
2839 dest
, bgp
->name_pretty
,
2841 bgp_mp_list_add(&mp_list
, pi
);
2845 if (BGP_PATH_HOLDDOWN(pi
))
2848 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2849 && !CHECK_FLAG(pi
->peer
->sflags
,
2850 PEER_STATUS_NSF_WAIT
))
2851 if (!peer_established(pi
->peer
))
2854 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2857 "%pBD(%s): %s has the same nexthop as the bestpath, skip it",
2858 dest
, bgp
->name_pretty
,
2863 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2864 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2870 "%pBD(%s): %s is equivalent to the bestpath, add to the multipath list",
2871 dest
, bgp
->name_pretty
,
2873 bgp_mp_list_add(&mp_list
, pi
);
2878 bgp_path_info_mpath_update(bgp
, dest
, new_select
, old_select
, &mp_list
,
2880 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2881 bgp_mp_list_clear(&mp_list
);
2883 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2885 result
->old
= old_select
;
2886 result
->new = new_select
;
2892 * A new route/change in bestpath of an existing route. Evaluate the path
2893 * for advertisement to the subgroup.
2895 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2896 struct bgp_path_info
*selected
,
2897 struct bgp_dest
*dest
,
2898 uint32_t addpath_tx_id
)
2900 const struct prefix
*p
;
2901 struct peer
*onlypeer
;
2908 p
= bgp_dest_get_prefix(dest
);
2909 afi
= SUBGRP_AFI(subgrp
);
2910 safi
= SUBGRP_SAFI(subgrp
);
2911 bgp
= SUBGRP_INST(subgrp
);
2912 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2915 if (BGP_DEBUG(update
, UPDATE_OUT
))
2916 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2918 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2919 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2920 PEER_STATUS_ORF_WAIT_REFRESH
))
2923 memset(&attr
, 0, sizeof(attr
));
2924 /* It's initialized in bgp_announce_check() */
2926 /* Announcement to the subgroup. If the route is filtered withdraw it.
2927 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2928 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2931 advertise
= bgp_check_advertise(bgp
, dest
);
2934 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2936 /* Route is selected, if the route is already installed
2937 * in FIB, then it is advertised
2940 if (!bgp_check_withdrawal(bgp
, dest
)) {
2941 struct attr
*adv_attr
=
2942 bgp_attr_intern(&attr
);
2944 bgp_adj_out_set_subgroup(dest
, subgrp
,
2948 bgp_adj_out_unset_subgroup(
2949 dest
, subgrp
, 1, addpath_tx_id
);
2952 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2956 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2958 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2963 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2964 * This is called at the end of route processing.
2966 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2968 struct bgp_path_info
*pi
;
2970 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2971 if (BGP_PATH_HOLDDOWN(pi
))
2973 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2974 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2979 * Has the route changed from the RIB's perspective? This is invoked only
2980 * if the route selection returns the same best route as earlier - to
2981 * determine if we need to update zebra or not.
2983 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2985 struct bgp_path_info
*mpinfo
;
2987 /* If this is multipath, check all selected paths for any nexthop
2988 * change or attribute change. Some attribute changes (e.g., community)
2989 * aren't of relevance to the RIB, but we'll update zebra to ensure
2990 * we handle the case of BGP nexthop change. This is the behavior
2991 * when the best path has an attribute change anyway.
2993 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2994 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2995 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2999 * If this is multipath, check all selected paths for any nexthop change
3001 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
3002 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
3003 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
3004 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
3008 /* Nothing has changed from the RIB's perspective. */
3012 struct bgp_process_queue
{
3014 STAILQ_HEAD(, bgp_dest
) pqueue
;
3015 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
3017 unsigned int queued
;
3020 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
3021 safi_t safi
, struct bgp_dest
*dest
,
3022 struct bgp_path_info
*new_select
,
3023 struct bgp_path_info
*old_select
)
3025 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3027 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
3030 if (advertise_type5_routes(bgp
, afi
) && new_select
3031 && is_route_injectable_into_evpn(new_select
)) {
3033 /* apply the route-map */
3034 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
3035 route_map_result_t ret
;
3036 struct bgp_path_info rmap_path
;
3037 struct bgp_path_info_extra rmap_path_extra
;
3038 struct attr dummy_attr
;
3040 dummy_attr
= *new_select
->attr
;
3042 /* Fill temp path_info */
3043 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
3044 new_select
, new_select
->peer
,
3047 RESET_FLAG(dummy_attr
.rmap_change_flags
);
3049 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
3052 if (ret
== RMAP_DENYMATCH
) {
3053 bgp_attr_flush(&dummy_attr
);
3054 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
3057 bgp_evpn_advertise_type5_route(
3058 bgp
, p
, &dummy_attr
, afi
, safi
);
3060 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
3063 } else if (advertise_type5_routes(bgp
, afi
) && old_select
3064 && is_route_injectable_into_evpn(old_select
))
3065 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
3069 * Utility to determine whether a particular path_info should use
3070 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3071 * in a path where we basically _know_ this is a BGP-LU route.
3073 static bool bgp_lu_need_null_label(struct bgp
*bgp
,
3074 const struct bgp_path_info
*new_select
,
3075 afi_t afi
, mpls_label_t
*label
)
3077 /* Certain types get imp null; so do paths where the nexthop is
3080 if (new_select
->sub_type
== BGP_ROUTE_STATIC
3081 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3082 || new_select
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
3083 goto need_null_label
;
3084 else if (new_select
->extra
&&
3085 bgp_is_valid_label(&new_select
->extra
->label
[0]))
3090 if (!!CHECK_FLAG(bgp
->flags
, BGP_FLAG_LU_EXPLICIT_NULL
))
3091 /* Disable PHP : explicit-null */
3092 *label
= afi
== AFI_IP
? MPLS_LABEL_IPV4_EXPLICIT_NULL
3093 : MPLS_LABEL_IPV6_EXPLICIT_NULL
;
3095 /* Enforced PHP popping: implicit-null */
3096 *label
= MPLS_LABEL_IMPLICIT_NULL
;
3102 * old_select = The old best path
3103 * new_select = the new best path
3105 * if (!old_select && new_select)
3106 * We are sending new information on.
3108 * if (old_select && new_select) {
3109 * if (new_select != old_select)
3110 * We have a new best path send a change
3112 * We've received a update with new attributes that needs
3116 * if (old_select && !new_select)
3117 * We have no eligible route that we can announce or the rn
3120 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
3121 afi_t afi
, safi_t safi
)
3123 struct bgp_path_info
*new_select
;
3124 struct bgp_path_info
*old_select
;
3125 struct bgp_path_info_pair old_and_new
;
3127 mpls_label_t mpls_label_null
;
3129 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
3131 debug
= bgp_debug_bestpath(dest
);
3134 "%s: bgp delete in progress, ignoring event, p=%pBD(%s)",
3135 __func__
, dest
, bgp
->name_pretty
);
3138 /* Is it end of initial update? (after startup) */
3140 frr_timestamp(3, bgp
->update_delay_zebra_resume_time
,
3141 sizeof(bgp
->update_delay_zebra_resume_time
));
3143 bgp
->main_zebra_update_hold
= 0;
3144 FOREACH_AFI_SAFI (afi
, safi
) {
3145 if (bgp_fibupd_safi(safi
))
3146 bgp_zebra_announce_table(bgp
, afi
, safi
);
3148 bgp
->main_peers_update_hold
= 0;
3150 bgp_start_routeadv(bgp
);
3154 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3156 debug
= bgp_debug_bestpath(dest
);
3158 zlog_debug("%s: p=%pBD(%s) afi=%s, safi=%s start", __func__
,
3159 dest
, bgp
->name_pretty
, afi2str(afi
),
3162 /* The best path calculation for the route is deferred if
3163 * BGP_NODE_SELECT_DEFER is set
3165 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3166 if (BGP_DEBUG(update
, UPDATE_OUT
))
3167 zlog_debug("SELECT_DEFER flag set for route %p(%s)",
3168 dest
, bgp
->name_pretty
);
3172 /* Best path selection. */
3173 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
3175 old_select
= old_and_new
.old
;
3176 new_select
= old_and_new
.new;
3178 /* Do we need to allocate or free labels?
3179 * Right now, since we only deal with per-prefix labels, it is not
3180 * necessary to do this upon changes to best path. Exceptions:
3181 * - label index has changed -> recalculate resulting label
3182 * - path_info sub_type changed -> switch to/from null label value
3183 * - no valid label (due to removed static label binding) -> get new one
3185 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
3188 || bgp_label_index_differs(new_select
, old_select
)
3189 || new_select
->sub_type
!= old_select
->sub_type
3190 || !bgp_is_valid_label(&dest
->local_label
)) {
3191 /* control label imposition for local routes,
3192 * aggregate and redistributed routes
3194 mpls_label_null
= MPLS_LABEL_IMPLICIT_NULL
;
3195 if (bgp_lu_need_null_label(bgp
, new_select
, afi
,
3196 &mpls_label_null
)) {
3199 BGP_NODE_REGISTERED_FOR_LABEL
)
3202 BGP_NODE_LABEL_REQUESTED
))
3203 bgp_unregister_for_label(dest
);
3204 dest
->local_label
= mpls_lse_encode(
3205 mpls_label_null
, 0, 0, 1);
3206 bgp_set_valid_label(&dest
->local_label
);
3208 bgp_register_for_label(dest
,
3211 } else if (CHECK_FLAG(dest
->flags
,
3212 BGP_NODE_REGISTERED_FOR_LABEL
)
3213 || CHECK_FLAG(dest
->flags
,
3214 BGP_NODE_LABEL_REQUESTED
)) {
3215 bgp_unregister_for_label(dest
);
3217 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
3218 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
3219 bgp_unregister_for_label(dest
);
3224 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3225 __func__
, dest
, bgp
->name_pretty
, afi2str(afi
),
3226 safi2str(safi
), old_select
, new_select
);
3228 /* If best route remains the same and this is not due to user-initiated
3229 * clear, see exactly what needs to be done.
3231 if (old_select
&& old_select
== new_select
3232 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
3233 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3234 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
3235 if (bgp_zebra_has_route_changed(old_select
)) {
3236 #ifdef ENABLE_BGP_VNC
3237 vnc_import_bgp_add_route(bgp
, p
, old_select
);
3238 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
3240 if (bgp_fibupd_safi(safi
)
3241 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3243 if (new_select
->type
== ZEBRA_ROUTE_BGP
3244 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3245 || new_select
->sub_type
3246 == BGP_ROUTE_IMPORTED
))
3248 bgp_zebra_announce(dest
, p
, old_select
,
3253 /* If there is a change of interest to peers, reannounce the
3255 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3256 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3257 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
3258 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3260 /* unicast routes must also be annouced to
3261 * labeled-unicast update-groups */
3262 if (safi
== SAFI_UNICAST
)
3263 group_announce_route(bgp
, afi
,
3264 SAFI_LABELED_UNICAST
, dest
,
3267 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
3268 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
3271 /* advertise/withdraw type-5 routes */
3272 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3273 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
3274 bgp_process_evpn_route_injection(
3275 bgp
, afi
, safi
, dest
, old_select
, old_select
);
3277 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3278 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3279 bgp_zebra_clear_route_change_flags(dest
);
3280 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3284 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3286 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
3288 /* bestpath has changed; bump version */
3289 if (old_select
|| new_select
) {
3290 bgp_bump_version(dest
);
3292 if (!bgp
->t_rmap_def_originate_eval
) {
3296 update_group_refresh_default_originate_route_map
,
3297 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
3298 &bgp
->t_rmap_def_originate_eval
);
3303 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
3306 zlog_debug("%s: setting SELECTED flag", __func__
);
3307 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
3308 bgp_path_info_unset_flag(dest
, new_select
,
3309 BGP_PATH_ATTR_CHANGED
);
3310 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3311 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3314 #ifdef ENABLE_BGP_VNC
3315 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3316 if (old_select
!= new_select
) {
3318 vnc_import_bgp_exterior_del_route(bgp
, p
,
3320 vnc_import_bgp_del_route(bgp
, p
, old_select
);
3323 vnc_import_bgp_exterior_add_route(bgp
, p
,
3325 vnc_import_bgp_add_route(bgp
, p
, new_select
);
3331 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3333 /* unicast routes must also be annouced to labeled-unicast update-groups
3335 if (safi
== SAFI_UNICAST
)
3336 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
3340 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
3341 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3343 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
3344 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3345 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3346 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
3348 /* if this is an evpn imported type-5 prefix,
3349 * we need to withdraw the route first to clear
3350 * the nh neigh and the RMAC entry.
3353 is_route_parent_evpn(old_select
))
3354 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3356 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
3358 /* Withdraw the route from the kernel. */
3359 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
3360 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
3361 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
3362 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
3364 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3368 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
3371 /* Clear any route change flags. */
3372 bgp_zebra_clear_route_change_flags(dest
);
3374 /* Reap old select bgp_path_info, if it has been removed */
3375 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
3376 bgp_path_info_reap(dest
, old_select
);
3378 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3382 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3383 void bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
3385 struct bgp_dest
*dest
;
3387 struct afi_safi_info
*thread_info
;
3389 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
3390 struct event
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
3392 thread_info
= EVENT_ARG(t
);
3393 XFREE(MTYPE_TMP
, thread_info
);
3394 EVENT_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
3397 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
3398 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
3399 get_afi_safi_str(afi
, safi
, false),
3400 bgp
->gr_info
[afi
][safi
].gr_deferred
);
3403 /* Process the route list */
3404 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
3405 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0 &&
3406 cnt
< BGP_MAX_BEST_ROUTE_SELECT
;
3407 dest
= bgp_route_next(dest
)) {
3408 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
3411 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3412 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3413 bgp_process_main_one(bgp
, dest
, afi
, safi
);
3416 /* If iteration stopped before the entire table was traversed then the
3417 * node needs to be unlocked.
3420 bgp_dest_unlock_node(dest
);
3424 /* Send EOR message when all routes are processed */
3425 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
3426 bgp_send_delayed_eor(bgp
);
3427 /* Send route processing complete message to RIB */
3428 bgp_zebra_update(bgp
, afi
, safi
,
3429 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
3433 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3435 thread_info
->afi
= afi
;
3436 thread_info
->safi
= safi
;
3437 thread_info
->bgp
= bgp
;
3439 /* If there are more routes to be processed, start the
3442 event_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3443 BGP_ROUTE_SELECT_DELAY
,
3444 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3447 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3449 struct bgp_process_queue
*pqnode
= data
;
3450 struct bgp
*bgp
= pqnode
->bgp
;
3451 struct bgp_table
*table
;
3452 struct bgp_dest
*dest
;
3455 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3456 bgp_process_main_one(bgp
, NULL
, 0, 0);
3457 /* should always have dedicated wq call */
3458 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3462 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3463 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3464 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3465 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3466 table
= bgp_dest_table(dest
);
3467 /* note, new DESTs may be added as part of processing */
3468 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3470 bgp_dest_unlock_node(dest
);
3471 bgp_table_unlock(table
);
3477 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3479 struct bgp_process_queue
*pqnode
= data
;
3481 bgp_unlock(pqnode
->bgp
);
3483 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3486 void bgp_process_queue_init(struct bgp
*bgp
)
3488 if (!bgp
->process_queue
) {
3491 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3492 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3495 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3496 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3497 bgp
->process_queue
->spec
.max_retries
= 0;
3498 bgp
->process_queue
->spec
.hold
= 50;
3499 /* Use a higher yield value of 50ms for main queue processing */
3500 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3503 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3505 struct bgp_process_queue
*pqnode
;
3507 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3508 sizeof(struct bgp_process_queue
));
3510 /* unlocked in bgp_processq_del */
3511 pqnode
->bgp
= bgp_lock(bgp
);
3512 STAILQ_INIT(&pqnode
->pqueue
);
3517 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3519 #define ARBITRARY_PROCESS_QLEN 10000
3520 struct work_queue
*wq
= bgp
->process_queue
;
3521 struct bgp_process_queue
*pqnode
;
3522 int pqnode_reuse
= 0;
3524 /* already scheduled for processing? */
3525 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3528 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3531 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3532 if (BGP_DEBUG(update
, UPDATE_OUT
))
3533 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3538 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
)) {
3539 if (BGP_DEBUG(update
, UPDATE_OUT
))
3541 "Soft reconfigure table in progress for route %p",
3549 /* Add route nodes to an existing work queue item until reaching the
3550 limit only if is from the same BGP view and it's not an EOIU marker
3552 if (work_queue_item_count(wq
)) {
3553 struct work_queue_item
*item
= work_queue_last_item(wq
);
3554 pqnode
= item
->data
;
3556 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3557 || pqnode
->bgp
!= bgp
3558 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3559 pqnode
= bgp_processq_alloc(bgp
);
3563 pqnode
= bgp_processq_alloc(bgp
);
3564 /* all unlocked in bgp_process_wq */
3565 bgp_table_lock(bgp_dest_table(dest
));
3567 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3568 bgp_dest_lock_node(dest
);
3570 /* can't be enqueued twice */
3571 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3572 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3576 work_queue_add(wq
, pqnode
);
3581 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3583 struct bgp_process_queue
*pqnode
;
3585 if (bgp
->process_queue
== NULL
)
3588 pqnode
= bgp_processq_alloc(bgp
);
3590 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3591 work_queue_add(bgp
->process_queue
, pqnode
);
3594 static void bgp_maximum_prefix_restart_timer(struct event
*thread
)
3598 peer
= EVENT_ARG(thread
);
3599 peer
->t_pmax_restart
= NULL
;
3601 if (bgp_debug_neighbor_events(peer
))
3603 "%s Maximum-prefix restart timer expired, restore peering",
3606 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3607 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3610 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3614 bool filtered
= false;
3615 struct bgp_dest
*dest
;
3616 struct bgp_adj_in
*ain
;
3617 struct attr attr
= {};
3618 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3620 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3621 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3622 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3626 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3630 if (bgp_input_modifier(
3631 peer
, rn_p
, &attr
, afi
, safi
,
3632 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3640 bgp_attr_flush(&attr
);
3647 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3651 iana_safi_t pkt_safi
;
3652 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3653 PEER_FLAG_MAX_PREFIX_FORCE
))
3654 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3655 + peer
->pcount
[afi
][safi
]
3656 : peer
->pcount
[afi
][safi
];
3658 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3661 if (pcount
> peer
->pmax
[afi
][safi
]) {
3662 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3663 PEER_STATUS_PREFIX_LIMIT
)
3668 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3669 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3670 peer
->pmax
[afi
][safi
]);
3671 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3673 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3674 PEER_FLAG_MAX_PREFIX_WARNING
))
3677 /* Convert AFI, SAFI to values for packet. */
3678 pkt_afi
= afi_int2iana(afi
);
3679 pkt_safi
= safi_int2iana(safi
);
3683 ndata
[0] = (pkt_afi
>> 8);
3685 ndata
[2] = pkt_safi
;
3686 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3687 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3688 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3689 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3691 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3692 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3693 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3697 /* Dynamic peers will just close their connection. */
3698 if (peer_dynamic_neighbor(peer
))
3701 /* restart timer start */
3702 if (peer
->pmax_restart
[afi
][safi
]) {
3703 peer
->v_pmax_restart
=
3704 peer
->pmax_restart
[afi
][safi
] * 60;
3706 if (bgp_debug_neighbor_events(peer
))
3708 "%pBP Maximum-prefix restart timer started for %d secs",
3709 peer
, peer
->v_pmax_restart
);
3711 BGP_TIMER_ON(peer
->t_pmax_restart
,
3712 bgp_maximum_prefix_restart_timer
,
3713 peer
->v_pmax_restart
);
3718 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3719 PEER_STATUS_PREFIX_LIMIT
);
3722 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3723 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3724 PEER_STATUS_PREFIX_THRESHOLD
)
3729 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3730 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3731 peer
->pmax
[afi
][safi
]);
3732 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3733 PEER_STATUS_PREFIX_THRESHOLD
);
3735 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3736 PEER_STATUS_PREFIX_THRESHOLD
);
3740 /* Unconditionally remove the route from the RIB, without taking
3741 * damping into consideration (eg, because the session went down)
3743 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3744 struct peer
*peer
, afi_t afi
, safi_t safi
)
3747 struct bgp
*bgp
= NULL
;
3748 bool delete_route
= false;
3750 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3753 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3754 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3756 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3759 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3760 delete_route
= true;
3761 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3762 delete_route
= true;
3764 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3765 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3766 bgp
= pi
->peer
->bgp
;
3767 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3772 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3773 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3776 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3777 struct peer
*peer
, afi_t afi
, safi_t safi
,
3778 struct prefix_rd
*prd
)
3780 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3782 /* apply dampening, if result is suppressed, we'll be retaining
3783 * the bgp_path_info in the RIB for historical reference.
3785 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3786 && peer
->sort
== BGP_PEER_EBGP
)
3787 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3788 == BGP_DAMP_SUPPRESSED
) {
3789 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3794 #ifdef ENABLE_BGP_VNC
3795 if (safi
== SAFI_MPLS_VPN
) {
3796 struct bgp_dest
*pdest
= NULL
;
3797 struct bgp_table
*table
= NULL
;
3799 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3800 (struct prefix
*)prd
);
3801 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3802 table
= bgp_dest_get_bgp_table_info(pdest
);
3804 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3805 peer
->bgp
, prd
, table
, p
, pi
);
3807 bgp_dest_unlock_node(pdest
);
3809 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3810 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3812 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3813 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3818 /* If this is an EVPN route, process for un-import. */
3819 if (safi
== SAFI_EVPN
)
3820 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3822 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3825 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3826 struct peer
*peer
, struct attr
*attr
,
3827 struct bgp_dest
*dest
)
3829 struct bgp_path_info
*new;
3831 /* Make new BGP info. */
3832 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3834 new->instance
= instance
;
3835 new->sub_type
= sub_type
;
3838 new->uptime
= monotime(NULL
);
3843 /* Check if received nexthop is valid or not. */
3844 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3845 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3846 struct bgp_dest
*dest
)
3849 bool is_bgp_static_route
=
3850 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3853 /* If `bgp allow-martian-nexthop` is turned on, return next-hop
3856 if (bgp
->allow_martian
)
3860 * Only validated for unicast and multicast currently.
3861 * Also valid for EVPN where the nexthop is an IP address.
3862 * If we are a bgp static route being checked then there is
3863 * no need to check to see if the nexthop is martian as
3864 * that it should be ok.
3866 if (is_bgp_static_route
||
3867 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3870 /* If NEXT_HOP is present, validate it. */
3871 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3872 if (attr
->nexthop
.s_addr
== INADDR_ANY
||
3873 !ipv4_unicast_valid(&attr
->nexthop
) ||
3874 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3878 /* If MP_NEXTHOP is present, validate it. */
3879 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3880 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3881 * it is not an IPv6 link-local address.
3883 * If we receive an UPDATE with nexthop length set to 32 bytes
3884 * we shouldn't discard an UPDATE if it's set to (::).
3885 * The link-local (2st) is validated along the code path later.
3887 if (attr
->mp_nexthop_len
) {
3888 switch (attr
->mp_nexthop_len
) {
3889 case BGP_ATTR_NHLEN_IPV4
:
3890 case BGP_ATTR_NHLEN_VPNV4
:
3891 ret
= (attr
->mp_nexthop_global_in
.s_addr
==
3893 !ipv4_unicast_valid(
3894 &attr
->mp_nexthop_global_in
) ||
3895 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3899 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3900 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3901 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3902 &attr
->mp_nexthop_global
)
3903 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3904 || IN6_IS_ADDR_MULTICAST(
3905 &attr
->mp_nexthop_global
)
3906 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3909 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3910 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3911 || IN6_IS_ADDR_MULTICAST(
3912 &attr
->mp_nexthop_global
)
3913 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3926 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3928 struct community
*old
;
3929 struct community
*new;
3930 struct community
*merge
;
3931 struct community
*no_export
;
3933 old
= bgp_attr_get_community(attr
);
3934 no_export
= community_str2com("no-export");
3939 merge
= community_merge(community_dup(old
), no_export
);
3942 community_free(&old
);
3944 new = community_uniq_sort(merge
);
3945 community_free(&merge
);
3947 new = community_dup(no_export
);
3950 community_free(&no_export
);
3952 bgp_attr_set_community(attr
, new);
3955 static bool bgp_accept_own(struct peer
*peer
, afi_t afi
, safi_t safi
,
3956 struct attr
*attr
, const struct prefix
*prefix
,
3959 struct listnode
*node
, *nnode
;
3961 bool accept_own_found
= false;
3963 if (safi
!= SAFI_MPLS_VPN
)
3966 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3967 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
))
3970 /* The route in question carries the ACCEPT_OWN community */
3971 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
3972 struct community
*comm
= bgp_attr_get_community(attr
);
3974 if (community_include(comm
, COMMUNITY_ACCEPT_OWN
))
3975 accept_own_found
= true;
3978 /* The route in question is targeted to one or more destination VRFs
3979 * on the router (as determined by inspecting the Route Target(s)).
3981 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
3982 if (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
)
3985 if (accept_own_found
&&
3987 bgp
->vpn_policy
[afi
]
3988 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
],
3989 bgp_attr_get_ecommunity(attr
))) {
3990 if (bgp_debug_update(peer
, prefix
, NULL
, 1))
3992 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3995 /* Treat this route as imported, because it's leaked
3996 * already from another VRF, and we got an updated
3997 * version from route-reflector with ACCEPT_OWN
4000 *sub_type
= BGP_ROUTE_IMPORTED
;
4009 void bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4010 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4011 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4012 uint32_t num_labels
, int soft_reconfig
,
4013 struct bgp_route_evpn
*evpn
)
4016 int aspath_loop_count
= 0;
4017 struct bgp_dest
*dest
;
4019 struct attr new_attr
;
4020 struct attr
*attr_new
;
4021 struct bgp_path_info
*pi
;
4022 struct bgp_path_info
*new = NULL
;
4023 struct bgp_path_info_extra
*extra
;
4025 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4027 int do_loop_check
= 1;
4028 int has_valid_label
= 0;
4030 bool force_evpn_import
= false;
4031 safi_t orig_safi
= safi
;
4032 bool leak_success
= true;
4035 if (frrtrace_enabled(frr_bgp
, process_update
)) {
4036 char pfxprint
[PREFIX2STR_BUFFER
];
4038 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
4039 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
4043 #ifdef ENABLE_BGP_VNC
4044 int vnc_implicit_withdraw
= 0;
4047 const struct prefix
*bgp_nht_param_prefix
;
4049 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4050 if (orig_safi
== SAFI_LABELED_UNICAST
)
4051 safi
= SAFI_UNICAST
;
4053 memset(&new_attr
, 0, sizeof(new_attr
));
4054 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
4055 new_attr
.label
= MPLS_INVALID_LABEL
;
4058 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4059 /* TODO: Check to see if we can get rid of "is_valid_label" */
4060 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
4061 has_valid_label
= (num_labels
> 0) ? 1 : 0;
4063 has_valid_label
= bgp_is_valid_label(label
);
4065 if (has_valid_label
)
4066 assert(label
!= NULL
);
4068 /* Update overlay index of the attribute */
4069 if (afi
== AFI_L2VPN
&& evpn
)
4070 memcpy(&attr
->evpn_overlay
, evpn
,
4071 sizeof(struct bgp_route_evpn
));
4073 /* When peer's soft reconfiguration enabled. Record input packet in
4076 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4077 && peer
!= bgp
->peer_self
)
4078 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
4080 /* Update permitted loop count */
4081 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN
))
4082 allowas_in
= peer
->allowas_in
[afi
][safi
];
4084 /* Check previously received route. */
4085 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4086 if (pi
->peer
== peer
&& pi
->type
== type
4087 && pi
->sub_type
== sub_type
4088 && pi
->addpath_rx_id
== addpath_id
)
4091 /* AS path local-as loop check. */
4092 if (peer
->change_local_as
) {
4094 aspath_loop_count
= allowas_in
;
4095 else if (!CHECK_FLAG(peer
->flags
,
4096 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
4097 aspath_loop_count
= 1;
4099 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
4100 > aspath_loop_count
) {
4101 peer
->stat_pfx_aspath_loop
++;
4102 reason
= "as-path contains our own AS;";
4107 /* If the peer is configured for "allowas-in origin" and the last ASN in
4109 * as-path is our ASN then we do not need to call aspath_loop_check
4111 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
4112 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
4115 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_REFLECTOR_CLIENT
))
4116 bgp_nht_param_prefix
= NULL
;
4118 bgp_nht_param_prefix
= p
;
4120 /* AS path loop check. */
4121 if (do_loop_check
) {
4122 if (aspath_loop_check(attr
->aspath
, bgp
->as
) >
4123 peer
->allowas_in
[afi
][safi
]) {
4124 peer
->stat_pfx_aspath_loop
++;
4125 reason
= "as-path contains our own AS;";
4130 /* If we're a CONFED we need to loop check the CONFED ID too */
4131 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
) && do_loop_check
)
4132 if (aspath_loop_check_confed(attr
->aspath
, bgp
->confed_id
) >
4133 peer
->allowas_in
[afi
][safi
]) {
4134 peer
->stat_pfx_aspath_loop
++;
4135 reason
= "as-path contains our own confed AS;";
4139 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4140 * enabled, then take care of that too.
4142 bool accept_own
= false;
4144 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
4145 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
4147 bgp_accept_own(peer
, afi
, safi
, attr
, p
, &sub_type
);
4149 peer
->stat_pfx_originator_loop
++;
4150 reason
= "originator is us;";
4155 /* Route reflector cluster ID check. */
4156 if (bgp_cluster_filter(peer
, attr
)) {
4157 peer
->stat_pfx_cluster_loop
++;
4158 reason
= "reflected from the same cluster;";
4162 /* Apply incoming filter. */
4163 if (bgp_input_filter(peer
, p
, attr
, afi
, orig_safi
) == FILTER_DENY
) {
4164 peer
->stat_pfx_filter
++;
4169 /* RFC 8212 to prevent route leaks.
4170 * This specification intends to improve this situation by requiring the
4171 * explicit configuration of both BGP Import and Export Policies for any
4172 * External BGP (EBGP) session such as customers, peers, or
4173 * confederation boundaries for all enabled address families. Through
4174 * codification of the aforementioned requirement, operators will
4175 * benefit from consistent behavior across different BGP
4178 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
4179 if (!bgp_inbound_policy_exists(peer
,
4180 &peer
->filter
[afi
][safi
])) {
4181 reason
= "inbound policy missing";
4182 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
4183 NULL
) > FIFTEENMINUTE2USEC
||
4184 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
4186 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4187 monotime(&bgp
->ebgprequirespolicywarning
);
4192 /* draft-ietf-idr-deprecate-as-set-confed-set
4193 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4194 * Eventually, This document (if approved) updates RFC 4271
4195 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4196 * and obsoletes RFC 6472.
4198 if (peer
->bgp
->reject_as_sets
)
4199 if (aspath_check_as_sets(attr
->aspath
)) {
4201 "as-path contains AS_SET or AS_CONFED_SET type;";
4207 /* Apply incoming route-map.
4208 * NB: new_attr may now contain newly allocated values from route-map
4210 * commands, so we need bgp_attr_flush in the error paths, until we
4212 * the attr (which takes over the memory references) */
4213 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, orig_safi
, NULL
, label
,
4216 peer
->stat_pfx_filter
++;
4217 reason
= "route-map;";
4218 bgp_attr_flush(&new_attr
);
4222 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
4223 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
4224 /* remove from RIB previous entry */
4225 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
4228 if (peer
->sort
== BGP_PEER_EBGP
) {
4231 * A BGP speaker receiving an announcement tagged with the
4232 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4233 * NO_EXPORT community as defined in RFC1997, or a
4234 * similar community, to prevent propagation of the
4235 * prefix outside the local AS. The community to prevent
4236 * propagation SHOULD be chosen according to the operator's
4239 if (bgp_attr_get_community(&new_attr
) &&
4240 community_include(bgp_attr_get_community(&new_attr
),
4241 COMMUNITY_BLACKHOLE
))
4242 bgp_attr_add_no_export_community(&new_attr
);
4244 /* If we receive the graceful-shutdown community from an eBGP
4245 * peer we must lower local-preference */
4246 if (bgp_attr_get_community(&new_attr
) &&
4247 community_include(bgp_attr_get_community(&new_attr
),
4249 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
4250 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
4252 /* If graceful-shutdown is configured globally or
4253 * per neighbor, then add the GSHUT community to
4254 * all paths received from eBGP peers. */
4255 } else if (bgp_in_graceful_shutdown(peer
->bgp
) ||
4256 CHECK_FLAG(peer
->flags
, PEER_FLAG_GRACEFUL_SHUTDOWN
))
4257 bgp_attr_add_gshut_community(&new_attr
);
4260 /* next hop check. */
4261 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
) &&
4262 bgp_update_martian_nexthop(bgp
, afi
, safi
, type
, sub_type
,
4264 peer
->stat_pfx_nh_invalid
++;
4265 reason
= "martian or self next-hop;";
4266 bgp_attr_flush(&new_attr
);
4270 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
4271 peer
->stat_pfx_nh_invalid
++;
4272 reason
= "self mac;";
4273 bgp_attr_flush(&new_attr
);
4277 if (bgp_check_role_applicability(afi
, safi
) &&
4278 bgp_otc_filter(peer
, &new_attr
)) {
4279 reason
= "failing otc validation";
4280 bgp_attr_flush(&new_attr
);
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 EVENT_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 event
*t
)
5060 struct peer_af
*paf
;
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 event_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 event
*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
= EVENT_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 event_add_event(bm
->master
, bgp_soft_reconfig_table_task
, table
,
5267 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 EVENT_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 event_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 bgp_free_aggregate_info(aggregate
);
8360 bgp_dest_unlock_node(dest
);
8361 bgp_dest_unlock_node(dest
);
8366 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
8367 safi_t safi
, const char *rmap
,
8368 uint8_t summary_only
, uint8_t as_set
,
8369 uint8_t origin
, bool match_med
,
8370 const char *suppress_map
)
8372 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8375 struct bgp_dest
*dest
;
8376 struct bgp_aggregate
*aggregate
;
8377 uint8_t as_set_new
= as_set
;
8379 if (suppress_map
&& summary_only
) {
8381 "'summary-only' and 'suppress-map' can't be used at the same time\n");
8382 return CMD_WARNING_CONFIG_FAILED
;
8385 /* Convert string to prefix structure. */
8386 ret
= str2prefix(prefix_str
, &p
);
8388 vty_out(vty
, "Malformed prefix\n");
8389 return CMD_WARNING_CONFIG_FAILED
;
8393 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
8394 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
8395 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8397 return CMD_WARNING_CONFIG_FAILED
;
8400 /* Old configuration check. */
8401 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
8402 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8405 vty_out(vty
, "There is already same aggregate network.\n");
8406 /* try to remove the old entry */
8407 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
8409 vty_out(vty
, "Error deleting aggregate.\n");
8410 bgp_dest_unlock_node(dest
);
8411 return CMD_WARNING_CONFIG_FAILED
;
8415 /* Make aggregate address structure. */
8416 aggregate
= bgp_aggregate_new();
8417 aggregate
->summary_only
= summary_only
;
8418 aggregate
->match_med
= match_med
;
8420 /* Network operators MUST NOT locally generate any new
8421 * announcements containing AS_SET or AS_CONFED_SET. If they have
8422 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8423 * SHOULD withdraw those routes and re-announce routes for the
8424 * aggregate or component prefixes (i.e., the more-specific routes
8425 * subsumed by the previously aggregated route) without AS_SET
8426 * or AS_CONFED_SET in the updates.
8428 if (bgp
->reject_as_sets
) {
8429 if (as_set
== AGGREGATE_AS_SET
) {
8430 as_set_new
= AGGREGATE_AS_UNSET
;
8432 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8435 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8439 aggregate
->as_set
= as_set_new
;
8440 aggregate
->safi
= safi
;
8441 /* Override ORIGIN attribute if defined.
8442 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8443 * to IGP which is not what rfc4271 says.
8444 * This enables the same behavior, optionally.
8446 aggregate
->origin
= origin
;
8449 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
8450 route_map_counter_decrement(aggregate
->rmap
.map
);
8451 aggregate
->rmap
.name
=
8452 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
8453 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
8454 route_map_counter_increment(aggregate
->rmap
.map
);
8458 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
8459 route_map_counter_decrement(aggregate
->suppress_map
);
8461 aggregate
->suppress_map_name
=
8462 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
8463 aggregate
->suppress_map
=
8464 route_map_lookup_by_name(aggregate
->suppress_map_name
);
8465 route_map_counter_increment(aggregate
->suppress_map
);
8468 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
8470 /* Aggregate address insert into BGP routing table. */
8471 if (!bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
)) {
8472 bgp_aggregate_free(aggregate
);
8473 bgp_dest_unlock_node(dest
);
8479 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
8480 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8482 "|summary-only$summary_only"
8483 "|route-map RMAP_NAME$rmap_name"
8484 "|origin <egp|igp|incomplete>$origin_s"
8485 "|matching-MED-only$match_med"
8486 "|suppress-map RMAP_NAME$suppress_map"
8489 "Configure BGP aggregate entries\n"
8490 "Aggregate prefix\n"
8491 "Aggregate address\n"
8493 "Generate AS set path information\n"
8494 "Filter more specific routes from updates\n"
8495 "Apply route map to aggregate network\n"
8500 "Unknown heritage\n"
8501 "Only aggregate routes with matching MED\n"
8502 "Suppress the selected more specific routes\n"
8503 "Route map with the route selectors\n")
8505 const char *prefix_s
= NULL
;
8506 safi_t safi
= bgp_node_safi(vty
);
8507 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8508 int as_set
= AGGREGATE_AS_UNSET
;
8509 char prefix_buf
[PREFIX2STR_BUFFER
];
8512 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8515 vty_out(vty
, "%% Inconsistent address and mask\n");
8516 return CMD_WARNING_CONFIG_FAILED
;
8518 prefix_s
= prefix_buf
;
8520 prefix_s
= prefix_str
;
8523 if (strcmp(origin_s
, "egp") == 0)
8524 origin
= BGP_ORIGIN_EGP
;
8525 else if (strcmp(origin_s
, "igp") == 0)
8526 origin
= BGP_ORIGIN_IGP
;
8527 else if (strcmp(origin_s
, "incomplete") == 0)
8528 origin
= BGP_ORIGIN_INCOMPLETE
;
8532 as_set
= AGGREGATE_AS_SET
;
8534 /* Handle configuration removal, otherwise installation. */
8536 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8538 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8539 summary_only
!= NULL
, as_set
, origin
,
8540 match_med
!= NULL
, suppress_map
);
8543 void bgp_free_aggregate_info(struct bgp_aggregate
*aggregate
)
8545 if (aggregate
->community
)
8546 community_free(&aggregate
->community
);
8548 hash_clean_and_free(&aggregate
->community_hash
,
8549 bgp_aggr_community_remove
);
8551 if (aggregate
->ecommunity
)
8552 ecommunity_free(&aggregate
->ecommunity
);
8554 hash_clean_and_free(&aggregate
->ecommunity_hash
,
8555 bgp_aggr_ecommunity_remove
);
8557 if (aggregate
->lcommunity
)
8558 lcommunity_free(&aggregate
->lcommunity
);
8560 hash_clean_and_free(&aggregate
->lcommunity_hash
,
8561 bgp_aggr_lcommunity_remove
);
8563 if (aggregate
->aspath
)
8564 aspath_free(aggregate
->aspath
);
8566 hash_clean_and_free(&aggregate
->aspath_hash
, bgp_aggr_aspath_remove
);
8568 bgp_aggregate_free(aggregate
);
8571 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8572 "[no] aggregate-address X:X::X:X/M$prefix [{"
8574 "|summary-only$summary_only"
8575 "|route-map RMAP_NAME$rmap_name"
8576 "|origin <egp|igp|incomplete>$origin_s"
8577 "|matching-MED-only$match_med"
8578 "|suppress-map RMAP_NAME$suppress_map"
8581 "Configure BGP aggregate entries\n"
8582 "Aggregate prefix\n"
8583 "Generate AS set path information\n"
8584 "Filter more specific routes from updates\n"
8585 "Apply route map to aggregate network\n"
8590 "Unknown heritage\n"
8591 "Only aggregate routes with matching MED\n"
8592 "Suppress the selected more specific routes\n"
8593 "Route map with the route selectors\n")
8595 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8596 int as_set
= AGGREGATE_AS_UNSET
;
8599 if (strcmp(origin_s
, "egp") == 0)
8600 origin
= BGP_ORIGIN_EGP
;
8601 else if (strcmp(origin_s
, "igp") == 0)
8602 origin
= BGP_ORIGIN_IGP
;
8603 else if (strcmp(origin_s
, "incomplete") == 0)
8604 origin
= BGP_ORIGIN_INCOMPLETE
;
8608 as_set
= AGGREGATE_AS_SET
;
8610 /* Handle configuration removal, otherwise installation. */
8612 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8615 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8616 rmap_name
, summary_only
!= NULL
, as_set
,
8617 origin
, match_med
!= NULL
, suppress_map
);
8620 /* Redistribute route treatment. */
8621 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8622 const union g_addr
*nexthop
, ifindex_t ifindex
,
8623 enum nexthop_types_t nhtype
, uint8_t distance
,
8624 enum blackhole_type bhtype
, uint32_t metric
,
8625 uint8_t type
, unsigned short instance
,
8628 struct bgp_path_info
*new;
8629 struct bgp_path_info
*bpi
;
8630 struct bgp_path_info rmap_path
;
8631 struct bgp_dest
*bn
;
8633 struct attr
*new_attr
;
8635 route_map_result_t ret
;
8636 struct bgp_redist
*red
;
8638 /* Make default attribute. */
8639 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
8641 * This must not be NULL to satisfy Coverity SA
8643 assert(attr
.aspath
);
8646 case NEXTHOP_TYPE_IFINDEX
:
8647 switch (p
->family
) {
8649 attr
.nexthop
.s_addr
= INADDR_ANY
;
8650 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8653 memset(&attr
.mp_nexthop_global
, 0,
8654 sizeof(attr
.mp_nexthop_global
));
8655 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8659 case NEXTHOP_TYPE_IPV4
:
8660 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8661 attr
.nexthop
= nexthop
->ipv4
;
8662 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8664 case NEXTHOP_TYPE_IPV6
:
8665 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8666 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8667 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8669 case NEXTHOP_TYPE_BLACKHOLE
:
8670 switch (p
->family
) {
8672 attr
.nexthop
.s_addr
= INADDR_ANY
;
8673 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8676 memset(&attr
.mp_nexthop_global
, 0,
8677 sizeof(attr
.mp_nexthop_global
));
8678 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8681 attr
.bh_type
= bhtype
;
8684 attr
.nh_type
= nhtype
;
8685 attr
.nh_ifindex
= ifindex
;
8688 attr
.distance
= distance
;
8689 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8693 bgp_attr_set_aigp_metric(&attr
, metric
);
8695 afi
= family2afi(p
->family
);
8697 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8699 struct attr attr_new
;
8701 /* Copy attribute for modification. */
8704 if (red
->redist_metric_flag
) {
8705 attr_new
.med
= red
->redist_metric
;
8706 bgp_attr_set_aigp_metric(&attr_new
, red
->redist_metric
);
8709 /* Apply route-map. */
8710 if (red
->rmap
.name
) {
8711 memset(&rmap_path
, 0, sizeof(rmap_path
));
8712 rmap_path
.peer
= bgp
->peer_self
;
8713 rmap_path
.attr
= &attr_new
;
8715 SET_FLAG(bgp
->peer_self
->rmap_type
,
8716 PEER_RMAP_TYPE_REDISTRIBUTE
);
8718 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8720 bgp
->peer_self
->rmap_type
= 0;
8722 if (ret
== RMAP_DENYMATCH
) {
8723 /* Free uninterned attribute. */
8724 bgp_attr_flush(&attr_new
);
8726 /* Unintern original. */
8727 aspath_unintern(&attr
.aspath
);
8728 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8733 if (bgp_in_graceful_shutdown(bgp
))
8734 bgp_attr_add_gshut_community(&attr_new
);
8736 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8737 SAFI_UNICAST
, p
, NULL
);
8739 new_attr
= bgp_attr_intern(&attr_new
);
8741 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8742 if (bpi
->peer
== bgp
->peer_self
8743 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8747 /* Ensure the (source route) type is updated. */
8749 if (attrhash_cmp(bpi
->attr
, new_attr
)
8750 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8751 bgp_attr_unintern(&new_attr
);
8752 aspath_unintern(&attr
.aspath
);
8753 bgp_dest_unlock_node(bn
);
8756 /* The attribute is changed. */
8757 bgp_path_info_set_flag(bn
, bpi
,
8758 BGP_PATH_ATTR_CHANGED
);
8760 /* Rewrite BGP route information. */
8761 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8762 bgp_path_info_restore(bn
, bpi
);
8764 bgp_aggregate_decrement(
8765 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8766 bgp_attr_unintern(&bpi
->attr
);
8767 bpi
->attr
= new_attr
;
8768 bpi
->uptime
= monotime(NULL
);
8770 /* Process change. */
8771 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8773 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8774 bgp_dest_unlock_node(bn
);
8775 aspath_unintern(&attr
.aspath
);
8777 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8779 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8781 vpn_leak_from_vrf_update(
8782 bgp_get_default(), bgp
, bpi
);
8788 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8789 bgp
->peer_self
, new_attr
, bn
);
8790 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8792 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8793 bgp_path_info_add(bn
, new);
8794 bgp_dest_unlock_node(bn
);
8795 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8796 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8798 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8799 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8801 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8805 /* Unintern original. */
8806 aspath_unintern(&attr
.aspath
);
8809 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8810 unsigned short instance
)
8813 struct bgp_dest
*dest
;
8814 struct bgp_path_info
*pi
;
8815 struct bgp_redist
*red
;
8817 afi
= family2afi(p
->family
);
8819 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8821 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8822 SAFI_UNICAST
, p
, NULL
);
8824 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8825 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8829 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8830 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8832 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8835 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8836 bgp_path_info_delete(dest
, pi
);
8837 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8839 bgp_dest_unlock_node(dest
);
8843 /* Withdraw specified route type's route. */
8844 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8845 unsigned short instance
)
8847 struct bgp_dest
*dest
;
8848 struct bgp_path_info
*pi
;
8849 struct bgp_table
*table
;
8851 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8853 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8854 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8855 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8856 && pi
->instance
== instance
)
8860 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8861 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8863 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8866 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8867 pi
, afi
, SAFI_UNICAST
);
8868 bgp_path_info_delete(dest
, pi
);
8869 if (!CHECK_FLAG(bgp
->flags
,
8870 BGP_FLAG_DELETE_IN_PROGRESS
))
8871 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8873 bgp_path_info_reap(dest
, pi
);
8878 /* Static function to display route. */
8879 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8880 struct vty
*vty
, json_object
*json
, bool wide
)
8883 char buf
[INET6_ADDRSTRLEN
];
8885 if (p
->family
== AF_INET
) {
8887 len
= vty_out(vty
, "%pFX", p
);
8889 json_object_string_add(json
, "prefix",
8890 inet_ntop(p
->family
,
8893 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8894 json_object_string_addf(json
, "network", "%pFX", p
);
8895 json_object_int_add(json
, "version", dest
->version
);
8897 } else if (p
->family
== AF_ETHERNET
) {
8898 len
= vty_out(vty
, "%pFX", p
);
8899 } else if (p
->family
== AF_EVPN
) {
8901 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8903 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8904 } else if (p
->family
== AF_FLOWSPEC
) {
8905 route_vty_out_flowspec(vty
, p
, NULL
,
8907 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8908 NLRI_STRING_FORMAT_MIN
, json
);
8911 len
= vty_out(vty
, "%pFX", p
);
8913 json_object_string_add(json
, "prefix",
8914 inet_ntop(p
->family
,
8917 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8918 json_object_string_addf(json
, "network", "%pFX", p
);
8919 json_object_int_add(json
, "version", dest
->version
);
8924 len
= wide
? (45 - len
) : (17 - len
);
8926 vty_out(vty
, "\n%*s", 20, " ");
8928 vty_out(vty
, "%*s", len
, " ");
8932 enum bgp_display_type
{
8936 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8939 case bgp_path_selection_none
:
8940 return "Nothing to Select";
8941 case bgp_path_selection_first
:
8942 return "First path received";
8943 case bgp_path_selection_evpn_sticky_mac
:
8944 return "EVPN Sticky Mac";
8945 case bgp_path_selection_evpn_seq
:
8946 return "EVPN sequence number";
8947 case bgp_path_selection_evpn_lower_ip
:
8948 return "EVPN lower IP";
8949 case bgp_path_selection_evpn_local_path
:
8950 return "EVPN local ES path";
8951 case bgp_path_selection_evpn_non_proxy
:
8952 return "EVPN non proxy";
8953 case bgp_path_selection_weight
:
8955 case bgp_path_selection_local_pref
:
8956 return "Local Pref";
8957 case bgp_path_selection_accept_own
:
8958 return "Accept Own";
8959 case bgp_path_selection_local_route
:
8960 return "Local Route";
8961 case bgp_path_selection_aigp
:
8963 case bgp_path_selection_confed_as_path
:
8964 return "Confederation based AS Path";
8965 case bgp_path_selection_as_path
:
8967 case bgp_path_selection_origin
:
8969 case bgp_path_selection_med
:
8971 case bgp_path_selection_peer
:
8973 case bgp_path_selection_confed
:
8974 return "Confed Peer Type";
8975 case bgp_path_selection_igp_metric
:
8976 return "IGP Metric";
8977 case bgp_path_selection_older
:
8978 return "Older Path";
8979 case bgp_path_selection_router_id
:
8981 case bgp_path_selection_cluster_length
:
8982 return "Cluster length";
8983 case bgp_path_selection_stale
:
8984 return "Path Staleness";
8985 case bgp_path_selection_local_configured
:
8986 return "Locally configured route";
8987 case bgp_path_selection_neighbor_ip
:
8988 return "Neighbor IP";
8989 case bgp_path_selection_default
:
8990 return "Nothing left to compare";
8992 return "Invalid (internal error)";
8995 /* Print the short form route status for a bgp_path_info */
8996 static void route_vty_short_status_out(struct vty
*vty
,
8997 struct bgp_path_info
*path
,
8998 const struct prefix
*p
,
8999 json_object
*json_path
)
9001 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
9005 /* Route status display. */
9006 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9007 json_object_boolean_true_add(json_path
, "removed");
9009 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9010 json_object_boolean_true_add(json_path
, "stale");
9012 if (path
->extra
&& bgp_path_suppressed(path
))
9013 json_object_boolean_true_add(json_path
, "suppressed");
9015 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9016 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9017 json_object_boolean_true_add(json_path
, "valid");
9020 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9021 json_object_boolean_true_add(json_path
, "history");
9023 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9024 json_object_boolean_true_add(json_path
, "damped");
9026 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9027 json_object_boolean_true_add(json_path
, "bestpath");
9028 json_object_string_add(json_path
, "selectionReason",
9029 bgp_path_selection_reason2str(
9030 path
->net
->reason
));
9033 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9034 json_object_boolean_true_add(json_path
, "multipath");
9036 /* Internal route. */
9037 if ((path
->peer
->as
)
9038 && (path
->peer
->as
== path
->peer
->local_as
))
9039 json_object_string_add(json_path
, "pathFrom",
9042 json_object_string_add(json_path
, "pathFrom",
9048 /* RPKI validation state */
9050 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
9052 if (rpki_state
== RPKI_VALID
)
9054 else if (rpki_state
== RPKI_INVALID
)
9056 else if (rpki_state
== RPKI_NOTFOUND
)
9061 /* Route status display. */
9062 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9064 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9066 else if (bgp_path_suppressed(path
))
9068 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9069 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9075 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9077 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9079 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
9081 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9086 /* Internal route. */
9087 if (path
->peer
&& (path
->peer
->as
)
9088 && (path
->peer
->as
== path
->peer
->local_as
))
9094 static char *bgp_nexthop_hostname(struct peer
*peer
,
9095 struct bgp_nexthop_cache
*bnc
)
9098 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
9099 return peer
->hostname
;
9103 /* called from terminal list command */
9104 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9105 struct bgp_path_info
*path
, int display
, safi_t safi
,
9106 json_object
*json_paths
, bool wide
)
9109 struct attr
*attr
= path
->attr
;
9110 json_object
*json_path
= NULL
;
9111 json_object
*json_nexthops
= NULL
;
9112 json_object
*json_nexthop_global
= NULL
;
9113 json_object
*json_nexthop_ll
= NULL
;
9114 json_object
*json_ext_community
= NULL
;
9115 char vrf_id_str
[VRF_NAMSIZ
] = {0};
9117 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9118 bool nexthop_othervrf
= false;
9119 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
9120 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
9121 char *nexthop_hostname
=
9122 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9123 char esi_buf
[ESI_STR_LEN
];
9126 json_path
= json_object_new_object();
9128 /* short status lead text */
9129 route_vty_short_status_out(vty
, path
, p
, json_path
);
9132 /* print prefix and mask */
9134 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9136 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
9138 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9142 * If vrf id of nexthop is different from that of prefix,
9143 * set up printable string to append
9145 if (path
->extra
&& path
->extra
->bgp_orig
) {
9146 const char *self
= "";
9151 nexthop_othervrf
= true;
9152 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9154 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
9155 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
9156 "@%s%s", VRFID_NONE_STR
, self
);
9158 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
9159 path
->extra
->bgp_orig
->vrf_id
, self
);
9161 if (path
->extra
->bgp_orig
->inst_type
9162 != BGP_INSTANCE_TYPE_DEFAULT
)
9164 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
9166 const char *self
= "";
9171 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
9175 * For ENCAP and EVPN routes, nexthop address family is not
9176 * neccessarily the same as the prefix address family.
9177 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9178 * EVPN routes are also exchanged with a MP nexthop. Currently,
9180 * is only IPv4, the value will be present in either
9182 * attr->mp_nexthop_global_in
9184 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
9186 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9190 snprintfrr(nexthop
, sizeof(nexthop
), "%pI4",
9191 &attr
->mp_nexthop_global_in
);
9194 snprintfrr(nexthop
, sizeof(nexthop
), "%pI6",
9195 &attr
->mp_nexthop_global
);
9198 snprintf(nexthop
, sizeof(nexthop
), "?");
9203 json_nexthop_global
= json_object_new_object();
9205 json_object_string_add(json_nexthop_global
, "ip",
9208 if (path
->peer
->hostname
)
9209 json_object_string_add(json_nexthop_global
,
9211 path
->peer
->hostname
);
9213 json_object_string_add(json_nexthop_global
, "afi",
9214 (af
== AF_INET
) ? "ipv4"
9216 json_object_boolean_true_add(json_nexthop_global
,
9219 if (nexthop_hostname
)
9220 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
9221 nexthop_hostname
, vrf_id_str
);
9223 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
9225 len
= wide
? (41 - len
) : (16 - len
);
9227 vty_out(vty
, "\n%*s", 36, " ");
9229 vty_out(vty
, "%*s", len
, " ");
9231 } else if (safi
== SAFI_EVPN
) {
9233 json_nexthop_global
= json_object_new_object();
9235 json_object_string_addf(json_nexthop_global
, "ip",
9237 &attr
->mp_nexthop_global_in
);
9239 if (path
->peer
->hostname
)
9240 json_object_string_add(json_nexthop_global
,
9242 path
->peer
->hostname
);
9244 json_object_string_add(json_nexthop_global
, "afi",
9246 json_object_boolean_true_add(json_nexthop_global
,
9249 if (nexthop_hostname
)
9250 len
= vty_out(vty
, "%pI4(%s)%s",
9251 &attr
->mp_nexthop_global_in
,
9252 nexthop_hostname
, vrf_id_str
);
9254 len
= vty_out(vty
, "%pI4%s",
9255 &attr
->mp_nexthop_global_in
,
9258 len
= wide
? (41 - len
) : (16 - len
);
9260 vty_out(vty
, "\n%*s", 36, " ");
9262 vty_out(vty
, "%*s", len
, " ");
9264 } else if (safi
== SAFI_FLOWSPEC
) {
9265 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
9267 json_nexthop_global
= json_object_new_object();
9269 json_object_string_add(json_nexthop_global
,
9271 json_object_string_addf(json_nexthop_global
,
9275 if (path
->peer
->hostname
)
9276 json_object_string_add(
9277 json_nexthop_global
, "hostname",
9278 path
->peer
->hostname
);
9280 json_object_boolean_true_add(
9281 json_nexthop_global
,
9284 if (nexthop_hostname
)
9285 len
= vty_out(vty
, "%pI4(%s)%s",
9290 len
= vty_out(vty
, "%pI4%s",
9294 len
= wide
? (41 - len
) : (16 - len
);
9296 vty_out(vty
, "\n%*s", 36, " ");
9298 vty_out(vty
, "%*s", len
, " ");
9301 } else if (p
->family
== AF_INET
&& !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9303 json_nexthop_global
= json_object_new_object();
9305 json_object_string_addf(json_nexthop_global
, "ip",
9306 "%pI4", &attr
->nexthop
);
9308 if (path
->peer
->hostname
)
9309 json_object_string_add(json_nexthop_global
,
9311 path
->peer
->hostname
);
9313 json_object_string_add(json_nexthop_global
, "afi",
9315 json_object_boolean_true_add(json_nexthop_global
,
9318 if (nexthop_hostname
)
9319 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
9320 nexthop_hostname
, vrf_id_str
);
9322 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
9325 len
= wide
? (41 - len
) : (16 - len
);
9327 vty_out(vty
, "\n%*s", 36, " ");
9329 vty_out(vty
, "%*s", len
, " ");
9334 else if (p
->family
== AF_INET6
|| BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9336 json_nexthop_global
= json_object_new_object();
9337 json_object_string_addf(json_nexthop_global
, "ip",
9339 &attr
->mp_nexthop_global
);
9341 if (path
->peer
->hostname
)
9342 json_object_string_add(json_nexthop_global
,
9344 path
->peer
->hostname
);
9346 json_object_string_add(json_nexthop_global
, "afi",
9348 json_object_string_add(json_nexthop_global
, "scope",
9351 /* We display both LL & GL if both have been
9353 if ((attr
->mp_nexthop_len
9354 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9355 || (path
->peer
->conf_if
)) {
9356 json_nexthop_ll
= json_object_new_object();
9357 json_object_string_addf(
9358 json_nexthop_ll
, "ip", "%pI6",
9359 &attr
->mp_nexthop_local
);
9361 if (path
->peer
->hostname
)
9362 json_object_string_add(
9363 json_nexthop_ll
, "hostname",
9364 path
->peer
->hostname
);
9366 json_object_string_add(json_nexthop_ll
, "afi",
9368 json_object_string_add(json_nexthop_ll
, "scope",
9371 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9372 &attr
->mp_nexthop_local
)
9374 && !attr
->mp_nexthop_prefer_global
)
9375 json_object_boolean_true_add(
9376 json_nexthop_ll
, "used");
9378 json_object_boolean_true_add(
9379 json_nexthop_global
, "used");
9381 json_object_boolean_true_add(
9382 json_nexthop_global
, "used");
9384 /* Display LL if LL/Global both in table unless
9385 * prefer-global is set */
9386 if (((attr
->mp_nexthop_len
9387 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9388 && !attr
->mp_nexthop_prefer_global
)
9389 || (path
->peer
->conf_if
)) {
9390 if (path
->peer
->conf_if
) {
9391 len
= vty_out(vty
, "%s",
9392 path
->peer
->conf_if
);
9393 /* len of IPv6 addr + max len of def
9395 len
= wide
? (41 - len
) : (16 - len
);
9398 vty_out(vty
, "\n%*s", 36, " ");
9400 vty_out(vty
, "%*s", len
, " ");
9402 if (nexthop_hostname
)
9405 &attr
->mp_nexthop_local
,
9411 &attr
->mp_nexthop_local
,
9414 len
= wide
? (41 - len
) : (16 - len
);
9417 vty_out(vty
, "\n%*s", 36, " ");
9419 vty_out(vty
, "%*s", len
, " ");
9422 if (nexthop_hostname
)
9423 len
= vty_out(vty
, "%pI6(%s)%s",
9424 &attr
->mp_nexthop_global
,
9428 len
= vty_out(vty
, "%pI6%s",
9429 &attr
->mp_nexthop_global
,
9432 len
= wide
? (41 - len
) : (16 - len
);
9435 vty_out(vty
, "\n%*s", 36, " ");
9437 vty_out(vty
, "%*s", len
, " ");
9443 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9445 json_object_int_add(json_path
, "metric", attr
->med
);
9447 vty_out(vty
, "%7u", attr
->med
);
9449 vty_out(vty
, "%10u", attr
->med
);
9450 else if (!json_paths
) {
9452 vty_out(vty
, "%*s", 7, " ");
9454 vty_out(vty
, "%*s", 10, " ");
9458 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9460 json_object_int_add(json_path
, "locPrf",
9463 vty_out(vty
, "%7u", attr
->local_pref
);
9464 else if (!json_paths
)
9468 json_object_int_add(json_path
, "weight", attr
->weight
);
9470 vty_out(vty
, "%7u ", attr
->weight
);
9473 json_object_string_addf(json_path
, "peerId", "%pSU",
9479 json_object_string_add(json_path
, "path",
9482 aspath_print_vty(vty
, attr
->aspath
);
9487 json_object_string_add(json_path
, "origin",
9488 bgp_origin_long_str
[attr
->origin
]);
9490 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9493 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9494 json_object_string_add(json_path
, "esi",
9495 esi_to_str(&attr
->esi
,
9496 esi_buf
, sizeof(esi_buf
)));
9498 if (safi
== SAFI_EVPN
&&
9499 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9500 json_ext_community
= json_object_new_object();
9501 json_object_string_add(
9502 json_ext_community
, "string",
9503 bgp_attr_get_ecommunity(attr
)->str
);
9504 json_object_object_add(json_path
,
9505 "extendedCommunity",
9506 json_ext_community
);
9510 json_object_boolean_true_add(json_path
,
9511 "announceNexthopSelf");
9512 if (nexthop_othervrf
) {
9513 json_object_string_add(json_path
, "nhVrfName",
9516 json_object_int_add(json_path
, "nhVrfId",
9517 ((nexthop_vrfid
== VRF_UNKNOWN
)
9519 : (int)nexthop_vrfid
));
9524 if (json_nexthop_global
|| json_nexthop_ll
) {
9525 json_nexthops
= json_object_new_array();
9527 if (json_nexthop_global
)
9528 json_object_array_add(json_nexthops
,
9529 json_nexthop_global
);
9531 if (json_nexthop_ll
)
9532 json_object_array_add(json_nexthops
,
9535 json_object_object_add(json_path
, "nexthops",
9539 json_object_array_add(json_paths
, json_path
);
9543 if (safi
== SAFI_EVPN
) {
9544 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9545 /* XXX - add these params to the json out */
9546 vty_out(vty
, "%*s", 20, " ");
9547 vty_out(vty
, "ESI:%s",
9548 esi_to_str(&attr
->esi
, esi_buf
,
9554 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9555 vty_out(vty
, "%*s", 20, " ");
9556 vty_out(vty
, "%s\n",
9557 bgp_attr_get_ecommunity(attr
)->str
);
9561 #ifdef ENABLE_BGP_VNC
9562 /* prints an additional line, indented, with VNC info, if
9564 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9565 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9570 /* called from terminal list command */
9571 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9572 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9573 bool use_json
, json_object
*json_ar
, bool wide
)
9575 json_object
*json_status
= NULL
;
9576 json_object
*json_net
= NULL
;
9580 /* Route status display. */
9582 json_status
= json_object_new_object();
9583 json_net
= json_object_new_object();
9590 /* print prefix and mask */
9592 if (safi
== SAFI_EVPN
)
9593 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9594 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9595 json_object_string_add(
9596 json_net
, "addrPrefix",
9597 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9599 json_object_int_add(json_net
, "prefixLen",
9601 json_object_string_addf(json_net
, "network", "%pFX", p
);
9604 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9606 /* Print attribute */
9609 if (p
->family
== AF_INET
&&
9610 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9611 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9612 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9613 json_object_string_addf(
9614 json_net
, "nextHop", "%pI4",
9615 &attr
->mp_nexthop_global_in
);
9617 json_object_string_addf(
9618 json_net
, "nextHop", "%pI4",
9620 } else if (p
->family
== AF_INET6
||
9621 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9622 json_object_string_addf(
9623 json_net
, "nextHopGlobal", "%pI6",
9624 &attr
->mp_nexthop_global
);
9625 } else if (p
->family
== AF_EVPN
&&
9626 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9627 json_object_string_addf(
9628 json_net
, "nextHop", "%pI4",
9629 &attr
->mp_nexthop_global_in
);
9633 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9634 json_object_int_add(json_net
, "metric",
9637 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9638 json_object_int_add(json_net
, "locPrf",
9641 json_object_int_add(json_net
, "weight", attr
->weight
);
9645 json_object_string_add(json_net
, "path",
9649 #if CONFDATE > 20231208
9650 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9652 json_object_string_add(json_net
, "bgpOriginCode",
9653 bgp_origin_str
[attr
->origin
]);
9654 json_object_string_add(
9656 bgp_origin_long_str
[attr
->origin
]);
9658 if (p
->family
== AF_INET
&&
9659 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9660 safi
== SAFI_EVPN
||
9661 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9662 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9663 || safi
== SAFI_EVPN
)
9664 vty_out(vty
, "%-16pI4",
9665 &attr
->mp_nexthop_global_in
);
9667 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9669 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9670 } else if (p
->family
== AF_INET6
||
9671 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9672 len
= vty_out(vty
, "%pI6",
9673 &attr
->mp_nexthop_global
);
9674 len
= wide
? (41 - len
) : (16 - len
);
9676 vty_out(vty
, "\n%*s", 36, " ");
9678 vty_out(vty
, "%*s", len
, " ");
9681 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9683 vty_out(vty
, "%7u", attr
->med
);
9685 vty_out(vty
, "%10u", attr
->med
);
9691 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9692 vty_out(vty
, "%7u", attr
->local_pref
);
9696 vty_out(vty
, "%7u ", attr
->weight
);
9700 aspath_print_vty(vty
, attr
->aspath
);
9703 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9707 struct bgp_path_info
*bpi
= bgp_dest_get_bgp_path_info(dest
);
9709 #if CONFDATE > 20231208
9710 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9712 json_object_boolean_true_add(json_status
, "*");
9713 json_object_boolean_true_add(json_status
, ">");
9714 json_object_boolean_true_add(json_net
, "valid");
9715 json_object_boolean_true_add(json_net
, "best");
9717 if (bpi
&& CHECK_FLAG(bpi
->flags
, BGP_PATH_MULTIPATH
)) {
9718 json_object_boolean_true_add(json_status
, "=");
9719 json_object_boolean_true_add(json_net
, "multipath");
9721 json_object_object_add(json_net
, "appliedStatusSymbols",
9723 json_object_object_addf(json_ar
, json_net
, "%pFX", p
);
9728 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9729 struct bgp_path_info
*path
, int display
, safi_t safi
,
9732 json_object
*json_out
= NULL
;
9734 mpls_label_t label
= MPLS_INVALID_LABEL
;
9740 json_out
= json_object_new_object();
9742 /* short status lead text */
9743 route_vty_short_status_out(vty
, path
, p
, json_out
);
9745 /* print prefix and mask */
9748 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9750 vty_out(vty
, "%*s", 17, " ");
9753 /* Print attribute */
9755 if (((p
->family
== AF_INET
) &&
9756 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9757 (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) ||
9758 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9759 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9760 || safi
== SAFI_EVPN
) {
9762 json_object_string_addf(
9763 json_out
, "mpNexthopGlobalIn", "%pI4",
9764 &attr
->mp_nexthop_global_in
);
9766 vty_out(vty
, "%-16pI4",
9767 &attr
->mp_nexthop_global_in
);
9770 json_object_string_addf(json_out
, "nexthop",
9771 "%pI4", &attr
->nexthop
);
9773 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9775 } else if (((p
->family
== AF_INET6
) &&
9776 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9777 (safi
== SAFI_EVPN
&& BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) ||
9778 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9781 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9783 json_object_string_addf(
9784 json_out
, "mpNexthopGlobalIn", "%pI6",
9785 &attr
->mp_nexthop_global
);
9789 &attr
->mp_nexthop_global
,
9790 buf_a
, sizeof(buf_a
)));
9791 } else if (attr
->mp_nexthop_len
9792 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9793 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9794 &attr
->mp_nexthop_global
,
9795 &attr
->mp_nexthop_local
);
9797 json_object_string_add(json_out
,
9798 "mpNexthopGlobalLocal",
9801 vty_out(vty
, "%s", buf_a
);
9805 label
= decode_label(&path
->extra
->label
[0]);
9807 if (bgp_is_valid_label(&label
)) {
9809 json_object_int_add(json_out
, "notag", label
);
9810 json_object_array_add(json
, json_out
);
9812 vty_out(vty
, "notag/%d", label
);
9819 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9820 struct bgp_path_info
*path
, int display
,
9821 json_object
*json_paths
)
9824 json_object
*json_path
= NULL
;
9825 json_object
*json_nexthop
= NULL
;
9826 json_object
*json_overlay
= NULL
;
9832 json_path
= json_object_new_object();
9833 json_overlay
= json_object_new_object();
9834 json_nexthop
= json_object_new_object();
9837 /* short status lead text */
9838 route_vty_short_status_out(vty
, path
, p
, json_path
);
9840 /* print prefix and mask */
9842 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9844 vty_out(vty
, "%*s", 17, " ");
9846 /* Print attribute */
9848 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9853 vty_out(vty
, "%-16pI4", &attr
->mp_nexthop_global_in
);
9855 json_object_string_addf(json_nexthop
, "ip", "%pI4",
9856 &attr
->mp_nexthop_global_in
);
9858 json_object_string_add(json_nexthop
, "afi", "ipv4");
9860 json_object_object_add(json_path
, "nexthop",
9866 vty_out(vty
, "%pI6(%pI6)", &attr
->mp_nexthop_global
,
9867 &attr
->mp_nexthop_local
);
9869 json_object_string_addf(json_nexthop
, "ipv6Global",
9871 &attr
->mp_nexthop_global
);
9873 json_object_string_addf(json_nexthop
, "ipv6LinkLocal",
9875 &attr
->mp_nexthop_local
);
9877 json_object_string_add(json_nexthop
, "afi", "ipv6");
9879 json_object_object_add(json_path
, "nexthop",
9887 json_object_string_add(json_nexthop
, "error",
9888 "Unsupported address-family");
9892 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9895 vty_out(vty
, "/%pIA", &eo
->gw_ip
);
9897 json_object_string_addf(json_overlay
, "gw", "%pIA", &eo
->gw_ip
);
9899 if (bgp_attr_get_ecommunity(attr
)) {
9901 struct ecommunity_val
*routermac
= ecommunity_lookup(
9902 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9903 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9906 mac
= ecom_mac2str((char *)routermac
->val
);
9909 vty_out(vty
, "/%s", mac
);
9911 json_object_string_add(json_overlay
, "rmac",
9914 XFREE(MTYPE_TMP
, mac
);
9921 json_object_object_add(json_path
, "overlay", json_overlay
);
9923 json_object_array_add(json_paths
, json_path
);
9927 /* dampening route */
9928 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9929 struct bgp_path_info
*path
, int display
,
9930 afi_t afi
, safi_t safi
, bool use_json
,
9931 json_object
*json_paths
)
9933 struct attr
*attr
= path
->attr
;
9935 char timebuf
[BGP_UPTIME_LEN
];
9936 json_object
*json_path
= NULL
;
9939 json_path
= json_object_new_object();
9941 /* short status lead text */
9942 route_vty_short_status_out(vty
, path
, p
, json_path
);
9944 /* print prefix and mask */
9947 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9949 vty_out(vty
, "%*s", 17, " ");
9951 len
= vty_out(vty
, "%s", path
->peer
->host
);
9955 vty_out(vty
, "\n%*s", 34, " ");
9957 vty_out(vty
, "%*s", len
, " ");
9960 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9961 BGP_UPTIME_LEN
, afi
, safi
,
9965 aspath_print_vty(vty
, attr
->aspath
);
9967 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9971 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9972 safi
, use_json
, json_path
);
9975 json_object_string_add(json_path
, "asPath",
9978 json_object_string_add(json_path
, "origin",
9979 bgp_origin_str
[attr
->origin
]);
9980 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9982 json_object_array_add(json_paths
, json_path
);
9987 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9988 struct bgp_path_info
*path
, int display
,
9989 afi_t afi
, safi_t safi
, bool use_json
,
9990 json_object
*json_paths
)
9992 struct attr
*attr
= path
->attr
;
9993 struct bgp_damp_info
*bdi
;
9994 char timebuf
[BGP_UPTIME_LEN
];
9996 json_object
*json_path
= NULL
;
10002 json_path
= json_object_new_object();
10004 bdi
= path
->extra
->damp_info
;
10006 /* short status lead text */
10007 route_vty_short_status_out(vty
, path
, p
, json_path
);
10011 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
10013 vty_out(vty
, "%*s", 17, " ");
10015 len
= vty_out(vty
, "%s", path
->peer
->host
);
10018 vty_out(vty
, "\n%*s", 33, " ");
10020 vty_out(vty
, "%*s", len
, " ");
10022 len
= vty_out(vty
, "%d", bdi
->flap
);
10027 vty_out(vty
, "%*s", len
, " ");
10029 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
10030 BGP_UPTIME_LEN
, 0, NULL
));
10032 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10033 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10034 vty_out(vty
, "%s ",
10035 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10036 BGP_UPTIME_LEN
, afi
,
10037 safi
, use_json
, NULL
));
10039 vty_out(vty
, "%*s ", 8, " ");
10042 aspath_print_vty(vty
, attr
->aspath
);
10044 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10046 vty_out(vty
, "\n");
10048 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10049 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
10051 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
10054 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10055 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10056 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10057 BGP_UPTIME_LEN
, afi
, safi
,
10058 use_json
, json_path
);
10061 json_object_string_add(json_path
, "asPath",
10062 attr
->aspath
->str
);
10064 json_object_string_add(json_path
, "origin",
10065 bgp_origin_str
[attr
->origin
]);
10067 json_object_array_add(json_paths
, json_path
);
10071 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
10072 int *first
, const char *header
,
10073 json_object
*json_adv_to
)
10075 json_object
*json_peer
= NULL
;
10078 /* 'advertised-to' is a dictionary of peers we have advertised
10080 * prefix too. The key is the peer's IP or swpX, the value is
10082 * hostname if we know it and "" if not.
10084 json_peer
= json_object_new_object();
10086 if (peer
->hostname
)
10087 json_object_string_add(json_peer
, "hostname",
10091 json_object_object_add(json_adv_to
, peer
->conf_if
,
10094 json_object_object_addf(json_adv_to
, json_peer
, "%pSU",
10098 vty_out(vty
, "%s", header
);
10103 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
10105 vty_out(vty
, " %s(%s)", peer
->hostname
,
10108 vty_out(vty
, " %s(%pSU)", peer
->hostname
,
10112 vty_out(vty
, " %s", peer
->conf_if
);
10114 vty_out(vty
, " %pSU", &peer
->su
);
10119 static void route_vty_out_tx_ids(struct vty
*vty
,
10120 struct bgp_addpath_info_data
*d
)
10124 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10125 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
10126 d
->addpath_tx_id
[i
],
10127 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
10131 static void route_vty_out_detail_es_info(struct vty
*vty
,
10132 struct bgp_path_info
*pi
,
10134 json_object
*json_path
)
10136 char esi_buf
[ESI_STR_LEN
];
10137 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
10138 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
10139 ATTR_ES_PEER_ROUTER
);
10140 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
10141 ATTR_ES_PEER_ACTIVE
);
10142 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
10143 ATTR_ES_PEER_PROXY
);
10144 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
10146 json_object
*json_es_info
= NULL
;
10148 json_object_string_add(
10151 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
10152 json_es_info
= json_object_new_object();
10154 json_object_boolean_true_add(
10155 json_es_info
, "localEs");
10157 json_object_boolean_true_add(
10158 json_es_info
, "peerActive");
10160 json_object_boolean_true_add(
10161 json_es_info
, "peerProxy");
10163 json_object_boolean_true_add(
10164 json_es_info
, "peerRouter");
10165 if (attr
->mm_sync_seqnum
)
10166 json_object_int_add(
10167 json_es_info
, "peerSeq",
10168 attr
->mm_sync_seqnum
);
10169 json_object_object_add(
10170 json_path
, "es_info",
10174 if (bgp_evpn_attr_is_sync(attr
))
10176 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10178 es_local
? "local-es":"",
10179 peer_proxy
? "proxy " : "",
10180 peer_active
? "active ":"",
10181 peer_router
? "router ":"",
10182 attr
->mm_sync_seqnum
);
10184 vty_out(vty
, " ESI %s %s\n",
10186 es_local
? "local-es":"");
10190 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
10191 const struct prefix
*p
, struct bgp_path_info
*path
,
10192 afi_t afi
, safi_t safi
,
10193 enum rpki_states rpki_curr_state
,
10194 json_object
*json_paths
)
10196 char buf
[INET6_ADDRSTRLEN
];
10198 struct attr
*attr
= path
->attr
;
10200 json_object
*json_bestpath
= NULL
;
10201 json_object
*json_cluster_list
= NULL
;
10202 json_object
*json_cluster_list_list
= NULL
;
10203 json_object
*json_ext_community
= NULL
;
10204 json_object
*json_last_update
= NULL
;
10205 json_object
*json_pmsi
= NULL
;
10206 json_object
*json_nexthop_global
= NULL
;
10207 json_object
*json_nexthop_ll
= NULL
;
10208 json_object
*json_nexthops
= NULL
;
10209 json_object
*json_path
= NULL
;
10210 json_object
*json_peer
= NULL
;
10211 json_object
*json_string
= NULL
;
10212 json_object
*json_adv_to
= NULL
;
10214 struct listnode
*node
, *nnode
;
10216 bool addpath_capable
;
10218 unsigned int first_as
;
10219 bool nexthop_self
=
10220 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
10222 char *nexthop_hostname
=
10223 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
10227 mpls_label_t label
= MPLS_INVALID_LABEL
;
10229 struct bgp_path_info
*bpi_ultimate
=
10230 bgp_get_imported_bpi_ultimate(path
);
10233 json_path
= json_object_new_object();
10234 json_peer
= json_object_new_object();
10235 json_nexthop_global
= json_object_new_object();
10238 if (safi
== SAFI_EVPN
) {
10240 vty_out(vty
, " Route %pFX", p
);
10244 if (path
->extra
&& path
->extra
->num_labels
) {
10245 bgp_evpn_label2str(path
->extra
->label
,
10246 path
->extra
->num_labels
, tag_buf
,
10249 if (safi
== SAFI_EVPN
) {
10251 if (tag_buf
[0] != '\0')
10252 vty_out(vty
, " VNI %s", tag_buf
);
10255 json_object_string_add(json_path
, "vni",
10261 if (safi
== SAFI_EVPN
10262 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
10263 char gwip_buf
[INET6_ADDRSTRLEN
];
10265 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
10269 json_object_string_add(json_path
, "gatewayIP",
10272 vty_out(vty
, " Gateway IP %s", gwip_buf
);
10275 if (safi
== SAFI_EVPN
&& !json_path
)
10276 vty_out(vty
, "\n");
10279 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
10280 struct bgp_path_info
*parent_ri
;
10281 struct bgp_dest
*dest
, *pdest
;
10283 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
10284 dest
= parent_ri
->net
;
10285 if (dest
&& dest
->pdest
) {
10286 pdest
= dest
->pdest
;
10287 if (is_pi_family_evpn(parent_ri
)) {
10288 vty_out(vty
, " Imported from ");
10289 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
10290 (struct prefix_rd
*)bgp_dest_get_prefix(
10292 vty_out(vty
, ":%pFX, VNI %s",
10293 (struct prefix_evpn
*)
10294 bgp_dest_get_prefix(dest
),
10296 if (CHECK_FLAG(attr
->es_flags
, ATTR_ES_L3_NHG
))
10297 vty_out(vty
, ", L3NHG %s",
10300 ATTR_ES_L3_NHG_ACTIVE
)
10303 vty_out(vty
, "\n");
10306 vty_out(vty
, " Imported from ");
10307 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
10308 (struct prefix_rd
*)bgp_dest_get_prefix(
10310 vty_out(vty
, ":%pFX\n",
10311 (struct prefix_evpn
*)
10312 bgp_dest_get_prefix(dest
));
10317 /* Line1 display AS-path, Aggregator */
10318 if (attr
->aspath
) {
10320 if (!attr
->aspath
->json
)
10321 aspath_str_update(attr
->aspath
, true);
10322 json_object_lock(attr
->aspath
->json
);
10323 json_object_object_add(json_path
, "aspath",
10324 attr
->aspath
->json
);
10326 if (attr
->aspath
->segments
)
10327 vty_out(vty
, " %s", attr
->aspath
->str
);
10329 vty_out(vty
, " Local");
10333 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
10335 json_object_boolean_true_add(json_path
, "removed");
10337 vty_out(vty
, ", (removed)");
10340 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10342 json_object_boolean_true_add(json_path
, "stale");
10344 vty_out(vty
, ", (stale)");
10347 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
10349 json_object_int_add(json_path
, "aggregatorAs",
10350 attr
->aggregator_as
);
10351 json_object_string_addf(json_path
, "aggregatorId",
10352 "%pI4", &attr
->aggregator_addr
);
10354 vty_out(vty
, ", (aggregated by %u %pI4)",
10355 attr
->aggregator_as
, &attr
->aggregator_addr
);
10359 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10360 PEER_FLAG_REFLECTOR_CLIENT
)) {
10362 json_object_boolean_true_add(json_path
,
10363 "rxedFromRrClient");
10365 vty_out(vty
, ", (Received from a RR-client)");
10368 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10369 PEER_FLAG_RSERVER_CLIENT
)) {
10371 json_object_boolean_true_add(json_path
,
10372 "rxedFromRsClient");
10374 vty_out(vty
, ", (Received from a RS-client)");
10377 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10379 json_object_boolean_true_add(json_path
,
10380 "dampeningHistoryEntry");
10382 vty_out(vty
, ", (history entry)");
10383 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10385 json_object_boolean_true_add(json_path
,
10386 "dampeningSuppressed");
10388 vty_out(vty
, ", (suppressed due to dampening)");
10392 vty_out(vty
, "\n");
10394 /* Line2 display Next-hop, Neighbor, Router-id */
10395 /* Display the nexthop */
10397 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
||
10398 p
->family
== AF_EVPN
) &&
10399 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
||
10400 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10401 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10402 || safi
== SAFI_EVPN
) {
10404 json_object_string_addf(
10405 json_nexthop_global
, "ip", "%pI4",
10406 &attr
->mp_nexthop_global_in
);
10408 if (path
->peer
->hostname
)
10409 json_object_string_add(
10410 json_nexthop_global
, "hostname",
10411 path
->peer
->hostname
);
10413 if (nexthop_hostname
)
10414 vty_out(vty
, " %pI4(%s)",
10415 &attr
->mp_nexthop_global_in
,
10418 vty_out(vty
, " %pI4",
10419 &attr
->mp_nexthop_global_in
);
10423 json_object_string_addf(json_nexthop_global
,
10427 if (path
->peer
->hostname
)
10428 json_object_string_add(
10429 json_nexthop_global
, "hostname",
10430 path
->peer
->hostname
);
10432 if (nexthop_hostname
)
10433 vty_out(vty
, " %pI4(%s)",
10437 vty_out(vty
, " %pI4",
10443 json_object_string_add(json_nexthop_global
, "afi",
10447 json_object_string_addf(json_nexthop_global
, "ip",
10449 &attr
->mp_nexthop_global
);
10451 if (path
->peer
->hostname
)
10452 json_object_string_add(json_nexthop_global
,
10454 path
->peer
->hostname
);
10456 json_object_string_add(json_nexthop_global
, "afi",
10458 json_object_string_add(json_nexthop_global
, "scope",
10461 if (nexthop_hostname
)
10462 vty_out(vty
, " %pI6(%s)",
10463 &attr
->mp_nexthop_global
,
10466 vty_out(vty
, " %pI6",
10467 &attr
->mp_nexthop_global
);
10471 /* Display the IGP cost or 'inaccessible' */
10472 if (!CHECK_FLAG(bpi_ultimate
->flags
, BGP_PATH_VALID
)) {
10473 bool import
= CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
);
10476 json_object_boolean_false_add(json_nexthop_global
,
10478 json_object_boolean_add(json_nexthop_global
,
10479 "importCheckEnabled", import
);
10481 vty_out(vty
, " (inaccessible%s)",
10482 import
? ", import-check enabled" : "");
10485 if (bpi_ultimate
->extra
&& bpi_ultimate
->extra
->igpmetric
) {
10487 json_object_int_add(
10488 json_nexthop_global
, "metric",
10489 bpi_ultimate
->extra
->igpmetric
);
10491 vty_out(vty
, " (metric %u)",
10492 bpi_ultimate
->extra
->igpmetric
);
10495 /* IGP cost is 0, display this only for json */
10498 json_object_int_add(json_nexthop_global
,
10503 json_object_boolean_true_add(json_nexthop_global
,
10507 /* Display peer "from" output */
10508 /* This path was originated locally */
10509 if (path
->peer
== bgp
->peer_self
) {
10511 if (safi
== SAFI_EVPN
|| (p
->family
== AF_INET
&&
10512 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10514 json_object_string_add(json_peer
, "peerId",
10517 vty_out(vty
, " from 0.0.0.0 ");
10520 json_object_string_add(json_peer
, "peerId",
10523 vty_out(vty
, " from :: ");
10527 json_object_string_addf(json_peer
, "routerId", "%pI4",
10530 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10533 /* We RXed this path from one of our peers */
10537 json_object_string_addf(json_peer
, "peerId", "%pSU",
10539 json_object_string_addf(json_peer
, "routerId", "%pI4",
10540 &path
->peer
->remote_id
);
10542 if (path
->peer
->hostname
)
10543 json_object_string_add(json_peer
, "hostname",
10544 path
->peer
->hostname
);
10546 if (path
->peer
->domainname
)
10547 json_object_string_add(json_peer
, "domainname",
10548 path
->peer
->domainname
);
10550 if (path
->peer
->conf_if
)
10551 json_object_string_add(json_peer
, "interface",
10552 path
->peer
->conf_if
);
10554 if (path
->peer
->conf_if
) {
10555 if (path
->peer
->hostname
10556 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10557 BGP_FLAG_SHOW_HOSTNAME
))
10558 vty_out(vty
, " from %s(%s)",
10559 path
->peer
->hostname
,
10560 path
->peer
->conf_if
);
10562 vty_out(vty
, " from %s",
10563 path
->peer
->conf_if
);
10565 if (path
->peer
->hostname
10566 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10567 BGP_FLAG_SHOW_HOSTNAME
))
10568 vty_out(vty
, " from %s(%s)",
10569 path
->peer
->hostname
,
10572 vty_out(vty
, " from %pSU",
10576 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10577 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10579 vty_out(vty
, " (%pI4)", &path
->peer
->remote_id
);
10584 * Note when vrfid of nexthop is different from that of prefix
10586 if (path
->extra
&& path
->extra
->bgp_orig
) {
10587 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10592 if (path
->extra
->bgp_orig
->inst_type
10593 == BGP_INSTANCE_TYPE_DEFAULT
)
10594 vn
= VRF_DEFAULT_NAME
;
10596 vn
= path
->extra
->bgp_orig
->name
;
10598 json_object_string_add(json_path
, "nhVrfName", vn
);
10600 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10601 json_object_int_add(json_path
, "nhVrfId", -1);
10603 json_object_int_add(json_path
, "nhVrfId",
10604 (int)nexthop_vrfid
);
10607 if (nexthop_vrfid
== VRF_UNKNOWN
)
10608 vty_out(vty
, " vrf ?");
10612 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10613 vty_out(vty
, " vrf %s(%u)",
10614 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10619 if (nexthop_self
) {
10621 json_object_boolean_true_add(json_path
,
10622 "announceNexthopSelf");
10624 vty_out(vty
, " announce-nh-self");
10629 vty_out(vty
, "\n");
10631 /* display the link-local nexthop */
10632 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10634 json_nexthop_ll
= json_object_new_object();
10635 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10636 &attr
->mp_nexthop_local
);
10638 if (path
->peer
->hostname
)
10639 json_object_string_add(json_nexthop_ll
,
10641 path
->peer
->hostname
);
10643 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10644 json_object_string_add(json_nexthop_ll
, "scope",
10647 json_object_boolean_true_add(json_nexthop_ll
,
10650 if (!attr
->mp_nexthop_prefer_global
)
10651 json_object_boolean_true_add(json_nexthop_ll
,
10654 json_object_boolean_true_add(
10655 json_nexthop_global
, "used");
10657 vty_out(vty
, " (%s) %s\n",
10658 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10659 buf
, INET6_ADDRSTRLEN
),
10660 attr
->mp_nexthop_prefer_global
10661 ? "(prefer-global)"
10665 /* If we do not have a link-local nexthop then we must flag the
10666 global as "used" */
10669 json_object_boolean_true_add(json_nexthop_global
,
10673 if (safi
== SAFI_EVPN
&&
10674 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10675 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10678 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10679 * Int/Ext/Local, Atomic, best */
10681 json_object_string_add(json_path
, "origin",
10682 bgp_origin_long_str
[attr
->origin
]);
10684 vty_out(vty
, " Origin %s",
10685 bgp_origin_long_str
[attr
->origin
]);
10687 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10689 json_object_int_add(json_path
, "metric", attr
->med
);
10691 vty_out(vty
, ", metric %u", attr
->med
);
10694 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10696 json_object_int_add(json_path
, "locPrf",
10699 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10702 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
10704 json_object_int_add(json_path
, "aigpMetric",
10705 bgp_attr_get_aigp_metric(attr
));
10707 vty_out(vty
, ", aigp-metric %" PRIu64
,
10708 bgp_attr_get_aigp_metric(attr
));
10711 if (attr
->weight
!= 0) {
10713 json_object_int_add(json_path
, "weight", attr
->weight
);
10715 vty_out(vty
, ", weight %u", attr
->weight
);
10718 if (attr
->tag
!= 0) {
10720 json_object_int_add(json_path
, "tag", attr
->tag
);
10722 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10725 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10727 json_object_boolean_false_add(json_path
, "valid");
10729 vty_out(vty
, ", invalid");
10730 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10732 json_object_boolean_true_add(json_path
, "valid");
10734 vty_out(vty
, ", valid");
10738 json_object_int_add(json_path
, "version", bn
->version
);
10740 if (path
->peer
!= bgp
->peer_self
) {
10741 if (path
->peer
->as
== path
->peer
->local_as
) {
10742 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10744 json_object_string_add(
10746 "confed-internal");
10748 vty_out(vty
, ", confed-internal");
10751 json_object_string_add(
10752 json_peer
, "type", "internal");
10754 vty_out(vty
, ", internal");
10757 if (bgp_confederation_peers_check(bgp
,
10760 json_object_string_add(
10762 "confed-external");
10764 vty_out(vty
, ", confed-external");
10767 json_object_string_add(
10768 json_peer
, "type", "external");
10770 vty_out(vty
, ", external");
10773 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10775 json_object_boolean_true_add(json_path
, "aggregated");
10776 json_object_boolean_true_add(json_path
, "local");
10778 vty_out(vty
, ", aggregated, local");
10780 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10782 json_object_boolean_true_add(json_path
, "sourced");
10784 vty_out(vty
, ", sourced");
10787 json_object_boolean_true_add(json_path
, "sourced");
10788 json_object_boolean_true_add(json_path
, "local");
10790 vty_out(vty
, ", sourced, local");
10794 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10796 json_object_boolean_true_add(json_path
,
10797 "atomicAggregate");
10799 vty_out(vty
, ", atomic-aggregate");
10802 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
10804 json_object_int_add(json_path
, "otc", attr
->otc
);
10806 vty_out(vty
, ", otc %u", attr
->otc
);
10809 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10810 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10811 && bgp_path_info_mpath_count(path
))) {
10813 json_object_boolean_true_add(json_path
, "multipath");
10815 vty_out(vty
, ", multipath");
10818 // Mark the bestpath(s)
10819 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10820 first_as
= aspath_get_first_as(attr
->aspath
);
10823 if (!json_bestpath
)
10824 json_bestpath
= json_object_new_object();
10825 json_object_int_add(json_bestpath
, "bestpathFromAs",
10829 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10831 vty_out(vty
, ", bestpath-from-AS Local");
10835 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10837 if (!json_bestpath
)
10838 json_bestpath
= json_object_new_object();
10839 json_object_boolean_true_add(json_bestpath
, "overall");
10840 json_object_string_add(
10841 json_bestpath
, "selectionReason",
10842 bgp_path_selection_reason2str(bn
->reason
));
10844 vty_out(vty
, ", best");
10845 vty_out(vty
, " (%s)",
10846 bgp_path_selection_reason2str(bn
->reason
));
10850 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10852 json_object_string_add(
10853 json_path
, "rpkiValidationState",
10854 bgp_rpki_validation2str(rpki_curr_state
));
10856 vty_out(vty
, ", rpki validation-state: %s",
10857 bgp_rpki_validation2str(rpki_curr_state
));
10861 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10864 vty_out(vty
, "\n");
10866 /* Line 4 display Community */
10867 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10869 if (!bgp_attr_get_community(attr
)->json
)
10870 community_str(bgp_attr_get_community(attr
),
10872 json_object_lock(bgp_attr_get_community(attr
)->json
);
10873 json_object_object_add(
10874 json_path
, "community",
10875 bgp_attr_get_community(attr
)->json
);
10877 vty_out(vty
, " Community: %s\n",
10878 bgp_attr_get_community(attr
)->str
);
10882 /* Line 5 display Extended-community */
10883 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10885 json_ext_community
= json_object_new_object();
10886 json_object_string_add(
10887 json_ext_community
, "string",
10888 bgp_attr_get_ecommunity(attr
)->str
);
10889 json_object_object_add(json_path
, "extendedCommunity",
10890 json_ext_community
);
10892 vty_out(vty
, " Extended Community: %s\n",
10893 bgp_attr_get_ecommunity(attr
)->str
);
10897 /* Line 6 display Large community */
10898 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10900 if (!bgp_attr_get_lcommunity(attr
)->json
)
10901 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10903 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10904 json_object_object_add(
10905 json_path
, "largeCommunity",
10906 bgp_attr_get_lcommunity(attr
)->json
);
10908 vty_out(vty
, " Large Community: %s\n",
10909 bgp_attr_get_lcommunity(attr
)->str
);
10913 /* Line 7 display Originator, Cluster-id */
10914 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10915 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10916 char buf
[BUFSIZ
] = {0};
10918 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10920 json_object_string_addf(json_path
,
10921 "originatorId", "%pI4",
10922 &attr
->originator_id
);
10924 vty_out(vty
, " Originator: %pI4",
10925 &attr
->originator_id
);
10928 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10929 struct cluster_list
*cluster
=
10930 bgp_attr_get_cluster(attr
);
10934 json_cluster_list
= json_object_new_object();
10935 json_cluster_list_list
=
10936 json_object_new_array();
10938 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10939 json_string
= json_object_new_string(
10942 buf
, sizeof(buf
)));
10943 json_object_array_add(
10944 json_cluster_list_list
,
10949 * struct cluster_list does not have
10950 * "str" variable like aspath and community
10951 * do. Add this someday if someone asks
10953 * json_object_string_add(json_cluster_list,
10954 * "string", cluster->str);
10956 json_object_object_add(json_cluster_list
,
10958 json_cluster_list_list
);
10959 json_object_object_add(json_path
, "clusterList",
10960 json_cluster_list
);
10962 vty_out(vty
, ", Cluster list: ");
10964 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10965 vty_out(vty
, "%pI4 ",
10966 &cluster
->list
[i
]);
10972 vty_out(vty
, "\n");
10975 if (path
->extra
&& path
->extra
->damp_info
)
10976 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
10979 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10980 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10981 mpls_lse_decode(path
->extra
->label
[0], &label
, &ttl
, &exp
,
10985 json_object_int_add(json_path
, "remoteLabel", label
);
10987 vty_out(vty
, " Remote label: %d\n", label
);
10991 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10993 json_object_string_addf(json_path
, "remoteSid", "%pI6",
10994 &path
->extra
->sid
[0].sid
);
10996 vty_out(vty
, " Remote SID: %pI6\n",
10997 &path
->extra
->sid
[0].sid
);
11001 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
11003 json_object_int_add(json_path
, "labelIndex",
11004 attr
->label_index
);
11006 vty_out(vty
, " Label Index: %d\n",
11007 attr
->label_index
);
11010 /* Line 8 display Addpath IDs */
11011 if (path
->addpath_rx_id
11012 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
11014 json_object_int_add(json_path
, "addpathRxId",
11015 path
->addpath_rx_id
);
11017 /* Keep backwards compatibility with the old API
11018 * by putting TX All's ID in the old field
11020 json_object_int_add(
11021 json_path
, "addpathTxId",
11023 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
11025 /* ... but create a specific field for each
11028 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
11029 json_object_int_add(
11031 bgp_addpath_names(i
)->id_json_name
,
11032 path
->tx_addpath
.addpath_tx_id
[i
]);
11035 vty_out(vty
, " AddPath ID: RX %u, ",
11036 path
->addpath_rx_id
);
11038 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
11042 /* If we used addpath to TX a non-bestpath we need to display
11043 * "Advertised to" on a path-by-path basis
11045 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11048 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11050 bgp_addpath_encode_tx(peer
, afi
, safi
);
11051 has_adj
= bgp_adj_out_lookup(
11053 bgp_addpath_id_for_peer(peer
, afi
, safi
,
11054 &path
->tx_addpath
));
11056 if ((addpath_capable
&& has_adj
)
11057 || (!addpath_capable
&& has_adj
11058 && CHECK_FLAG(path
->flags
,
11059 BGP_PATH_SELECTED
))) {
11060 if (json_path
&& !json_adv_to
)
11061 json_adv_to
= json_object_new_object();
11063 route_vty_out_advertised_to(
11065 " Advertised to:", json_adv_to
);
11071 json_object_object_add(
11072 json_path
, "advertisedTo", json_adv_to
);
11076 vty_out(vty
, "\n");
11081 /* Line 9 display Uptime */
11082 tbuf
= time(NULL
) - (monotime(NULL
) - path
->uptime
);
11084 json_last_update
= json_object_new_object();
11085 json_object_int_add(json_last_update
, "epoch", tbuf
);
11086 json_object_string_add(json_last_update
, "string",
11088 json_object_object_add(json_path
, "lastUpdate",
11091 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
11093 /* Line 10 display PMSI tunnel attribute, if present */
11094 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
11095 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
11096 bgp_attr_get_pmsi_tnl_type(attr
),
11097 PMSI_TNLTYPE_STR_DEFAULT
);
11100 json_pmsi
= json_object_new_object();
11101 json_object_string_add(json_pmsi
, "tunnelType", str
);
11102 json_object_int_add(json_pmsi
, "label",
11103 label2vni(&attr
->label
));
11104 json_object_object_add(json_path
, "pmsi", json_pmsi
);
11106 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
11107 str
, label2vni(&attr
->label
));
11110 if (path
->peer
->t_gr_restart
&&
11111 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
11112 unsigned long gr_remaining
=
11113 event_timer_remain_second(path
->peer
->t_gr_restart
);
11116 json_object_int_add(json_path
,
11117 "gracefulRestartSecondsRemaining",
11121 " Time until Graceful Restart stale route deleted: %lu\n",
11125 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
11126 bgp_attr_get_community(attr
) &&
11127 community_include(bgp_attr_get_community(attr
),
11128 COMMUNITY_LLGR_STALE
)) {
11129 unsigned long llgr_remaining
= event_timer_remain_second(
11130 path
->peer
->t_llgr_stale
[afi
][safi
]);
11133 json_object_int_add(json_path
, "llgrSecondsRemaining",
11137 " Time until Long-lived stale route deleted: %lu\n",
11141 /* Output some debug about internal state of the dest flags */
11143 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
11144 json_object_boolean_true_add(json_path
, "processScheduled");
11145 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
11146 json_object_boolean_true_add(json_path
, "userCleared");
11147 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
11148 json_object_boolean_true_add(json_path
, "labelChanged");
11149 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
11150 json_object_boolean_true_add(json_path
, "registeredForLabel");
11151 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
11152 json_object_boolean_true_add(json_path
, "selectDefered");
11153 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
11154 json_object_boolean_true_add(json_path
, "fibInstalled");
11155 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
11156 json_object_boolean_true_add(json_path
, "fibPending");
11158 if (json_nexthop_global
|| json_nexthop_ll
) {
11159 json_nexthops
= json_object_new_array();
11161 if (json_nexthop_global
)
11162 json_object_array_add(json_nexthops
,
11163 json_nexthop_global
);
11165 if (json_nexthop_ll
)
11166 json_object_array_add(json_nexthops
,
11169 json_object_object_add(json_path
, "nexthops",
11173 json_object_object_add(json_path
, "peer", json_peer
);
11174 json_object_array_add(json_paths
, json_path
);
11178 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
11179 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11180 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
11182 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11183 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11185 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11186 const char *comstr
, int exact
, afi_t afi
,
11187 safi_t safi
, uint16_t show_flags
);
11189 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11190 struct bgp_table
*table
, enum bgp_show_type type
,
11191 void *output_arg
, const char *rd
, int is_last
,
11192 unsigned long *output_cum
, unsigned long *total_cum
,
11193 unsigned long *json_header_depth
, uint16_t show_flags
,
11194 enum rpki_states rpki_target_state
)
11196 struct bgp_path_info
*pi
;
11197 struct bgp_dest
*dest
;
11198 bool header
= true;
11199 bool json_detail_header
= false;
11201 unsigned long output_count
= 0;
11202 unsigned long total_count
= 0;
11204 json_object
*json_paths
= NULL
;
11206 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11207 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11208 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11209 bool detail_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
11210 bool detail_routes
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
11212 if (output_cum
&& *output_cum
!= 0)
11215 if (use_json
&& !*json_header_depth
) {
11217 *json_header_depth
= 1;
11219 vty_out(vty
, "{\n");
11220 *json_header_depth
= 2;
11223 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11224 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
11226 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
11227 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
11230 table
->version
, &bgp
->router_id
,
11231 bgp
->default_local_pref
);
11232 if ((bgp
->asnotation
== ASNOTATION_PLAIN
) ||
11233 ((bgp
->asnotation
== ASNOTATION_DOT
) &&
11234 (bgp
->as
< UINT16_MAX
)))
11235 vty_out(vty
, "%u", bgp
->as
);
11237 vty_out(vty
, "\"");
11238 vty_out(vty
, ASN_FORMAT(bgp
->asnotation
), &bgp
->as
);
11239 vty_out(vty
, "\"");
11241 vty_out(vty
, ",\n \"routes\": { ");
11243 vty_out(vty
, " \"routeDistinguishers\" : {");
11244 ++*json_header_depth
;
11248 if (use_json
&& rd
) {
11249 vty_out(vty
, " \"%s\" : { ", rd
);
11252 /* Check for 'json detail', where we need header output once per dest */
11253 if (use_json
&& detail_json
&& type
!= bgp_show_type_dampend_paths
&&
11254 type
!= bgp_show_type_damp_neighbor
&&
11255 type
!= bgp_show_type_flap_statistics
&&
11256 type
!= bgp_show_type_flap_neighbor
)
11257 json_detail_header
= true;
11259 /* Start processing of routes. */
11260 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
11261 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11262 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11263 bool json_detail_header_used
= false;
11265 pi
= bgp_dest_get_bgp_path_info(dest
);
11271 json_paths
= json_object_new_array();
11275 for (; pi
; pi
= pi
->next
) {
11276 struct community
*picomm
= NULL
;
11278 picomm
= bgp_attr_get_community(pi
->attr
);
11282 if (type
== bgp_show_type_prefix_version
) {
11284 strtoul(output_arg
, NULL
, 10);
11285 if (dest
->version
< version
)
11289 if (type
== bgp_show_type_community_alias
) {
11290 char *alias
= output_arg
;
11291 char **communities
;
11293 bool found
= false;
11296 frrstr_split(picomm
->str
, " ",
11297 &communities
, &num
);
11298 for (int i
= 0; i
< num
; i
++) {
11299 const char *com2alias
=
11300 bgp_community2alias(
11303 && strcmp(alias
, com2alias
)
11309 XFREE(MTYPE_TMP
, communities
);
11313 bgp_attr_get_lcommunity(pi
->attr
)) {
11314 frrstr_split(bgp_attr_get_lcommunity(
11317 " ", &communities
, &num
);
11318 for (int i
= 0; i
< num
; i
++) {
11319 const char *com2alias
=
11320 bgp_community2alias(
11323 && strcmp(alias
, com2alias
)
11329 XFREE(MTYPE_TMP
, communities
);
11336 if (type
== bgp_show_type_rpki
) {
11337 if (dest_p
->family
== AF_INET
11338 || dest_p
->family
== AF_INET6
)
11339 rpki_curr_state
= hook_call(
11340 bgp_rpki_prefix_status
,
11341 pi
->peer
, pi
->attr
, dest_p
);
11342 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11343 && rpki_curr_state
!= rpki_target_state
)
11347 if (type
== bgp_show_type_flap_statistics
11348 || type
== bgp_show_type_flap_neighbor
11349 || type
== bgp_show_type_dampend_paths
11350 || type
== bgp_show_type_damp_neighbor
) {
11351 if (!(pi
->extra
&& pi
->extra
->damp_info
))
11354 if (type
== bgp_show_type_regexp
) {
11355 regex_t
*regex
= output_arg
;
11357 if (bgp_regexec(regex
, pi
->attr
->aspath
)
11361 if (type
== bgp_show_type_prefix_list
) {
11362 struct prefix_list
*plist
= output_arg
;
11364 if (prefix_list_apply(plist
, dest_p
)
11368 if (type
== bgp_show_type_access_list
) {
11369 struct access_list
*alist
= output_arg
;
11371 if (access_list_apply(alist
, dest_p
) !=
11375 if (type
== bgp_show_type_filter_list
) {
11376 struct as_list
*as_list
= output_arg
;
11378 if (as_list_apply(as_list
, pi
->attr
->aspath
)
11379 != AS_FILTER_PERMIT
)
11382 if (type
== bgp_show_type_route_map
) {
11383 struct route_map
*rmap
= output_arg
;
11384 struct bgp_path_info path
;
11385 struct bgp_path_info_extra extra
;
11386 struct attr dummy_attr
= {};
11387 route_map_result_t ret
;
11389 dummy_attr
= *pi
->attr
;
11391 prep_for_rmap_apply(&path
, &extra
, dest
, pi
,
11392 pi
->peer
, &dummy_attr
);
11394 ret
= route_map_apply(rmap
, dest_p
, &path
);
11395 bgp_attr_flush(&dummy_attr
);
11396 if (ret
== RMAP_DENYMATCH
)
11399 if (type
== bgp_show_type_neighbor
11400 || type
== bgp_show_type_flap_neighbor
11401 || type
== bgp_show_type_damp_neighbor
) {
11402 union sockunion
*su
= output_arg
;
11404 if (pi
->peer
== NULL
11405 || pi
->peer
->su_remote
== NULL
11406 || !sockunion_same(pi
->peer
->su_remote
, su
))
11409 if (type
== bgp_show_type_cidr_only
) {
11410 uint32_t destination
;
11412 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11413 if (IN_CLASSC(destination
)
11414 && dest_p
->prefixlen
== 24)
11416 if (IN_CLASSB(destination
)
11417 && dest_p
->prefixlen
== 16)
11419 if (IN_CLASSA(destination
)
11420 && dest_p
->prefixlen
== 8)
11423 if (type
== bgp_show_type_prefix_longer
) {
11425 if (!prefix_match(p
, dest_p
))
11428 if (type
== bgp_show_type_community_all
) {
11432 if (type
== bgp_show_type_community
) {
11433 struct community
*com
= output_arg
;
11435 if (!picomm
|| !community_match(picomm
, com
))
11438 if (type
== bgp_show_type_community_exact
) {
11439 struct community
*com
= output_arg
;
11441 if (!picomm
|| !community_cmp(picomm
, com
))
11444 if (type
== bgp_show_type_community_list
) {
11445 struct community_list
*list
= output_arg
;
11447 if (!community_list_match(picomm
, list
))
11450 if (type
== bgp_show_type_community_list_exact
) {
11451 struct community_list
*list
= output_arg
;
11453 if (!community_list_exact_match(picomm
, list
))
11456 if (type
== bgp_show_type_lcommunity
) {
11457 struct lcommunity
*lcom
= output_arg
;
11459 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11461 bgp_attr_get_lcommunity(pi
->attr
),
11466 if (type
== bgp_show_type_lcommunity_exact
) {
11467 struct lcommunity
*lcom
= output_arg
;
11469 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11471 bgp_attr_get_lcommunity(pi
->attr
),
11475 if (type
== bgp_show_type_lcommunity_list
) {
11476 struct community_list
*list
= output_arg
;
11478 if (!lcommunity_list_match(
11479 bgp_attr_get_lcommunity(pi
->attr
),
11484 == bgp_show_type_lcommunity_list_exact
) {
11485 struct community_list
*list
= output_arg
;
11487 if (!lcommunity_list_exact_match(
11488 bgp_attr_get_lcommunity(pi
->attr
),
11492 if (type
== bgp_show_type_lcommunity_all
) {
11493 if (!bgp_attr_get_lcommunity(pi
->attr
))
11496 if (type
== bgp_show_type_dampend_paths
11497 || type
== bgp_show_type_damp_neighbor
) {
11498 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11499 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11502 if (type
== bgp_show_type_self_originated
) {
11503 if (pi
->peer
!= bgp
->peer_self
)
11507 if (!use_json
&& header
) {
11509 "BGP table version is %" PRIu64
11510 ", local router ID is %pI4, vrf id ",
11511 table
->version
, &bgp
->router_id
);
11512 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11513 vty_out(vty
, "%s", VRFID_NONE_STR
);
11515 vty_out(vty
, "%u", bgp
->vrf_id
);
11516 vty_out(vty
, "\n");
11517 vty_out(vty
, "Default local pref %u, ",
11518 bgp
->default_local_pref
);
11519 vty_out(vty
, "local AS ");
11520 vty_out(vty
, ASN_FORMAT(bgp
->asnotation
),
11522 vty_out(vty
, "\n");
11523 if (!detail_routes
) {
11524 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11525 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11526 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11527 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11529 if (type
== bgp_show_type_dampend_paths
11530 || type
== bgp_show_type_damp_neighbor
)
11531 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11532 else if (type
== bgp_show_type_flap_statistics
11533 || type
== bgp_show_type_flap_neighbor
)
11534 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11535 else if (!detail_routes
)
11536 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11537 : BGP_SHOW_HEADER
));
11541 if (rd
!= NULL
&& !display
&& !output_count
) {
11544 "Route Distinguisher: %s\n",
11547 if (type
== bgp_show_type_dampend_paths
11548 || type
== bgp_show_type_damp_neighbor
)
11549 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11550 AFI_IP
, safi
, use_json
,
11552 else if (type
== bgp_show_type_flap_statistics
11553 || type
== bgp_show_type_flap_neighbor
)
11554 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11555 AFI_IP
, safi
, use_json
,
11558 if (detail_routes
|| detail_json
) {
11559 const struct prefix_rd
*prd
= NULL
;
11562 prd
= bgp_rd_from_dest(
11563 dest
->pdest
, safi
);
11566 route_vty_out_detail_header(
11568 bgp_dest_get_prefix(
11570 prd
, table
->afi
, safi
,
11573 route_vty_out_detail(
11574 vty
, bgp
, dest
, dest_p
, pi
,
11575 family2afi(dest_p
->family
),
11576 safi
, RPKI_NOT_BEING_USED
,
11579 route_vty_out(vty
, dest_p
, pi
, display
,
11580 safi
, json_paths
, wide
);
11591 /* encode prefix */
11592 if (dest_p
->family
== AF_FLOWSPEC
) {
11593 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11596 bgp_fs_nlri_get_string(
11598 dest_p
->u
.prefix_flowspec
.ptr
,
11599 dest_p
->u
.prefix_flowspec
.prefixlen
,
11600 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11601 family2afi(dest_p
->u
11602 .prefix_flowspec
.family
));
11604 vty_out(vty
, "\"%s/%d\": ", retstr
,
11605 dest_p
->u
.prefix_flowspec
11608 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11609 dest_p
->u
.prefix_flowspec
11613 vty_out(vty
, "\"%pFX\": ", dest_p
);
11615 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11618 /* This is used for 'json detail' vty keywords.
11620 * In plain 'json' the per-prefix header is encoded
11621 * as a standalone dictionary in the first json_paths
11623 * "<prefix>": [{header}, {path-1}, {path-N}]
11624 * (which is confusing and borderline broken)
11626 * For 'json detail' this changes the value
11627 * of each prefix-key to be a dictionary where each
11628 * header item has its own key, and json_paths is
11629 * tucked under the "paths" key:
11631 * "<header-key-1>": <header-val-1>,
11632 * "<header-key-N>": <header-val-N>,
11633 * "paths": [{path-1}, {path-N}]
11636 if (json_detail_header
&& json_paths
!= NULL
) {
11637 const struct prefix_rd
*prd
;
11639 /* Start per-prefix dictionary */
11640 vty_out(vty
, "{\n");
11642 prd
= bgp_rd_from_dest(dest
, safi
);
11644 route_vty_out_detail_header(
11646 bgp_dest_get_prefix(dest
), prd
,
11647 table
->afi
, safi
, json_paths
, true);
11649 vty_out(vty
, "\"paths\": ");
11650 json_detail_header_used
= true;
11654 * We are using no_pretty here because under
11655 * extremely high settings( say lots and lots of
11656 * routes with lots and lots of ways to reach
11657 * that route via different paths ) this can
11658 * save several minutes of output when FRR
11659 * is run on older cpu's or more underperforming
11660 * routers out there
11662 vty_json_no_pretty(vty
, json_paths
);
11664 /* End per-prefix dictionary */
11665 if (json_detail_header_used
)
11666 vty_out(vty
, "} ");
11671 json_object_free(json_paths
);
11675 output_count
+= *output_cum
;
11676 *output_cum
= output_count
;
11679 total_count
+= *total_cum
;
11680 *total_cum
= total_count
;
11684 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11688 for (i
= 0; i
< *json_header_depth
; ++i
)
11689 vty_out(vty
, " } ");
11691 vty_out(vty
, "\n");
11695 /* No route is displayed */
11696 if (output_count
== 0) {
11697 if (type
== bgp_show_type_normal
)
11699 "No BGP prefixes displayed, %ld exist\n",
11703 "\nDisplayed %ld routes and %ld total paths\n",
11704 output_count
, total_count
);
11708 return CMD_SUCCESS
;
11711 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11712 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11713 enum bgp_show_type type
, void *output_arg
,
11714 uint16_t show_flags
)
11716 struct bgp_dest
*dest
, *next
;
11717 unsigned long output_cum
= 0;
11718 unsigned long total_cum
= 0;
11719 unsigned long json_header_depth
= 0;
11720 struct bgp_table
*itable
;
11722 bool use_json
= !!CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11724 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11726 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11727 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11729 next
= bgp_route_next(dest
);
11730 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11733 itable
= bgp_dest_get_bgp_table_info(dest
);
11734 if (itable
!= NULL
) {
11735 struct prefix_rd prd
;
11736 char rd
[RD_ADDRSTRLEN
];
11738 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11739 prefix_rd2str(&prd
, rd
, sizeof(rd
), bgp
->asnotation
);
11740 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11741 rd
, next
== NULL
, &output_cum
,
11742 &total_cum
, &json_header_depth
,
11743 show_flags
, RPKI_NOT_BEING_USED
);
11749 if (output_cum
== 0)
11750 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11754 "\nDisplayed %ld routes and %ld total paths\n",
11755 output_cum
, total_cum
);
11757 if (use_json
&& output_cum
== 0)
11758 vty_out(vty
, "{}\n");
11760 return CMD_SUCCESS
;
11763 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11764 enum bgp_show_type type
, void *output_arg
,
11765 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11767 struct bgp_table
*table
;
11768 unsigned long json_header_depth
= 0;
11769 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11772 bgp
= bgp_get_default();
11777 vty_out(vty
, "No BGP process is configured\n");
11779 vty_out(vty
, "{}\n");
11780 return CMD_WARNING
;
11783 /* Labeled-unicast routes live in the unicast table. */
11784 if (safi
== SAFI_LABELED_UNICAST
)
11785 safi
= SAFI_UNICAST
;
11787 table
= bgp
->rib
[afi
][safi
];
11788 /* use MPLS and ENCAP specific shows until they are merged */
11789 if (safi
== SAFI_MPLS_VPN
) {
11790 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11791 output_arg
, show_flags
);
11794 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11795 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11796 output_arg
, use_json
,
11800 if (safi
== SAFI_EVPN
)
11801 return bgp_evpn_show_all_routes(vty
, bgp
, type
, use_json
, 0);
11803 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11804 NULL
, NULL
, &json_header_depth
, show_flags
,
11805 rpki_target_state
);
11808 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11809 safi_t safi
, uint16_t show_flags
)
11811 struct listnode
*node
, *nnode
;
11814 bool route_output
= false;
11815 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11818 vty_out(vty
, "{\n");
11820 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11821 route_output
= true;
11824 vty_out(vty
, ",\n");
11828 vty_out(vty
, "\"%s\":",
11829 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11833 vty_out(vty
, "\nInstance %s:\n",
11834 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11838 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11839 show_flags
, RPKI_NOT_BEING_USED
);
11843 vty_out(vty
, "}\n");
11844 else if (!route_output
)
11845 vty_out(vty
, "%% BGP instance not found\n");
11848 /* Header of detailed BGP route information */
11849 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11850 struct bgp_dest
*dest
, const struct prefix
*p
,
11851 const struct prefix_rd
*prd
, afi_t afi
,
11852 safi_t safi
, json_object
*json
,
11853 bool incremental_print
)
11855 struct bgp_path_info
*pi
;
11857 struct listnode
*node
, *nnode
;
11858 char buf1
[RD_ADDRSTRLEN
];
11862 int accept_own
= 0;
11863 int route_filter_translated_v4
= 0;
11864 int route_filter_v4
= 0;
11865 int route_filter_translated_v6
= 0;
11866 int route_filter_v6
= 0;
11867 int llgr_stale
= 0;
11869 int accept_own_nexthop
= 0;
11872 int no_advertise
= 0;
11876 int has_valid_label
= 0;
11877 mpls_label_t label
= 0;
11878 json_object
*json_adv_to
= NULL
;
11883 mpls_lse_decode(dest
->local_label
, &label
, &ttl
, &exp
, &bos
);
11885 has_valid_label
= bgp_is_valid_label(&label
);
11887 if (safi
== SAFI_EVPN
) {
11889 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11890 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
),
11893 prd
? ":" : "", (struct prefix_evpn
*)p
);
11895 json_object_string_add(
11897 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
),
11900 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11905 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11907 (((safi
== SAFI_MPLS_VPN
||
11908 safi
== SAFI_ENCAP
) &&
11910 ? prefix_rd2str(prd
, buf1
,
11914 safi
== SAFI_MPLS_VPN
&& prd
? ":" : "", p
,
11918 if (incremental_print
) {
11919 vty_out(vty
, "\"prefix\": \"%pFX\",\n", p
);
11920 vty_out(vty
, "\"version\": \"%" PRIu64
"\",\n",
11923 json_object_string_addf(json
, "prefix", "%pFX",
11925 json_object_int_add(json
, "version",
11931 if (has_valid_label
) {
11933 if (incremental_print
)
11934 vty_out(vty
, "\"localLabel\": \"%u\",\n",
11937 json_object_int_add(json
, "localLabel", label
);
11939 vty_out(vty
, "Local label: %d\n", label
);
11943 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11944 vty_out(vty
, "not allocated\n");
11946 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11947 struct community
*picomm
= NULL
;
11949 picomm
= bgp_attr_get_community(pi
->attr
);
11952 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11954 if (bgp_path_suppressed(pi
))
11960 no_advertise
+= community_include(
11961 picomm
, COMMUNITY_NO_ADVERTISE
);
11963 community_include(picomm
, COMMUNITY_NO_EXPORT
);
11965 community_include(picomm
, COMMUNITY_LOCAL_AS
);
11967 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
11968 route_filter_translated_v4
+= community_include(
11969 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11970 route_filter_translated_v6
+= community_include(
11971 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11972 route_filter_v4
+= community_include(
11973 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
11974 route_filter_v6
+= community_include(
11975 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
11977 community_include(picomm
, COMMUNITY_LLGR_STALE
);
11978 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
11979 accept_own_nexthop
+= community_include(
11980 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11982 community_include(picomm
, COMMUNITY_BLACKHOLE
);
11983 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
11988 vty_out(vty
, "Paths: (%d available", count
);
11990 vty_out(vty
, ", best #%d", best
);
11991 if (safi
== SAFI_UNICAST
) {
11992 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11993 vty_out(vty
, ", table %s",
11996 vty_out(vty
, ", vrf %s",
12000 vty_out(vty
, ", no best path");
12004 ", accept own local route exported and imported in different VRF");
12005 else if (route_filter_translated_v4
)
12007 ", mark translated RTs for VPNv4 route filtering");
12008 else if (route_filter_v4
)
12010 ", attach RT as-is for VPNv4 route filtering");
12011 else if (route_filter_translated_v6
)
12013 ", mark translated RTs for VPNv6 route filtering");
12014 else if (route_filter_v6
)
12016 ", attach RT as-is for VPNv6 route filtering");
12017 else if (llgr_stale
)
12019 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
12022 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
12023 else if (accept_own_nexthop
)
12025 ", accept local nexthop");
12026 else if (blackhole
)
12027 vty_out(vty
, ", inform peer to blackhole prefix");
12028 else if (no_export
)
12029 vty_out(vty
, ", not advertised to EBGP peer");
12030 else if (no_advertise
)
12031 vty_out(vty
, ", not advertised to any peer");
12033 vty_out(vty
, ", not advertised outside local AS");
12036 ", inform EBGP peer not to advertise to their EBGP peers");
12040 ", Advertisements suppressed by an aggregate.");
12041 vty_out(vty
, ")\n");
12044 /* If we are not using addpath then we can display Advertised to and
12046 * show what peers we advertised the bestpath to. If we are using
12048 * though then we must display Advertised to on a path-by-path basis. */
12049 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
12050 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
12051 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
12052 if (json
&& !json_adv_to
)
12053 json_adv_to
= json_object_new_object();
12055 route_vty_out_advertised_to(
12057 " Advertised to non peer-group peers:\n ",
12062 if (json
&& json_adv_to
) {
12063 if (incremental_print
) {
12064 vty_out(vty
, "\"advertisedTo\": ");
12065 vty_json(vty
, json_adv_to
);
12068 json_object_object_add(json
, "advertisedTo",
12071 if (!json
&& first
)
12072 vty_out(vty
, " Not advertised to any peer");
12073 vty_out(vty
, "\n");
12078 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
12079 struct bgp_dest
*bgp_node
, struct vty
*vty
,
12080 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
12081 json_object
*json
, enum bgp_path_type pathtype
,
12082 int *display
, enum rpki_states rpki_target_state
)
12084 struct bgp_path_info
*pi
;
12086 json_object
*json_header
= NULL
;
12087 json_object
*json_paths
= NULL
;
12088 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
12090 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
12091 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
12093 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
12094 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
12095 pi
->peer
, pi
->attr
, p
);
12097 if (rpki_target_state
!= RPKI_NOT_BEING_USED
12098 && rpki_curr_state
!= rpki_target_state
)
12101 if (json
&& !json_paths
) {
12102 /* Instantiate json_paths only if path is valid */
12103 json_paths
= json_object_new_array();
12105 json_header
= json_object_new_object();
12107 json_header
= json
;
12111 route_vty_out_detail_header(
12112 vty
, bgp
, bgp_node
,
12113 bgp_dest_get_prefix(bgp_node
), pfx_rd
, AFI_IP
,
12114 safi
, json_header
, false);
12119 if (pathtype
== BGP_PATH_SHOW_ALL
12120 || (pathtype
== BGP_PATH_SHOW_BESTPATH
12121 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12122 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
12123 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
12124 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
12125 route_vty_out_detail(vty
, bgp
, bgp_node
,
12126 bgp_dest_get_prefix(bgp_node
), pi
,
12127 AFI_IP
, safi
, rpki_curr_state
,
12131 if (json
&& json_paths
) {
12132 json_object_object_add(json_header
, "paths", json_paths
);
12135 json_object_object_addf(
12137 BGP_RD_AS_FORMAT(bgp
->asnotation
), pfx_rd
);
12142 * Return rd based on safi
12144 const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
12148 case SAFI_MPLS_VPN
:
12151 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
12154 case SAFI_MULTICAST
:
12155 case SAFI_LABELED_UNICAST
:
12156 case SAFI_FLOWSPEC
:
12161 assert(!"Reached end of function when we were not expecting it");
12164 /* Display specified route of BGP table. */
12165 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
12166 struct bgp_table
*rib
, const char *ip_str
,
12167 afi_t afi
, safi_t safi
,
12168 enum rpki_states rpki_target_state
,
12169 struct prefix_rd
*prd
, int prefix_check
,
12170 enum bgp_path_type pathtype
, bool use_json
)
12174 struct prefix match
;
12175 struct bgp_dest
*dest
;
12176 struct bgp_dest
*rm
;
12177 struct bgp_table
*table
;
12178 json_object
*json
= NULL
;
12179 json_object
*json_paths
= NULL
;
12181 /* Check IP address argument. */
12182 ret
= str2prefix(ip_str
, &match
);
12184 vty_out(vty
, "address is malformed\n");
12185 return CMD_WARNING
;
12188 match
.family
= afi2family(afi
);
12191 json
= json_object_new_object();
12193 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
12194 for (dest
= bgp_table_top(rib
); dest
;
12195 dest
= bgp_route_next(dest
)) {
12196 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12198 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
12200 table
= bgp_dest_get_bgp_table_info(dest
);
12204 rm
= bgp_node_match(table
, &match
);
12208 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
12210 && rm_p
->prefixlen
!= match
.prefixlen
) {
12211 bgp_dest_unlock_node(rm
);
12215 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12216 bgp
, afi
, safi
, json
, pathtype
,
12217 &display
, rpki_target_state
);
12219 bgp_dest_unlock_node(rm
);
12221 } else if (safi
== SAFI_EVPN
) {
12222 struct bgp_dest
*longest_pfx
;
12223 bool is_exact_pfxlen_match
= false;
12225 for (dest
= bgp_table_top(rib
); dest
;
12226 dest
= bgp_route_next(dest
)) {
12227 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12229 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
12231 table
= bgp_dest_get_bgp_table_info(dest
);
12235 longest_pfx
= NULL
;
12236 is_exact_pfxlen_match
= false;
12238 * Search through all the prefixes for a match. The
12239 * pfx's are enumerated in ascending order of pfxlens.
12240 * So, the last pfx match is the longest match. Set
12241 * is_exact_pfxlen_match when we get exact pfxlen match
12243 for (rm
= bgp_table_top(table
); rm
;
12244 rm
= bgp_route_next(rm
)) {
12245 const struct prefix
*rm_p
=
12246 bgp_dest_get_prefix(rm
);
12248 * Get prefixlen of the ip-prefix within type5
12251 if (evpn_type5_prefix_match(rm_p
, &match
)
12255 bgp_evpn_get_type5_prefixlen(
12257 if (type5_pfxlen
== match
.prefixlen
) {
12258 is_exact_pfxlen_match
= true;
12259 bgp_dest_unlock_node(rm
);
12268 if (prefix_check
&& !is_exact_pfxlen_match
)
12272 bgp_dest_lock_node(rm
);
12274 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12275 bgp
, afi
, safi
, json
, pathtype
,
12276 &display
, rpki_target_state
);
12278 bgp_dest_unlock_node(rm
);
12280 } else if (safi
== SAFI_FLOWSPEC
) {
12282 json_paths
= json_object_new_array();
12284 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
12285 &match
, prefix_check
,
12291 json_object_object_add(json
, "paths",
12294 json_object_free(json_paths
);
12297 dest
= bgp_node_match(rib
, &match
);
12298 if (dest
!= NULL
) {
12299 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12301 || dest_p
->prefixlen
== match
.prefixlen
) {
12302 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
12303 safi
, json
, pathtype
,
12304 &display
, rpki_target_state
);
12307 bgp_dest_unlock_node(dest
);
12312 vty_json(vty
, json
);
12315 vty_out(vty
, "%% Network not in table\n");
12316 return CMD_WARNING
;
12320 return CMD_SUCCESS
;
12323 /* Display specified route of Main RIB */
12324 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
12325 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
12326 int prefix_check
, enum bgp_path_type pathtype
,
12327 enum rpki_states rpki_target_state
, bool use_json
)
12330 bgp
= bgp_get_default();
12333 vty_out(vty
, "No BGP process is configured\n");
12335 vty_out(vty
, "{}\n");
12336 return CMD_WARNING
;
12340 /* labeled-unicast routes live in the unicast table */
12341 if (safi
== SAFI_LABELED_UNICAST
)
12342 safi
= SAFI_UNICAST
;
12344 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
12345 afi
, safi
, rpki_target_state
, prd
,
12346 prefix_check
, pathtype
, use_json
);
12349 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
12350 struct cmd_token
**argv
, bool exact
, afi_t afi
,
12351 safi_t safi
, bool uj
)
12353 struct lcommunity
*lcom
;
12358 uint16_t show_flags
= 0;
12362 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12364 b
= buffer_new(1024);
12365 for (i
= 0; i
< argc
; i
++) {
12367 buffer_putc(b
, ' ');
12369 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
12371 buffer_putstr(b
, argv
[i
]->arg
);
12375 buffer_putc(b
, '\0');
12377 str
= buffer_getstr(b
);
12380 lcom
= lcommunity_str2com(str
);
12381 XFREE(MTYPE_TMP
, str
);
12383 vty_out(vty
, "%% Large-community malformed\n");
12384 return CMD_WARNING
;
12387 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12388 (exact
? bgp_show_type_lcommunity_exact
12389 : bgp_show_type_lcommunity
),
12390 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
12392 lcommunity_free(&lcom
);
12396 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
12397 const char *lcom
, bool exact
, afi_t afi
,
12398 safi_t safi
, bool uj
)
12400 struct community_list
*list
;
12401 uint16_t show_flags
= 0;
12404 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12407 list
= community_list_lookup(bgp_clist
, lcom
, 0,
12408 LARGE_COMMUNITY_LIST_MASTER
);
12409 if (list
== NULL
) {
12410 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
12412 return CMD_WARNING
;
12415 return bgp_show(vty
, bgp
, afi
, safi
,
12416 (exact
? bgp_show_type_lcommunity_list_exact
12417 : bgp_show_type_lcommunity_list
),
12418 list
, show_flags
, RPKI_NOT_BEING_USED
);
12421 DEFUN (show_ip_bgp_large_community_list
,
12422 show_ip_bgp_large_community_list_cmd
,
12423 "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]",
12427 BGP_INSTANCE_HELP_STR
12429 BGP_SAFI_WITH_LABEL_HELP_STR
12430 "Display routes matching the large-community-list\n"
12431 "large-community-list number\n"
12432 "large-community-list name\n"
12433 "Exact match of the large-communities\n"
12436 afi_t afi
= AFI_IP6
;
12437 safi_t safi
= SAFI_UNICAST
;
12439 bool exact_match
= 0;
12440 struct bgp
*bgp
= NULL
;
12441 bool uj
= use_json(argc
, argv
);
12446 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12449 return CMD_WARNING
;
12451 argv_find(argv
, argc
, "large-community-list", &idx
);
12453 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12455 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
12458 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
12459 exact_match
, afi
, safi
, uj
);
12461 DEFUN (show_ip_bgp_large_community
,
12462 show_ip_bgp_large_community_cmd
,
12463 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
12467 BGP_INSTANCE_HELP_STR
12469 BGP_SAFI_WITH_LABEL_HELP_STR
12470 "Display routes matching the large-communities\n"
12471 "List of large-community numbers\n"
12472 "Exact match of the large-communities\n"
12475 afi_t afi
= AFI_IP6
;
12476 safi_t safi
= SAFI_UNICAST
;
12478 bool exact_match
= 0;
12479 struct bgp
*bgp
= NULL
;
12480 bool uj
= use_json(argc
, argv
);
12481 uint16_t show_flags
= 0;
12485 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12488 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12491 return CMD_WARNING
;
12493 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12494 if (argv_find(argv
, argc
, "exact-match", &idx
)) {
12498 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12499 exact_match
, afi
, safi
, uj
);
12501 return bgp_show(vty
, bgp
, afi
, safi
,
12502 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12503 RPKI_NOT_BEING_USED
);
12506 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12507 safi_t safi
, struct json_object
*json_array
);
12508 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12509 safi_t safi
, struct json_object
*json
);
12512 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12513 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12514 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12515 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12517 bool uj
= use_json(argc
, argv
);
12518 struct bgp
*bgp
= NULL
;
12519 safi_t safi
= SAFI_UNICAST
;
12520 afi_t afi
= AFI_IP6
;
12522 struct json_object
*json_all
= NULL
;
12523 struct json_object
*json_afi_safi
= NULL
;
12525 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12528 return CMD_WARNING
;
12531 json_all
= json_object_new_object();
12533 FOREACH_AFI_SAFI (afi
, safi
) {
12535 * So limit output to those afi/safi pairs that
12536 * actually have something interesting in them
12538 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12543 json_afi_safi
= json_object_new_array();
12544 json_object_object_add(
12546 get_afi_safi_str(afi
, safi
, true),
12549 json_afi_safi
= NULL
;
12552 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12556 vty_json(vty
, json_all
);
12558 return CMD_SUCCESS
;
12561 /* BGP route print out function without JSON */
12562 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12563 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12564 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12568 BGP_INSTANCE_HELP_STR
12571 "BGP RIB advertisement statistics\n"
12574 afi_t afi
= AFI_IP6
;
12575 safi_t safi
= SAFI_UNICAST
;
12576 struct bgp
*bgp
= NULL
;
12578 bool uj
= use_json(argc
, argv
);
12579 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12581 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12584 return CMD_WARNING
;
12587 json_afi_safi
= json_object_new_array();
12589 json_afi_safi
= NULL
;
12591 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12594 json
= json_object_new_object();
12595 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12597 vty_json(vty
, json
);
12602 /* BGP route print out function without JSON */
12603 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12604 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12605 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12607 statistics [json]",
12608 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12609 BGP_SAFI_WITH_LABEL_HELP_STR
12610 "BGP RIB advertisement statistics\n" JSON_STR
)
12612 afi_t afi
= AFI_IP6
;
12613 safi_t safi
= SAFI_UNICAST
;
12614 struct bgp
*bgp
= NULL
;
12616 bool uj
= use_json(argc
, argv
);
12617 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12619 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12622 return CMD_WARNING
;
12625 json_afi_safi
= json_object_new_array();
12627 json_afi_safi
= NULL
;
12629 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12632 json
= json_object_new_object();
12633 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12635 vty_json(vty
, json
);
12640 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12641 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12642 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12643 "]] [all$all] dampening parameters [json]",
12644 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12645 BGP_SAFI_WITH_LABEL_HELP_STR
12646 "Display the entries for all address families\n"
12647 "Display detailed information about dampening\n"
12648 "Display detail of configured dampening parameters\n"
12651 afi_t afi
= AFI_IP6
;
12652 safi_t safi
= SAFI_UNICAST
;
12653 struct bgp
*bgp
= NULL
;
12655 uint16_t show_flags
= 0;
12656 bool uj
= use_json(argc
, argv
);
12660 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12663 /* [<ipv4|ipv6> [all]] */
12665 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12666 if (argv_find(argv
, argc
, "ipv4", &idx
))
12667 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12669 if (argv_find(argv
, argc
, "ipv6", &idx
))
12670 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12673 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12676 return CMD_WARNING
;
12678 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12681 /* BGP route print out function */
12682 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12683 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12684 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12688 |dampening <flap-statistics|dampened-paths>\
12689 |community [AA:NN|local-AS|no-advertise|no-export\
12690 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12691 |accept-own|accept-own-nexthop|route-filter-v6\
12692 |route-filter-v4|route-filter-translated-v6\
12693 |route-filter-translated-v4] [exact-match]\
12694 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12695 |filter-list AS_PATH_FILTER_NAME\
12697 |access-list ACCESSLIST_NAME\
12698 |route-map RMAP_NAME\
12699 |rpki <invalid|valid|notfound>\
12700 |version (1-4294967295)\
12702 |A.B.C.D/M longer-prefixes\
12703 |X:X::X:X/M longer-prefixes\
12704 |"BGP_SELF_ORIG_CMD_STR
"\
12705 |detail-routes$detail_routes\
12706 ] [json$uj [detail$detail_json] | wide$wide]",
12707 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12708 BGP_SAFI_WITH_LABEL_HELP_STR
12709 "Display the entries for all address families\n"
12710 "Display only routes with non-natural netmasks\n"
12711 "Display detailed information about dampening\n"
12712 "Display flap statistics of routes\n"
12713 "Display paths suppressed due to dampening\n"
12714 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12715 "Do not send outside local AS (well-known community)\n"
12716 "Do not advertise to any peer (well-known community)\n"
12717 "Do not export to next AS (well-known community)\n"
12718 "Graceful shutdown (well-known community)\n"
12719 "Do not export to any peer (well-known community)\n"
12720 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12721 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12722 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12723 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12724 "Should accept VPN route with local nexthop (well-known community)\n"
12725 "RT VPNv6 route filtering (well-known community)\n"
12726 "RT VPNv4 route filtering (well-known community)\n"
12727 "RT translated VPNv6 route filtering (well-known community)\n"
12728 "RT translated VPNv4 route filtering (well-known community)\n"
12729 "Exact match of the communities\n"
12730 "Community-list number\n"
12731 "Community-list name\n"
12732 "Display routes matching the community-list\n"
12733 "Exact match of the communities\n"
12734 "Display routes conforming to the filter-list\n"
12735 "Regular expression access list name\n"
12736 "Display routes conforming to the prefix-list\n"
12737 "Prefix-list name\n"
12738 "Display routes conforming to the access-list\n"
12739 "Access-list name\n"
12740 "Display routes matching the route-map\n"
12741 "A route-map to match on\n"
12742 "RPKI route types\n"
12743 "A valid path as determined by rpki\n"
12744 "A invalid path as determined by rpki\n"
12745 "A path that has no rpki data\n"
12746 "Display prefixes with matching version numbers\n"
12747 "Version number and above\n"
12748 "Display prefixes with matching BGP community alias\n"
12749 "BGP community alias\n"
12751 "Display route and more specific routes\n"
12753 "Display route and more specific routes\n"
12754 BGP_SELF_ORIG_HELP_STR
12755 "Display detailed version of all routes\n"
12757 "Display detailed version of JSON output\n"
12758 "Increase table width for longer prefixes\n")
12760 afi_t afi
= AFI_IP6
;
12761 safi_t safi
= SAFI_UNICAST
;
12762 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12763 void *output_arg
= NULL
;
12764 struct bgp
*bgp
= NULL
;
12766 int exact_match
= 0;
12767 char *community
= NULL
;
12769 uint16_t show_flags
= 0;
12770 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12775 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12779 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
12782 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
12784 /* [<ipv4|ipv6> [all]] */
12786 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12788 if (argv_find(argv
, argc
, "ipv4", &idx
))
12789 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12791 if (argv_find(argv
, argc
, "ipv6", &idx
))
12792 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12796 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12798 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12801 return CMD_WARNING
;
12803 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12804 sh_type
= bgp_show_type_cidr_only
;
12806 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12807 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12808 sh_type
= bgp_show_type_dampend_paths
;
12809 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12810 sh_type
= bgp_show_type_flap_statistics
;
12813 if (argv_find(argv
, argc
, "community", &idx
)) {
12814 char *maybecomm
= NULL
;
12816 if (idx
+ 1 < argc
) {
12817 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12818 maybecomm
= argv
[idx
+ 1]->arg
;
12820 maybecomm
= argv
[idx
+ 1]->text
;
12823 if (maybecomm
&& !strmatch(maybecomm
, "json")
12824 && !strmatch(maybecomm
, "exact-match"))
12825 community
= maybecomm
;
12827 if (argv_find(argv
, argc
, "exact-match", &idx
))
12831 sh_type
= bgp_show_type_community_all
;
12834 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12835 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12836 struct community_list
*list
;
12838 if (argv_find(argv
, argc
, "exact-match", &idx
))
12841 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12842 COMMUNITY_LIST_MASTER
);
12843 if (list
== NULL
) {
12844 vty_out(vty
, "%% %s community-list not found\n",
12845 clist_number_or_name
);
12846 return CMD_WARNING
;
12850 sh_type
= bgp_show_type_community_list_exact
;
12852 sh_type
= bgp_show_type_community_list
;
12856 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12857 const char *filter
= argv
[++idx
]->arg
;
12858 struct as_list
*as_list
;
12860 as_list
= as_list_lookup(filter
);
12861 if (as_list
== NULL
) {
12862 vty_out(vty
, "%% %s AS-path access-list not found\n",
12864 return CMD_WARNING
;
12867 sh_type
= bgp_show_type_filter_list
;
12868 output_arg
= as_list
;
12871 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12872 const char *prefix_list_str
= argv
[++idx
]->arg
;
12873 struct prefix_list
*plist
;
12875 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12876 if (plist
== NULL
) {
12877 vty_out(vty
, "%% %s prefix-list not found\n",
12879 return CMD_WARNING
;
12882 sh_type
= bgp_show_type_prefix_list
;
12883 output_arg
= plist
;
12886 if (argv_find(argv
, argc
, "access-list", &idx
)) {
12887 const char *access_list_str
= argv
[++idx
]->arg
;
12888 struct access_list
*alist
;
12890 alist
= access_list_lookup(afi
, access_list_str
);
12892 vty_out(vty
, "%% %s access-list not found\n",
12894 return CMD_WARNING
;
12897 sh_type
= bgp_show_type_access_list
;
12898 output_arg
= alist
;
12901 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12902 const char *rmap_str
= argv
[++idx
]->arg
;
12903 struct route_map
*rmap
;
12905 rmap
= route_map_lookup_by_name(rmap_str
);
12907 vty_out(vty
, "%% %s route-map not found\n", rmap_str
);
12908 return CMD_WARNING
;
12911 sh_type
= bgp_show_type_route_map
;
12915 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12916 sh_type
= bgp_show_type_rpki
;
12917 if (argv_find(argv
, argc
, "valid", &idx
))
12918 rpki_target_state
= RPKI_VALID
;
12919 else if (argv_find(argv
, argc
, "invalid", &idx
))
12920 rpki_target_state
= RPKI_INVALID
;
12923 /* Display prefixes with matching version numbers */
12924 if (argv_find(argv
, argc
, "version", &idx
)) {
12925 sh_type
= bgp_show_type_prefix_version
;
12926 output_arg
= argv
[idx
+ 1]->arg
;
12929 /* Display prefixes with matching BGP community alias */
12930 if (argv_find(argv
, argc
, "alias", &idx
)) {
12931 sh_type
= bgp_show_type_community_alias
;
12932 output_arg
= argv
[idx
+ 1]->arg
;
12935 /* prefix-longer */
12936 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12937 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12938 const char *prefix_str
= argv
[idx
]->arg
;
12940 if (!str2prefix(prefix_str
, &p
)) {
12941 vty_out(vty
, "%% Malformed Prefix\n");
12942 return CMD_WARNING
;
12945 sh_type
= bgp_show_type_prefix_longer
;
12949 /* self originated only */
12950 if (argv_find(argv
, argc
, BGP_SELF_ORIG_CMD_STR
, &idx
))
12951 sh_type
= bgp_show_type_self_originated
;
12954 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12956 return bgp_show_community(vty
, bgp
, community
,
12957 exact_match
, afi
, safi
,
12960 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12961 output_arg
, show_flags
,
12962 rpki_target_state
);
12964 struct listnode
*node
;
12966 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12970 vty_out(vty
, "{\n");
12972 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12973 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12974 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12977 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12978 FOREACH_SAFI (safi
) {
12979 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12987 vty_out(vty
, ",\n");
12988 vty_out(vty
, "\"%s\":{\n",
12989 get_afi_safi_str(afi
,
12994 "\nFor address family: %s\n",
13000 bgp_show_community(
13001 vty
, abgp
, community
,
13002 exact_match
, afi
, safi
,
13005 bgp_show(vty
, abgp
, afi
, safi
,
13006 sh_type
, output_arg
,
13008 rpki_target_state
);
13010 vty_out(vty
, "}\n");
13014 /* show <ip> bgp all: for each AFI and SAFI*/
13015 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
13016 FOREACH_AFI_SAFI (afi
, safi
) {
13017 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
13025 vty_out(vty
, ",\n");
13027 vty_out(vty
, "\"%s\":{\n",
13028 get_afi_safi_str(afi
,
13033 "\nFor address family: %s\n",
13039 bgp_show_community(
13040 vty
, abgp
, community
,
13041 exact_match
, afi
, safi
,
13044 bgp_show(vty
, abgp
, afi
, safi
,
13045 sh_type
, output_arg
,
13047 rpki_target_state
);
13049 vty_out(vty
, "}\n");
13054 vty_out(vty
, "}\n");
13056 return CMD_SUCCESS
;
13059 DEFUN (show_ip_bgp_route
,
13060 show_ip_bgp_route_cmd
,
13061 "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]",
13065 BGP_INSTANCE_HELP_STR
13067 BGP_SAFI_WITH_LABEL_HELP_STR
13068 "Network in the BGP routing table to display\n"
13070 "Network in the BGP routing table to display\n"
13072 "Display only the bestpath\n"
13073 "Display only multipaths\n"
13074 "Display only paths that match the specified rpki state\n"
13075 "A valid path as determined by rpki\n"
13076 "A invalid path as determined by rpki\n"
13077 "A path that has no rpki data\n"
13080 int prefix_check
= 0;
13082 afi_t afi
= AFI_IP6
;
13083 safi_t safi
= SAFI_UNICAST
;
13084 char *prefix
= NULL
;
13085 struct bgp
*bgp
= NULL
;
13086 enum bgp_path_type path_type
;
13087 bool uj
= use_json(argc
, argv
);
13091 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13094 return CMD_WARNING
;
13098 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13099 return CMD_WARNING
;
13102 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13103 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
13104 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
13106 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
13107 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
13110 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
13111 && afi
!= AFI_IP6
) {
13113 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13114 return CMD_WARNING
;
13116 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
13117 && afi
!= AFI_IP
) {
13119 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13120 return CMD_WARNING
;
13123 prefix
= argv
[idx
]->arg
;
13125 /* [<bestpath|multipath>] */
13126 if (argv_find(argv
, argc
, "bestpath", &idx
))
13127 path_type
= BGP_PATH_SHOW_BESTPATH
;
13128 else if (argv_find(argv
, argc
, "multipath", &idx
))
13129 path_type
= BGP_PATH_SHOW_MULTIPATH
;
13131 path_type
= BGP_PATH_SHOW_ALL
;
13133 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
13134 path_type
, RPKI_NOT_BEING_USED
, uj
);
13137 DEFUN (show_ip_bgp_regexp
,
13138 show_ip_bgp_regexp_cmd
,
13139 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
13143 BGP_INSTANCE_HELP_STR
13145 BGP_SAFI_WITH_LABEL_HELP_STR
13146 "Display routes matching the AS path regular expression\n"
13147 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13150 afi_t afi
= AFI_IP6
;
13151 safi_t safi
= SAFI_UNICAST
;
13152 struct bgp
*bgp
= NULL
;
13153 bool uj
= use_json(argc
, argv
);
13154 char *regstr
= NULL
;
13157 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13160 return CMD_WARNING
;
13162 // get index of regex
13163 if (argv_find(argv
, argc
, "REGEX", &idx
))
13164 regstr
= argv
[idx
]->arg
;
13167 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
13168 bgp_show_type_regexp
, uj
);
13171 DEFPY (show_ip_bgp_instance_all
,
13172 show_ip_bgp_instance_all_cmd
,
13173 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
13177 BGP_INSTANCE_ALL_HELP_STR
13179 BGP_SAFI_WITH_LABEL_HELP_STR
13181 "Increase table width for longer prefixes\n")
13183 afi_t afi
= AFI_IP6
;
13184 safi_t safi
= SAFI_UNICAST
;
13185 struct bgp
*bgp
= NULL
;
13187 uint16_t show_flags
= 0;
13191 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13195 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13197 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13200 return CMD_WARNING
;
13202 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
13203 return CMD_SUCCESS
;
13206 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
13207 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
13212 uint16_t show_flags
= 0;
13215 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13217 if (!config_bgp_aspath_validate(regstr
)) {
13218 vty_out(vty
, "Invalid character in REGEX %s\n",
13220 return CMD_WARNING_CONFIG_FAILED
;
13223 regex
= bgp_regcomp(regstr
);
13225 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
13226 return CMD_WARNING
;
13229 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
13230 RPKI_NOT_BEING_USED
);
13231 bgp_regex_free(regex
);
13235 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
13236 const char *comstr
, int exact
, afi_t afi
,
13237 safi_t safi
, uint16_t show_flags
)
13239 struct community
*com
;
13242 com
= community_str2com(comstr
);
13244 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
13245 return CMD_WARNING
;
13248 ret
= bgp_show(vty
, bgp
, afi
, safi
,
13249 (exact
? bgp_show_type_community_exact
13250 : bgp_show_type_community
),
13251 com
, show_flags
, RPKI_NOT_BEING_USED
);
13252 community_free(&com
);
13258 BGP_STATS_MAXBITLEN
= 0,
13260 BGP_STATS_PREFIXES
,
13262 BGP_STATS_UNAGGREGATEABLE
,
13263 BGP_STATS_MAX_AGGREGATEABLE
,
13264 BGP_STATS_AGGREGATES
,
13266 BGP_STATS_ASPATH_COUNT
,
13267 BGP_STATS_ASPATH_MAXHOPS
,
13268 BGP_STATS_ASPATH_TOTHOPS
,
13269 BGP_STATS_ASPATH_MAXSIZE
,
13270 BGP_STATS_ASPATH_TOTSIZE
,
13271 BGP_STATS_ASN_HIGHEST
,
13275 #define TABLE_STATS_IDX_VTY 0
13276 #define TABLE_STATS_IDX_JSON 1
13278 static const char *table_stats_strs
[][2] = {
13279 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
13280 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
13281 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
13282 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
13283 "unaggregateablePrefixes"},
13284 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
13285 "maximumAggregateablePrefixes"},
13286 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
13287 "bgpAggregateAdvertisements"},
13288 [BGP_STATS_SPACE
] = {"Address space advertised",
13289 "addressSpaceAdvertised"},
13290 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
13291 "advertisementsWithPaths"},
13292 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
13294 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
13296 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
13297 "averageAsPathLengthHops"},
13298 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
13299 "averageAsPathSizeBytes"},
13300 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
13301 [BGP_STATS_MAX
] = {NULL
, NULL
}
13304 struct bgp_table_stats
{
13305 struct bgp_table
*table
;
13306 unsigned long long counts
[BGP_STATS_MAX
];
13309 prefix_len_count
[MAX(EVPN_ROUTE_PREFIXLEN
, IPV6_MAX_BITLEN
) +
13312 double total_space
;
13315 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
13316 struct bgp_table_stats
*ts
, unsigned int space
)
13318 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
13319 struct bgp_path_info
*pi
;
13320 const struct prefix
*rn_p
;
13322 if (!bgp_dest_has_bgp_path_info_data(dest
))
13325 rn_p
= bgp_dest_get_prefix(dest
);
13326 ts
->counts
[BGP_STATS_PREFIXES
]++;
13327 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
13329 ts
->prefix_len_count
[rn_p
->prefixlen
]++;
13330 /* check if the prefix is included by any other announcements */
13331 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
13332 pdest
= bgp_dest_parent_nolock(pdest
);
13334 if (pdest
== NULL
|| pdest
== top
) {
13335 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
13336 /* announced address space */
13338 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
13339 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
13340 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
13343 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
13344 ts
->counts
[BGP_STATS_RIB
]++;
13346 if (CHECK_FLAG(pi
->attr
->flag
,
13347 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
13348 ts
->counts
[BGP_STATS_AGGREGATES
]++;
13350 /* as-path stats */
13351 if (pi
->attr
->aspath
) {
13352 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
13353 unsigned int size
= aspath_size(pi
->attr
->aspath
);
13354 as_t highest
= aspath_highest(pi
->attr
->aspath
);
13356 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
13358 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
13359 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
13361 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
13362 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
13364 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
13365 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
13366 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
13367 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
13372 static void bgp_table_stats_walker(struct event
*t
)
13374 struct bgp_dest
*dest
, *ndest
;
13375 struct bgp_dest
*top
;
13376 struct bgp_table_stats
*ts
= EVENT_ARG(t
);
13377 unsigned int space
= 0;
13379 if (!(top
= bgp_table_top(ts
->table
)))
13382 switch (ts
->table
->afi
) {
13384 space
= IPV4_MAX_BITLEN
;
13387 space
= IPV6_MAX_BITLEN
;
13390 space
= EVPN_ROUTE_PREFIXLEN
;
13397 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
13399 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
13400 if (ts
->table
->safi
== SAFI_MPLS_VPN
13401 || ts
->table
->safi
== SAFI_ENCAP
13402 || ts
->table
->safi
== SAFI_EVPN
) {
13403 struct bgp_table
*table
;
13405 table
= bgp_dest_get_bgp_table_info(dest
);
13409 top
= bgp_table_top(table
);
13410 for (ndest
= bgp_table_top(table
); ndest
;
13411 ndest
= bgp_route_next(ndest
))
13412 bgp_table_stats_rn(ndest
, top
, ts
, space
);
13414 bgp_table_stats_rn(dest
, top
, ts
, space
);
13419 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
13420 struct json_object
*json_array
)
13422 struct listnode
*node
, *nnode
;
13425 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
13426 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13429 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13430 safi_t safi
, struct json_object
*json_array
)
13432 struct bgp_table_stats ts
;
13434 int ret
= CMD_SUCCESS
;
13436 struct json_object
*json
= NULL
;
13437 uint32_t bitlen
= 0;
13438 struct json_object
*json_bitlen
;
13441 json
= json_object_new_object();
13443 if (!bgp
->rib
[afi
][safi
]) {
13444 char warning_msg
[50];
13446 snprintf(warning_msg
, sizeof(warning_msg
),
13447 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
13451 vty_out(vty
, "%s\n", warning_msg
);
13453 json_object_string_add(json
, "warning", warning_msg
);
13456 goto end_table_stats
;
13460 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
13461 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
13463 json_object_string_add(json
, "instance", bgp
->name_pretty
);
13465 /* labeled-unicast routes live in the unicast table */
13466 if (safi
== SAFI_LABELED_UNICAST
)
13467 safi
= SAFI_UNICAST
;
13469 memset(&ts
, 0, sizeof(ts
));
13470 ts
.table
= bgp
->rib
[afi
][safi
];
13471 event_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
13473 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
13474 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
13475 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
13479 case BGP_STATS_ASPATH_TOTHOPS
:
13480 case BGP_STATS_ASPATH_TOTSIZE
:
13483 temp_buf
, sizeof(temp_buf
), "%12.2f",
13485 ? (float)ts
.counts
[i
]
13487 [BGP_STATS_ASPATH_COUNT
]
13489 vty_out(vty
, "%-30s: %s",
13490 table_stats_strs
[i
]
13491 [TABLE_STATS_IDX_VTY
],
13494 json_object_double_add(
13496 table_stats_strs
[i
]
13497 [TABLE_STATS_IDX_JSON
],
13499 ? (double)ts
.counts
[i
]
13500 / (double)ts
.counts
13501 [BGP_STATS_ASPATH_COUNT
]
13505 case BGP_STATS_TOTPLEN
:
13508 temp_buf
, sizeof(temp_buf
), "%12.2f",
13510 ? (float)ts
.counts
[i
]
13512 [BGP_STATS_PREFIXES
]
13514 vty_out(vty
, "%-30s: %s",
13515 table_stats_strs
[i
]
13516 [TABLE_STATS_IDX_VTY
],
13519 json_object_double_add(
13521 table_stats_strs
[i
]
13522 [TABLE_STATS_IDX_JSON
],
13524 ? (double)ts
.counts
[i
]
13525 / (double)ts
.counts
13526 [BGP_STATS_PREFIXES
]
13530 case BGP_STATS_SPACE
:
13532 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13534 vty_out(vty
, "%-30s: %s\n",
13535 table_stats_strs
[i
]
13536 [TABLE_STATS_IDX_VTY
],
13539 json_object_double_add(
13541 table_stats_strs
[i
]
13542 [TABLE_STATS_IDX_JSON
],
13543 (double)ts
.total_space
);
13545 if (afi
== AFI_IP6
) {
13547 snprintf(temp_buf
, sizeof(temp_buf
),
13550 * pow(2.0, -128 + 32));
13551 vty_out(vty
, "%30s: %s\n",
13552 "/32 equivalent %s\n",
13555 json_object_double_add(
13556 json
, "/32equivalent",
13557 (double)(ts
.total_space
13562 snprintf(temp_buf
, sizeof(temp_buf
),
13565 * pow(2.0, -128 + 48));
13566 vty_out(vty
, "%30s: %s\n",
13567 "/48 equivalent %s\n",
13570 json_object_double_add(
13571 json
, "/48equivalent",
13572 (double)(ts
.total_space
13578 snprintf(temp_buf
, sizeof(temp_buf
),
13580 ts
.total_space
* 100.
13582 vty_out(vty
, "%30s: %s\n",
13583 "% announced ", temp_buf
);
13585 json_object_double_add(
13586 json
, "%announced",
13587 (double)(ts
.total_space
* 100.
13591 snprintf(temp_buf
, sizeof(temp_buf
),
13594 * pow(2.0, -32 + 8));
13595 vty_out(vty
, "%30s: %s\n",
13596 "/8 equivalent ", temp_buf
);
13598 json_object_double_add(
13599 json
, "/8equivalent",
13600 (double)(ts
.total_space
13601 * pow(2.0, -32 + 8)));
13604 snprintf(temp_buf
, sizeof(temp_buf
),
13607 * pow(2.0, -32 + 24));
13608 vty_out(vty
, "%30s: %s\n",
13609 "/24 equivalent ", temp_buf
);
13611 json_object_double_add(
13612 json
, "/24equivalent",
13613 (double)(ts
.total_space
13614 * pow(2.0, -32 + 24)));
13620 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13622 vty_out(vty
, "%-30s: %s",
13623 table_stats_strs
[i
]
13624 [TABLE_STATS_IDX_VTY
],
13627 json_object_int_add(
13629 table_stats_strs
[i
]
13630 [TABLE_STATS_IDX_JSON
],
13635 vty_out(vty
, "\n");
13640 bitlen
= IPV4_MAX_BITLEN
;
13643 bitlen
= IPV6_MAX_BITLEN
;
13646 bitlen
= EVPN_ROUTE_PREFIXLEN
;
13654 json_bitlen
= json_object_new_array();
13656 for (i
= 0; i
<= bitlen
; i
++) {
13657 struct json_object
*ind_bit
= json_object_new_object();
13659 if (!ts
.prefix_len_count
[i
])
13662 snprintf(temp_buf
, sizeof(temp_buf
), "%u", i
);
13663 json_object_int_add(ind_bit
, temp_buf
,
13664 ts
.prefix_len_count
[i
]);
13665 json_object_array_add(json_bitlen
, ind_bit
);
13667 json_object_object_add(json
, "prefixLength", json_bitlen
);
13672 json_object_array_add(json_array
, json
);
13676 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13677 safi_t safi
, struct json_object
*json_array
)
13680 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13681 return CMD_SUCCESS
;
13684 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13696 PCOUNT_BPATH_SELECTED
,
13697 PCOUNT_PFCNT
, /* the figure we display to users */
13701 static const char *const pcount_strs
[] = {
13702 [PCOUNT_ADJ_IN
] = "Adj-in",
13703 [PCOUNT_DAMPED
] = "Damped",
13704 [PCOUNT_REMOVED
] = "Removed",
13705 [PCOUNT_HISTORY
] = "History",
13706 [PCOUNT_STALE
] = "Stale",
13707 [PCOUNT_VALID
] = "Valid",
13708 [PCOUNT_ALL
] = "All RIB",
13709 [PCOUNT_COUNTED
] = "PfxCt counted",
13710 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13711 [PCOUNT_PFCNT
] = "Useable",
13712 [PCOUNT_MAX
] = NULL
,
13715 struct peer_pcounts
{
13716 unsigned int count
[PCOUNT_MAX
];
13717 const struct peer
*peer
;
13718 const struct bgp_table
*table
;
13722 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13724 const struct bgp_adj_in
*ain
;
13725 const struct bgp_path_info
*pi
;
13726 const struct peer
*peer
= pc
->peer
;
13728 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13729 if (ain
->peer
== peer
)
13730 pc
->count
[PCOUNT_ADJ_IN
]++;
13732 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13734 if (pi
->peer
!= peer
)
13737 pc
->count
[PCOUNT_ALL
]++;
13739 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13740 pc
->count
[PCOUNT_DAMPED
]++;
13741 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13742 pc
->count
[PCOUNT_HISTORY
]++;
13743 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13744 pc
->count
[PCOUNT_REMOVED
]++;
13745 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13746 pc
->count
[PCOUNT_STALE
]++;
13747 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13748 pc
->count
[PCOUNT_VALID
]++;
13749 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13750 pc
->count
[PCOUNT_PFCNT
]++;
13751 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13752 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13754 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13755 pc
->count
[PCOUNT_COUNTED
]++;
13756 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13758 EC_LIB_DEVELOPMENT
,
13759 "Attempting to count but flags say it is unusable");
13761 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13763 EC_LIB_DEVELOPMENT
,
13764 "Not counted but flags say we should");
13769 static void bgp_peer_count_walker(struct event
*t
)
13771 struct bgp_dest
*rn
, *rm
;
13772 const struct bgp_table
*table
;
13773 struct peer_pcounts
*pc
= EVENT_ARG(t
);
13775 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13776 || pc
->safi
== SAFI_EVPN
) {
13777 /* Special handling for 2-level routing tables. */
13778 for (rn
= bgp_table_top(pc
->table
); rn
;
13779 rn
= bgp_route_next(rn
)) {
13780 table
= bgp_dest_get_bgp_table_info(rn
);
13782 for (rm
= bgp_table_top(table
); rm
;
13783 rm
= bgp_route_next(rm
))
13784 bgp_peer_count_proc(rm
, pc
);
13787 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13788 bgp_peer_count_proc(rn
, pc
);
13791 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13792 safi_t safi
, bool use_json
)
13794 struct peer_pcounts pcounts
= {.peer
= peer
};
13796 json_object
*json
= NULL
;
13797 json_object
*json_loop
= NULL
;
13800 json
= json_object_new_object();
13801 json_loop
= json_object_new_object();
13804 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13805 || !peer
->bgp
->rib
[afi
][safi
]) {
13807 json_object_string_add(
13809 "No such neighbor or address family");
13810 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13811 json_object_free(json
);
13812 json_object_free(json_loop
);
13814 vty_out(vty
, "%% No such neighbor or address family\n");
13816 return CMD_WARNING
;
13819 memset(&pcounts
, 0, sizeof(pcounts
));
13820 pcounts
.peer
= peer
;
13821 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13822 pcounts
.safi
= safi
;
13824 /* in-place call via thread subsystem so as to record execution time
13825 * stats for the thread-walk (i.e. ensure this can't be blamed on
13826 * on just vty_read()).
13828 event_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13831 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13832 json_object_string_add(json
, "multiProtocol",
13833 get_afi_safi_str(afi
, safi
, true));
13834 json_object_int_add(json
, "pfxCounter",
13835 peer
->pcount
[afi
][safi
]);
13837 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13838 json_object_int_add(json_loop
, pcount_strs
[i
],
13841 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13843 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13844 json_object_string_add(json
, "pfxctDriftFor",
13846 json_object_string_add(
13847 json
, "recommended",
13848 "Please report this bug, with the above command output");
13850 vty_json(vty
, json
);
13854 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13855 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13856 peer
->hostname
, peer
->host
,
13857 get_afi_safi_str(afi
, safi
, false));
13859 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13860 get_afi_safi_str(afi
, safi
, false));
13863 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13864 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13866 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13867 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13870 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13871 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13873 "Please report this bug, with the above command output\n");
13877 return CMD_SUCCESS
;
13880 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13881 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13882 "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]",
13886 BGP_INSTANCE_HELP_STR
13889 "Detailed information on TCP and BGP neighbor connections\n"
13890 "Neighbor to display information about\n"
13891 "Neighbor to display information about\n"
13892 "Neighbor on BGP configured interface\n"
13893 "Display detailed prefix count information\n"
13896 afi_t afi
= AFI_IP6
;
13897 safi_t safi
= SAFI_UNICAST
;
13900 struct bgp
*bgp
= NULL
;
13901 bool uj
= use_json(argc
, argv
);
13906 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13909 return CMD_WARNING
;
13911 argv_find(argv
, argc
, "neighbors", &idx
);
13912 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13914 return CMD_WARNING
;
13916 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13919 #ifdef KEEP_OLD_VPN_COMMANDS
13920 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13921 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13922 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13927 "Display information about all VPNv4 NLRIs\n"
13928 "Detailed information on TCP and BGP neighbor connections\n"
13929 "Neighbor to display information about\n"
13930 "Neighbor to display information about\n"
13931 "Neighbor on BGP configured interface\n"
13932 "Display detailed prefix count information\n"
13937 bool uj
= use_json(argc
, argv
);
13939 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13941 return CMD_WARNING
;
13943 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13946 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13947 show_ip_bgp_vpn_all_route_prefix_cmd
,
13948 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13953 "Display information about all VPNv4 NLRIs\n"
13954 "Network in the BGP routing table to display\n"
13955 "Network in the BGP routing table to display\n"
13959 char *network
= NULL
;
13960 struct bgp
*bgp
= bgp_get_default();
13962 vty_out(vty
, "Can't find default instance\n");
13963 return CMD_WARNING
;
13966 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13967 network
= argv
[idx
]->arg
;
13968 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13969 network
= argv
[idx
]->arg
;
13971 vty_out(vty
, "Unable to figure out Network\n");
13972 return CMD_WARNING
;
13975 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13976 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13977 use_json(argc
, argv
));
13979 #endif /* KEEP_OLD_VPN_COMMANDS */
13981 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13982 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13983 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13988 "Network in the BGP routing table to display\n"
13989 "Network in the BGP routing table to display\n"
13990 "Network in the BGP routing table to display\n"
13991 "Network in the BGP routing table to display\n"
13995 char *network
= NULL
;
13996 int prefix_check
= 0;
13998 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13999 argv_find(argv
, argc
, "X:X::X:X", &idx
))
14000 network
= argv
[idx
]->arg
;
14001 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
14002 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
14003 network
= argv
[idx
]->arg
;
14006 vty_out(vty
, "Unable to figure out Network\n");
14007 return CMD_WARNING
;
14009 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
14010 prefix_check
, BGP_PATH_SHOW_ALL
,
14011 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
14014 static void show_adj_route_header(struct vty
*vty
, struct peer
*peer
,
14015 struct bgp_table
*table
, int *header1
,
14016 int *header2
, json_object
*json
,
14017 json_object
*json_scode
,
14018 json_object
*json_ocode
, bool wide
,
14021 uint64_t version
= table
? table
->version
: 0;
14025 json_object_int_add(json
, "bgpTableVersion", version
);
14026 json_object_string_addf(json
, "bgpLocalRouterId",
14027 "%pI4", &peer
->bgp
->router_id
);
14028 json_object_int_add(json
, "defaultLocPrf",
14029 peer
->bgp
->default_local_pref
);
14030 json_object_int_add(json
, "localAS",
14031 peer
->change_local_as
14032 ? peer
->change_local_as
14034 json_object_object_add(json
, "bgpStatusCodes",
14036 json_object_object_add(json
, "bgpOriginCodes",
14040 "BGP table version is %" PRIu64
14041 ", local router ID is %pI4, vrf id ",
14042 version
, &peer
->bgp
->router_id
);
14043 if (peer
->bgp
->vrf_id
== VRF_UNKNOWN
)
14044 vty_out(vty
, "%s", VRFID_NONE_STR
);
14046 vty_out(vty
, "%u", peer
->bgp
->vrf_id
);
14047 vty_out(vty
, "\n");
14048 vty_out(vty
, "Default local pref %u, ",
14049 peer
->bgp
->default_local_pref
);
14050 vty_out(vty
, "local AS %u\n",
14051 peer
->change_local_as
? peer
->change_local_as
14054 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14055 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14056 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14057 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14063 if (!json
&& !detail
)
14064 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
14065 : BGP_SHOW_HEADER
));
14071 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
14072 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
14073 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
14074 json_object
*json_scode
, json_object
*json_ocode
,
14075 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
14076 const struct prefix
*match
, unsigned long *output_count
,
14077 unsigned long *filtered_count
)
14079 struct bgp_adj_in
*ain
= NULL
;
14080 struct bgp_adj_out
*adj
= NULL
;
14081 struct bgp_dest
*dest
;
14085 struct update_subgroup
*subgrp
;
14086 struct peer_af
*paf
= NULL
;
14087 bool route_filtered
;
14088 bool detail
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14089 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14090 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14091 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14092 || (safi
== SAFI_EVPN
))
14096 json_object
*json_net
= NULL
;
14100 /* If the user supplied a prefix, look for a matching route instead
14101 * of walking the whole table.
14104 dest
= bgp_node_match(table
, match
);
14107 vty_out(vty
, "Network not in table\n");
14111 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
14113 if (rn_p
->prefixlen
!= match
->prefixlen
) {
14115 vty_out(vty
, "Network not in table\n");
14116 bgp_dest_unlock_node(dest
);
14120 if (type
== bgp_show_adj_route_received
||
14121 type
== bgp_show_adj_route_filtered
) {
14122 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14123 if (ain
->peer
== peer
) {
14128 /* bail out if if adj_out is empty, or
14129 * if the prefix isn't in this peer's
14132 if (!ain
|| ain
->peer
!= peer
) {
14134 vty_out(vty
, "Network not in table\n");
14135 bgp_dest_unlock_node(dest
);
14138 } else if (type
== bgp_show_adj_route_advertised
) {
14139 bool peer_found
= false;
14141 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
) {
14142 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14143 if (paf
->peer
== peer
&& adj
->attr
) {
14152 /* bail out if if adj_out is empty, or
14153 * if the prefix isn't in this peer's
14156 if (!paf
|| !peer_found
) {
14158 vty_out(vty
, "Network not in table\n");
14159 bgp_dest_unlock_node(dest
);
14164 ret
= bgp_output_modifier(peer
, rn_p
, &attr
, afi
, safi
,
14167 if (ret
!= RMAP_DENY
) {
14168 show_adj_route_header(vty
, peer
, table
, header1
,
14169 header2
, json
, json_scode
,
14170 json_ocode
, wide
, detail
);
14173 json_net
= json_object_new_object();
14175 bgp_show_path_info(NULL
/* prefix_rd */, dest
, vty
, bgp
,
14176 afi
, safi
, json_net
,
14177 BGP_PATH_SHOW_ALL
, &display
,
14178 RPKI_NOT_BEING_USED
);
14180 json_object_object_addf(json_ar
, json_net
,
14184 (*filtered_count
)++;
14186 bgp_attr_flush(&attr
);
14187 bgp_dest_unlock_node(dest
);
14192 subgrp
= peer_subgroup(peer
, afi
, safi
);
14194 if (type
== bgp_show_adj_route_advertised
&& subgrp
14195 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
14197 json_object_int_add(json
, "bgpTableVersion",
14199 json_object_string_addf(json
, "bgpLocalRouterId",
14200 "%pI4", &bgp
->router_id
);
14201 json_object_int_add(json
, "defaultLocPrf",
14202 bgp
->default_local_pref
);
14203 json_object_int_add(json
, "localAS",
14204 peer
->change_local_as
14205 ? peer
->change_local_as
14207 json_object_object_add(json
, "bgpStatusCodes",
14209 json_object_object_add(json
, "bgpOriginCodes",
14211 json_object_string_add(
14212 json
, "bgpOriginatingDefaultNetwork",
14213 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14216 "BGP table version is %" PRIu64
14217 ", local router ID is %pI4, vrf id ",
14218 table
->version
, &bgp
->router_id
);
14219 if (bgp
->vrf_id
== VRF_UNKNOWN
)
14220 vty_out(vty
, "%s", VRFID_NONE_STR
);
14222 vty_out(vty
, "%u", bgp
->vrf_id
);
14223 vty_out(vty
, "\n");
14224 vty_out(vty
, "Default local pref %u, ",
14225 bgp
->default_local_pref
);
14226 vty_out(vty
, "local AS %u\n",
14227 peer
->change_local_as
? peer
->change_local_as
14230 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14231 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14232 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14233 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14236 vty_out(vty
, "Originating default network %s\n\n",
14237 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14243 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
14244 if (type
== bgp_show_adj_route_received
14245 || type
== bgp_show_adj_route_filtered
) {
14246 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14247 if (ain
->peer
!= peer
)
14250 show_adj_route_header(vty
, peer
, table
, header1
,
14251 header2
, json
, json_scode
,
14252 json_ocode
, wide
, detail
);
14254 if ((safi
== SAFI_MPLS_VPN
)
14255 || (safi
== SAFI_ENCAP
)
14256 || (safi
== SAFI_EVPN
)) {
14258 json_object_string_add(
14259 json_ar
, "rd", rd_str
);
14260 else if (show_rd
&& rd_str
) {
14262 "Route Distinguisher: %s\n",
14269 route_filtered
= false;
14271 /* Filter prefix using distribute list,
14272 * filter list or prefix list
14274 const struct prefix
*rn_p
=
14275 bgp_dest_get_prefix(dest
);
14276 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
14279 route_filtered
= true;
14281 /* Filter prefix using route-map */
14282 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
14283 safi
, rmap_name
, NULL
,
14286 if (type
== bgp_show_adj_route_filtered
&&
14287 !route_filtered
&& ret
!= RMAP_DENY
) {
14288 bgp_attr_flush(&attr
);
14292 if (type
== bgp_show_adj_route_received
14293 && (route_filtered
|| ret
== RMAP_DENY
))
14294 (*filtered_count
)++;
14299 json_object_new_object();
14300 bgp_show_path_info(
14301 NULL
/* prefix_rd */, dest
, vty
,
14302 bgp
, afi
, safi
, json_net
,
14303 BGP_PATH_SHOW_ALL
, &display
,
14304 RPKI_NOT_BEING_USED
);
14306 json_object_object_addf(
14310 route_vty_out_tmp(vty
, dest
, rn_p
,
14311 &attr
, safi
, use_json
,
14313 bgp_attr_flush(&attr
);
14316 } else if (type
== bgp_show_adj_route_advertised
) {
14317 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
14318 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14319 if (paf
->peer
!= peer
|| !adj
->attr
)
14322 show_adj_route_header(
14323 vty
, peer
, table
, header1
,
14324 header2
, json
, json_scode
,
14325 json_ocode
, wide
, detail
);
14327 const struct prefix
*rn_p
=
14328 bgp_dest_get_prefix(dest
);
14331 ret
= bgp_output_modifier(
14332 peer
, rn_p
, &attr
, afi
, safi
,
14335 if (ret
!= RMAP_DENY
) {
14336 if ((safi
== SAFI_MPLS_VPN
)
14337 || (safi
== SAFI_ENCAP
)
14338 || (safi
== SAFI_EVPN
)) {
14340 json_object_string_add(
14347 "Route Distinguisher: %s\n",
14355 json_object_new_object();
14356 bgp_show_path_info(
14365 RPKI_NOT_BEING_USED
);
14367 json_object_object_addf(
14380 (*filtered_count
)++;
14383 bgp_attr_flush(&attr
);
14385 } else if (type
== bgp_show_adj_route_bestpath
) {
14386 struct bgp_path_info
*pi
;
14388 show_adj_route_header(vty
, peer
, table
, header1
,
14389 header2
, json
, json_scode
,
14390 json_ocode
, wide
, detail
);
14392 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
14394 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
14396 if (pi
->peer
!= peer
)
14399 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
14405 json_object_new_object();
14406 bgp_show_path_info(
14407 NULL
/* prefix_rd */, dest
, vty
,
14408 bgp
, afi
, safi
, json_net
,
14409 BGP_PATH_SHOW_BESTPATH
,
14410 &display
, RPKI_NOT_BEING_USED
);
14412 json_object_object_addf(
14417 vty
, dest
, rn_p
, pi
->attr
, safi
,
14418 use_json
, json_ar
, wide
);
14425 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
14426 safi_t safi
, enum bgp_show_adj_route_type type
,
14427 const char *rmap_name
, const struct prefix
*match
,
14428 uint16_t show_flags
)
14431 struct bgp_table
*table
;
14432 json_object
*json
= NULL
;
14433 json_object
*json_scode
= NULL
;
14434 json_object
*json_ocode
= NULL
;
14435 json_object
*json_ar
= NULL
;
14436 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14438 /* Init BGP headers here so they're only displayed once
14439 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14445 * Initialize variables for each RD
14446 * All prefixes under an RD is aggregated within "json_routes"
14448 char rd_str
[BUFSIZ
] = {0};
14449 json_object
*json_routes
= NULL
;
14452 /* For 2-tier tables, prefix counts need to be
14453 * maintained across multiple runs of show_adj_route()
14455 unsigned long output_count_per_rd
;
14456 unsigned long filtered_count_per_rd
;
14457 unsigned long output_count
= 0;
14458 unsigned long filtered_count
= 0;
14461 json
= json_object_new_object();
14462 json_ar
= json_object_new_object();
14463 json_scode
= json_object_new_object();
14464 json_ocode
= json_object_new_object();
14465 #if CONFDATE > 20231208
14466 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14468 json_object_string_add(json_scode
, "suppressed", "s");
14469 json_object_string_add(json_scode
, "damped", "d");
14470 json_object_string_add(json_scode
, "history", "h");
14471 json_object_string_add(json_scode
, "valid", "*");
14472 json_object_string_add(json_scode
, "best", ">");
14473 json_object_string_add(json_scode
, "multipath", "=");
14474 json_object_string_add(json_scode
, "internal", "i");
14475 json_object_string_add(json_scode
, "ribFailure", "r");
14476 json_object_string_add(json_scode
, "stale", "S");
14477 json_object_string_add(json_scode
, "removed", "R");
14479 #if CONFDATE > 20231208
14480 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14482 json_object_string_add(json_ocode
, "igp", "i");
14483 json_object_string_add(json_ocode
, "egp", "e");
14484 json_object_string_add(json_ocode
, "incomplete", "?");
14487 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14489 json_object_string_add(
14491 "No such neighbor or address family");
14492 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14493 json_object_free(json
);
14494 json_object_free(json_ar
);
14495 json_object_free(json_scode
);
14496 json_object_free(json_ocode
);
14498 vty_out(vty
, "%% No such neighbor or address family\n");
14500 return CMD_WARNING
;
14503 if ((type
== bgp_show_adj_route_received
14504 || type
== bgp_show_adj_route_filtered
)
14505 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
14506 PEER_FLAG_SOFT_RECONFIG
)) {
14508 json_object_string_add(
14510 "Inbound soft reconfiguration not enabled");
14511 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14512 json_object_free(json
);
14513 json_object_free(json_ar
);
14514 json_object_free(json_scode
);
14515 json_object_free(json_ocode
);
14518 "%% Inbound soft reconfiguration not enabled\n");
14520 return CMD_WARNING
;
14525 /* labeled-unicast routes live in the unicast table */
14526 if (safi
== SAFI_LABELED_UNICAST
)
14527 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
14529 table
= bgp
->rib
[afi
][safi
];
14531 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14532 || (safi
== SAFI_EVPN
)) {
14534 struct bgp_dest
*dest
;
14536 for (dest
= bgp_table_top(table
); dest
;
14537 dest
= bgp_route_next(dest
)) {
14538 table
= bgp_dest_get_bgp_table_info(dest
);
14542 output_count_per_rd
= 0;
14543 filtered_count_per_rd
= 0;
14546 json_routes
= json_object_new_object();
14548 const struct prefix_rd
*prd
;
14549 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14552 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
),
14556 vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14557 json
, json_routes
, json_scode
, json_ocode
,
14558 show_flags
, &header1
, &header2
, rd_str
, match
,
14559 &output_count_per_rd
, &filtered_count_per_rd
);
14561 /* Don't include an empty RD in the output! */
14562 if (json_routes
&& (output_count_per_rd
> 0))
14563 json_object_object_add(json_ar
, rd_str
,
14566 output_count
+= output_count_per_rd
;
14567 filtered_count
+= filtered_count_per_rd
;
14570 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14571 json
, json_ar
, json_scode
, json_ocode
,
14572 show_flags
, &header1
, &header2
, rd_str
, match
,
14573 &output_count
, &filtered_count
);
14576 if (type
== bgp_show_adj_route_advertised
)
14577 json_object_object_add(json
, "advertisedRoutes",
14580 json_object_object_add(json
, "receivedRoutes", json_ar
);
14581 json_object_int_add(json
, "totalPrefixCounter", output_count
);
14582 json_object_int_add(json
, "filteredPrefixCounter",
14586 * These fields only give up ownership to `json` when `header1`
14587 * is used (set to zero). See code in `show_adj_route` and
14588 * `show_adj_route_header`.
14590 if (header1
== 1) {
14591 json_object_free(json_scode
);
14592 json_object_free(json_ocode
);
14595 vty_json(vty
, json
);
14596 } else if (output_count
> 0) {
14597 if (!match
&& filtered_count
> 0)
14599 "\nTotal number of prefixes %ld (%ld filtered)\n",
14600 output_count
, filtered_count
);
14602 vty_out(vty
, "\nTotal number of prefixes %ld\n",
14606 return CMD_SUCCESS
;
14609 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
14610 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
14611 "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]",
14615 BGP_INSTANCE_HELP_STR
14617 BGP_SAFI_WITH_LABEL_HELP_STR
14618 "Detailed information on TCP and BGP neighbor connections\n"
14619 "Neighbor to display information about\n"
14620 "Neighbor to display information about\n"
14621 "Neighbor on BGP configured interface\n"
14622 "Display the routes selected by best path\n"
14623 "Display detailed version of routes\n"
14625 "Increase table width for longer prefixes\n")
14627 afi_t afi
= AFI_IP6
;
14628 safi_t safi
= SAFI_UNICAST
;
14629 char *rmap_name
= NULL
;
14630 char *peerstr
= NULL
;
14631 struct bgp
*bgp
= NULL
;
14633 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
14635 uint16_t show_flags
= 0;
14638 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14641 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14644 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14646 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14650 return CMD_WARNING
;
14652 argv_find(argv
, argc
, "neighbors", &idx
);
14653 peerstr
= argv
[++idx
]->arg
;
14655 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14657 return CMD_WARNING
;
14659 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, NULL
,
14663 DEFPY(show_ip_bgp_instance_neighbor_advertised_route
,
14664 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
14665 "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]",
14669 BGP_INSTANCE_HELP_STR
14671 BGP_SAFI_WITH_LABEL_HELP_STR
14672 "Display the entries for all address families\n"
14673 "Detailed information on TCP and BGP neighbor connections\n"
14674 "Neighbor to display information about\n"
14675 "Neighbor to display information about\n"
14676 "Neighbor on BGP configured interface\n"
14677 "Display the routes advertised to a BGP neighbor\n"
14678 "Display the received routes from neighbor\n"
14679 "Display the filtered routes received from neighbor\n"
14680 "Route-map to modify the attributes\n"
14681 "Name of the route map\n"
14684 "Display detailed version of routes\n"
14686 "Increase table width for longer prefixes\n")
14688 afi_t afi
= AFI_IP6
;
14689 safi_t safi
= SAFI_UNICAST
;
14690 char *peerstr
= NULL
;
14691 struct bgp
*bgp
= NULL
;
14693 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
14696 uint16_t show_flags
= 0;
14697 struct listnode
*node
;
14700 if (detail
|| prefix_str
)
14701 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14705 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14709 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
14710 if (argv_find(argv
, argc
, "ipv4", &idx
))
14711 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
14713 if (argv_find(argv
, argc
, "ipv6", &idx
))
14714 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
14718 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14720 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14723 return CMD_WARNING
;
14725 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14726 argv_find(argv
, argc
, "neighbors", &idx
);
14727 peerstr
= argv
[++idx
]->arg
;
14729 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14731 return CMD_WARNING
;
14733 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
14734 type
= bgp_show_adj_route_advertised
;
14735 else if (argv_find(argv
, argc
, "received-routes", &idx
))
14736 type
= bgp_show_adj_route_received
;
14737 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
14738 type
= bgp_show_adj_route_filtered
;
14741 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, route_map
,
14742 prefix_str
? prefix
: NULL
, show_flags
);
14744 vty_out(vty
, "{\n");
14746 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14747 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14748 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14750 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14751 FOREACH_SAFI (safi
) {
14752 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14759 vty_out(vty
, ",\n");
14760 vty_out(vty
, "\"%s\":",
14761 get_afi_safi_str(afi
, safi
,
14765 "\nFor address family: %s\n",
14766 get_afi_safi_str(afi
, safi
,
14769 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14770 route_map
, prefix
, show_flags
);
14774 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14775 FOREACH_AFI_SAFI (afi
, safi
) {
14776 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14783 vty_out(vty
, ",\n");
14784 vty_out(vty
, "\"%s\":",
14785 get_afi_safi_str(afi
, safi
,
14789 "\nFor address family: %s\n",
14790 get_afi_safi_str(afi
, safi
,
14793 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14794 route_map
, prefix
, show_flags
);
14799 vty_out(vty
, "}\n");
14801 return CMD_SUCCESS
;
14804 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14805 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14806 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14810 BGP_INSTANCE_HELP_STR
14813 BGP_AF_MODIFIER_STR
14814 "Detailed information on TCP and BGP neighbor connections\n"
14815 "Neighbor to display information about\n"
14816 "Neighbor to display information about\n"
14817 "Neighbor on BGP configured interface\n"
14818 "Display information received from a BGP neighbor\n"
14819 "Display the prefixlist filter\n"
14822 afi_t afi
= AFI_IP6
;
14823 safi_t safi
= SAFI_UNICAST
;
14824 char *peerstr
= NULL
;
14829 struct bgp
*bgp
= NULL
;
14830 bool uj
= use_json(argc
, argv
);
14835 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14838 return CMD_WARNING
;
14840 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14841 argv_find(argv
, argc
, "neighbors", &idx
);
14842 peerstr
= argv
[++idx
]->arg
;
14844 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14846 return CMD_WARNING
;
14848 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14849 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14852 vty_out(vty
, "Address Family: %s\n",
14853 get_afi_safi_str(afi
, safi
, false));
14854 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14857 vty_out(vty
, "{}\n");
14859 vty_out(vty
, "No functional output\n");
14862 return CMD_SUCCESS
;
14865 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14866 afi_t afi
, safi_t safi
,
14867 enum bgp_show_type type
, bool use_json
)
14869 uint16_t show_flags
= 0;
14872 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14874 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14876 json_object
*json_no
= NULL
;
14877 json_no
= json_object_new_object();
14878 json_object_string_add(
14879 json_no
, "warning",
14880 "No such neighbor or address family");
14881 vty_out(vty
, "%s\n",
14882 json_object_to_json_string(json_no
));
14883 json_object_free(json_no
);
14885 vty_out(vty
, "%% No such neighbor or address family\n");
14886 return CMD_WARNING
;
14889 /* labeled-unicast routes live in the unicast table */
14890 if (safi
== SAFI_LABELED_UNICAST
)
14891 safi
= SAFI_UNICAST
;
14893 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14894 RPKI_NOT_BEING_USED
);
14897 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14898 show_ip_bgp_flowspec_routes_detailed_cmd
,
14899 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14903 BGP_INSTANCE_HELP_STR
14906 "Detailed information on flowspec entries\n"
14909 afi_t afi
= AFI_IP6
;
14910 safi_t safi
= SAFI_UNICAST
;
14911 struct bgp
*bgp
= NULL
;
14913 bool uj
= use_json(argc
, argv
);
14914 uint16_t show_flags
= BGP_SHOW_OPT_ROUTES_DETAIL
;
14918 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14921 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14924 return CMD_WARNING
;
14926 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14927 show_flags
, RPKI_NOT_BEING_USED
);
14930 DEFUN (show_ip_bgp_neighbor_routes
,
14931 show_ip_bgp_neighbor_routes_cmd
,
14932 "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]",
14936 BGP_INSTANCE_HELP_STR
14938 BGP_SAFI_WITH_LABEL_HELP_STR
14939 "Detailed information on TCP and BGP neighbor connections\n"
14940 "Neighbor to display information about\n"
14941 "Neighbor to display information about\n"
14942 "Neighbor on BGP configured interface\n"
14943 "Display flap statistics of the routes learned from neighbor\n"
14944 "Display the dampened routes received from neighbor\n"
14945 "Display routes learned from neighbor\n"
14948 char *peerstr
= NULL
;
14949 struct bgp
*bgp
= NULL
;
14950 afi_t afi
= AFI_IP6
;
14951 safi_t safi
= SAFI_UNICAST
;
14953 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14955 bool uj
= use_json(argc
, argv
);
14960 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14963 return CMD_WARNING
;
14965 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14966 argv_find(argv
, argc
, "neighbors", &idx
);
14967 peerstr
= argv
[++idx
]->arg
;
14969 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14971 return CMD_WARNING
;
14973 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14974 sh_type
= bgp_show_type_flap_neighbor
;
14975 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14976 sh_type
= bgp_show_type_damp_neighbor
;
14977 else if (argv_find(argv
, argc
, "routes", &idx
))
14978 sh_type
= bgp_show_type_neighbor
;
14980 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14983 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14985 struct bgp_distance
{
14986 /* Distance value for the IP source prefix. */
14989 /* Name of the access-list to be matched. */
14993 DEFUN (show_bgp_afi_vpn_rd_route
,
14994 show_bgp_afi_vpn_rd_route_cmd
,
14995 "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]",
14999 BGP_AF_MODIFIER_STR
15000 "Display information for a route distinguisher\n"
15001 "Route Distinguisher\n"
15002 "All Route Distinguishers\n"
15003 "Network in the BGP routing table to display\n"
15004 "Network in the BGP routing table to display\n"
15008 struct prefix_rd prd
;
15009 afi_t afi
= AFI_MAX
;
15012 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
15013 vty_out(vty
, "%% Malformed Address Family\n");
15014 return CMD_WARNING
;
15017 if (!strcmp(argv
[5]->arg
, "all"))
15018 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
15019 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
15020 RPKI_NOT_BEING_USED
,
15021 use_json(argc
, argv
));
15023 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
15025 vty_out(vty
, "%% Malformed Route Distinguisher\n");
15026 return CMD_WARNING
;
15029 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
15030 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
15031 use_json(argc
, argv
));
15034 static struct bgp_distance
*bgp_distance_new(void)
15036 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
15039 static void bgp_distance_free(struct bgp_distance
*bdistance
)
15041 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
15044 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
15045 const char *ip_str
, const char *access_list_str
)
15052 struct bgp_dest
*dest
;
15053 struct bgp_distance
*bdistance
;
15055 afi
= bgp_node_afi(vty
);
15056 safi
= bgp_node_safi(vty
);
15058 ret
= str2prefix(ip_str
, &p
);
15060 vty_out(vty
, "Malformed prefix\n");
15061 return CMD_WARNING_CONFIG_FAILED
;
15064 distance
= atoi(distance_str
);
15066 /* Get BGP distance node. */
15067 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
15068 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15070 bgp_dest_unlock_node(dest
);
15072 bdistance
= bgp_distance_new();
15073 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
15076 /* Set distance value. */
15077 bdistance
->distance
= distance
;
15079 /* Reset access-list configuration. */
15080 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
15081 if (access_list_str
)
15082 bdistance
->access_list
=
15083 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
15085 return CMD_SUCCESS
;
15088 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
15089 const char *ip_str
, const char *access_list_str
)
15096 struct bgp_dest
*dest
;
15097 struct bgp_distance
*bdistance
;
15099 afi
= bgp_node_afi(vty
);
15100 safi
= bgp_node_safi(vty
);
15102 ret
= str2prefix(ip_str
, &p
);
15104 vty_out(vty
, "Malformed prefix\n");
15105 return CMD_WARNING_CONFIG_FAILED
;
15108 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
15110 vty_out(vty
, "Can't find specified prefix\n");
15111 return CMD_WARNING_CONFIG_FAILED
;
15114 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15115 distance
= atoi(distance_str
);
15117 if (bdistance
->distance
!= distance
) {
15118 vty_out(vty
, "Distance does not match configured\n");
15119 bgp_dest_unlock_node(dest
);
15120 return CMD_WARNING_CONFIG_FAILED
;
15123 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
15124 bgp_distance_free(bdistance
);
15126 bgp_dest_set_bgp_path_info(dest
, NULL
);
15127 bgp_dest_unlock_node(dest
);
15128 bgp_dest_unlock_node(dest
);
15130 return CMD_SUCCESS
;
15133 /* Apply BGP information to distance method. */
15134 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
15135 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
15137 struct bgp_dest
*dest
;
15138 struct prefix q
= {0};
15140 struct bgp_distance
*bdistance
;
15141 struct access_list
*alist
;
15142 struct bgp_static
*bgp_static
;
15143 struct bgp_path_info
*bpi_ultimate
;
15148 peer
= pinfo
->peer
;
15150 if (pinfo
->attr
->distance
)
15151 return pinfo
->attr
->distance
;
15153 /* get peer origin to calculate appropriate distance */
15154 if (pinfo
->sub_type
== BGP_ROUTE_IMPORTED
) {
15155 bpi_ultimate
= bgp_get_imported_bpi_ultimate(pinfo
);
15156 peer
= bpi_ultimate
->peer
;
15159 /* Check source address.
15160 * Note: for aggregate route, peer can have unspec af type.
15162 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
15163 && !sockunion2hostprefix(&peer
->su
, &q
))
15166 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
15168 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15169 bgp_dest_unlock_node(dest
);
15171 if (bdistance
->access_list
) {
15172 alist
= access_list_lookup(afi
, bdistance
->access_list
);
15174 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
15175 return bdistance
->distance
;
15177 return bdistance
->distance
;
15180 /* Backdoor check. */
15181 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
15183 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15184 bgp_dest_unlock_node(dest
);
15186 if (bgp_static
->backdoor
) {
15187 if (bgp
->distance_local
[afi
][safi
])
15188 return bgp
->distance_local
[afi
][safi
];
15190 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15194 if (peer
->sort
== BGP_PEER_EBGP
) {
15195 if (bgp
->distance_ebgp
[afi
][safi
])
15196 return bgp
->distance_ebgp
[afi
][safi
];
15197 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
15198 } else if (peer
->sort
== BGP_PEER_IBGP
) {
15199 if (bgp
->distance_ibgp
[afi
][safi
])
15200 return bgp
->distance_ibgp
[afi
][safi
];
15201 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15203 if (bgp
->distance_local
[afi
][safi
])
15204 return bgp
->distance_local
[afi
][safi
];
15205 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15209 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15210 * we should tell ZEBRA update the routes for a specific
15211 * AFI/SAFI to reflect changes in RIB.
15213 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
15215 safi_t update_safi
)
15220 FOREACH_AFI_SAFI (afi
, safi
) {
15221 if (!bgp_fibupd_safi(safi
))
15224 if (afi
!= update_afi
&& safi
!= update_safi
)
15227 if (BGP_DEBUG(zebra
, ZEBRA
))
15229 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15230 __func__
, afi
, safi
);
15231 bgp_zebra_announce_table(bgp
, afi
, safi
);
15235 DEFUN (bgp_distance
,
15237 "distance bgp (1-255) (1-255) (1-255)",
15238 "Define an administrative distance\n"
15240 "Distance for routes external to the AS\n"
15241 "Distance for routes internal to the AS\n"
15242 "Distance for local routes\n")
15244 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15245 int idx_number
= 2;
15246 int idx_number_2
= 3;
15247 int idx_number_3
= 4;
15248 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
15249 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
15250 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
15254 afi
= bgp_node_afi(vty
);
15255 safi
= bgp_node_safi(vty
);
15257 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
15258 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
15259 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
15260 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
15261 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
15262 bgp
->distance_local
[afi
][safi
] = distance_local
;
15263 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15265 return CMD_SUCCESS
;
15268 DEFUN (no_bgp_distance
,
15269 no_bgp_distance_cmd
,
15270 "no distance bgp [(1-255) (1-255) (1-255)]",
15272 "Define an administrative distance\n"
15274 "Distance for routes external to the AS\n"
15275 "Distance for routes internal to the AS\n"
15276 "Distance for local routes\n")
15278 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15282 afi
= bgp_node_afi(vty
);
15283 safi
= bgp_node_safi(vty
);
15285 if (bgp
->distance_ebgp
[afi
][safi
] != 0
15286 || bgp
->distance_ibgp
[afi
][safi
] != 0
15287 || bgp
->distance_local
[afi
][safi
] != 0) {
15288 bgp
->distance_ebgp
[afi
][safi
] = 0;
15289 bgp
->distance_ibgp
[afi
][safi
] = 0;
15290 bgp
->distance_local
[afi
][safi
] = 0;
15291 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15293 return CMD_SUCCESS
;
15297 DEFUN (bgp_distance_source
,
15298 bgp_distance_source_cmd
,
15299 "distance (1-255) A.B.C.D/M",
15300 "Define an administrative distance\n"
15301 "Administrative distance\n"
15302 "IP source prefix\n")
15304 int idx_number
= 1;
15305 int idx_ipv4_prefixlen
= 2;
15306 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15307 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15308 return CMD_SUCCESS
;
15311 DEFUN (no_bgp_distance_source
,
15312 no_bgp_distance_source_cmd
,
15313 "no distance (1-255) A.B.C.D/M",
15315 "Define an administrative distance\n"
15316 "Administrative distance\n"
15317 "IP source prefix\n")
15319 int idx_number
= 2;
15320 int idx_ipv4_prefixlen
= 3;
15321 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15322 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15323 return CMD_SUCCESS
;
15326 DEFUN (bgp_distance_source_access_list
,
15327 bgp_distance_source_access_list_cmd
,
15328 "distance (1-255) A.B.C.D/M WORD",
15329 "Define an administrative distance\n"
15330 "Administrative distance\n"
15331 "IP source prefix\n"
15332 "Access list name\n")
15334 int idx_number
= 1;
15335 int idx_ipv4_prefixlen
= 2;
15337 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15338 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15339 return CMD_SUCCESS
;
15342 DEFUN (no_bgp_distance_source_access_list
,
15343 no_bgp_distance_source_access_list_cmd
,
15344 "no distance (1-255) A.B.C.D/M WORD",
15346 "Define an administrative distance\n"
15347 "Administrative distance\n"
15348 "IP source prefix\n"
15349 "Access list name\n")
15351 int idx_number
= 2;
15352 int idx_ipv4_prefixlen
= 3;
15354 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15355 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15356 return CMD_SUCCESS
;
15359 DEFUN (ipv6_bgp_distance_source
,
15360 ipv6_bgp_distance_source_cmd
,
15361 "distance (1-255) X:X::X:X/M",
15362 "Define an administrative distance\n"
15363 "Administrative distance\n"
15364 "IP source prefix\n")
15366 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
15367 return CMD_SUCCESS
;
15370 DEFUN (no_ipv6_bgp_distance_source
,
15371 no_ipv6_bgp_distance_source_cmd
,
15372 "no distance (1-255) X:X::X:X/M",
15374 "Define an administrative distance\n"
15375 "Administrative distance\n"
15376 "IP source prefix\n")
15378 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
15379 return CMD_SUCCESS
;
15382 DEFUN (ipv6_bgp_distance_source_access_list
,
15383 ipv6_bgp_distance_source_access_list_cmd
,
15384 "distance (1-255) X:X::X:X/M WORD",
15385 "Define an administrative distance\n"
15386 "Administrative distance\n"
15387 "IP source prefix\n"
15388 "Access list name\n")
15390 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
15391 return CMD_SUCCESS
;
15394 DEFUN (no_ipv6_bgp_distance_source_access_list
,
15395 no_ipv6_bgp_distance_source_access_list_cmd
,
15396 "no distance (1-255) X:X::X:X/M WORD",
15398 "Define an administrative distance\n"
15399 "Administrative distance\n"
15400 "IP source prefix\n"
15401 "Access list name\n")
15403 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
15404 return CMD_SUCCESS
;
15407 DEFUN (bgp_damp_set
,
15409 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15410 "BGP Specific commands\n"
15411 "Enable route-flap dampening\n"
15412 "Half-life time for the penalty\n"
15413 "Value to start reusing a route\n"
15414 "Value to start suppressing a route\n"
15415 "Maximum duration to suppress a stable route\n")
15417 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15418 int idx_half_life
= 2;
15420 int idx_suppress
= 4;
15421 int idx_max_suppress
= 5;
15422 int half
= DEFAULT_HALF_LIFE
* 60;
15423 int reuse
= DEFAULT_REUSE
;
15424 int suppress
= DEFAULT_SUPPRESS
;
15425 int max
= 4 * half
;
15428 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15429 reuse
= atoi(argv
[idx_reuse
]->arg
);
15430 suppress
= atoi(argv
[idx_suppress
]->arg
);
15431 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
15432 } else if (argc
== 3) {
15433 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15438 * These can't be 0 but our SA doesn't understand the
15439 * way our cli is constructed
15443 if (suppress
< reuse
) {
15445 "Suppress value cannot be less than reuse value \n");
15449 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
15450 reuse
, suppress
, max
);
15453 DEFUN (bgp_damp_unset
,
15454 bgp_damp_unset_cmd
,
15455 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15457 "BGP Specific commands\n"
15458 "Enable route-flap dampening\n"
15459 "Half-life time for the penalty\n"
15460 "Value to start reusing a route\n"
15461 "Value to start suppressing a route\n"
15462 "Maximum duration to suppress a stable route\n")
15464 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15465 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
15468 /* Display specified route of BGP table. */
15469 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
15470 const char *ip_str
, afi_t afi
, safi_t safi
,
15471 struct prefix_rd
*prd
, int prefix_check
)
15474 struct prefix match
;
15475 struct bgp_dest
*dest
;
15476 struct bgp_dest
*rm
;
15477 struct bgp_path_info
*pi
;
15478 struct bgp_path_info
*pi_temp
;
15480 struct bgp_table
*table
;
15482 /* BGP structure lookup. */
15484 bgp
= bgp_lookup_by_name(view_name
);
15486 vty_out(vty
, "%% Can't find BGP instance %s\n",
15488 return CMD_WARNING
;
15491 bgp
= bgp_get_default();
15493 vty_out(vty
, "%% No BGP process is configured\n");
15494 return CMD_WARNING
;
15498 /* Check IP address argument. */
15499 ret
= str2prefix(ip_str
, &match
);
15501 vty_out(vty
, "%% address is malformed\n");
15502 return CMD_WARNING
;
15505 match
.family
= afi2family(afi
);
15507 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
15508 || (safi
== SAFI_EVPN
)) {
15509 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
15510 dest
= bgp_route_next(dest
)) {
15511 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15513 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
15515 table
= bgp_dest_get_bgp_table_info(dest
);
15518 rm
= bgp_node_match(table
, &match
);
15522 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
15525 || rm_p
->prefixlen
== match
.prefixlen
) {
15526 pi
= bgp_dest_get_bgp_path_info(rm
);
15528 if (pi
->extra
&& pi
->extra
->damp_info
) {
15529 pi_temp
= pi
->next
;
15530 bgp_damp_info_free(
15531 pi
->extra
->damp_info
,
15539 bgp_dest_unlock_node(rm
);
15542 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
15543 if (dest
!= NULL
) {
15544 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15547 || dest_p
->prefixlen
== match
.prefixlen
) {
15548 pi
= bgp_dest_get_bgp_path_info(dest
);
15550 if (pi
->extra
&& pi
->extra
->damp_info
) {
15551 pi_temp
= pi
->next
;
15552 bgp_damp_info_free(
15553 pi
->extra
->damp_info
,
15561 bgp_dest_unlock_node(dest
);
15565 return CMD_SUCCESS
;
15568 DEFUN (clear_ip_bgp_dampening
,
15569 clear_ip_bgp_dampening_cmd
,
15570 "clear ip bgp dampening",
15574 "Clear route flap dampening information\n")
15576 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
15577 return CMD_SUCCESS
;
15580 DEFUN (clear_ip_bgp_dampening_prefix
,
15581 clear_ip_bgp_dampening_prefix_cmd
,
15582 "clear ip bgp dampening A.B.C.D/M",
15586 "Clear route flap dampening information\n"
15589 int idx_ipv4_prefixlen
= 4;
15590 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
15591 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
15594 DEFUN (clear_ip_bgp_dampening_address
,
15595 clear_ip_bgp_dampening_address_cmd
,
15596 "clear ip bgp dampening A.B.C.D",
15600 "Clear route flap dampening information\n"
15601 "Network to clear damping information\n")
15604 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
15605 SAFI_UNICAST
, NULL
, 0);
15608 DEFUN (clear_ip_bgp_dampening_address_mask
,
15609 clear_ip_bgp_dampening_address_mask_cmd
,
15610 "clear ip bgp dampening A.B.C.D A.B.C.D",
15614 "Clear route flap dampening information\n"
15615 "Network to clear damping information\n"
15619 int idx_ipv4_2
= 5;
15621 char prefix_str
[BUFSIZ
];
15623 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
15624 prefix_str
, sizeof(prefix_str
));
15626 vty_out(vty
, "%% Inconsistent address and mask\n");
15627 return CMD_WARNING
;
15630 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
15634 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
15636 struct vty
*vty
= arg
;
15637 struct peer
*peer
= bucket
->data
;
15639 vty_out(vty
, "\tPeer: %s %pSU\n", peer
->host
, &peer
->su
);
15642 DEFUN (show_bgp_listeners
,
15643 show_bgp_listeners_cmd
,
15644 "show bgp listeners",
15647 "Display Listen Sockets and who created them\n")
15649 bgp_dump_listener_info(vty
);
15651 return CMD_SUCCESS
;
15654 DEFUN (show_bgp_peerhash
,
15655 show_bgp_peerhash_cmd
,
15656 "show bgp peerhash",
15659 "Display information about the BGP peerhash\n")
15661 struct list
*instances
= bm
->bgp
;
15662 struct listnode
*node
;
15665 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
15666 vty_out(vty
, "BGP: %s\n", bgp
->name
);
15667 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
15671 return CMD_SUCCESS
;
15674 /* also used for encap safi */
15675 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
15676 afi_t afi
, safi_t safi
)
15678 struct bgp_dest
*pdest
;
15679 struct bgp_dest
*dest
;
15680 struct bgp_table
*table
;
15681 const struct prefix
*p
;
15682 struct bgp_static
*bgp_static
;
15683 mpls_label_t label
;
15685 /* Network configuration. */
15686 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15687 pdest
= bgp_route_next(pdest
)) {
15688 table
= bgp_dest_get_bgp_table_info(pdest
);
15692 for (dest
= bgp_table_top(table
); dest
;
15693 dest
= bgp_route_next(dest
)) {
15694 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15695 if (bgp_static
== NULL
)
15698 p
= bgp_dest_get_prefix(dest
);
15700 /* "network" configuration display. */
15701 label
= decode_label(&bgp_static
->label
);
15703 vty_out(vty
, " network %pFX rd %s", p
,
15704 bgp_static
->prd_pretty
);
15705 if (safi
== SAFI_MPLS_VPN
)
15706 vty_out(vty
, " label %u", label
);
15708 if (bgp_static
->rmap
.name
)
15709 vty_out(vty
, " route-map %s",
15710 bgp_static
->rmap
.name
);
15712 if (bgp_static
->backdoor
)
15713 vty_out(vty
, " backdoor");
15715 vty_out(vty
, "\n");
15720 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
15721 afi_t afi
, safi_t safi
)
15723 struct bgp_dest
*pdest
;
15724 struct bgp_dest
*dest
;
15725 struct bgp_table
*table
;
15726 const struct prefix
*p
;
15727 struct bgp_static
*bgp_static
;
15728 char buf
[PREFIX_STRLEN
* 2];
15729 char buf2
[SU_ADDRSTRLEN
];
15730 char esi_buf
[ESI_STR_LEN
];
15732 /* Network configuration. */
15733 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15734 pdest
= bgp_route_next(pdest
)) {
15735 table
= bgp_dest_get_bgp_table_info(pdest
);
15739 for (dest
= bgp_table_top(table
); dest
;
15740 dest
= bgp_route_next(dest
)) {
15741 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15742 if (bgp_static
== NULL
)
15745 char *macrouter
= NULL
;
15747 if (bgp_static
->router_mac
)
15748 macrouter
= prefix_mac2str(
15749 bgp_static
->router_mac
, NULL
, 0);
15750 if (bgp_static
->eth_s_id
)
15751 esi_to_str(bgp_static
->eth_s_id
,
15752 esi_buf
, sizeof(esi_buf
));
15753 p
= bgp_dest_get_prefix(dest
);
15755 /* "network" configuration display. */
15756 if (p
->u
.prefix_evpn
.route_type
== 5) {
15757 char local_buf
[PREFIX_STRLEN
];
15759 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15760 struct prefix_evpn
*)p
)
15764 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
15766 local_buf
, sizeof(local_buf
));
15767 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15768 p
->u
.prefix_evpn
.prefix_addr
15769 .ip_prefix_length
);
15771 prefix2str(p
, buf
, sizeof(buf
));
15774 if (bgp_static
->gatewayIp
.family
== AF_INET
15775 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15776 inet_ntop(bgp_static
->gatewayIp
.family
,
15777 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15780 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15781 buf
, bgp_static
->prd_pretty
,
15782 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15783 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15786 XFREE(MTYPE_TMP
, macrouter
);
15791 /* Configuration of static route announcement and aggregate
15793 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15796 struct bgp_dest
*dest
;
15797 const struct prefix
*p
;
15798 struct bgp_static
*bgp_static
;
15799 struct bgp_aggregate
*bgp_aggregate
;
15801 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15802 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15806 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15807 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15811 /* Network configuration. */
15812 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15813 dest
= bgp_route_next(dest
)) {
15814 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15815 if (bgp_static
== NULL
)
15818 p
= bgp_dest_get_prefix(dest
);
15820 vty_out(vty
, " network %pFX", p
);
15822 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15823 vty_out(vty
, " label-index %u",
15824 bgp_static
->label_index
);
15826 if (bgp_static
->rmap
.name
)
15827 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15829 if (bgp_static
->backdoor
)
15830 vty_out(vty
, " backdoor");
15832 vty_out(vty
, "\n");
15835 /* Aggregate-address configuration. */
15836 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15837 dest
= bgp_route_next(dest
)) {
15838 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15839 if (bgp_aggregate
== NULL
)
15842 p
= bgp_dest_get_prefix(dest
);
15844 vty_out(vty
, " aggregate-address %pFX", p
);
15846 if (bgp_aggregate
->as_set
)
15847 vty_out(vty
, " as-set");
15849 if (bgp_aggregate
->summary_only
)
15850 vty_out(vty
, " summary-only");
15852 if (bgp_aggregate
->rmap
.name
)
15853 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15855 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15856 vty_out(vty
, " origin %s",
15857 bgp_origin2str(bgp_aggregate
->origin
));
15859 if (bgp_aggregate
->match_med
)
15860 vty_out(vty
, " matching-MED-only");
15862 if (bgp_aggregate
->suppress_map_name
)
15863 vty_out(vty
, " suppress-map %s",
15864 bgp_aggregate
->suppress_map_name
);
15866 vty_out(vty
, "\n");
15870 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15873 struct bgp_dest
*dest
;
15874 struct bgp_distance
*bdistance
;
15876 /* Distance configuration. */
15877 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15878 && bgp
->distance_local
[afi
][safi
]
15879 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15880 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15881 || bgp
->distance_local
[afi
][safi
]
15882 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15883 vty_out(vty
, " distance bgp %d %d %d\n",
15884 bgp
->distance_ebgp
[afi
][safi
],
15885 bgp
->distance_ibgp
[afi
][safi
],
15886 bgp
->distance_local
[afi
][safi
]);
15889 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15890 dest
= bgp_route_next(dest
)) {
15891 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15892 if (bdistance
!= NULL
)
15893 vty_out(vty
, " distance %d %pBD %s\n",
15894 bdistance
->distance
, dest
,
15895 bdistance
->access_list
? bdistance
->access_list
15900 /* Allocate routing table structure and install commands. */
15901 void bgp_route_init(void)
15906 /* Init BGP distance table. */
15907 FOREACH_AFI_SAFI (afi
, safi
)
15908 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15910 /* IPv4 BGP commands. */
15911 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15912 install_element(BGP_NODE
, &bgp_network_cmd
);
15913 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15915 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15917 /* IPv4 unicast configuration. */
15918 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15919 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15920 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15922 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15924 /* IPv4 multicast configuration. */
15925 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15926 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15927 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15928 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15930 /* IPv4 labeled-unicast configuration. */
15931 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15932 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15934 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15935 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15936 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15937 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15938 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15939 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15940 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15941 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15943 install_element(VIEW_NODE
,
15944 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15945 install_element(VIEW_NODE
,
15946 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15947 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15948 install_element(VIEW_NODE
,
15949 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15950 #ifdef KEEP_OLD_VPN_COMMANDS
15951 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15952 #endif /* KEEP_OLD_VPN_COMMANDS */
15953 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15954 install_element(VIEW_NODE
,
15955 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15957 /* BGP dampening clear commands */
15958 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15959 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15961 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15962 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15965 install_element(ENABLE_NODE
,
15966 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15967 #ifdef KEEP_OLD_VPN_COMMANDS
15968 install_element(ENABLE_NODE
,
15969 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15970 #endif /* KEEP_OLD_VPN_COMMANDS */
15972 /* New config IPv6 BGP commands. */
15973 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15974 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15975 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15977 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15979 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15981 /* IPv6 labeled unicast address family. */
15982 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15983 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15985 install_element(BGP_NODE
, &bgp_distance_cmd
);
15986 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15987 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15988 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
15989 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
15990 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
15991 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15992 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15993 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15994 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
15995 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
15996 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
15997 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15998 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15999 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
16000 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
16001 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
16002 install_element(BGP_IPV4M_NODE
,
16003 &no_bgp_distance_source_access_list_cmd
);
16004 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
16005 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
16006 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
16007 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
16008 install_element(BGP_IPV6_NODE
,
16009 &ipv6_bgp_distance_source_access_list_cmd
);
16010 install_element(BGP_IPV6_NODE
,
16011 &no_ipv6_bgp_distance_source_access_list_cmd
);
16012 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
16013 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
16014 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
16015 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
16016 install_element(BGP_IPV6M_NODE
,
16017 &ipv6_bgp_distance_source_access_list_cmd
);
16018 install_element(BGP_IPV6M_NODE
,
16019 &no_ipv6_bgp_distance_source_access_list_cmd
);
16021 /* BGP dampening */
16022 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
16023 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
16024 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
16025 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
16026 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
16027 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
16028 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
16029 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
16030 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
16031 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
16032 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
16033 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
16034 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
16035 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
16037 /* Large Communities */
16038 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
16039 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
16041 /* show bgp ipv4 flowspec detailed */
16042 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
16044 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
16045 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
16048 void bgp_route_finish(void)
16053 FOREACH_AFI_SAFI (afi
, safi
) {
16054 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
16055 bgp_distance_table
[afi
][safi
] = NULL
;