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
)
3084 else if (new_select
->extra
&&
3085 bgp_is_valid_label(&new_select
->extra
->label
[0]))
3089 if (!!CHECK_FLAG(bgp
->flags
, BGP_FLAG_LU_EXPLICIT_NULL
))
3090 /* Disable PHP : explicit-null */
3091 *label
= afi
== AFI_IP
? MPLS_LABEL_IPV4_EXPLICIT_NULL
3092 : MPLS_LABEL_IPV6_EXPLICIT_NULL
;
3094 /* Enforced PHP popping: implicit-null */
3095 *label
= MPLS_LABEL_IMPLICIT_NULL
;
3101 * old_select = The old best path
3102 * new_select = the new best path
3104 * if (!old_select && new_select)
3105 * We are sending new information on.
3107 * if (old_select && new_select) {
3108 * if (new_select != old_select)
3109 * We have a new best path send a change
3111 * We've received a update with new attributes that needs
3115 * if (old_select && !new_select)
3116 * We have no eligible route that we can announce or the rn
3119 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
3120 afi_t afi
, safi_t safi
)
3122 struct bgp_path_info
*new_select
;
3123 struct bgp_path_info
*old_select
;
3124 struct bgp_path_info_pair old_and_new
;
3126 mpls_label_t mpls_label_null
;
3128 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
3130 debug
= bgp_debug_bestpath(dest
);
3133 "%s: bgp delete in progress, ignoring event, p=%pBD(%s)",
3134 __func__
, dest
, bgp
->name_pretty
);
3137 /* Is it end of initial update? (after startup) */
3139 frr_timestamp(3, bgp
->update_delay_zebra_resume_time
,
3140 sizeof(bgp
->update_delay_zebra_resume_time
));
3142 bgp
->main_zebra_update_hold
= 0;
3143 FOREACH_AFI_SAFI (afi
, safi
) {
3144 if (bgp_fibupd_safi(safi
))
3145 bgp_zebra_announce_table(bgp
, afi
, safi
);
3147 bgp
->main_peers_update_hold
= 0;
3149 bgp_start_routeadv(bgp
);
3153 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3155 debug
= bgp_debug_bestpath(dest
);
3157 zlog_debug("%s: p=%pBD(%s) afi=%s, safi=%s start", __func__
,
3158 dest
, bgp
->name_pretty
, afi2str(afi
),
3161 /* The best path calculation for the route is deferred if
3162 * BGP_NODE_SELECT_DEFER is set
3164 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3165 if (BGP_DEBUG(update
, UPDATE_OUT
))
3166 zlog_debug("SELECT_DEFER flag set for route %p(%s)",
3167 dest
, bgp
->name_pretty
);
3171 /* Best path selection. */
3172 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
3174 old_select
= old_and_new
.old
;
3175 new_select
= old_and_new
.new;
3177 /* Do we need to allocate or free labels?
3178 * Right now, since we only deal with per-prefix labels, it is not
3179 * necessary to do this upon changes to best path. Exceptions:
3180 * - label index has changed -> recalculate resulting label
3181 * - path_info sub_type changed -> switch to/from null label value
3182 * - no valid label (due to removed static label binding) -> get new one
3184 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
3187 || bgp_label_index_differs(new_select
, old_select
)
3188 || new_select
->sub_type
!= old_select
->sub_type
3189 || !bgp_is_valid_label(&dest
->local_label
)) {
3190 /* control label imposition for local routes,
3191 * aggregate and redistributed routes
3193 mpls_label_null
= MPLS_LABEL_IMPLICIT_NULL
;
3194 if (bgp_lu_need_null_label(bgp
, new_select
, afi
,
3195 &mpls_label_null
)) {
3198 BGP_NODE_REGISTERED_FOR_LABEL
)
3201 BGP_NODE_LABEL_REQUESTED
))
3202 bgp_unregister_for_label(dest
);
3203 dest
->local_label
= mpls_lse_encode(
3204 mpls_label_null
, 0, 0, 1);
3205 bgp_set_valid_label(&dest
->local_label
);
3207 bgp_register_for_label(dest
,
3210 } else if (CHECK_FLAG(dest
->flags
,
3211 BGP_NODE_REGISTERED_FOR_LABEL
)
3212 || CHECK_FLAG(dest
->flags
,
3213 BGP_NODE_LABEL_REQUESTED
)) {
3214 bgp_unregister_for_label(dest
);
3216 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
3217 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
3218 bgp_unregister_for_label(dest
);
3223 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3224 __func__
, dest
, bgp
->name_pretty
, afi2str(afi
),
3225 safi2str(safi
), old_select
, new_select
);
3227 /* If best route remains the same and this is not due to user-initiated
3228 * clear, see exactly what needs to be done.
3230 if (old_select
&& old_select
== new_select
3231 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
3232 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3233 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
3234 if (bgp_zebra_has_route_changed(old_select
)) {
3235 #ifdef ENABLE_BGP_VNC
3236 vnc_import_bgp_add_route(bgp
, p
, old_select
);
3237 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
3239 if (bgp_fibupd_safi(safi
)
3240 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3242 if (new_select
->type
== ZEBRA_ROUTE_BGP
3243 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3244 || new_select
->sub_type
3245 == BGP_ROUTE_IMPORTED
))
3247 bgp_zebra_announce(dest
, p
, old_select
,
3252 /* If there is a change of interest to peers, reannounce the
3254 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3255 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3256 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
3257 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3259 /* unicast routes must also be annouced to
3260 * labeled-unicast update-groups */
3261 if (safi
== SAFI_UNICAST
)
3262 group_announce_route(bgp
, afi
,
3263 SAFI_LABELED_UNICAST
, dest
,
3266 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
3267 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
3270 /* advertise/withdraw type-5 routes */
3271 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3272 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
3273 bgp_process_evpn_route_injection(
3274 bgp
, afi
, safi
, dest
, old_select
, old_select
);
3276 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3277 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3278 bgp_zebra_clear_route_change_flags(dest
);
3279 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3283 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3285 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
3287 /* bestpath has changed; bump version */
3288 if (old_select
|| new_select
) {
3289 bgp_bump_version(dest
);
3291 if (!bgp
->t_rmap_def_originate_eval
) {
3295 update_group_refresh_default_originate_route_map
,
3296 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
3297 &bgp
->t_rmap_def_originate_eval
);
3302 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
3305 zlog_debug("%s: setting SELECTED flag", __func__
);
3306 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
3307 bgp_path_info_unset_flag(dest
, new_select
,
3308 BGP_PATH_ATTR_CHANGED
);
3309 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3310 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3313 #ifdef ENABLE_BGP_VNC
3314 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3315 if (old_select
!= new_select
) {
3317 vnc_import_bgp_exterior_del_route(bgp
, p
,
3319 vnc_import_bgp_del_route(bgp
, p
, old_select
);
3322 vnc_import_bgp_exterior_add_route(bgp
, p
,
3324 vnc_import_bgp_add_route(bgp
, p
, new_select
);
3330 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3332 /* unicast routes must also be annouced to labeled-unicast update-groups
3334 if (safi
== SAFI_UNICAST
)
3335 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
3339 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
3340 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3342 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
3343 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3344 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3345 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
3347 /* if this is an evpn imported type-5 prefix,
3348 * we need to withdraw the route first to clear
3349 * the nh neigh and the RMAC entry.
3352 is_route_parent_evpn(old_select
))
3353 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3355 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
3357 /* Withdraw the route from the kernel. */
3358 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
3359 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
3360 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
3361 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
3363 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3367 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
3370 /* Clear any route change flags. */
3371 bgp_zebra_clear_route_change_flags(dest
);
3373 /* Reap old select bgp_path_info, if it has been removed */
3374 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
3375 bgp_path_info_reap(dest
, old_select
);
3377 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3381 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3382 void bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
3384 struct bgp_dest
*dest
;
3386 struct afi_safi_info
*thread_info
;
3388 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
3389 struct event
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
3391 thread_info
= EVENT_ARG(t
);
3392 XFREE(MTYPE_TMP
, thread_info
);
3393 EVENT_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
3396 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
3397 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
3398 get_afi_safi_str(afi
, safi
, false),
3399 bgp
->gr_info
[afi
][safi
].gr_deferred
);
3402 /* Process the route list */
3403 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
3404 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0 &&
3405 cnt
< BGP_MAX_BEST_ROUTE_SELECT
;
3406 dest
= bgp_route_next(dest
)) {
3407 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
3410 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3411 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3412 bgp_process_main_one(bgp
, dest
, afi
, safi
);
3415 /* If iteration stopped before the entire table was traversed then the
3416 * node needs to be unlocked.
3419 bgp_dest_unlock_node(dest
);
3423 /* Send EOR message when all routes are processed */
3424 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
3425 bgp_send_delayed_eor(bgp
);
3426 /* Send route processing complete message to RIB */
3427 bgp_zebra_update(bgp
, afi
, safi
,
3428 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
3432 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3434 thread_info
->afi
= afi
;
3435 thread_info
->safi
= safi
;
3436 thread_info
->bgp
= bgp
;
3438 /* If there are more routes to be processed, start the
3441 event_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3442 BGP_ROUTE_SELECT_DELAY
,
3443 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3446 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3448 struct bgp_process_queue
*pqnode
= data
;
3449 struct bgp
*bgp
= pqnode
->bgp
;
3450 struct bgp_table
*table
;
3451 struct bgp_dest
*dest
;
3454 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3455 bgp_process_main_one(bgp
, NULL
, 0, 0);
3456 /* should always have dedicated wq call */
3457 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3461 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3462 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3463 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3464 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3465 table
= bgp_dest_table(dest
);
3466 /* note, new DESTs may be added as part of processing */
3467 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3469 bgp_dest_unlock_node(dest
);
3470 bgp_table_unlock(table
);
3476 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3478 struct bgp_process_queue
*pqnode
= data
;
3480 bgp_unlock(pqnode
->bgp
);
3482 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3485 void bgp_process_queue_init(struct bgp
*bgp
)
3487 if (!bgp
->process_queue
) {
3490 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3491 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3494 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3495 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3496 bgp
->process_queue
->spec
.max_retries
= 0;
3497 bgp
->process_queue
->spec
.hold
= 50;
3498 /* Use a higher yield value of 50ms for main queue processing */
3499 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3502 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3504 struct bgp_process_queue
*pqnode
;
3506 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3507 sizeof(struct bgp_process_queue
));
3509 /* unlocked in bgp_processq_del */
3510 pqnode
->bgp
= bgp_lock(bgp
);
3511 STAILQ_INIT(&pqnode
->pqueue
);
3516 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3518 #define ARBITRARY_PROCESS_QLEN 10000
3519 struct work_queue
*wq
= bgp
->process_queue
;
3520 struct bgp_process_queue
*pqnode
;
3521 int pqnode_reuse
= 0;
3523 /* already scheduled for processing? */
3524 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3527 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3530 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3531 if (BGP_DEBUG(update
, UPDATE_OUT
))
3532 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3537 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
)) {
3538 if (BGP_DEBUG(update
, UPDATE_OUT
))
3540 "Soft reconfigure table in progress for route %p",
3548 /* Add route nodes to an existing work queue item until reaching the
3549 limit only if is from the same BGP view and it's not an EOIU marker
3551 if (work_queue_item_count(wq
)) {
3552 struct work_queue_item
*item
= work_queue_last_item(wq
);
3553 pqnode
= item
->data
;
3555 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3556 || pqnode
->bgp
!= bgp
3557 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3558 pqnode
= bgp_processq_alloc(bgp
);
3562 pqnode
= bgp_processq_alloc(bgp
);
3563 /* all unlocked in bgp_process_wq */
3564 bgp_table_lock(bgp_dest_table(dest
));
3566 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3567 bgp_dest_lock_node(dest
);
3569 /* can't be enqueued twice */
3570 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3571 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3575 work_queue_add(wq
, pqnode
);
3580 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3582 struct bgp_process_queue
*pqnode
;
3584 if (bgp
->process_queue
== NULL
)
3587 pqnode
= bgp_processq_alloc(bgp
);
3589 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3590 work_queue_add(bgp
->process_queue
, pqnode
);
3593 static void bgp_maximum_prefix_restart_timer(struct event
*thread
)
3597 peer
= EVENT_ARG(thread
);
3598 peer
->t_pmax_restart
= NULL
;
3600 if (bgp_debug_neighbor_events(peer
))
3602 "%s Maximum-prefix restart timer expired, restore peering",
3605 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3606 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3609 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3613 bool filtered
= false;
3614 struct bgp_dest
*dest
;
3615 struct bgp_adj_in
*ain
;
3616 struct attr attr
= {};
3617 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3619 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3620 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3621 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3625 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3629 if (bgp_input_modifier(
3630 peer
, rn_p
, &attr
, afi
, safi
,
3631 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3639 bgp_attr_flush(&attr
);
3646 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3650 iana_safi_t pkt_safi
;
3651 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3652 PEER_FLAG_MAX_PREFIX_FORCE
))
3653 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3654 + peer
->pcount
[afi
][safi
]
3655 : peer
->pcount
[afi
][safi
];
3657 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3660 if (pcount
> peer
->pmax
[afi
][safi
]) {
3661 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3662 PEER_STATUS_PREFIX_LIMIT
)
3667 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3668 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3669 peer
->pmax
[afi
][safi
]);
3670 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3672 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3673 PEER_FLAG_MAX_PREFIX_WARNING
))
3676 /* Convert AFI, SAFI to values for packet. */
3677 pkt_afi
= afi_int2iana(afi
);
3678 pkt_safi
= safi_int2iana(safi
);
3682 ndata
[0] = (pkt_afi
>> 8);
3684 ndata
[2] = pkt_safi
;
3685 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3686 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3687 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3688 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3690 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3691 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3692 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3696 /* Dynamic peers will just close their connection. */
3697 if (peer_dynamic_neighbor(peer
))
3700 /* restart timer start */
3701 if (peer
->pmax_restart
[afi
][safi
]) {
3702 peer
->v_pmax_restart
=
3703 peer
->pmax_restart
[afi
][safi
] * 60;
3705 if (bgp_debug_neighbor_events(peer
))
3707 "%pBP Maximum-prefix restart timer started for %d secs",
3708 peer
, peer
->v_pmax_restart
);
3710 BGP_TIMER_ON(peer
->t_pmax_restart
,
3711 bgp_maximum_prefix_restart_timer
,
3712 peer
->v_pmax_restart
);
3717 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3718 PEER_STATUS_PREFIX_LIMIT
);
3721 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3722 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3723 PEER_STATUS_PREFIX_THRESHOLD
)
3728 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3729 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3730 peer
->pmax
[afi
][safi
]);
3731 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3732 PEER_STATUS_PREFIX_THRESHOLD
);
3734 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3735 PEER_STATUS_PREFIX_THRESHOLD
);
3739 /* Unconditionally remove the route from the RIB, without taking
3740 * damping into consideration (eg, because the session went down)
3742 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3743 struct peer
*peer
, afi_t afi
, safi_t safi
)
3746 struct bgp
*bgp
= NULL
;
3747 bool delete_route
= false;
3749 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3752 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3753 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3755 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3758 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3759 delete_route
= true;
3760 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3761 delete_route
= true;
3763 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3764 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3765 bgp
= pi
->peer
->bgp
;
3766 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3771 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3772 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3775 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3776 struct peer
*peer
, afi_t afi
, safi_t safi
,
3777 struct prefix_rd
*prd
)
3779 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3781 /* apply dampening, if result is suppressed, we'll be retaining
3782 * the bgp_path_info in the RIB for historical reference.
3784 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3785 && peer
->sort
== BGP_PEER_EBGP
)
3786 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3787 == BGP_DAMP_SUPPRESSED
) {
3788 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3793 #ifdef ENABLE_BGP_VNC
3794 if (safi
== SAFI_MPLS_VPN
) {
3795 struct bgp_dest
*pdest
= NULL
;
3796 struct bgp_table
*table
= NULL
;
3798 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3799 (struct prefix
*)prd
);
3800 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3801 table
= bgp_dest_get_bgp_table_info(pdest
);
3803 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3804 peer
->bgp
, prd
, table
, p
, pi
);
3806 bgp_dest_unlock_node(pdest
);
3808 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3809 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3811 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3812 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3817 /* If this is an EVPN route, process for un-import. */
3818 if (safi
== SAFI_EVPN
)
3819 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3821 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3824 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3825 struct peer
*peer
, struct attr
*attr
,
3826 struct bgp_dest
*dest
)
3828 struct bgp_path_info
*new;
3830 /* Make new BGP info. */
3831 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3833 new->instance
= instance
;
3834 new->sub_type
= sub_type
;
3837 new->uptime
= monotime(NULL
);
3842 /* Check if received nexthop is valid or not. */
3843 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3844 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3845 struct bgp_dest
*dest
)
3848 bool is_bgp_static_route
=
3849 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3852 /* If `bgp allow-martian-nexthop` is turned on, return next-hop
3855 if (bgp
->allow_martian
)
3859 * Only validated for unicast and multicast currently.
3860 * Also valid for EVPN where the nexthop is an IP address.
3861 * If we are a bgp static route being checked then there is
3862 * no need to check to see if the nexthop is martian as
3863 * that it should be ok.
3865 if (is_bgp_static_route
||
3866 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3869 /* If NEXT_HOP is present, validate it. */
3870 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3871 if (attr
->nexthop
.s_addr
== INADDR_ANY
||
3872 !ipv4_unicast_valid(&attr
->nexthop
) ||
3873 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3877 /* If MP_NEXTHOP is present, validate it. */
3878 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3879 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3880 * it is not an IPv6 link-local address.
3882 * If we receive an UPDATE with nexthop length set to 32 bytes
3883 * we shouldn't discard an UPDATE if it's set to (::).
3884 * The link-local (2st) is validated along the code path later.
3886 if (attr
->mp_nexthop_len
) {
3887 switch (attr
->mp_nexthop_len
) {
3888 case BGP_ATTR_NHLEN_IPV4
:
3889 case BGP_ATTR_NHLEN_VPNV4
:
3890 ret
= (attr
->mp_nexthop_global_in
.s_addr
==
3892 !ipv4_unicast_valid(
3893 &attr
->mp_nexthop_global_in
) ||
3894 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3898 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3899 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3900 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3901 &attr
->mp_nexthop_global
)
3902 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3903 || IN6_IS_ADDR_MULTICAST(
3904 &attr
->mp_nexthop_global
)
3905 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3908 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3909 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3910 || IN6_IS_ADDR_MULTICAST(
3911 &attr
->mp_nexthop_global
)
3912 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3925 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3927 struct community
*old
;
3928 struct community
*new;
3929 struct community
*merge
;
3930 struct community
*no_export
;
3932 old
= bgp_attr_get_community(attr
);
3933 no_export
= community_str2com("no-export");
3938 merge
= community_merge(community_dup(old
), no_export
);
3941 community_free(&old
);
3943 new = community_uniq_sort(merge
);
3944 community_free(&merge
);
3946 new = community_dup(no_export
);
3949 community_free(&no_export
);
3951 bgp_attr_set_community(attr
, new);
3954 static bool bgp_accept_own(struct peer
*peer
, afi_t afi
, safi_t safi
,
3955 struct attr
*attr
, const struct prefix
*prefix
,
3958 struct listnode
*node
, *nnode
;
3960 bool accept_own_found
= false;
3962 if (safi
!= SAFI_MPLS_VPN
)
3965 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3966 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
))
3969 /* The route in question carries the ACCEPT_OWN community */
3970 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
3971 struct community
*comm
= bgp_attr_get_community(attr
);
3973 if (community_include(comm
, COMMUNITY_ACCEPT_OWN
))
3974 accept_own_found
= true;
3977 /* The route in question is targeted to one or more destination VRFs
3978 * on the router (as determined by inspecting the Route Target(s)).
3980 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
3981 if (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
)
3984 if (accept_own_found
&&
3986 bgp
->vpn_policy
[afi
]
3987 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
],
3988 bgp_attr_get_ecommunity(attr
))) {
3989 if (bgp_debug_update(peer
, prefix
, NULL
, 1))
3991 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3994 /* Treat this route as imported, because it's leaked
3995 * already from another VRF, and we got an updated
3996 * version from route-reflector with ACCEPT_OWN
3999 *sub_type
= BGP_ROUTE_IMPORTED
;
4008 void bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4009 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4010 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4011 uint32_t num_labels
, int soft_reconfig
,
4012 struct bgp_route_evpn
*evpn
)
4015 int aspath_loop_count
= 0;
4016 struct bgp_dest
*dest
;
4018 struct attr new_attr
;
4019 struct attr
*attr_new
;
4020 struct bgp_path_info
*pi
;
4021 struct bgp_path_info
*new = NULL
;
4022 struct bgp_path_info_extra
*extra
;
4024 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4026 int do_loop_check
= 1;
4027 int has_valid_label
= 0;
4029 bool force_evpn_import
= false;
4030 safi_t orig_safi
= safi
;
4031 bool leak_success
= true;
4034 if (frrtrace_enabled(frr_bgp
, process_update
)) {
4035 char pfxprint
[PREFIX2STR_BUFFER
];
4037 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
4038 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
4042 #ifdef ENABLE_BGP_VNC
4043 int vnc_implicit_withdraw
= 0;
4046 const struct prefix
*bgp_nht_param_prefix
;
4048 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4049 if (orig_safi
== SAFI_LABELED_UNICAST
)
4050 safi
= SAFI_UNICAST
;
4052 memset(&new_attr
, 0, sizeof(new_attr
));
4053 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
4054 new_attr
.label
= MPLS_INVALID_LABEL
;
4057 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4058 /* TODO: Check to see if we can get rid of "is_valid_label" */
4059 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
4060 has_valid_label
= (num_labels
> 0) ? 1 : 0;
4062 has_valid_label
= bgp_is_valid_label(label
);
4064 if (has_valid_label
)
4065 assert(label
!= NULL
);
4067 /* Update overlay index of the attribute */
4068 if (afi
== AFI_L2VPN
&& evpn
)
4069 memcpy(&attr
->evpn_overlay
, evpn
,
4070 sizeof(struct bgp_route_evpn
));
4072 /* When peer's soft reconfiguration enabled. Record input packet in
4075 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4076 && peer
!= bgp
->peer_self
)
4077 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
4079 /* Update permitted loop count */
4080 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN
))
4081 allowas_in
= peer
->allowas_in
[afi
][safi
];
4083 /* Check previously received route. */
4084 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4085 if (pi
->peer
== peer
&& pi
->type
== type
4086 && pi
->sub_type
== sub_type
4087 && pi
->addpath_rx_id
== addpath_id
)
4090 /* AS path local-as loop check. */
4091 if (peer
->change_local_as
) {
4093 aspath_loop_count
= allowas_in
;
4094 else if (!CHECK_FLAG(peer
->flags
,
4095 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
4096 aspath_loop_count
= 1;
4098 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
4099 > aspath_loop_count
) {
4100 peer
->stat_pfx_aspath_loop
++;
4101 reason
= "as-path contains our own AS;";
4106 /* If the peer is configured for "allowas-in origin" and the last ASN in
4108 * as-path is our ASN then we do not need to call aspath_loop_check
4110 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
4111 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
4114 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_REFLECTOR_CLIENT
))
4115 bgp_nht_param_prefix
= NULL
;
4117 bgp_nht_param_prefix
= p
;
4119 /* AS path loop check. */
4120 if (do_loop_check
) {
4121 if (aspath_loop_check(attr
->aspath
, bgp
->as
) >
4122 peer
->allowas_in
[afi
][safi
]) {
4123 peer
->stat_pfx_aspath_loop
++;
4124 reason
= "as-path contains our own AS;";
4129 /* If we're a CONFED we need to loop check the CONFED ID too */
4130 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
) && do_loop_check
)
4131 if (aspath_loop_check_confed(attr
->aspath
, bgp
->confed_id
) >
4132 peer
->allowas_in
[afi
][safi
]) {
4133 peer
->stat_pfx_aspath_loop
++;
4134 reason
= "as-path contains our own confed AS;";
4138 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4139 * enabled, then take care of that too.
4141 bool accept_own
= false;
4143 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
4144 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
4146 bgp_accept_own(peer
, afi
, safi
, attr
, p
, &sub_type
);
4148 peer
->stat_pfx_originator_loop
++;
4149 reason
= "originator is us;";
4154 /* Route reflector cluster ID check. */
4155 if (bgp_cluster_filter(peer
, attr
)) {
4156 peer
->stat_pfx_cluster_loop
++;
4157 reason
= "reflected from the same cluster;";
4161 /* Apply incoming filter. */
4162 if (bgp_input_filter(peer
, p
, attr
, afi
, orig_safi
) == FILTER_DENY
) {
4163 peer
->stat_pfx_filter
++;
4168 /* RFC 8212 to prevent route leaks.
4169 * This specification intends to improve this situation by requiring the
4170 * explicit configuration of both BGP Import and Export Policies for any
4171 * External BGP (EBGP) session such as customers, peers, or
4172 * confederation boundaries for all enabled address families. Through
4173 * codification of the aforementioned requirement, operators will
4174 * benefit from consistent behavior across different BGP
4177 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
4178 if (!bgp_inbound_policy_exists(peer
,
4179 &peer
->filter
[afi
][safi
])) {
4180 reason
= "inbound policy missing";
4181 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
4182 NULL
) > FIFTEENMINUTE2USEC
||
4183 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
4185 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4186 monotime(&bgp
->ebgprequirespolicywarning
);
4191 /* draft-ietf-idr-deprecate-as-set-confed-set
4192 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4193 * Eventually, This document (if approved) updates RFC 4271
4194 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4195 * and obsoletes RFC 6472.
4197 if (peer
->bgp
->reject_as_sets
)
4198 if (aspath_check_as_sets(attr
->aspath
)) {
4200 "as-path contains AS_SET or AS_CONFED_SET type;";
4206 /* Apply incoming route-map.
4207 * NB: new_attr may now contain newly allocated values from route-map
4209 * commands, so we need bgp_attr_flush in the error paths, until we
4211 * the attr (which takes over the memory references) */
4212 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, orig_safi
, NULL
, label
,
4215 peer
->stat_pfx_filter
++;
4216 reason
= "route-map;";
4217 bgp_attr_flush(&new_attr
);
4221 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
4222 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
4223 /* remove from RIB previous entry */
4224 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
4227 if (peer
->sort
== BGP_PEER_EBGP
) {
4230 * A BGP speaker receiving an announcement tagged with the
4231 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4232 * NO_EXPORT community as defined in RFC1997, or a
4233 * similar community, to prevent propagation of the
4234 * prefix outside the local AS. The community to prevent
4235 * propagation SHOULD be chosen according to the operator's
4238 if (bgp_attr_get_community(&new_attr
) &&
4239 community_include(bgp_attr_get_community(&new_attr
),
4240 COMMUNITY_BLACKHOLE
))
4241 bgp_attr_add_no_export_community(&new_attr
);
4243 /* If we receive the graceful-shutdown community from an eBGP
4244 * peer we must lower local-preference */
4245 if (bgp_attr_get_community(&new_attr
) &&
4246 community_include(bgp_attr_get_community(&new_attr
),
4248 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
4249 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
4251 /* If graceful-shutdown is configured globally or
4252 * per neighbor, then add the GSHUT community to
4253 * all paths received from eBGP peers. */
4254 } else if (bgp_in_graceful_shutdown(peer
->bgp
) ||
4255 CHECK_FLAG(peer
->flags
, PEER_FLAG_GRACEFUL_SHUTDOWN
))
4256 bgp_attr_add_gshut_community(&new_attr
);
4259 /* next hop check. */
4260 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
) &&
4261 bgp_update_martian_nexthop(bgp
, afi
, safi
, type
, sub_type
,
4263 peer
->stat_pfx_nh_invalid
++;
4264 reason
= "martian or self next-hop;";
4265 bgp_attr_flush(&new_attr
);
4269 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
4270 peer
->stat_pfx_nh_invalid
++;
4271 reason
= "self mac;";
4272 bgp_attr_flush(&new_attr
);
4276 if (bgp_check_role_applicability(afi
, safi
) &&
4277 bgp_otc_filter(peer
, &new_attr
)) {
4278 reason
= "failing otc validation";
4279 bgp_attr_flush(&new_attr
);
4283 /* If neighbor soo is configured, tag all incoming routes with
4284 * this SoO tag and then filter out advertisements in
4285 * subgroup_announce_check() if it matches the configured SoO
4286 * on the other peer.
4288 if (peer
->soo
[afi
][safi
]) {
4289 struct ecommunity
*old_ecomm
=
4290 bgp_attr_get_ecommunity(&new_attr
);
4291 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
4292 struct ecommunity
*new_ecomm
;
4295 new_ecomm
= ecommunity_merge(ecommunity_dup(old_ecomm
),
4298 if (!old_ecomm
->refcnt
)
4299 ecommunity_free(&old_ecomm
);
4301 new_ecomm
= ecommunity_dup(ecomm_soo
);
4304 bgp_attr_set_ecommunity(&new_attr
, new_ecomm
);
4307 attr_new
= bgp_attr_intern(&new_attr
);
4309 /* If the update is implicit withdraw. */
4311 pi
->uptime
= monotime(NULL
);
4312 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
4314 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4316 /* Same attribute comes in. */
4317 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4319 && (!has_valid_label
4320 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
4321 num_labels
* sizeof(mpls_label_t
))
4323 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4324 BGP_CONFIG_DAMPENING
)
4325 && peer
->sort
== BGP_PEER_EBGP
4326 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4327 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4328 bgp_debug_rdpfxpath2str(
4329 afi
, safi
, prd
, p
, label
,
4330 num_labels
, addpath_id
? 1 : 0,
4331 addpath_id
, evpn
, pfx_buf
,
4333 zlog_debug("%pBP rcvd %s", peer
,
4337 if (bgp_damp_update(pi
, dest
, afi
, safi
)
4338 != BGP_DAMP_SUPPRESSED
) {
4339 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
4341 bgp_process(bgp
, dest
, afi
, safi
);
4343 } else /* Duplicate - odd */
4345 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4346 if (!peer
->rcvd_attr_printed
) {
4348 "%pBP rcvd UPDATE w/ attr: %s",
4350 peer
->rcvd_attr_str
);
4351 peer
->rcvd_attr_printed
= 1;
4354 bgp_debug_rdpfxpath2str(
4355 afi
, safi
, prd
, p
, label
,
4356 num_labels
, addpath_id
? 1 : 0,
4357 addpath_id
, evpn
, pfx_buf
,
4360 "%pBP rcvd %s...duplicate ignored",
4364 /* graceful restart STALE flag unset. */
4365 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4366 bgp_path_info_unset_flag(
4367 dest
, pi
, BGP_PATH_STALE
);
4368 bgp_dest_set_defer_flag(dest
, false);
4369 bgp_process(bgp
, dest
, afi
, safi
);
4373 bgp_dest_unlock_node(dest
);
4374 bgp_attr_unintern(&attr_new
);
4379 /* Withdraw/Announce before we fully processed the withdraw */
4380 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4381 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4382 bgp_debug_rdpfxpath2str(
4383 afi
, safi
, prd
, p
, label
, num_labels
,
4384 addpath_id
? 1 : 0, addpath_id
, evpn
,
4385 pfx_buf
, sizeof(pfx_buf
));
4387 "%pBP rcvd %s, flapped quicker than processing",
4391 bgp_path_info_restore(dest
, pi
);
4394 * If the BGP_PATH_REMOVED flag is set, then EVPN
4395 * routes would have been unimported already when a
4396 * prior BGP withdraw processing happened. Such routes
4397 * need to be imported again, so flag accordingly.
4399 force_evpn_import
= true;
4401 /* implicit withdraw, decrement aggregate and pcount
4402 * here. only if update is accepted, they'll increment
4405 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4408 /* Received Logging. */
4409 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4410 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
4411 num_labels
, addpath_id
? 1 : 0,
4412 addpath_id
, evpn
, pfx_buf
,
4414 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4417 /* graceful restart STALE flag unset. */
4418 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4419 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
4420 bgp_dest_set_defer_flag(dest
, false);
4423 /* The attribute is changed. */
4424 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
4426 /* Update bgp route dampening information. */
4427 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4428 && peer
->sort
== BGP_PEER_EBGP
) {
4429 /* This is implicit withdraw so we should update
4432 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
4433 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
4435 #ifdef ENABLE_BGP_VNC
4436 if (safi
== SAFI_MPLS_VPN
) {
4437 struct bgp_dest
*pdest
= NULL
;
4438 struct bgp_table
*table
= NULL
;
4440 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4441 (struct prefix
*)prd
);
4442 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4443 table
= bgp_dest_get_bgp_table_info(pdest
);
4445 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
4446 bgp
, prd
, table
, p
, pi
);
4448 bgp_dest_unlock_node(pdest
);
4450 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4451 && (safi
== SAFI_UNICAST
)) {
4452 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4454 * Implicit withdraw case.
4456 ++vnc_implicit_withdraw
;
4457 vnc_import_bgp_del_route(bgp
, p
, pi
);
4458 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
4463 /* Special handling for EVPN update of an existing route. If the
4464 * extended community attribute has changed, we need to
4466 * the route using its existing extended community. It will be
4467 * subsequently processed for import with the new extended
4470 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
4473 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
4475 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4478 cmp
= ecommunity_cmp(
4479 bgp_attr_get_ecommunity(pi
->attr
),
4480 bgp_attr_get_ecommunity(attr_new
));
4482 if (bgp_debug_update(peer
, p
, NULL
, 1))
4484 "Change in EXT-COMM, existing %s new %s",
4486 bgp_attr_get_ecommunity(
4489 bgp_attr_get_ecommunity(
4491 if (safi
== SAFI_EVPN
)
4492 bgp_evpn_unimport_route(
4493 bgp
, afi
, safi
, p
, pi
);
4494 else /* SAFI_MPLS_VPN */
4495 vpn_leak_to_vrf_withdraw(pi
);
4500 /* Update to new attribute. */
4501 bgp_attr_unintern(&pi
->attr
);
4502 pi
->attr
= attr_new
;
4504 /* Update MPLS label */
4505 if (has_valid_label
) {
4506 extra
= bgp_path_info_extra_get(pi
);
4507 if (extra
->label
!= label
) {
4508 memcpy(&extra
->label
, label
,
4509 num_labels
* sizeof(mpls_label_t
));
4510 extra
->num_labels
= num_labels
;
4512 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4513 bgp_set_valid_label(&extra
->label
[0]);
4516 /* Update SRv6 SID */
4517 if (attr
->srv6_l3vpn
) {
4518 extra
= bgp_path_info_extra_get(pi
);
4519 if (sid_diff(&extra
->sid
[0].sid
,
4520 &attr
->srv6_l3vpn
->sid
)) {
4521 sid_copy(&extra
->sid
[0].sid
,
4522 &attr
->srv6_l3vpn
->sid
);
4523 extra
->num_sids
= 1;
4525 extra
->sid
[0].loc_block_len
= 0;
4526 extra
->sid
[0].loc_node_len
= 0;
4527 extra
->sid
[0].func_len
= 0;
4528 extra
->sid
[0].arg_len
= 0;
4529 extra
->sid
[0].transposition_len
= 0;
4530 extra
->sid
[0].transposition_offset
= 0;
4532 if (attr
->srv6_l3vpn
->loc_block_len
!= 0) {
4533 extra
->sid
[0].loc_block_len
=
4534 attr
->srv6_l3vpn
->loc_block_len
;
4535 extra
->sid
[0].loc_node_len
=
4536 attr
->srv6_l3vpn
->loc_node_len
;
4537 extra
->sid
[0].func_len
=
4538 attr
->srv6_l3vpn
->func_len
;
4539 extra
->sid
[0].arg_len
=
4540 attr
->srv6_l3vpn
->arg_len
;
4541 extra
->sid
[0].transposition_len
=
4543 ->transposition_len
;
4544 extra
->sid
[0].transposition_offset
=
4546 ->transposition_offset
;
4549 } else if (attr
->srv6_vpn
) {
4550 extra
= bgp_path_info_extra_get(pi
);
4551 if (sid_diff(&extra
->sid
[0].sid
,
4552 &attr
->srv6_vpn
->sid
)) {
4553 sid_copy(&extra
->sid
[0].sid
,
4554 &attr
->srv6_vpn
->sid
);
4555 extra
->num_sids
= 1;
4559 #ifdef ENABLE_BGP_VNC
4560 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4561 && (safi
== SAFI_UNICAST
)) {
4562 if (vnc_implicit_withdraw
) {
4564 * Add back the route with its new attributes
4566 * The route is still selected, until the route
4568 * queued by bgp_process actually runs. We have
4570 * update to the VNC side immediately to avoid
4572 * configuration changes (e.g., route-map
4574 * trigger re-importation of the entire RIB.
4576 vnc_import_bgp_add_route(bgp
, p
, pi
);
4577 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4582 /* Update bgp route dampening information. */
4583 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4584 && peer
->sort
== BGP_PEER_EBGP
) {
4585 /* Now we do normal update dampening. */
4586 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4587 if (ret
== BGP_DAMP_SUPPRESSED
) {
4588 bgp_dest_unlock_node(dest
);
4593 /* Nexthop reachability check - for unicast and
4594 * labeled-unicast.. */
4595 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4596 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4597 || (safi
== SAFI_EVPN
&&
4598 bgp_evpn_is_prefix_nht_supported(p
))) {
4599 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4600 && peer
->ttl
== BGP_DEFAULT_TTL
4601 && !CHECK_FLAG(peer
->flags
,
4602 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4603 && !CHECK_FLAG(bgp
->flags
,
4604 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4609 struct bgp
*bgp_nexthop
= bgp
;
4611 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4612 bgp_nexthop
= pi
->extra
->bgp_orig
;
4614 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4616 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4617 safi
, pi
, NULL
, connected
,
4618 bgp_nht_param_prefix
) ||
4619 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4620 bgp_path_info_set_flag(dest
, pi
,
4623 if (BGP_DEBUG(nht
, NHT
)) {
4624 zlog_debug("%s(%pI4): NH unresolved",
4626 (in_addr_t
*)&attr_new
->nexthop
);
4628 bgp_path_info_unset_flag(dest
, pi
,
4633 bgp_path_info_set_flag(dest
, pi
,
4634 BGP_PATH_ACCEPT_OWN
);
4636 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4639 #ifdef ENABLE_BGP_VNC
4640 if (safi
== SAFI_MPLS_VPN
) {
4641 struct bgp_dest
*pdest
= NULL
;
4642 struct bgp_table
*table
= NULL
;
4644 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4645 (struct prefix
*)prd
);
4646 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4647 table
= bgp_dest_get_bgp_table_info(pdest
);
4649 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4650 bgp
, prd
, table
, p
, pi
);
4652 bgp_dest_unlock_node(pdest
);
4656 /* If this is an EVPN route and some attribute has changed,
4657 * or we are explicitly told to perform a route import, process
4658 * route for import. If the extended community has changed, we
4660 * have done the un-import earlier and the import would result
4662 * route getting injected into appropriate L2 VNIs. If it is
4664 * some other attribute change, the import will result in
4666 * the attributes for the route in the VNI(s).
4668 if (safi
== SAFI_EVPN
&&
4669 (!same_attr
|| force_evpn_import
) &&
4670 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4671 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4673 /* Process change. */
4674 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4676 bgp_process(bgp
, dest
, afi
, safi
);
4677 bgp_dest_unlock_node(dest
);
4679 if (SAFI_UNICAST
== safi
4680 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4681 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4683 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4685 if ((SAFI_MPLS_VPN
== safi
)
4686 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4687 leak_success
= vpn_leak_to_vrf_update(bgp
, pi
, prd
);
4690 #ifdef ENABLE_BGP_VNC
4691 if (SAFI_MPLS_VPN
== safi
) {
4692 mpls_label_t label_decoded
= decode_label(label
);
4694 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4695 type
, sub_type
, &label_decoded
);
4697 if (SAFI_ENCAP
== safi
) {
4698 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4699 type
, sub_type
, NULL
);
4702 if ((safi
== SAFI_MPLS_VPN
) &&
4703 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4704 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4706 bgp_unlink_nexthop(pi
);
4707 bgp_path_info_delete(dest
, pi
);
4710 } // End of implicit withdraw
4712 /* Received Logging. */
4713 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4714 if (!peer
->rcvd_attr_printed
) {
4715 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4716 peer
->rcvd_attr_str
);
4717 peer
->rcvd_attr_printed
= 1;
4720 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4721 addpath_id
? 1 : 0, addpath_id
, evpn
,
4722 pfx_buf
, sizeof(pfx_buf
));
4723 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4726 /* Make new BGP info. */
4727 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4729 /* Update MPLS label */
4730 if (has_valid_label
) {
4731 extra
= bgp_path_info_extra_get(new);
4732 if (extra
->label
!= label
) {
4733 memcpy(&extra
->label
, label
,
4734 num_labels
* sizeof(mpls_label_t
));
4735 extra
->num_labels
= num_labels
;
4737 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4738 bgp_set_valid_label(&extra
->label
[0]);
4741 /* Update SRv6 SID */
4742 if (safi
== SAFI_MPLS_VPN
) {
4743 extra
= bgp_path_info_extra_get(new);
4744 if (attr
->srv6_l3vpn
) {
4745 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_l3vpn
->sid
);
4746 extra
->num_sids
= 1;
4748 extra
->sid
[0].loc_block_len
=
4749 attr
->srv6_l3vpn
->loc_block_len
;
4750 extra
->sid
[0].loc_node_len
=
4751 attr
->srv6_l3vpn
->loc_node_len
;
4752 extra
->sid
[0].func_len
= attr
->srv6_l3vpn
->func_len
;
4753 extra
->sid
[0].arg_len
= attr
->srv6_l3vpn
->arg_len
;
4754 extra
->sid
[0].transposition_len
=
4755 attr
->srv6_l3vpn
->transposition_len
;
4756 extra
->sid
[0].transposition_offset
=
4757 attr
->srv6_l3vpn
->transposition_offset
;
4758 } else if (attr
->srv6_vpn
) {
4759 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_vpn
->sid
);
4760 extra
->num_sids
= 1;
4764 /* Nexthop reachability check. */
4765 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4766 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4767 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4768 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4769 && peer
->ttl
== BGP_DEFAULT_TTL
4770 && !CHECK_FLAG(peer
->flags
,
4771 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4772 && !CHECK_FLAG(bgp
->flags
,
4773 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4778 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4780 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4781 connected
, bgp_nht_param_prefix
) ||
4782 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4783 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4785 if (BGP_DEBUG(nht
, NHT
))
4786 zlog_debug("%s(%pI4): NH unresolved", __func__
,
4787 &attr_new
->nexthop
);
4788 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4792 bgp_path_info_set_flag(dest
, new, BGP_PATH_ACCEPT_OWN
);
4794 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4797 /* If maximum prefix count is configured and current prefix
4800 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0)) {
4801 reason
= "maximum-prefix overflow";
4802 bgp_attr_flush(&new_attr
);
4807 new->addpath_rx_id
= addpath_id
;
4809 /* Increment prefix */
4810 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4812 /* Register new BGP information. */
4813 bgp_path_info_add(dest
, new);
4815 /* route_node_get lock */
4816 bgp_dest_unlock_node(dest
);
4818 #ifdef ENABLE_BGP_VNC
4819 if (safi
== SAFI_MPLS_VPN
) {
4820 struct bgp_dest
*pdest
= NULL
;
4821 struct bgp_table
*table
= NULL
;
4823 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4824 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4825 table
= bgp_dest_get_bgp_table_info(pdest
);
4827 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4828 bgp
, prd
, table
, p
, new);
4830 bgp_dest_unlock_node(pdest
);
4834 /* If this is an EVPN route, process for import. */
4835 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4836 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4838 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4840 /* Process change. */
4841 bgp_process(bgp
, dest
, afi
, safi
);
4843 if (SAFI_UNICAST
== safi
4844 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4845 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4846 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4848 if ((SAFI_MPLS_VPN
== safi
)
4849 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4850 leak_success
= vpn_leak_to_vrf_update(bgp
, new, prd
);
4852 #ifdef ENABLE_BGP_VNC
4853 if (SAFI_MPLS_VPN
== safi
) {
4854 mpls_label_t label_decoded
= decode_label(label
);
4856 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4857 sub_type
, &label_decoded
);
4859 if (SAFI_ENCAP
== safi
) {
4860 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4864 if ((safi
== SAFI_MPLS_VPN
) &&
4865 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4866 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4868 bgp_unlink_nexthop(new);
4869 bgp_path_info_delete(dest
, new);
4874 /* This BGP update is filtered. Log the reason then update BGP
4878 bgp_unlink_nexthop(new);
4879 bgp_path_info_delete(dest
, new);
4880 bgp_path_info_extra_free(&new->extra
);
4881 XFREE(MTYPE_BGP_ROUTE
, new);
4884 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4886 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4887 if (!peer
->rcvd_attr_printed
) {
4888 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4889 peer
->rcvd_attr_str
);
4890 peer
->rcvd_attr_printed
= 1;
4893 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4894 addpath_id
? 1 : 0, addpath_id
, evpn
,
4895 pfx_buf
, sizeof(pfx_buf
));
4896 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4897 peer
, pfx_buf
, reason
);
4901 /* If this is an EVPN route, un-import it as it is now filtered.
4903 if (safi
== SAFI_EVPN
)
4904 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4906 if (SAFI_UNICAST
== safi
4907 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4908 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4910 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4912 if ((SAFI_MPLS_VPN
== safi
)
4913 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4915 vpn_leak_to_vrf_withdraw(pi
);
4918 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4921 bgp_dest_unlock_node(dest
);
4923 #ifdef ENABLE_BGP_VNC
4925 * Filtered update is treated as an implicit withdrawal (see
4927 * a few lines above)
4929 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4930 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4938 void bgp_withdraw(struct peer
*peer
, const struct prefix
*p
,
4939 uint32_t addpath_id
, afi_t afi
, safi_t safi
, int type
,
4940 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4941 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4944 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4945 struct bgp_dest
*dest
;
4946 struct bgp_path_info
*pi
;
4948 #ifdef ENABLE_BGP_VNC
4949 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4950 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4958 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4960 /* If peer is soft reconfiguration enabled. Record input packet for
4961 * further calculation.
4963 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4964 * routes that are filtered. This tanks out Quagga RS pretty badly due
4966 * the iteration over all RS clients.
4967 * Since we need to remove the entry from adj_in anyway, do that first
4969 * if there was no entry, we don't need to do anything more.
4971 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4972 && peer
!= bgp
->peer_self
)
4973 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4974 peer
->stat_pfx_dup_withdraw
++;
4976 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4977 bgp_debug_rdpfxpath2str(
4978 afi
, safi
, prd
, p
, label
, num_labels
,
4979 addpath_id
? 1 : 0, addpath_id
, NULL
,
4980 pfx_buf
, sizeof(pfx_buf
));
4982 "%s withdrawing route %s not in adj-in",
4983 peer
->host
, pfx_buf
);
4985 bgp_dest_unlock_node(dest
);
4989 /* Lookup withdrawn route. */
4990 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4991 if (pi
->peer
== peer
&& pi
->type
== type
4992 && pi
->sub_type
== sub_type
4993 && pi
->addpath_rx_id
== addpath_id
)
4997 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4998 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4999 addpath_id
? 1 : 0, addpath_id
, NULL
,
5000 pfx_buf
, sizeof(pfx_buf
));
5001 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer
,
5005 /* Withdraw specified route from routing table. */
5006 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
5007 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
5008 if (SAFI_UNICAST
== safi
5009 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5010 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5011 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5013 if ((SAFI_MPLS_VPN
== safi
)
5014 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5016 vpn_leak_to_vrf_withdraw(pi
);
5018 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
5019 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
5020 addpath_id
? 1 : 0, addpath_id
, NULL
,
5021 pfx_buf
, sizeof(pfx_buf
));
5022 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
5025 /* Unlock bgp_node_get() lock. */
5026 bgp_dest_unlock_node(dest
);
5031 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
5034 struct update_subgroup
*subgrp
;
5035 subgrp
= peer_subgroup(peer
, afi
, safi
);
5036 subgroup_default_originate(subgrp
, withdraw
);
5041 * bgp_stop_announce_route_timer
5043 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
5045 if (!paf
->t_announce_route
)
5048 EVENT_OFF(paf
->t_announce_route
);
5052 * bgp_announce_route_timer_expired
5054 * Callback that is invoked when the route announcement timer for a
5057 static void bgp_announce_route_timer_expired(struct event
*t
)
5059 struct peer_af
*paf
;
5065 if (!peer_established(peer
))
5068 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
5071 peer_af_announce_route(paf
, 1);
5073 /* Notify BGP conditional advertisement scanner percess */
5074 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
5078 * bgp_announce_route
5080 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
5082 * if force is true we will force an update even if the update
5083 * limiting code is attempted to kick in.
5085 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
, bool force
)
5087 struct peer_af
*paf
;
5088 struct update_subgroup
*subgrp
;
5090 paf
= peer_af_find(peer
, afi
, safi
);
5093 subgrp
= PAF_SUBGRP(paf
);
5096 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5097 * or a refresh has already been triggered.
5099 if (!subgrp
|| paf
->t_announce_route
)
5103 SET_FLAG(subgrp
->sflags
, SUBGRP_STATUS_FORCE_UPDATES
);
5106 * Start a timer to stagger/delay the announce. This serves
5107 * two purposes - announcement can potentially be combined for
5108 * multiple peers and the announcement doesn't happen in the
5111 event_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
5112 (subgrp
->peer_count
== 1)
5113 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5114 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
5115 &paf
->t_announce_route
);
5119 * Announce routes from all AF tables to a peer.
5121 * This should ONLY be called when there is a need to refresh the
5122 * routes to the peer based on a policy change for this peer alone
5123 * or a route refresh request received from the peer.
5124 * The operation will result in splitting the peer from its existing
5125 * subgroups and putting it in new subgroups.
5127 void bgp_announce_route_all(struct peer
*peer
)
5132 FOREACH_AFI_SAFI (afi
, safi
)
5133 bgp_announce_route(peer
, afi
, safi
, false);
5136 /* Flag or unflag bgp_dest to determine whether it should be treated by
5137 * bgp_soft_reconfig_table_task.
5138 * Flag if flag is true. Unflag if flag is false.
5140 static void bgp_soft_reconfig_table_flag(struct bgp_table
*table
, bool flag
)
5142 struct bgp_dest
*dest
;
5143 struct bgp_adj_in
*ain
;
5148 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5149 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5150 if (ain
->peer
!= NULL
)
5153 if (flag
&& ain
!= NULL
&& ain
->peer
!= NULL
)
5154 SET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5156 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5160 static void bgp_soft_reconfig_table_update(struct peer
*peer
,
5161 struct bgp_dest
*dest
,
5162 struct bgp_adj_in
*ain
, afi_t afi
,
5163 safi_t safi
, struct prefix_rd
*prd
)
5165 struct bgp_path_info
*pi
;
5166 uint32_t num_labels
= 0;
5167 mpls_label_t
*label_pnt
= NULL
;
5168 struct bgp_route_evpn evpn
;
5170 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5171 if (pi
->peer
== peer
)
5174 if (pi
&& pi
->extra
)
5175 num_labels
= pi
->extra
->num_labels
;
5177 label_pnt
= &pi
->extra
->label
[0];
5179 memcpy(&evpn
, bgp_attr_get_evpn_overlay(pi
->attr
),
5182 memset(&evpn
, 0, sizeof(evpn
));
5184 bgp_update(peer
, bgp_dest_get_prefix(dest
), ain
->addpath_rx_id
,
5185 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, prd
,
5186 label_pnt
, num_labels
, 1, &evpn
);
5189 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5190 struct bgp_table
*table
,
5191 struct prefix_rd
*prd
)
5193 struct bgp_dest
*dest
;
5194 struct bgp_adj_in
*ain
;
5197 table
= peer
->bgp
->rib
[afi
][safi
];
5199 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5200 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5201 if (ain
->peer
!= peer
)
5204 bgp_soft_reconfig_table_update(peer
, dest
, ain
, afi
,
5209 /* Do soft reconfig table per bgp table.
5210 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5211 * when BGP_NODE_SOFT_RECONFIG is set,
5212 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5213 * Schedule a new thread to continue the job.
5214 * Without splitting the full job into several part,
5215 * vtysh waits for the job to finish before responding to a BGP command
5217 static void bgp_soft_reconfig_table_task(struct event
*thread
)
5219 uint32_t iter
, max_iter
;
5220 struct bgp_dest
*dest
;
5221 struct bgp_adj_in
*ain
;
5223 struct bgp_table
*table
;
5224 struct prefix_rd
*prd
;
5225 struct listnode
*node
, *nnode
;
5227 table
= EVENT_ARG(thread
);
5230 max_iter
= SOFT_RECONFIG_TASK_MAX_PREFIX
;
5231 if (table
->soft_reconfig_init
) {
5232 /* first call of the function with a new srta structure.
5233 * Don't do any treatment this time on nodes
5234 * in order vtysh to respond quickly
5239 for (iter
= 0, dest
= bgp_table_top(table
); (dest
&& iter
< max_iter
);
5240 dest
= bgp_route_next(dest
)) {
5241 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
))
5244 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5246 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5247 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
,
5249 if (ain
->peer
!= peer
)
5252 bgp_soft_reconfig_table_update(
5253 peer
, dest
, ain
, table
->afi
,
5260 /* we're either starting the initial iteration,
5261 * or we're going to continue an ongoing iteration
5263 if (dest
|| table
->soft_reconfig_init
) {
5264 table
->soft_reconfig_init
= false;
5265 event_add_event(bm
->master
, bgp_soft_reconfig_table_task
, table
,
5266 0, &table
->soft_reconfig_thread
);
5269 /* we're done, clean up the background iteration context info and
5270 schedule route annoucement
5272 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
, peer
)) {
5273 listnode_delete(table
->soft_reconfig_peers
, peer
);
5274 bgp_announce_route(peer
, table
->afi
, table
->safi
, false);
5277 list_delete(&table
->soft_reconfig_peers
);
5281 /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5283 * - bgp cannot be NULL
5284 * - if table and peer are NULL, cancel all threads within the bgp instance
5285 * - if table is NULL and peer is not,
5286 * remove peer in all threads within the bgp instance
5287 * - if peer is NULL, cancel all threads matching table within the bgp instance
5289 void bgp_soft_reconfig_table_task_cancel(const struct bgp
*bgp
,
5290 const struct bgp_table
*table
,
5291 const struct peer
*peer
)
5294 struct listnode
*node
, *nnode
;
5296 struct bgp_table
*ntable
;
5301 FOREACH_AFI_SAFI (afi
, safi
) {
5302 ntable
= bgp
->rib
[afi
][safi
];
5305 if (table
&& table
!= ntable
)
5308 for (ALL_LIST_ELEMENTS(ntable
->soft_reconfig_peers
, node
, nnode
,
5310 if (peer
&& peer
!= npeer
)
5312 listnode_delete(ntable
->soft_reconfig_peers
, npeer
);
5315 if (!ntable
->soft_reconfig_peers
5316 || !list_isempty(ntable
->soft_reconfig_peers
))
5319 list_delete(&ntable
->soft_reconfig_peers
);
5320 bgp_soft_reconfig_table_flag(ntable
, false);
5321 EVENT_OFF(ntable
->soft_reconfig_thread
);
5326 * Returns false if the peer is not configured for soft reconfig in
5328 bool bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5330 struct bgp_dest
*dest
;
5331 struct bgp_table
*table
;
5332 struct listnode
*node
, *nnode
;
5334 struct peer_af
*paf
;
5336 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
))
5339 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
5340 && (safi
!= SAFI_EVPN
)) {
5341 table
= peer
->bgp
->rib
[afi
][safi
];
5345 table
->soft_reconfig_init
= true;
5347 if (!table
->soft_reconfig_peers
)
5348 table
->soft_reconfig_peers
= list_new();
5350 /* add peer to the table soft_reconfig_peers if not already
5353 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
,
5359 listnode_add(table
->soft_reconfig_peers
, peer
);
5361 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5362 * on table would start back at the beginning.
5364 bgp_soft_reconfig_table_flag(table
, true);
5366 if (!table
->soft_reconfig_thread
)
5367 event_add_event(bm
->master
,
5368 bgp_soft_reconfig_table_task
, table
, 0,
5369 &table
->soft_reconfig_thread
);
5370 /* Cancel bgp_announce_route_timer_expired threads.
5371 * bgp_announce_route_timer_expired threads have been scheduled
5372 * to announce routes as soon as the soft_reconfigure process
5374 * In this case, soft_reconfigure is also scheduled by using
5375 * a thread but is planned after the
5376 * bgp_announce_route_timer_expired threads. It means that,
5377 * without cancelling the threads, the route announcement task
5378 * would run before the soft reconfiguration one. That would
5379 * useless and would block vtysh during several seconds. Route
5380 * announcements are rescheduled as soon as the soft_reconfigure
5383 paf
= peer_af_find(peer
, afi
, safi
);
5385 bgp_stop_announce_route_timer(paf
);
5387 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5388 dest
= bgp_route_next(dest
)) {
5389 table
= bgp_dest_get_bgp_table_info(dest
);
5394 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5395 struct prefix_rd prd
;
5397 prd
.family
= AF_UNSPEC
;
5399 memcpy(&prd
.val
, p
->u
.val
, 8);
5401 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
5408 struct bgp_clear_node_queue
{
5409 struct bgp_dest
*dest
;
5412 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
5414 struct bgp_clear_node_queue
*cnq
= data
;
5415 struct bgp_dest
*dest
= cnq
->dest
;
5416 struct peer
*peer
= wq
->spec
.data
;
5417 struct bgp_path_info
*pi
;
5419 afi_t afi
= bgp_dest_table(dest
)->afi
;
5420 safi_t safi
= bgp_dest_table(dest
)->safi
;
5422 assert(dest
&& peer
);
5425 /* It is possible that we have multiple paths for a prefix from a peer
5426 * if that peer is using AddPath.
5428 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5429 if (pi
->peer
!= peer
)
5432 /* graceful restart STALE flag set. */
5433 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
5434 && peer
->nsf
[afi
][safi
])
5435 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5436 PEER_STATUS_ENHANCED_REFRESH
))
5437 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5438 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
5439 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
5441 /* If this is an EVPN route, process for
5443 if (safi
== SAFI_EVPN
)
5444 bgp_evpn_unimport_route(
5446 bgp_dest_get_prefix(dest
), pi
);
5447 /* Handle withdraw for VRF route-leaking and L3VPN */
5448 if (SAFI_UNICAST
== safi
5449 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
5450 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5451 vpn_leak_from_vrf_withdraw(bgp_get_default(),
5454 if (SAFI_MPLS_VPN
== safi
&&
5455 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5456 vpn_leak_to_vrf_withdraw(pi
);
5459 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5465 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
5467 struct bgp_clear_node_queue
*cnq
= data
;
5468 struct bgp_dest
*dest
= cnq
->dest
;
5469 struct bgp_table
*table
= bgp_dest_table(dest
);
5471 bgp_dest_unlock_node(dest
);
5472 bgp_table_unlock(table
);
5473 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
5476 static void bgp_clear_node_complete(struct work_queue
*wq
)
5478 struct peer
*peer
= wq
->spec
.data
;
5480 /* Tickle FSM to start moving again */
5481 BGP_EVENT_ADD(peer
, Clearing_Completed
);
5483 peer_unlock(peer
); /* bgp_clear_route */
5486 static void bgp_clear_node_queue_init(struct peer
*peer
)
5488 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5490 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
5491 #undef CLEAR_QUEUE_NAME_LEN
5493 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
5494 peer
->clear_node_queue
->spec
.hold
= 10;
5495 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
5496 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
5497 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
5498 peer
->clear_node_queue
->spec
.max_retries
= 0;
5500 /* we only 'lock' this peer reference when the queue is actually active
5502 peer
->clear_node_queue
->spec
.data
= peer
;
5505 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5506 struct bgp_table
*table
)
5508 struct bgp_dest
*dest
;
5509 int force
= peer
->bgp
->process_queue
? 0 : 1;
5512 table
= peer
->bgp
->rib
[afi
][safi
];
5514 /* If still no table => afi/safi isn't configured at all or smth. */
5518 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5519 struct bgp_path_info
*pi
, *next
;
5520 struct bgp_adj_in
*ain
;
5521 struct bgp_adj_in
*ain_next
;
5523 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5524 * queued for every clearing peer, regardless of whether it is
5525 * relevant to the peer at hand.
5527 * Overview: There are 3 different indices which need to be
5528 * scrubbed, potentially, when a peer is removed:
5530 * 1 peer's routes visible via the RIB (ie accepted routes)
5531 * 2 peer's routes visible by the (optional) peer's adj-in index
5532 * 3 other routes visible by the peer's adj-out index
5534 * 3 there is no hurry in scrubbing, once the struct peer is
5535 * removed from bgp->peer, we could just GC such deleted peer's
5536 * adj-outs at our leisure.
5538 * 1 and 2 must be 'scrubbed' in some way, at least made
5539 * invisible via RIB index before peer session is allowed to be
5540 * brought back up. So one needs to know when such a 'search' is
5545 * - there'd be a single global queue or a single RIB walker
5546 * - rather than tracking which route_nodes still need to be
5547 * examined on a peer basis, we'd track which peers still
5550 * Given that our per-peer prefix-counts now should be reliable,
5551 * this may actually be achievable. It doesn't seem to be a huge
5552 * problem at this time,
5554 * It is possible that we have multiple paths for a prefix from
5556 * if that peer is using AddPath.
5560 ain_next
= ain
->next
;
5562 if (ain
->peer
== peer
)
5563 bgp_adj_in_remove(dest
, ain
);
5568 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5570 if (pi
->peer
!= peer
)
5574 bgp_path_info_reap(dest
, pi
);
5576 struct bgp_clear_node_queue
*cnq
;
5578 /* both unlocked in bgp_clear_node_queue_del */
5579 bgp_table_lock(bgp_dest_table(dest
));
5580 bgp_dest_lock_node(dest
);
5582 MTYPE_BGP_CLEAR_NODE_QUEUE
,
5583 sizeof(struct bgp_clear_node_queue
));
5585 work_queue_add(peer
->clear_node_queue
, cnq
);
5593 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5595 struct bgp_dest
*dest
;
5596 struct bgp_table
*table
;
5598 if (peer
->clear_node_queue
== NULL
)
5599 bgp_clear_node_queue_init(peer
);
5601 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5602 * Idle until it receives a Clearing_Completed event. This protects
5603 * against peers which flap faster than we can we clear, which could
5606 * a) race with routes from the new session being installed before
5607 * clear_route_node visits the node (to delete the route of that
5609 * b) resource exhaustion, clear_route_node likely leads to an entry
5610 * on the process_main queue. Fast-flapping could cause that queue
5614 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5615 * the unlock will happen upon work-queue completion; other wise, the
5616 * unlock happens at the end of this function.
5618 if (!peer
->clear_node_queue
->thread
)
5621 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
5622 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
5624 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5625 dest
= bgp_route_next(dest
)) {
5626 table
= bgp_dest_get_bgp_table_info(dest
);
5630 bgp_clear_route_table(peer
, afi
, safi
, table
);
5633 /* unlock if no nodes got added to the clear-node-queue. */
5634 if (!peer
->clear_node_queue
->thread
)
5638 void bgp_clear_route_all(struct peer
*peer
)
5643 FOREACH_AFI_SAFI (afi
, safi
)
5644 bgp_clear_route(peer
, afi
, safi
);
5646 #ifdef ENABLE_BGP_VNC
5647 rfapiProcessPeerDown(peer
);
5651 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5653 struct bgp_table
*table
;
5654 struct bgp_dest
*dest
;
5655 struct bgp_adj_in
*ain
;
5656 struct bgp_adj_in
*ain_next
;
5658 table
= peer
->bgp
->rib
[afi
][safi
];
5660 /* It is possible that we have multiple paths for a prefix from a peer
5661 * if that peer is using AddPath.
5663 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5667 ain_next
= ain
->next
;
5669 if (ain
->peer
== peer
)
5670 bgp_adj_in_remove(dest
, ain
);
5677 /* If any of the routes from the peer have been marked with the NO_LLGR
5678 * community, either as sent by the peer, or as the result of a configured
5679 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5680 * operation of [RFC4271].
5682 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5684 struct bgp_dest
*dest
;
5685 struct bgp_path_info
*pi
;
5686 struct bgp_table
*table
;
5688 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5689 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5690 dest
= bgp_route_next(dest
)) {
5691 struct bgp_dest
*rm
;
5693 /* look for neighbor in tables */
5694 table
= bgp_dest_get_bgp_table_info(dest
);
5698 for (rm
= bgp_table_top(table
); rm
;
5699 rm
= bgp_route_next(rm
))
5700 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
5702 if (pi
->peer
!= peer
)
5705 peer
->af_sflags
[afi
][safi
],
5706 PEER_STATUS_LLGR_WAIT
) &&
5707 bgp_attr_get_community(pi
->attr
) &&
5709 bgp_attr_get_community(
5713 if (!CHECK_FLAG(pi
->flags
,
5718 * If this is VRF leaked route
5719 * process for withdraw.
5722 BGP_ROUTE_IMPORTED
&&
5723 peer
->bgp
->inst_type
==
5724 BGP_INSTANCE_TYPE_DEFAULT
)
5725 vpn_leak_to_vrf_withdraw(pi
);
5727 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
5732 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5733 dest
= bgp_route_next(dest
))
5734 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5736 if (pi
->peer
!= peer
)
5738 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5739 PEER_STATUS_LLGR_WAIT
) &&
5740 bgp_attr_get_community(pi
->attr
) &&
5742 bgp_attr_get_community(pi
->attr
),
5745 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
5747 if (safi
== SAFI_UNICAST
&&
5748 (peer
->bgp
->inst_type
==
5749 BGP_INSTANCE_TYPE_VRF
||
5750 peer
->bgp
->inst_type
==
5751 BGP_INSTANCE_TYPE_DEFAULT
))
5752 vpn_leak_from_vrf_withdraw(
5753 bgp_get_default(), peer
->bgp
,
5756 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5762 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5764 struct bgp_dest
*dest
, *ndest
;
5765 struct bgp_path_info
*pi
;
5766 struct bgp_table
*table
;
5768 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5769 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5770 dest
= bgp_route_next(dest
)) {
5771 table
= bgp_dest_get_bgp_table_info(dest
);
5775 for (ndest
= bgp_table_top(table
); ndest
;
5776 ndest
= bgp_route_next(ndest
)) {
5777 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5779 if (pi
->peer
!= peer
)
5783 peer
->af_sflags
[afi
][safi
],
5784 PEER_STATUS_ENHANCED_REFRESH
))
5785 && !CHECK_FLAG(pi
->flags
,
5789 BGP_PATH_UNUSEABLE
)) {
5790 if (bgp_debug_neighbor_events(
5793 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5797 bgp_dest_get_prefix(
5800 bgp_path_info_set_flag(
5808 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5809 dest
= bgp_route_next(dest
)) {
5810 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5812 if (pi
->peer
!= peer
)
5815 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5816 PEER_STATUS_ENHANCED_REFRESH
))
5817 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5818 && !CHECK_FLAG(pi
->flags
,
5819 BGP_PATH_UNUSEABLE
)) {
5820 if (bgp_debug_neighbor_events(peer
))
5822 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5825 bgp_dest_get_prefix(
5828 bgp_path_info_set_flag(dest
, pi
,
5836 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5838 if (peer
->sort
== BGP_PEER_IBGP
)
5841 if (peer
->sort
== BGP_PEER_EBGP
5842 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5843 || FILTER_LIST_OUT_NAME(filter
)
5844 || DISTRIBUTE_OUT_NAME(filter
)))
5849 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5851 if (peer
->sort
== BGP_PEER_IBGP
)
5854 if (peer
->sort
== BGP_PEER_EBGP
5855 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5856 || FILTER_LIST_IN_NAME(filter
)
5857 || DISTRIBUTE_IN_NAME(filter
)))
5862 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5865 struct bgp_dest
*dest
;
5866 struct bgp_path_info
*pi
;
5867 struct bgp_path_info
*next
;
5869 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5870 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5871 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5875 /* Unimport EVPN routes from VRFs */
5876 if (safi
== SAFI_EVPN
)
5877 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5880 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5881 && pi
->type
== ZEBRA_ROUTE_BGP
5882 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5883 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5884 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5886 if (bgp_fibupd_safi(safi
))
5887 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5890 bgp_path_info_reap(dest
, pi
);
5894 /* Delete all kernel routes. */
5895 void bgp_cleanup_routes(struct bgp
*bgp
)
5898 struct bgp_dest
*dest
;
5899 struct bgp_table
*table
;
5901 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5902 if (afi
== AFI_L2VPN
)
5904 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5907 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5909 if (afi
!= AFI_L2VPN
) {
5911 safi
= SAFI_MPLS_VPN
;
5912 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5913 dest
= bgp_route_next(dest
)) {
5914 table
= bgp_dest_get_bgp_table_info(dest
);
5915 if (table
!= NULL
) {
5916 bgp_cleanup_table(bgp
, table
, safi
);
5917 bgp_table_finish(&table
);
5918 bgp_dest_set_bgp_table_info(dest
, NULL
);
5919 bgp_dest_unlock_node(dest
);
5923 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5924 dest
= bgp_route_next(dest
)) {
5925 table
= bgp_dest_get_bgp_table_info(dest
);
5926 if (table
!= NULL
) {
5927 bgp_cleanup_table(bgp
, table
, safi
);
5928 bgp_table_finish(&table
);
5929 bgp_dest_set_bgp_table_info(dest
, NULL
);
5930 bgp_dest_unlock_node(dest
);
5935 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5936 dest
= bgp_route_next(dest
)) {
5937 table
= bgp_dest_get_bgp_table_info(dest
);
5938 if (table
!= NULL
) {
5939 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5940 bgp_table_finish(&table
);
5941 bgp_dest_set_bgp_table_info(dest
, NULL
);
5942 bgp_dest_unlock_node(dest
);
5947 void bgp_reset(void)
5950 bgp_zclient_reset();
5951 access_list_reset();
5952 prefix_list_reset();
5955 bool bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5957 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5958 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5959 PEER_CAP_ADDPATH_AF_TX_RCV
));
5962 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5964 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5965 struct bgp_nlri
*packet
)
5973 bool addpath_capable
;
5974 uint32_t addpath_id
;
5977 lim
= pnt
+ packet
->length
;
5979 safi
= packet
->safi
;
5981 addpath_capable
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5983 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5984 syntactic validity. If the field is syntactically incorrect,
5985 then the Error Subcode is set to Invalid Network Field. */
5986 for (; pnt
< lim
; pnt
+= psize
) {
5987 /* Clear prefix structure. */
5988 memset(&p
, 0, sizeof(p
));
5990 if (addpath_capable
) {
5992 /* When packet overflow occurs return immediately. */
5993 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5994 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5996 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5997 addpath_id
= ntohl(addpath_id
);
5998 pnt
+= BGP_ADDPATH_ID_LEN
;
6001 /* Fetch prefix length. */
6002 p
.prefixlen
= *pnt
++;
6003 /* afi/safi validity already verified by caller,
6004 * bgp_update_receive */
6005 p
.family
= afi2family(afi
);
6007 /* Prefix length check. */
6008 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
6011 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
6012 peer
->host
, p
.prefixlen
, packet
->afi
);
6013 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
6016 /* Packet size overflow check. */
6017 psize
= PSIZE(p
.prefixlen
);
6019 /* When packet overflow occur return immediately. */
6020 if (pnt
+ psize
> lim
) {
6023 "%s [Error] Update packet error (prefix length %d overflows packet)",
6024 peer
->host
, p
.prefixlen
);
6025 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
6028 /* Defensive coding, double-check the psize fits in a struct
6029 * prefix for the v4 and v6 afi's and unicast/multicast */
6030 if (psize
> (ssize_t
)sizeof(p
.u
.val
)) {
6033 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
6034 peer
->host
, p
.prefixlen
, sizeof(p
.u
.val
));
6035 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6038 /* Fetch prefix from NLRI packet. */
6039 memcpy(p
.u
.val
, pnt
, psize
);
6041 /* Check address. */
6042 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
6043 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
6044 /* From RFC4271 Section 6.3:
6046 * If a prefix in the NLRI field is semantically
6048 * (e.g., an unexpected multicast IP address),
6050 * be logged locally, and the prefix SHOULD be
6055 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6056 peer
->host
, &p
.u
.prefix4
);
6061 /* Check address. */
6062 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
6063 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6066 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6067 peer
->host
, &p
.u
.prefix6
);
6071 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
6074 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6075 peer
->host
, &p
.u
.prefix6
);
6081 /* Normal process. */
6083 bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
6084 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
,
6087 bgp_withdraw(peer
, &p
, addpath_id
, afi
, safi
,
6088 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
,
6091 /* Do not send BGP notification twice when maximum-prefix count
6093 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
6094 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
6097 /* Packet length consistency check. */
6101 "%s [Error] Update packet error (prefix length mismatch with total length)",
6103 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6106 return BGP_NLRI_PARSE_OK
;
6109 static struct bgp_static
*bgp_static_new(void)
6111 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
6114 static void bgp_static_free(struct bgp_static
*bgp_static
)
6116 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6117 route_map_counter_decrement(bgp_static
->rmap
.map
);
6119 if (bgp_static
->prd_pretty
)
6120 XFREE(MTYPE_BGP
, bgp_static
->prd_pretty
);
6121 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
6122 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
6125 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
6126 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
6128 struct bgp_dest
*dest
;
6129 struct bgp_path_info
*pi
;
6130 struct bgp_path_info
*new;
6131 struct bgp_path_info rmap_path
;
6133 struct attr
*attr_new
;
6134 route_map_result_t ret
;
6135 #ifdef ENABLE_BGP_VNC
6136 int vnc_implicit_withdraw
= 0;
6141 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6143 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6145 attr
.nexthop
= bgp_static
->igpnexthop
;
6146 attr
.med
= bgp_static
->igpmetric
;
6147 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6150 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
6152 if (bgp_static
->igpmetric
)
6153 bgp_attr_set_aigp_metric(&attr
, bgp_static
->igpmetric
);
6155 if (bgp_static
->atomic
)
6156 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
6158 /* Store label index, if required. */
6159 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
6160 attr
.label_index
= bgp_static
->label_index
;
6161 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
6164 /* Apply route-map. */
6165 if (bgp_static
->rmap
.name
) {
6166 struct attr attr_tmp
= attr
;
6168 memset(&rmap_path
, 0, sizeof(rmap_path
));
6169 rmap_path
.peer
= bgp
->peer_self
;
6170 rmap_path
.attr
= &attr_tmp
;
6172 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6174 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6176 bgp
->peer_self
->rmap_type
= 0;
6178 if (ret
== RMAP_DENYMATCH
) {
6179 /* Free uninterned attribute. */
6180 bgp_attr_flush(&attr_tmp
);
6182 /* Unintern original. */
6183 aspath_unintern(&attr
.aspath
);
6184 bgp_static_withdraw(bgp
, p
, afi
, safi
);
6185 bgp_dest_unlock_node(dest
);
6189 if (bgp_in_graceful_shutdown(bgp
))
6190 bgp_attr_add_gshut_community(&attr_tmp
);
6192 attr_new
= bgp_attr_intern(&attr_tmp
);
6195 if (bgp_in_graceful_shutdown(bgp
))
6196 bgp_attr_add_gshut_community(&attr
);
6198 attr_new
= bgp_attr_intern(&attr
);
6201 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6202 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6203 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6207 if (attrhash_cmp(pi
->attr
, attr_new
)
6208 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
6209 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
6210 bgp_dest_unlock_node(dest
);
6211 bgp_attr_unintern(&attr_new
);
6212 aspath_unintern(&attr
.aspath
);
6215 /* The attribute is changed. */
6216 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6218 /* Rewrite BGP route information. */
6219 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6220 bgp_path_info_restore(dest
, pi
);
6222 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6223 #ifdef ENABLE_BGP_VNC
6224 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6225 && (safi
== SAFI_UNICAST
)) {
6226 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
6228 * Implicit withdraw case.
6229 * We have to do this before pi is
6232 ++vnc_implicit_withdraw
;
6233 vnc_import_bgp_del_route(bgp
, p
, pi
);
6234 vnc_import_bgp_exterior_del_route(
6239 bgp_attr_unintern(&pi
->attr
);
6240 pi
->attr
= attr_new
;
6241 pi
->uptime
= monotime(NULL
);
6242 #ifdef ENABLE_BGP_VNC
6243 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6244 && (safi
== SAFI_UNICAST
)) {
6245 if (vnc_implicit_withdraw
) {
6246 vnc_import_bgp_add_route(bgp
, p
, pi
);
6247 vnc_import_bgp_exterior_add_route(
6253 /* Nexthop reachability check. */
6254 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6255 && (safi
== SAFI_UNICAST
6256 || safi
== SAFI_LABELED_UNICAST
)) {
6258 struct bgp
*bgp_nexthop
= bgp
;
6260 if (pi
->extra
&& pi
->extra
->bgp_orig
)
6261 bgp_nexthop
= pi
->extra
->bgp_orig
;
6263 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
6264 afi
, safi
, pi
, NULL
,
6266 bgp_path_info_set_flag(dest
, pi
,
6269 if (BGP_DEBUG(nht
, NHT
)) {
6270 char buf1
[INET6_ADDRSTRLEN
];
6271 inet_ntop(p
->family
,
6275 "%s(%s): Route not in table, not advertising",
6278 bgp_path_info_unset_flag(
6279 dest
, pi
, BGP_PATH_VALID
);
6282 /* Delete the NHT structure if any, if we're
6284 * enabling/disabling import check. We
6285 * deregister the route
6286 * from NHT to avoid overloading NHT and the
6287 * process interaction
6289 bgp_unlink_nexthop(pi
);
6290 bgp_path_info_set_flag(dest
, pi
,
6293 /* Process change. */
6294 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6295 bgp_process(bgp
, dest
, afi
, safi
);
6297 if (SAFI_UNICAST
== safi
6298 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6300 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6301 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
6305 bgp_dest_unlock_node(dest
);
6306 aspath_unintern(&attr
.aspath
);
6311 /* Make new BGP info. */
6312 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6314 /* Nexthop reachability check. */
6315 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6316 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
6317 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0,
6319 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6321 if (BGP_DEBUG(nht
, NHT
)) {
6322 char buf1
[INET6_ADDRSTRLEN
];
6324 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
6327 "%s(%s): Route not in table, not advertising",
6330 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
6333 /* Delete the NHT structure if any, if we're toggling between
6334 * enabling/disabling import check. We deregister the route
6335 * from NHT to avoid overloading NHT and the process interaction
6337 bgp_unlink_nexthop(new);
6339 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6342 /* Aggregate address increment. */
6343 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6345 /* Register new BGP information. */
6346 bgp_path_info_add(dest
, new);
6348 /* route_node_get lock */
6349 bgp_dest_unlock_node(dest
);
6351 /* Process change. */
6352 bgp_process(bgp
, dest
, afi
, safi
);
6354 if (SAFI_UNICAST
== safi
6355 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6356 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6357 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6360 /* Unintern original. */
6361 aspath_unintern(&attr
.aspath
);
6364 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6367 struct bgp_dest
*dest
;
6368 struct bgp_path_info
*pi
;
6370 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6372 /* Check selected route and self inserted route. */
6373 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6374 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6375 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6378 /* Withdraw static BGP route from routing table. */
6380 if (SAFI_UNICAST
== safi
6381 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6382 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6383 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
6385 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6386 bgp_unlink_nexthop(pi
);
6387 bgp_path_info_delete(dest
, pi
);
6388 bgp_process(bgp
, dest
, afi
, safi
);
6391 /* Unlock bgp_node_lookup. */
6392 bgp_dest_unlock_node(dest
);
6396 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6398 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
6399 afi_t afi
, safi_t safi
,
6400 struct prefix_rd
*prd
)
6402 struct bgp_dest
*dest
;
6403 struct bgp_path_info
*pi
;
6405 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
6407 /* Check selected route and self inserted route. */
6408 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6409 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6410 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6413 /* Withdraw static BGP route from routing table. */
6415 #ifdef ENABLE_BGP_VNC
6416 rfapiProcessWithdraw(
6417 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
6418 1); /* Kill, since it is an administrative change */
6420 if (SAFI_MPLS_VPN
== safi
6421 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6422 vpn_leak_to_vrf_withdraw(pi
);
6424 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6425 bgp_path_info_delete(dest
, pi
);
6426 bgp_process(bgp
, dest
, afi
, safi
);
6429 /* Unlock bgp_node_lookup. */
6430 bgp_dest_unlock_node(dest
);
6433 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
6434 struct bgp_static
*bgp_static
, afi_t afi
,
6437 struct bgp_dest
*dest
;
6438 struct bgp_path_info
*new;
6439 struct attr
*attr_new
;
6440 struct attr attr
= {0};
6441 struct bgp_path_info
*pi
;
6442 #ifdef ENABLE_BGP_VNC
6443 mpls_label_t label
= 0;
6445 uint32_t num_labels
= 0;
6449 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
6451 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
6454 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6456 attr
.nexthop
= bgp_static
->igpnexthop
;
6457 attr
.med
= bgp_static
->igpmetric
;
6458 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6460 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
6461 || (safi
== SAFI_ENCAP
)) {
6462 if (afi
== AFI_IP
) {
6463 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
6464 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
6467 if (afi
== AFI_L2VPN
) {
6468 if (bgp_static
->gatewayIp
.family
== AF_INET
) {
6469 SET_IPADDR_V4(&attr
.evpn_overlay
.gw_ip
);
6470 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v4
,
6471 &bgp_static
->gatewayIp
.u
.prefix4
,
6473 } else if (bgp_static
->gatewayIp
.family
== AF_INET6
) {
6474 SET_IPADDR_V6(&attr
.evpn_overlay
.gw_ip
);
6475 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v6
,
6476 &bgp_static
->gatewayIp
.u
.prefix6
,
6479 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
6480 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
6481 struct bgp_encap_type_vxlan bet
;
6482 memset(&bet
, 0, sizeof(bet
));
6483 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
6484 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
6486 if (bgp_static
->router_mac
) {
6487 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
6490 /* Apply route-map. */
6491 if (bgp_static
->rmap
.name
) {
6492 struct attr attr_tmp
= attr
;
6493 struct bgp_path_info rmap_path
;
6494 route_map_result_t ret
;
6496 rmap_path
.peer
= bgp
->peer_self
;
6497 rmap_path
.attr
= &attr_tmp
;
6499 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6501 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6503 bgp
->peer_self
->rmap_type
= 0;
6505 if (ret
== RMAP_DENYMATCH
) {
6506 /* Free uninterned attribute. */
6507 bgp_attr_flush(&attr_tmp
);
6509 /* Unintern original. */
6510 aspath_unintern(&attr
.aspath
);
6511 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
6513 bgp_dest_unlock_node(dest
);
6517 attr_new
= bgp_attr_intern(&attr_tmp
);
6519 attr_new
= bgp_attr_intern(&attr
);
6522 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6523 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6524 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6528 if (attrhash_cmp(pi
->attr
, attr_new
)
6529 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
6530 bgp_dest_unlock_node(dest
);
6531 bgp_attr_unintern(&attr_new
);
6532 aspath_unintern(&attr
.aspath
);
6535 /* The attribute is changed. */
6536 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6538 /* Rewrite BGP route information. */
6539 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6540 bgp_path_info_restore(dest
, pi
);
6542 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6543 bgp_attr_unintern(&pi
->attr
);
6544 pi
->attr
= attr_new
;
6545 pi
->uptime
= monotime(NULL
);
6546 #ifdef ENABLE_BGP_VNC
6548 label
= decode_label(&pi
->extra
->label
[0]);
6551 /* Process change. */
6552 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6553 bgp_process(bgp
, dest
, afi
, safi
);
6555 if (SAFI_MPLS_VPN
== safi
6556 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6557 vpn_leak_to_vrf_update(bgp
, pi
,
6560 #ifdef ENABLE_BGP_VNC
6561 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
6562 pi
->attr
, afi
, safi
, pi
->type
,
6563 pi
->sub_type
, &label
);
6565 bgp_dest_unlock_node(dest
);
6566 aspath_unintern(&attr
.aspath
);
6572 /* Make new BGP info. */
6573 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6575 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6576 bgp_path_info_extra_get(new);
6578 new->extra
->label
[0] = bgp_static
->label
;
6579 new->extra
->num_labels
= num_labels
;
6581 #ifdef ENABLE_BGP_VNC
6582 label
= decode_label(&bgp_static
->label
);
6585 /* Aggregate address increment. */
6586 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6588 /* Register new BGP information. */
6589 bgp_path_info_add(dest
, new);
6590 /* route_node_get lock */
6591 bgp_dest_unlock_node(dest
);
6593 /* Process change. */
6594 bgp_process(bgp
, dest
, afi
, safi
);
6596 if (SAFI_MPLS_VPN
== safi
6597 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6598 vpn_leak_to_vrf_update(bgp
, new, &bgp_static
->prd
);
6600 #ifdef ENABLE_BGP_VNC
6601 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6602 safi
, new->type
, new->sub_type
, &label
);
6605 /* Unintern original. */
6606 aspath_unintern(&attr
.aspath
);
6609 /* Configure static BGP network. When user don't run zebra, static
6610 route should be installed as valid. */
6611 static int bgp_static_set(struct vty
*vty
, const char *negate
,
6612 const char *ip_str
, afi_t afi
, safi_t safi
,
6613 const char *rmap
, int backdoor
, uint32_t label_index
)
6615 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6618 struct bgp_static
*bgp_static
;
6619 struct bgp_dest
*dest
;
6620 uint8_t need_update
= 0;
6622 /* Convert IP prefix string to struct prefix. */
6623 ret
= str2prefix(ip_str
, &p
);
6625 vty_out(vty
, "%% Malformed prefix\n");
6626 return CMD_WARNING_CONFIG_FAILED
;
6628 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6629 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
6630 return CMD_WARNING_CONFIG_FAILED
;
6637 /* Set BGP static route configuration. */
6638 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6641 vty_out(vty
, "%% Can't find static route specified\n");
6642 return CMD_WARNING_CONFIG_FAILED
;
6645 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6647 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6648 && (label_index
!= bgp_static
->label_index
)) {
6650 "%% label-index doesn't match static route\n");
6651 bgp_dest_unlock_node(dest
);
6652 return CMD_WARNING_CONFIG_FAILED
;
6655 if ((rmap
&& bgp_static
->rmap
.name
)
6656 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6658 "%% route-map name doesn't match static route\n");
6659 bgp_dest_unlock_node(dest
);
6660 return CMD_WARNING_CONFIG_FAILED
;
6663 /* Update BGP RIB. */
6664 if (!bgp_static
->backdoor
)
6665 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6667 /* Clear configuration. */
6668 bgp_static_free(bgp_static
);
6669 bgp_dest_set_bgp_static_info(dest
, NULL
);
6670 bgp_dest_unlock_node(dest
);
6671 bgp_dest_unlock_node(dest
);
6674 /* Set BGP static route configuration. */
6675 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6676 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6678 /* Configuration change. */
6679 /* Label index cannot be changed. */
6680 if (bgp_static
->label_index
!= label_index
) {
6681 vty_out(vty
, "%% cannot change label-index\n");
6682 bgp_dest_unlock_node(dest
);
6683 return CMD_WARNING_CONFIG_FAILED
;
6686 /* Check previous routes are installed into BGP. */
6687 if (bgp_static
->valid
6688 && bgp_static
->backdoor
!= backdoor
)
6691 bgp_static
->backdoor
= backdoor
;
6694 XFREE(MTYPE_ROUTE_MAP_NAME
,
6695 bgp_static
->rmap
.name
);
6696 route_map_counter_decrement(
6697 bgp_static
->rmap
.map
);
6698 bgp_static
->rmap
.name
=
6699 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6700 bgp_static
->rmap
.map
=
6701 route_map_lookup_by_name(rmap
);
6702 route_map_counter_increment(
6703 bgp_static
->rmap
.map
);
6705 XFREE(MTYPE_ROUTE_MAP_NAME
,
6706 bgp_static
->rmap
.name
);
6707 route_map_counter_decrement(
6708 bgp_static
->rmap
.map
);
6709 bgp_static
->rmap
.map
= NULL
;
6710 bgp_static
->valid
= 0;
6712 bgp_dest_unlock_node(dest
);
6714 /* New configuration. */
6715 bgp_static
= bgp_static_new();
6716 bgp_static
->backdoor
= backdoor
;
6717 bgp_static
->valid
= 0;
6718 bgp_static
->igpmetric
= 0;
6719 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6720 bgp_static
->label_index
= label_index
;
6723 XFREE(MTYPE_ROUTE_MAP_NAME
,
6724 bgp_static
->rmap
.name
);
6725 route_map_counter_decrement(
6726 bgp_static
->rmap
.map
);
6727 bgp_static
->rmap
.name
=
6728 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6729 bgp_static
->rmap
.map
=
6730 route_map_lookup_by_name(rmap
);
6731 route_map_counter_increment(
6732 bgp_static
->rmap
.map
);
6734 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6737 bgp_static
->valid
= 1;
6739 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6741 if (!bgp_static
->backdoor
)
6742 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6748 void bgp_static_add(struct bgp
*bgp
)
6752 struct bgp_dest
*dest
;
6753 struct bgp_dest
*rm
;
6754 struct bgp_table
*table
;
6755 struct bgp_static
*bgp_static
;
6757 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6758 FOREACH_AFI_SAFI (afi
, safi
)
6759 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6760 dest
= bgp_route_next(dest
)) {
6761 if (!bgp_dest_has_bgp_path_info_data(dest
))
6764 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6765 || (safi
== SAFI_EVPN
)) {
6766 table
= bgp_dest_get_bgp_table_info(dest
);
6768 for (rm
= bgp_table_top(table
); rm
;
6769 rm
= bgp_route_next(rm
)) {
6771 bgp_dest_get_bgp_static_info(
6773 bgp_static_update_safi(
6774 bgp
, bgp_dest_get_prefix(rm
),
6775 bgp_static
, afi
, safi
);
6779 bgp
, bgp_dest_get_prefix(dest
),
6780 bgp_dest_get_bgp_static_info(dest
), afi
,
6784 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6787 /* Called from bgp_delete(). Delete all static routes from the BGP
6789 void bgp_static_delete(struct bgp
*bgp
)
6793 struct bgp_dest
*dest
;
6794 struct bgp_dest
*rm
;
6795 struct bgp_table
*table
;
6796 struct bgp_static
*bgp_static
;
6798 FOREACH_AFI_SAFI (afi
, safi
)
6799 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6800 dest
= bgp_route_next(dest
)) {
6801 if (!bgp_dest_has_bgp_path_info_data(dest
))
6804 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6805 || (safi
== SAFI_EVPN
)) {
6806 table
= bgp_dest_get_bgp_table_info(dest
);
6808 for (rm
= bgp_table_top(table
); rm
;
6809 rm
= bgp_route_next(rm
)) {
6811 bgp_dest_get_bgp_static_info(
6816 bgp_static_withdraw_safi(
6817 bgp
, bgp_dest_get_prefix(rm
),
6819 (struct prefix_rd
*)
6820 bgp_dest_get_prefix(
6822 bgp_static_free(bgp_static
);
6823 bgp_dest_set_bgp_static_info(rm
,
6825 bgp_dest_unlock_node(rm
);
6828 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6829 bgp_static_withdraw(bgp
,
6830 bgp_dest_get_prefix(dest
),
6832 bgp_static_free(bgp_static
);
6833 bgp_dest_set_bgp_static_info(dest
, NULL
);
6834 bgp_dest_unlock_node(dest
);
6839 void bgp_static_redo_import_check(struct bgp
*bgp
)
6843 struct bgp_dest
*dest
;
6844 struct bgp_dest
*rm
;
6845 struct bgp_table
*table
;
6846 struct bgp_static
*bgp_static
;
6848 /* Use this flag to force reprocessing of the route */
6849 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6850 FOREACH_AFI_SAFI (afi
, safi
) {
6851 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6852 dest
= bgp_route_next(dest
)) {
6853 if (!bgp_dest_has_bgp_path_info_data(dest
))
6856 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6857 || (safi
== SAFI_EVPN
)) {
6858 table
= bgp_dest_get_bgp_table_info(dest
);
6860 for (rm
= bgp_table_top(table
); rm
;
6861 rm
= bgp_route_next(rm
)) {
6863 bgp_dest_get_bgp_static_info(
6865 bgp_static_update_safi(
6866 bgp
, bgp_dest_get_prefix(rm
),
6867 bgp_static
, afi
, safi
);
6870 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6871 bgp_static_update(bgp
,
6872 bgp_dest_get_prefix(dest
),
6873 bgp_static
, afi
, safi
);
6877 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6880 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6883 struct bgp_table
*table
;
6884 struct bgp_dest
*dest
;
6885 struct bgp_path_info
*pi
;
6887 /* Do not install the aggregate route if BGP is in the
6888 * process of termination.
6890 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6891 || (bgp
->peer_self
== NULL
))
6894 table
= bgp
->rib
[afi
][safi
];
6895 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6896 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6897 if (pi
->peer
== bgp
->peer_self
6898 && ((pi
->type
== ZEBRA_ROUTE_BGP
6899 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6900 || (pi
->type
!= ZEBRA_ROUTE_BGP
6902 == BGP_ROUTE_REDISTRIBUTE
))) {
6903 bgp_aggregate_decrement(
6904 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6906 bgp_unlink_nexthop(pi
);
6907 bgp_path_info_delete(dest
, pi
);
6908 bgp_process(bgp
, dest
, afi
, safi
);
6915 * Purge all networks and redistributed routes from routing table.
6916 * Invoked upon the instance going down.
6918 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6923 FOREACH_AFI_SAFI (afi
, safi
)
6924 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6929 * Currently this is used to set static routes for VPN and ENCAP.
6930 * I think it can probably be factored with bgp_static_set.
6932 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6933 const char *ip_str
, const char *rd_str
,
6934 const char *label_str
, const char *rmap_str
,
6935 int evpn_type
, const char *esi
, const char *gwip
,
6936 const char *ethtag
, const char *routermac
)
6938 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6941 struct prefix_rd prd
;
6942 struct bgp_dest
*pdest
;
6943 struct bgp_dest
*dest
;
6944 struct bgp_table
*table
;
6945 struct bgp_static
*bgp_static
;
6946 mpls_label_t label
= MPLS_INVALID_LABEL
;
6947 struct prefix gw_ip
;
6949 /* validate ip prefix */
6950 ret
= str2prefix(ip_str
, &p
);
6952 vty_out(vty
, "%% Malformed prefix\n");
6953 return CMD_WARNING_CONFIG_FAILED
;
6956 if ((afi
== AFI_L2VPN
)
6957 && (bgp_build_evpn_prefix(evpn_type
,
6958 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6959 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6960 return CMD_WARNING_CONFIG_FAILED
;
6963 ret
= str2prefix_rd(rd_str
, &prd
);
6965 vty_out(vty
, "%% Malformed rd\n");
6966 return CMD_WARNING_CONFIG_FAILED
;
6970 unsigned long label_val
;
6971 label_val
= strtoul(label_str
, NULL
, 10);
6972 encode_label(label_val
, &label
);
6975 if (safi
== SAFI_EVPN
) {
6976 if (esi
&& str2esi(esi
, NULL
) == 0) {
6977 vty_out(vty
, "%% Malformed ESI\n");
6978 return CMD_WARNING_CONFIG_FAILED
;
6980 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6981 vty_out(vty
, "%% Malformed Router MAC\n");
6982 return CMD_WARNING_CONFIG_FAILED
;
6985 memset(&gw_ip
, 0, sizeof(gw_ip
));
6986 ret
= str2prefix(gwip
, &gw_ip
);
6988 vty_out(vty
, "%% Malformed GatewayIp\n");
6989 return CMD_WARNING_CONFIG_FAILED
;
6991 if ((gw_ip
.family
== AF_INET
6992 && is_evpn_prefix_ipaddr_v6(
6993 (struct prefix_evpn
*)&p
))
6994 || (gw_ip
.family
== AF_INET6
6995 && is_evpn_prefix_ipaddr_v4(
6996 (struct prefix_evpn
*)&p
))) {
6998 "%% GatewayIp family differs with IP prefix\n");
6999 return CMD_WARNING_CONFIG_FAILED
;
7003 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7004 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7005 bgp_dest_set_bgp_table_info(pdest
,
7006 bgp_table_init(bgp
, afi
, safi
));
7007 table
= bgp_dest_get_bgp_table_info(pdest
);
7009 dest
= bgp_node_get(table
, &p
);
7011 if (bgp_dest_has_bgp_path_info_data(dest
)) {
7012 vty_out(vty
, "%% Same network configuration exists\n");
7013 bgp_dest_unlock_node(dest
);
7015 /* New configuration. */
7016 bgp_static
= bgp_static_new();
7017 bgp_static
->backdoor
= 0;
7018 bgp_static
->valid
= 0;
7019 bgp_static
->igpmetric
= 0;
7020 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
7021 bgp_static
->label
= label
;
7022 bgp_static
->prd
= prd
;
7025 bgp_static
->prd_pretty
= XSTRDUP(MTYPE_BGP
, rd_str
);
7027 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
7028 route_map_counter_decrement(bgp_static
->rmap
.map
);
7029 bgp_static
->rmap
.name
=
7030 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
7031 bgp_static
->rmap
.map
=
7032 route_map_lookup_by_name(rmap_str
);
7033 route_map_counter_increment(bgp_static
->rmap
.map
);
7036 if (safi
== SAFI_EVPN
) {
7038 bgp_static
->eth_s_id
=
7041 str2esi(esi
, bgp_static
->eth_s_id
);
7044 bgp_static
->router_mac
=
7045 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
7046 (void)prefix_str2mac(routermac
,
7047 bgp_static
->router_mac
);
7050 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
7052 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
7054 bgp_static
->valid
= 1;
7055 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
7061 /* Configure static BGP network. */
7062 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
7063 const char *ip_str
, const char *rd_str
,
7064 const char *label_str
, int evpn_type
, const char *esi
,
7065 const char *gwip
, const char *ethtag
)
7067 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7070 struct prefix_rd prd
;
7071 struct bgp_dest
*pdest
;
7072 struct bgp_dest
*dest
;
7073 struct bgp_table
*table
;
7074 struct bgp_static
*bgp_static
;
7075 mpls_label_t label
= MPLS_INVALID_LABEL
;
7077 /* Convert IP prefix string to struct prefix. */
7078 ret
= str2prefix(ip_str
, &p
);
7080 vty_out(vty
, "%% Malformed prefix\n");
7081 return CMD_WARNING_CONFIG_FAILED
;
7084 if ((afi
== AFI_L2VPN
)
7085 && (bgp_build_evpn_prefix(evpn_type
,
7086 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
7087 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
7088 return CMD_WARNING_CONFIG_FAILED
;
7090 ret
= str2prefix_rd(rd_str
, &prd
);
7092 vty_out(vty
, "%% Malformed rd\n");
7093 return CMD_WARNING_CONFIG_FAILED
;
7097 unsigned long label_val
;
7098 label_val
= strtoul(label_str
, NULL
, 10);
7099 encode_label(label_val
, &label
);
7102 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7103 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7104 bgp_dest_set_bgp_table_info(pdest
,
7105 bgp_table_init(bgp
, afi
, safi
));
7107 bgp_dest_unlock_node(pdest
);
7108 table
= bgp_dest_get_bgp_table_info(pdest
);
7110 dest
= bgp_node_lookup(table
, &p
);
7113 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
7115 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
7116 bgp_static_free(bgp_static
);
7117 bgp_dest_set_bgp_static_info(dest
, NULL
);
7118 bgp_dest_unlock_node(dest
);
7119 bgp_dest_unlock_node(dest
);
7121 vty_out(vty
, "%% Can't find the route\n");
7126 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
7127 const char *rmap_name
)
7129 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7130 struct bgp_rmap
*rmap
;
7132 rmap
= &bgp
->table_map
[afi
][safi
];
7134 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7135 route_map_counter_decrement(rmap
->map
);
7136 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
7137 rmap
->map
= route_map_lookup_by_name(rmap_name
);
7138 route_map_counter_increment(rmap
->map
);
7140 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7141 route_map_counter_decrement(rmap
->map
);
7145 if (bgp_fibupd_safi(safi
))
7146 bgp_zebra_announce_table(bgp
, afi
, safi
);
7151 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
7152 const char *rmap_name
)
7154 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7155 struct bgp_rmap
*rmap
;
7157 rmap
= &bgp
->table_map
[afi
][safi
];
7158 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7159 route_map_counter_decrement(rmap
->map
);
7162 if (bgp_fibupd_safi(safi
))
7163 bgp_zebra_announce_table(bgp
, afi
, safi
);
7168 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
7171 if (bgp
->table_map
[afi
][safi
].name
) {
7172 vty_out(vty
, " table-map %s\n",
7173 bgp
->table_map
[afi
][safi
].name
);
7177 DEFUN (bgp_table_map
,
7180 "BGP table to RIB route download filter\n"
7181 "Name of the route map\n")
7184 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7185 argv
[idx_word
]->arg
);
7187 DEFUN (no_bgp_table_map
,
7188 no_bgp_table_map_cmd
,
7189 "no table-map WORD",
7191 "BGP table to RIB route download filter\n"
7192 "Name of the route map\n")
7195 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7196 argv
[idx_word
]->arg
);
7202 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
7203 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
7204 backdoor$backdoor}]",
7206 "Specify a network to announce via BGP\n"
7211 "Route-map to modify the attributes\n"
7212 "Name of the route map\n"
7213 "Label index to associate with the prefix\n"
7214 "Label index value\n"
7215 "Specify a BGP backdoor route\n")
7217 char addr_prefix_str
[BUFSIZ
];
7222 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
7224 sizeof(addr_prefix_str
));
7226 vty_out(vty
, "%% Inconsistent address and mask\n");
7227 return CMD_WARNING_CONFIG_FAILED
;
7231 return bgp_static_set(
7232 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
7233 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
7234 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7237 DEFPY(ipv6_bgp_network
,
7238 ipv6_bgp_network_cmd
,
7239 "[no] network X:X::X:X/M$prefix \
7240 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
7242 "Specify a network to announce via BGP\n"
7244 "Route-map to modify the attributes\n"
7245 "Name of the route map\n"
7246 "Label index to associate with the prefix\n"
7247 "Label index value\n")
7249 return bgp_static_set(
7250 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
7251 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7254 static struct bgp_aggregate
*bgp_aggregate_new(void)
7256 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
7259 void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
7261 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7262 route_map_counter_decrement(aggregate
->suppress_map
);
7263 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7264 route_map_counter_decrement(aggregate
->rmap
.map
);
7265 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
7269 * Helper function to avoid repeated code: prepare variables for a
7270 * `route_map_apply` call.
7272 * \returns `true` on route map match, otherwise `false`.
7274 static bool aggr_suppress_map_test(struct bgp
*bgp
,
7275 struct bgp_aggregate
*aggregate
,
7276 struct bgp_path_info
*pi
)
7278 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
7279 route_map_result_t rmr
= RMAP_DENYMATCH
;
7280 struct bgp_path_info rmap_path
= {};
7281 struct attr attr
= {};
7283 /* No route map entries created, just don't match. */
7284 if (aggregate
->suppress_map
== NULL
)
7287 /* Call route map matching and return result. */
7288 attr
.aspath
= aspath_empty(bgp
->asnotation
);
7289 rmap_path
.peer
= bgp
->peer_self
;
7290 rmap_path
.attr
= &attr
;
7292 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
7293 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
7294 bgp
->peer_self
->rmap_type
= 0;
7296 bgp_attr_flush(&attr
);
7297 aspath_unintern(&attr
.aspath
);
7299 return rmr
== RMAP_PERMITMATCH
;
7302 /** Test whether the aggregation has suppressed this path or not. */
7303 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
7304 struct bgp_path_info
*pi
)
7306 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
7309 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
7313 * Suppress this path and keep the reference.
7315 * \returns `true` if needs processing otherwise `false`.
7317 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
7318 struct bgp_path_info
*pi
)
7320 struct bgp_path_info_extra
*pie
;
7322 /* Path is already suppressed by this aggregation. */
7323 if (aggr_suppress_exists(aggregate
, pi
))
7326 pie
= bgp_path_info_extra_get(pi
);
7328 /* This is the first suppression, allocate memory and list it. */
7329 if (pie
->aggr_suppressors
== NULL
)
7330 pie
->aggr_suppressors
= list_new();
7332 listnode_add(pie
->aggr_suppressors
, aggregate
);
7334 /* Only mark for processing if suppressed. */
7335 if (listcount(pie
->aggr_suppressors
) == 1) {
7336 if (BGP_DEBUG(update
, UPDATE_OUT
))
7337 zlog_debug("aggregate-address suppressing: %pFX",
7338 bgp_dest_get_prefix(pi
->net
));
7340 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7348 * Unsuppress this path and remove the reference.
7350 * \returns `true` if needs processing otherwise `false`.
7352 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
7353 struct bgp_path_info
*pi
)
7355 /* Path wasn't suppressed. */
7356 if (!aggr_suppress_exists(aggregate
, pi
))
7359 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
7361 /* Unsuppress and free extra memory if last item. */
7362 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
7363 if (BGP_DEBUG(update
, UPDATE_OUT
))
7364 zlog_debug("aggregate-address unsuppressing: %pFX",
7365 bgp_dest_get_prefix(pi
->net
));
7367 list_delete(&pi
->extra
->aggr_suppressors
);
7368 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7375 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
7376 struct aspath
*aspath
,
7377 struct community
*comm
,
7378 struct ecommunity
*ecomm
,
7379 struct lcommunity
*lcomm
)
7381 static struct aspath
*ae
= NULL
;
7382 enum asnotation_mode asnotation
;
7384 asnotation
= bgp_get_asnotation(NULL
);
7387 ae
= aspath_empty(asnotation
);
7392 if (origin
!= pi
->attr
->origin
)
7395 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
7398 if (!community_cmp(bgp_attr_get_community(pi
->attr
), comm
))
7401 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi
->attr
), ecomm
))
7404 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi
->attr
), lcomm
))
7407 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
7413 static void bgp_aggregate_install(
7414 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
7415 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
7416 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
7417 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
7419 struct bgp_dest
*dest
;
7420 struct bgp_table
*table
;
7421 struct bgp_path_info
*pi
, *orig
, *new;
7424 table
= bgp
->rib
[afi
][safi
];
7426 dest
= bgp_node_get(table
, p
);
7428 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7429 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
7430 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7434 * If we have paths with different MEDs, then don't install
7435 * (or uninstall) the aggregate route.
7437 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
7438 goto uninstall_aggregate_route
;
7440 if (aggregate
->count
> 0) {
7442 * If the aggregate information has not changed
7443 * no need to re-install it again.
7445 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
7446 ecommunity
, lcommunity
)) {
7447 bgp_dest_unlock_node(dest
);
7450 aspath_free(aspath
);
7452 community_free(&community
);
7454 ecommunity_free(&ecommunity
);
7456 lcommunity_free(&lcommunity
);
7462 * Mark the old as unusable
7465 bgp_path_info_delete(dest
, pi
);
7467 attr
= bgp_attr_aggregate_intern(
7468 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
7469 aggregate
, atomic_aggregate
, p
);
7472 aspath_free(aspath
);
7473 community_free(&community
);
7474 ecommunity_free(&ecommunity
);
7475 lcommunity_free(&lcommunity
);
7476 bgp_dest_unlock_node(dest
);
7477 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
7478 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
7479 zlog_debug("%s: %pFX null attribute", __func__
,
7484 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
7485 bgp
->peer_self
, attr
, dest
);
7487 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7489 bgp_path_info_add(dest
, new);
7490 bgp_process(bgp
, dest
, afi
, safi
);
7492 uninstall_aggregate_route
:
7493 for (pi
= orig
; pi
; pi
= pi
->next
)
7494 if (pi
->peer
== bgp
->peer_self
7495 && pi
->type
== ZEBRA_ROUTE_BGP
7496 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7499 /* Withdraw static BGP route from routing table. */
7501 bgp_path_info_delete(dest
, pi
);
7502 bgp_process(bgp
, dest
, afi
, safi
);
7506 bgp_dest_unlock_node(dest
);
7510 * Check if the current path has different MED than other known paths.
7512 * \returns `true` if the MED matched the others else `false`.
7514 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
7515 struct bgp
*bgp
, struct bgp_path_info
*pi
)
7517 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
7519 /* This is the first route being analyzed. */
7520 if (!aggregate
->med_initialized
) {
7521 aggregate
->med_initialized
= true;
7522 aggregate
->med_mismatched
= false;
7523 aggregate
->med_matched_value
= cur_med
;
7525 /* Check if routes with different MED showed up. */
7526 if (cur_med
!= aggregate
->med_matched_value
)
7527 aggregate
->med_mismatched
= true;
7530 return !aggregate
->med_mismatched
;
7534 * Initializes and tests all routes in the aggregate address path for MED
7537 * \returns `true` if all MEDs are the same otherwise `false`.
7539 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
7540 struct bgp
*bgp
, const struct prefix
*p
,
7541 afi_t afi
, safi_t safi
)
7543 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7544 const struct prefix
*dest_p
;
7545 struct bgp_dest
*dest
, *top
;
7546 struct bgp_path_info
*pi
;
7547 bool med_matched
= true;
7549 aggregate
->med_initialized
= false;
7551 top
= bgp_node_get(table
, p
);
7552 for (dest
= bgp_node_get(table
, p
); dest
;
7553 dest
= bgp_route_next_until(dest
, top
)) {
7554 dest_p
= bgp_dest_get_prefix(dest
);
7555 if (dest_p
->prefixlen
<= p
->prefixlen
)
7558 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7559 if (BGP_PATH_HOLDDOWN(pi
))
7561 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7563 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
7564 med_matched
= false;
7571 bgp_dest_unlock_node(top
);
7577 * Toggles the route suppression status for this aggregate address
7580 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
7581 struct bgp
*bgp
, const struct prefix
*p
,
7582 afi_t afi
, safi_t safi
, bool suppress
)
7584 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7585 const struct prefix
*dest_p
;
7586 struct bgp_dest
*dest
, *top
;
7587 struct bgp_path_info
*pi
;
7588 bool toggle_suppression
;
7590 /* We've found a different MED we must revert any suppressed routes. */
7591 top
= bgp_node_get(table
, p
);
7592 for (dest
= bgp_node_get(table
, p
); dest
;
7593 dest
= bgp_route_next_until(dest
, top
)) {
7594 dest_p
= bgp_dest_get_prefix(dest
);
7595 if (dest_p
->prefixlen
<= p
->prefixlen
)
7598 toggle_suppression
= false;
7599 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7600 if (BGP_PATH_HOLDDOWN(pi
))
7602 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7605 /* We are toggling suppression back. */
7607 /* Suppress route if not suppressed already. */
7608 if (aggr_suppress_path(aggregate
, pi
))
7609 toggle_suppression
= true;
7613 /* Install route if there is no more suppression. */
7614 if (aggr_unsuppress_path(aggregate
, pi
))
7615 toggle_suppression
= true;
7618 if (toggle_suppression
)
7619 bgp_process(bgp
, dest
, afi
, safi
);
7621 bgp_dest_unlock_node(top
);
7625 * Aggregate address MED matching incremental test: this function is called
7626 * when the initial aggregation occurred and we are only testing a single
7629 * In addition to testing and setting the MED validity it also installs back
7630 * suppressed routes (if summary is configured).
7632 * Must not be called in `bgp_aggregate_route`.
7634 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7635 struct bgp
*bgp
, const struct prefix
*p
,
7636 afi_t afi
, safi_t safi
,
7637 struct bgp_path_info
*pi
)
7639 /* MED matching disabled. */
7640 if (!aggregate
->match_med
)
7643 /* Aggregation with different MED, recheck if we have got equal MEDs
7646 if (aggregate
->med_mismatched
&&
7647 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
) &&
7648 aggregate
->summary_only
)
7649 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
,
7652 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7654 /* No mismatches, just quit. */
7655 if (!aggregate
->med_mismatched
)
7658 /* Route summarization is disabled. */
7659 if (!aggregate
->summary_only
)
7662 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7665 /* Update an aggregate as routes are added/removed from the BGP table */
7666 bool bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7667 safi_t safi
, struct bgp_aggregate
*aggregate
)
7669 struct bgp_table
*table
;
7670 struct bgp_dest
*top
;
7671 struct bgp_dest
*dest
;
7673 struct aspath
*aspath
= NULL
;
7674 struct community
*community
= NULL
;
7675 struct ecommunity
*ecommunity
= NULL
;
7676 struct lcommunity
*lcommunity
= NULL
;
7677 struct bgp_path_info
*pi
;
7678 unsigned long match
= 0;
7679 uint8_t atomic_aggregate
= 0;
7681 /* If the bgp instance is being deleted or self peer is deleted
7682 * then do not create aggregate route
7684 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
7685 bgp
->peer_self
== NULL
)
7688 /* Initialize and test routes for MED difference. */
7689 if (aggregate
->match_med
)
7690 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7693 * Reset aggregate count: we might've been called from route map
7694 * update so in that case we must retest all more specific routes.
7696 * \see `bgp_route_map_process_update`.
7698 aggregate
->count
= 0;
7699 aggregate
->incomplete_origin_count
= 0;
7700 aggregate
->incomplete_origin_count
= 0;
7701 aggregate
->egp_origin_count
= 0;
7703 /* ORIGIN attribute: If at least one route among routes that are
7704 aggregated has ORIGIN with the value INCOMPLETE, then the
7705 aggregated route must have the ORIGIN attribute with the value
7706 INCOMPLETE. Otherwise, if at least one route among routes that
7707 are aggregated has ORIGIN with the value EGP, then the aggregated
7708 route must have the origin attribute with the value EGP. In all
7709 other case the value of the ORIGIN attribute of the aggregated
7710 route is INTERNAL. */
7711 origin
= BGP_ORIGIN_IGP
;
7713 table
= bgp
->rib
[afi
][safi
];
7715 top
= bgp_node_get(table
, p
);
7716 for (dest
= bgp_node_get(table
, p
); dest
;
7717 dest
= bgp_route_next_until(dest
, top
)) {
7718 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7720 if (dest_p
->prefixlen
<= p
->prefixlen
)
7723 /* If suppress fib is enabled and route not installed
7724 * in FIB, skip the route
7726 if (!bgp_check_advertise(bgp
, dest
))
7731 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7732 if (BGP_PATH_HOLDDOWN(pi
))
7736 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7737 atomic_aggregate
= 1;
7739 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7743 * summary-only aggregate route suppress
7744 * aggregated route announcements.
7747 * Don't create summaries if MED didn't match
7748 * otherwise neither the specific routes and the
7749 * aggregation will be announced.
7751 if (aggregate
->summary_only
7752 && AGGREGATE_MED_VALID(aggregate
)) {
7753 if (aggr_suppress_path(aggregate
, pi
))
7758 * Suppress more specific routes that match the route
7762 * Don't suppress routes if MED matching is enabled and
7763 * it mismatched otherwise we might end up with no
7764 * routes for this path.
7766 if (aggregate
->suppress_map_name
7767 && AGGREGATE_MED_VALID(aggregate
)
7768 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7769 if (aggr_suppress_path(aggregate
, pi
))
7776 * If at least one route among routes that are
7777 * aggregated has ORIGIN with the value INCOMPLETE,
7778 * then the aggregated route MUST have the ORIGIN
7779 * attribute with the value INCOMPLETE. Otherwise, if
7780 * at least one route among routes that are aggregated
7781 * has ORIGIN with the value EGP, then the aggregated
7782 * route MUST have the ORIGIN attribute with the value
7785 switch (pi
->attr
->origin
) {
7786 case BGP_ORIGIN_INCOMPLETE
:
7787 aggregate
->incomplete_origin_count
++;
7789 case BGP_ORIGIN_EGP
:
7790 aggregate
->egp_origin_count
++;
7798 if (!aggregate
->as_set
)
7802 * as-set aggregate route generate origin, as path,
7803 * and community aggregation.
7805 /* Compute aggregate route's as-path.
7807 bgp_compute_aggregate_aspath_hash(aggregate
,
7810 /* Compute aggregate route's community.
7812 if (bgp_attr_get_community(pi
->attr
))
7813 bgp_compute_aggregate_community_hash(
7815 bgp_attr_get_community(pi
->attr
));
7817 /* Compute aggregate route's extended community.
7819 if (bgp_attr_get_ecommunity(pi
->attr
))
7820 bgp_compute_aggregate_ecommunity_hash(
7822 bgp_attr_get_ecommunity(pi
->attr
));
7824 /* Compute aggregate route's large community.
7826 if (bgp_attr_get_lcommunity(pi
->attr
))
7827 bgp_compute_aggregate_lcommunity_hash(
7829 bgp_attr_get_lcommunity(pi
->attr
));
7832 bgp_process(bgp
, dest
, afi
, safi
);
7834 if (aggregate
->as_set
) {
7835 bgp_compute_aggregate_aspath_val(aggregate
);
7836 bgp_compute_aggregate_community_val(aggregate
);
7837 bgp_compute_aggregate_ecommunity_val(aggregate
);
7838 bgp_compute_aggregate_lcommunity_val(aggregate
);
7842 bgp_dest_unlock_node(top
);
7845 if (aggregate
->incomplete_origin_count
> 0)
7846 origin
= BGP_ORIGIN_INCOMPLETE
;
7847 else if (aggregate
->egp_origin_count
> 0)
7848 origin
= BGP_ORIGIN_EGP
;
7850 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7851 origin
= aggregate
->origin
;
7853 if (aggregate
->as_set
) {
7854 if (aggregate
->aspath
)
7855 /* Retrieve aggregate route's as-path.
7857 aspath
= aspath_dup(aggregate
->aspath
);
7859 if (aggregate
->community
)
7860 /* Retrieve aggregate route's community.
7862 community
= community_dup(aggregate
->community
);
7864 if (aggregate
->ecommunity
)
7865 /* Retrieve aggregate route's ecommunity.
7867 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7869 if (aggregate
->lcommunity
)
7870 /* Retrieve aggregate route's lcommunity.
7872 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7875 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7876 ecommunity
, lcommunity
, atomic_aggregate
,
7882 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7883 safi_t safi
, struct bgp_aggregate
*aggregate
)
7885 struct bgp_table
*table
;
7886 struct bgp_dest
*top
;
7887 struct bgp_dest
*dest
;
7888 struct bgp_path_info
*pi
;
7889 unsigned long match
;
7891 table
= bgp
->rib
[afi
][safi
];
7893 /* If routes exists below this node, generate aggregate routes. */
7894 top
= bgp_node_get(table
, p
);
7895 for (dest
= bgp_node_get(table
, p
); dest
;
7896 dest
= bgp_route_next_until(dest
, top
)) {
7897 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7899 if (dest_p
->prefixlen
<= p
->prefixlen
)
7903 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7904 if (BGP_PATH_HOLDDOWN(pi
))
7907 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7911 * This route is suppressed: attempt to unsuppress it.
7913 * `aggr_unsuppress_path` will fail if this particular
7914 * aggregate route was not the suppressor.
7916 if (pi
->extra
&& pi
->extra
->aggr_suppressors
&&
7917 listcount(pi
->extra
->aggr_suppressors
)) {
7918 if (aggr_unsuppress_path(aggregate
, pi
))
7924 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7925 aggregate
->incomplete_origin_count
--;
7926 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7927 aggregate
->egp_origin_count
--;
7929 if (aggregate
->as_set
) {
7930 /* Remove as-path from aggregate.
7932 bgp_remove_aspath_from_aggregate_hash(
7936 if (bgp_attr_get_community(pi
->attr
))
7937 /* Remove community from aggregate.
7939 bgp_remove_comm_from_aggregate_hash(
7941 bgp_attr_get_community(
7944 if (bgp_attr_get_ecommunity(pi
->attr
))
7945 /* Remove ecommunity from aggregate.
7947 bgp_remove_ecomm_from_aggregate_hash(
7949 bgp_attr_get_ecommunity(
7952 if (bgp_attr_get_lcommunity(pi
->attr
))
7953 /* Remove lcommunity from aggregate.
7955 bgp_remove_lcomm_from_aggregate_hash(
7957 bgp_attr_get_lcommunity(
7962 /* If this node was suppressed, process the change. */
7964 bgp_process(bgp
, dest
, afi
, safi
);
7966 if (aggregate
->as_set
) {
7967 aspath_free(aggregate
->aspath
);
7968 aggregate
->aspath
= NULL
;
7969 if (aggregate
->community
)
7970 community_free(&aggregate
->community
);
7971 if (aggregate
->ecommunity
)
7972 ecommunity_free(&aggregate
->ecommunity
);
7973 if (aggregate
->lcommunity
)
7974 lcommunity_free(&aggregate
->lcommunity
);
7977 bgp_dest_unlock_node(top
);
7980 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7981 const struct prefix
*aggr_p
,
7982 struct bgp_path_info
*pinew
, afi_t afi
,
7984 struct bgp_aggregate
*aggregate
)
7987 struct aspath
*aspath
= NULL
;
7988 uint8_t atomic_aggregate
= 0;
7989 struct community
*community
= NULL
;
7990 struct ecommunity
*ecommunity
= NULL
;
7991 struct lcommunity
*lcommunity
= NULL
;
7993 /* If the bgp instance is being deleted or self peer is deleted
7994 * then do not create aggregate route
7996 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7997 || (bgp
->peer_self
== NULL
))
8000 /* ORIGIN attribute: If at least one route among routes that are
8001 * aggregated has ORIGIN with the value INCOMPLETE, then the
8002 * aggregated route must have the ORIGIN attribute with the value
8003 * INCOMPLETE. Otherwise, if at least one route among routes that
8004 * are aggregated has ORIGIN with the value EGP, then the aggregated
8005 * route must have the origin attribute with the value EGP. In all
8006 * other case the value of the ORIGIN attribute of the aggregated
8007 * route is INTERNAL.
8009 origin
= BGP_ORIGIN_IGP
;
8014 * This must be called before `summary` check to avoid
8015 * "suppressing" twice.
8017 if (aggregate
->match_med
)
8018 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
8021 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8022 aggr_suppress_path(aggregate
, pinew
);
8024 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8025 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
8026 aggr_suppress_path(aggregate
, pinew
);
8028 switch (pinew
->attr
->origin
) {
8029 case BGP_ORIGIN_INCOMPLETE
:
8030 aggregate
->incomplete_origin_count
++;
8032 case BGP_ORIGIN_EGP
:
8033 aggregate
->egp_origin_count
++;
8041 if (aggregate
->incomplete_origin_count
> 0)
8042 origin
= BGP_ORIGIN_INCOMPLETE
;
8043 else if (aggregate
->egp_origin_count
> 0)
8044 origin
= BGP_ORIGIN_EGP
;
8046 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8047 origin
= aggregate
->origin
;
8049 if (aggregate
->as_set
) {
8050 /* Compute aggregate route's as-path.
8052 bgp_compute_aggregate_aspath(aggregate
,
8053 pinew
->attr
->aspath
);
8055 /* Compute aggregate route's community.
8057 if (bgp_attr_get_community(pinew
->attr
))
8058 bgp_compute_aggregate_community(
8059 aggregate
, bgp_attr_get_community(pinew
->attr
));
8061 /* Compute aggregate route's extended community.
8063 if (bgp_attr_get_ecommunity(pinew
->attr
))
8064 bgp_compute_aggregate_ecommunity(
8066 bgp_attr_get_ecommunity(pinew
->attr
));
8068 /* Compute aggregate route's large community.
8070 if (bgp_attr_get_lcommunity(pinew
->attr
))
8071 bgp_compute_aggregate_lcommunity(
8073 bgp_attr_get_lcommunity(pinew
->attr
));
8075 /* Retrieve aggregate route's as-path.
8077 if (aggregate
->aspath
)
8078 aspath
= aspath_dup(aggregate
->aspath
);
8080 /* Retrieve aggregate route's community.
8082 if (aggregate
->community
)
8083 community
= community_dup(aggregate
->community
);
8085 /* Retrieve aggregate route's ecommunity.
8087 if (aggregate
->ecommunity
)
8088 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8090 /* Retrieve aggregate route's lcommunity.
8092 if (aggregate
->lcommunity
)
8093 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8096 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8097 aspath
, community
, ecommunity
,
8098 lcommunity
, atomic_aggregate
, aggregate
);
8101 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
8103 struct bgp_path_info
*pi
,
8104 struct bgp_aggregate
*aggregate
,
8105 const struct prefix
*aggr_p
)
8108 struct aspath
*aspath
= NULL
;
8109 uint8_t atomic_aggregate
= 0;
8110 struct community
*community
= NULL
;
8111 struct ecommunity
*ecommunity
= NULL
;
8112 struct lcommunity
*lcommunity
= NULL
;
8113 unsigned long match
= 0;
8115 /* If the bgp instance is being deleted or self peer is deleted
8116 * then do not create aggregate route
8118 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
8119 || (bgp
->peer_self
== NULL
))
8122 if (BGP_PATH_HOLDDOWN(pi
))
8125 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
8128 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8129 if (aggr_unsuppress_path(aggregate
, pi
))
8132 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8133 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
8134 if (aggr_unsuppress_path(aggregate
, pi
))
8138 * This must be called after `summary`, `suppress-map` check to avoid
8139 * "unsuppressing" twice.
8141 if (aggregate
->match_med
)
8142 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
);
8144 if (aggregate
->count
> 0)
8147 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
8148 aggregate
->incomplete_origin_count
--;
8149 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
8150 aggregate
->egp_origin_count
--;
8152 if (aggregate
->as_set
) {
8153 /* Remove as-path from aggregate.
8155 bgp_remove_aspath_from_aggregate(aggregate
,
8158 if (bgp_attr_get_community(pi
->attr
))
8159 /* Remove community from aggregate.
8161 bgp_remove_community_from_aggregate(
8162 aggregate
, bgp_attr_get_community(pi
->attr
));
8164 if (bgp_attr_get_ecommunity(pi
->attr
))
8165 /* Remove ecommunity from aggregate.
8167 bgp_remove_ecommunity_from_aggregate(
8168 aggregate
, bgp_attr_get_ecommunity(pi
->attr
));
8170 if (bgp_attr_get_lcommunity(pi
->attr
))
8171 /* Remove lcommunity from aggregate.
8173 bgp_remove_lcommunity_from_aggregate(
8174 aggregate
, bgp_attr_get_lcommunity(pi
->attr
));
8177 /* If this node was suppressed, process the change. */
8179 bgp_process(bgp
, pi
->net
, afi
, safi
);
8181 origin
= BGP_ORIGIN_IGP
;
8182 if (aggregate
->incomplete_origin_count
> 0)
8183 origin
= BGP_ORIGIN_INCOMPLETE
;
8184 else if (aggregate
->egp_origin_count
> 0)
8185 origin
= BGP_ORIGIN_EGP
;
8187 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8188 origin
= aggregate
->origin
;
8190 if (aggregate
->as_set
) {
8191 /* Retrieve aggregate route's as-path.
8193 if (aggregate
->aspath
)
8194 aspath
= aspath_dup(aggregate
->aspath
);
8196 /* Retrieve aggregate route's community.
8198 if (aggregate
->community
)
8199 community
= community_dup(aggregate
->community
);
8201 /* Retrieve aggregate route's ecommunity.
8203 if (aggregate
->ecommunity
)
8204 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8206 /* Retrieve aggregate route's lcommunity.
8208 if (aggregate
->lcommunity
)
8209 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8212 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8213 aspath
, community
, ecommunity
,
8214 lcommunity
, atomic_aggregate
, aggregate
);
8217 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
8218 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
8220 struct bgp_dest
*child
;
8221 struct bgp_dest
*dest
;
8222 struct bgp_aggregate
*aggregate
;
8223 struct bgp_table
*table
;
8225 table
= bgp
->aggregate
[afi
][safi
];
8227 /* No aggregates configured. */
8228 if (bgp_table_top_nolock(table
) == NULL
)
8231 if (p
->prefixlen
== 0)
8234 if (BGP_PATH_HOLDDOWN(pi
))
8237 /* If suppress fib is enabled and route not installed
8238 * in FIB, do not update the aggregate route
8240 if (!bgp_check_advertise(bgp
, pi
->net
))
8243 child
= bgp_node_get(table
, p
);
8245 /* Aggregate address configuration check. */
8246 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8247 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8249 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8250 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8251 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
8255 bgp_dest_unlock_node(child
);
8258 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
8259 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
8261 struct bgp_dest
*child
;
8262 struct bgp_dest
*dest
;
8263 struct bgp_aggregate
*aggregate
;
8264 struct bgp_table
*table
;
8266 table
= bgp
->aggregate
[afi
][safi
];
8268 /* No aggregates configured. */
8269 if (bgp_table_top_nolock(table
) == NULL
)
8272 if (p
->prefixlen
== 0)
8275 child
= bgp_node_get(table
, p
);
8277 /* Aggregate address configuration check. */
8278 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8279 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8281 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8282 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8283 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
8287 bgp_dest_unlock_node(child
);
8290 /* Aggregate route attribute. */
8291 #define AGGREGATE_SUMMARY_ONLY 1
8292 #define AGGREGATE_AS_SET 1
8293 #define AGGREGATE_AS_UNSET 0
8295 static const char *bgp_origin2str(uint8_t origin
)
8298 case BGP_ORIGIN_IGP
:
8300 case BGP_ORIGIN_EGP
:
8302 case BGP_ORIGIN_INCOMPLETE
:
8303 return "incomplete";
8308 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
8311 case RPKI_NOT_BEING_USED
:
8321 assert(!"We should never get here this is a dev escape");
8325 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
8326 afi_t afi
, safi_t safi
)
8328 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8331 struct bgp_dest
*dest
;
8332 struct bgp_aggregate
*aggregate
;
8334 /* Convert string to prefix structure. */
8335 ret
= str2prefix(prefix_str
, &p
);
8337 vty_out(vty
, "Malformed prefix\n");
8338 return CMD_WARNING_CONFIG_FAILED
;
8342 /* Old configuration check. */
8343 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
8346 "%% There is no aggregate-address configuration.\n");
8347 return CMD_WARNING_CONFIG_FAILED
;
8350 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8351 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
8352 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
8353 NULL
, NULL
, 0, aggregate
);
8355 /* Unlock aggregate address configuration. */
8356 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
8358 bgp_free_aggregate_info(aggregate
);
8359 bgp_dest_unlock_node(dest
);
8360 bgp_dest_unlock_node(dest
);
8365 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
8366 safi_t safi
, const char *rmap
,
8367 uint8_t summary_only
, uint8_t as_set
,
8368 uint8_t origin
, bool match_med
,
8369 const char *suppress_map
)
8371 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8374 struct bgp_dest
*dest
;
8375 struct bgp_aggregate
*aggregate
;
8376 uint8_t as_set_new
= as_set
;
8378 if (suppress_map
&& summary_only
) {
8380 "'summary-only' and 'suppress-map' can't be used at the same time\n");
8381 return CMD_WARNING_CONFIG_FAILED
;
8384 /* Convert string to prefix structure. */
8385 ret
= str2prefix(prefix_str
, &p
);
8387 vty_out(vty
, "Malformed prefix\n");
8388 return CMD_WARNING_CONFIG_FAILED
;
8392 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
8393 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
8394 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8396 return CMD_WARNING_CONFIG_FAILED
;
8399 /* Old configuration check. */
8400 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
8401 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8404 vty_out(vty
, "There is already same aggregate network.\n");
8405 /* try to remove the old entry */
8406 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
8408 vty_out(vty
, "Error deleting aggregate.\n");
8409 bgp_dest_unlock_node(dest
);
8410 return CMD_WARNING_CONFIG_FAILED
;
8414 /* Make aggregate address structure. */
8415 aggregate
= bgp_aggregate_new();
8416 aggregate
->summary_only
= summary_only
;
8417 aggregate
->match_med
= match_med
;
8419 /* Network operators MUST NOT locally generate any new
8420 * announcements containing AS_SET or AS_CONFED_SET. If they have
8421 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8422 * SHOULD withdraw those routes and re-announce routes for the
8423 * aggregate or component prefixes (i.e., the more-specific routes
8424 * subsumed by the previously aggregated route) without AS_SET
8425 * or AS_CONFED_SET in the updates.
8427 if (bgp
->reject_as_sets
) {
8428 if (as_set
== AGGREGATE_AS_SET
) {
8429 as_set_new
= AGGREGATE_AS_UNSET
;
8431 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8434 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8438 aggregate
->as_set
= as_set_new
;
8439 aggregate
->safi
= safi
;
8440 /* Override ORIGIN attribute if defined.
8441 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8442 * to IGP which is not what rfc4271 says.
8443 * This enables the same behavior, optionally.
8445 aggregate
->origin
= origin
;
8448 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
8449 route_map_counter_decrement(aggregate
->rmap
.map
);
8450 aggregate
->rmap
.name
=
8451 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
8452 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
8453 route_map_counter_increment(aggregate
->rmap
.map
);
8457 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
8458 route_map_counter_decrement(aggregate
->suppress_map
);
8460 aggregate
->suppress_map_name
=
8461 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
8462 aggregate
->suppress_map
=
8463 route_map_lookup_by_name(aggregate
->suppress_map_name
);
8464 route_map_counter_increment(aggregate
->suppress_map
);
8467 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
8469 /* Aggregate address insert into BGP routing table. */
8470 if (!bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
)) {
8471 bgp_aggregate_free(aggregate
);
8472 bgp_dest_unlock_node(dest
);
8478 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
8479 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8481 "|summary-only$summary_only"
8482 "|route-map RMAP_NAME$rmap_name"
8483 "|origin <egp|igp|incomplete>$origin_s"
8484 "|matching-MED-only$match_med"
8485 "|suppress-map RMAP_NAME$suppress_map"
8488 "Configure BGP aggregate entries\n"
8489 "Aggregate prefix\n"
8490 "Aggregate address\n"
8492 "Generate AS set path information\n"
8493 "Filter more specific routes from updates\n"
8494 "Apply route map to aggregate network\n"
8499 "Unknown heritage\n"
8500 "Only aggregate routes with matching MED\n"
8501 "Suppress the selected more specific routes\n"
8502 "Route map with the route selectors\n")
8504 const char *prefix_s
= NULL
;
8505 safi_t safi
= bgp_node_safi(vty
);
8506 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8507 int as_set
= AGGREGATE_AS_UNSET
;
8508 char prefix_buf
[PREFIX2STR_BUFFER
];
8511 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8514 vty_out(vty
, "%% Inconsistent address and mask\n");
8515 return CMD_WARNING_CONFIG_FAILED
;
8517 prefix_s
= prefix_buf
;
8519 prefix_s
= prefix_str
;
8522 if (strcmp(origin_s
, "egp") == 0)
8523 origin
= BGP_ORIGIN_EGP
;
8524 else if (strcmp(origin_s
, "igp") == 0)
8525 origin
= BGP_ORIGIN_IGP
;
8526 else if (strcmp(origin_s
, "incomplete") == 0)
8527 origin
= BGP_ORIGIN_INCOMPLETE
;
8531 as_set
= AGGREGATE_AS_SET
;
8533 /* Handle configuration removal, otherwise installation. */
8535 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8537 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8538 summary_only
!= NULL
, as_set
, origin
,
8539 match_med
!= NULL
, suppress_map
);
8542 void bgp_free_aggregate_info(struct bgp_aggregate
*aggregate
)
8544 if (aggregate
->community
)
8545 community_free(&aggregate
->community
);
8547 hash_clean_and_free(&aggregate
->community_hash
,
8548 bgp_aggr_community_remove
);
8550 if (aggregate
->ecommunity
)
8551 ecommunity_free(&aggregate
->ecommunity
);
8553 hash_clean_and_free(&aggregate
->ecommunity_hash
,
8554 bgp_aggr_ecommunity_remove
);
8556 if (aggregate
->lcommunity
)
8557 lcommunity_free(&aggregate
->lcommunity
);
8559 hash_clean_and_free(&aggregate
->lcommunity_hash
,
8560 bgp_aggr_lcommunity_remove
);
8562 if (aggregate
->aspath
)
8563 aspath_free(aggregate
->aspath
);
8565 hash_clean_and_free(&aggregate
->aspath_hash
, bgp_aggr_aspath_remove
);
8567 bgp_aggregate_free(aggregate
);
8570 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8571 "[no] aggregate-address X:X::X:X/M$prefix [{"
8573 "|summary-only$summary_only"
8574 "|route-map RMAP_NAME$rmap_name"
8575 "|origin <egp|igp|incomplete>$origin_s"
8576 "|matching-MED-only$match_med"
8577 "|suppress-map RMAP_NAME$suppress_map"
8580 "Configure BGP aggregate entries\n"
8581 "Aggregate prefix\n"
8582 "Generate AS set path information\n"
8583 "Filter more specific routes from updates\n"
8584 "Apply route map to aggregate network\n"
8589 "Unknown heritage\n"
8590 "Only aggregate routes with matching MED\n"
8591 "Suppress the selected more specific routes\n"
8592 "Route map with the route selectors\n")
8594 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8595 int as_set
= AGGREGATE_AS_UNSET
;
8598 if (strcmp(origin_s
, "egp") == 0)
8599 origin
= BGP_ORIGIN_EGP
;
8600 else if (strcmp(origin_s
, "igp") == 0)
8601 origin
= BGP_ORIGIN_IGP
;
8602 else if (strcmp(origin_s
, "incomplete") == 0)
8603 origin
= BGP_ORIGIN_INCOMPLETE
;
8607 as_set
= AGGREGATE_AS_SET
;
8609 /* Handle configuration removal, otherwise installation. */
8611 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8614 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8615 rmap_name
, summary_only
!= NULL
, as_set
,
8616 origin
, match_med
!= NULL
, suppress_map
);
8619 /* Redistribute route treatment. */
8620 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8621 const union g_addr
*nexthop
, ifindex_t ifindex
,
8622 enum nexthop_types_t nhtype
, uint8_t distance
,
8623 enum blackhole_type bhtype
, uint32_t metric
,
8624 uint8_t type
, unsigned short instance
,
8627 struct bgp_path_info
*new;
8628 struct bgp_path_info
*bpi
;
8629 struct bgp_path_info rmap_path
;
8630 struct bgp_dest
*bn
;
8632 struct attr
*new_attr
;
8634 route_map_result_t ret
;
8635 struct bgp_redist
*red
;
8637 /* Make default attribute. */
8638 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
8640 * This must not be NULL to satisfy Coverity SA
8642 assert(attr
.aspath
);
8645 case NEXTHOP_TYPE_IFINDEX
:
8646 switch (p
->family
) {
8648 attr
.nexthop
.s_addr
= INADDR_ANY
;
8649 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8652 memset(&attr
.mp_nexthop_global
, 0,
8653 sizeof(attr
.mp_nexthop_global
));
8654 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8658 case NEXTHOP_TYPE_IPV4
:
8659 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8660 attr
.nexthop
= nexthop
->ipv4
;
8661 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8663 case NEXTHOP_TYPE_IPV6
:
8664 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8665 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8666 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8668 case NEXTHOP_TYPE_BLACKHOLE
:
8669 switch (p
->family
) {
8671 attr
.nexthop
.s_addr
= INADDR_ANY
;
8672 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8675 memset(&attr
.mp_nexthop_global
, 0,
8676 sizeof(attr
.mp_nexthop_global
));
8677 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8680 attr
.bh_type
= bhtype
;
8683 attr
.nh_type
= nhtype
;
8684 attr
.nh_ifindex
= ifindex
;
8687 attr
.distance
= distance
;
8688 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8692 bgp_attr_set_aigp_metric(&attr
, metric
);
8694 afi
= family2afi(p
->family
);
8696 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8698 struct attr attr_new
;
8700 /* Copy attribute for modification. */
8703 if (red
->redist_metric_flag
) {
8704 attr_new
.med
= red
->redist_metric
;
8705 bgp_attr_set_aigp_metric(&attr_new
, red
->redist_metric
);
8708 /* Apply route-map. */
8709 if (red
->rmap
.name
) {
8710 memset(&rmap_path
, 0, sizeof(rmap_path
));
8711 rmap_path
.peer
= bgp
->peer_self
;
8712 rmap_path
.attr
= &attr_new
;
8714 SET_FLAG(bgp
->peer_self
->rmap_type
,
8715 PEER_RMAP_TYPE_REDISTRIBUTE
);
8717 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8719 bgp
->peer_self
->rmap_type
= 0;
8721 if (ret
== RMAP_DENYMATCH
) {
8722 /* Free uninterned attribute. */
8723 bgp_attr_flush(&attr_new
);
8725 /* Unintern original. */
8726 aspath_unintern(&attr
.aspath
);
8727 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8732 if (bgp_in_graceful_shutdown(bgp
))
8733 bgp_attr_add_gshut_community(&attr_new
);
8735 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8736 SAFI_UNICAST
, p
, NULL
);
8738 new_attr
= bgp_attr_intern(&attr_new
);
8740 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8741 if (bpi
->peer
== bgp
->peer_self
8742 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8746 /* Ensure the (source route) type is updated. */
8748 if (attrhash_cmp(bpi
->attr
, new_attr
)
8749 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8750 bgp_attr_unintern(&new_attr
);
8751 aspath_unintern(&attr
.aspath
);
8752 bgp_dest_unlock_node(bn
);
8755 /* The attribute is changed. */
8756 bgp_path_info_set_flag(bn
, bpi
,
8757 BGP_PATH_ATTR_CHANGED
);
8759 /* Rewrite BGP route information. */
8760 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8761 bgp_path_info_restore(bn
, bpi
);
8763 bgp_aggregate_decrement(
8764 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8765 bgp_attr_unintern(&bpi
->attr
);
8766 bpi
->attr
= new_attr
;
8767 bpi
->uptime
= monotime(NULL
);
8769 /* Process change. */
8770 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8772 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8773 bgp_dest_unlock_node(bn
);
8774 aspath_unintern(&attr
.aspath
);
8776 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8778 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8780 vpn_leak_from_vrf_update(
8781 bgp_get_default(), bgp
, bpi
);
8787 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8788 bgp
->peer_self
, new_attr
, bn
);
8789 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8791 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8792 bgp_path_info_add(bn
, new);
8793 bgp_dest_unlock_node(bn
);
8794 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8795 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8797 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8798 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8800 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8804 /* Unintern original. */
8805 aspath_unintern(&attr
.aspath
);
8808 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8809 unsigned short instance
)
8812 struct bgp_dest
*dest
;
8813 struct bgp_path_info
*pi
;
8814 struct bgp_redist
*red
;
8816 afi
= family2afi(p
->family
);
8818 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8820 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8821 SAFI_UNICAST
, p
, NULL
);
8823 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8824 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8828 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8829 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8831 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8834 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8835 bgp_path_info_delete(dest
, pi
);
8836 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8838 bgp_dest_unlock_node(dest
);
8842 /* Withdraw specified route type's route. */
8843 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8844 unsigned short instance
)
8846 struct bgp_dest
*dest
;
8847 struct bgp_path_info
*pi
;
8848 struct bgp_table
*table
;
8850 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8852 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8853 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8854 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8855 && pi
->instance
== instance
)
8859 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8860 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8862 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8865 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8866 pi
, afi
, SAFI_UNICAST
);
8867 bgp_path_info_delete(dest
, pi
);
8868 if (!CHECK_FLAG(bgp
->flags
,
8869 BGP_FLAG_DELETE_IN_PROGRESS
))
8870 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8872 bgp_path_info_reap(dest
, pi
);
8877 /* Static function to display route. */
8878 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8879 struct vty
*vty
, json_object
*json
, bool wide
)
8882 char buf
[INET6_ADDRSTRLEN
];
8884 if (p
->family
== AF_INET
) {
8886 len
= vty_out(vty
, "%pFX", p
);
8888 json_object_string_add(json
, "prefix",
8889 inet_ntop(p
->family
,
8892 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8893 json_object_string_addf(json
, "network", "%pFX", p
);
8894 json_object_int_add(json
, "version", dest
->version
);
8896 } else if (p
->family
== AF_ETHERNET
) {
8897 len
= vty_out(vty
, "%pFX", p
);
8898 } else if (p
->family
== AF_EVPN
) {
8900 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8902 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8903 } else if (p
->family
== AF_FLOWSPEC
) {
8904 route_vty_out_flowspec(vty
, p
, NULL
,
8906 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8907 NLRI_STRING_FORMAT_MIN
, json
);
8910 len
= vty_out(vty
, "%pFX", p
);
8912 json_object_string_add(json
, "prefix",
8913 inet_ntop(p
->family
,
8916 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8917 json_object_string_addf(json
, "network", "%pFX", p
);
8918 json_object_int_add(json
, "version", dest
->version
);
8923 len
= wide
? (45 - len
) : (17 - len
);
8925 vty_out(vty
, "\n%*s", 20, " ");
8927 vty_out(vty
, "%*s", len
, " ");
8931 enum bgp_display_type
{
8935 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8938 case bgp_path_selection_none
:
8939 return "Nothing to Select";
8940 case bgp_path_selection_first
:
8941 return "First path received";
8942 case bgp_path_selection_evpn_sticky_mac
:
8943 return "EVPN Sticky Mac";
8944 case bgp_path_selection_evpn_seq
:
8945 return "EVPN sequence number";
8946 case bgp_path_selection_evpn_lower_ip
:
8947 return "EVPN lower IP";
8948 case bgp_path_selection_evpn_local_path
:
8949 return "EVPN local ES path";
8950 case bgp_path_selection_evpn_non_proxy
:
8951 return "EVPN non proxy";
8952 case bgp_path_selection_weight
:
8954 case bgp_path_selection_local_pref
:
8955 return "Local Pref";
8956 case bgp_path_selection_accept_own
:
8957 return "Accept Own";
8958 case bgp_path_selection_local_route
:
8959 return "Local Route";
8960 case bgp_path_selection_aigp
:
8962 case bgp_path_selection_confed_as_path
:
8963 return "Confederation based AS Path";
8964 case bgp_path_selection_as_path
:
8966 case bgp_path_selection_origin
:
8968 case bgp_path_selection_med
:
8970 case bgp_path_selection_peer
:
8972 case bgp_path_selection_confed
:
8973 return "Confed Peer Type";
8974 case bgp_path_selection_igp_metric
:
8975 return "IGP Metric";
8976 case bgp_path_selection_older
:
8977 return "Older Path";
8978 case bgp_path_selection_router_id
:
8980 case bgp_path_selection_cluster_length
:
8981 return "Cluster length";
8982 case bgp_path_selection_stale
:
8983 return "Path Staleness";
8984 case bgp_path_selection_local_configured
:
8985 return "Locally configured route";
8986 case bgp_path_selection_neighbor_ip
:
8987 return "Neighbor IP";
8988 case bgp_path_selection_default
:
8989 return "Nothing left to compare";
8991 return "Invalid (internal error)";
8994 /* Print the short form route status for a bgp_path_info */
8995 static void route_vty_short_status_out(struct vty
*vty
,
8996 struct bgp_path_info
*path
,
8997 const struct prefix
*p
,
8998 json_object
*json_path
)
9000 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
9004 /* Route status display. */
9005 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9006 json_object_boolean_true_add(json_path
, "removed");
9008 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9009 json_object_boolean_true_add(json_path
, "stale");
9011 if (path
->extra
&& bgp_path_suppressed(path
))
9012 json_object_boolean_true_add(json_path
, "suppressed");
9014 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9015 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9016 json_object_boolean_true_add(json_path
, "valid");
9019 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9020 json_object_boolean_true_add(json_path
, "history");
9022 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9023 json_object_boolean_true_add(json_path
, "damped");
9025 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9026 json_object_boolean_true_add(json_path
, "bestpath");
9027 json_object_string_add(json_path
, "selectionReason",
9028 bgp_path_selection_reason2str(
9029 path
->net
->reason
));
9032 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9033 json_object_boolean_true_add(json_path
, "multipath");
9035 /* Internal route. */
9036 if ((path
->peer
->as
)
9037 && (path
->peer
->as
== path
->peer
->local_as
))
9038 json_object_string_add(json_path
, "pathFrom",
9041 json_object_string_add(json_path
, "pathFrom",
9047 /* RPKI validation state */
9049 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
9051 if (rpki_state
== RPKI_VALID
)
9053 else if (rpki_state
== RPKI_INVALID
)
9055 else if (rpki_state
== RPKI_NOTFOUND
)
9060 /* Route status display. */
9061 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9063 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9065 else if (bgp_path_suppressed(path
))
9067 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9068 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9074 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9076 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9078 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
9080 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9085 /* Internal route. */
9086 if (path
->peer
&& (path
->peer
->as
)
9087 && (path
->peer
->as
== path
->peer
->local_as
))
9093 static char *bgp_nexthop_hostname(struct peer
*peer
,
9094 struct bgp_nexthop_cache
*bnc
)
9097 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
9098 return peer
->hostname
;
9102 /* called from terminal list command */
9103 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9104 struct bgp_path_info
*path
, int display
, safi_t safi
,
9105 json_object
*json_paths
, bool wide
)
9108 struct attr
*attr
= path
->attr
;
9109 json_object
*json_path
= NULL
;
9110 json_object
*json_nexthops
= NULL
;
9111 json_object
*json_nexthop_global
= NULL
;
9112 json_object
*json_nexthop_ll
= NULL
;
9113 json_object
*json_ext_community
= NULL
;
9114 char vrf_id_str
[VRF_NAMSIZ
] = {0};
9116 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9117 bool nexthop_othervrf
= false;
9118 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
9119 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
9120 char *nexthop_hostname
=
9121 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9122 char esi_buf
[ESI_STR_LEN
];
9125 json_path
= json_object_new_object();
9127 /* short status lead text */
9128 route_vty_short_status_out(vty
, path
, p
, json_path
);
9131 /* print prefix and mask */
9133 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9135 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
9137 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9141 * If vrf id of nexthop is different from that of prefix,
9142 * set up printable string to append
9144 if (path
->extra
&& path
->extra
->bgp_orig
) {
9145 const char *self
= "";
9150 nexthop_othervrf
= true;
9151 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9153 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
9154 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
9155 "@%s%s", VRFID_NONE_STR
, self
);
9157 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
9158 path
->extra
->bgp_orig
->vrf_id
, self
);
9160 if (path
->extra
->bgp_orig
->inst_type
9161 != BGP_INSTANCE_TYPE_DEFAULT
)
9163 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
9165 const char *self
= "";
9170 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
9174 * For ENCAP and EVPN routes, nexthop address family is not
9175 * neccessarily the same as the prefix address family.
9176 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9177 * EVPN routes are also exchanged with a MP nexthop. Currently,
9179 * is only IPv4, the value will be present in either
9181 * attr->mp_nexthop_global_in
9183 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
9185 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9189 snprintfrr(nexthop
, sizeof(nexthop
), "%pI4",
9190 &attr
->mp_nexthop_global_in
);
9193 snprintfrr(nexthop
, sizeof(nexthop
), "%pI6",
9194 &attr
->mp_nexthop_global
);
9197 snprintf(nexthop
, sizeof(nexthop
), "?");
9202 json_nexthop_global
= json_object_new_object();
9204 json_object_string_add(json_nexthop_global
, "ip",
9207 if (path
->peer
->hostname
)
9208 json_object_string_add(json_nexthop_global
,
9210 path
->peer
->hostname
);
9212 json_object_string_add(json_nexthop_global
, "afi",
9213 (af
== AF_INET
) ? "ipv4"
9215 json_object_boolean_true_add(json_nexthop_global
,
9218 if (nexthop_hostname
)
9219 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
9220 nexthop_hostname
, vrf_id_str
);
9222 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
9224 len
= wide
? (41 - len
) : (16 - len
);
9226 vty_out(vty
, "\n%*s", 36, " ");
9228 vty_out(vty
, "%*s", len
, " ");
9230 } else if (safi
== SAFI_EVPN
) {
9232 json_nexthop_global
= json_object_new_object();
9234 json_object_string_addf(json_nexthop_global
, "ip",
9236 &attr
->mp_nexthop_global_in
);
9238 if (path
->peer
->hostname
)
9239 json_object_string_add(json_nexthop_global
,
9241 path
->peer
->hostname
);
9243 json_object_string_add(json_nexthop_global
, "afi",
9245 json_object_boolean_true_add(json_nexthop_global
,
9248 if (nexthop_hostname
)
9249 len
= vty_out(vty
, "%pI4(%s)%s",
9250 &attr
->mp_nexthop_global_in
,
9251 nexthop_hostname
, vrf_id_str
);
9253 len
= vty_out(vty
, "%pI4%s",
9254 &attr
->mp_nexthop_global_in
,
9257 len
= wide
? (41 - len
) : (16 - len
);
9259 vty_out(vty
, "\n%*s", 36, " ");
9261 vty_out(vty
, "%*s", len
, " ");
9263 } else if (safi
== SAFI_FLOWSPEC
) {
9264 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
9266 json_nexthop_global
= json_object_new_object();
9268 json_object_string_add(json_nexthop_global
,
9270 json_object_string_addf(json_nexthop_global
,
9274 if (path
->peer
->hostname
)
9275 json_object_string_add(
9276 json_nexthop_global
, "hostname",
9277 path
->peer
->hostname
);
9279 json_object_boolean_true_add(
9280 json_nexthop_global
,
9283 if (nexthop_hostname
)
9284 len
= vty_out(vty
, "%pI4(%s)%s",
9289 len
= vty_out(vty
, "%pI4%s",
9293 len
= wide
? (41 - len
) : (16 - len
);
9295 vty_out(vty
, "\n%*s", 36, " ");
9297 vty_out(vty
, "%*s", len
, " ");
9300 } else if (p
->family
== AF_INET
&& !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9302 json_nexthop_global
= json_object_new_object();
9304 json_object_string_addf(json_nexthop_global
, "ip",
9305 "%pI4", &attr
->nexthop
);
9307 if (path
->peer
->hostname
)
9308 json_object_string_add(json_nexthop_global
,
9310 path
->peer
->hostname
);
9312 json_object_string_add(json_nexthop_global
, "afi",
9314 json_object_boolean_true_add(json_nexthop_global
,
9317 if (nexthop_hostname
)
9318 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
9319 nexthop_hostname
, vrf_id_str
);
9321 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
9324 len
= wide
? (41 - len
) : (16 - len
);
9326 vty_out(vty
, "\n%*s", 36, " ");
9328 vty_out(vty
, "%*s", len
, " ");
9333 else if (p
->family
== AF_INET6
|| BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9335 json_nexthop_global
= json_object_new_object();
9336 json_object_string_addf(json_nexthop_global
, "ip",
9338 &attr
->mp_nexthop_global
);
9340 if (path
->peer
->hostname
)
9341 json_object_string_add(json_nexthop_global
,
9343 path
->peer
->hostname
);
9345 json_object_string_add(json_nexthop_global
, "afi",
9347 json_object_string_add(json_nexthop_global
, "scope",
9350 /* We display both LL & GL if both have been
9352 if ((attr
->mp_nexthop_len
9353 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9354 || (path
->peer
->conf_if
)) {
9355 json_nexthop_ll
= json_object_new_object();
9356 json_object_string_addf(
9357 json_nexthop_ll
, "ip", "%pI6",
9358 &attr
->mp_nexthop_local
);
9360 if (path
->peer
->hostname
)
9361 json_object_string_add(
9362 json_nexthop_ll
, "hostname",
9363 path
->peer
->hostname
);
9365 json_object_string_add(json_nexthop_ll
, "afi",
9367 json_object_string_add(json_nexthop_ll
, "scope",
9370 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9371 &attr
->mp_nexthop_local
)
9373 && !attr
->mp_nexthop_prefer_global
)
9374 json_object_boolean_true_add(
9375 json_nexthop_ll
, "used");
9377 json_object_boolean_true_add(
9378 json_nexthop_global
, "used");
9380 json_object_boolean_true_add(
9381 json_nexthop_global
, "used");
9383 /* Display LL if LL/Global both in table unless
9384 * prefer-global is set */
9385 if (((attr
->mp_nexthop_len
9386 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9387 && !attr
->mp_nexthop_prefer_global
)
9388 || (path
->peer
->conf_if
)) {
9389 if (path
->peer
->conf_if
) {
9390 len
= vty_out(vty
, "%s",
9391 path
->peer
->conf_if
);
9392 /* len of IPv6 addr + max len of def
9394 len
= wide
? (41 - len
) : (16 - len
);
9397 vty_out(vty
, "\n%*s", 36, " ");
9399 vty_out(vty
, "%*s", len
, " ");
9401 if (nexthop_hostname
)
9404 &attr
->mp_nexthop_local
,
9410 &attr
->mp_nexthop_local
,
9413 len
= wide
? (41 - len
) : (16 - len
);
9416 vty_out(vty
, "\n%*s", 36, " ");
9418 vty_out(vty
, "%*s", len
, " ");
9421 if (nexthop_hostname
)
9422 len
= vty_out(vty
, "%pI6(%s)%s",
9423 &attr
->mp_nexthop_global
,
9427 len
= vty_out(vty
, "%pI6%s",
9428 &attr
->mp_nexthop_global
,
9431 len
= wide
? (41 - len
) : (16 - len
);
9434 vty_out(vty
, "\n%*s", 36, " ");
9436 vty_out(vty
, "%*s", len
, " ");
9442 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9444 json_object_int_add(json_path
, "metric", attr
->med
);
9446 vty_out(vty
, "%7u", attr
->med
);
9448 vty_out(vty
, "%10u", attr
->med
);
9449 else if (!json_paths
) {
9451 vty_out(vty
, "%*s", 7, " ");
9453 vty_out(vty
, "%*s", 10, " ");
9457 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9459 json_object_int_add(json_path
, "locPrf",
9462 vty_out(vty
, "%7u", attr
->local_pref
);
9463 else if (!json_paths
)
9467 json_object_int_add(json_path
, "weight", attr
->weight
);
9469 vty_out(vty
, "%7u ", attr
->weight
);
9472 json_object_string_addf(json_path
, "peerId", "%pSU",
9478 json_object_string_add(json_path
, "path",
9481 aspath_print_vty(vty
, attr
->aspath
);
9486 json_object_string_add(json_path
, "origin",
9487 bgp_origin_long_str
[attr
->origin
]);
9489 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9492 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9493 json_object_string_add(json_path
, "esi",
9494 esi_to_str(&attr
->esi
,
9495 esi_buf
, sizeof(esi_buf
)));
9497 if (safi
== SAFI_EVPN
&&
9498 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9499 json_ext_community
= json_object_new_object();
9500 json_object_string_add(
9501 json_ext_community
, "string",
9502 bgp_attr_get_ecommunity(attr
)->str
);
9503 json_object_object_add(json_path
,
9504 "extendedCommunity",
9505 json_ext_community
);
9509 json_object_boolean_true_add(json_path
,
9510 "announceNexthopSelf");
9511 if (nexthop_othervrf
) {
9512 json_object_string_add(json_path
, "nhVrfName",
9515 json_object_int_add(json_path
, "nhVrfId",
9516 ((nexthop_vrfid
== VRF_UNKNOWN
)
9518 : (int)nexthop_vrfid
));
9523 if (json_nexthop_global
|| json_nexthop_ll
) {
9524 json_nexthops
= json_object_new_array();
9526 if (json_nexthop_global
)
9527 json_object_array_add(json_nexthops
,
9528 json_nexthop_global
);
9530 if (json_nexthop_ll
)
9531 json_object_array_add(json_nexthops
,
9534 json_object_object_add(json_path
, "nexthops",
9538 json_object_array_add(json_paths
, json_path
);
9542 if (safi
== SAFI_EVPN
) {
9543 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9544 /* XXX - add these params to the json out */
9545 vty_out(vty
, "%*s", 20, " ");
9546 vty_out(vty
, "ESI:%s",
9547 esi_to_str(&attr
->esi
, esi_buf
,
9553 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9554 vty_out(vty
, "%*s", 20, " ");
9555 vty_out(vty
, "%s\n",
9556 bgp_attr_get_ecommunity(attr
)->str
);
9560 #ifdef ENABLE_BGP_VNC
9561 /* prints an additional line, indented, with VNC info, if
9563 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9564 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9569 /* called from terminal list command */
9570 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9571 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9572 bool use_json
, json_object
*json_ar
, bool wide
)
9574 json_object
*json_status
= NULL
;
9575 json_object
*json_net
= NULL
;
9579 /* Route status display. */
9581 json_status
= json_object_new_object();
9582 json_net
= json_object_new_object();
9589 /* print prefix and mask */
9591 if (safi
== SAFI_EVPN
)
9592 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9593 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9594 json_object_string_add(
9595 json_net
, "addrPrefix",
9596 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9598 json_object_int_add(json_net
, "prefixLen",
9600 json_object_string_addf(json_net
, "network", "%pFX", p
);
9603 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9605 /* Print attribute */
9608 if (p
->family
== AF_INET
&&
9609 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9610 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9611 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9612 json_object_string_addf(
9613 json_net
, "nextHop", "%pI4",
9614 &attr
->mp_nexthop_global_in
);
9616 json_object_string_addf(
9617 json_net
, "nextHop", "%pI4",
9619 } else if (p
->family
== AF_INET6
||
9620 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9621 json_object_string_addf(
9622 json_net
, "nextHopGlobal", "%pI6",
9623 &attr
->mp_nexthop_global
);
9624 } else if (p
->family
== AF_EVPN
&&
9625 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9626 json_object_string_addf(
9627 json_net
, "nextHop", "%pI4",
9628 &attr
->mp_nexthop_global_in
);
9632 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9633 json_object_int_add(json_net
, "metric",
9636 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9637 json_object_int_add(json_net
, "locPrf",
9640 json_object_int_add(json_net
, "weight", attr
->weight
);
9644 json_object_string_add(json_net
, "path",
9648 #if CONFDATE > 20231208
9649 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9651 json_object_string_add(json_net
, "bgpOriginCode",
9652 bgp_origin_str
[attr
->origin
]);
9653 json_object_string_add(
9655 bgp_origin_long_str
[attr
->origin
]);
9657 if (p
->family
== AF_INET
&&
9658 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9659 safi
== SAFI_EVPN
||
9660 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9661 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9662 || safi
== SAFI_EVPN
)
9663 vty_out(vty
, "%-16pI4",
9664 &attr
->mp_nexthop_global_in
);
9666 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9668 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9669 } else if (p
->family
== AF_INET6
||
9670 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9671 len
= vty_out(vty
, "%pI6",
9672 &attr
->mp_nexthop_global
);
9673 len
= wide
? (41 - len
) : (16 - len
);
9675 vty_out(vty
, "\n%*s", 36, " ");
9677 vty_out(vty
, "%*s", len
, " ");
9680 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9682 vty_out(vty
, "%7u", attr
->med
);
9684 vty_out(vty
, "%10u", attr
->med
);
9690 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9691 vty_out(vty
, "%7u", attr
->local_pref
);
9695 vty_out(vty
, "%7u ", attr
->weight
);
9699 aspath_print_vty(vty
, attr
->aspath
);
9702 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9706 struct bgp_path_info
*bpi
= bgp_dest_get_bgp_path_info(dest
);
9708 #if CONFDATE > 20231208
9709 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9711 json_object_boolean_true_add(json_status
, "*");
9712 json_object_boolean_true_add(json_status
, ">");
9713 json_object_boolean_true_add(json_net
, "valid");
9714 json_object_boolean_true_add(json_net
, "best");
9716 if (bpi
&& CHECK_FLAG(bpi
->flags
, BGP_PATH_MULTIPATH
)) {
9717 json_object_boolean_true_add(json_status
, "=");
9718 json_object_boolean_true_add(json_net
, "multipath");
9720 json_object_object_add(json_net
, "appliedStatusSymbols",
9722 json_object_object_addf(json_ar
, json_net
, "%pFX", p
);
9727 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9728 struct bgp_path_info
*path
, int display
, safi_t safi
,
9731 json_object
*json_out
= NULL
;
9733 mpls_label_t label
= MPLS_INVALID_LABEL
;
9739 json_out
= json_object_new_object();
9741 /* short status lead text */
9742 route_vty_short_status_out(vty
, path
, p
, json_out
);
9744 /* print prefix and mask */
9747 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9749 vty_out(vty
, "%*s", 17, " ");
9752 /* Print attribute */
9754 if (((p
->family
== AF_INET
) &&
9755 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9756 (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) ||
9757 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9758 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9759 || safi
== SAFI_EVPN
) {
9761 json_object_string_addf(
9762 json_out
, "mpNexthopGlobalIn", "%pI4",
9763 &attr
->mp_nexthop_global_in
);
9765 vty_out(vty
, "%-16pI4",
9766 &attr
->mp_nexthop_global_in
);
9769 json_object_string_addf(json_out
, "nexthop",
9770 "%pI4", &attr
->nexthop
);
9772 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9774 } else if (((p
->family
== AF_INET6
) &&
9775 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9776 (safi
== SAFI_EVPN
&& BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) ||
9777 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9780 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9782 json_object_string_addf(
9783 json_out
, "mpNexthopGlobalIn", "%pI6",
9784 &attr
->mp_nexthop_global
);
9788 &attr
->mp_nexthop_global
,
9789 buf_a
, sizeof(buf_a
)));
9790 } else if (attr
->mp_nexthop_len
9791 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9792 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9793 &attr
->mp_nexthop_global
,
9794 &attr
->mp_nexthop_local
);
9796 json_object_string_add(json_out
,
9797 "mpNexthopGlobalLocal",
9800 vty_out(vty
, "%s", buf_a
);
9804 label
= decode_label(&path
->extra
->label
[0]);
9806 if (bgp_is_valid_label(&label
)) {
9808 json_object_int_add(json_out
, "notag", label
);
9809 json_object_array_add(json
, json_out
);
9811 vty_out(vty
, "notag/%d", label
);
9818 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9819 struct bgp_path_info
*path
, int display
,
9820 json_object
*json_paths
)
9823 json_object
*json_path
= NULL
;
9824 json_object
*json_nexthop
= NULL
;
9825 json_object
*json_overlay
= NULL
;
9831 json_path
= json_object_new_object();
9832 json_overlay
= json_object_new_object();
9833 json_nexthop
= json_object_new_object();
9836 /* short status lead text */
9837 route_vty_short_status_out(vty
, path
, p
, json_path
);
9839 /* print prefix and mask */
9841 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9843 vty_out(vty
, "%*s", 17, " ");
9845 /* Print attribute */
9847 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9852 vty_out(vty
, "%-16pI4", &attr
->mp_nexthop_global_in
);
9854 json_object_string_addf(json_nexthop
, "ip", "%pI4",
9855 &attr
->mp_nexthop_global_in
);
9857 json_object_string_add(json_nexthop
, "afi", "ipv4");
9859 json_object_object_add(json_path
, "nexthop",
9865 vty_out(vty
, "%pI6(%pI6)", &attr
->mp_nexthop_global
,
9866 &attr
->mp_nexthop_local
);
9868 json_object_string_addf(json_nexthop
, "ipv6Global",
9870 &attr
->mp_nexthop_global
);
9872 json_object_string_addf(json_nexthop
, "ipv6LinkLocal",
9874 &attr
->mp_nexthop_local
);
9876 json_object_string_add(json_nexthop
, "afi", "ipv6");
9878 json_object_object_add(json_path
, "nexthop",
9886 json_object_string_add(json_nexthop
, "error",
9887 "Unsupported address-family");
9891 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9894 vty_out(vty
, "/%pIA", &eo
->gw_ip
);
9896 json_object_string_addf(json_overlay
, "gw", "%pIA", &eo
->gw_ip
);
9898 if (bgp_attr_get_ecommunity(attr
)) {
9900 struct ecommunity_val
*routermac
= ecommunity_lookup(
9901 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9902 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9905 mac
= ecom_mac2str((char *)routermac
->val
);
9908 vty_out(vty
, "/%s", mac
);
9910 json_object_string_add(json_overlay
, "rmac",
9913 XFREE(MTYPE_TMP
, mac
);
9920 json_object_object_add(json_path
, "overlay", json_overlay
);
9922 json_object_array_add(json_paths
, json_path
);
9926 /* dampening route */
9927 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9928 struct bgp_path_info
*path
, int display
,
9929 afi_t afi
, safi_t safi
, bool use_json
,
9930 json_object
*json_paths
)
9932 struct attr
*attr
= path
->attr
;
9934 char timebuf
[BGP_UPTIME_LEN
];
9935 json_object
*json_path
= NULL
;
9938 json_path
= json_object_new_object();
9940 /* short status lead text */
9941 route_vty_short_status_out(vty
, path
, p
, json_path
);
9943 /* print prefix and mask */
9946 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9948 vty_out(vty
, "%*s", 17, " ");
9950 len
= vty_out(vty
, "%s", path
->peer
->host
);
9954 vty_out(vty
, "\n%*s", 34, " ");
9956 vty_out(vty
, "%*s", len
, " ");
9959 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9960 BGP_UPTIME_LEN
, afi
, safi
,
9964 aspath_print_vty(vty
, attr
->aspath
);
9966 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9970 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9971 safi
, use_json
, json_path
);
9974 json_object_string_add(json_path
, "asPath",
9977 json_object_string_add(json_path
, "origin",
9978 bgp_origin_str
[attr
->origin
]);
9979 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9981 json_object_array_add(json_paths
, json_path
);
9986 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9987 struct bgp_path_info
*path
, int display
,
9988 afi_t afi
, safi_t safi
, bool use_json
,
9989 json_object
*json_paths
)
9991 struct attr
*attr
= path
->attr
;
9992 struct bgp_damp_info
*bdi
;
9993 char timebuf
[BGP_UPTIME_LEN
];
9995 json_object
*json_path
= NULL
;
10001 json_path
= json_object_new_object();
10003 bdi
= path
->extra
->damp_info
;
10005 /* short status lead text */
10006 route_vty_short_status_out(vty
, path
, p
, json_path
);
10010 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
10012 vty_out(vty
, "%*s", 17, " ");
10014 len
= vty_out(vty
, "%s", path
->peer
->host
);
10017 vty_out(vty
, "\n%*s", 33, " ");
10019 vty_out(vty
, "%*s", len
, " ");
10021 len
= vty_out(vty
, "%d", bdi
->flap
);
10026 vty_out(vty
, "%*s", len
, " ");
10028 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
10029 BGP_UPTIME_LEN
, 0, NULL
));
10031 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10032 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10033 vty_out(vty
, "%s ",
10034 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10035 BGP_UPTIME_LEN
, afi
,
10036 safi
, use_json
, NULL
));
10038 vty_out(vty
, "%*s ", 8, " ");
10041 aspath_print_vty(vty
, attr
->aspath
);
10043 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10045 vty_out(vty
, "\n");
10047 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10048 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
10050 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
10053 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10054 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10055 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10056 BGP_UPTIME_LEN
, afi
, safi
,
10057 use_json
, json_path
);
10060 json_object_string_add(json_path
, "asPath",
10061 attr
->aspath
->str
);
10063 json_object_string_add(json_path
, "origin",
10064 bgp_origin_str
[attr
->origin
]);
10066 json_object_array_add(json_paths
, json_path
);
10070 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
10071 int *first
, const char *header
,
10072 json_object
*json_adv_to
)
10074 json_object
*json_peer
= NULL
;
10077 /* 'advertised-to' is a dictionary of peers we have advertised
10079 * prefix too. The key is the peer's IP or swpX, the value is
10081 * hostname if we know it and "" if not.
10083 json_peer
= json_object_new_object();
10085 if (peer
->hostname
)
10086 json_object_string_add(json_peer
, "hostname",
10090 json_object_object_add(json_adv_to
, peer
->conf_if
,
10093 json_object_object_addf(json_adv_to
, json_peer
, "%pSU",
10097 vty_out(vty
, "%s", header
);
10102 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
10104 vty_out(vty
, " %s(%s)", peer
->hostname
,
10107 vty_out(vty
, " %s(%pSU)", peer
->hostname
,
10111 vty_out(vty
, " %s", peer
->conf_if
);
10113 vty_out(vty
, " %pSU", &peer
->su
);
10118 static void route_vty_out_tx_ids(struct vty
*vty
,
10119 struct bgp_addpath_info_data
*d
)
10123 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10124 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
10125 d
->addpath_tx_id
[i
],
10126 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
10130 static void route_vty_out_detail_es_info(struct vty
*vty
,
10131 struct bgp_path_info
*pi
,
10133 json_object
*json_path
)
10135 char esi_buf
[ESI_STR_LEN
];
10136 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
10137 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
10138 ATTR_ES_PEER_ROUTER
);
10139 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
10140 ATTR_ES_PEER_ACTIVE
);
10141 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
10142 ATTR_ES_PEER_PROXY
);
10143 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
10145 json_object
*json_es_info
= NULL
;
10147 json_object_string_add(
10150 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
10151 json_es_info
= json_object_new_object();
10153 json_object_boolean_true_add(
10154 json_es_info
, "localEs");
10156 json_object_boolean_true_add(
10157 json_es_info
, "peerActive");
10159 json_object_boolean_true_add(
10160 json_es_info
, "peerProxy");
10162 json_object_boolean_true_add(
10163 json_es_info
, "peerRouter");
10164 if (attr
->mm_sync_seqnum
)
10165 json_object_int_add(
10166 json_es_info
, "peerSeq",
10167 attr
->mm_sync_seqnum
);
10168 json_object_object_add(
10169 json_path
, "es_info",
10173 if (bgp_evpn_attr_is_sync(attr
))
10175 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10177 es_local
? "local-es":"",
10178 peer_proxy
? "proxy " : "",
10179 peer_active
? "active ":"",
10180 peer_router
? "router ":"",
10181 attr
->mm_sync_seqnum
);
10183 vty_out(vty
, " ESI %s %s\n",
10185 es_local
? "local-es":"");
10189 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
10190 const struct prefix
*p
, struct bgp_path_info
*path
,
10191 afi_t afi
, safi_t safi
,
10192 enum rpki_states rpki_curr_state
,
10193 json_object
*json_paths
)
10195 char buf
[INET6_ADDRSTRLEN
];
10197 struct attr
*attr
= path
->attr
;
10199 json_object
*json_bestpath
= NULL
;
10200 json_object
*json_cluster_list
= NULL
;
10201 json_object
*json_cluster_list_list
= NULL
;
10202 json_object
*json_ext_community
= NULL
;
10203 json_object
*json_last_update
= NULL
;
10204 json_object
*json_pmsi
= NULL
;
10205 json_object
*json_nexthop_global
= NULL
;
10206 json_object
*json_nexthop_ll
= NULL
;
10207 json_object
*json_nexthops
= NULL
;
10208 json_object
*json_path
= NULL
;
10209 json_object
*json_peer
= NULL
;
10210 json_object
*json_string
= NULL
;
10211 json_object
*json_adv_to
= NULL
;
10213 struct listnode
*node
, *nnode
;
10215 bool addpath_capable
;
10217 unsigned int first_as
;
10218 bool nexthop_self
=
10219 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
10221 char *nexthop_hostname
=
10222 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
10226 mpls_label_t label
= MPLS_INVALID_LABEL
;
10228 struct bgp_path_info
*bpi_ultimate
=
10229 bgp_get_imported_bpi_ultimate(path
);
10232 json_path
= json_object_new_object();
10233 json_peer
= json_object_new_object();
10234 json_nexthop_global
= json_object_new_object();
10237 if (safi
== SAFI_EVPN
) {
10239 vty_out(vty
, " Route %pFX", p
);
10243 if (path
->extra
&& path
->extra
->num_labels
) {
10244 bgp_evpn_label2str(path
->extra
->label
,
10245 path
->extra
->num_labels
, tag_buf
,
10248 if (safi
== SAFI_EVPN
) {
10250 if (tag_buf
[0] != '\0')
10251 vty_out(vty
, " VNI %s", tag_buf
);
10254 json_object_string_add(json_path
, "vni",
10260 if (safi
== SAFI_EVPN
10261 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
10262 char gwip_buf
[INET6_ADDRSTRLEN
];
10264 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
10268 json_object_string_add(json_path
, "gatewayIP",
10271 vty_out(vty
, " Gateway IP %s", gwip_buf
);
10274 if (safi
== SAFI_EVPN
&& !json_path
)
10275 vty_out(vty
, "\n");
10278 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
10279 struct bgp_path_info
*parent_ri
;
10280 struct bgp_dest
*dest
, *pdest
;
10282 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
10283 dest
= parent_ri
->net
;
10284 if (dest
&& dest
->pdest
) {
10285 pdest
= dest
->pdest
;
10286 if (is_pi_family_evpn(parent_ri
)) {
10287 vty_out(vty
, " Imported from ");
10288 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
10289 (struct prefix_rd
*)bgp_dest_get_prefix(
10291 vty_out(vty
, ":%pFX, VNI %s",
10292 (struct prefix_evpn
*)
10293 bgp_dest_get_prefix(dest
),
10295 if (CHECK_FLAG(attr
->es_flags
, ATTR_ES_L3_NHG
))
10296 vty_out(vty
, ", L3NHG %s",
10299 ATTR_ES_L3_NHG_ACTIVE
)
10302 vty_out(vty
, "\n");
10305 vty_out(vty
, " Imported from ");
10306 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
10307 (struct prefix_rd
*)bgp_dest_get_prefix(
10309 vty_out(vty
, ":%pFX\n",
10310 (struct prefix_evpn
*)
10311 bgp_dest_get_prefix(dest
));
10316 /* Line1 display AS-path, Aggregator */
10317 if (attr
->aspath
) {
10319 if (!attr
->aspath
->json
)
10320 aspath_str_update(attr
->aspath
, true);
10321 json_object_lock(attr
->aspath
->json
);
10322 json_object_object_add(json_path
, "aspath",
10323 attr
->aspath
->json
);
10325 if (attr
->aspath
->segments
)
10326 vty_out(vty
, " %s", attr
->aspath
->str
);
10328 vty_out(vty
, " Local");
10332 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
10334 json_object_boolean_true_add(json_path
, "removed");
10336 vty_out(vty
, ", (removed)");
10339 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10341 json_object_boolean_true_add(json_path
, "stale");
10343 vty_out(vty
, ", (stale)");
10346 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
10348 json_object_int_add(json_path
, "aggregatorAs",
10349 attr
->aggregator_as
);
10350 json_object_string_addf(json_path
, "aggregatorId",
10351 "%pI4", &attr
->aggregator_addr
);
10353 vty_out(vty
, ", (aggregated by %u %pI4)",
10354 attr
->aggregator_as
, &attr
->aggregator_addr
);
10358 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10359 PEER_FLAG_REFLECTOR_CLIENT
)) {
10361 json_object_boolean_true_add(json_path
,
10362 "rxedFromRrClient");
10364 vty_out(vty
, ", (Received from a RR-client)");
10367 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10368 PEER_FLAG_RSERVER_CLIENT
)) {
10370 json_object_boolean_true_add(json_path
,
10371 "rxedFromRsClient");
10373 vty_out(vty
, ", (Received from a RS-client)");
10376 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10378 json_object_boolean_true_add(json_path
,
10379 "dampeningHistoryEntry");
10381 vty_out(vty
, ", (history entry)");
10382 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10384 json_object_boolean_true_add(json_path
,
10385 "dampeningSuppressed");
10387 vty_out(vty
, ", (suppressed due to dampening)");
10391 vty_out(vty
, "\n");
10393 /* Line2 display Next-hop, Neighbor, Router-id */
10394 /* Display the nexthop */
10396 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
||
10397 p
->family
== AF_EVPN
) &&
10398 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
||
10399 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10400 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10401 || safi
== SAFI_EVPN
) {
10403 json_object_string_addf(
10404 json_nexthop_global
, "ip", "%pI4",
10405 &attr
->mp_nexthop_global_in
);
10407 if (path
->peer
->hostname
)
10408 json_object_string_add(
10409 json_nexthop_global
, "hostname",
10410 path
->peer
->hostname
);
10412 if (nexthop_hostname
)
10413 vty_out(vty
, " %pI4(%s)",
10414 &attr
->mp_nexthop_global_in
,
10417 vty_out(vty
, " %pI4",
10418 &attr
->mp_nexthop_global_in
);
10422 json_object_string_addf(json_nexthop_global
,
10426 if (path
->peer
->hostname
)
10427 json_object_string_add(
10428 json_nexthop_global
, "hostname",
10429 path
->peer
->hostname
);
10431 if (nexthop_hostname
)
10432 vty_out(vty
, " %pI4(%s)",
10436 vty_out(vty
, " %pI4",
10442 json_object_string_add(json_nexthop_global
, "afi",
10446 json_object_string_addf(json_nexthop_global
, "ip",
10448 &attr
->mp_nexthop_global
);
10450 if (path
->peer
->hostname
)
10451 json_object_string_add(json_nexthop_global
,
10453 path
->peer
->hostname
);
10455 json_object_string_add(json_nexthop_global
, "afi",
10457 json_object_string_add(json_nexthop_global
, "scope",
10460 if (nexthop_hostname
)
10461 vty_out(vty
, " %pI6(%s)",
10462 &attr
->mp_nexthop_global
,
10465 vty_out(vty
, " %pI6",
10466 &attr
->mp_nexthop_global
);
10470 /* Display the IGP cost or 'inaccessible' */
10471 if (!CHECK_FLAG(bpi_ultimate
->flags
, BGP_PATH_VALID
)) {
10472 bool import
= CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
);
10475 json_object_boolean_false_add(json_nexthop_global
,
10477 json_object_boolean_add(json_nexthop_global
,
10478 "importCheckEnabled", import
);
10480 vty_out(vty
, " (inaccessible%s)",
10481 import
? ", import-check enabled" : "");
10484 if (bpi_ultimate
->extra
&& bpi_ultimate
->extra
->igpmetric
) {
10486 json_object_int_add(
10487 json_nexthop_global
, "metric",
10488 bpi_ultimate
->extra
->igpmetric
);
10490 vty_out(vty
, " (metric %u)",
10491 bpi_ultimate
->extra
->igpmetric
);
10494 /* IGP cost is 0, display this only for json */
10497 json_object_int_add(json_nexthop_global
,
10502 json_object_boolean_true_add(json_nexthop_global
,
10506 /* Display peer "from" output */
10507 /* This path was originated locally */
10508 if (path
->peer
== bgp
->peer_self
) {
10510 if (safi
== SAFI_EVPN
|| (p
->family
== AF_INET
&&
10511 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10513 json_object_string_add(json_peer
, "peerId",
10516 vty_out(vty
, " from 0.0.0.0 ");
10519 json_object_string_add(json_peer
, "peerId",
10522 vty_out(vty
, " from :: ");
10526 json_object_string_addf(json_peer
, "routerId", "%pI4",
10529 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10532 /* We RXed this path from one of our peers */
10536 json_object_string_addf(json_peer
, "peerId", "%pSU",
10538 json_object_string_addf(json_peer
, "routerId", "%pI4",
10539 &path
->peer
->remote_id
);
10541 if (path
->peer
->hostname
)
10542 json_object_string_add(json_peer
, "hostname",
10543 path
->peer
->hostname
);
10545 if (path
->peer
->domainname
)
10546 json_object_string_add(json_peer
, "domainname",
10547 path
->peer
->domainname
);
10549 if (path
->peer
->conf_if
)
10550 json_object_string_add(json_peer
, "interface",
10551 path
->peer
->conf_if
);
10553 if (path
->peer
->conf_if
) {
10554 if (path
->peer
->hostname
10555 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10556 BGP_FLAG_SHOW_HOSTNAME
))
10557 vty_out(vty
, " from %s(%s)",
10558 path
->peer
->hostname
,
10559 path
->peer
->conf_if
);
10561 vty_out(vty
, " from %s",
10562 path
->peer
->conf_if
);
10564 if (path
->peer
->hostname
10565 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10566 BGP_FLAG_SHOW_HOSTNAME
))
10567 vty_out(vty
, " from %s(%s)",
10568 path
->peer
->hostname
,
10571 vty_out(vty
, " from %pSU",
10575 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10576 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10578 vty_out(vty
, " (%pI4)", &path
->peer
->remote_id
);
10583 * Note when vrfid of nexthop is different from that of prefix
10585 if (path
->extra
&& path
->extra
->bgp_orig
) {
10586 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10591 if (path
->extra
->bgp_orig
->inst_type
10592 == BGP_INSTANCE_TYPE_DEFAULT
)
10593 vn
= VRF_DEFAULT_NAME
;
10595 vn
= path
->extra
->bgp_orig
->name
;
10597 json_object_string_add(json_path
, "nhVrfName", vn
);
10599 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10600 json_object_int_add(json_path
, "nhVrfId", -1);
10602 json_object_int_add(json_path
, "nhVrfId",
10603 (int)nexthop_vrfid
);
10606 if (nexthop_vrfid
== VRF_UNKNOWN
)
10607 vty_out(vty
, " vrf ?");
10611 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10612 vty_out(vty
, " vrf %s(%u)",
10613 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10618 if (nexthop_self
) {
10620 json_object_boolean_true_add(json_path
,
10621 "announceNexthopSelf");
10623 vty_out(vty
, " announce-nh-self");
10628 vty_out(vty
, "\n");
10630 /* display the link-local nexthop */
10631 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10633 json_nexthop_ll
= json_object_new_object();
10634 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10635 &attr
->mp_nexthop_local
);
10637 if (path
->peer
->hostname
)
10638 json_object_string_add(json_nexthop_ll
,
10640 path
->peer
->hostname
);
10642 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10643 json_object_string_add(json_nexthop_ll
, "scope",
10646 json_object_boolean_true_add(json_nexthop_ll
,
10649 if (!attr
->mp_nexthop_prefer_global
)
10650 json_object_boolean_true_add(json_nexthop_ll
,
10653 json_object_boolean_true_add(
10654 json_nexthop_global
, "used");
10656 vty_out(vty
, " (%s) %s\n",
10657 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10658 buf
, INET6_ADDRSTRLEN
),
10659 attr
->mp_nexthop_prefer_global
10660 ? "(prefer-global)"
10664 /* If we do not have a link-local nexthop then we must flag the
10665 global as "used" */
10668 json_object_boolean_true_add(json_nexthop_global
,
10672 if (safi
== SAFI_EVPN
&&
10673 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10674 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10677 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10678 * Int/Ext/Local, Atomic, best */
10680 json_object_string_add(json_path
, "origin",
10681 bgp_origin_long_str
[attr
->origin
]);
10683 vty_out(vty
, " Origin %s",
10684 bgp_origin_long_str
[attr
->origin
]);
10686 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10688 json_object_int_add(json_path
, "metric", attr
->med
);
10690 vty_out(vty
, ", metric %u", attr
->med
);
10693 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10695 json_object_int_add(json_path
, "locPrf",
10698 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10701 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
10703 json_object_int_add(json_path
, "aigpMetric",
10704 bgp_attr_get_aigp_metric(attr
));
10706 vty_out(vty
, ", aigp-metric %" PRIu64
,
10707 bgp_attr_get_aigp_metric(attr
));
10710 if (attr
->weight
!= 0) {
10712 json_object_int_add(json_path
, "weight", attr
->weight
);
10714 vty_out(vty
, ", weight %u", attr
->weight
);
10717 if (attr
->tag
!= 0) {
10719 json_object_int_add(json_path
, "tag", attr
->tag
);
10721 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10724 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10726 json_object_boolean_false_add(json_path
, "valid");
10728 vty_out(vty
, ", invalid");
10729 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10731 json_object_boolean_true_add(json_path
, "valid");
10733 vty_out(vty
, ", valid");
10737 json_object_int_add(json_path
, "version", bn
->version
);
10739 if (path
->peer
!= bgp
->peer_self
) {
10740 if (path
->peer
->as
== path
->peer
->local_as
) {
10741 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10743 json_object_string_add(
10745 "confed-internal");
10747 vty_out(vty
, ", confed-internal");
10750 json_object_string_add(
10751 json_peer
, "type", "internal");
10753 vty_out(vty
, ", internal");
10756 if (bgp_confederation_peers_check(bgp
,
10759 json_object_string_add(
10761 "confed-external");
10763 vty_out(vty
, ", confed-external");
10766 json_object_string_add(
10767 json_peer
, "type", "external");
10769 vty_out(vty
, ", external");
10772 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10774 json_object_boolean_true_add(json_path
, "aggregated");
10775 json_object_boolean_true_add(json_path
, "local");
10777 vty_out(vty
, ", aggregated, local");
10779 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10781 json_object_boolean_true_add(json_path
, "sourced");
10783 vty_out(vty
, ", sourced");
10786 json_object_boolean_true_add(json_path
, "sourced");
10787 json_object_boolean_true_add(json_path
, "local");
10789 vty_out(vty
, ", sourced, local");
10793 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10795 json_object_boolean_true_add(json_path
,
10796 "atomicAggregate");
10798 vty_out(vty
, ", atomic-aggregate");
10801 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
10803 json_object_int_add(json_path
, "otc", attr
->otc
);
10805 vty_out(vty
, ", otc %u", attr
->otc
);
10808 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10809 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10810 && bgp_path_info_mpath_count(path
))) {
10812 json_object_boolean_true_add(json_path
, "multipath");
10814 vty_out(vty
, ", multipath");
10817 // Mark the bestpath(s)
10818 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10819 first_as
= aspath_get_first_as(attr
->aspath
);
10822 if (!json_bestpath
)
10823 json_bestpath
= json_object_new_object();
10824 json_object_int_add(json_bestpath
, "bestpathFromAs",
10828 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10830 vty_out(vty
, ", bestpath-from-AS Local");
10834 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10836 if (!json_bestpath
)
10837 json_bestpath
= json_object_new_object();
10838 json_object_boolean_true_add(json_bestpath
, "overall");
10839 json_object_string_add(
10840 json_bestpath
, "selectionReason",
10841 bgp_path_selection_reason2str(bn
->reason
));
10843 vty_out(vty
, ", best");
10844 vty_out(vty
, " (%s)",
10845 bgp_path_selection_reason2str(bn
->reason
));
10849 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10851 json_object_string_add(
10852 json_path
, "rpkiValidationState",
10853 bgp_rpki_validation2str(rpki_curr_state
));
10855 vty_out(vty
, ", rpki validation-state: %s",
10856 bgp_rpki_validation2str(rpki_curr_state
));
10860 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10863 vty_out(vty
, "\n");
10865 /* Line 4 display Community */
10866 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10868 if (!bgp_attr_get_community(attr
)->json
)
10869 community_str(bgp_attr_get_community(attr
),
10871 json_object_lock(bgp_attr_get_community(attr
)->json
);
10872 json_object_object_add(
10873 json_path
, "community",
10874 bgp_attr_get_community(attr
)->json
);
10876 vty_out(vty
, " Community: %s\n",
10877 bgp_attr_get_community(attr
)->str
);
10881 /* Line 5 display Extended-community */
10882 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10884 json_ext_community
= json_object_new_object();
10885 json_object_string_add(
10886 json_ext_community
, "string",
10887 bgp_attr_get_ecommunity(attr
)->str
);
10888 json_object_object_add(json_path
, "extendedCommunity",
10889 json_ext_community
);
10891 vty_out(vty
, " Extended Community: %s\n",
10892 bgp_attr_get_ecommunity(attr
)->str
);
10896 /* Line 6 display Large community */
10897 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10899 if (!bgp_attr_get_lcommunity(attr
)->json
)
10900 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10902 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10903 json_object_object_add(
10904 json_path
, "largeCommunity",
10905 bgp_attr_get_lcommunity(attr
)->json
);
10907 vty_out(vty
, " Large Community: %s\n",
10908 bgp_attr_get_lcommunity(attr
)->str
);
10912 /* Line 7 display Originator, Cluster-id */
10913 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10914 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10915 char buf
[BUFSIZ
] = {0};
10917 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10919 json_object_string_addf(json_path
,
10920 "originatorId", "%pI4",
10921 &attr
->originator_id
);
10923 vty_out(vty
, " Originator: %pI4",
10924 &attr
->originator_id
);
10927 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10928 struct cluster_list
*cluster
=
10929 bgp_attr_get_cluster(attr
);
10933 json_cluster_list
= json_object_new_object();
10934 json_cluster_list_list
=
10935 json_object_new_array();
10937 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10938 json_string
= json_object_new_string(
10941 buf
, sizeof(buf
)));
10942 json_object_array_add(
10943 json_cluster_list_list
,
10948 * struct cluster_list does not have
10949 * "str" variable like aspath and community
10950 * do. Add this someday if someone asks
10952 * json_object_string_add(json_cluster_list,
10953 * "string", cluster->str);
10955 json_object_object_add(json_cluster_list
,
10957 json_cluster_list_list
);
10958 json_object_object_add(json_path
, "clusterList",
10959 json_cluster_list
);
10961 vty_out(vty
, ", Cluster list: ");
10963 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10964 vty_out(vty
, "%pI4 ",
10965 &cluster
->list
[i
]);
10971 vty_out(vty
, "\n");
10974 if (path
->extra
&& path
->extra
->damp_info
)
10975 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
10978 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10979 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10980 mpls_lse_decode(path
->extra
->label
[0], &label
, &ttl
, &exp
,
10984 json_object_int_add(json_path
, "remoteLabel", label
);
10986 vty_out(vty
, " Remote label: %d\n", label
);
10990 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10992 json_object_string_addf(json_path
, "remoteSid", "%pI6",
10993 &path
->extra
->sid
[0].sid
);
10995 vty_out(vty
, " Remote SID: %pI6\n",
10996 &path
->extra
->sid
[0].sid
);
11000 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
11002 json_object_int_add(json_path
, "labelIndex",
11003 attr
->label_index
);
11005 vty_out(vty
, " Label Index: %d\n",
11006 attr
->label_index
);
11009 /* Line 8 display Addpath IDs */
11010 if (path
->addpath_rx_id
11011 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
11013 json_object_int_add(json_path
, "addpathRxId",
11014 path
->addpath_rx_id
);
11016 /* Keep backwards compatibility with the old API
11017 * by putting TX All's ID in the old field
11019 json_object_int_add(
11020 json_path
, "addpathTxId",
11022 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
11024 /* ... but create a specific field for each
11027 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
11028 json_object_int_add(
11030 bgp_addpath_names(i
)->id_json_name
,
11031 path
->tx_addpath
.addpath_tx_id
[i
]);
11034 vty_out(vty
, " AddPath ID: RX %u, ",
11035 path
->addpath_rx_id
);
11037 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
11041 /* If we used addpath to TX a non-bestpath we need to display
11042 * "Advertised to" on a path-by-path basis
11044 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11047 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11049 bgp_addpath_encode_tx(peer
, afi
, safi
);
11050 has_adj
= bgp_adj_out_lookup(
11052 bgp_addpath_id_for_peer(peer
, afi
, safi
,
11053 &path
->tx_addpath
));
11055 if ((addpath_capable
&& has_adj
)
11056 || (!addpath_capable
&& has_adj
11057 && CHECK_FLAG(path
->flags
,
11058 BGP_PATH_SELECTED
))) {
11059 if (json_path
&& !json_adv_to
)
11060 json_adv_to
= json_object_new_object();
11062 route_vty_out_advertised_to(
11064 " Advertised to:", json_adv_to
);
11070 json_object_object_add(
11071 json_path
, "advertisedTo", json_adv_to
);
11075 vty_out(vty
, "\n");
11080 /* Line 9 display Uptime */
11081 tbuf
= time(NULL
) - (monotime(NULL
) - path
->uptime
);
11083 json_last_update
= json_object_new_object();
11084 json_object_int_add(json_last_update
, "epoch", tbuf
);
11085 json_object_string_add(json_last_update
, "string",
11087 json_object_object_add(json_path
, "lastUpdate",
11090 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
11092 /* Line 10 display PMSI tunnel attribute, if present */
11093 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
11094 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
11095 bgp_attr_get_pmsi_tnl_type(attr
),
11096 PMSI_TNLTYPE_STR_DEFAULT
);
11099 json_pmsi
= json_object_new_object();
11100 json_object_string_add(json_pmsi
, "tunnelType", str
);
11101 json_object_int_add(json_pmsi
, "label",
11102 label2vni(&attr
->label
));
11103 json_object_object_add(json_path
, "pmsi", json_pmsi
);
11105 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
11106 str
, label2vni(&attr
->label
));
11109 if (path
->peer
->t_gr_restart
&&
11110 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
11111 unsigned long gr_remaining
=
11112 event_timer_remain_second(path
->peer
->t_gr_restart
);
11115 json_object_int_add(json_path
,
11116 "gracefulRestartSecondsRemaining",
11120 " Time until Graceful Restart stale route deleted: %lu\n",
11124 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
11125 bgp_attr_get_community(attr
) &&
11126 community_include(bgp_attr_get_community(attr
),
11127 COMMUNITY_LLGR_STALE
)) {
11128 unsigned long llgr_remaining
= event_timer_remain_second(
11129 path
->peer
->t_llgr_stale
[afi
][safi
]);
11132 json_object_int_add(json_path
, "llgrSecondsRemaining",
11136 " Time until Long-lived stale route deleted: %lu\n",
11140 /* Output some debug about internal state of the dest flags */
11142 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
11143 json_object_boolean_true_add(json_path
, "processScheduled");
11144 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
11145 json_object_boolean_true_add(json_path
, "userCleared");
11146 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
11147 json_object_boolean_true_add(json_path
, "labelChanged");
11148 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
11149 json_object_boolean_true_add(json_path
, "registeredForLabel");
11150 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
11151 json_object_boolean_true_add(json_path
, "selectDefered");
11152 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
11153 json_object_boolean_true_add(json_path
, "fibInstalled");
11154 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
11155 json_object_boolean_true_add(json_path
, "fibPending");
11157 if (json_nexthop_global
|| json_nexthop_ll
) {
11158 json_nexthops
= json_object_new_array();
11160 if (json_nexthop_global
)
11161 json_object_array_add(json_nexthops
,
11162 json_nexthop_global
);
11164 if (json_nexthop_ll
)
11165 json_object_array_add(json_nexthops
,
11168 json_object_object_add(json_path
, "nexthops",
11172 json_object_object_add(json_path
, "peer", json_peer
);
11173 json_object_array_add(json_paths
, json_path
);
11177 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
11178 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11179 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
11181 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11182 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11184 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11185 const char *comstr
, int exact
, afi_t afi
,
11186 safi_t safi
, uint16_t show_flags
);
11188 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11189 struct bgp_table
*table
, enum bgp_show_type type
,
11190 void *output_arg
, const char *rd
, int is_last
,
11191 unsigned long *output_cum
, unsigned long *total_cum
,
11192 unsigned long *json_header_depth
, uint16_t show_flags
,
11193 enum rpki_states rpki_target_state
)
11195 struct bgp_path_info
*pi
;
11196 struct bgp_dest
*dest
;
11197 bool header
= true;
11198 bool json_detail_header
= false;
11200 unsigned long output_count
= 0;
11201 unsigned long total_count
= 0;
11203 json_object
*json_paths
= NULL
;
11205 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11206 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11207 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11208 bool detail_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
11209 bool detail_routes
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
11211 if (output_cum
&& *output_cum
!= 0)
11214 if (use_json
&& !*json_header_depth
) {
11216 *json_header_depth
= 1;
11218 vty_out(vty
, "{\n");
11219 *json_header_depth
= 2;
11222 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11223 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
11225 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
11226 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
11229 table
->version
, &bgp
->router_id
,
11230 bgp
->default_local_pref
);
11231 if ((bgp
->asnotation
== ASNOTATION_PLAIN
) ||
11232 ((bgp
->asnotation
== ASNOTATION_DOT
) &&
11233 (bgp
->as
< UINT16_MAX
)))
11234 vty_out(vty
, "%u", bgp
->as
);
11236 vty_out(vty
, "\"");
11237 vty_out(vty
, ASN_FORMAT(bgp
->asnotation
), &bgp
->as
);
11238 vty_out(vty
, "\"");
11240 vty_out(vty
, ",\n \"routes\": { ");
11242 vty_out(vty
, " \"routeDistinguishers\" : {");
11243 ++*json_header_depth
;
11247 if (use_json
&& rd
) {
11248 vty_out(vty
, " \"%s\" : { ", rd
);
11251 /* Check for 'json detail', where we need header output once per dest */
11252 if (use_json
&& detail_json
&& type
!= bgp_show_type_dampend_paths
&&
11253 type
!= bgp_show_type_damp_neighbor
&&
11254 type
!= bgp_show_type_flap_statistics
&&
11255 type
!= bgp_show_type_flap_neighbor
)
11256 json_detail_header
= true;
11258 /* Start processing of routes. */
11259 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
11260 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11261 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11262 bool json_detail_header_used
= false;
11264 pi
= bgp_dest_get_bgp_path_info(dest
);
11270 json_paths
= json_object_new_array();
11274 for (; pi
; pi
= pi
->next
) {
11275 struct community
*picomm
= NULL
;
11277 picomm
= bgp_attr_get_community(pi
->attr
);
11281 if (type
== bgp_show_type_prefix_version
) {
11283 strtoul(output_arg
, NULL
, 10);
11284 if (dest
->version
< version
)
11288 if (type
== bgp_show_type_community_alias
) {
11289 char *alias
= output_arg
;
11290 char **communities
;
11292 bool found
= false;
11295 frrstr_split(picomm
->str
, " ",
11296 &communities
, &num
);
11297 for (int i
= 0; i
< num
; i
++) {
11298 const char *com2alias
=
11299 bgp_community2alias(
11302 && strcmp(alias
, com2alias
)
11308 XFREE(MTYPE_TMP
, communities
);
11312 bgp_attr_get_lcommunity(pi
->attr
)) {
11313 frrstr_split(bgp_attr_get_lcommunity(
11316 " ", &communities
, &num
);
11317 for (int i
= 0; i
< num
; i
++) {
11318 const char *com2alias
=
11319 bgp_community2alias(
11322 && strcmp(alias
, com2alias
)
11328 XFREE(MTYPE_TMP
, communities
);
11335 if (type
== bgp_show_type_rpki
) {
11336 if (dest_p
->family
== AF_INET
11337 || dest_p
->family
== AF_INET6
)
11338 rpki_curr_state
= hook_call(
11339 bgp_rpki_prefix_status
,
11340 pi
->peer
, pi
->attr
, dest_p
);
11341 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11342 && rpki_curr_state
!= rpki_target_state
)
11346 if (type
== bgp_show_type_flap_statistics
11347 || type
== bgp_show_type_flap_neighbor
11348 || type
== bgp_show_type_dampend_paths
11349 || type
== bgp_show_type_damp_neighbor
) {
11350 if (!(pi
->extra
&& pi
->extra
->damp_info
))
11353 if (type
== bgp_show_type_regexp
) {
11354 regex_t
*regex
= output_arg
;
11356 if (bgp_regexec(regex
, pi
->attr
->aspath
)
11360 if (type
== bgp_show_type_prefix_list
) {
11361 struct prefix_list
*plist
= output_arg
;
11363 if (prefix_list_apply(plist
, dest_p
)
11367 if (type
== bgp_show_type_access_list
) {
11368 struct access_list
*alist
= output_arg
;
11370 if (access_list_apply(alist
, dest_p
) !=
11374 if (type
== bgp_show_type_filter_list
) {
11375 struct as_list
*as_list
= output_arg
;
11377 if (as_list_apply(as_list
, pi
->attr
->aspath
)
11378 != AS_FILTER_PERMIT
)
11381 if (type
== bgp_show_type_route_map
) {
11382 struct route_map
*rmap
= output_arg
;
11383 struct bgp_path_info path
;
11384 struct bgp_path_info_extra extra
;
11385 struct attr dummy_attr
= {};
11386 route_map_result_t ret
;
11388 dummy_attr
= *pi
->attr
;
11390 prep_for_rmap_apply(&path
, &extra
, dest
, pi
,
11391 pi
->peer
, &dummy_attr
);
11393 ret
= route_map_apply(rmap
, dest_p
, &path
);
11394 bgp_attr_flush(&dummy_attr
);
11395 if (ret
== RMAP_DENYMATCH
)
11398 if (type
== bgp_show_type_neighbor
11399 || type
== bgp_show_type_flap_neighbor
11400 || type
== bgp_show_type_damp_neighbor
) {
11401 union sockunion
*su
= output_arg
;
11403 if (pi
->peer
== NULL
11404 || pi
->peer
->su_remote
== NULL
11405 || !sockunion_same(pi
->peer
->su_remote
, su
))
11408 if (type
== bgp_show_type_cidr_only
) {
11409 uint32_t destination
;
11411 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11412 if (IN_CLASSC(destination
)
11413 && dest_p
->prefixlen
== 24)
11415 if (IN_CLASSB(destination
)
11416 && dest_p
->prefixlen
== 16)
11418 if (IN_CLASSA(destination
)
11419 && dest_p
->prefixlen
== 8)
11422 if (type
== bgp_show_type_prefix_longer
) {
11424 if (!prefix_match(p
, dest_p
))
11427 if (type
== bgp_show_type_community_all
) {
11431 if (type
== bgp_show_type_community
) {
11432 struct community
*com
= output_arg
;
11434 if (!picomm
|| !community_match(picomm
, com
))
11437 if (type
== bgp_show_type_community_exact
) {
11438 struct community
*com
= output_arg
;
11440 if (!picomm
|| !community_cmp(picomm
, com
))
11443 if (type
== bgp_show_type_community_list
) {
11444 struct community_list
*list
= output_arg
;
11446 if (!community_list_match(picomm
, list
))
11449 if (type
== bgp_show_type_community_list_exact
) {
11450 struct community_list
*list
= output_arg
;
11452 if (!community_list_exact_match(picomm
, list
))
11455 if (type
== bgp_show_type_lcommunity
) {
11456 struct lcommunity
*lcom
= output_arg
;
11458 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11460 bgp_attr_get_lcommunity(pi
->attr
),
11465 if (type
== bgp_show_type_lcommunity_exact
) {
11466 struct lcommunity
*lcom
= output_arg
;
11468 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11470 bgp_attr_get_lcommunity(pi
->attr
),
11474 if (type
== bgp_show_type_lcommunity_list
) {
11475 struct community_list
*list
= output_arg
;
11477 if (!lcommunity_list_match(
11478 bgp_attr_get_lcommunity(pi
->attr
),
11483 == bgp_show_type_lcommunity_list_exact
) {
11484 struct community_list
*list
= output_arg
;
11486 if (!lcommunity_list_exact_match(
11487 bgp_attr_get_lcommunity(pi
->attr
),
11491 if (type
== bgp_show_type_lcommunity_all
) {
11492 if (!bgp_attr_get_lcommunity(pi
->attr
))
11495 if (type
== bgp_show_type_dampend_paths
11496 || type
== bgp_show_type_damp_neighbor
) {
11497 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11498 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11501 if (type
== bgp_show_type_self_originated
) {
11502 if (pi
->peer
!= bgp
->peer_self
)
11506 if (!use_json
&& header
) {
11508 "BGP table version is %" PRIu64
11509 ", local router ID is %pI4, vrf id ",
11510 table
->version
, &bgp
->router_id
);
11511 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11512 vty_out(vty
, "%s", VRFID_NONE_STR
);
11514 vty_out(vty
, "%u", bgp
->vrf_id
);
11515 vty_out(vty
, "\n");
11516 vty_out(vty
, "Default local pref %u, ",
11517 bgp
->default_local_pref
);
11518 vty_out(vty
, "local AS ");
11519 vty_out(vty
, ASN_FORMAT(bgp
->asnotation
),
11521 vty_out(vty
, "\n");
11522 if (!detail_routes
) {
11523 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11524 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11525 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11526 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11528 if (type
== bgp_show_type_dampend_paths
11529 || type
== bgp_show_type_damp_neighbor
)
11530 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11531 else if (type
== bgp_show_type_flap_statistics
11532 || type
== bgp_show_type_flap_neighbor
)
11533 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11534 else if (!detail_routes
)
11535 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11536 : BGP_SHOW_HEADER
));
11540 if (rd
!= NULL
&& !display
&& !output_count
) {
11543 "Route Distinguisher: %s\n",
11546 if (type
== bgp_show_type_dampend_paths
11547 || type
== bgp_show_type_damp_neighbor
)
11548 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11549 AFI_IP
, safi
, use_json
,
11551 else if (type
== bgp_show_type_flap_statistics
11552 || type
== bgp_show_type_flap_neighbor
)
11553 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11554 AFI_IP
, safi
, use_json
,
11557 if (detail_routes
|| detail_json
) {
11558 const struct prefix_rd
*prd
= NULL
;
11561 prd
= bgp_rd_from_dest(
11562 dest
->pdest
, safi
);
11565 route_vty_out_detail_header(
11567 bgp_dest_get_prefix(
11569 prd
, table
->afi
, safi
,
11572 route_vty_out_detail(
11573 vty
, bgp
, dest
, dest_p
, pi
,
11574 family2afi(dest_p
->family
),
11575 safi
, RPKI_NOT_BEING_USED
,
11578 route_vty_out(vty
, dest_p
, pi
, display
,
11579 safi
, json_paths
, wide
);
11590 /* encode prefix */
11591 if (dest_p
->family
== AF_FLOWSPEC
) {
11592 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11595 bgp_fs_nlri_get_string(
11597 dest_p
->u
.prefix_flowspec
.ptr
,
11598 dest_p
->u
.prefix_flowspec
.prefixlen
,
11599 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11600 family2afi(dest_p
->u
11601 .prefix_flowspec
.family
));
11603 vty_out(vty
, "\"%s/%d\": ", retstr
,
11604 dest_p
->u
.prefix_flowspec
11607 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11608 dest_p
->u
.prefix_flowspec
11612 vty_out(vty
, "\"%pFX\": ", dest_p
);
11614 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11617 /* This is used for 'json detail' vty keywords.
11619 * In plain 'json' the per-prefix header is encoded
11620 * as a standalone dictionary in the first json_paths
11622 * "<prefix>": [{header}, {path-1}, {path-N}]
11623 * (which is confusing and borderline broken)
11625 * For 'json detail' this changes the value
11626 * of each prefix-key to be a dictionary where each
11627 * header item has its own key, and json_paths is
11628 * tucked under the "paths" key:
11630 * "<header-key-1>": <header-val-1>,
11631 * "<header-key-N>": <header-val-N>,
11632 * "paths": [{path-1}, {path-N}]
11635 if (json_detail_header
&& json_paths
!= NULL
) {
11636 const struct prefix_rd
*prd
;
11638 /* Start per-prefix dictionary */
11639 vty_out(vty
, "{\n");
11641 prd
= bgp_rd_from_dest(dest
, safi
);
11643 route_vty_out_detail_header(
11645 bgp_dest_get_prefix(dest
), prd
,
11646 table
->afi
, safi
, json_paths
, true);
11648 vty_out(vty
, "\"paths\": ");
11649 json_detail_header_used
= true;
11653 * We are using no_pretty here because under
11654 * extremely high settings( say lots and lots of
11655 * routes with lots and lots of ways to reach
11656 * that route via different paths ) this can
11657 * save several minutes of output when FRR
11658 * is run on older cpu's or more underperforming
11659 * routers out there
11661 vty_json_no_pretty(vty
, json_paths
);
11663 /* End per-prefix dictionary */
11664 if (json_detail_header_used
)
11665 vty_out(vty
, "} ");
11670 json_object_free(json_paths
);
11674 output_count
+= *output_cum
;
11675 *output_cum
= output_count
;
11678 total_count
+= *total_cum
;
11679 *total_cum
= total_count
;
11683 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11687 for (i
= 0; i
< *json_header_depth
; ++i
)
11688 vty_out(vty
, " } ");
11690 vty_out(vty
, "\n");
11694 /* No route is displayed */
11695 if (output_count
== 0) {
11696 if (type
== bgp_show_type_normal
)
11698 "No BGP prefixes displayed, %ld exist\n",
11702 "\nDisplayed %ld routes and %ld total paths\n",
11703 output_count
, total_count
);
11707 return CMD_SUCCESS
;
11710 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11711 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11712 enum bgp_show_type type
, void *output_arg
,
11713 uint16_t show_flags
)
11715 struct bgp_dest
*dest
, *next
;
11716 unsigned long output_cum
= 0;
11717 unsigned long total_cum
= 0;
11718 unsigned long json_header_depth
= 0;
11719 struct bgp_table
*itable
;
11721 bool use_json
= !!CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11723 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11725 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11726 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11728 next
= bgp_route_next(dest
);
11729 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11732 itable
= bgp_dest_get_bgp_table_info(dest
);
11733 if (itable
!= NULL
) {
11734 struct prefix_rd prd
;
11735 char rd
[RD_ADDRSTRLEN
];
11737 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11738 prefix_rd2str(&prd
, rd
, sizeof(rd
), bgp
->asnotation
);
11739 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11740 rd
, next
== NULL
, &output_cum
,
11741 &total_cum
, &json_header_depth
,
11742 show_flags
, RPKI_NOT_BEING_USED
);
11748 if (output_cum
== 0)
11749 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11753 "\nDisplayed %ld routes and %ld total paths\n",
11754 output_cum
, total_cum
);
11756 if (use_json
&& output_cum
== 0)
11757 vty_out(vty
, "{}\n");
11759 return CMD_SUCCESS
;
11762 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11763 enum bgp_show_type type
, void *output_arg
,
11764 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11766 struct bgp_table
*table
;
11767 unsigned long json_header_depth
= 0;
11768 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11771 bgp
= bgp_get_default();
11776 vty_out(vty
, "No BGP process is configured\n");
11778 vty_out(vty
, "{}\n");
11779 return CMD_WARNING
;
11782 /* Labeled-unicast routes live in the unicast table. */
11783 if (safi
== SAFI_LABELED_UNICAST
)
11784 safi
= SAFI_UNICAST
;
11786 table
= bgp
->rib
[afi
][safi
];
11787 /* use MPLS and ENCAP specific shows until they are merged */
11788 if (safi
== SAFI_MPLS_VPN
) {
11789 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11790 output_arg
, show_flags
);
11793 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11794 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11795 output_arg
, use_json
,
11799 if (safi
== SAFI_EVPN
)
11800 return bgp_evpn_show_all_routes(vty
, bgp
, type
, use_json
, 0);
11802 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11803 NULL
, NULL
, &json_header_depth
, show_flags
,
11804 rpki_target_state
);
11807 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11808 safi_t safi
, uint16_t show_flags
)
11810 struct listnode
*node
, *nnode
;
11813 bool route_output
= false;
11814 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11817 vty_out(vty
, "{\n");
11819 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11820 route_output
= true;
11823 vty_out(vty
, ",\n");
11827 vty_out(vty
, "\"%s\":",
11828 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11832 vty_out(vty
, "\nInstance %s:\n",
11833 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11837 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11838 show_flags
, RPKI_NOT_BEING_USED
);
11842 vty_out(vty
, "}\n");
11843 else if (!route_output
)
11844 vty_out(vty
, "%% BGP instance not found\n");
11847 /* Header of detailed BGP route information */
11848 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11849 struct bgp_dest
*dest
, const struct prefix
*p
,
11850 const struct prefix_rd
*prd
, afi_t afi
,
11851 safi_t safi
, json_object
*json
,
11852 bool incremental_print
)
11854 struct bgp_path_info
*pi
;
11856 struct listnode
*node
, *nnode
;
11857 char buf1
[RD_ADDRSTRLEN
];
11861 int accept_own
= 0;
11862 int route_filter_translated_v4
= 0;
11863 int route_filter_v4
= 0;
11864 int route_filter_translated_v6
= 0;
11865 int route_filter_v6
= 0;
11866 int llgr_stale
= 0;
11868 int accept_own_nexthop
= 0;
11871 int no_advertise
= 0;
11875 int has_valid_label
= 0;
11876 mpls_label_t label
= 0;
11877 json_object
*json_adv_to
= NULL
;
11882 mpls_lse_decode(dest
->local_label
, &label
, &ttl
, &exp
, &bos
);
11884 has_valid_label
= bgp_is_valid_label(&label
);
11886 if (safi
== SAFI_EVPN
) {
11888 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11889 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
),
11892 prd
? ":" : "", (struct prefix_evpn
*)p
);
11894 json_object_string_add(
11896 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
),
11899 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11904 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11906 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11907 ? prefix_rd2str(prd
, buf1
,
11911 safi
== SAFI_MPLS_VPN
? ":" : "", p
,
11915 if (incremental_print
) {
11916 vty_out(vty
, "\"prefix\": \"%pFX\",\n", p
);
11917 vty_out(vty
, "\"version\": \"%" PRIu64
"\",\n",
11920 json_object_string_addf(json
, "prefix", "%pFX",
11922 json_object_int_add(json
, "version",
11928 if (has_valid_label
) {
11930 if (incremental_print
)
11931 vty_out(vty
, "\"localLabel\": \"%u\",\n",
11934 json_object_int_add(json
, "localLabel", label
);
11936 vty_out(vty
, "Local label: %d\n", label
);
11940 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11941 vty_out(vty
, "not allocated\n");
11943 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11944 struct community
*picomm
= NULL
;
11946 picomm
= bgp_attr_get_community(pi
->attr
);
11949 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11951 if (bgp_path_suppressed(pi
))
11957 no_advertise
+= community_include(
11958 picomm
, COMMUNITY_NO_ADVERTISE
);
11960 community_include(picomm
, COMMUNITY_NO_EXPORT
);
11962 community_include(picomm
, COMMUNITY_LOCAL_AS
);
11964 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
11965 route_filter_translated_v4
+= community_include(
11966 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11967 route_filter_translated_v6
+= community_include(
11968 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11969 route_filter_v4
+= community_include(
11970 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
11971 route_filter_v6
+= community_include(
11972 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
11974 community_include(picomm
, COMMUNITY_LLGR_STALE
);
11975 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
11976 accept_own_nexthop
+= community_include(
11977 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11979 community_include(picomm
, COMMUNITY_BLACKHOLE
);
11980 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
11985 vty_out(vty
, "Paths: (%d available", count
);
11987 vty_out(vty
, ", best #%d", best
);
11988 if (safi
== SAFI_UNICAST
) {
11989 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11990 vty_out(vty
, ", table %s",
11993 vty_out(vty
, ", vrf %s",
11997 vty_out(vty
, ", no best path");
12001 ", accept own local route exported and imported in different VRF");
12002 else if (route_filter_translated_v4
)
12004 ", mark translated RTs for VPNv4 route filtering");
12005 else if (route_filter_v4
)
12007 ", attach RT as-is for VPNv4 route filtering");
12008 else if (route_filter_translated_v6
)
12010 ", mark translated RTs for VPNv6 route filtering");
12011 else if (route_filter_v6
)
12013 ", attach RT as-is for VPNv6 route filtering");
12014 else if (llgr_stale
)
12016 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
12019 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
12020 else if (accept_own_nexthop
)
12022 ", accept local nexthop");
12023 else if (blackhole
)
12024 vty_out(vty
, ", inform peer to blackhole prefix");
12025 else if (no_export
)
12026 vty_out(vty
, ", not advertised to EBGP peer");
12027 else if (no_advertise
)
12028 vty_out(vty
, ", not advertised to any peer");
12030 vty_out(vty
, ", not advertised outside local AS");
12033 ", inform EBGP peer not to advertise to their EBGP peers");
12037 ", Advertisements suppressed by an aggregate.");
12038 vty_out(vty
, ")\n");
12041 /* If we are not using addpath then we can display Advertised to and
12043 * show what peers we advertised the bestpath to. If we are using
12045 * though then we must display Advertised to on a path-by-path basis. */
12046 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
12047 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
12048 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
12049 if (json
&& !json_adv_to
)
12050 json_adv_to
= json_object_new_object();
12052 route_vty_out_advertised_to(
12054 " Advertised to non peer-group peers:\n ",
12059 if (json
&& json_adv_to
) {
12060 if (incremental_print
) {
12061 vty_out(vty
, "\"advertisedTo\": ");
12062 vty_json(vty
, json_adv_to
);
12065 json_object_object_add(json
, "advertisedTo",
12068 if (!json
&& first
)
12069 vty_out(vty
, " Not advertised to any peer");
12070 vty_out(vty
, "\n");
12075 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
12076 struct bgp_dest
*bgp_node
, struct vty
*vty
,
12077 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
12078 json_object
*json
, enum bgp_path_type pathtype
,
12079 int *display
, enum rpki_states rpki_target_state
)
12081 struct bgp_path_info
*pi
;
12083 json_object
*json_header
= NULL
;
12084 json_object
*json_paths
= NULL
;
12085 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
12087 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
12088 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
12090 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
12091 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
12092 pi
->peer
, pi
->attr
, p
);
12094 if (rpki_target_state
!= RPKI_NOT_BEING_USED
12095 && rpki_curr_state
!= rpki_target_state
)
12098 if (json
&& !json_paths
) {
12099 /* Instantiate json_paths only if path is valid */
12100 json_paths
= json_object_new_array();
12102 json_header
= json_object_new_object();
12104 json_header
= json
;
12108 route_vty_out_detail_header(
12109 vty
, bgp
, bgp_node
,
12110 bgp_dest_get_prefix(bgp_node
), pfx_rd
, AFI_IP
,
12111 safi
, json_header
, false);
12116 if (pathtype
== BGP_PATH_SHOW_ALL
12117 || (pathtype
== BGP_PATH_SHOW_BESTPATH
12118 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12119 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
12120 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
12121 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
12122 route_vty_out_detail(vty
, bgp
, bgp_node
,
12123 bgp_dest_get_prefix(bgp_node
), pi
,
12124 AFI_IP
, safi
, rpki_curr_state
,
12128 if (json
&& json_paths
) {
12129 json_object_object_add(json_header
, "paths", json_paths
);
12132 json_object_object_addf(
12134 BGP_RD_AS_FORMAT(bgp
->asnotation
), pfx_rd
);
12139 * Return rd based on safi
12141 const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
12145 case SAFI_MPLS_VPN
:
12148 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
12151 case SAFI_MULTICAST
:
12152 case SAFI_LABELED_UNICAST
:
12153 case SAFI_FLOWSPEC
:
12158 assert(!"Reached end of function when we were not expecting it");
12161 /* Display specified route of BGP table. */
12162 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
12163 struct bgp_table
*rib
, const char *ip_str
,
12164 afi_t afi
, safi_t safi
,
12165 enum rpki_states rpki_target_state
,
12166 struct prefix_rd
*prd
, int prefix_check
,
12167 enum bgp_path_type pathtype
, bool use_json
)
12171 struct prefix match
;
12172 struct bgp_dest
*dest
;
12173 struct bgp_dest
*rm
;
12174 struct bgp_table
*table
;
12175 json_object
*json
= NULL
;
12176 json_object
*json_paths
= NULL
;
12178 /* Check IP address argument. */
12179 ret
= str2prefix(ip_str
, &match
);
12181 vty_out(vty
, "address is malformed\n");
12182 return CMD_WARNING
;
12185 match
.family
= afi2family(afi
);
12188 json
= json_object_new_object();
12190 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
12191 for (dest
= bgp_table_top(rib
); dest
;
12192 dest
= bgp_route_next(dest
)) {
12193 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12195 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
12197 table
= bgp_dest_get_bgp_table_info(dest
);
12201 rm
= bgp_node_match(table
, &match
);
12205 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
12207 && rm_p
->prefixlen
!= match
.prefixlen
) {
12208 bgp_dest_unlock_node(rm
);
12212 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12213 bgp
, afi
, safi
, json
, pathtype
,
12214 &display
, rpki_target_state
);
12216 bgp_dest_unlock_node(rm
);
12218 } else if (safi
== SAFI_EVPN
) {
12219 struct bgp_dest
*longest_pfx
;
12220 bool is_exact_pfxlen_match
= false;
12222 for (dest
= bgp_table_top(rib
); dest
;
12223 dest
= bgp_route_next(dest
)) {
12224 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12226 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
12228 table
= bgp_dest_get_bgp_table_info(dest
);
12232 longest_pfx
= NULL
;
12233 is_exact_pfxlen_match
= false;
12235 * Search through all the prefixes for a match. The
12236 * pfx's are enumerated in ascending order of pfxlens.
12237 * So, the last pfx match is the longest match. Set
12238 * is_exact_pfxlen_match when we get exact pfxlen match
12240 for (rm
= bgp_table_top(table
); rm
;
12241 rm
= bgp_route_next(rm
)) {
12242 const struct prefix
*rm_p
=
12243 bgp_dest_get_prefix(rm
);
12245 * Get prefixlen of the ip-prefix within type5
12248 if (evpn_type5_prefix_match(rm_p
, &match
)
12252 bgp_evpn_get_type5_prefixlen(
12254 if (type5_pfxlen
== match
.prefixlen
) {
12255 is_exact_pfxlen_match
= true;
12256 bgp_dest_unlock_node(rm
);
12265 if (prefix_check
&& !is_exact_pfxlen_match
)
12269 bgp_dest_lock_node(rm
);
12271 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12272 bgp
, afi
, safi
, json
, pathtype
,
12273 &display
, rpki_target_state
);
12275 bgp_dest_unlock_node(rm
);
12277 } else if (safi
== SAFI_FLOWSPEC
) {
12279 json_paths
= json_object_new_array();
12281 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
12282 &match
, prefix_check
,
12288 json_object_object_add(json
, "paths",
12291 json_object_free(json_paths
);
12294 dest
= bgp_node_match(rib
, &match
);
12295 if (dest
!= NULL
) {
12296 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12298 || dest_p
->prefixlen
== match
.prefixlen
) {
12299 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
12300 safi
, json
, pathtype
,
12301 &display
, rpki_target_state
);
12304 bgp_dest_unlock_node(dest
);
12309 vty_json(vty
, json
);
12312 vty_out(vty
, "%% Network not in table\n");
12313 return CMD_WARNING
;
12317 return CMD_SUCCESS
;
12320 /* Display specified route of Main RIB */
12321 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
12322 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
12323 int prefix_check
, enum bgp_path_type pathtype
,
12324 enum rpki_states rpki_target_state
, bool use_json
)
12327 bgp
= bgp_get_default();
12330 vty_out(vty
, "No BGP process is configured\n");
12332 vty_out(vty
, "{}\n");
12333 return CMD_WARNING
;
12337 /* labeled-unicast routes live in the unicast table */
12338 if (safi
== SAFI_LABELED_UNICAST
)
12339 safi
= SAFI_UNICAST
;
12341 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
12342 afi
, safi
, rpki_target_state
, prd
,
12343 prefix_check
, pathtype
, use_json
);
12346 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
12347 struct cmd_token
**argv
, bool exact
, afi_t afi
,
12348 safi_t safi
, bool uj
)
12350 struct lcommunity
*lcom
;
12355 uint16_t show_flags
= 0;
12359 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12361 b
= buffer_new(1024);
12362 for (i
= 0; i
< argc
; i
++) {
12364 buffer_putc(b
, ' ');
12366 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
12368 buffer_putstr(b
, argv
[i
]->arg
);
12372 buffer_putc(b
, '\0');
12374 str
= buffer_getstr(b
);
12377 lcom
= lcommunity_str2com(str
);
12378 XFREE(MTYPE_TMP
, str
);
12380 vty_out(vty
, "%% Large-community malformed\n");
12381 return CMD_WARNING
;
12384 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12385 (exact
? bgp_show_type_lcommunity_exact
12386 : bgp_show_type_lcommunity
),
12387 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
12389 lcommunity_free(&lcom
);
12393 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
12394 const char *lcom
, bool exact
, afi_t afi
,
12395 safi_t safi
, bool uj
)
12397 struct community_list
*list
;
12398 uint16_t show_flags
= 0;
12401 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12404 list
= community_list_lookup(bgp_clist
, lcom
, 0,
12405 LARGE_COMMUNITY_LIST_MASTER
);
12406 if (list
== NULL
) {
12407 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
12409 return CMD_WARNING
;
12412 return bgp_show(vty
, bgp
, afi
, safi
,
12413 (exact
? bgp_show_type_lcommunity_list_exact
12414 : bgp_show_type_lcommunity_list
),
12415 list
, show_flags
, RPKI_NOT_BEING_USED
);
12418 DEFUN (show_ip_bgp_large_community_list
,
12419 show_ip_bgp_large_community_list_cmd
,
12420 "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]",
12424 BGP_INSTANCE_HELP_STR
12426 BGP_SAFI_WITH_LABEL_HELP_STR
12427 "Display routes matching the large-community-list\n"
12428 "large-community-list number\n"
12429 "large-community-list name\n"
12430 "Exact match of the large-communities\n"
12433 afi_t afi
= AFI_IP6
;
12434 safi_t safi
= SAFI_UNICAST
;
12436 bool exact_match
= 0;
12437 struct bgp
*bgp
= NULL
;
12438 bool uj
= use_json(argc
, argv
);
12443 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12446 return CMD_WARNING
;
12448 argv_find(argv
, argc
, "large-community-list", &idx
);
12450 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12452 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
12455 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
12456 exact_match
, afi
, safi
, uj
);
12458 DEFUN (show_ip_bgp_large_community
,
12459 show_ip_bgp_large_community_cmd
,
12460 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
12464 BGP_INSTANCE_HELP_STR
12466 BGP_SAFI_WITH_LABEL_HELP_STR
12467 "Display routes matching the large-communities\n"
12468 "List of large-community numbers\n"
12469 "Exact match of the large-communities\n"
12472 afi_t afi
= AFI_IP6
;
12473 safi_t safi
= SAFI_UNICAST
;
12475 bool exact_match
= 0;
12476 struct bgp
*bgp
= NULL
;
12477 bool uj
= use_json(argc
, argv
);
12478 uint16_t show_flags
= 0;
12482 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12485 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12488 return CMD_WARNING
;
12490 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12491 if (argv_find(argv
, argc
, "exact-match", &idx
)) {
12495 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12496 exact_match
, afi
, safi
, uj
);
12498 return bgp_show(vty
, bgp
, afi
, safi
,
12499 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12500 RPKI_NOT_BEING_USED
);
12503 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12504 safi_t safi
, struct json_object
*json_array
);
12505 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12506 safi_t safi
, struct json_object
*json
);
12509 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12510 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12511 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12512 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12514 bool uj
= use_json(argc
, argv
);
12515 struct bgp
*bgp
= NULL
;
12516 safi_t safi
= SAFI_UNICAST
;
12517 afi_t afi
= AFI_IP6
;
12519 struct json_object
*json_all
= NULL
;
12520 struct json_object
*json_afi_safi
= NULL
;
12522 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12525 return CMD_WARNING
;
12528 json_all
= json_object_new_object();
12530 FOREACH_AFI_SAFI (afi
, safi
) {
12532 * So limit output to those afi/safi pairs that
12533 * actually have something interesting in them
12535 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12540 json_afi_safi
= json_object_new_array();
12541 json_object_object_add(
12543 get_afi_safi_str(afi
, safi
, true),
12546 json_afi_safi
= NULL
;
12549 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12553 vty_json(vty
, json_all
);
12555 return CMD_SUCCESS
;
12558 /* BGP route print out function without JSON */
12559 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12560 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12561 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12565 BGP_INSTANCE_HELP_STR
12568 "BGP RIB advertisement statistics\n"
12571 afi_t afi
= AFI_IP6
;
12572 safi_t safi
= SAFI_UNICAST
;
12573 struct bgp
*bgp
= NULL
;
12575 bool uj
= use_json(argc
, argv
);
12576 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12578 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12581 return CMD_WARNING
;
12584 json_afi_safi
= json_object_new_array();
12586 json_afi_safi
= NULL
;
12588 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12591 json
= json_object_new_object();
12592 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12594 vty_json(vty
, json
);
12599 /* BGP route print out function without JSON */
12600 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12601 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12602 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12604 statistics [json]",
12605 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12606 BGP_SAFI_WITH_LABEL_HELP_STR
12607 "BGP RIB advertisement statistics\n" JSON_STR
)
12609 afi_t afi
= AFI_IP6
;
12610 safi_t safi
= SAFI_UNICAST
;
12611 struct bgp
*bgp
= NULL
;
12613 bool uj
= use_json(argc
, argv
);
12614 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12616 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12619 return CMD_WARNING
;
12622 json_afi_safi
= json_object_new_array();
12624 json_afi_safi
= NULL
;
12626 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12629 json
= json_object_new_object();
12630 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12632 vty_json(vty
, json
);
12637 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12638 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12639 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12640 "]] [all$all] dampening parameters [json]",
12641 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12642 BGP_SAFI_WITH_LABEL_HELP_STR
12643 "Display the entries for all address families\n"
12644 "Display detailed information about dampening\n"
12645 "Display detail of configured dampening parameters\n"
12648 afi_t afi
= AFI_IP6
;
12649 safi_t safi
= SAFI_UNICAST
;
12650 struct bgp
*bgp
= NULL
;
12652 uint16_t show_flags
= 0;
12653 bool uj
= use_json(argc
, argv
);
12657 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12660 /* [<ipv4|ipv6> [all]] */
12662 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12663 if (argv_find(argv
, argc
, "ipv4", &idx
))
12664 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12666 if (argv_find(argv
, argc
, "ipv6", &idx
))
12667 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12670 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12673 return CMD_WARNING
;
12675 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12678 /* BGP route print out function */
12679 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12680 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12681 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12685 |dampening <flap-statistics|dampened-paths>\
12686 |community [AA:NN|local-AS|no-advertise|no-export\
12687 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12688 |accept-own|accept-own-nexthop|route-filter-v6\
12689 |route-filter-v4|route-filter-translated-v6\
12690 |route-filter-translated-v4] [exact-match]\
12691 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12692 |filter-list AS_PATH_FILTER_NAME\
12694 |access-list ACCESSLIST_NAME\
12695 |route-map RMAP_NAME\
12696 |rpki <invalid|valid|notfound>\
12697 |version (1-4294967295)\
12699 |A.B.C.D/M longer-prefixes\
12700 |X:X::X:X/M longer-prefixes\
12701 |"BGP_SELF_ORIG_CMD_STR
"\
12702 |detail-routes$detail_routes\
12703 ] [json$uj [detail$detail_json] | wide$wide]",
12704 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12705 BGP_SAFI_WITH_LABEL_HELP_STR
12706 "Display the entries for all address families\n"
12707 "Display only routes with non-natural netmasks\n"
12708 "Display detailed information about dampening\n"
12709 "Display flap statistics of routes\n"
12710 "Display paths suppressed due to dampening\n"
12711 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12712 "Do not send outside local AS (well-known community)\n"
12713 "Do not advertise to any peer (well-known community)\n"
12714 "Do not export to next AS (well-known community)\n"
12715 "Graceful shutdown (well-known community)\n"
12716 "Do not export to any peer (well-known community)\n"
12717 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12718 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12719 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12720 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12721 "Should accept VPN route with local nexthop (well-known community)\n"
12722 "RT VPNv6 route filtering (well-known community)\n"
12723 "RT VPNv4 route filtering (well-known community)\n"
12724 "RT translated VPNv6 route filtering (well-known community)\n"
12725 "RT translated VPNv4 route filtering (well-known community)\n"
12726 "Exact match of the communities\n"
12727 "Community-list number\n"
12728 "Community-list name\n"
12729 "Display routes matching the community-list\n"
12730 "Exact match of the communities\n"
12731 "Display routes conforming to the filter-list\n"
12732 "Regular expression access list name\n"
12733 "Display routes conforming to the prefix-list\n"
12734 "Prefix-list name\n"
12735 "Display routes conforming to the access-list\n"
12736 "Access-list name\n"
12737 "Display routes matching the route-map\n"
12738 "A route-map to match on\n"
12739 "RPKI route types\n"
12740 "A valid path as determined by rpki\n"
12741 "A invalid path as determined by rpki\n"
12742 "A path that has no rpki data\n"
12743 "Display prefixes with matching version numbers\n"
12744 "Version number and above\n"
12745 "Display prefixes with matching BGP community alias\n"
12746 "BGP community alias\n"
12748 "Display route and more specific routes\n"
12750 "Display route and more specific routes\n"
12751 BGP_SELF_ORIG_HELP_STR
12752 "Display detailed version of all routes\n"
12754 "Display detailed version of JSON output\n"
12755 "Increase table width for longer prefixes\n")
12757 afi_t afi
= AFI_IP6
;
12758 safi_t safi
= SAFI_UNICAST
;
12759 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12760 void *output_arg
= NULL
;
12761 struct bgp
*bgp
= NULL
;
12763 int exact_match
= 0;
12764 char *community
= NULL
;
12766 uint16_t show_flags
= 0;
12767 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12772 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12776 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
12779 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
12781 /* [<ipv4|ipv6> [all]] */
12783 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12785 if (argv_find(argv
, argc
, "ipv4", &idx
))
12786 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12788 if (argv_find(argv
, argc
, "ipv6", &idx
))
12789 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12793 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12795 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12798 return CMD_WARNING
;
12800 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12801 sh_type
= bgp_show_type_cidr_only
;
12803 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12804 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12805 sh_type
= bgp_show_type_dampend_paths
;
12806 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12807 sh_type
= bgp_show_type_flap_statistics
;
12810 if (argv_find(argv
, argc
, "community", &idx
)) {
12811 char *maybecomm
= NULL
;
12813 if (idx
+ 1 < argc
) {
12814 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12815 maybecomm
= argv
[idx
+ 1]->arg
;
12817 maybecomm
= argv
[idx
+ 1]->text
;
12820 if (maybecomm
&& !strmatch(maybecomm
, "json")
12821 && !strmatch(maybecomm
, "exact-match"))
12822 community
= maybecomm
;
12824 if (argv_find(argv
, argc
, "exact-match", &idx
))
12828 sh_type
= bgp_show_type_community_all
;
12831 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12832 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12833 struct community_list
*list
;
12835 if (argv_find(argv
, argc
, "exact-match", &idx
))
12838 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12839 COMMUNITY_LIST_MASTER
);
12840 if (list
== NULL
) {
12841 vty_out(vty
, "%% %s community-list not found\n",
12842 clist_number_or_name
);
12843 return CMD_WARNING
;
12847 sh_type
= bgp_show_type_community_list_exact
;
12849 sh_type
= bgp_show_type_community_list
;
12853 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12854 const char *filter
= argv
[++idx
]->arg
;
12855 struct as_list
*as_list
;
12857 as_list
= as_list_lookup(filter
);
12858 if (as_list
== NULL
) {
12859 vty_out(vty
, "%% %s AS-path access-list not found\n",
12861 return CMD_WARNING
;
12864 sh_type
= bgp_show_type_filter_list
;
12865 output_arg
= as_list
;
12868 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12869 const char *prefix_list_str
= argv
[++idx
]->arg
;
12870 struct prefix_list
*plist
;
12872 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12873 if (plist
== NULL
) {
12874 vty_out(vty
, "%% %s prefix-list not found\n",
12876 return CMD_WARNING
;
12879 sh_type
= bgp_show_type_prefix_list
;
12880 output_arg
= plist
;
12883 if (argv_find(argv
, argc
, "access-list", &idx
)) {
12884 const char *access_list_str
= argv
[++idx
]->arg
;
12885 struct access_list
*alist
;
12887 alist
= access_list_lookup(afi
, access_list_str
);
12889 vty_out(vty
, "%% %s access-list not found\n",
12891 return CMD_WARNING
;
12894 sh_type
= bgp_show_type_access_list
;
12895 output_arg
= alist
;
12898 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12899 const char *rmap_str
= argv
[++idx
]->arg
;
12900 struct route_map
*rmap
;
12902 rmap
= route_map_lookup_by_name(rmap_str
);
12904 vty_out(vty
, "%% %s route-map not found\n", rmap_str
);
12905 return CMD_WARNING
;
12908 sh_type
= bgp_show_type_route_map
;
12912 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12913 sh_type
= bgp_show_type_rpki
;
12914 if (argv_find(argv
, argc
, "valid", &idx
))
12915 rpki_target_state
= RPKI_VALID
;
12916 else if (argv_find(argv
, argc
, "invalid", &idx
))
12917 rpki_target_state
= RPKI_INVALID
;
12920 /* Display prefixes with matching version numbers */
12921 if (argv_find(argv
, argc
, "version", &idx
)) {
12922 sh_type
= bgp_show_type_prefix_version
;
12923 output_arg
= argv
[idx
+ 1]->arg
;
12926 /* Display prefixes with matching BGP community alias */
12927 if (argv_find(argv
, argc
, "alias", &idx
)) {
12928 sh_type
= bgp_show_type_community_alias
;
12929 output_arg
= argv
[idx
+ 1]->arg
;
12932 /* prefix-longer */
12933 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12934 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12935 const char *prefix_str
= argv
[idx
]->arg
;
12937 if (!str2prefix(prefix_str
, &p
)) {
12938 vty_out(vty
, "%% Malformed Prefix\n");
12939 return CMD_WARNING
;
12942 sh_type
= bgp_show_type_prefix_longer
;
12946 /* self originated only */
12947 if (argv_find(argv
, argc
, BGP_SELF_ORIG_CMD_STR
, &idx
))
12948 sh_type
= bgp_show_type_self_originated
;
12951 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12953 return bgp_show_community(vty
, bgp
, community
,
12954 exact_match
, afi
, safi
,
12957 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12958 output_arg
, show_flags
,
12959 rpki_target_state
);
12961 struct listnode
*node
;
12963 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12967 vty_out(vty
, "{\n");
12969 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12970 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12971 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12974 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12975 FOREACH_SAFI (safi
) {
12976 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12984 vty_out(vty
, ",\n");
12985 vty_out(vty
, "\"%s\":{\n",
12986 get_afi_safi_str(afi
,
12991 "\nFor address family: %s\n",
12997 bgp_show_community(
12998 vty
, abgp
, community
,
12999 exact_match
, afi
, safi
,
13002 bgp_show(vty
, abgp
, afi
, safi
,
13003 sh_type
, output_arg
,
13005 rpki_target_state
);
13007 vty_out(vty
, "}\n");
13011 /* show <ip> bgp all: for each AFI and SAFI*/
13012 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
13013 FOREACH_AFI_SAFI (afi
, safi
) {
13014 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
13022 vty_out(vty
, ",\n");
13024 vty_out(vty
, "\"%s\":{\n",
13025 get_afi_safi_str(afi
,
13030 "\nFor address family: %s\n",
13036 bgp_show_community(
13037 vty
, abgp
, community
,
13038 exact_match
, afi
, safi
,
13041 bgp_show(vty
, abgp
, afi
, safi
,
13042 sh_type
, output_arg
,
13044 rpki_target_state
);
13046 vty_out(vty
, "}\n");
13051 vty_out(vty
, "}\n");
13053 return CMD_SUCCESS
;
13056 DEFUN (show_ip_bgp_route
,
13057 show_ip_bgp_route_cmd
,
13058 "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]",
13062 BGP_INSTANCE_HELP_STR
13064 BGP_SAFI_WITH_LABEL_HELP_STR
13065 "Network in the BGP routing table to display\n"
13067 "Network in the BGP routing table to display\n"
13069 "Display only the bestpath\n"
13070 "Display only multipaths\n"
13071 "Display only paths that match the specified rpki state\n"
13072 "A valid path as determined by rpki\n"
13073 "A invalid path as determined by rpki\n"
13074 "A path that has no rpki data\n"
13077 int prefix_check
= 0;
13079 afi_t afi
= AFI_IP6
;
13080 safi_t safi
= SAFI_UNICAST
;
13081 char *prefix
= NULL
;
13082 struct bgp
*bgp
= NULL
;
13083 enum bgp_path_type path_type
;
13084 bool uj
= use_json(argc
, argv
);
13088 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13091 return CMD_WARNING
;
13095 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13096 return CMD_WARNING
;
13099 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13100 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
13101 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
13103 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
13104 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
13107 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
13108 && afi
!= AFI_IP6
) {
13110 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13111 return CMD_WARNING
;
13113 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
13114 && afi
!= AFI_IP
) {
13116 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13117 return CMD_WARNING
;
13120 prefix
= argv
[idx
]->arg
;
13122 /* [<bestpath|multipath>] */
13123 if (argv_find(argv
, argc
, "bestpath", &idx
))
13124 path_type
= BGP_PATH_SHOW_BESTPATH
;
13125 else if (argv_find(argv
, argc
, "multipath", &idx
))
13126 path_type
= BGP_PATH_SHOW_MULTIPATH
;
13128 path_type
= BGP_PATH_SHOW_ALL
;
13130 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
13131 path_type
, RPKI_NOT_BEING_USED
, uj
);
13134 DEFUN (show_ip_bgp_regexp
,
13135 show_ip_bgp_regexp_cmd
,
13136 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
13140 BGP_INSTANCE_HELP_STR
13142 BGP_SAFI_WITH_LABEL_HELP_STR
13143 "Display routes matching the AS path regular expression\n"
13144 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13147 afi_t afi
= AFI_IP6
;
13148 safi_t safi
= SAFI_UNICAST
;
13149 struct bgp
*bgp
= NULL
;
13150 bool uj
= use_json(argc
, argv
);
13151 char *regstr
= NULL
;
13154 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13157 return CMD_WARNING
;
13159 // get index of regex
13160 if (argv_find(argv
, argc
, "REGEX", &idx
))
13161 regstr
= argv
[idx
]->arg
;
13164 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
13165 bgp_show_type_regexp
, uj
);
13168 DEFPY (show_ip_bgp_instance_all
,
13169 show_ip_bgp_instance_all_cmd
,
13170 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
13174 BGP_INSTANCE_ALL_HELP_STR
13176 BGP_SAFI_WITH_LABEL_HELP_STR
13178 "Increase table width for longer prefixes\n")
13180 afi_t afi
= AFI_IP6
;
13181 safi_t safi
= SAFI_UNICAST
;
13182 struct bgp
*bgp
= NULL
;
13184 uint16_t show_flags
= 0;
13188 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13192 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13194 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13197 return CMD_WARNING
;
13199 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
13200 return CMD_SUCCESS
;
13203 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
13204 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
13209 uint16_t show_flags
= 0;
13212 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13214 if (!config_bgp_aspath_validate(regstr
)) {
13215 vty_out(vty
, "Invalid character in REGEX %s\n",
13217 return CMD_WARNING_CONFIG_FAILED
;
13220 regex
= bgp_regcomp(regstr
);
13222 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
13223 return CMD_WARNING
;
13226 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
13227 RPKI_NOT_BEING_USED
);
13228 bgp_regex_free(regex
);
13232 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
13233 const char *comstr
, int exact
, afi_t afi
,
13234 safi_t safi
, uint16_t show_flags
)
13236 struct community
*com
;
13239 com
= community_str2com(comstr
);
13241 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
13242 return CMD_WARNING
;
13245 ret
= bgp_show(vty
, bgp
, afi
, safi
,
13246 (exact
? bgp_show_type_community_exact
13247 : bgp_show_type_community
),
13248 com
, show_flags
, RPKI_NOT_BEING_USED
);
13249 community_free(&com
);
13255 BGP_STATS_MAXBITLEN
= 0,
13257 BGP_STATS_PREFIXES
,
13259 BGP_STATS_UNAGGREGATEABLE
,
13260 BGP_STATS_MAX_AGGREGATEABLE
,
13261 BGP_STATS_AGGREGATES
,
13263 BGP_STATS_ASPATH_COUNT
,
13264 BGP_STATS_ASPATH_MAXHOPS
,
13265 BGP_STATS_ASPATH_TOTHOPS
,
13266 BGP_STATS_ASPATH_MAXSIZE
,
13267 BGP_STATS_ASPATH_TOTSIZE
,
13268 BGP_STATS_ASN_HIGHEST
,
13272 #define TABLE_STATS_IDX_VTY 0
13273 #define TABLE_STATS_IDX_JSON 1
13275 static const char *table_stats_strs
[][2] = {
13276 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
13277 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
13278 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
13279 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
13280 "unaggregateablePrefixes"},
13281 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
13282 "maximumAggregateablePrefixes"},
13283 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
13284 "bgpAggregateAdvertisements"},
13285 [BGP_STATS_SPACE
] = {"Address space advertised",
13286 "addressSpaceAdvertised"},
13287 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
13288 "advertisementsWithPaths"},
13289 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
13291 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
13293 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
13294 "averageAsPathLengthHops"},
13295 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
13296 "averageAsPathSizeBytes"},
13297 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
13298 [BGP_STATS_MAX
] = {NULL
, NULL
}
13301 struct bgp_table_stats
{
13302 struct bgp_table
*table
;
13303 unsigned long long counts
[BGP_STATS_MAX
];
13306 prefix_len_count
[MAX(EVPN_ROUTE_PREFIXLEN
, IPV6_MAX_BITLEN
) +
13309 double total_space
;
13312 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
13313 struct bgp_table_stats
*ts
, unsigned int space
)
13315 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
13316 struct bgp_path_info
*pi
;
13317 const struct prefix
*rn_p
;
13319 if (!bgp_dest_has_bgp_path_info_data(dest
))
13322 rn_p
= bgp_dest_get_prefix(dest
);
13323 ts
->counts
[BGP_STATS_PREFIXES
]++;
13324 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
13326 ts
->prefix_len_count
[rn_p
->prefixlen
]++;
13327 /* check if the prefix is included by any other announcements */
13328 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
13329 pdest
= bgp_dest_parent_nolock(pdest
);
13331 if (pdest
== NULL
|| pdest
== top
) {
13332 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
13333 /* announced address space */
13335 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
13336 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
13337 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
13340 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
13341 ts
->counts
[BGP_STATS_RIB
]++;
13343 if (CHECK_FLAG(pi
->attr
->flag
,
13344 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
13345 ts
->counts
[BGP_STATS_AGGREGATES
]++;
13347 /* as-path stats */
13348 if (pi
->attr
->aspath
) {
13349 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
13350 unsigned int size
= aspath_size(pi
->attr
->aspath
);
13351 as_t highest
= aspath_highest(pi
->attr
->aspath
);
13353 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
13355 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
13356 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
13358 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
13359 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
13361 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
13362 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
13363 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
13364 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
13369 static void bgp_table_stats_walker(struct event
*t
)
13371 struct bgp_dest
*dest
, *ndest
;
13372 struct bgp_dest
*top
;
13373 struct bgp_table_stats
*ts
= EVENT_ARG(t
);
13374 unsigned int space
= 0;
13376 if (!(top
= bgp_table_top(ts
->table
)))
13379 switch (ts
->table
->afi
) {
13381 space
= IPV4_MAX_BITLEN
;
13384 space
= IPV6_MAX_BITLEN
;
13387 space
= EVPN_ROUTE_PREFIXLEN
;
13394 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
13396 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
13397 if (ts
->table
->safi
== SAFI_MPLS_VPN
13398 || ts
->table
->safi
== SAFI_ENCAP
13399 || ts
->table
->safi
== SAFI_EVPN
) {
13400 struct bgp_table
*table
;
13402 table
= bgp_dest_get_bgp_table_info(dest
);
13406 top
= bgp_table_top(table
);
13407 for (ndest
= bgp_table_top(table
); ndest
;
13408 ndest
= bgp_route_next(ndest
))
13409 bgp_table_stats_rn(ndest
, top
, ts
, space
);
13411 bgp_table_stats_rn(dest
, top
, ts
, space
);
13416 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
13417 struct json_object
*json_array
)
13419 struct listnode
*node
, *nnode
;
13422 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
13423 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13426 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13427 safi_t safi
, struct json_object
*json_array
)
13429 struct bgp_table_stats ts
;
13431 int ret
= CMD_SUCCESS
;
13433 struct json_object
*json
= NULL
;
13434 uint32_t bitlen
= 0;
13435 struct json_object
*json_bitlen
;
13438 json
= json_object_new_object();
13440 if (!bgp
->rib
[afi
][safi
]) {
13441 char warning_msg
[50];
13443 snprintf(warning_msg
, sizeof(warning_msg
),
13444 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
13448 vty_out(vty
, "%s\n", warning_msg
);
13450 json_object_string_add(json
, "warning", warning_msg
);
13453 goto end_table_stats
;
13457 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
13458 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
13460 json_object_string_add(json
, "instance", bgp
->name_pretty
);
13462 /* labeled-unicast routes live in the unicast table */
13463 if (safi
== SAFI_LABELED_UNICAST
)
13464 safi
= SAFI_UNICAST
;
13466 memset(&ts
, 0, sizeof(ts
));
13467 ts
.table
= bgp
->rib
[afi
][safi
];
13468 event_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
13470 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
13471 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
13472 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
13476 case BGP_STATS_ASPATH_TOTHOPS
:
13477 case BGP_STATS_ASPATH_TOTSIZE
:
13480 temp_buf
, sizeof(temp_buf
), "%12.2f",
13482 ? (float)ts
.counts
[i
]
13484 [BGP_STATS_ASPATH_COUNT
]
13486 vty_out(vty
, "%-30s: %s",
13487 table_stats_strs
[i
]
13488 [TABLE_STATS_IDX_VTY
],
13491 json_object_double_add(
13493 table_stats_strs
[i
]
13494 [TABLE_STATS_IDX_JSON
],
13496 ? (double)ts
.counts
[i
]
13497 / (double)ts
.counts
13498 [BGP_STATS_ASPATH_COUNT
]
13502 case BGP_STATS_TOTPLEN
:
13505 temp_buf
, sizeof(temp_buf
), "%12.2f",
13507 ? (float)ts
.counts
[i
]
13509 [BGP_STATS_PREFIXES
]
13511 vty_out(vty
, "%-30s: %s",
13512 table_stats_strs
[i
]
13513 [TABLE_STATS_IDX_VTY
],
13516 json_object_double_add(
13518 table_stats_strs
[i
]
13519 [TABLE_STATS_IDX_JSON
],
13521 ? (double)ts
.counts
[i
]
13522 / (double)ts
.counts
13523 [BGP_STATS_PREFIXES
]
13527 case BGP_STATS_SPACE
:
13529 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13531 vty_out(vty
, "%-30s: %s\n",
13532 table_stats_strs
[i
]
13533 [TABLE_STATS_IDX_VTY
],
13536 json_object_double_add(
13538 table_stats_strs
[i
]
13539 [TABLE_STATS_IDX_JSON
],
13540 (double)ts
.total_space
);
13542 if (afi
== AFI_IP6
) {
13544 snprintf(temp_buf
, sizeof(temp_buf
),
13547 * pow(2.0, -128 + 32));
13548 vty_out(vty
, "%30s: %s\n",
13549 "/32 equivalent %s\n",
13552 json_object_double_add(
13553 json
, "/32equivalent",
13554 (double)(ts
.total_space
13559 snprintf(temp_buf
, sizeof(temp_buf
),
13562 * pow(2.0, -128 + 48));
13563 vty_out(vty
, "%30s: %s\n",
13564 "/48 equivalent %s\n",
13567 json_object_double_add(
13568 json
, "/48equivalent",
13569 (double)(ts
.total_space
13575 snprintf(temp_buf
, sizeof(temp_buf
),
13577 ts
.total_space
* 100.
13579 vty_out(vty
, "%30s: %s\n",
13580 "% announced ", temp_buf
);
13582 json_object_double_add(
13583 json
, "%announced",
13584 (double)(ts
.total_space
* 100.
13588 snprintf(temp_buf
, sizeof(temp_buf
),
13591 * pow(2.0, -32 + 8));
13592 vty_out(vty
, "%30s: %s\n",
13593 "/8 equivalent ", temp_buf
);
13595 json_object_double_add(
13596 json
, "/8equivalent",
13597 (double)(ts
.total_space
13598 * pow(2.0, -32 + 8)));
13601 snprintf(temp_buf
, sizeof(temp_buf
),
13604 * pow(2.0, -32 + 24));
13605 vty_out(vty
, "%30s: %s\n",
13606 "/24 equivalent ", temp_buf
);
13608 json_object_double_add(
13609 json
, "/24equivalent",
13610 (double)(ts
.total_space
13611 * pow(2.0, -32 + 24)));
13617 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13619 vty_out(vty
, "%-30s: %s",
13620 table_stats_strs
[i
]
13621 [TABLE_STATS_IDX_VTY
],
13624 json_object_int_add(
13626 table_stats_strs
[i
]
13627 [TABLE_STATS_IDX_JSON
],
13632 vty_out(vty
, "\n");
13637 bitlen
= IPV4_MAX_BITLEN
;
13640 bitlen
= IPV6_MAX_BITLEN
;
13643 bitlen
= EVPN_ROUTE_PREFIXLEN
;
13651 json_bitlen
= json_object_new_array();
13653 for (i
= 0; i
<= bitlen
; i
++) {
13654 struct json_object
*ind_bit
= json_object_new_object();
13656 if (!ts
.prefix_len_count
[i
])
13659 snprintf(temp_buf
, sizeof(temp_buf
), "%u", i
);
13660 json_object_int_add(ind_bit
, temp_buf
,
13661 ts
.prefix_len_count
[i
]);
13662 json_object_array_add(json_bitlen
, ind_bit
);
13664 json_object_object_add(json
, "prefixLength", json_bitlen
);
13669 json_object_array_add(json_array
, json
);
13673 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13674 safi_t safi
, struct json_object
*json_array
)
13677 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13678 return CMD_SUCCESS
;
13681 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13693 PCOUNT_BPATH_SELECTED
,
13694 PCOUNT_PFCNT
, /* the figure we display to users */
13698 static const char *const pcount_strs
[] = {
13699 [PCOUNT_ADJ_IN
] = "Adj-in",
13700 [PCOUNT_DAMPED
] = "Damped",
13701 [PCOUNT_REMOVED
] = "Removed",
13702 [PCOUNT_HISTORY
] = "History",
13703 [PCOUNT_STALE
] = "Stale",
13704 [PCOUNT_VALID
] = "Valid",
13705 [PCOUNT_ALL
] = "All RIB",
13706 [PCOUNT_COUNTED
] = "PfxCt counted",
13707 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13708 [PCOUNT_PFCNT
] = "Useable",
13709 [PCOUNT_MAX
] = NULL
,
13712 struct peer_pcounts
{
13713 unsigned int count
[PCOUNT_MAX
];
13714 const struct peer
*peer
;
13715 const struct bgp_table
*table
;
13719 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13721 const struct bgp_adj_in
*ain
;
13722 const struct bgp_path_info
*pi
;
13723 const struct peer
*peer
= pc
->peer
;
13725 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13726 if (ain
->peer
== peer
)
13727 pc
->count
[PCOUNT_ADJ_IN
]++;
13729 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13731 if (pi
->peer
!= peer
)
13734 pc
->count
[PCOUNT_ALL
]++;
13736 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13737 pc
->count
[PCOUNT_DAMPED
]++;
13738 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13739 pc
->count
[PCOUNT_HISTORY
]++;
13740 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13741 pc
->count
[PCOUNT_REMOVED
]++;
13742 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13743 pc
->count
[PCOUNT_STALE
]++;
13744 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13745 pc
->count
[PCOUNT_VALID
]++;
13746 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13747 pc
->count
[PCOUNT_PFCNT
]++;
13748 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13749 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13751 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13752 pc
->count
[PCOUNT_COUNTED
]++;
13753 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13755 EC_LIB_DEVELOPMENT
,
13756 "Attempting to count but flags say it is unusable");
13758 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13760 EC_LIB_DEVELOPMENT
,
13761 "Not counted but flags say we should");
13766 static void bgp_peer_count_walker(struct event
*t
)
13768 struct bgp_dest
*rn
, *rm
;
13769 const struct bgp_table
*table
;
13770 struct peer_pcounts
*pc
= EVENT_ARG(t
);
13772 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13773 || pc
->safi
== SAFI_EVPN
) {
13774 /* Special handling for 2-level routing tables. */
13775 for (rn
= bgp_table_top(pc
->table
); rn
;
13776 rn
= bgp_route_next(rn
)) {
13777 table
= bgp_dest_get_bgp_table_info(rn
);
13779 for (rm
= bgp_table_top(table
); rm
;
13780 rm
= bgp_route_next(rm
))
13781 bgp_peer_count_proc(rm
, pc
);
13784 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13785 bgp_peer_count_proc(rn
, pc
);
13788 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13789 safi_t safi
, bool use_json
)
13791 struct peer_pcounts pcounts
= {.peer
= peer
};
13793 json_object
*json
= NULL
;
13794 json_object
*json_loop
= NULL
;
13797 json
= json_object_new_object();
13798 json_loop
= json_object_new_object();
13801 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13802 || !peer
->bgp
->rib
[afi
][safi
]) {
13804 json_object_string_add(
13806 "No such neighbor or address family");
13807 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13808 json_object_free(json
);
13809 json_object_free(json_loop
);
13811 vty_out(vty
, "%% No such neighbor or address family\n");
13813 return CMD_WARNING
;
13816 memset(&pcounts
, 0, sizeof(pcounts
));
13817 pcounts
.peer
= peer
;
13818 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13819 pcounts
.safi
= safi
;
13821 /* in-place call via thread subsystem so as to record execution time
13822 * stats for the thread-walk (i.e. ensure this can't be blamed on
13823 * on just vty_read()).
13825 event_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13828 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13829 json_object_string_add(json
, "multiProtocol",
13830 get_afi_safi_str(afi
, safi
, true));
13831 json_object_int_add(json
, "pfxCounter",
13832 peer
->pcount
[afi
][safi
]);
13834 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13835 json_object_int_add(json_loop
, pcount_strs
[i
],
13838 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13840 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13841 json_object_string_add(json
, "pfxctDriftFor",
13843 json_object_string_add(
13844 json
, "recommended",
13845 "Please report this bug, with the above command output");
13847 vty_json(vty
, json
);
13851 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13852 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13853 peer
->hostname
, peer
->host
,
13854 get_afi_safi_str(afi
, safi
, false));
13856 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13857 get_afi_safi_str(afi
, safi
, false));
13860 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13861 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13863 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13864 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13867 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13868 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13870 "Please report this bug, with the above command output\n");
13874 return CMD_SUCCESS
;
13877 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13878 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13879 "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]",
13883 BGP_INSTANCE_HELP_STR
13886 "Detailed information on TCP and BGP neighbor connections\n"
13887 "Neighbor to display information about\n"
13888 "Neighbor to display information about\n"
13889 "Neighbor on BGP configured interface\n"
13890 "Display detailed prefix count information\n"
13893 afi_t afi
= AFI_IP6
;
13894 safi_t safi
= SAFI_UNICAST
;
13897 struct bgp
*bgp
= NULL
;
13898 bool uj
= use_json(argc
, argv
);
13903 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13906 return CMD_WARNING
;
13908 argv_find(argv
, argc
, "neighbors", &idx
);
13909 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13911 return CMD_WARNING
;
13913 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13916 #ifdef KEEP_OLD_VPN_COMMANDS
13917 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13918 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13919 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13924 "Display information about all VPNv4 NLRIs\n"
13925 "Detailed information on TCP and BGP neighbor connections\n"
13926 "Neighbor to display information about\n"
13927 "Neighbor to display information about\n"
13928 "Neighbor on BGP configured interface\n"
13929 "Display detailed prefix count information\n"
13934 bool uj
= use_json(argc
, argv
);
13936 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13938 return CMD_WARNING
;
13940 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13943 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13944 show_ip_bgp_vpn_all_route_prefix_cmd
,
13945 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13950 "Display information about all VPNv4 NLRIs\n"
13951 "Network in the BGP routing table to display\n"
13952 "Network in the BGP routing table to display\n"
13956 char *network
= NULL
;
13957 struct bgp
*bgp
= bgp_get_default();
13959 vty_out(vty
, "Can't find default instance\n");
13960 return CMD_WARNING
;
13963 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13964 network
= argv
[idx
]->arg
;
13965 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13966 network
= argv
[idx
]->arg
;
13968 vty_out(vty
, "Unable to figure out Network\n");
13969 return CMD_WARNING
;
13972 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13973 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13974 use_json(argc
, argv
));
13976 #endif /* KEEP_OLD_VPN_COMMANDS */
13978 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13979 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13980 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13985 "Network in the BGP routing table to display\n"
13986 "Network in the BGP routing table to display\n"
13987 "Network in the BGP routing table to display\n"
13988 "Network in the BGP routing table to display\n"
13992 char *network
= NULL
;
13993 int prefix_check
= 0;
13995 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13996 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13997 network
= argv
[idx
]->arg
;
13998 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13999 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
14000 network
= argv
[idx
]->arg
;
14003 vty_out(vty
, "Unable to figure out Network\n");
14004 return CMD_WARNING
;
14006 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
14007 prefix_check
, BGP_PATH_SHOW_ALL
,
14008 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
14011 static void show_adj_route_header(struct vty
*vty
, struct peer
*peer
,
14012 struct bgp_table
*table
, int *header1
,
14013 int *header2
, json_object
*json
,
14014 json_object
*json_scode
,
14015 json_object
*json_ocode
, bool wide
,
14018 uint64_t version
= table
? table
->version
: 0;
14022 json_object_int_add(json
, "bgpTableVersion", version
);
14023 json_object_string_addf(json
, "bgpLocalRouterId",
14024 "%pI4", &peer
->bgp
->router_id
);
14025 json_object_int_add(json
, "defaultLocPrf",
14026 peer
->bgp
->default_local_pref
);
14027 json_object_int_add(json
, "localAS",
14028 peer
->change_local_as
14029 ? peer
->change_local_as
14031 json_object_object_add(json
, "bgpStatusCodes",
14033 json_object_object_add(json
, "bgpOriginCodes",
14037 "BGP table version is %" PRIu64
14038 ", local router ID is %pI4, vrf id ",
14039 version
, &peer
->bgp
->router_id
);
14040 if (peer
->bgp
->vrf_id
== VRF_UNKNOWN
)
14041 vty_out(vty
, "%s", VRFID_NONE_STR
);
14043 vty_out(vty
, "%u", peer
->bgp
->vrf_id
);
14044 vty_out(vty
, "\n");
14045 vty_out(vty
, "Default local pref %u, ",
14046 peer
->bgp
->default_local_pref
);
14047 vty_out(vty
, "local AS %u\n",
14048 peer
->change_local_as
? peer
->change_local_as
14051 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14052 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14053 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14054 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14060 if (!json
&& !detail
)
14061 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
14062 : BGP_SHOW_HEADER
));
14068 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
14069 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
14070 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
14071 json_object
*json_scode
, json_object
*json_ocode
,
14072 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
14073 const struct prefix
*match
, unsigned long *output_count
,
14074 unsigned long *filtered_count
)
14076 struct bgp_adj_in
*ain
= NULL
;
14077 struct bgp_adj_out
*adj
= NULL
;
14078 struct bgp_dest
*dest
;
14082 struct update_subgroup
*subgrp
;
14083 struct peer_af
*paf
= NULL
;
14084 bool route_filtered
;
14085 bool detail
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14086 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14087 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14088 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14089 || (safi
== SAFI_EVPN
))
14093 json_object
*json_net
= NULL
;
14097 /* If the user supplied a prefix, look for a matching route instead
14098 * of walking the whole table.
14101 dest
= bgp_node_match(table
, match
);
14104 vty_out(vty
, "Network not in table\n");
14108 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
14110 if (rn_p
->prefixlen
!= match
->prefixlen
) {
14112 vty_out(vty
, "Network not in table\n");
14113 bgp_dest_unlock_node(dest
);
14117 if (type
== bgp_show_adj_route_received
||
14118 type
== bgp_show_adj_route_filtered
) {
14119 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14120 if (ain
->peer
== peer
) {
14125 /* bail out if if adj_out is empty, or
14126 * if the prefix isn't in this peer's
14129 if (!ain
|| ain
->peer
!= peer
) {
14131 vty_out(vty
, "Network not in table\n");
14132 bgp_dest_unlock_node(dest
);
14135 } else if (type
== bgp_show_adj_route_advertised
) {
14136 bool peer_found
= false;
14138 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
) {
14139 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14140 if (paf
->peer
== peer
&& adj
->attr
) {
14149 /* bail out if if adj_out is empty, or
14150 * if the prefix isn't in this peer's
14153 if (!paf
|| !peer_found
) {
14155 vty_out(vty
, "Network not in table\n");
14156 bgp_dest_unlock_node(dest
);
14161 ret
= bgp_output_modifier(peer
, rn_p
, &attr
, afi
, safi
,
14164 if (ret
!= RMAP_DENY
) {
14165 show_adj_route_header(vty
, peer
, table
, header1
,
14166 header2
, json
, json_scode
,
14167 json_ocode
, wide
, detail
);
14170 json_net
= json_object_new_object();
14172 bgp_show_path_info(NULL
/* prefix_rd */, dest
, vty
, bgp
,
14173 afi
, safi
, json_net
,
14174 BGP_PATH_SHOW_ALL
, &display
,
14175 RPKI_NOT_BEING_USED
);
14177 json_object_object_addf(json_ar
, json_net
,
14181 (*filtered_count
)++;
14183 bgp_attr_flush(&attr
);
14184 bgp_dest_unlock_node(dest
);
14189 subgrp
= peer_subgroup(peer
, afi
, safi
);
14191 if (type
== bgp_show_adj_route_advertised
&& subgrp
14192 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
14194 json_object_int_add(json
, "bgpTableVersion",
14196 json_object_string_addf(json
, "bgpLocalRouterId",
14197 "%pI4", &bgp
->router_id
);
14198 json_object_int_add(json
, "defaultLocPrf",
14199 bgp
->default_local_pref
);
14200 json_object_int_add(json
, "localAS",
14201 peer
->change_local_as
14202 ? peer
->change_local_as
14204 json_object_object_add(json
, "bgpStatusCodes",
14206 json_object_object_add(json
, "bgpOriginCodes",
14208 json_object_string_add(
14209 json
, "bgpOriginatingDefaultNetwork",
14210 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14213 "BGP table version is %" PRIu64
14214 ", local router ID is %pI4, vrf id ",
14215 table
->version
, &bgp
->router_id
);
14216 if (bgp
->vrf_id
== VRF_UNKNOWN
)
14217 vty_out(vty
, "%s", VRFID_NONE_STR
);
14219 vty_out(vty
, "%u", bgp
->vrf_id
);
14220 vty_out(vty
, "\n");
14221 vty_out(vty
, "Default local pref %u, ",
14222 bgp
->default_local_pref
);
14223 vty_out(vty
, "local AS %u\n",
14224 peer
->change_local_as
? peer
->change_local_as
14227 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14228 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14229 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14230 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14233 vty_out(vty
, "Originating default network %s\n\n",
14234 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14240 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
14241 if (type
== bgp_show_adj_route_received
14242 || type
== bgp_show_adj_route_filtered
) {
14243 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14244 if (ain
->peer
!= peer
)
14247 show_adj_route_header(vty
, peer
, table
, header1
,
14248 header2
, json
, json_scode
,
14249 json_ocode
, wide
, detail
);
14251 if ((safi
== SAFI_MPLS_VPN
)
14252 || (safi
== SAFI_ENCAP
)
14253 || (safi
== SAFI_EVPN
)) {
14255 json_object_string_add(
14256 json_ar
, "rd", rd_str
);
14257 else if (show_rd
&& rd_str
) {
14259 "Route Distinguisher: %s\n",
14266 route_filtered
= false;
14268 /* Filter prefix using distribute list,
14269 * filter list or prefix list
14271 const struct prefix
*rn_p
=
14272 bgp_dest_get_prefix(dest
);
14273 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
14276 route_filtered
= true;
14278 /* Filter prefix using route-map */
14279 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
14280 safi
, rmap_name
, NULL
,
14283 if (type
== bgp_show_adj_route_filtered
&&
14284 !route_filtered
&& ret
!= RMAP_DENY
) {
14285 bgp_attr_flush(&attr
);
14289 if (type
== bgp_show_adj_route_received
14290 && (route_filtered
|| ret
== RMAP_DENY
))
14291 (*filtered_count
)++;
14296 json_object_new_object();
14297 bgp_show_path_info(
14298 NULL
/* prefix_rd */, dest
, vty
,
14299 bgp
, afi
, safi
, json_net
,
14300 BGP_PATH_SHOW_ALL
, &display
,
14301 RPKI_NOT_BEING_USED
);
14303 json_object_object_addf(
14307 route_vty_out_tmp(vty
, dest
, rn_p
,
14308 &attr
, safi
, use_json
,
14310 bgp_attr_flush(&attr
);
14313 } else if (type
== bgp_show_adj_route_advertised
) {
14314 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
14315 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14316 if (paf
->peer
!= peer
|| !adj
->attr
)
14319 show_adj_route_header(
14320 vty
, peer
, table
, header1
,
14321 header2
, json
, json_scode
,
14322 json_ocode
, wide
, detail
);
14324 const struct prefix
*rn_p
=
14325 bgp_dest_get_prefix(dest
);
14328 ret
= bgp_output_modifier(
14329 peer
, rn_p
, &attr
, afi
, safi
,
14332 if (ret
!= RMAP_DENY
) {
14333 if ((safi
== SAFI_MPLS_VPN
)
14334 || (safi
== SAFI_ENCAP
)
14335 || (safi
== SAFI_EVPN
)) {
14337 json_object_string_add(
14344 "Route Distinguisher: %s\n",
14352 json_object_new_object();
14353 bgp_show_path_info(
14362 RPKI_NOT_BEING_USED
);
14364 json_object_object_addf(
14377 (*filtered_count
)++;
14380 bgp_attr_flush(&attr
);
14382 } else if (type
== bgp_show_adj_route_bestpath
) {
14383 struct bgp_path_info
*pi
;
14385 show_adj_route_header(vty
, peer
, table
, header1
,
14386 header2
, json
, json_scode
,
14387 json_ocode
, wide
, detail
);
14389 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
14391 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
14393 if (pi
->peer
!= peer
)
14396 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
14402 json_object_new_object();
14403 bgp_show_path_info(
14404 NULL
/* prefix_rd */, dest
, vty
,
14405 bgp
, afi
, safi
, json_net
,
14406 BGP_PATH_SHOW_BESTPATH
,
14407 &display
, RPKI_NOT_BEING_USED
);
14409 json_object_object_addf(
14414 vty
, dest
, rn_p
, pi
->attr
, safi
,
14415 use_json
, json_ar
, wide
);
14422 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
14423 safi_t safi
, enum bgp_show_adj_route_type type
,
14424 const char *rmap_name
, const struct prefix
*match
,
14425 uint16_t show_flags
)
14428 struct bgp_table
*table
;
14429 json_object
*json
= NULL
;
14430 json_object
*json_scode
= NULL
;
14431 json_object
*json_ocode
= NULL
;
14432 json_object
*json_ar
= NULL
;
14433 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14435 /* Init BGP headers here so they're only displayed once
14436 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14442 * Initialize variables for each RD
14443 * All prefixes under an RD is aggregated within "json_routes"
14445 char rd_str
[BUFSIZ
] = {0};
14446 json_object
*json_routes
= NULL
;
14449 /* For 2-tier tables, prefix counts need to be
14450 * maintained across multiple runs of show_adj_route()
14452 unsigned long output_count_per_rd
;
14453 unsigned long filtered_count_per_rd
;
14454 unsigned long output_count
= 0;
14455 unsigned long filtered_count
= 0;
14458 json
= json_object_new_object();
14459 json_ar
= json_object_new_object();
14460 json_scode
= json_object_new_object();
14461 json_ocode
= json_object_new_object();
14462 #if CONFDATE > 20231208
14463 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14465 json_object_string_add(json_scode
, "suppressed", "s");
14466 json_object_string_add(json_scode
, "damped", "d");
14467 json_object_string_add(json_scode
, "history", "h");
14468 json_object_string_add(json_scode
, "valid", "*");
14469 json_object_string_add(json_scode
, "best", ">");
14470 json_object_string_add(json_scode
, "multipath", "=");
14471 json_object_string_add(json_scode
, "internal", "i");
14472 json_object_string_add(json_scode
, "ribFailure", "r");
14473 json_object_string_add(json_scode
, "stale", "S");
14474 json_object_string_add(json_scode
, "removed", "R");
14476 #if CONFDATE > 20231208
14477 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14479 json_object_string_add(json_ocode
, "igp", "i");
14480 json_object_string_add(json_ocode
, "egp", "e");
14481 json_object_string_add(json_ocode
, "incomplete", "?");
14484 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14486 json_object_string_add(
14488 "No such neighbor or address family");
14489 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14490 json_object_free(json
);
14491 json_object_free(json_ar
);
14492 json_object_free(json_scode
);
14493 json_object_free(json_ocode
);
14495 vty_out(vty
, "%% No such neighbor or address family\n");
14497 return CMD_WARNING
;
14500 if ((type
== bgp_show_adj_route_received
14501 || type
== bgp_show_adj_route_filtered
)
14502 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
14503 PEER_FLAG_SOFT_RECONFIG
)) {
14505 json_object_string_add(
14507 "Inbound soft reconfiguration not enabled");
14508 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14509 json_object_free(json
);
14510 json_object_free(json_ar
);
14511 json_object_free(json_scode
);
14512 json_object_free(json_ocode
);
14515 "%% Inbound soft reconfiguration not enabled\n");
14517 return CMD_WARNING
;
14522 /* labeled-unicast routes live in the unicast table */
14523 if (safi
== SAFI_LABELED_UNICAST
)
14524 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
14526 table
= bgp
->rib
[afi
][safi
];
14528 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14529 || (safi
== SAFI_EVPN
)) {
14531 struct bgp_dest
*dest
;
14533 for (dest
= bgp_table_top(table
); dest
;
14534 dest
= bgp_route_next(dest
)) {
14535 table
= bgp_dest_get_bgp_table_info(dest
);
14539 output_count_per_rd
= 0;
14540 filtered_count_per_rd
= 0;
14543 json_routes
= json_object_new_object();
14545 const struct prefix_rd
*prd
;
14546 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14549 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
),
14553 vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14554 json
, json_routes
, json_scode
, json_ocode
,
14555 show_flags
, &header1
, &header2
, rd_str
, match
,
14556 &output_count_per_rd
, &filtered_count_per_rd
);
14558 /* Don't include an empty RD in the output! */
14559 if (json_routes
&& (output_count_per_rd
> 0))
14560 json_object_object_add(json_ar
, rd_str
,
14563 output_count
+= output_count_per_rd
;
14564 filtered_count
+= filtered_count_per_rd
;
14567 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14568 json
, json_ar
, json_scode
, json_ocode
,
14569 show_flags
, &header1
, &header2
, rd_str
, match
,
14570 &output_count
, &filtered_count
);
14573 if (type
== bgp_show_adj_route_advertised
)
14574 json_object_object_add(json
, "advertisedRoutes",
14577 json_object_object_add(json
, "receivedRoutes", json_ar
);
14578 json_object_int_add(json
, "totalPrefixCounter", output_count
);
14579 json_object_int_add(json
, "filteredPrefixCounter",
14583 * These fields only give up ownership to `json` when `header1`
14584 * is used (set to zero). See code in `show_adj_route` and
14585 * `show_adj_route_header`.
14587 if (header1
== 1) {
14588 json_object_free(json_scode
);
14589 json_object_free(json_ocode
);
14592 vty_json(vty
, json
);
14593 } else if (output_count
> 0) {
14594 if (!match
&& filtered_count
> 0)
14596 "\nTotal number of prefixes %ld (%ld filtered)\n",
14597 output_count
, filtered_count
);
14599 vty_out(vty
, "\nTotal number of prefixes %ld\n",
14603 return CMD_SUCCESS
;
14606 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
14607 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
14608 "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]",
14612 BGP_INSTANCE_HELP_STR
14614 BGP_SAFI_WITH_LABEL_HELP_STR
14615 "Detailed information on TCP and BGP neighbor connections\n"
14616 "Neighbor to display information about\n"
14617 "Neighbor to display information about\n"
14618 "Neighbor on BGP configured interface\n"
14619 "Display the routes selected by best path\n"
14620 "Display detailed version of routes\n"
14622 "Increase table width for longer prefixes\n")
14624 afi_t afi
= AFI_IP6
;
14625 safi_t safi
= SAFI_UNICAST
;
14626 char *rmap_name
= NULL
;
14627 char *peerstr
= NULL
;
14628 struct bgp
*bgp
= NULL
;
14630 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
14632 uint16_t show_flags
= 0;
14635 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14638 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14641 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14643 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14647 return CMD_WARNING
;
14649 argv_find(argv
, argc
, "neighbors", &idx
);
14650 peerstr
= argv
[++idx
]->arg
;
14652 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14654 return CMD_WARNING
;
14656 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, NULL
,
14660 DEFPY(show_ip_bgp_instance_neighbor_advertised_route
,
14661 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
14662 "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]",
14666 BGP_INSTANCE_HELP_STR
14668 BGP_SAFI_WITH_LABEL_HELP_STR
14669 "Display the entries for all address families\n"
14670 "Detailed information on TCP and BGP neighbor connections\n"
14671 "Neighbor to display information about\n"
14672 "Neighbor to display information about\n"
14673 "Neighbor on BGP configured interface\n"
14674 "Display the routes advertised to a BGP neighbor\n"
14675 "Display the received routes from neighbor\n"
14676 "Display the filtered routes received from neighbor\n"
14677 "Route-map to modify the attributes\n"
14678 "Name of the route map\n"
14681 "Display detailed version of routes\n"
14683 "Increase table width for longer prefixes\n")
14685 afi_t afi
= AFI_IP6
;
14686 safi_t safi
= SAFI_UNICAST
;
14687 char *peerstr
= NULL
;
14688 struct bgp
*bgp
= NULL
;
14690 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
14693 uint16_t show_flags
= 0;
14694 struct listnode
*node
;
14697 if (detail
|| prefix_str
)
14698 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14702 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14706 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
14707 if (argv_find(argv
, argc
, "ipv4", &idx
))
14708 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
14710 if (argv_find(argv
, argc
, "ipv6", &idx
))
14711 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
14715 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14717 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14720 return CMD_WARNING
;
14722 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14723 argv_find(argv
, argc
, "neighbors", &idx
);
14724 peerstr
= argv
[++idx
]->arg
;
14726 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14728 return CMD_WARNING
;
14730 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
14731 type
= bgp_show_adj_route_advertised
;
14732 else if (argv_find(argv
, argc
, "received-routes", &idx
))
14733 type
= bgp_show_adj_route_received
;
14734 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
14735 type
= bgp_show_adj_route_filtered
;
14738 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, route_map
,
14739 prefix_str
? prefix
: NULL
, show_flags
);
14741 vty_out(vty
, "{\n");
14743 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14744 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14745 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14747 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14748 FOREACH_SAFI (safi
) {
14749 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14756 vty_out(vty
, ",\n");
14757 vty_out(vty
, "\"%s\":",
14758 get_afi_safi_str(afi
, safi
,
14762 "\nFor address family: %s\n",
14763 get_afi_safi_str(afi
, safi
,
14766 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14767 route_map
, prefix
, show_flags
);
14771 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14772 FOREACH_AFI_SAFI (afi
, safi
) {
14773 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14780 vty_out(vty
, ",\n");
14781 vty_out(vty
, "\"%s\":",
14782 get_afi_safi_str(afi
, safi
,
14786 "\nFor address family: %s\n",
14787 get_afi_safi_str(afi
, safi
,
14790 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14791 route_map
, prefix
, show_flags
);
14796 vty_out(vty
, "}\n");
14798 return CMD_SUCCESS
;
14801 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14802 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14803 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14807 BGP_INSTANCE_HELP_STR
14810 BGP_AF_MODIFIER_STR
14811 "Detailed information on TCP and BGP neighbor connections\n"
14812 "Neighbor to display information about\n"
14813 "Neighbor to display information about\n"
14814 "Neighbor on BGP configured interface\n"
14815 "Display information received from a BGP neighbor\n"
14816 "Display the prefixlist filter\n"
14819 afi_t afi
= AFI_IP6
;
14820 safi_t safi
= SAFI_UNICAST
;
14821 char *peerstr
= NULL
;
14826 struct bgp
*bgp
= NULL
;
14827 bool uj
= use_json(argc
, argv
);
14832 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14835 return CMD_WARNING
;
14837 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14838 argv_find(argv
, argc
, "neighbors", &idx
);
14839 peerstr
= argv
[++idx
]->arg
;
14841 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14843 return CMD_WARNING
;
14845 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14846 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14849 vty_out(vty
, "Address Family: %s\n",
14850 get_afi_safi_str(afi
, safi
, false));
14851 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14854 vty_out(vty
, "{}\n");
14856 vty_out(vty
, "No functional output\n");
14859 return CMD_SUCCESS
;
14862 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14863 afi_t afi
, safi_t safi
,
14864 enum bgp_show_type type
, bool use_json
)
14866 uint16_t show_flags
= 0;
14869 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14871 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14873 json_object
*json_no
= NULL
;
14874 json_no
= json_object_new_object();
14875 json_object_string_add(
14876 json_no
, "warning",
14877 "No such neighbor or address family");
14878 vty_out(vty
, "%s\n",
14879 json_object_to_json_string(json_no
));
14880 json_object_free(json_no
);
14882 vty_out(vty
, "%% No such neighbor or address family\n");
14883 return CMD_WARNING
;
14886 /* labeled-unicast routes live in the unicast table */
14887 if (safi
== SAFI_LABELED_UNICAST
)
14888 safi
= SAFI_UNICAST
;
14890 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14891 RPKI_NOT_BEING_USED
);
14894 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14895 show_ip_bgp_flowspec_routes_detailed_cmd
,
14896 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14900 BGP_INSTANCE_HELP_STR
14903 "Detailed information on flowspec entries\n"
14906 afi_t afi
= AFI_IP6
;
14907 safi_t safi
= SAFI_UNICAST
;
14908 struct bgp
*bgp
= NULL
;
14910 bool uj
= use_json(argc
, argv
);
14911 uint16_t show_flags
= BGP_SHOW_OPT_ROUTES_DETAIL
;
14915 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14918 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14921 return CMD_WARNING
;
14923 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14924 show_flags
, RPKI_NOT_BEING_USED
);
14927 DEFUN (show_ip_bgp_neighbor_routes
,
14928 show_ip_bgp_neighbor_routes_cmd
,
14929 "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]",
14933 BGP_INSTANCE_HELP_STR
14935 BGP_SAFI_WITH_LABEL_HELP_STR
14936 "Detailed information on TCP and BGP neighbor connections\n"
14937 "Neighbor to display information about\n"
14938 "Neighbor to display information about\n"
14939 "Neighbor on BGP configured interface\n"
14940 "Display flap statistics of the routes learned from neighbor\n"
14941 "Display the dampened routes received from neighbor\n"
14942 "Display routes learned from neighbor\n"
14945 char *peerstr
= NULL
;
14946 struct bgp
*bgp
= NULL
;
14947 afi_t afi
= AFI_IP6
;
14948 safi_t safi
= SAFI_UNICAST
;
14950 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14952 bool uj
= use_json(argc
, argv
);
14957 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14960 return CMD_WARNING
;
14962 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14963 argv_find(argv
, argc
, "neighbors", &idx
);
14964 peerstr
= argv
[++idx
]->arg
;
14966 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14968 return CMD_WARNING
;
14970 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14971 sh_type
= bgp_show_type_flap_neighbor
;
14972 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14973 sh_type
= bgp_show_type_damp_neighbor
;
14974 else if (argv_find(argv
, argc
, "routes", &idx
))
14975 sh_type
= bgp_show_type_neighbor
;
14977 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14980 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14982 struct bgp_distance
{
14983 /* Distance value for the IP source prefix. */
14986 /* Name of the access-list to be matched. */
14990 DEFUN (show_bgp_afi_vpn_rd_route
,
14991 show_bgp_afi_vpn_rd_route_cmd
,
14992 "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]",
14996 BGP_AF_MODIFIER_STR
14997 "Display information for a route distinguisher\n"
14998 "Route Distinguisher\n"
14999 "All Route Distinguishers\n"
15000 "Network in the BGP routing table to display\n"
15001 "Network in the BGP routing table to display\n"
15005 struct prefix_rd prd
;
15006 afi_t afi
= AFI_MAX
;
15009 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
15010 vty_out(vty
, "%% Malformed Address Family\n");
15011 return CMD_WARNING
;
15014 if (!strcmp(argv
[5]->arg
, "all"))
15015 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
15016 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
15017 RPKI_NOT_BEING_USED
,
15018 use_json(argc
, argv
));
15020 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
15022 vty_out(vty
, "%% Malformed Route Distinguisher\n");
15023 return CMD_WARNING
;
15026 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
15027 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
15028 use_json(argc
, argv
));
15031 static struct bgp_distance
*bgp_distance_new(void)
15033 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
15036 static void bgp_distance_free(struct bgp_distance
*bdistance
)
15038 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
15041 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
15042 const char *ip_str
, const char *access_list_str
)
15049 struct bgp_dest
*dest
;
15050 struct bgp_distance
*bdistance
;
15052 afi
= bgp_node_afi(vty
);
15053 safi
= bgp_node_safi(vty
);
15055 ret
= str2prefix(ip_str
, &p
);
15057 vty_out(vty
, "Malformed prefix\n");
15058 return CMD_WARNING_CONFIG_FAILED
;
15061 distance
= atoi(distance_str
);
15063 /* Get BGP distance node. */
15064 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
15065 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15067 bgp_dest_unlock_node(dest
);
15069 bdistance
= bgp_distance_new();
15070 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
15073 /* Set distance value. */
15074 bdistance
->distance
= distance
;
15076 /* Reset access-list configuration. */
15077 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
15078 if (access_list_str
)
15079 bdistance
->access_list
=
15080 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
15082 return CMD_SUCCESS
;
15085 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
15086 const char *ip_str
, const char *access_list_str
)
15093 struct bgp_dest
*dest
;
15094 struct bgp_distance
*bdistance
;
15096 afi
= bgp_node_afi(vty
);
15097 safi
= bgp_node_safi(vty
);
15099 ret
= str2prefix(ip_str
, &p
);
15101 vty_out(vty
, "Malformed prefix\n");
15102 return CMD_WARNING_CONFIG_FAILED
;
15105 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
15107 vty_out(vty
, "Can't find specified prefix\n");
15108 return CMD_WARNING_CONFIG_FAILED
;
15111 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15112 distance
= atoi(distance_str
);
15114 if (bdistance
->distance
!= distance
) {
15115 vty_out(vty
, "Distance does not match configured\n");
15116 bgp_dest_unlock_node(dest
);
15117 return CMD_WARNING_CONFIG_FAILED
;
15120 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
15121 bgp_distance_free(bdistance
);
15123 bgp_dest_set_bgp_path_info(dest
, NULL
);
15124 bgp_dest_unlock_node(dest
);
15125 bgp_dest_unlock_node(dest
);
15127 return CMD_SUCCESS
;
15130 /* Apply BGP information to distance method. */
15131 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
15132 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
15134 struct bgp_dest
*dest
;
15135 struct prefix q
= {0};
15137 struct bgp_distance
*bdistance
;
15138 struct access_list
*alist
;
15139 struct bgp_static
*bgp_static
;
15140 struct bgp_path_info
*bpi_ultimate
;
15145 peer
= pinfo
->peer
;
15147 if (pinfo
->attr
->distance
)
15148 return pinfo
->attr
->distance
;
15150 /* get peer origin to calculate appropriate distance */
15151 if (pinfo
->sub_type
== BGP_ROUTE_IMPORTED
) {
15152 bpi_ultimate
= bgp_get_imported_bpi_ultimate(pinfo
);
15153 peer
= bpi_ultimate
->peer
;
15156 /* Check source address.
15157 * Note: for aggregate route, peer can have unspec af type.
15159 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
15160 && !sockunion2hostprefix(&peer
->su
, &q
))
15163 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
15165 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15166 bgp_dest_unlock_node(dest
);
15168 if (bdistance
->access_list
) {
15169 alist
= access_list_lookup(afi
, bdistance
->access_list
);
15171 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
15172 return bdistance
->distance
;
15174 return bdistance
->distance
;
15177 /* Backdoor check. */
15178 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
15180 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15181 bgp_dest_unlock_node(dest
);
15183 if (bgp_static
->backdoor
) {
15184 if (bgp
->distance_local
[afi
][safi
])
15185 return bgp
->distance_local
[afi
][safi
];
15187 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15191 if (peer
->sort
== BGP_PEER_EBGP
) {
15192 if (bgp
->distance_ebgp
[afi
][safi
])
15193 return bgp
->distance_ebgp
[afi
][safi
];
15194 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
15195 } else if (peer
->sort
== BGP_PEER_IBGP
) {
15196 if (bgp
->distance_ibgp
[afi
][safi
])
15197 return bgp
->distance_ibgp
[afi
][safi
];
15198 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15200 if (bgp
->distance_local
[afi
][safi
])
15201 return bgp
->distance_local
[afi
][safi
];
15202 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15206 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15207 * we should tell ZEBRA update the routes for a specific
15208 * AFI/SAFI to reflect changes in RIB.
15210 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
15212 safi_t update_safi
)
15217 FOREACH_AFI_SAFI (afi
, safi
) {
15218 if (!bgp_fibupd_safi(safi
))
15221 if (afi
!= update_afi
&& safi
!= update_safi
)
15224 if (BGP_DEBUG(zebra
, ZEBRA
))
15226 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15227 __func__
, afi
, safi
);
15228 bgp_zebra_announce_table(bgp
, afi
, safi
);
15232 DEFUN (bgp_distance
,
15234 "distance bgp (1-255) (1-255) (1-255)",
15235 "Define an administrative distance\n"
15237 "Distance for routes external to the AS\n"
15238 "Distance for routes internal to the AS\n"
15239 "Distance for local routes\n")
15241 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15242 int idx_number
= 2;
15243 int idx_number_2
= 3;
15244 int idx_number_3
= 4;
15245 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
15246 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
15247 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
15251 afi
= bgp_node_afi(vty
);
15252 safi
= bgp_node_safi(vty
);
15254 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
15255 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
15256 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
15257 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_announce_routes_distance_update(bgp
, afi
, safi
);
15262 return CMD_SUCCESS
;
15265 DEFUN (no_bgp_distance
,
15266 no_bgp_distance_cmd
,
15267 "no distance bgp [(1-255) (1-255) (1-255)]",
15269 "Define an administrative distance\n"
15271 "Distance for routes external to the AS\n"
15272 "Distance for routes internal to the AS\n"
15273 "Distance for local routes\n")
15275 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15279 afi
= bgp_node_afi(vty
);
15280 safi
= bgp_node_safi(vty
);
15282 if (bgp
->distance_ebgp
[afi
][safi
] != 0
15283 || bgp
->distance_ibgp
[afi
][safi
] != 0
15284 || bgp
->distance_local
[afi
][safi
] != 0) {
15285 bgp
->distance_ebgp
[afi
][safi
] = 0;
15286 bgp
->distance_ibgp
[afi
][safi
] = 0;
15287 bgp
->distance_local
[afi
][safi
] = 0;
15288 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15290 return CMD_SUCCESS
;
15294 DEFUN (bgp_distance_source
,
15295 bgp_distance_source_cmd
,
15296 "distance (1-255) A.B.C.D/M",
15297 "Define an administrative distance\n"
15298 "Administrative distance\n"
15299 "IP source prefix\n")
15301 int idx_number
= 1;
15302 int idx_ipv4_prefixlen
= 2;
15303 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15304 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15305 return CMD_SUCCESS
;
15308 DEFUN (no_bgp_distance_source
,
15309 no_bgp_distance_source_cmd
,
15310 "no distance (1-255) A.B.C.D/M",
15312 "Define an administrative distance\n"
15313 "Administrative distance\n"
15314 "IP source prefix\n")
15316 int idx_number
= 2;
15317 int idx_ipv4_prefixlen
= 3;
15318 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15319 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15320 return CMD_SUCCESS
;
15323 DEFUN (bgp_distance_source_access_list
,
15324 bgp_distance_source_access_list_cmd
,
15325 "distance (1-255) A.B.C.D/M WORD",
15326 "Define an administrative distance\n"
15327 "Administrative distance\n"
15328 "IP source prefix\n"
15329 "Access list name\n")
15331 int idx_number
= 1;
15332 int idx_ipv4_prefixlen
= 2;
15334 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15335 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15336 return CMD_SUCCESS
;
15339 DEFUN (no_bgp_distance_source_access_list
,
15340 no_bgp_distance_source_access_list_cmd
,
15341 "no distance (1-255) A.B.C.D/M WORD",
15343 "Define an administrative distance\n"
15344 "Administrative distance\n"
15345 "IP source prefix\n"
15346 "Access list name\n")
15348 int idx_number
= 2;
15349 int idx_ipv4_prefixlen
= 3;
15351 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15352 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15353 return CMD_SUCCESS
;
15356 DEFUN (ipv6_bgp_distance_source
,
15357 ipv6_bgp_distance_source_cmd
,
15358 "distance (1-255) X:X::X:X/M",
15359 "Define an administrative distance\n"
15360 "Administrative distance\n"
15361 "IP source prefix\n")
15363 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
15364 return CMD_SUCCESS
;
15367 DEFUN (no_ipv6_bgp_distance_source
,
15368 no_ipv6_bgp_distance_source_cmd
,
15369 "no distance (1-255) X:X::X:X/M",
15371 "Define an administrative distance\n"
15372 "Administrative distance\n"
15373 "IP source prefix\n")
15375 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
15376 return CMD_SUCCESS
;
15379 DEFUN (ipv6_bgp_distance_source_access_list
,
15380 ipv6_bgp_distance_source_access_list_cmd
,
15381 "distance (1-255) X:X::X:X/M WORD",
15382 "Define an administrative distance\n"
15383 "Administrative distance\n"
15384 "IP source prefix\n"
15385 "Access list name\n")
15387 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
15388 return CMD_SUCCESS
;
15391 DEFUN (no_ipv6_bgp_distance_source_access_list
,
15392 no_ipv6_bgp_distance_source_access_list_cmd
,
15393 "no distance (1-255) X:X::X:X/M WORD",
15395 "Define an administrative distance\n"
15396 "Administrative distance\n"
15397 "IP source prefix\n"
15398 "Access list name\n")
15400 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
15401 return CMD_SUCCESS
;
15404 DEFUN (bgp_damp_set
,
15406 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15407 "BGP Specific commands\n"
15408 "Enable route-flap dampening\n"
15409 "Half-life time for the penalty\n"
15410 "Value to start reusing a route\n"
15411 "Value to start suppressing a route\n"
15412 "Maximum duration to suppress a stable route\n")
15414 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15415 int idx_half_life
= 2;
15417 int idx_suppress
= 4;
15418 int idx_max_suppress
= 5;
15419 int half
= DEFAULT_HALF_LIFE
* 60;
15420 int reuse
= DEFAULT_REUSE
;
15421 int suppress
= DEFAULT_SUPPRESS
;
15422 int max
= 4 * half
;
15425 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15426 reuse
= atoi(argv
[idx_reuse
]->arg
);
15427 suppress
= atoi(argv
[idx_suppress
]->arg
);
15428 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
15429 } else if (argc
== 3) {
15430 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15435 * These can't be 0 but our SA doesn't understand the
15436 * way our cli is constructed
15440 if (suppress
< reuse
) {
15442 "Suppress value cannot be less than reuse value \n");
15446 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
15447 reuse
, suppress
, max
);
15450 DEFUN (bgp_damp_unset
,
15451 bgp_damp_unset_cmd
,
15452 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15454 "BGP Specific commands\n"
15455 "Enable route-flap dampening\n"
15456 "Half-life time for the penalty\n"
15457 "Value to start reusing a route\n"
15458 "Value to start suppressing a route\n"
15459 "Maximum duration to suppress a stable route\n")
15461 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15462 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
15465 /* Display specified route of BGP table. */
15466 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
15467 const char *ip_str
, afi_t afi
, safi_t safi
,
15468 struct prefix_rd
*prd
, int prefix_check
)
15471 struct prefix match
;
15472 struct bgp_dest
*dest
;
15473 struct bgp_dest
*rm
;
15474 struct bgp_path_info
*pi
;
15475 struct bgp_path_info
*pi_temp
;
15477 struct bgp_table
*table
;
15479 /* BGP structure lookup. */
15481 bgp
= bgp_lookup_by_name(view_name
);
15483 vty_out(vty
, "%% Can't find BGP instance %s\n",
15485 return CMD_WARNING
;
15488 bgp
= bgp_get_default();
15490 vty_out(vty
, "%% No BGP process is configured\n");
15491 return CMD_WARNING
;
15495 /* Check IP address argument. */
15496 ret
= str2prefix(ip_str
, &match
);
15498 vty_out(vty
, "%% address is malformed\n");
15499 return CMD_WARNING
;
15502 match
.family
= afi2family(afi
);
15504 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
15505 || (safi
== SAFI_EVPN
)) {
15506 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
15507 dest
= bgp_route_next(dest
)) {
15508 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15510 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
15512 table
= bgp_dest_get_bgp_table_info(dest
);
15515 rm
= bgp_node_match(table
, &match
);
15519 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
15522 || rm_p
->prefixlen
== match
.prefixlen
) {
15523 pi
= bgp_dest_get_bgp_path_info(rm
);
15525 if (pi
->extra
&& pi
->extra
->damp_info
) {
15526 pi_temp
= pi
->next
;
15527 bgp_damp_info_free(
15528 pi
->extra
->damp_info
,
15536 bgp_dest_unlock_node(rm
);
15539 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
15540 if (dest
!= NULL
) {
15541 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15544 || dest_p
->prefixlen
== match
.prefixlen
) {
15545 pi
= bgp_dest_get_bgp_path_info(dest
);
15547 if (pi
->extra
&& pi
->extra
->damp_info
) {
15548 pi_temp
= pi
->next
;
15549 bgp_damp_info_free(
15550 pi
->extra
->damp_info
,
15558 bgp_dest_unlock_node(dest
);
15562 return CMD_SUCCESS
;
15565 DEFUN (clear_ip_bgp_dampening
,
15566 clear_ip_bgp_dampening_cmd
,
15567 "clear ip bgp dampening",
15571 "Clear route flap dampening information\n")
15573 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
15574 return CMD_SUCCESS
;
15577 DEFUN (clear_ip_bgp_dampening_prefix
,
15578 clear_ip_bgp_dampening_prefix_cmd
,
15579 "clear ip bgp dampening A.B.C.D/M",
15583 "Clear route flap dampening information\n"
15586 int idx_ipv4_prefixlen
= 4;
15587 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
15588 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
15591 DEFUN (clear_ip_bgp_dampening_address
,
15592 clear_ip_bgp_dampening_address_cmd
,
15593 "clear ip bgp dampening A.B.C.D",
15597 "Clear route flap dampening information\n"
15598 "Network to clear damping information\n")
15601 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
15602 SAFI_UNICAST
, NULL
, 0);
15605 DEFUN (clear_ip_bgp_dampening_address_mask
,
15606 clear_ip_bgp_dampening_address_mask_cmd
,
15607 "clear ip bgp dampening A.B.C.D A.B.C.D",
15611 "Clear route flap dampening information\n"
15612 "Network to clear damping information\n"
15616 int idx_ipv4_2
= 5;
15618 char prefix_str
[BUFSIZ
];
15620 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
15621 prefix_str
, sizeof(prefix_str
));
15623 vty_out(vty
, "%% Inconsistent address and mask\n");
15624 return CMD_WARNING
;
15627 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
15631 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
15633 struct vty
*vty
= arg
;
15634 struct peer
*peer
= bucket
->data
;
15636 vty_out(vty
, "\tPeer: %s %pSU\n", peer
->host
, &peer
->su
);
15639 DEFUN (show_bgp_listeners
,
15640 show_bgp_listeners_cmd
,
15641 "show bgp listeners",
15644 "Display Listen Sockets and who created them\n")
15646 bgp_dump_listener_info(vty
);
15648 return CMD_SUCCESS
;
15651 DEFUN (show_bgp_peerhash
,
15652 show_bgp_peerhash_cmd
,
15653 "show bgp peerhash",
15656 "Display information about the BGP peerhash\n")
15658 struct list
*instances
= bm
->bgp
;
15659 struct listnode
*node
;
15662 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
15663 vty_out(vty
, "BGP: %s\n", bgp
->name
);
15664 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
15668 return CMD_SUCCESS
;
15671 /* also used for encap safi */
15672 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
15673 afi_t afi
, safi_t safi
)
15675 struct bgp_dest
*pdest
;
15676 struct bgp_dest
*dest
;
15677 struct bgp_table
*table
;
15678 const struct prefix
*p
;
15679 struct bgp_static
*bgp_static
;
15680 mpls_label_t label
;
15682 /* Network configuration. */
15683 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15684 pdest
= bgp_route_next(pdest
)) {
15685 table
= bgp_dest_get_bgp_table_info(pdest
);
15689 for (dest
= bgp_table_top(table
); dest
;
15690 dest
= bgp_route_next(dest
)) {
15691 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15692 if (bgp_static
== NULL
)
15695 p
= bgp_dest_get_prefix(dest
);
15697 /* "network" configuration display. */
15698 label
= decode_label(&bgp_static
->label
);
15700 vty_out(vty
, " network %pFX rd %s", p
,
15701 bgp_static
->prd_pretty
);
15702 if (safi
== SAFI_MPLS_VPN
)
15703 vty_out(vty
, " label %u", label
);
15705 if (bgp_static
->rmap
.name
)
15706 vty_out(vty
, " route-map %s",
15707 bgp_static
->rmap
.name
);
15709 if (bgp_static
->backdoor
)
15710 vty_out(vty
, " backdoor");
15712 vty_out(vty
, "\n");
15717 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
15718 afi_t afi
, safi_t safi
)
15720 struct bgp_dest
*pdest
;
15721 struct bgp_dest
*dest
;
15722 struct bgp_table
*table
;
15723 const struct prefix
*p
;
15724 struct bgp_static
*bgp_static
;
15725 char buf
[PREFIX_STRLEN
* 2];
15726 char buf2
[SU_ADDRSTRLEN
];
15727 char esi_buf
[ESI_STR_LEN
];
15729 /* Network configuration. */
15730 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15731 pdest
= bgp_route_next(pdest
)) {
15732 table
= bgp_dest_get_bgp_table_info(pdest
);
15736 for (dest
= bgp_table_top(table
); dest
;
15737 dest
= bgp_route_next(dest
)) {
15738 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15739 if (bgp_static
== NULL
)
15742 char *macrouter
= NULL
;
15744 if (bgp_static
->router_mac
)
15745 macrouter
= prefix_mac2str(
15746 bgp_static
->router_mac
, NULL
, 0);
15747 if (bgp_static
->eth_s_id
)
15748 esi_to_str(bgp_static
->eth_s_id
,
15749 esi_buf
, sizeof(esi_buf
));
15750 p
= bgp_dest_get_prefix(dest
);
15752 /* "network" configuration display. */
15753 if (p
->u
.prefix_evpn
.route_type
== 5) {
15754 char local_buf
[PREFIX_STRLEN
];
15756 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15757 struct prefix_evpn
*)p
)
15761 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
15763 local_buf
, sizeof(local_buf
));
15764 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15765 p
->u
.prefix_evpn
.prefix_addr
15766 .ip_prefix_length
);
15768 prefix2str(p
, buf
, sizeof(buf
));
15771 if (bgp_static
->gatewayIp
.family
== AF_INET
15772 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15773 inet_ntop(bgp_static
->gatewayIp
.family
,
15774 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15777 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15778 buf
, bgp_static
->prd_pretty
,
15779 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15780 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15783 XFREE(MTYPE_TMP
, macrouter
);
15788 /* Configuration of static route announcement and aggregate
15790 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15793 struct bgp_dest
*dest
;
15794 const struct prefix
*p
;
15795 struct bgp_static
*bgp_static
;
15796 struct bgp_aggregate
*bgp_aggregate
;
15798 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15799 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15803 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15804 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15808 /* Network configuration. */
15809 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15810 dest
= bgp_route_next(dest
)) {
15811 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15812 if (bgp_static
== NULL
)
15815 p
= bgp_dest_get_prefix(dest
);
15817 vty_out(vty
, " network %pFX", p
);
15819 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15820 vty_out(vty
, " label-index %u",
15821 bgp_static
->label_index
);
15823 if (bgp_static
->rmap
.name
)
15824 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15826 if (bgp_static
->backdoor
)
15827 vty_out(vty
, " backdoor");
15829 vty_out(vty
, "\n");
15832 /* Aggregate-address configuration. */
15833 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15834 dest
= bgp_route_next(dest
)) {
15835 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15836 if (bgp_aggregate
== NULL
)
15839 p
= bgp_dest_get_prefix(dest
);
15841 vty_out(vty
, " aggregate-address %pFX", p
);
15843 if (bgp_aggregate
->as_set
)
15844 vty_out(vty
, " as-set");
15846 if (bgp_aggregate
->summary_only
)
15847 vty_out(vty
, " summary-only");
15849 if (bgp_aggregate
->rmap
.name
)
15850 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15852 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15853 vty_out(vty
, " origin %s",
15854 bgp_origin2str(bgp_aggregate
->origin
));
15856 if (bgp_aggregate
->match_med
)
15857 vty_out(vty
, " matching-MED-only");
15859 if (bgp_aggregate
->suppress_map_name
)
15860 vty_out(vty
, " suppress-map %s",
15861 bgp_aggregate
->suppress_map_name
);
15863 vty_out(vty
, "\n");
15867 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15870 struct bgp_dest
*dest
;
15871 struct bgp_distance
*bdistance
;
15873 /* Distance configuration. */
15874 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15875 && bgp
->distance_local
[afi
][safi
]
15876 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15877 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15878 || bgp
->distance_local
[afi
][safi
]
15879 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15880 vty_out(vty
, " distance bgp %d %d %d\n",
15881 bgp
->distance_ebgp
[afi
][safi
],
15882 bgp
->distance_ibgp
[afi
][safi
],
15883 bgp
->distance_local
[afi
][safi
]);
15886 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15887 dest
= bgp_route_next(dest
)) {
15888 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15889 if (bdistance
!= NULL
)
15890 vty_out(vty
, " distance %d %pBD %s\n",
15891 bdistance
->distance
, dest
,
15892 bdistance
->access_list
? bdistance
->access_list
15897 /* Allocate routing table structure and install commands. */
15898 void bgp_route_init(void)
15903 /* Init BGP distance table. */
15904 FOREACH_AFI_SAFI (afi
, safi
)
15905 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15907 /* IPv4 BGP commands. */
15908 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15909 install_element(BGP_NODE
, &bgp_network_cmd
);
15910 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15912 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15914 /* IPv4 unicast configuration. */
15915 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15916 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15917 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15919 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15921 /* IPv4 multicast configuration. */
15922 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15923 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15924 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15925 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15927 /* IPv4 labeled-unicast configuration. */
15928 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15929 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15931 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15932 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15933 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15934 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15935 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15936 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15937 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15938 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15940 install_element(VIEW_NODE
,
15941 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15942 install_element(VIEW_NODE
,
15943 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15944 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15945 install_element(VIEW_NODE
,
15946 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15947 #ifdef KEEP_OLD_VPN_COMMANDS
15948 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15949 #endif /* KEEP_OLD_VPN_COMMANDS */
15950 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15951 install_element(VIEW_NODE
,
15952 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15954 /* BGP dampening clear commands */
15955 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15956 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15958 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15959 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15962 install_element(ENABLE_NODE
,
15963 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15964 #ifdef KEEP_OLD_VPN_COMMANDS
15965 install_element(ENABLE_NODE
,
15966 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15967 #endif /* KEEP_OLD_VPN_COMMANDS */
15969 /* New config IPv6 BGP commands. */
15970 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15971 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15972 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15974 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15976 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15978 /* IPv6 labeled unicast address family. */
15979 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15980 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15982 install_element(BGP_NODE
, &bgp_distance_cmd
);
15983 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15984 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15985 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
15986 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
15987 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
15988 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15989 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15990 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15991 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
15992 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
15993 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
15994 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15995 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15996 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
15997 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
15998 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
15999 install_element(BGP_IPV4M_NODE
,
16000 &no_bgp_distance_source_access_list_cmd
);
16001 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
16002 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
16003 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
16004 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
16005 install_element(BGP_IPV6_NODE
,
16006 &ipv6_bgp_distance_source_access_list_cmd
);
16007 install_element(BGP_IPV6_NODE
,
16008 &no_ipv6_bgp_distance_source_access_list_cmd
);
16009 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
16010 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
16011 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
16012 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
16013 install_element(BGP_IPV6M_NODE
,
16014 &ipv6_bgp_distance_source_access_list_cmd
);
16015 install_element(BGP_IPV6M_NODE
,
16016 &no_ipv6_bgp_distance_source_access_list_cmd
);
16018 /* BGP dampening */
16019 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
16020 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
16021 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
16022 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
16023 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
16024 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
16025 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
16026 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
16027 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
16028 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
16029 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
16030 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
16031 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
16032 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
16034 /* Large Communities */
16035 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
16036 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
16038 /* show bgp ipv4 flowspec detailed */
16039 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
16041 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
16042 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
16045 void bgp_route_finish(void)
16050 FOREACH_AFI_SAFI (afi
, safi
) {
16051 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
16052 bgp_distance_table
[afi
][safi
] = NULL
;