1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* BGP routing information
3 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
4 * Copyright (C) 2016 Job Snijders <job@instituut.net>
21 #include "sockunion.h"
24 #include "workqueue.h"
29 #include "lib_errors.h"
31 #include "bgpd/bgpd.h"
32 #include "bgpd/bgp_table.h"
33 #include "bgpd/bgp_route.h"
34 #include "bgpd/bgp_attr.h"
35 #include "bgpd/bgp_debug.h"
36 #include "bgpd/bgp_errors.h"
37 #include "bgpd/bgp_aspath.h"
38 #include "bgpd/bgp_regex.h"
39 #include "bgpd/bgp_community.h"
40 #include "bgpd/bgp_community_alias.h"
41 #include "bgpd/bgp_ecommunity.h"
42 #include "bgpd/bgp_lcommunity.h"
43 #include "bgpd/bgp_clist.h"
44 #include "bgpd/bgp_packet.h"
45 #include "bgpd/bgp_filter.h"
46 #include "bgpd/bgp_fsm.h"
47 #include "bgpd/bgp_mplsvpn.h"
48 #include "bgpd/bgp_nexthop.h"
49 #include "bgpd/bgp_damp.h"
50 #include "bgpd/bgp_advertise.h"
51 #include "bgpd/bgp_zebra.h"
52 #include "bgpd/bgp_vty.h"
53 #include "bgpd/bgp_mpath.h"
54 #include "bgpd/bgp_nht.h"
55 #include "bgpd/bgp_updgrp.h"
56 #include "bgpd/bgp_label.h"
57 #include "bgpd/bgp_addpath.h"
58 #include "bgpd/bgp_mac.h"
59 #include "bgpd/bgp_network.h"
60 #include "bgpd/bgp_trace.h"
61 #include "bgpd/bgp_rpki.h"
64 #include "bgpd/rfapi/rfapi_backend.h"
65 #include "bgpd/rfapi/vnc_import_bgp.h"
66 #include "bgpd/rfapi/vnc_export_bgp.h"
68 #include "bgpd/bgp_encap_types.h"
69 #include "bgpd/bgp_encap_tlv.h"
70 #include "bgpd/bgp_evpn.h"
71 #include "bgpd/bgp_evpn_mh.h"
72 #include "bgpd/bgp_evpn_vty.h"
73 #include "bgpd/bgp_flowspec.h"
74 #include "bgpd/bgp_flowspec_util.h"
75 #include "bgpd/bgp_pbr.h"
77 #include "bgpd/bgp_route_clippy.c"
79 DEFINE_HOOK(bgp_snmp_update_stats
,
80 (struct bgp_node
*rn
, struct bgp_path_info
*pi
, bool added
),
83 DEFINE_HOOK(bgp_rpki_prefix_status
,
84 (struct peer
*peer
, struct attr
*attr
,
85 const struct prefix
*prefix
),
86 (peer
, attr
, prefix
));
88 /* Extern from bgp_dump.c */
89 extern const char *bgp_origin_str
[];
90 extern const char *bgp_origin_long_str
[];
93 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
94 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
95 static const struct message bgp_pmsi_tnltype_str
[] = {
96 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
97 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
98 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
99 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
100 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
101 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
102 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
103 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
107 #define VRFID_NONE_STR "-"
108 #define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
110 DEFINE_HOOK(bgp_process
,
111 (struct bgp
* bgp
, afi_t afi
, safi_t safi
, struct bgp_dest
*bn
,
112 struct peer
*peer
, bool withdraw
),
113 (bgp
, afi
, safi
, bn
, peer
, withdraw
));
115 /** Test if path is suppressed. */
116 static bool bgp_path_suppressed(struct bgp_path_info
*pi
)
118 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
121 return listcount(pi
->extra
->aggr_suppressors
) > 0;
124 struct bgp_dest
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
125 safi_t safi
, const struct prefix
*p
,
126 struct prefix_rd
*prd
)
128 struct bgp_dest
*dest
;
129 struct bgp_dest
*pdest
= NULL
;
133 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
134 || (safi
== SAFI_EVPN
)) {
135 pdest
= bgp_node_get(table
, (struct prefix
*)prd
);
137 if (!bgp_dest_has_bgp_path_info_data(pdest
))
138 bgp_dest_set_bgp_table_info(
139 pdest
, bgp_table_init(table
->bgp
, afi
, safi
));
141 bgp_dest_unlock_node(pdest
);
142 table
= bgp_dest_get_bgp_table_info(pdest
);
145 dest
= bgp_node_get(table
, p
);
147 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
148 || (safi
== SAFI_EVPN
))
154 struct bgp_dest
*bgp_safi_node_lookup(struct bgp_table
*table
, safi_t safi
,
155 const struct prefix
*p
,
156 struct prefix_rd
*prd
)
158 struct bgp_dest
*dest
;
159 struct bgp_dest
*pdest
= NULL
;
164 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
165 || (safi
== SAFI_EVPN
)) {
166 pdest
= bgp_node_lookup(table
, (struct prefix
*)prd
);
170 if (!bgp_dest_has_bgp_path_info_data(pdest
)) {
171 bgp_dest_unlock_node(pdest
);
175 table
= bgp_dest_get_bgp_table_info(pdest
);
178 dest
= bgp_node_lookup(table
, p
);
183 /* Allocate bgp_path_info_extra */
184 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
186 struct bgp_path_info_extra
*new;
187 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
188 sizeof(struct bgp_path_info_extra
));
189 new->label
[0] = MPLS_INVALID_LABEL
;
191 new->bgp_fs_pbr
= NULL
;
192 new->bgp_fs_iprule
= NULL
;
196 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
198 struct bgp_path_info_extra
*e
;
200 if (!extra
|| !*extra
)
205 bgp_damp_info_free(e
->damp_info
, 0, e
->damp_info
->afi
,
210 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
213 /* FIXME: since multiple e may have the same e->parent
214 * and e->parent->net is holding a refcount for each
215 * of them, we need to do some fudging here.
217 * WARNING: if bpi->net->lock drops to 0, bpi may be
218 * freed as well (because bpi->net was holding the
219 * last reference to bpi) => write after free!
223 bpi
= bgp_path_info_lock(bpi
);
224 refcount
= bgp_dest_get_lock_count(bpi
->net
) - 1;
225 bgp_dest_unlock_node((struct bgp_dest
*)bpi
->net
);
228 bgp_path_info_unlock(bpi
);
230 bgp_path_info_unlock(e
->parent
);
235 bgp_unlock(e
->bgp_orig
);
238 peer_unlock(e
->peer_orig
);
240 if (e
->aggr_suppressors
)
241 list_delete(&e
->aggr_suppressors
);
244 bgp_evpn_path_mh_info_free(e
->mh_info
);
246 if ((*extra
)->bgp_fs_iprule
)
247 list_delete(&((*extra
)->bgp_fs_iprule
));
248 if ((*extra
)->bgp_fs_pbr
)
249 list_delete(&((*extra
)->bgp_fs_pbr
));
250 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
253 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
254 * allocated if required.
256 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
259 pi
->extra
= bgp_path_info_extra_new();
263 /* Free bgp route information. */
264 void bgp_path_info_free_with_caller(const char *name
,
265 struct bgp_path_info
*path
)
267 frrtrace(2, frr_bgp
, bgp_path_info_free
, path
, name
);
268 bgp_attr_unintern(&path
->attr
);
270 bgp_unlink_nexthop(path
);
271 bgp_path_info_extra_free(&path
->extra
);
272 bgp_path_info_mpath_free(&path
->mpath
);
274 bgp_addpath_free_info_data(&path
->tx_addpath
,
275 &path
->net
->tx_addpath
);
277 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
279 XFREE(MTYPE_BGP_ROUTE
, path
);
282 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
288 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
290 assert(path
&& path
->lock
> 0);
293 if (path
->lock
== 0) {
294 bgp_path_info_free(path
);
301 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
302 static int bgp_dest_set_defer_flag(struct bgp_dest
*dest
, bool delete)
305 struct bgp_path_info
*old_pi
, *nextpi
;
306 bool set_flag
= false;
307 struct bgp
*bgp
= NULL
;
308 struct bgp_table
*table
= NULL
;
312 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
313 * then the route selection is deferred
315 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
318 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
319 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
320 table
= bgp_dest_table(dest
);
325 "Route %pBD(%s) is in workqueue and being processed, not deferred.",
326 dest
, bgp
? bgp
->name_pretty
: "(Unknown)");
332 table
= bgp_dest_table(dest
);
339 for (old_pi
= bgp_dest_get_bgp_path_info(dest
);
340 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
341 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
344 /* Route selection is deferred if there is a stale path which
345 * which indicates peer is in restart mode
347 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
348 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
351 /* If the peer is graceful restart capable and peer is
352 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
355 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
356 && BGP_PEER_RESTARTING_MODE(peer
)
358 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
366 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
369 if (set_flag
&& table
) {
370 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
371 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
372 bgp
->gr_info
[afi
][safi
].gr_deferred
++;
373 SET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
374 if (BGP_DEBUG(update
, UPDATE_OUT
))
375 zlog_debug("DEFER route %pBD(%s), dest %p",
376 dest
, bgp
->name_pretty
, dest
);
383 void bgp_path_info_add_with_caller(const char *name
, struct bgp_dest
*dest
,
384 struct bgp_path_info
*pi
)
386 frrtrace(3, frr_bgp
, bgp_path_info_add
, dest
, pi
, name
);
387 struct bgp_path_info
*top
;
389 top
= bgp_dest_get_bgp_path_info(dest
);
395 bgp_dest_set_bgp_path_info(dest
, pi
);
397 bgp_path_info_lock(pi
);
398 bgp_dest_lock_node(dest
);
399 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
400 bgp_dest_set_defer_flag(dest
, false);
401 hook_call(bgp_snmp_update_stats
, dest
, pi
, true);
404 /* Do the actual removal of info from RIB, for use by bgp_process
405 completion callback *only* */
406 void bgp_path_info_reap(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
409 pi
->next
->prev
= pi
->prev
;
411 pi
->prev
->next
= pi
->next
;
413 bgp_dest_set_bgp_path_info(dest
, pi
->next
);
415 bgp_path_info_mpath_dequeue(pi
);
416 bgp_path_info_unlock(pi
);
417 hook_call(bgp_snmp_update_stats
, dest
, pi
, false);
418 bgp_dest_unlock_node(dest
);
421 void bgp_path_info_delete(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
423 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_REMOVED
);
424 /* set of previous already took care of pcount */
425 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
428 /* undo the effects of a previous call to bgp_path_info_delete; typically
429 called when a route is deleted and then quickly re-added before the
430 deletion has been processed */
431 void bgp_path_info_restore(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
433 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_REMOVED
);
434 /* unset of previous already took care of pcount */
435 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
438 /* Adjust pcount as required */
439 static void bgp_pcount_adjust(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
441 struct bgp_table
*table
;
443 assert(dest
&& bgp_dest_table(dest
));
444 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
446 table
= bgp_dest_table(dest
);
448 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
451 if (!BGP_PATH_COUNTABLE(pi
)
452 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
454 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
456 /* slight hack, but more robust against errors. */
457 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
458 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
460 flog_err(EC_LIB_DEVELOPMENT
,
461 "Asked to decrement 0 prefix count for peer");
462 } else if (BGP_PATH_COUNTABLE(pi
)
463 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
464 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
465 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
469 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
470 struct bgp_path_info
*pi2
)
472 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
475 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
476 * This is here primarily to keep prefix-count in check.
478 void bgp_path_info_set_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
481 SET_FLAG(pi
->flags
, flag
);
483 /* early bath if we know it's not a flag that changes countability state
485 if (!CHECK_FLAG(flag
,
486 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
489 bgp_pcount_adjust(dest
, pi
);
492 void bgp_path_info_unset_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
495 UNSET_FLAG(pi
->flags
, flag
);
497 /* early bath if we know it's not a flag that changes countability state
499 if (!CHECK_FLAG(flag
,
500 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
503 bgp_pcount_adjust(dest
, pi
);
506 /* Get MED value. If MED value is missing and "bgp bestpath
507 missing-as-worst" is specified, treat it as the worst value. */
508 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
510 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
513 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
520 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
,
525 if (pi
->sub_type
== BGP_ROUTE_IMPORTED
&&
526 bgp_get_imported_bpi_ultimate(pi
))
527 peer
= bgp_get_imported_bpi_ultimate(pi
)->peer
;
531 if (pi
->addpath_rx_id
)
532 snprintf(buf
, buf_len
, "path %s (addpath rxid %d)", peer
->host
,
535 snprintf(buf
, buf_len
, "path %s", peer
->host
);
540 * Get the ultimate path info.
542 struct bgp_path_info
*bgp_get_imported_bpi_ultimate(struct bgp_path_info
*info
)
544 struct bgp_path_info
*bpi_ultimate
;
546 if (info
->sub_type
!= BGP_ROUTE_IMPORTED
)
549 for (bpi_ultimate
= info
;
550 bpi_ultimate
->extra
&& bpi_ultimate
->extra
->parent
;
551 bpi_ultimate
= bpi_ultimate
->extra
->parent
)
557 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
559 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
560 struct bgp_path_info
*exist
, int *paths_eq
,
561 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
562 char *pfx_buf
, afi_t afi
, safi_t safi
,
563 enum bgp_path_selection_reason
*reason
)
565 const struct prefix
*new_p
;
566 struct attr
*newattr
, *existattr
;
567 enum bgp_peer_sort new_sort
;
568 enum bgp_peer_sort exist_sort
;
574 uint32_t exist_weight
;
575 uint32_t newm
, existm
;
576 struct in_addr new_id
;
577 struct in_addr exist_id
;
580 int internal_as_route
;
583 int igp_metric_ret
= 0;
584 int peer_sort_ret
= -1;
585 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
586 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
588 uint32_t exist_mm_seq
;
595 bool new_origin
, exist_origin
;
596 struct bgp_path_info
*bpi_ultimate
;
597 struct peer
*peer_new
, *peer_exist
;
603 *reason
= bgp_path_selection_none
;
605 zlog_debug("%s: new is NULL", pfx_buf
);
610 bpi_ultimate
= bgp_get_imported_bpi_ultimate(new);
611 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, new_buf
,
616 *reason
= bgp_path_selection_first
;
618 zlog_debug("%s(%s): %s is the initial bestpath",
619 pfx_buf
, bgp
->name_pretty
, new_buf
);
624 bpi_ultimate
= bgp_get_imported_bpi_ultimate(exist
);
625 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, exist_buf
,
627 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
628 pfx_buf
, bgp
->name_pretty
, new_buf
, new->flags
,
629 exist_buf
, exist
->flags
);
633 existattr
= exist
->attr
;
635 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
636 * Capability" to a neighbor MUST perform the following upon receiving
637 * a route from that neighbor with the "LLGR_STALE" community, or upon
638 * attaching the "LLGR_STALE" community itself per Section 4.2:
640 * Treat the route as the least-preferred in route selection (see
641 * below). See the Risks of Depreferencing Routes section (Section 5.2)
642 * for a discussion of potential risks inherent in doing this.
644 if (bgp_attr_get_community(newattr
) &&
645 community_include(bgp_attr_get_community(newattr
),
646 COMMUNITY_LLGR_STALE
)) {
649 "%s: %s wins over %s due to LLGR_STALE community",
650 pfx_buf
, new_buf
, exist_buf
);
654 if (bgp_attr_get_community(existattr
) &&
655 community_include(bgp_attr_get_community(existattr
),
656 COMMUNITY_LLGR_STALE
)) {
659 "%s: %s loses to %s due to LLGR_STALE community",
660 pfx_buf
, new_buf
, exist_buf
);
664 new_p
= bgp_dest_get_prefix(new->net
);
666 /* For EVPN routes, we cannot just go by local vs remote, we have to
667 * look at the MAC mobility sequence number, if present.
669 if ((safi
== SAFI_EVPN
)
670 && (new_p
->u
.prefix_evpn
.route_type
== BGP_EVPN_MAC_IP_ROUTE
)) {
671 /* This is an error condition described in RFC 7432 Section
673 * states that in this scenario "the PE MUST alert the operator"
675 * does not state what other action to take. In order to provide
677 * consistency in this scenario we are going to prefer the path
681 if (newattr
->sticky
!= existattr
->sticky
) {
683 prefix2str(new_p
, pfx_buf
,
685 * PREFIX2STR_BUFFER
);
686 bgp_path_info_path_with_addpath_rx_str(
687 new, new_buf
, sizeof(new_buf
));
688 bgp_path_info_path_with_addpath_rx_str(
689 exist
, exist_buf
, sizeof(exist_buf
));
692 if (newattr
->sticky
&& !existattr
->sticky
) {
693 *reason
= bgp_path_selection_evpn_sticky_mac
;
696 "%s: %s wins over %s due to sticky MAC flag",
697 pfx_buf
, new_buf
, exist_buf
);
701 if (!newattr
->sticky
&& existattr
->sticky
) {
702 *reason
= bgp_path_selection_evpn_sticky_mac
;
705 "%s: %s loses to %s due to sticky MAC flag",
706 pfx_buf
, new_buf
, exist_buf
);
711 new_esi
= bgp_evpn_attr_get_esi(newattr
);
712 exist_esi
= bgp_evpn_attr_get_esi(existattr
);
713 if (bgp_evpn_is_esi_valid(new_esi
) &&
714 !memcmp(new_esi
, exist_esi
, sizeof(esi_t
))) {
720 /* If both paths have the same non-zero ES and
721 * one path is local it wins.
722 * PS: Note the local path wins even if the remote
723 * has the higher MM seq. The local path's
724 * MM seq will be fixed up to match the highest
725 * rem seq, subsequently.
728 char esi_buf
[ESI_STR_LEN
];
730 if (bgp_evpn_is_path_local(bgp
, new)) {
731 *reason
= bgp_path_selection_evpn_local_path
;
734 "%s: %s wins over %s as ES %s is same and local",
735 pfx_buf
, new_buf
, exist_buf
,
736 esi_to_str(new_esi
, esi_buf
,
740 if (bgp_evpn_is_path_local(bgp
, exist
)) {
741 *reason
= bgp_path_selection_evpn_local_path
;
744 "%s: %s loses to %s as ES %s is same and local",
745 pfx_buf
, new_buf
, exist_buf
,
746 esi_to_str(new_esi
, esi_buf
,
752 new_mm_seq
= mac_mobility_seqnum(newattr
);
753 exist_mm_seq
= mac_mobility_seqnum(existattr
);
755 if (new_mm_seq
> exist_mm_seq
) {
756 *reason
= bgp_path_selection_evpn_seq
;
759 "%s: %s wins over %s due to MM seq %u > %u",
760 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
765 if (new_mm_seq
< exist_mm_seq
) {
766 *reason
= bgp_path_selection_evpn_seq
;
769 "%s: %s loses to %s due to MM seq %u < %u",
770 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
775 /* if the sequence numbers and ESI are the same and one path
776 * is non-proxy it wins (over proxy)
778 new_proxy
= bgp_evpn_attr_is_proxy(newattr
);
779 old_proxy
= bgp_evpn_attr_is_proxy(existattr
);
780 if (same_esi
&& bgp_evpn_attr_is_local_es(newattr
) &&
781 old_proxy
!= new_proxy
) {
783 *reason
= bgp_path_selection_evpn_non_proxy
;
786 "%s: %s wins over %s, same seq/es and non-proxy",
787 pfx_buf
, new_buf
, exist_buf
);
791 *reason
= bgp_path_selection_evpn_non_proxy
;
794 "%s: %s loses to %s, same seq/es and non-proxy",
795 pfx_buf
, new_buf
, exist_buf
);
800 * if sequence numbers are the same path with the lowest IP
803 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
805 *reason
= bgp_path_selection_evpn_lower_ip
;
808 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
809 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
810 &new->attr
->nexthop
);
814 *reason
= bgp_path_selection_evpn_lower_ip
;
817 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
818 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
819 &new->attr
->nexthop
);
824 /* 1. Weight check. */
825 new_weight
= newattr
->weight
;
826 exist_weight
= existattr
->weight
;
828 if (new_weight
> exist_weight
) {
829 *reason
= bgp_path_selection_weight
;
831 zlog_debug("%s: %s wins over %s due to weight %d > %d",
832 pfx_buf
, new_buf
, exist_buf
, new_weight
,
837 if (new_weight
< exist_weight
) {
838 *reason
= bgp_path_selection_weight
;
840 zlog_debug("%s: %s loses to %s due to weight %d < %d",
841 pfx_buf
, new_buf
, exist_buf
, new_weight
,
846 /* 2. Local preference check. */
847 new_pref
= exist_pref
= bgp
->default_local_pref
;
849 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
850 new_pref
= newattr
->local_pref
;
851 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
852 exist_pref
= existattr
->local_pref
;
854 if (new_pref
> exist_pref
) {
855 *reason
= bgp_path_selection_local_pref
;
858 "%s: %s wins over %s due to localpref %d > %d",
859 pfx_buf
, new_buf
, exist_buf
, new_pref
,
864 if (new_pref
< exist_pref
) {
865 *reason
= bgp_path_selection_local_pref
;
868 "%s: %s loses to %s due to localpref %d < %d",
869 pfx_buf
, new_buf
, exist_buf
, new_pref
,
874 /* If a BGP speaker supports ACCEPT_OWN and is configured for the
875 * extensions defined in this document, the following step is inserted
876 * after the LOCAL_PREF comparison step in the BGP decision process:
877 * When comparing a pair of routes for a BGP destination, the
878 * route with the ACCEPT_OWN community attached is preferred over
879 * the route that does not have the community.
880 * This extra step MUST only be invoked during the best path selection
881 * process of VPN-IP routes.
883 if (safi
== SAFI_MPLS_VPN
&&
884 (CHECK_FLAG(new->peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
) ||
885 CHECK_FLAG(exist
->peer
->af_flags
[afi
][safi
],
886 PEER_FLAG_ACCEPT_OWN
))) {
887 bool new_accept_own
= false;
888 bool exist_accept_own
= false;
889 uint32_t accept_own
= COMMUNITY_ACCEPT_OWN
;
891 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))
892 new_accept_own
= community_include(
893 bgp_attr_get_community(newattr
), accept_own
);
894 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))
895 exist_accept_own
= community_include(
896 bgp_attr_get_community(existattr
), accept_own
);
898 if (new_accept_own
&& !exist_accept_own
) {
899 *reason
= bgp_path_selection_accept_own
;
902 "%s: %s wins over %s due to accept-own",
903 pfx_buf
, new_buf
, exist_buf
);
907 if (!new_accept_own
&& exist_accept_own
) {
908 *reason
= bgp_path_selection_accept_own
;
911 "%s: %s loses to %s due to accept-own",
912 pfx_buf
, new_buf
, exist_buf
);
917 /* Tie-breaker - AIGP (Metric TLV) attribute */
918 if (CHECK_FLAG(newattr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) &&
919 CHECK_FLAG(existattr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) &&
920 CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_AIGP
)) {
921 uint64_t new_aigp
= bgp_attr_get_aigp_metric(newattr
);
922 uint64_t exist_aigp
= bgp_attr_get_aigp_metric(existattr
);
924 if (new_aigp
< exist_aigp
) {
925 *reason
= bgp_path_selection_aigp
;
928 "%s: %s wins over %s due to AIGP %" PRIu64
930 pfx_buf
, new_buf
, exist_buf
, new_aigp
,
935 if (new_aigp
> exist_aigp
) {
936 *reason
= bgp_path_selection_aigp
;
939 "%s: %s loses to %s due to AIGP %" PRIu64
941 pfx_buf
, new_buf
, exist_buf
, new_aigp
,
947 /* 3. Local route check. We prefer:
949 * - BGP_ROUTE_AGGREGATE
950 * - BGP_ROUTE_REDISTRIBUTE
952 new_origin
= !(new->sub_type
== BGP_ROUTE_NORMAL
||
953 new->sub_type
== BGP_ROUTE_IMPORTED
);
954 exist_origin
= !(exist
->sub_type
== BGP_ROUTE_NORMAL
||
955 exist
->sub_type
== BGP_ROUTE_IMPORTED
);
957 if (new_origin
&& !exist_origin
) {
958 *reason
= bgp_path_selection_local_route
;
961 "%s: %s wins over %s due to preferred BGP_ROUTE type",
962 pfx_buf
, new_buf
, exist_buf
);
966 if (!new_origin
&& exist_origin
) {
967 *reason
= bgp_path_selection_local_route
;
970 "%s: %s loses to %s due to preferred BGP_ROUTE type",
971 pfx_buf
, new_buf
, exist_buf
);
975 /* Here if these are imported routes then get ultimate pi for
978 new = bgp_get_imported_bpi_ultimate(new);
979 exist
= bgp_get_imported_bpi_ultimate(exist
);
981 existattr
= exist
->attr
;
983 /* 4. AS path length check. */
984 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
985 int exist_hops
= aspath_count_hops(existattr
->aspath
);
986 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
988 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
991 aspath_hops
= aspath_count_hops(newattr
->aspath
);
992 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
994 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
995 *reason
= bgp_path_selection_confed_as_path
;
998 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
999 pfx_buf
, new_buf
, exist_buf
,
1001 (exist_hops
+ exist_confeds
));
1005 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
1006 *reason
= bgp_path_selection_confed_as_path
;
1009 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
1010 pfx_buf
, new_buf
, exist_buf
,
1012 (exist_hops
+ exist_confeds
));
1016 int newhops
= aspath_count_hops(newattr
->aspath
);
1018 if (newhops
< exist_hops
) {
1019 *reason
= bgp_path_selection_as_path
;
1022 "%s: %s wins over %s due to aspath hopcount %d < %d",
1023 pfx_buf
, new_buf
, exist_buf
,
1024 newhops
, exist_hops
);
1028 if (newhops
> exist_hops
) {
1029 *reason
= bgp_path_selection_as_path
;
1032 "%s: %s loses to %s due to aspath hopcount %d > %d",
1033 pfx_buf
, new_buf
, exist_buf
,
1034 newhops
, exist_hops
);
1040 /* 5. Origin check. */
1041 if (newattr
->origin
< existattr
->origin
) {
1042 *reason
= bgp_path_selection_origin
;
1044 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
1045 pfx_buf
, new_buf
, exist_buf
,
1046 bgp_origin_long_str
[newattr
->origin
],
1047 bgp_origin_long_str
[existattr
->origin
]);
1051 if (newattr
->origin
> existattr
->origin
) {
1052 *reason
= bgp_path_selection_origin
;
1054 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
1055 pfx_buf
, new_buf
, exist_buf
,
1056 bgp_origin_long_str
[newattr
->origin
],
1057 bgp_origin_long_str
[existattr
->origin
]);
1062 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
1063 && aspath_count_hops(existattr
->aspath
) == 0);
1064 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
1065 && aspath_count_confeds(existattr
->aspath
) > 0
1066 && aspath_count_hops(newattr
->aspath
) == 0
1067 && aspath_count_hops(existattr
->aspath
) == 0);
1069 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
1070 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
1071 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
1072 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
1073 || internal_as_route
) {
1074 new_med
= bgp_med_value(new->attr
, bgp
);
1075 exist_med
= bgp_med_value(exist
->attr
, bgp
);
1077 if (new_med
< exist_med
) {
1078 *reason
= bgp_path_selection_med
;
1081 "%s: %s wins over %s due to MED %d < %d",
1082 pfx_buf
, new_buf
, exist_buf
, new_med
,
1087 if (new_med
> exist_med
) {
1088 *reason
= bgp_path_selection_med
;
1091 "%s: %s loses to %s due to MED %d > %d",
1092 pfx_buf
, new_buf
, exist_buf
, new_med
,
1098 if (exist
->sub_type
== BGP_ROUTE_IMPORTED
) {
1099 bpi_ultimate
= bgp_get_imported_bpi_ultimate(exist
);
1100 peer_exist
= bpi_ultimate
->peer
;
1102 peer_exist
= exist
->peer
;
1104 if (new->sub_type
== BGP_ROUTE_IMPORTED
) {
1105 bpi_ultimate
= bgp_get_imported_bpi_ultimate(new);
1106 peer_new
= bpi_ultimate
->peer
;
1108 peer_new
= new->peer
;
1110 /* 7. Peer type check. */
1111 new_sort
= peer_new
->sort
;
1112 exist_sort
= peer_exist
->sort
;
1114 if (new_sort
== BGP_PEER_EBGP
1115 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
1116 *reason
= bgp_path_selection_peer
;
1119 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1120 pfx_buf
, new_buf
, exist_buf
);
1121 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1126 if (exist_sort
== BGP_PEER_EBGP
1127 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
1128 *reason
= bgp_path_selection_peer
;
1131 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1132 pfx_buf
, new_buf
, exist_buf
);
1133 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1138 /* 8. IGP metric check. */
1142 newm
= new->extra
->igpmetric
;
1144 existm
= exist
->extra
->igpmetric
;
1146 if (newm
< existm
) {
1147 if (debug
&& peer_sort_ret
< 0)
1149 "%s: %s wins over %s due to IGP metric %u < %u",
1150 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1154 if (newm
> existm
) {
1155 if (debug
&& peer_sort_ret
< 0)
1157 "%s: %s loses to %s due to IGP metric %u > %u",
1158 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1162 /* 9. Same IGP metric. Compare the cluster list length as
1163 representative of IGP hops metric. Rewrite the metric value
1164 pair (newm, existm) with the cluster list length. Prefer the
1165 path with smaller cluster list length. */
1166 if (newm
== existm
) {
1167 if (peer_sort_lookup(peer_new
) == BGP_PEER_IBGP
&&
1168 peer_sort_lookup(peer_exist
) == BGP_PEER_IBGP
&&
1169 (mpath_cfg
== NULL
|| mpath_cfg
->same_clusterlen
)) {
1170 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1171 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1173 if (newm
< existm
) {
1174 if (debug
&& peer_sort_ret
< 0)
1176 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
1177 pfx_buf
, new_buf
, exist_buf
,
1182 if (newm
> existm
) {
1183 if (debug
&& peer_sort_ret
< 0)
1185 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
1186 pfx_buf
, new_buf
, exist_buf
,
1193 /* 10. confed-external vs. confed-internal */
1194 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1195 if (new_sort
== BGP_PEER_CONFED
1196 && exist_sort
== BGP_PEER_IBGP
) {
1197 *reason
= bgp_path_selection_confed
;
1200 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1201 pfx_buf
, new_buf
, exist_buf
);
1202 if (!CHECK_FLAG(bgp
->flags
,
1203 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1208 if (exist_sort
== BGP_PEER_CONFED
1209 && new_sort
== BGP_PEER_IBGP
) {
1210 *reason
= bgp_path_selection_confed
;
1213 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1214 pfx_buf
, new_buf
, exist_buf
);
1215 if (!CHECK_FLAG(bgp
->flags
,
1216 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1222 /* 11. Maximum path check. */
1223 if (newm
== existm
) {
1224 /* If one path has a label but the other does not, do not treat
1225 * them as equals for multipath
1232 newl
= new->extra
->num_labels
;
1234 existl
= exist
->extra
->num_labels
;
1235 if (((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0])) !=
1237 bgp_is_valid_label(&exist
->extra
->label
[0]))) ||
1241 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1242 pfx_buf
, new_buf
, exist_buf
);
1243 } else if (CHECK_FLAG(bgp
->flags
,
1244 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
1247 * For the two paths, all comparison steps till IGP
1249 * have succeeded - including AS_PATH hop count. Since
1251 * bestpath as-path multipath-relax' knob is on, we
1253 * an exact match of AS_PATH. Thus, mark the paths are
1255 * That will trigger both these paths to get into the
1263 "%s: %s and %s are equal via multipath-relax",
1264 pfx_buf
, new_buf
, exist_buf
);
1265 } else if (peer_new
->sort
== BGP_PEER_IBGP
) {
1266 if (aspath_cmp(new->attr
->aspath
,
1267 exist
->attr
->aspath
)) {
1272 "%s: %s and %s are equal via matching aspaths",
1273 pfx_buf
, new_buf
, exist_buf
);
1275 } else if (peer_new
->as
== peer_exist
->as
) {
1280 "%s: %s and %s are equal via same remote-as",
1281 pfx_buf
, new_buf
, exist_buf
);
1285 * TODO: If unequal cost ibgp multipath is enabled we can
1286 * mark the paths as equal here instead of returning
1289 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1290 * if either step 7 or 10 (peer type checks) yielded a winner,
1291 * that result was returned immediately. Returning from step 10
1292 * ignored the return value computed in steps 8 and 9 (IGP
1293 * metric checks). In order to preserve that behavior, if
1294 * peer_sort_ret is set, return that rather than igp_metric_ret.
1296 ret
= peer_sort_ret
;
1297 if (peer_sort_ret
< 0) {
1298 ret
= igp_metric_ret
;
1302 "%s: %s wins over %s after IGP metric comparison",
1303 pfx_buf
, new_buf
, exist_buf
);
1306 "%s: %s loses to %s after IGP metric comparison",
1307 pfx_buf
, new_buf
, exist_buf
);
1309 *reason
= bgp_path_selection_igp_metric
;
1315 * At this point, the decision whether to set *paths_eq = 1 has been
1316 * completed. If we deferred returning because of bestpath peer-type
1317 * relax configuration, return now.
1319 if (peer_sort_ret
>= 0)
1320 return peer_sort_ret
;
1322 /* 12. If both paths are external, prefer the path that was received
1323 first (the oldest one). This step minimizes route-flap, since a
1324 newer path won't displace an older one, even if it was the
1325 preferred route based on the additional decision criteria below. */
1326 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1327 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1328 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1329 *reason
= bgp_path_selection_older
;
1332 "%s: %s wins over %s due to oldest external",
1333 pfx_buf
, new_buf
, exist_buf
);
1337 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1338 *reason
= bgp_path_selection_older
;
1341 "%s: %s loses to %s due to oldest external",
1342 pfx_buf
, new_buf
, exist_buf
);
1347 /* 13. Router-ID comparison. */
1348 /* If one of the paths is "stale", the corresponding peer router-id will
1349 * be 0 and would always win over the other path. If originator id is
1350 * used for the comparison, it will decide which path is better.
1352 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1353 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1355 new_id
.s_addr
= peer_new
->remote_id
.s_addr
;
1356 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1357 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1359 exist_id
.s_addr
= peer_exist
->remote_id
.s_addr
;
1361 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1362 *reason
= bgp_path_selection_router_id
;
1365 "%s: %s wins over %s due to Router-ID comparison",
1366 pfx_buf
, new_buf
, exist_buf
);
1370 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1371 *reason
= bgp_path_selection_router_id
;
1374 "%s: %s loses to %s due to Router-ID comparison",
1375 pfx_buf
, new_buf
, exist_buf
);
1379 /* 14. Cluster length comparison. */
1380 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1381 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1383 if (new_cluster
< exist_cluster
) {
1384 *reason
= bgp_path_selection_cluster_length
;
1387 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1388 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1393 if (new_cluster
> exist_cluster
) {
1394 *reason
= bgp_path_selection_cluster_length
;
1397 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1398 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1403 /* 15. Neighbor address comparison. */
1404 /* Do this only if neither path is "stale" as stale paths do not have
1405 * valid peer information (as the connection may or may not be up).
1407 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1408 *reason
= bgp_path_selection_stale
;
1411 "%s: %s wins over %s due to latter path being STALE",
1412 pfx_buf
, new_buf
, exist_buf
);
1416 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1417 *reason
= bgp_path_selection_stale
;
1420 "%s: %s loses to %s due to former path being STALE",
1421 pfx_buf
, new_buf
, exist_buf
);
1425 /* locally configured routes to advertise do not have su_remote */
1426 if (peer_new
->su_remote
== NULL
) {
1427 *reason
= bgp_path_selection_local_configured
;
1431 if (peer_exist
->su_remote
== NULL
) {
1432 *reason
= bgp_path_selection_local_configured
;
1436 ret
= sockunion_cmp(peer_new
->su_remote
, peer_exist
->su_remote
);
1439 *reason
= bgp_path_selection_neighbor_ip
;
1442 "%s: %s loses to %s due to Neighor IP comparison",
1443 pfx_buf
, new_buf
, exist_buf
);
1448 *reason
= bgp_path_selection_neighbor_ip
;
1451 "%s: %s wins over %s due to Neighor IP comparison",
1452 pfx_buf
, new_buf
, exist_buf
);
1456 *reason
= bgp_path_selection_default
;
1458 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1459 pfx_buf
, new_buf
, exist_buf
);
1465 int bgp_evpn_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
1466 struct bgp_path_info
*exist
, int *paths_eq
)
1468 enum bgp_path_selection_reason reason
;
1469 char pfx_buf
[PREFIX2STR_BUFFER
];
1471 return bgp_path_info_cmp(bgp
, new, exist
, paths_eq
, NULL
, 0, pfx_buf
,
1472 AFI_L2VPN
, SAFI_EVPN
, &reason
);
1475 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1476 * is preferred, or 0 if they are the same (usually will only occur if
1477 * multipath is enabled
1478 * This version is compatible with */
1479 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1480 struct bgp_path_info
*exist
, char *pfx_buf
,
1481 afi_t afi
, safi_t safi
,
1482 enum bgp_path_selection_reason
*reason
)
1486 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1500 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1501 const struct prefix
*p
,
1502 struct attr
*attr
, afi_t afi
,
1505 struct bgp_filter
*filter
;
1506 enum filter_type ret
= FILTER_PERMIT
;
1508 filter
= &peer
->filter
[afi
][safi
];
1510 #define FILTER_EXIST_WARN(F, f, filter) \
1511 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1512 zlog_debug("%s: Could not find configured input %s-list %s!", \
1513 peer->host, #f, F##_IN_NAME(filter));
1515 if (DISTRIBUTE_IN_NAME(filter
)) {
1516 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1518 if (access_list_apply(DISTRIBUTE_IN(filter
), p
)
1525 if (PREFIX_LIST_IN_NAME(filter
)) {
1526 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1528 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
)
1535 if (FILTER_LIST_IN_NAME(filter
)) {
1536 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1538 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1539 == AS_FILTER_DENY
) {
1546 if (frrtrace_enabled(frr_bgp
, input_filter
)) {
1547 char pfxprint
[PREFIX2STR_BUFFER
];
1549 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1550 frrtrace(5, frr_bgp
, input_filter
, peer
, pfxprint
, afi
, safi
,
1551 ret
== FILTER_PERMIT
? "permit" : "deny");
1555 #undef FILTER_EXIST_WARN
1558 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1559 const struct prefix
*p
,
1560 struct attr
*attr
, afi_t afi
,
1563 struct bgp_filter
*filter
;
1564 enum filter_type ret
= FILTER_PERMIT
;
1566 filter
= &peer
->filter
[afi
][safi
];
1568 #define FILTER_EXIST_WARN(F, f, filter) \
1569 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1570 zlog_debug("%s: Could not find configured output %s-list %s!", \
1571 peer->host, #f, F##_OUT_NAME(filter));
1573 if (DISTRIBUTE_OUT_NAME(filter
)) {
1574 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1576 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
)
1583 if (PREFIX_LIST_OUT_NAME(filter
)) {
1584 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1586 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1593 if (FILTER_LIST_OUT_NAME(filter
)) {
1594 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1596 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1597 == AS_FILTER_DENY
) {
1603 if (frrtrace_enabled(frr_bgp
, output_filter
)) {
1604 char pfxprint
[PREFIX2STR_BUFFER
];
1606 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1607 frrtrace(5, frr_bgp
, output_filter
, peer
, pfxprint
, afi
, safi
,
1608 ret
== FILTER_PERMIT
? "permit" : "deny");
1613 #undef FILTER_EXIST_WARN
1616 /* If community attribute includes no_export then return 1. */
1617 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1619 if (bgp_attr_get_community(attr
)) {
1620 /* NO_ADVERTISE check. */
1621 if (community_include(bgp_attr_get_community(attr
),
1622 COMMUNITY_NO_ADVERTISE
))
1625 /* NO_EXPORT check. */
1626 if (peer
->sort
== BGP_PEER_EBGP
&&
1627 community_include(bgp_attr_get_community(attr
),
1628 COMMUNITY_NO_EXPORT
))
1631 /* NO_EXPORT_SUBCONFED check. */
1632 if (peer
->sort
== BGP_PEER_EBGP
1633 || peer
->sort
== BGP_PEER_CONFED
)
1634 if (community_include(bgp_attr_get_community(attr
),
1635 COMMUNITY_NO_EXPORT_SUBCONFED
))
1641 /* Route reflection loop check. */
1642 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1644 struct in_addr cluster_id
;
1645 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1648 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1649 cluster_id
= peer
->bgp
->cluster_id
;
1651 cluster_id
= peer
->bgp
->router_id
;
1653 if (cluster_loop_check(cluster
, cluster_id
))
1659 static bool bgp_otc_filter(struct peer
*peer
, struct attr
*attr
)
1661 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1662 if (peer
->local_role
== ROLE_PROVIDER
||
1663 peer
->local_role
== ROLE_RS_SERVER
)
1665 if (peer
->local_role
== ROLE_PEER
&& attr
->otc
!= peer
->as
)
1669 if (peer
->local_role
== ROLE_CUSTOMER
||
1670 peer
->local_role
== ROLE_PEER
||
1671 peer
->local_role
== ROLE_RS_CLIENT
) {
1672 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1673 attr
->otc
= peer
->as
;
1678 static bool bgp_otc_egress(struct peer
*peer
, struct attr
*attr
)
1680 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1681 if (peer
->local_role
== ROLE_CUSTOMER
||
1682 peer
->local_role
== ROLE_RS_CLIENT
||
1683 peer
->local_role
== ROLE_PEER
)
1687 if (peer
->local_role
== ROLE_PROVIDER
||
1688 peer
->local_role
== ROLE_PEER
||
1689 peer
->local_role
== ROLE_RS_SERVER
) {
1690 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1691 attr
->otc
= peer
->bgp
->as
;
1696 static bool bgp_check_role_applicability(afi_t afi
, safi_t safi
)
1698 return ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_UNICAST
);
1701 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1702 struct attr
*attr
, afi_t afi
, safi_t safi
,
1703 const char *rmap_name
, mpls_label_t
*label
,
1704 uint32_t num_labels
, struct bgp_dest
*dest
)
1706 struct bgp_filter
*filter
;
1707 struct bgp_path_info rmap_path
= { 0 };
1708 struct bgp_path_info_extra extra
= { 0 };
1709 route_map_result_t ret
;
1710 struct route_map
*rmap
= NULL
;
1712 filter
= &peer
->filter
[afi
][safi
];
1714 /* Apply default weight value. */
1715 if (peer
->weight
[afi
][safi
])
1716 attr
->weight
= peer
->weight
[afi
][safi
];
1719 rmap
= route_map_lookup_by_name(rmap_name
);
1724 if (ROUTE_MAP_IN_NAME(filter
)) {
1725 rmap
= ROUTE_MAP_IN(filter
);
1732 /* Route map apply. */
1734 memset(&rmap_path
, 0, sizeof(rmap_path
));
1735 /* Duplicate current value to new structure for modification. */
1736 rmap_path
.peer
= peer
;
1737 rmap_path
.attr
= attr
;
1738 rmap_path
.extra
= &extra
;
1739 rmap_path
.net
= dest
;
1741 extra
.num_labels
= num_labels
;
1742 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1743 memcpy(extra
.label
, label
,
1744 num_labels
* sizeof(mpls_label_t
));
1746 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1748 /* Apply BGP route map to the attribute. */
1749 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1751 peer
->rmap_type
= 0;
1753 if (ret
== RMAP_DENYMATCH
)
1759 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1760 struct attr
*attr
, afi_t afi
, safi_t safi
,
1761 const char *rmap_name
)
1763 struct bgp_path_info rmap_path
;
1764 route_map_result_t ret
;
1765 struct route_map
*rmap
= NULL
;
1769 * So if we get to this point and have no rmap_name
1770 * we want to just show the output as it currently
1776 /* Apply default weight value. */
1777 if (peer
->weight
[afi
][safi
])
1778 attr
->weight
= peer
->weight
[afi
][safi
];
1780 rmap
= route_map_lookup_by_name(rmap_name
);
1783 * If we have a route map name and we do not find
1784 * the routemap that means we have an implicit
1790 memset(&rmap_path
, 0, sizeof(rmap_path
));
1791 /* Route map apply. */
1792 /* Duplicate current value to new structure for modification. */
1793 rmap_path
.peer
= peer
;
1794 rmap_path
.attr
= attr
;
1796 rmap_type
= peer
->rmap_type
;
1797 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1799 /* Apply BGP route map to the attribute. */
1800 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1802 peer
->rmap_type
= rmap_type
;
1804 if (ret
== RMAP_DENYMATCH
)
1806 * caller has multiple error paths with bgp_attr_flush()
1813 /* If this is an EBGP peer with remove-private-AS */
1814 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1815 struct peer
*peer
, struct attr
*attr
)
1817 if (peer
->sort
== BGP_PEER_EBGP
1818 && (peer_af_flag_check(peer
, afi
, safi
,
1819 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1820 || peer_af_flag_check(peer
, afi
, safi
,
1821 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1822 || peer_af_flag_check(peer
, afi
, safi
,
1823 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1824 || peer_af_flag_check(peer
, afi
, safi
,
1825 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1826 // Take action on the entire aspath
1827 if (peer_af_flag_check(peer
, afi
, safi
,
1828 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1829 || peer_af_flag_check(peer
, afi
, safi
,
1830 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1831 if (peer_af_flag_check(
1833 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1834 attr
->aspath
= aspath_replace_private_asns(
1835 attr
->aspath
, bgp
->as
, peer
->as
);
1838 * Even if the aspath consists of just private ASNs we
1839 * need to walk the AS-Path to maintain all instances
1840 * of the peer's ASN to break possible loops.
1843 attr
->aspath
= aspath_remove_private_asns(
1844 attr
->aspath
, peer
->as
);
1847 // 'all' was not specified so the entire aspath must be private
1849 // for us to do anything
1850 else if (aspath_private_as_check(attr
->aspath
)) {
1851 if (peer_af_flag_check(
1853 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1854 attr
->aspath
= aspath_replace_private_asns(
1855 attr
->aspath
, bgp
->as
, peer
->as
);
1858 * Walk the aspath to retain any instances of
1861 attr
->aspath
= aspath_remove_private_asns(
1862 attr
->aspath
, peer
->as
);
1867 /* If this is an EBGP peer with as-override */
1868 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1869 struct peer
*peer
, struct attr
*attr
)
1871 struct aspath
*aspath
;
1873 if (peer
->sort
== BGP_PEER_EBGP
&&
1874 peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1875 if (attr
->aspath
->refcnt
)
1876 aspath
= aspath_dup(attr
->aspath
);
1878 aspath
= attr
->aspath
;
1880 attr
->aspath
= aspath_intern(
1881 aspath_replace_specific_asn(aspath
, peer
->as
, bgp
->as
));
1883 aspath_free(aspath
);
1887 void bgp_attr_add_llgr_community(struct attr
*attr
)
1889 struct community
*old
;
1890 struct community
*new;
1891 struct community
*merge
;
1892 struct community
*llgr
;
1894 old
= bgp_attr_get_community(attr
);
1895 llgr
= community_str2com("llgr-stale");
1900 merge
= community_merge(community_dup(old
), llgr
);
1902 if (old
->refcnt
== 0)
1903 community_free(&old
);
1905 new = community_uniq_sort(merge
);
1906 community_free(&merge
);
1908 new = community_dup(llgr
);
1911 community_free(&llgr
);
1913 bgp_attr_set_community(attr
, new);
1916 void bgp_attr_add_gshut_community(struct attr
*attr
)
1918 struct community
*old
;
1919 struct community
*new;
1920 struct community
*merge
;
1921 struct community
*gshut
;
1923 old
= bgp_attr_get_community(attr
);
1924 gshut
= community_str2com("graceful-shutdown");
1929 merge
= community_merge(community_dup(old
), gshut
);
1931 if (old
->refcnt
== 0)
1932 community_free(&old
);
1934 new = community_uniq_sort(merge
);
1935 community_free(&merge
);
1937 new = community_dup(gshut
);
1940 community_free(&gshut
);
1941 bgp_attr_set_community(attr
, new);
1943 /* When we add the graceful-shutdown community we must also
1944 * lower the local-preference */
1945 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1946 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1950 /* Notify BGP Conditional advertisement scanner process. */
1951 void bgp_notify_conditional_adv_scanner(struct update_subgroup
*subgrp
)
1953 struct peer
*peer
= SUBGRP_PEER(subgrp
);
1954 afi_t afi
= SUBGRP_AFI(subgrp
);
1955 safi_t safi
= SUBGRP_SAFI(subgrp
);
1956 struct bgp_filter
*filter
= &peer
->filter
[afi
][safi
];
1958 if (!ADVERTISE_MAP_NAME(filter
))
1961 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
))
1964 peer
->advmap_table_change
= true;
1968 void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1970 if (family
== AF_INET
) {
1971 attr
->nexthop
.s_addr
= INADDR_ANY
;
1972 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1974 if (family
== AF_INET6
)
1975 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1976 if (family
== AF_EVPN
)
1977 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1980 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
1981 struct update_subgroup
*subgrp
,
1982 const struct prefix
*p
, struct attr
*attr
,
1983 struct attr
*post_attr
)
1985 struct bgp_filter
*filter
;
1988 struct peer
*onlypeer
;
1990 struct attr
*piattr
;
1991 route_map_result_t ret
;
1996 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1997 bool nh_reset
= false;
2000 if (DISABLE_BGP_ANNOUNCE
)
2003 afi
= SUBGRP_AFI(subgrp
);
2004 safi
= SUBGRP_SAFI(subgrp
);
2005 peer
= SUBGRP_PEER(subgrp
);
2007 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
2008 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
2011 filter
= &peer
->filter
[afi
][safi
];
2012 bgp
= SUBGRP_INST(subgrp
);
2013 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
2016 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX_OUT
) &&
2017 peer
->pmax_out
[afi
][safi
] != 0 &&
2018 subgrp
->pscount
>= peer
->pmax_out
[afi
][safi
]) {
2019 if (BGP_DEBUG(update
, UPDATE_OUT
) ||
2020 BGP_DEBUG(update
, UPDATE_PREFIX
)) {
2021 zlog_debug("%s reached maximum prefix to be send (%u)",
2022 peer
->host
, peer
->pmax_out
[afi
][safi
]);
2027 #ifdef ENABLE_BGP_VNC
2028 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
2029 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
2030 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
2033 * direct and direct_ext type routes originate internally even
2034 * though they can have peer pointers that reference other
2037 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
2043 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
2044 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
2045 && (pi
->type
== ZEBRA_ROUTE_BGP
)
2046 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2048 /* Applies to routes leaked vpn->vrf and vrf->vpn */
2053 /* With addpath we may be asked to TX all kinds of paths so make sure
2055 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
2056 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
2057 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
2061 /* If this is not the bestpath then check to see if there is an enabled
2063 * feature that requires us to advertise it */
2064 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2065 if (!bgp_addpath_capable(pi
, peer
, afi
, safi
))
2068 /* Aggregate-address suppress check. */
2069 if (bgp_path_suppressed(pi
) && !UNSUPPRESS_MAP_NAME(filter
))
2073 * If we are doing VRF 2 VRF leaking via the import
2074 * statement, we want to prevent the route going
2075 * off box as that the RT and RD created are localy
2076 * significant and globaly useless.
2078 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
2079 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
2082 /* If it's labeled safi, make sure the route has a valid label. */
2083 if (safi
== SAFI_LABELED_UNICAST
) {
2084 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
2085 if (!bgp_is_valid_label(&label
)) {
2086 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2087 zlog_debug("u%" PRIu64
":s%" PRIu64
2088 " %pFX is filtered - no label (%p)",
2089 subgrp
->update_group
->id
, subgrp
->id
,
2095 /* Do not send back route to sender. */
2096 if (onlypeer
&& from
== onlypeer
) {
2100 /* Do not send the default route in the BGP table if the neighbor is
2101 * configured for default-originate */
2102 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2103 PEER_FLAG_DEFAULT_ORIGINATE
)) {
2104 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
2106 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
2110 /* Transparency check. */
2111 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
2112 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
2117 /* If community is not disabled check the no-export and local. */
2118 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
2119 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2120 zlog_debug("%s: community filter check fail for %pFX",
2125 /* If the attribute has originator-id and it is same as remote
2127 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2128 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
2129 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2131 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2136 /* ORF prefix-list filter check */
2137 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
2138 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
2139 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
2140 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
2141 if (peer
->orf_plist
[afi
][safi
]) {
2142 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
2144 if (bgp_debug_update(NULL
, p
,
2145 subgrp
->update_group
, 0))
2147 "%pBP [Update:SEND] %pFX is filtered via ORF",
2153 /* Output filter check. */
2154 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
2155 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2156 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer
,
2161 /* AS path loop check. */
2162 if (peer
->as_path_loop_detection
&&
2163 aspath_loop_check(piattr
->aspath
, peer
->as
)) {
2164 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2166 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2171 /* If we're a CONFED we need to loop check the CONFED ID too */
2172 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
2173 if (aspath_loop_check_confed(piattr
->aspath
, bgp
->confed_id
)) {
2174 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2176 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2177 peer
, bgp
->confed_id
);
2182 /* Route-Reflect check. */
2183 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2188 /* IBGP reflection check. */
2189 if (reflect
&& !samepeer_safe
) {
2190 /* A route from a Client peer. */
2191 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
2192 PEER_FLAG_REFLECTOR_CLIENT
)) {
2193 /* Reflect to all the Non-Client peers and also to the
2194 Client peers other than the originator. Originator
2196 is already done. So there is noting to do. */
2197 /* no bgp client-to-client reflection check. */
2198 if (CHECK_FLAG(bgp
->flags
,
2199 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
2200 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2201 PEER_FLAG_REFLECTOR_CLIENT
))
2204 /* A route from a Non-client peer. Reflect to all other
2206 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2207 PEER_FLAG_REFLECTOR_CLIENT
))
2212 /* For modify attribute, copy it to temporary structure.
2213 * post_attr comes from BGP conditional advertisements, where
2214 * attributes are already processed by advertise-map route-map,
2215 * and this needs to be saved instead of overwriting from the
2223 /* If local-preference is not set. */
2224 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
2225 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
2226 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2227 attr
->local_pref
= bgp
->default_local_pref
;
2230 /* If originator-id is not set and the route is to be reflected,
2231 set the originator id */
2233 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
2234 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
2235 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
2238 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2240 if (peer
->sort
== BGP_PEER_EBGP
2241 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
2242 if (from
!= bgp
->peer_self
&& !transparent
2243 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2244 PEER_FLAG_MED_UNCHANGED
))
2246 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
2249 /* Since the nexthop attribute can vary per peer, it is not explicitly
2251 * in announce check, only certain flags and length (or number of
2253 * -- for IPv6/MP_REACH) are set here in order to guide the update
2255 * code in setting the nexthop(s) on a per peer basis in
2257 * Typically, the source nexthop in the attribute is preserved but in
2259 * scenarios where we know it will always be overwritten, we reset the
2260 * nexthop to "0" in an attempt to achieve better Update packing. An
2261 * example of this is when a prefix from each of 2 IBGP peers needs to
2263 * announced to an EBGP peer (and they have the same attributes barring
2267 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
2269 #define NEXTHOP_IS_V6 \
2270 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2271 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2272 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2273 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2275 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2277 * the peer (group) is configured to receive link-local nexthop
2279 * and it is available in the prefix OR we're not reflecting the route,
2280 * link-local nexthop address is valid and
2281 * the peer (group) to whom we're going to announce is on a shared
2283 * and this is either a self-originated route or the peer is EBGP.
2284 * By checking if nexthop LL address is valid we are sure that
2285 * we do not announce LL address as `::`.
2287 if (NEXTHOP_IS_V6
) {
2288 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2289 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2290 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
2291 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
2292 || (!reflect
&& !transparent
2293 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
2294 && peer
->shared_network
2295 && (from
== bgp
->peer_self
2296 || peer
->sort
== BGP_PEER_EBGP
))) {
2297 if (safi
== SAFI_MPLS_VPN
)
2298 attr
->mp_nexthop_len
=
2299 BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
;
2301 attr
->mp_nexthop_len
=
2302 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2305 /* Clear off link-local nexthop in source, whenever it is not
2307 * ensure more prefixes share the same attribute for
2310 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2311 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
2312 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
2315 if (bgp_check_role_applicability(afi
, safi
) &&
2316 bgp_otc_egress(peer
, attr
))
2319 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
2320 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
2322 if (filter
->advmap
.update_type
== UPDATE_TYPE_WITHDRAW
&&
2323 filter
->advmap
.aname
&&
2324 route_map_lookup_by_name(filter
->advmap
.aname
)) {
2325 struct bgp_path_info rmap_path
= {0};
2326 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2327 struct attr dummy_attr
= *attr
;
2329 /* Fill temp path_info */
2330 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2331 pi
, peer
, &dummy_attr
);
2333 struct route_map
*amap
=
2334 route_map_lookup_by_name(filter
->advmap
.aname
);
2336 ret
= route_map_apply(amap
, p
, &rmap_path
);
2338 bgp_attr_flush(&dummy_attr
);
2341 * The conditional advertisement mode is Withdraw and this
2342 * prefix is a conditional prefix. Don't advertise it
2344 if (ret
== RMAP_PERMITMATCH
)
2348 /* Route map & unsuppress-map apply. */
2350 (ROUTE_MAP_OUT_NAME(filter
) || bgp_path_suppressed(pi
))) {
2351 struct bgp_path_info rmap_path
= {0};
2352 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2353 struct attr dummy_attr
= {0};
2355 /* Fill temp path_info */
2356 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2359 /* don't confuse inbound and outbound setting */
2360 RESET_FLAG(attr
->rmap_change_flags
);
2363 * The route reflector is not allowed to modify the attributes
2364 * of the reflected IBGP routes unless explicitly allowed.
2366 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2367 && !CHECK_FLAG(bgp
->flags
,
2368 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
2370 rmap_path
.attr
= &dummy_attr
;
2373 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
2375 if (bgp_path_suppressed(pi
))
2376 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
2379 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
2382 bgp_attr_flush(&dummy_attr
);
2383 peer
->rmap_type
= 0;
2385 if (ret
== RMAP_DENYMATCH
) {
2386 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2388 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2390 bgp_path_suppressed(pi
)
2391 ? UNSUPPRESS_MAP_NAME(filter
)
2392 : ROUTE_MAP_OUT_NAME(filter
));
2393 bgp_attr_flush(rmap_path
.attr
);
2398 /* RFC 8212 to prevent route leaks.
2399 * This specification intends to improve this situation by requiring the
2400 * explicit configuration of both BGP Import and Export Policies for any
2401 * External BGP (EBGP) session such as customers, peers, or
2402 * confederation boundaries for all enabled address families. Through
2403 * codification of the aforementioned requirement, operators will
2404 * benefit from consistent behavior across different BGP
2407 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2408 if (!bgp_outbound_policy_exists(peer
, filter
)) {
2409 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
2410 NULL
) > FIFTEENMINUTE2USEC
||
2411 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
2413 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2414 monotime(&bgp
->ebgprequirespolicywarning
);
2419 /* draft-ietf-idr-deprecate-as-set-confed-set
2420 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2421 * Eventually, This document (if approved) updates RFC 4271
2422 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2423 * and obsoletes RFC 6472.
2425 if (peer
->bgp
->reject_as_sets
)
2426 if (aspath_check_as_sets(attr
->aspath
))
2429 /* If neighbor soo is configured, then check if the route has
2430 * SoO extended community and validate against the configured
2431 * one. If they match, do not announce, to prevent routing
2434 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) &&
2435 peer
->soo
[afi
][safi
]) {
2436 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
2437 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
2439 if ((ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS
,
2440 ECOMMUNITY_SITE_ORIGIN
) ||
2441 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS4
,
2442 ECOMMUNITY_SITE_ORIGIN
) ||
2443 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_IP
,
2444 ECOMMUNITY_SITE_ORIGIN
)) &&
2445 ecommunity_include(ecomm
, ecomm_soo
)) {
2446 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2448 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2449 peer
, p
, ecommunity_str(ecomm_soo
));
2454 /* Codification of AS 0 Processing */
2455 if (aspath_check_as_zero(attr
->aspath
))
2458 if (bgp_in_graceful_shutdown(bgp
)) {
2459 if (peer
->sort
== BGP_PEER_IBGP
2460 || peer
->sort
== BGP_PEER_CONFED
) {
2461 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2462 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2464 bgp_attr_add_gshut_community(attr
);
2468 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2469 * Capability" to a neighbor MUST perform the following upon receiving
2470 * a route from that neighbor with the "LLGR_STALE" community, or upon
2471 * attaching the "LLGR_STALE" community itself per Section 4.2:
2473 * The route SHOULD NOT be advertised to any neighbor from which the
2474 * Long-lived Graceful Restart Capability has not been received.
2476 if (bgp_attr_get_community(attr
) &&
2477 community_include(bgp_attr_get_community(attr
),
2478 COMMUNITY_LLGR_STALE
) &&
2479 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_RCV
) &&
2480 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_ADV
))
2483 /* After route-map has been applied, we check to see if the nexthop to
2484 * be carried in the attribute (that is used for the announcement) can
2485 * be cleared off or not. We do this in all cases where we would be
2486 * setting the nexthop to "ourselves". For IPv6, we only need to
2488 * the global nexthop here; the link-local nexthop would have been
2490 * already, and if not, it is required by the update formation code.
2491 * Also see earlier comments in this function.
2494 * If route-map has performed some operation on the nexthop or the peer
2495 * configuration says to pass it unchanged, we cannot reset the nexthop
2496 * here, so only attempt to do it if these aren't true. Note that the
2497 * route-map handler itself might have cleared the nexthop, if for
2499 * it is configured as 'peer-address'.
2501 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2502 piattr
->rmap_change_flags
)
2504 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2505 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2506 /* We can reset the nexthop, if setting (or forcing) it to
2508 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2509 PEER_FLAG_NEXTHOP_SELF
)
2510 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2511 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2513 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2514 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2515 subgroup_announce_reset_nhop(
2516 (peer_cap_enhe(peer
, afi
, safi
)
2522 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2523 /* Can also reset the nexthop if announcing to EBGP, but
2525 * no peer in the subgroup is on a shared subnet.
2526 * Note: 3rd party nexthop currently implemented for
2529 if ((p
->family
== AF_INET
) &&
2530 (!bgp_subgrp_multiaccess_check_v4(
2533 subgroup_announce_reset_nhop(
2534 (peer_cap_enhe(peer
, afi
, safi
)
2541 if ((p
->family
== AF_INET6
) &&
2542 (!bgp_subgrp_multiaccess_check_v6(
2543 piattr
->mp_nexthop_global
,
2545 subgroup_announce_reset_nhop(
2546 (peer_cap_enhe(peer
, afi
, safi
)
2555 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2557 * This flag is used for leaked vpn-vrf routes
2559 int family
= p
->family
;
2561 if (peer_cap_enhe(peer
, afi
, safi
))
2564 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2566 "%s: %pFX BGP_PATH_ANNC_NH_SELF, family=%s",
2567 __func__
, p
, family2str(family
));
2568 subgroup_announce_reset_nhop(family
, attr
);
2573 /* If IPv6/MP and nexthop does not have any override and happens
2575 * be a link-local address, reset it so that we don't pass along
2577 * source's link-local IPv6 address to recipients who may not be
2579 * the same interface.
2581 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2582 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2583 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2588 /* If this is an iBGP, send Origin Validation State (OVS)
2589 * extended community (rfc8097).
2591 if (peer
->sort
== BGP_PEER_IBGP
) {
2592 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
2594 rpki_state
= hook_call(bgp_rpki_prefix_status
, peer
, attr
, p
);
2596 if (rpki_state
!= RPKI_NOT_BEING_USED
)
2597 bgp_attr_set_ecommunity(
2598 attr
, ecommunity_add_origin_validation_state(
2600 bgp_attr_get_ecommunity(attr
)));
2604 * When the next hop is set to ourselves, if all multipaths have
2605 * link-bandwidth announce the cumulative bandwidth as that makes
2606 * the most sense. However, don't modify if the link-bandwidth has
2607 * been explicitly set by user policy.
2610 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2611 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2612 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2613 bgp_attr_set_ecommunity(
2615 ecommunity_replace_linkbw(
2616 bgp
->as
, bgp_attr_get_ecommunity(attr
), cum_bw
,
2619 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
)));
2624 static void bgp_route_select_timer_expire(struct event
*thread
)
2626 struct afi_safi_info
*info
;
2631 info
= EVENT_ARG(thread
);
2636 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2637 XFREE(MTYPE_TMP
, info
);
2639 /* Best path selection */
2640 bgp_best_path_select_defer(bgp
, afi
, safi
);
2643 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2644 struct bgp_maxpaths_cfg
*mpath_cfg
,
2645 struct bgp_path_info_pair
*result
, afi_t afi
,
2648 struct bgp_path_info
*new_select
;
2649 struct bgp_path_info
*old_select
;
2650 struct bgp_path_info
*pi
;
2651 struct bgp_path_info
*pi1
;
2652 struct bgp_path_info
*pi2
;
2653 struct bgp_path_info
*nextpi
= NULL
;
2654 int paths_eq
, do_mpath
, debug
;
2655 struct list mp_list
;
2656 char pfx_buf
[PREFIX2STR_BUFFER
];
2657 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2659 bgp_mp_list_init(&mp_list
);
2661 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2663 debug
= bgp_debug_bestpath(dest
);
2666 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2668 dest
->reason
= bgp_path_selection_none
;
2669 /* bgp deterministic-med */
2671 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2673 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2674 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2676 bgp_path_info_unset_flag(dest
, pi1
,
2677 BGP_PATH_DMED_SELECTED
);
2679 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2681 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2683 if (BGP_PATH_HOLDDOWN(pi1
))
2685 if (pi1
->peer
!= bgp
->peer_self
&&
2686 !CHECK_FLAG(pi1
->peer
->sflags
,
2687 PEER_STATUS_NSF_WAIT
)) {
2688 if (!peer_established(pi1
->peer
))
2694 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2695 if (CHECK_FLAG(pi2
->flags
,
2696 BGP_PATH_DMED_CHECK
))
2698 if (BGP_PATH_HOLDDOWN(pi2
))
2700 if (pi2
->peer
!= bgp
->peer_self
2703 PEER_STATUS_NSF_WAIT
))
2704 if (pi2
->peer
->status
2708 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2710 && !aspath_cmp_left_confed(
2715 if (bgp_path_info_cmp(
2716 bgp
, pi2
, new_select
,
2717 &paths_eq
, mpath_cfg
, debug
,
2720 bgp_path_info_unset_flag(
2722 BGP_PATH_DMED_SELECTED
);
2726 bgp_path_info_set_flag(
2727 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2730 bgp_path_info_set_flag(dest
, new_select
,
2731 BGP_PATH_DMED_CHECK
);
2732 bgp_path_info_set_flag(dest
, new_select
,
2733 BGP_PATH_DMED_SELECTED
);
2736 bgp_path_info_path_with_addpath_rx_str(
2737 new_select
, path_buf
, sizeof(path_buf
));
2739 "%pBD(%s): %s is the bestpath from AS %u",
2740 dest
, bgp
->name_pretty
, path_buf
,
2741 aspath_get_first_as(
2742 new_select
->attr
->aspath
));
2747 /* Check old selected route and new selected route. */
2750 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2751 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2752 enum bgp_path_selection_reason reason
;
2754 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2757 if (BGP_PATH_HOLDDOWN(pi
)) {
2758 /* reap REMOVED routes, if needs be
2759 * selected route must stay for a while longer though
2761 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2762 && (pi
!= old_select
))
2763 bgp_path_info_reap(dest
, pi
);
2767 "%s: %pBD(%s) pi from %s in holddown",
2768 __func__
, dest
, bgp
->name_pretty
,
2774 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2775 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2776 if (!peer_established(pi
->peer
)) {
2780 "%s: %pBD(%s) non self peer %s not estab state",
2788 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2789 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2790 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2792 zlog_debug("%s: %pBD(%s) pi %s dmed", __func__
,
2793 dest
, bgp
->name_pretty
,
2798 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2800 reason
= dest
->reason
;
2801 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2802 debug
, pfx_buf
, afi
, safi
,
2804 if (new_select
== NULL
&&
2805 reason
!= bgp_path_selection_none
)
2806 dest
->reason
= reason
;
2811 /* Now that we know which path is the bestpath see if any of the other
2813 * qualify as multipaths
2817 bgp_path_info_path_with_addpath_rx_str(
2818 new_select
, path_buf
, sizeof(path_buf
));
2820 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2822 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2823 dest
, bgp
->name_pretty
, path_buf
,
2824 old_select
? old_select
->peer
->host
: "NONE");
2827 if (do_mpath
&& new_select
) {
2828 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2829 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2832 bgp_path_info_path_with_addpath_rx_str(
2833 pi
, path_buf
, sizeof(path_buf
));
2835 if (pi
== new_select
) {
2838 "%pBD(%s): %s is the bestpath, add to the multipath list",
2839 dest
, bgp
->name_pretty
,
2841 bgp_mp_list_add(&mp_list
, pi
);
2845 if (BGP_PATH_HOLDDOWN(pi
))
2848 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2849 && !CHECK_FLAG(pi
->peer
->sflags
,
2850 PEER_STATUS_NSF_WAIT
))
2851 if (!peer_established(pi
->peer
))
2854 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2857 "%pBD(%s): %s has the same nexthop as the bestpath, skip it",
2858 dest
, bgp
->name_pretty
,
2863 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2864 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2870 "%pBD(%s): %s is equivalent to the bestpath, add to the multipath list",
2871 dest
, bgp
->name_pretty
,
2873 bgp_mp_list_add(&mp_list
, pi
);
2878 bgp_path_info_mpath_update(bgp
, dest
, new_select
, old_select
, &mp_list
,
2880 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2881 bgp_mp_list_clear(&mp_list
);
2883 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2885 result
->old
= old_select
;
2886 result
->new = new_select
;
2892 * A new route/change in bestpath of an existing route. Evaluate the path
2893 * for advertisement to the subgroup.
2895 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2896 struct bgp_path_info
*selected
,
2897 struct bgp_dest
*dest
,
2898 uint32_t addpath_tx_id
)
2900 const struct prefix
*p
;
2901 struct peer
*onlypeer
;
2908 p
= bgp_dest_get_prefix(dest
);
2909 afi
= SUBGRP_AFI(subgrp
);
2910 safi
= SUBGRP_SAFI(subgrp
);
2911 bgp
= SUBGRP_INST(subgrp
);
2912 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2915 if (BGP_DEBUG(update
, UPDATE_OUT
))
2916 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2918 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2919 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2920 PEER_STATUS_ORF_WAIT_REFRESH
))
2923 memset(&attr
, 0, sizeof(attr
));
2924 /* It's initialized in bgp_announce_check() */
2926 /* Announcement to the subgroup. If the route is filtered withdraw it.
2927 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2928 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2931 advertise
= bgp_check_advertise(bgp
, dest
);
2934 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2936 /* Route is selected, if the route is already installed
2937 * in FIB, then it is advertised
2940 if (!bgp_check_withdrawal(bgp
, dest
)) {
2941 struct attr
*adv_attr
=
2942 bgp_attr_intern(&attr
);
2944 bgp_adj_out_set_subgroup(dest
, subgrp
,
2948 bgp_adj_out_unset_subgroup(
2949 dest
, subgrp
, 1, addpath_tx_id
);
2952 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2956 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2958 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2963 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2964 * This is called at the end of route processing.
2966 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2968 struct bgp_path_info
*pi
;
2970 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2971 if (BGP_PATH_HOLDDOWN(pi
))
2973 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2974 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2979 * Has the route changed from the RIB's perspective? This is invoked only
2980 * if the route selection returns the same best route as earlier - to
2981 * determine if we need to update zebra or not.
2983 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2985 struct bgp_path_info
*mpinfo
;
2987 /* If this is multipath, check all selected paths for any nexthop
2988 * change or attribute change. Some attribute changes (e.g., community)
2989 * aren't of relevance to the RIB, but we'll update zebra to ensure
2990 * we handle the case of BGP nexthop change. This is the behavior
2991 * when the best path has an attribute change anyway.
2993 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2994 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2995 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2999 * If this is multipath, check all selected paths for any nexthop change
3001 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
3002 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
3003 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
3004 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
3008 /* Nothing has changed from the RIB's perspective. */
3012 struct bgp_process_queue
{
3014 STAILQ_HEAD(, bgp_dest
) pqueue
;
3015 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
3017 unsigned int queued
;
3020 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
3021 safi_t safi
, struct bgp_dest
*dest
,
3022 struct bgp_path_info
*new_select
,
3023 struct bgp_path_info
*old_select
)
3025 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3027 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
3030 if (advertise_type5_routes(bgp
, afi
) && new_select
3031 && is_route_injectable_into_evpn(new_select
)) {
3033 /* apply the route-map */
3034 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
3035 route_map_result_t ret
;
3036 struct bgp_path_info rmap_path
;
3037 struct bgp_path_info_extra rmap_path_extra
;
3038 struct attr dummy_attr
;
3040 dummy_attr
= *new_select
->attr
;
3042 /* Fill temp path_info */
3043 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
3044 new_select
, new_select
->peer
,
3047 RESET_FLAG(dummy_attr
.rmap_change_flags
);
3049 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
3052 if (ret
== RMAP_DENYMATCH
) {
3053 bgp_attr_flush(&dummy_attr
);
3054 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
3057 bgp_evpn_advertise_type5_route(
3058 bgp
, p
, &dummy_attr
, afi
, safi
);
3060 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
3063 } else if (advertise_type5_routes(bgp
, afi
) && old_select
3064 && is_route_injectable_into_evpn(old_select
))
3065 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
3069 * Utility to determine whether a particular path_info should use
3070 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3071 * in a path where we basically _know_ this is a BGP-LU route.
3073 static bool bgp_lu_need_null_label(struct bgp
*bgp
,
3074 const struct bgp_path_info
*new_select
,
3075 afi_t afi
, mpls_label_t
*label
)
3077 /* Certain types get imp null; so do paths where the nexthop is
3080 if (new_select
->sub_type
== BGP_ROUTE_STATIC
3081 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3082 || new_select
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
3083 goto need_null_label
;
3084 else if (new_select
->extra
&&
3085 bgp_is_valid_label(&new_select
->extra
->label
[0]))
3090 if (!!CHECK_FLAG(bgp
->flags
, BGP_FLAG_LU_EXPLICIT_NULL
))
3091 /* Disable PHP : explicit-null */
3092 *label
= afi
== AFI_IP
? MPLS_LABEL_IPV4_EXPLICIT_NULL
3093 : MPLS_LABEL_IPV6_EXPLICIT_NULL
;
3095 /* Enforced PHP popping: implicit-null */
3096 *label
= MPLS_LABEL_IMPLICIT_NULL
;
3102 * old_select = The old best path
3103 * new_select = the new best path
3105 * if (!old_select && new_select)
3106 * We are sending new information on.
3108 * if (old_select && new_select) {
3109 * if (new_select != old_select)
3110 * We have a new best path send a change
3112 * We've received a update with new attributes that needs
3116 * if (old_select && !new_select)
3117 * We have no eligible route that we can announce or the rn
3120 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
3121 afi_t afi
, safi_t safi
)
3123 struct bgp_path_info
*new_select
;
3124 struct bgp_path_info
*old_select
;
3125 struct bgp_path_info_pair old_and_new
;
3127 mpls_label_t mpls_label_null
;
3129 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
3131 debug
= bgp_debug_bestpath(dest
);
3134 "%s: bgp delete in progress, ignoring event, p=%pBD(%s)",
3135 __func__
, dest
, bgp
->name_pretty
);
3138 /* Is it end of initial update? (after startup) */
3140 frr_timestamp(3, bgp
->update_delay_zebra_resume_time
,
3141 sizeof(bgp
->update_delay_zebra_resume_time
));
3143 bgp
->main_zebra_update_hold
= 0;
3144 FOREACH_AFI_SAFI (afi
, safi
) {
3145 if (bgp_fibupd_safi(safi
))
3146 bgp_zebra_announce_table(bgp
, afi
, safi
);
3148 bgp
->main_peers_update_hold
= 0;
3150 bgp_start_routeadv(bgp
);
3154 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3156 debug
= bgp_debug_bestpath(dest
);
3158 zlog_debug("%s: p=%pBD(%s) afi=%s, safi=%s start", __func__
,
3159 dest
, bgp
->name_pretty
, afi2str(afi
),
3162 /* The best path calculation for the route is deferred if
3163 * BGP_NODE_SELECT_DEFER is set
3165 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3166 if (BGP_DEBUG(update
, UPDATE_OUT
))
3167 zlog_debug("SELECT_DEFER flag set for route %p(%s)",
3168 dest
, bgp
->name_pretty
);
3172 /* Best path selection. */
3173 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
3175 old_select
= old_and_new
.old
;
3176 new_select
= old_and_new
.new;
3178 /* Do we need to allocate or free labels?
3179 * Right now, since we only deal with per-prefix labels, it is not
3180 * necessary to do this upon changes to best path. Exceptions:
3181 * - label index has changed -> recalculate resulting label
3182 * - path_info sub_type changed -> switch to/from null label value
3183 * - no valid label (due to removed static label binding) -> get new one
3185 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
3188 || bgp_label_index_differs(new_select
, old_select
)
3189 || new_select
->sub_type
!= old_select
->sub_type
3190 || !bgp_is_valid_label(&dest
->local_label
)) {
3191 /* control label imposition for local routes,
3192 * aggregate and redistributed routes
3194 mpls_label_null
= MPLS_LABEL_IMPLICIT_NULL
;
3195 if (bgp_lu_need_null_label(bgp
, new_select
, afi
,
3196 &mpls_label_null
)) {
3199 BGP_NODE_REGISTERED_FOR_LABEL
)
3202 BGP_NODE_LABEL_REQUESTED
))
3203 bgp_unregister_for_label(dest
);
3204 dest
->local_label
= mpls_lse_encode(
3205 mpls_label_null
, 0, 0, 1);
3206 bgp_set_valid_label(&dest
->local_label
);
3208 bgp_register_for_label(dest
,
3211 } else if (CHECK_FLAG(dest
->flags
,
3212 BGP_NODE_REGISTERED_FOR_LABEL
)
3213 || CHECK_FLAG(dest
->flags
,
3214 BGP_NODE_LABEL_REQUESTED
)) {
3215 bgp_unregister_for_label(dest
);
3217 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
3218 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
3219 bgp_unregister_for_label(dest
);
3224 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3225 __func__
, dest
, bgp
->name_pretty
, afi2str(afi
),
3226 safi2str(safi
), old_select
, new_select
);
3228 /* If best route remains the same and this is not due to user-initiated
3229 * clear, see exactly what needs to be done.
3231 if (old_select
&& old_select
== new_select
3232 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
3233 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3234 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
3235 if (bgp_zebra_has_route_changed(old_select
)) {
3236 #ifdef ENABLE_BGP_VNC
3237 vnc_import_bgp_add_route(bgp
, p
, old_select
);
3238 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
3240 if (bgp_fibupd_safi(safi
)
3241 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3243 if (new_select
->type
== ZEBRA_ROUTE_BGP
3244 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3245 || new_select
->sub_type
3246 == BGP_ROUTE_IMPORTED
))
3248 bgp_zebra_announce(dest
, p
, old_select
,
3253 /* If there is a change of interest to peers, reannounce the
3255 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3256 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3257 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
3258 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3260 /* unicast routes must also be annouced to
3261 * labeled-unicast update-groups */
3262 if (safi
== SAFI_UNICAST
)
3263 group_announce_route(bgp
, afi
,
3264 SAFI_LABELED_UNICAST
, dest
,
3267 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
3268 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
3271 /* advertise/withdraw type-5 routes */
3272 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3273 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
3274 bgp_process_evpn_route_injection(
3275 bgp
, afi
, safi
, dest
, old_select
, old_select
);
3277 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3278 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3279 bgp_zebra_clear_route_change_flags(dest
);
3280 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3284 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3286 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
3288 /* bestpath has changed; bump version */
3289 if (old_select
|| new_select
) {
3290 bgp_bump_version(dest
);
3292 if (!bgp
->t_rmap_def_originate_eval
) {
3296 update_group_refresh_default_originate_route_map
,
3297 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
3298 &bgp
->t_rmap_def_originate_eval
);
3303 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
3306 zlog_debug("%s: setting SELECTED flag", __func__
);
3307 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
3308 bgp_path_info_unset_flag(dest
, new_select
,
3309 BGP_PATH_ATTR_CHANGED
);
3310 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3311 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3314 #ifdef ENABLE_BGP_VNC
3315 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3316 if (old_select
!= new_select
) {
3318 vnc_import_bgp_exterior_del_route(bgp
, p
,
3320 vnc_import_bgp_del_route(bgp
, p
, old_select
);
3323 vnc_import_bgp_exterior_add_route(bgp
, p
,
3325 vnc_import_bgp_add_route(bgp
, p
, new_select
);
3331 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3333 /* unicast routes must also be annouced to labeled-unicast update-groups
3335 if (safi
== SAFI_UNICAST
)
3336 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
3340 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
3341 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3343 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
3344 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3345 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3346 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
3348 /* if this is an evpn imported type-5 prefix,
3349 * we need to withdraw the route first to clear
3350 * the nh neigh and the RMAC entry.
3353 is_route_parent_evpn(old_select
))
3354 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3356 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
3358 /* Withdraw the route from the kernel. */
3359 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
3360 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
3361 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
3362 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
3364 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3368 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
3371 /* Clear any route change flags. */
3372 bgp_zebra_clear_route_change_flags(dest
);
3374 /* Reap old select bgp_path_info, if it has been removed */
3375 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
3376 bgp_path_info_reap(dest
, old_select
);
3378 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3382 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3383 void bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
3385 struct bgp_dest
*dest
;
3387 struct afi_safi_info
*thread_info
;
3389 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
3390 struct event
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
3392 thread_info
= EVENT_ARG(t
);
3393 XFREE(MTYPE_TMP
, thread_info
);
3394 EVENT_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
3397 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
3398 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
3399 get_afi_safi_str(afi
, safi
, false),
3400 bgp
->gr_info
[afi
][safi
].gr_deferred
);
3403 /* Process the route list */
3404 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
3405 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0 &&
3406 cnt
< BGP_MAX_BEST_ROUTE_SELECT
;
3407 dest
= bgp_route_next(dest
)) {
3408 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
3411 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3412 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3413 bgp_process_main_one(bgp
, dest
, afi
, safi
);
3416 /* If iteration stopped before the entire table was traversed then the
3417 * node needs to be unlocked.
3420 bgp_dest_unlock_node(dest
);
3424 /* Send EOR message when all routes are processed */
3425 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
3426 bgp_send_delayed_eor(bgp
);
3427 /* Send route processing complete message to RIB */
3428 bgp_zebra_update(bgp
, afi
, safi
,
3429 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
3433 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3435 thread_info
->afi
= afi
;
3436 thread_info
->safi
= safi
;
3437 thread_info
->bgp
= bgp
;
3439 /* If there are more routes to be processed, start the
3442 event_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3443 BGP_ROUTE_SELECT_DELAY
,
3444 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3447 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3449 struct bgp_process_queue
*pqnode
= data
;
3450 struct bgp
*bgp
= pqnode
->bgp
;
3451 struct bgp_table
*table
;
3452 struct bgp_dest
*dest
;
3455 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3456 bgp_process_main_one(bgp
, NULL
, 0, 0);
3457 /* should always have dedicated wq call */
3458 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3462 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3463 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3464 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3465 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3466 table
= bgp_dest_table(dest
);
3467 /* note, new DESTs may be added as part of processing */
3468 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3470 bgp_dest_unlock_node(dest
);
3471 bgp_table_unlock(table
);
3477 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3479 struct bgp_process_queue
*pqnode
= data
;
3481 bgp_unlock(pqnode
->bgp
);
3483 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3486 void bgp_process_queue_init(struct bgp
*bgp
)
3488 if (!bgp
->process_queue
) {
3491 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3492 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3495 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3496 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3497 bgp
->process_queue
->spec
.max_retries
= 0;
3498 bgp
->process_queue
->spec
.hold
= 50;
3499 /* Use a higher yield value of 50ms for main queue processing */
3500 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3503 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3505 struct bgp_process_queue
*pqnode
;
3507 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3508 sizeof(struct bgp_process_queue
));
3510 /* unlocked in bgp_processq_del */
3511 pqnode
->bgp
= bgp_lock(bgp
);
3512 STAILQ_INIT(&pqnode
->pqueue
);
3517 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3519 #define ARBITRARY_PROCESS_QLEN 10000
3520 struct work_queue
*wq
= bgp
->process_queue
;
3521 struct bgp_process_queue
*pqnode
;
3522 int pqnode_reuse
= 0;
3524 /* already scheduled for processing? */
3525 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3528 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3531 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3532 if (BGP_DEBUG(update
, UPDATE_OUT
))
3533 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3538 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
)) {
3539 if (BGP_DEBUG(update
, UPDATE_OUT
))
3541 "Soft reconfigure table in progress for route %p",
3549 /* Add route nodes to an existing work queue item until reaching the
3550 limit only if is from the same BGP view and it's not an EOIU marker
3552 if (work_queue_item_count(wq
)) {
3553 struct work_queue_item
*item
= work_queue_last_item(wq
);
3554 pqnode
= item
->data
;
3556 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3557 || pqnode
->bgp
!= bgp
3558 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3559 pqnode
= bgp_processq_alloc(bgp
);
3563 pqnode
= bgp_processq_alloc(bgp
);
3564 /* all unlocked in bgp_process_wq */
3565 bgp_table_lock(bgp_dest_table(dest
));
3567 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3568 bgp_dest_lock_node(dest
);
3570 /* can't be enqueued twice */
3571 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3572 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3576 work_queue_add(wq
, pqnode
);
3581 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3583 struct bgp_process_queue
*pqnode
;
3585 if (bgp
->process_queue
== NULL
)
3588 pqnode
= bgp_processq_alloc(bgp
);
3590 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3591 work_queue_add(bgp
->process_queue
, pqnode
);
3594 static void bgp_maximum_prefix_restart_timer(struct event
*thread
)
3598 peer
= EVENT_ARG(thread
);
3599 peer
->t_pmax_restart
= NULL
;
3601 if (bgp_debug_neighbor_events(peer
))
3603 "%s Maximum-prefix restart timer expired, restore peering",
3606 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3607 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3610 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3614 bool filtered
= false;
3615 struct bgp_dest
*dest
;
3616 struct bgp_adj_in
*ain
;
3617 struct attr attr
= {};
3618 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3620 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3621 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3622 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3626 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3630 if (bgp_input_modifier(
3631 peer
, rn_p
, &attr
, afi
, safi
,
3632 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3640 bgp_attr_flush(&attr
);
3647 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3651 iana_safi_t pkt_safi
;
3652 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3653 PEER_FLAG_MAX_PREFIX_FORCE
))
3654 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3655 + peer
->pcount
[afi
][safi
]
3656 : peer
->pcount
[afi
][safi
];
3658 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3661 if (pcount
> peer
->pmax
[afi
][safi
]) {
3662 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3663 PEER_STATUS_PREFIX_LIMIT
)
3668 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3669 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3670 peer
->pmax
[afi
][safi
]);
3671 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3673 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3674 PEER_FLAG_MAX_PREFIX_WARNING
))
3677 /* Convert AFI, SAFI to values for packet. */
3678 pkt_afi
= afi_int2iana(afi
);
3679 pkt_safi
= safi_int2iana(safi
);
3683 ndata
[0] = (pkt_afi
>> 8);
3685 ndata
[2] = pkt_safi
;
3686 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3687 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3688 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3689 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3691 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3692 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3693 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3697 /* Dynamic peers will just close their connection. */
3698 if (peer_dynamic_neighbor(peer
))
3701 /* restart timer start */
3702 if (peer
->pmax_restart
[afi
][safi
]) {
3703 peer
->v_pmax_restart
=
3704 peer
->pmax_restart
[afi
][safi
] * 60;
3706 if (bgp_debug_neighbor_events(peer
))
3708 "%pBP Maximum-prefix restart timer started for %d secs",
3709 peer
, peer
->v_pmax_restart
);
3711 BGP_TIMER_ON(peer
->t_pmax_restart
,
3712 bgp_maximum_prefix_restart_timer
,
3713 peer
->v_pmax_restart
);
3718 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3719 PEER_STATUS_PREFIX_LIMIT
);
3722 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3723 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3724 PEER_STATUS_PREFIX_THRESHOLD
)
3729 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3730 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3731 peer
->pmax
[afi
][safi
]);
3732 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3733 PEER_STATUS_PREFIX_THRESHOLD
);
3735 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3736 PEER_STATUS_PREFIX_THRESHOLD
);
3740 /* Unconditionally remove the route from the RIB, without taking
3741 * damping into consideration (eg, because the session went down)
3743 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3744 struct peer
*peer
, afi_t afi
, safi_t safi
)
3747 struct bgp
*bgp
= NULL
;
3748 bool delete_route
= false;
3750 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3753 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3754 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3756 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3759 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3760 delete_route
= true;
3761 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3762 delete_route
= true;
3764 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3765 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3766 bgp
= pi
->peer
->bgp
;
3767 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3772 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3773 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3776 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3777 struct peer
*peer
, afi_t afi
, safi_t safi
,
3778 struct prefix_rd
*prd
)
3780 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3782 /* apply dampening, if result is suppressed, we'll be retaining
3783 * the bgp_path_info in the RIB for historical reference.
3785 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3786 && peer
->sort
== BGP_PEER_EBGP
)
3787 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3788 == BGP_DAMP_SUPPRESSED
) {
3789 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3794 #ifdef ENABLE_BGP_VNC
3795 if (safi
== SAFI_MPLS_VPN
) {
3796 struct bgp_dest
*pdest
= NULL
;
3797 struct bgp_table
*table
= NULL
;
3799 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3800 (struct prefix
*)prd
);
3801 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3802 table
= bgp_dest_get_bgp_table_info(pdest
);
3804 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3805 peer
->bgp
, prd
, table
, p
, pi
);
3807 bgp_dest_unlock_node(pdest
);
3809 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3810 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3812 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3813 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3818 /* If this is an EVPN route, process for un-import. */
3819 if (safi
== SAFI_EVPN
)
3820 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3822 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3825 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3826 struct peer
*peer
, struct attr
*attr
,
3827 struct bgp_dest
*dest
)
3829 struct bgp_path_info
*new;
3831 /* Make new BGP info. */
3832 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3834 new->instance
= instance
;
3835 new->sub_type
= sub_type
;
3838 new->uptime
= monotime(NULL
);
3843 /* Check if received nexthop is valid or not. */
3844 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3845 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3846 struct bgp_dest
*dest
)
3849 bool is_bgp_static_route
=
3850 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3853 /* If `bgp allow-martian-nexthop` is turned on, return next-hop
3856 if (bgp
->allow_martian
)
3860 * Only validated for unicast and multicast currently.
3861 * Also valid for EVPN where the nexthop is an IP address.
3862 * If we are a bgp static route being checked then there is
3863 * no need to check to see if the nexthop is martian as
3864 * that it should be ok.
3866 if (is_bgp_static_route
||
3867 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3870 /* If NEXT_HOP is present, validate it. */
3871 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3872 if (attr
->nexthop
.s_addr
== INADDR_ANY
||
3873 !ipv4_unicast_valid(&attr
->nexthop
) ||
3874 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3878 /* If MP_NEXTHOP is present, validate it. */
3879 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3880 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3881 * it is not an IPv6 link-local address.
3883 * If we receive an UPDATE with nexthop length set to 32 bytes
3884 * we shouldn't discard an UPDATE if it's set to (::).
3885 * The link-local (2st) is validated along the code path later.
3887 if (attr
->mp_nexthop_len
) {
3888 switch (attr
->mp_nexthop_len
) {
3889 case BGP_ATTR_NHLEN_IPV4
:
3890 case BGP_ATTR_NHLEN_VPNV4
:
3891 ret
= (attr
->mp_nexthop_global_in
.s_addr
==
3893 !ipv4_unicast_valid(
3894 &attr
->mp_nexthop_global_in
) ||
3895 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3899 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3900 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3901 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3902 &attr
->mp_nexthop_global
)
3903 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3904 || IN6_IS_ADDR_MULTICAST(
3905 &attr
->mp_nexthop_global
)
3906 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3909 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3910 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3911 || IN6_IS_ADDR_MULTICAST(
3912 &attr
->mp_nexthop_global
)
3913 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3926 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3928 struct community
*old
;
3929 struct community
*new;
3930 struct community
*merge
;
3931 struct community
*no_export
;
3933 old
= bgp_attr_get_community(attr
);
3934 no_export
= community_str2com("no-export");
3939 merge
= community_merge(community_dup(old
), no_export
);
3942 community_free(&old
);
3944 new = community_uniq_sort(merge
);
3945 community_free(&merge
);
3947 new = community_dup(no_export
);
3950 community_free(&no_export
);
3952 bgp_attr_set_community(attr
, new);
3955 static bool bgp_accept_own(struct peer
*peer
, afi_t afi
, safi_t safi
,
3956 struct attr
*attr
, const struct prefix
*prefix
,
3959 struct listnode
*node
, *nnode
;
3961 bool accept_own_found
= false;
3963 if (safi
!= SAFI_MPLS_VPN
)
3966 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3967 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
))
3970 /* The route in question carries the ACCEPT_OWN community */
3971 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
3972 struct community
*comm
= bgp_attr_get_community(attr
);
3974 if (community_include(comm
, COMMUNITY_ACCEPT_OWN
))
3975 accept_own_found
= true;
3978 /* The route in question is targeted to one or more destination VRFs
3979 * on the router (as determined by inspecting the Route Target(s)).
3981 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
3982 if (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
)
3985 if (accept_own_found
&&
3987 bgp
->vpn_policy
[afi
]
3988 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
],
3989 bgp_attr_get_ecommunity(attr
))) {
3990 if (bgp_debug_update(peer
, prefix
, NULL
, 1))
3992 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3995 /* Treat this route as imported, because it's leaked
3996 * already from another VRF, and we got an updated
3997 * version from route-reflector with ACCEPT_OWN
4000 *sub_type
= BGP_ROUTE_IMPORTED
;
4009 void bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4010 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4011 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4012 uint32_t num_labels
, int soft_reconfig
,
4013 struct bgp_route_evpn
*evpn
)
4016 int aspath_loop_count
= 0;
4017 struct bgp_dest
*dest
;
4019 struct attr new_attr
;
4020 struct attr
*attr_new
;
4021 struct bgp_path_info
*pi
;
4022 struct bgp_path_info
*new = NULL
;
4023 struct bgp_path_info_extra
*extra
;
4025 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4027 int do_loop_check
= 1;
4028 int has_valid_label
= 0;
4030 bool force_evpn_import
= false;
4031 safi_t orig_safi
= safi
;
4032 bool leak_success
= true;
4035 if (frrtrace_enabled(frr_bgp
, process_update
)) {
4036 char pfxprint
[PREFIX2STR_BUFFER
];
4038 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
4039 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
4043 #ifdef ENABLE_BGP_VNC
4044 int vnc_implicit_withdraw
= 0;
4047 const struct prefix
*bgp_nht_param_prefix
;
4049 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4050 if (orig_safi
== SAFI_LABELED_UNICAST
)
4051 safi
= SAFI_UNICAST
;
4053 memset(&new_attr
, 0, sizeof(new_attr
));
4054 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
4055 new_attr
.label
= MPLS_INVALID_LABEL
;
4058 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4059 /* TODO: Check to see if we can get rid of "is_valid_label" */
4060 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
4061 has_valid_label
= (num_labels
> 0) ? 1 : 0;
4063 has_valid_label
= bgp_is_valid_label(label
);
4065 if (has_valid_label
)
4066 assert(label
!= NULL
);
4069 /* When peer's soft reconfiguration enabled. Record input packet in
4071 if (!soft_reconfig
&&
4072 CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
) &&
4073 peer
!= bgp
->peer_self
) {
4075 * If the trigger is not from soft_reconfig and if
4076 * PEER_FLAG_SOFT_RECONFIG is enabled for the peer, then attr
4077 * will not be interned. In which case, it is ok to update the
4078 * attr->evpn_overlay, so that, this can be stored in adj_in.
4080 if ((afi
== AFI_L2VPN
) && evpn
) {
4081 memcpy(&attr
->evpn_overlay
, evpn
,
4082 sizeof(struct bgp_route_evpn
));
4084 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
4087 /* Update permitted loop count */
4088 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN
))
4089 allowas_in
= peer
->allowas_in
[afi
][safi
];
4091 /* Check previously received route. */
4092 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4093 if (pi
->peer
== peer
&& pi
->type
== type
4094 && pi
->sub_type
== sub_type
4095 && pi
->addpath_rx_id
== addpath_id
)
4098 /* AS path local-as loop check. */
4099 if (peer
->change_local_as
) {
4101 aspath_loop_count
= allowas_in
;
4102 else if (!CHECK_FLAG(peer
->flags
,
4103 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
4104 aspath_loop_count
= 1;
4106 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
4107 > aspath_loop_count
) {
4108 peer
->stat_pfx_aspath_loop
++;
4109 reason
= "as-path contains our own AS;";
4114 /* If the peer is configured for "allowas-in origin" and the last ASN in
4116 * as-path is our ASN then we do not need to call aspath_loop_check
4118 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
4119 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
4122 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_REFLECTOR_CLIENT
))
4123 bgp_nht_param_prefix
= NULL
;
4125 bgp_nht_param_prefix
= p
;
4127 /* AS path loop check. */
4128 if (do_loop_check
) {
4129 if (aspath_loop_check(attr
->aspath
, bgp
->as
) >
4130 peer
->allowas_in
[afi
][safi
]) {
4131 peer
->stat_pfx_aspath_loop
++;
4132 reason
= "as-path contains our own AS;";
4137 /* If we're a CONFED we need to loop check the CONFED ID too */
4138 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
) && do_loop_check
)
4139 if (aspath_loop_check_confed(attr
->aspath
, bgp
->confed_id
) >
4140 peer
->allowas_in
[afi
][safi
]) {
4141 peer
->stat_pfx_aspath_loop
++;
4142 reason
= "as-path contains our own confed AS;";
4146 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4147 * enabled, then take care of that too.
4149 bool accept_own
= false;
4151 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
4152 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
4154 bgp_accept_own(peer
, afi
, safi
, attr
, p
, &sub_type
);
4156 peer
->stat_pfx_originator_loop
++;
4157 reason
= "originator is us;";
4162 /* Route reflector cluster ID check. */
4163 if (bgp_cluster_filter(peer
, attr
)) {
4164 peer
->stat_pfx_cluster_loop
++;
4165 reason
= "reflected from the same cluster;";
4169 /* Apply incoming filter. */
4170 if (bgp_input_filter(peer
, p
, attr
, afi
, orig_safi
) == FILTER_DENY
) {
4171 peer
->stat_pfx_filter
++;
4176 /* RFC 8212 to prevent route leaks.
4177 * This specification intends to improve this situation by requiring the
4178 * explicit configuration of both BGP Import and Export Policies for any
4179 * External BGP (EBGP) session such as customers, peers, or
4180 * confederation boundaries for all enabled address families. Through
4181 * codification of the aforementioned requirement, operators will
4182 * benefit from consistent behavior across different BGP
4185 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
4186 if (!bgp_inbound_policy_exists(peer
,
4187 &peer
->filter
[afi
][safi
])) {
4188 reason
= "inbound policy missing";
4189 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
4190 NULL
) > FIFTEENMINUTE2USEC
||
4191 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
4193 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4194 monotime(&bgp
->ebgprequirespolicywarning
);
4199 /* draft-ietf-idr-deprecate-as-set-confed-set
4200 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4201 * Eventually, This document (if approved) updates RFC 4271
4202 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4203 * and obsoletes RFC 6472.
4205 if (peer
->bgp
->reject_as_sets
)
4206 if (aspath_check_as_sets(attr
->aspath
)) {
4208 "as-path contains AS_SET or AS_CONFED_SET type;";
4214 * If bgp_update is called with soft_reconfig set then
4215 * attr is interned. In this case, do not overwrite the
4216 * attr->evpn_overlay with evpn directly. Instead memcpy
4217 * evpn to new_atr.evpn_overlay before it is interned.
4219 if (soft_reconfig
&& (afi
== AFI_L2VPN
) && evpn
)
4220 memcpy(&new_attr
.evpn_overlay
, evpn
,
4221 sizeof(struct bgp_route_evpn
));
4223 /* Apply incoming route-map.
4224 * NB: new_attr may now contain newly allocated values from route-map
4226 * commands, so we need bgp_attr_flush in the error paths, until we
4228 * the attr (which takes over the memory references) */
4229 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, orig_safi
, NULL
, label
,
4232 peer
->stat_pfx_filter
++;
4233 reason
= "route-map;";
4234 bgp_attr_flush(&new_attr
);
4238 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
4239 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
4240 /* remove from RIB previous entry */
4241 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
4244 if (peer
->sort
== BGP_PEER_EBGP
) {
4247 * A BGP speaker receiving an announcement tagged with the
4248 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4249 * NO_EXPORT community as defined in RFC1997, or a
4250 * similar community, to prevent propagation of the
4251 * prefix outside the local AS. The community to prevent
4252 * propagation SHOULD be chosen according to the operator's
4255 if (bgp_attr_get_community(&new_attr
) &&
4256 community_include(bgp_attr_get_community(&new_attr
),
4257 COMMUNITY_BLACKHOLE
))
4258 bgp_attr_add_no_export_community(&new_attr
);
4260 /* If we receive the graceful-shutdown community from an eBGP
4261 * peer we must lower local-preference */
4262 if (bgp_attr_get_community(&new_attr
) &&
4263 community_include(bgp_attr_get_community(&new_attr
),
4265 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
4266 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
4268 /* If graceful-shutdown is configured globally or
4269 * per neighbor, then add the GSHUT community to
4270 * all paths received from eBGP peers. */
4271 } else if (bgp_in_graceful_shutdown(peer
->bgp
) ||
4272 CHECK_FLAG(peer
->flags
, PEER_FLAG_GRACEFUL_SHUTDOWN
))
4273 bgp_attr_add_gshut_community(&new_attr
);
4276 /* next hop check. */
4277 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
) &&
4278 bgp_update_martian_nexthop(bgp
, afi
, safi
, type
, sub_type
,
4280 peer
->stat_pfx_nh_invalid
++;
4281 reason
= "martian or self next-hop;";
4282 bgp_attr_flush(&new_attr
);
4286 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
4287 peer
->stat_pfx_nh_invalid
++;
4288 reason
= "self mac;";
4289 bgp_attr_flush(&new_attr
);
4293 if (bgp_check_role_applicability(afi
, safi
) &&
4294 bgp_otc_filter(peer
, &new_attr
)) {
4295 reason
= "failing otc validation";
4296 bgp_attr_flush(&new_attr
);
4300 /* If neighbor soo is configured, tag all incoming routes with
4301 * this SoO tag and then filter out advertisements in
4302 * subgroup_announce_check() if it matches the configured SoO
4303 * on the other peer.
4305 if (peer
->soo
[afi
][safi
]) {
4306 struct ecommunity
*old_ecomm
=
4307 bgp_attr_get_ecommunity(&new_attr
);
4308 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
4309 struct ecommunity
*new_ecomm
;
4312 new_ecomm
= ecommunity_merge(ecommunity_dup(old_ecomm
),
4315 if (!old_ecomm
->refcnt
)
4316 ecommunity_free(&old_ecomm
);
4318 new_ecomm
= ecommunity_dup(ecomm_soo
);
4321 bgp_attr_set_ecommunity(&new_attr
, new_ecomm
);
4324 attr_new
= bgp_attr_intern(&new_attr
);
4326 /* If the update is implicit withdraw. */
4328 pi
->uptime
= monotime(NULL
);
4329 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
4331 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4333 /* Same attribute comes in. */
4334 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4336 && (!has_valid_label
4337 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
4338 num_labels
* sizeof(mpls_label_t
))
4340 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4341 BGP_CONFIG_DAMPENING
)
4342 && peer
->sort
== BGP_PEER_EBGP
4343 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4344 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4345 bgp_debug_rdpfxpath2str(
4346 afi
, safi
, prd
, p
, label
,
4347 num_labels
, addpath_id
? 1 : 0,
4348 addpath_id
, evpn
, pfx_buf
,
4350 zlog_debug("%pBP rcvd %s", peer
,
4354 if (bgp_damp_update(pi
, dest
, afi
, safi
)
4355 != BGP_DAMP_SUPPRESSED
) {
4356 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
4358 bgp_process(bgp
, dest
, afi
, safi
);
4360 } else /* Duplicate - odd */
4362 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4363 if (!peer
->rcvd_attr_printed
) {
4365 "%pBP rcvd UPDATE w/ attr: %s",
4367 peer
->rcvd_attr_str
);
4368 peer
->rcvd_attr_printed
= 1;
4371 bgp_debug_rdpfxpath2str(
4372 afi
, safi
, prd
, p
, label
,
4373 num_labels
, addpath_id
? 1 : 0,
4374 addpath_id
, evpn
, pfx_buf
,
4377 "%pBP rcvd %s...duplicate ignored",
4381 /* graceful restart STALE flag unset. */
4382 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4383 bgp_path_info_unset_flag(
4384 dest
, pi
, BGP_PATH_STALE
);
4385 bgp_dest_set_defer_flag(dest
, false);
4386 bgp_process(bgp
, dest
, afi
, safi
);
4390 bgp_dest_unlock_node(dest
);
4391 bgp_attr_unintern(&attr_new
);
4396 /* Withdraw/Announce before we fully processed the withdraw */
4397 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4398 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4399 bgp_debug_rdpfxpath2str(
4400 afi
, safi
, prd
, p
, label
, num_labels
,
4401 addpath_id
? 1 : 0, addpath_id
, evpn
,
4402 pfx_buf
, sizeof(pfx_buf
));
4404 "%pBP rcvd %s, flapped quicker than processing",
4408 bgp_path_info_restore(dest
, pi
);
4411 * If the BGP_PATH_REMOVED flag is set, then EVPN
4412 * routes would have been unimported already when a
4413 * prior BGP withdraw processing happened. Such routes
4414 * need to be imported again, so flag accordingly.
4416 force_evpn_import
= true;
4418 /* implicit withdraw, decrement aggregate and pcount
4419 * here. only if update is accepted, they'll increment
4422 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4425 /* Received Logging. */
4426 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4427 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
4428 num_labels
, addpath_id
? 1 : 0,
4429 addpath_id
, evpn
, pfx_buf
,
4431 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4434 /* graceful restart STALE flag unset. */
4435 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4436 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
4437 bgp_dest_set_defer_flag(dest
, false);
4440 /* The attribute is changed. */
4441 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
4443 /* Update bgp route dampening information. */
4444 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4445 && peer
->sort
== BGP_PEER_EBGP
) {
4446 /* This is implicit withdraw so we should update
4449 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
4450 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
4452 #ifdef ENABLE_BGP_VNC
4453 if (safi
== SAFI_MPLS_VPN
) {
4454 struct bgp_dest
*pdest
= NULL
;
4455 struct bgp_table
*table
= NULL
;
4457 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4458 (struct prefix
*)prd
);
4459 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4460 table
= bgp_dest_get_bgp_table_info(pdest
);
4462 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
4463 bgp
, prd
, table
, p
, pi
);
4465 bgp_dest_unlock_node(pdest
);
4467 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4468 && (safi
== SAFI_UNICAST
)) {
4469 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4471 * Implicit withdraw case.
4473 ++vnc_implicit_withdraw
;
4474 vnc_import_bgp_del_route(bgp
, p
, pi
);
4475 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
4480 /* Special handling for EVPN update of an existing route. If the
4481 * extended community attribute has changed, we need to
4483 * the route using its existing extended community. It will be
4484 * subsequently processed for import with the new extended
4487 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
4490 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
4492 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4495 cmp
= ecommunity_cmp(
4496 bgp_attr_get_ecommunity(pi
->attr
),
4497 bgp_attr_get_ecommunity(attr_new
));
4499 if (bgp_debug_update(peer
, p
, NULL
, 1))
4501 "Change in EXT-COMM, existing %s new %s",
4503 bgp_attr_get_ecommunity(
4506 bgp_attr_get_ecommunity(
4508 if (safi
== SAFI_EVPN
)
4509 bgp_evpn_unimport_route(
4510 bgp
, afi
, safi
, p
, pi
);
4511 else /* SAFI_MPLS_VPN */
4512 vpn_leak_to_vrf_withdraw(pi
);
4517 /* Update to new attribute. */
4518 bgp_attr_unintern(&pi
->attr
);
4519 pi
->attr
= attr_new
;
4521 /* Update MPLS label */
4522 if (has_valid_label
) {
4523 extra
= bgp_path_info_extra_get(pi
);
4524 if (extra
->label
!= label
) {
4525 memcpy(&extra
->label
, label
,
4526 num_labels
* sizeof(mpls_label_t
));
4527 extra
->num_labels
= num_labels
;
4529 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4530 bgp_set_valid_label(&extra
->label
[0]);
4533 /* Update SRv6 SID */
4534 if (attr
->srv6_l3vpn
) {
4535 extra
= bgp_path_info_extra_get(pi
);
4536 if (sid_diff(&extra
->sid
[0].sid
,
4537 &attr
->srv6_l3vpn
->sid
)) {
4538 sid_copy(&extra
->sid
[0].sid
,
4539 &attr
->srv6_l3vpn
->sid
);
4540 extra
->num_sids
= 1;
4542 extra
->sid
[0].loc_block_len
= 0;
4543 extra
->sid
[0].loc_node_len
= 0;
4544 extra
->sid
[0].func_len
= 0;
4545 extra
->sid
[0].arg_len
= 0;
4546 extra
->sid
[0].transposition_len
= 0;
4547 extra
->sid
[0].transposition_offset
= 0;
4549 if (attr
->srv6_l3vpn
->loc_block_len
!= 0) {
4550 extra
->sid
[0].loc_block_len
=
4551 attr
->srv6_l3vpn
->loc_block_len
;
4552 extra
->sid
[0].loc_node_len
=
4553 attr
->srv6_l3vpn
->loc_node_len
;
4554 extra
->sid
[0].func_len
=
4555 attr
->srv6_l3vpn
->func_len
;
4556 extra
->sid
[0].arg_len
=
4557 attr
->srv6_l3vpn
->arg_len
;
4558 extra
->sid
[0].transposition_len
=
4560 ->transposition_len
;
4561 extra
->sid
[0].transposition_offset
=
4563 ->transposition_offset
;
4566 } else if (attr
->srv6_vpn
) {
4567 extra
= bgp_path_info_extra_get(pi
);
4568 if (sid_diff(&extra
->sid
[0].sid
,
4569 &attr
->srv6_vpn
->sid
)) {
4570 sid_copy(&extra
->sid
[0].sid
,
4571 &attr
->srv6_vpn
->sid
);
4572 extra
->num_sids
= 1;
4576 #ifdef ENABLE_BGP_VNC
4577 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4578 && (safi
== SAFI_UNICAST
)) {
4579 if (vnc_implicit_withdraw
) {
4581 * Add back the route with its new attributes
4583 * The route is still selected, until the route
4585 * queued by bgp_process actually runs. We have
4587 * update to the VNC side immediately to avoid
4589 * configuration changes (e.g., route-map
4591 * trigger re-importation of the entire RIB.
4593 vnc_import_bgp_add_route(bgp
, p
, pi
);
4594 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4599 /* Update bgp route dampening information. */
4600 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4601 && peer
->sort
== BGP_PEER_EBGP
) {
4602 /* Now we do normal update dampening. */
4603 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4604 if (ret
== BGP_DAMP_SUPPRESSED
) {
4605 bgp_dest_unlock_node(dest
);
4610 /* Nexthop reachability check - for unicast and
4611 * labeled-unicast.. */
4612 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4613 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4614 || (safi
== SAFI_EVPN
&&
4615 bgp_evpn_is_prefix_nht_supported(p
))) {
4616 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4617 && peer
->ttl
== BGP_DEFAULT_TTL
4618 && !CHECK_FLAG(peer
->flags
,
4619 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4620 && !CHECK_FLAG(bgp
->flags
,
4621 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4626 struct bgp
*bgp_nexthop
= bgp
;
4628 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4629 bgp_nexthop
= pi
->extra
->bgp_orig
;
4631 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4633 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4634 safi
, pi
, NULL
, connected
,
4635 bgp_nht_param_prefix
) ||
4636 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4637 bgp_path_info_set_flag(dest
, pi
,
4640 if (BGP_DEBUG(nht
, NHT
)) {
4641 zlog_debug("%s(%pI4): NH unresolved",
4643 (in_addr_t
*)&attr_new
->nexthop
);
4645 bgp_path_info_unset_flag(dest
, pi
,
4650 bgp_path_info_set_flag(dest
, pi
,
4651 BGP_PATH_ACCEPT_OWN
);
4653 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4656 #ifdef ENABLE_BGP_VNC
4657 if (safi
== SAFI_MPLS_VPN
) {
4658 struct bgp_dest
*pdest
= NULL
;
4659 struct bgp_table
*table
= NULL
;
4661 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4662 (struct prefix
*)prd
);
4663 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4664 table
= bgp_dest_get_bgp_table_info(pdest
);
4666 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4667 bgp
, prd
, table
, p
, pi
);
4669 bgp_dest_unlock_node(pdest
);
4673 /* If this is an EVPN route and some attribute has changed,
4674 * or we are explicitly told to perform a route import, process
4675 * route for import. If the extended community has changed, we
4677 * have done the un-import earlier and the import would result
4679 * route getting injected into appropriate L2 VNIs. If it is
4681 * some other attribute change, the import will result in
4683 * the attributes for the route in the VNI(s).
4685 if (safi
== SAFI_EVPN
&&
4686 (!same_attr
|| force_evpn_import
) &&
4687 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4688 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4690 /* Process change. */
4691 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4693 bgp_process(bgp
, dest
, afi
, safi
);
4694 bgp_dest_unlock_node(dest
);
4696 if (SAFI_UNICAST
== safi
4697 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4698 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4700 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4702 if ((SAFI_MPLS_VPN
== safi
)
4703 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4704 leak_success
= vpn_leak_to_vrf_update(bgp
, pi
, prd
);
4707 #ifdef ENABLE_BGP_VNC
4708 if (SAFI_MPLS_VPN
== safi
) {
4709 mpls_label_t label_decoded
= decode_label(label
);
4711 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4712 type
, sub_type
, &label_decoded
);
4714 if (SAFI_ENCAP
== safi
) {
4715 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4716 type
, sub_type
, NULL
);
4719 if ((safi
== SAFI_MPLS_VPN
) &&
4720 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4721 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4723 bgp_unlink_nexthop(pi
);
4724 bgp_path_info_delete(dest
, pi
);
4727 } // End of implicit withdraw
4729 /* Received Logging. */
4730 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4731 if (!peer
->rcvd_attr_printed
) {
4732 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4733 peer
->rcvd_attr_str
);
4734 peer
->rcvd_attr_printed
= 1;
4737 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4738 addpath_id
? 1 : 0, addpath_id
, evpn
,
4739 pfx_buf
, sizeof(pfx_buf
));
4740 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4743 /* Make new BGP info. */
4744 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4746 /* Update MPLS label */
4747 if (has_valid_label
) {
4748 extra
= bgp_path_info_extra_get(new);
4749 if (extra
->label
!= label
) {
4750 memcpy(&extra
->label
, label
,
4751 num_labels
* sizeof(mpls_label_t
));
4752 extra
->num_labels
= num_labels
;
4754 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4755 bgp_set_valid_label(&extra
->label
[0]);
4758 /* Update SRv6 SID */
4759 if (safi
== SAFI_MPLS_VPN
) {
4760 extra
= bgp_path_info_extra_get(new);
4761 if (attr
->srv6_l3vpn
) {
4762 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_l3vpn
->sid
);
4763 extra
->num_sids
= 1;
4765 extra
->sid
[0].loc_block_len
=
4766 attr
->srv6_l3vpn
->loc_block_len
;
4767 extra
->sid
[0].loc_node_len
=
4768 attr
->srv6_l3vpn
->loc_node_len
;
4769 extra
->sid
[0].func_len
= attr
->srv6_l3vpn
->func_len
;
4770 extra
->sid
[0].arg_len
= attr
->srv6_l3vpn
->arg_len
;
4771 extra
->sid
[0].transposition_len
=
4772 attr
->srv6_l3vpn
->transposition_len
;
4773 extra
->sid
[0].transposition_offset
=
4774 attr
->srv6_l3vpn
->transposition_offset
;
4775 } else if (attr
->srv6_vpn
) {
4776 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_vpn
->sid
);
4777 extra
->num_sids
= 1;
4781 /* Nexthop reachability check. */
4782 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4783 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4784 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4785 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4786 && peer
->ttl
== BGP_DEFAULT_TTL
4787 && !CHECK_FLAG(peer
->flags
,
4788 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4789 && !CHECK_FLAG(bgp
->flags
,
4790 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4795 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4797 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4798 connected
, bgp_nht_param_prefix
) ||
4799 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4800 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4802 if (BGP_DEBUG(nht
, NHT
))
4803 zlog_debug("%s(%pI4): NH unresolved", __func__
,
4804 &attr_new
->nexthop
);
4805 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4809 bgp_path_info_set_flag(dest
, new, BGP_PATH_ACCEPT_OWN
);
4811 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4814 /* If maximum prefix count is configured and current prefix
4817 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0)) {
4818 reason
= "maximum-prefix overflow";
4819 bgp_attr_flush(&new_attr
);
4824 new->addpath_rx_id
= addpath_id
;
4826 /* Increment prefix */
4827 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4829 /* Register new BGP information. */
4830 bgp_path_info_add(dest
, new);
4832 /* route_node_get lock */
4833 bgp_dest_unlock_node(dest
);
4835 #ifdef ENABLE_BGP_VNC
4836 if (safi
== SAFI_MPLS_VPN
) {
4837 struct bgp_dest
*pdest
= NULL
;
4838 struct bgp_table
*table
= NULL
;
4840 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4841 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4842 table
= bgp_dest_get_bgp_table_info(pdest
);
4844 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4845 bgp
, prd
, table
, p
, new);
4847 bgp_dest_unlock_node(pdest
);
4851 /* If this is an EVPN route, process for import. */
4852 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4853 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4855 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4857 /* Process change. */
4858 bgp_process(bgp
, dest
, afi
, safi
);
4860 if (SAFI_UNICAST
== safi
4861 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4862 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4863 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4865 if ((SAFI_MPLS_VPN
== safi
)
4866 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4867 leak_success
= vpn_leak_to_vrf_update(bgp
, new, prd
);
4869 #ifdef ENABLE_BGP_VNC
4870 if (SAFI_MPLS_VPN
== safi
) {
4871 mpls_label_t label_decoded
= decode_label(label
);
4873 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4874 sub_type
, &label_decoded
);
4876 if (SAFI_ENCAP
== safi
) {
4877 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4881 if ((safi
== SAFI_MPLS_VPN
) &&
4882 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4883 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4885 bgp_unlink_nexthop(new);
4886 bgp_path_info_delete(dest
, new);
4891 /* This BGP update is filtered. Log the reason then update BGP
4895 bgp_unlink_nexthop(new);
4896 bgp_path_info_delete(dest
, new);
4897 bgp_path_info_extra_free(&new->extra
);
4898 XFREE(MTYPE_BGP_ROUTE
, new);
4901 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4903 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4904 if (!peer
->rcvd_attr_printed
) {
4905 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4906 peer
->rcvd_attr_str
);
4907 peer
->rcvd_attr_printed
= 1;
4910 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4911 addpath_id
? 1 : 0, addpath_id
, evpn
,
4912 pfx_buf
, sizeof(pfx_buf
));
4913 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4914 peer
, pfx_buf
, reason
);
4918 /* If this is an EVPN route, un-import it as it is now filtered.
4920 if (safi
== SAFI_EVPN
)
4921 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4923 if (SAFI_UNICAST
== safi
4924 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4925 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4927 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4929 if ((SAFI_MPLS_VPN
== safi
)
4930 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4932 vpn_leak_to_vrf_withdraw(pi
);
4935 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4938 bgp_dest_unlock_node(dest
);
4940 #ifdef ENABLE_BGP_VNC
4942 * Filtered update is treated as an implicit withdrawal (see
4944 * a few lines above)
4946 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4947 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4955 void bgp_withdraw(struct peer
*peer
, const struct prefix
*p
,
4956 uint32_t addpath_id
, afi_t afi
, safi_t safi
, int type
,
4957 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4958 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4961 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4962 struct bgp_dest
*dest
;
4963 struct bgp_path_info
*pi
;
4965 #ifdef ENABLE_BGP_VNC
4966 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4967 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4975 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4977 /* If peer is soft reconfiguration enabled. Record input packet for
4978 * further calculation.
4980 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4981 * routes that are filtered. This tanks out Quagga RS pretty badly due
4983 * the iteration over all RS clients.
4984 * Since we need to remove the entry from adj_in anyway, do that first
4986 * if there was no entry, we don't need to do anything more.
4988 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4989 && peer
!= bgp
->peer_self
)
4990 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4991 peer
->stat_pfx_dup_withdraw
++;
4993 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4994 bgp_debug_rdpfxpath2str(
4995 afi
, safi
, prd
, p
, label
, num_labels
,
4996 addpath_id
? 1 : 0, addpath_id
, NULL
,
4997 pfx_buf
, sizeof(pfx_buf
));
4999 "%s withdrawing route %s not in adj-in",
5000 peer
->host
, pfx_buf
);
5002 bgp_dest_unlock_node(dest
);
5006 /* Lookup withdrawn route. */
5007 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5008 if (pi
->peer
== peer
&& pi
->type
== type
5009 && pi
->sub_type
== sub_type
5010 && pi
->addpath_rx_id
== addpath_id
)
5014 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
5015 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
5016 addpath_id
? 1 : 0, addpath_id
, NULL
,
5017 pfx_buf
, sizeof(pfx_buf
));
5018 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer
,
5022 /* Withdraw specified route from routing table. */
5023 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
5024 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
5025 if (SAFI_UNICAST
== safi
5026 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5027 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5028 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5030 if ((SAFI_MPLS_VPN
== safi
)
5031 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5033 vpn_leak_to_vrf_withdraw(pi
);
5035 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
5036 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
5037 addpath_id
? 1 : 0, addpath_id
, NULL
,
5038 pfx_buf
, sizeof(pfx_buf
));
5039 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
5042 /* Unlock bgp_node_get() lock. */
5043 bgp_dest_unlock_node(dest
);
5048 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
5051 struct update_subgroup
*subgrp
;
5052 subgrp
= peer_subgroup(peer
, afi
, safi
);
5053 subgroup_default_originate(subgrp
, withdraw
);
5058 * bgp_stop_announce_route_timer
5060 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
5062 if (!paf
->t_announce_route
)
5065 EVENT_OFF(paf
->t_announce_route
);
5069 * bgp_announce_route_timer_expired
5071 * Callback that is invoked when the route announcement timer for a
5074 static void bgp_announce_route_timer_expired(struct event
*t
)
5076 struct peer_af
*paf
;
5082 if (!peer_established(peer
))
5085 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
5088 peer_af_announce_route(paf
, 1);
5090 /* Notify BGP conditional advertisement scanner percess */
5091 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
5095 * bgp_announce_route
5097 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
5099 * if force is true we will force an update even if the update
5100 * limiting code is attempted to kick in.
5102 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
, bool force
)
5104 struct peer_af
*paf
;
5105 struct update_subgroup
*subgrp
;
5107 paf
= peer_af_find(peer
, afi
, safi
);
5110 subgrp
= PAF_SUBGRP(paf
);
5113 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5114 * or a refresh has already been triggered.
5116 if (!subgrp
|| paf
->t_announce_route
)
5120 SET_FLAG(subgrp
->sflags
, SUBGRP_STATUS_FORCE_UPDATES
);
5123 * Start a timer to stagger/delay the announce. This serves
5124 * two purposes - announcement can potentially be combined for
5125 * multiple peers and the announcement doesn't happen in the
5128 event_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
5129 (subgrp
->peer_count
== 1)
5130 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5131 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
5132 &paf
->t_announce_route
);
5136 * Announce routes from all AF tables to a peer.
5138 * This should ONLY be called when there is a need to refresh the
5139 * routes to the peer based on a policy change for this peer alone
5140 * or a route refresh request received from the peer.
5141 * The operation will result in splitting the peer from its existing
5142 * subgroups and putting it in new subgroups.
5144 void bgp_announce_route_all(struct peer
*peer
)
5149 FOREACH_AFI_SAFI (afi
, safi
)
5150 bgp_announce_route(peer
, afi
, safi
, false);
5153 /* Flag or unflag bgp_dest to determine whether it should be treated by
5154 * bgp_soft_reconfig_table_task.
5155 * Flag if flag is true. Unflag if flag is false.
5157 static void bgp_soft_reconfig_table_flag(struct bgp_table
*table
, bool flag
)
5159 struct bgp_dest
*dest
;
5160 struct bgp_adj_in
*ain
;
5165 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5166 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5167 if (ain
->peer
!= NULL
)
5170 if (flag
&& ain
!= NULL
&& ain
->peer
!= NULL
)
5171 SET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5173 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5177 static void bgp_soft_reconfig_table_update(struct peer
*peer
,
5178 struct bgp_dest
*dest
,
5179 struct bgp_adj_in
*ain
, afi_t afi
,
5180 safi_t safi
, struct prefix_rd
*prd
)
5182 struct bgp_path_info
*pi
;
5183 uint32_t num_labels
= 0;
5184 mpls_label_t
*label_pnt
= NULL
;
5185 struct bgp_route_evpn evpn
;
5187 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5188 if (pi
->peer
== peer
)
5191 if (pi
&& pi
->extra
)
5192 num_labels
= pi
->extra
->num_labels
;
5194 label_pnt
= &pi
->extra
->label
[0];
5196 memcpy(&evpn
, bgp_attr_get_evpn_overlay(pi
->attr
),
5199 memset(&evpn
, 0, sizeof(evpn
));
5201 bgp_update(peer
, bgp_dest_get_prefix(dest
), ain
->addpath_rx_id
,
5202 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, prd
,
5203 label_pnt
, num_labels
, 1, &evpn
);
5206 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5207 struct bgp_table
*table
,
5208 struct prefix_rd
*prd
)
5210 struct bgp_dest
*dest
;
5211 struct bgp_adj_in
*ain
;
5214 table
= peer
->bgp
->rib
[afi
][safi
];
5216 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5217 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5218 if (ain
->peer
!= peer
)
5221 bgp_soft_reconfig_table_update(peer
, dest
, ain
, afi
,
5226 /* Do soft reconfig table per bgp table.
5227 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5228 * when BGP_NODE_SOFT_RECONFIG is set,
5229 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5230 * Schedule a new thread to continue the job.
5231 * Without splitting the full job into several part,
5232 * vtysh waits for the job to finish before responding to a BGP command
5234 static void bgp_soft_reconfig_table_task(struct event
*thread
)
5236 uint32_t iter
, max_iter
;
5237 struct bgp_dest
*dest
;
5238 struct bgp_adj_in
*ain
;
5240 struct bgp_table
*table
;
5241 struct prefix_rd
*prd
;
5242 struct listnode
*node
, *nnode
;
5244 table
= EVENT_ARG(thread
);
5247 max_iter
= SOFT_RECONFIG_TASK_MAX_PREFIX
;
5248 if (table
->soft_reconfig_init
) {
5249 /* first call of the function with a new srta structure.
5250 * Don't do any treatment this time on nodes
5251 * in order vtysh to respond quickly
5256 for (iter
= 0, dest
= bgp_table_top(table
); (dest
&& iter
< max_iter
);
5257 dest
= bgp_route_next(dest
)) {
5258 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
))
5261 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5263 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5264 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
,
5266 if (ain
->peer
!= peer
)
5269 bgp_soft_reconfig_table_update(
5270 peer
, dest
, ain
, table
->afi
,
5277 /* we're either starting the initial iteration,
5278 * or we're going to continue an ongoing iteration
5280 if (dest
|| table
->soft_reconfig_init
) {
5281 table
->soft_reconfig_init
= false;
5282 event_add_event(bm
->master
, bgp_soft_reconfig_table_task
, table
,
5283 0, &table
->soft_reconfig_thread
);
5286 /* we're done, clean up the background iteration context info and
5287 schedule route annoucement
5289 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
, peer
)) {
5290 listnode_delete(table
->soft_reconfig_peers
, peer
);
5291 bgp_announce_route(peer
, table
->afi
, table
->safi
, false);
5294 list_delete(&table
->soft_reconfig_peers
);
5298 /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5300 * - bgp cannot be NULL
5301 * - if table and peer are NULL, cancel all threads within the bgp instance
5302 * - if table is NULL and peer is not,
5303 * remove peer in all threads within the bgp instance
5304 * - if peer is NULL, cancel all threads matching table within the bgp instance
5306 void bgp_soft_reconfig_table_task_cancel(const struct bgp
*bgp
,
5307 const struct bgp_table
*table
,
5308 const struct peer
*peer
)
5311 struct listnode
*node
, *nnode
;
5313 struct bgp_table
*ntable
;
5318 FOREACH_AFI_SAFI (afi
, safi
) {
5319 ntable
= bgp
->rib
[afi
][safi
];
5322 if (table
&& table
!= ntable
)
5325 for (ALL_LIST_ELEMENTS(ntable
->soft_reconfig_peers
, node
, nnode
,
5327 if (peer
&& peer
!= npeer
)
5329 listnode_delete(ntable
->soft_reconfig_peers
, npeer
);
5332 if (!ntable
->soft_reconfig_peers
5333 || !list_isempty(ntable
->soft_reconfig_peers
))
5336 list_delete(&ntable
->soft_reconfig_peers
);
5337 bgp_soft_reconfig_table_flag(ntable
, false);
5338 EVENT_OFF(ntable
->soft_reconfig_thread
);
5343 * Returns false if the peer is not configured for soft reconfig in
5345 bool bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5347 struct bgp_dest
*dest
;
5348 struct bgp_table
*table
;
5349 struct listnode
*node
, *nnode
;
5351 struct peer_af
*paf
;
5353 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
))
5356 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
5357 && (safi
!= SAFI_EVPN
)) {
5358 table
= peer
->bgp
->rib
[afi
][safi
];
5362 table
->soft_reconfig_init
= true;
5364 if (!table
->soft_reconfig_peers
)
5365 table
->soft_reconfig_peers
= list_new();
5367 /* add peer to the table soft_reconfig_peers if not already
5370 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
,
5376 listnode_add(table
->soft_reconfig_peers
, peer
);
5378 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5379 * on table would start back at the beginning.
5381 bgp_soft_reconfig_table_flag(table
, true);
5383 if (!table
->soft_reconfig_thread
)
5384 event_add_event(bm
->master
,
5385 bgp_soft_reconfig_table_task
, table
, 0,
5386 &table
->soft_reconfig_thread
);
5387 /* Cancel bgp_announce_route_timer_expired threads.
5388 * bgp_announce_route_timer_expired threads have been scheduled
5389 * to announce routes as soon as the soft_reconfigure process
5391 * In this case, soft_reconfigure is also scheduled by using
5392 * a thread but is planned after the
5393 * bgp_announce_route_timer_expired threads. It means that,
5394 * without cancelling the threads, the route announcement task
5395 * would run before the soft reconfiguration one. That would
5396 * useless and would block vtysh during several seconds. Route
5397 * announcements are rescheduled as soon as the soft_reconfigure
5400 paf
= peer_af_find(peer
, afi
, safi
);
5402 bgp_stop_announce_route_timer(paf
);
5404 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5405 dest
= bgp_route_next(dest
)) {
5406 table
= bgp_dest_get_bgp_table_info(dest
);
5411 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5412 struct prefix_rd prd
;
5414 prd
.family
= AF_UNSPEC
;
5416 memcpy(&prd
.val
, p
->u
.val
, 8);
5418 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
5425 struct bgp_clear_node_queue
{
5426 struct bgp_dest
*dest
;
5429 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
5431 struct bgp_clear_node_queue
*cnq
= data
;
5432 struct bgp_dest
*dest
= cnq
->dest
;
5433 struct peer
*peer
= wq
->spec
.data
;
5434 struct bgp_path_info
*pi
;
5436 afi_t afi
= bgp_dest_table(dest
)->afi
;
5437 safi_t safi
= bgp_dest_table(dest
)->safi
;
5439 assert(dest
&& peer
);
5442 /* It is possible that we have multiple paths for a prefix from a peer
5443 * if that peer is using AddPath.
5445 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5446 if (pi
->peer
!= peer
)
5449 /* graceful restart STALE flag set. */
5450 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
5451 && peer
->nsf
[afi
][safi
])
5452 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5453 PEER_STATUS_ENHANCED_REFRESH
))
5454 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5455 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
5456 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
5458 /* If this is an EVPN route, process for
5460 if (safi
== SAFI_EVPN
)
5461 bgp_evpn_unimport_route(
5463 bgp_dest_get_prefix(dest
), pi
);
5464 /* Handle withdraw for VRF route-leaking and L3VPN */
5465 if (SAFI_UNICAST
== safi
5466 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
5467 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5468 vpn_leak_from_vrf_withdraw(bgp_get_default(),
5471 if (SAFI_MPLS_VPN
== safi
&&
5472 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5473 vpn_leak_to_vrf_withdraw(pi
);
5476 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5482 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
5484 struct bgp_clear_node_queue
*cnq
= data
;
5485 struct bgp_dest
*dest
= cnq
->dest
;
5486 struct bgp_table
*table
= bgp_dest_table(dest
);
5488 bgp_dest_unlock_node(dest
);
5489 bgp_table_unlock(table
);
5490 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
5493 static void bgp_clear_node_complete(struct work_queue
*wq
)
5495 struct peer
*peer
= wq
->spec
.data
;
5497 /* Tickle FSM to start moving again */
5498 BGP_EVENT_ADD(peer
, Clearing_Completed
);
5500 peer_unlock(peer
); /* bgp_clear_route */
5503 static void bgp_clear_node_queue_init(struct peer
*peer
)
5505 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5507 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
5508 #undef CLEAR_QUEUE_NAME_LEN
5510 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
5511 peer
->clear_node_queue
->spec
.hold
= 10;
5512 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
5513 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
5514 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
5515 peer
->clear_node_queue
->spec
.max_retries
= 0;
5517 /* we only 'lock' this peer reference when the queue is actually active
5519 peer
->clear_node_queue
->spec
.data
= peer
;
5522 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5523 struct bgp_table
*table
)
5525 struct bgp_dest
*dest
;
5526 int force
= peer
->bgp
->process_queue
? 0 : 1;
5529 table
= peer
->bgp
->rib
[afi
][safi
];
5531 /* If still no table => afi/safi isn't configured at all or smth. */
5535 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5536 struct bgp_path_info
*pi
, *next
;
5537 struct bgp_adj_in
*ain
;
5538 struct bgp_adj_in
*ain_next
;
5540 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5541 * queued for every clearing peer, regardless of whether it is
5542 * relevant to the peer at hand.
5544 * Overview: There are 3 different indices which need to be
5545 * scrubbed, potentially, when a peer is removed:
5547 * 1 peer's routes visible via the RIB (ie accepted routes)
5548 * 2 peer's routes visible by the (optional) peer's adj-in index
5549 * 3 other routes visible by the peer's adj-out index
5551 * 3 there is no hurry in scrubbing, once the struct peer is
5552 * removed from bgp->peer, we could just GC such deleted peer's
5553 * adj-outs at our leisure.
5555 * 1 and 2 must be 'scrubbed' in some way, at least made
5556 * invisible via RIB index before peer session is allowed to be
5557 * brought back up. So one needs to know when such a 'search' is
5562 * - there'd be a single global queue or a single RIB walker
5563 * - rather than tracking which route_nodes still need to be
5564 * examined on a peer basis, we'd track which peers still
5567 * Given that our per-peer prefix-counts now should be reliable,
5568 * this may actually be achievable. It doesn't seem to be a huge
5569 * problem at this time,
5571 * It is possible that we have multiple paths for a prefix from
5573 * if that peer is using AddPath.
5577 ain_next
= ain
->next
;
5579 if (ain
->peer
== peer
)
5580 bgp_adj_in_remove(dest
, ain
);
5585 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5587 if (pi
->peer
!= peer
)
5591 bgp_path_info_reap(dest
, pi
);
5593 struct bgp_clear_node_queue
*cnq
;
5595 /* both unlocked in bgp_clear_node_queue_del */
5596 bgp_table_lock(bgp_dest_table(dest
));
5597 bgp_dest_lock_node(dest
);
5599 MTYPE_BGP_CLEAR_NODE_QUEUE
,
5600 sizeof(struct bgp_clear_node_queue
));
5602 work_queue_add(peer
->clear_node_queue
, cnq
);
5610 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5612 struct bgp_dest
*dest
;
5613 struct bgp_table
*table
;
5615 if (peer
->clear_node_queue
== NULL
)
5616 bgp_clear_node_queue_init(peer
);
5618 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5619 * Idle until it receives a Clearing_Completed event. This protects
5620 * against peers which flap faster than we can we clear, which could
5623 * a) race with routes from the new session being installed before
5624 * clear_route_node visits the node (to delete the route of that
5626 * b) resource exhaustion, clear_route_node likely leads to an entry
5627 * on the process_main queue. Fast-flapping could cause that queue
5631 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5632 * the unlock will happen upon work-queue completion; other wise, the
5633 * unlock happens at the end of this function.
5635 if (!peer
->clear_node_queue
->thread
)
5638 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
5639 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
5641 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5642 dest
= bgp_route_next(dest
)) {
5643 table
= bgp_dest_get_bgp_table_info(dest
);
5647 bgp_clear_route_table(peer
, afi
, safi
, table
);
5650 /* unlock if no nodes got added to the clear-node-queue. */
5651 if (!peer
->clear_node_queue
->thread
)
5655 void bgp_clear_route_all(struct peer
*peer
)
5660 FOREACH_AFI_SAFI (afi
, safi
)
5661 bgp_clear_route(peer
, afi
, safi
);
5663 #ifdef ENABLE_BGP_VNC
5664 rfapiProcessPeerDown(peer
);
5668 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5670 struct bgp_table
*table
;
5671 struct bgp_dest
*dest
;
5672 struct bgp_adj_in
*ain
;
5673 struct bgp_adj_in
*ain_next
;
5675 table
= peer
->bgp
->rib
[afi
][safi
];
5677 /* It is possible that we have multiple paths for a prefix from a peer
5678 * if that peer is using AddPath.
5680 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5684 ain_next
= ain
->next
;
5686 if (ain
->peer
== peer
)
5687 bgp_adj_in_remove(dest
, ain
);
5694 /* If any of the routes from the peer have been marked with the NO_LLGR
5695 * community, either as sent by the peer, or as the result of a configured
5696 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5697 * operation of [RFC4271].
5699 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5701 struct bgp_dest
*dest
;
5702 struct bgp_path_info
*pi
;
5703 struct bgp_table
*table
;
5705 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5706 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5707 dest
= bgp_route_next(dest
)) {
5708 struct bgp_dest
*rm
;
5710 /* look for neighbor in tables */
5711 table
= bgp_dest_get_bgp_table_info(dest
);
5715 for (rm
= bgp_table_top(table
); rm
;
5716 rm
= bgp_route_next(rm
))
5717 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
5719 if (pi
->peer
!= peer
)
5722 peer
->af_sflags
[afi
][safi
],
5723 PEER_STATUS_LLGR_WAIT
) &&
5724 bgp_attr_get_community(pi
->attr
) &&
5726 bgp_attr_get_community(
5730 if (!CHECK_FLAG(pi
->flags
,
5735 * If this is VRF leaked route
5736 * process for withdraw.
5739 BGP_ROUTE_IMPORTED
&&
5740 peer
->bgp
->inst_type
==
5741 BGP_INSTANCE_TYPE_DEFAULT
)
5742 vpn_leak_to_vrf_withdraw(pi
);
5744 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
5749 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5750 dest
= bgp_route_next(dest
))
5751 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5753 if (pi
->peer
!= peer
)
5755 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5756 PEER_STATUS_LLGR_WAIT
) &&
5757 bgp_attr_get_community(pi
->attr
) &&
5759 bgp_attr_get_community(pi
->attr
),
5762 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
5764 if (safi
== SAFI_UNICAST
&&
5765 (peer
->bgp
->inst_type
==
5766 BGP_INSTANCE_TYPE_VRF
||
5767 peer
->bgp
->inst_type
==
5768 BGP_INSTANCE_TYPE_DEFAULT
))
5769 vpn_leak_from_vrf_withdraw(
5770 bgp_get_default(), peer
->bgp
,
5773 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5779 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5781 struct bgp_dest
*dest
, *ndest
;
5782 struct bgp_path_info
*pi
;
5783 struct bgp_table
*table
;
5785 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5786 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5787 dest
= bgp_route_next(dest
)) {
5788 table
= bgp_dest_get_bgp_table_info(dest
);
5792 for (ndest
= bgp_table_top(table
); ndest
;
5793 ndest
= bgp_route_next(ndest
)) {
5794 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5796 if (pi
->peer
!= peer
)
5800 peer
->af_sflags
[afi
][safi
],
5801 PEER_STATUS_ENHANCED_REFRESH
))
5802 && !CHECK_FLAG(pi
->flags
,
5806 BGP_PATH_UNUSEABLE
)) {
5807 if (bgp_debug_neighbor_events(
5810 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5814 bgp_dest_get_prefix(
5817 bgp_path_info_set_flag(
5825 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5826 dest
= bgp_route_next(dest
)) {
5827 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5829 if (pi
->peer
!= peer
)
5832 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5833 PEER_STATUS_ENHANCED_REFRESH
))
5834 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5835 && !CHECK_FLAG(pi
->flags
,
5836 BGP_PATH_UNUSEABLE
)) {
5837 if (bgp_debug_neighbor_events(peer
))
5839 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5842 bgp_dest_get_prefix(
5845 bgp_path_info_set_flag(dest
, pi
,
5853 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5855 if (peer
->sort
== BGP_PEER_IBGP
)
5858 if (peer
->sort
== BGP_PEER_EBGP
5859 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5860 || FILTER_LIST_OUT_NAME(filter
)
5861 || DISTRIBUTE_OUT_NAME(filter
)))
5866 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5868 if (peer
->sort
== BGP_PEER_IBGP
)
5871 if (peer
->sort
== BGP_PEER_EBGP
5872 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5873 || FILTER_LIST_IN_NAME(filter
)
5874 || DISTRIBUTE_IN_NAME(filter
)))
5879 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5882 struct bgp_dest
*dest
;
5883 struct bgp_path_info
*pi
;
5884 struct bgp_path_info
*next
;
5886 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5887 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5888 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5892 /* Unimport EVPN routes from VRFs */
5893 if (safi
== SAFI_EVPN
)
5894 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5897 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5898 && pi
->type
== ZEBRA_ROUTE_BGP
5899 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5900 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5901 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5903 if (bgp_fibupd_safi(safi
))
5904 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5907 bgp_path_info_reap(dest
, pi
);
5911 /* Delete all kernel routes. */
5912 void bgp_cleanup_routes(struct bgp
*bgp
)
5915 struct bgp_dest
*dest
;
5916 struct bgp_table
*table
;
5918 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5919 if (afi
== AFI_L2VPN
)
5921 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5924 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5926 if (afi
!= AFI_L2VPN
) {
5928 safi
= SAFI_MPLS_VPN
;
5929 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5930 dest
= bgp_route_next(dest
)) {
5931 table
= bgp_dest_get_bgp_table_info(dest
);
5932 if (table
!= NULL
) {
5933 bgp_cleanup_table(bgp
, table
, safi
);
5934 bgp_table_finish(&table
);
5935 bgp_dest_set_bgp_table_info(dest
, NULL
);
5936 bgp_dest_unlock_node(dest
);
5940 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5941 dest
= bgp_route_next(dest
)) {
5942 table
= bgp_dest_get_bgp_table_info(dest
);
5943 if (table
!= NULL
) {
5944 bgp_cleanup_table(bgp
, table
, safi
);
5945 bgp_table_finish(&table
);
5946 bgp_dest_set_bgp_table_info(dest
, NULL
);
5947 bgp_dest_unlock_node(dest
);
5952 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5953 dest
= bgp_route_next(dest
)) {
5954 table
= bgp_dest_get_bgp_table_info(dest
);
5955 if (table
!= NULL
) {
5956 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5957 bgp_table_finish(&table
);
5958 bgp_dest_set_bgp_table_info(dest
, NULL
);
5959 bgp_dest_unlock_node(dest
);
5964 void bgp_reset(void)
5967 bgp_zclient_reset();
5968 access_list_reset();
5969 prefix_list_reset();
5972 bool bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5974 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5975 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5976 PEER_CAP_ADDPATH_AF_TX_RCV
));
5979 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5981 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5982 struct bgp_nlri
*packet
)
5990 bool addpath_capable
;
5991 uint32_t addpath_id
;
5994 lim
= pnt
+ packet
->length
;
5996 safi
= packet
->safi
;
5998 addpath_capable
= bgp_addpath_encode_rx(peer
, afi
, safi
);
6000 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
6001 syntactic validity. If the field is syntactically incorrect,
6002 then the Error Subcode is set to Invalid Network Field. */
6003 for (; pnt
< lim
; pnt
+= psize
) {
6004 /* Clear prefix structure. */
6005 memset(&p
, 0, sizeof(p
));
6007 if (addpath_capable
) {
6009 /* When packet overflow occurs return immediately. */
6010 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
6011 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
6013 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
6014 addpath_id
= ntohl(addpath_id
);
6015 pnt
+= BGP_ADDPATH_ID_LEN
;
6018 /* Fetch prefix length. */
6019 p
.prefixlen
= *pnt
++;
6020 /* afi/safi validity already verified by caller,
6021 * bgp_update_receive */
6022 p
.family
= afi2family(afi
);
6024 /* Prefix length check. */
6025 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
6028 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
6029 peer
->host
, p
.prefixlen
, packet
->afi
);
6030 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
6033 /* Packet size overflow check. */
6034 psize
= PSIZE(p
.prefixlen
);
6036 /* When packet overflow occur return immediately. */
6037 if (pnt
+ psize
> lim
) {
6040 "%s [Error] Update packet error (prefix length %d overflows packet)",
6041 peer
->host
, p
.prefixlen
);
6042 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
6045 /* Defensive coding, double-check the psize fits in a struct
6046 * prefix for the v4 and v6 afi's and unicast/multicast */
6047 if (psize
> (ssize_t
)sizeof(p
.u
.val
)) {
6050 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
6051 peer
->host
, p
.prefixlen
, sizeof(p
.u
.val
));
6052 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6055 /* Fetch prefix from NLRI packet. */
6056 memcpy(p
.u
.val
, pnt
, psize
);
6058 /* Check address. */
6059 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
6060 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
6061 /* From RFC4271 Section 6.3:
6063 * If a prefix in the NLRI field is semantically
6065 * (e.g., an unexpected multicast IP address),
6067 * be logged locally, and the prefix SHOULD be
6072 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6073 peer
->host
, &p
.u
.prefix4
);
6078 /* Check address. */
6079 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
6080 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6083 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6084 peer
->host
, &p
.u
.prefix6
);
6088 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
6091 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6092 peer
->host
, &p
.u
.prefix6
);
6098 /* Normal process. */
6100 bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
6101 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
,
6104 bgp_withdraw(peer
, &p
, addpath_id
, afi
, safi
,
6105 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
,
6108 /* Do not send BGP notification twice when maximum-prefix count
6110 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
6111 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
6114 /* Packet length consistency check. */
6118 "%s [Error] Update packet error (prefix length mismatch with total length)",
6120 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6123 return BGP_NLRI_PARSE_OK
;
6126 static struct bgp_static
*bgp_static_new(void)
6128 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
6131 static void bgp_static_free(struct bgp_static
*bgp_static
)
6133 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6134 route_map_counter_decrement(bgp_static
->rmap
.map
);
6136 if (bgp_static
->prd_pretty
)
6137 XFREE(MTYPE_BGP
, bgp_static
->prd_pretty
);
6138 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
6139 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
6142 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
6143 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
6145 struct bgp_dest
*dest
;
6146 struct bgp_path_info
*pi
;
6147 struct bgp_path_info
*new;
6148 struct bgp_path_info rmap_path
;
6150 struct attr
*attr_new
;
6151 route_map_result_t ret
;
6152 #ifdef ENABLE_BGP_VNC
6153 int vnc_implicit_withdraw
= 0;
6158 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6160 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6162 attr
.nexthop
= bgp_static
->igpnexthop
;
6163 attr
.med
= bgp_static
->igpmetric
;
6164 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6167 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
6169 if (bgp_static
->igpmetric
)
6170 bgp_attr_set_aigp_metric(&attr
, bgp_static
->igpmetric
);
6172 if (bgp_static
->atomic
)
6173 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
6175 /* Store label index, if required. */
6176 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
6177 attr
.label_index
= bgp_static
->label_index
;
6178 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
6181 /* Apply route-map. */
6182 if (bgp_static
->rmap
.name
) {
6183 struct attr attr_tmp
= attr
;
6185 memset(&rmap_path
, 0, sizeof(rmap_path
));
6186 rmap_path
.peer
= bgp
->peer_self
;
6187 rmap_path
.attr
= &attr_tmp
;
6189 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6191 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6193 bgp
->peer_self
->rmap_type
= 0;
6195 if (ret
== RMAP_DENYMATCH
) {
6196 /* Free uninterned attribute. */
6197 bgp_attr_flush(&attr_tmp
);
6199 /* Unintern original. */
6200 aspath_unintern(&attr
.aspath
);
6201 bgp_static_withdraw(bgp
, p
, afi
, safi
);
6202 bgp_dest_unlock_node(dest
);
6206 if (bgp_in_graceful_shutdown(bgp
))
6207 bgp_attr_add_gshut_community(&attr_tmp
);
6209 attr_new
= bgp_attr_intern(&attr_tmp
);
6212 if (bgp_in_graceful_shutdown(bgp
))
6213 bgp_attr_add_gshut_community(&attr
);
6215 attr_new
= bgp_attr_intern(&attr
);
6218 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6219 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6220 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6224 if (attrhash_cmp(pi
->attr
, attr_new
)
6225 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
6226 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
6227 bgp_dest_unlock_node(dest
);
6228 bgp_attr_unintern(&attr_new
);
6229 aspath_unintern(&attr
.aspath
);
6232 /* The attribute is changed. */
6233 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6235 /* Rewrite BGP route information. */
6236 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6237 bgp_path_info_restore(dest
, pi
);
6239 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6240 #ifdef ENABLE_BGP_VNC
6241 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6242 && (safi
== SAFI_UNICAST
)) {
6243 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
6245 * Implicit withdraw case.
6246 * We have to do this before pi is
6249 ++vnc_implicit_withdraw
;
6250 vnc_import_bgp_del_route(bgp
, p
, pi
);
6251 vnc_import_bgp_exterior_del_route(
6256 bgp_attr_unintern(&pi
->attr
);
6257 pi
->attr
= attr_new
;
6258 pi
->uptime
= monotime(NULL
);
6259 #ifdef ENABLE_BGP_VNC
6260 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6261 && (safi
== SAFI_UNICAST
)) {
6262 if (vnc_implicit_withdraw
) {
6263 vnc_import_bgp_add_route(bgp
, p
, pi
);
6264 vnc_import_bgp_exterior_add_route(
6270 /* Nexthop reachability check. */
6271 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6272 && (safi
== SAFI_UNICAST
6273 || safi
== SAFI_LABELED_UNICAST
)) {
6275 struct bgp
*bgp_nexthop
= bgp
;
6277 if (pi
->extra
&& pi
->extra
->bgp_orig
)
6278 bgp_nexthop
= pi
->extra
->bgp_orig
;
6280 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
6281 afi
, safi
, pi
, NULL
,
6283 bgp_path_info_set_flag(dest
, pi
,
6286 if (BGP_DEBUG(nht
, NHT
)) {
6287 char buf1
[INET6_ADDRSTRLEN
];
6288 inet_ntop(p
->family
,
6292 "%s(%s): Route not in table, not advertising",
6295 bgp_path_info_unset_flag(
6296 dest
, pi
, BGP_PATH_VALID
);
6299 /* Delete the NHT structure if any, if we're
6301 * enabling/disabling import check. We
6302 * deregister the route
6303 * from NHT to avoid overloading NHT and the
6304 * process interaction
6306 bgp_unlink_nexthop(pi
);
6307 bgp_path_info_set_flag(dest
, pi
,
6310 /* Process change. */
6311 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6312 bgp_process(bgp
, dest
, afi
, safi
);
6314 if (SAFI_UNICAST
== safi
6315 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6317 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6318 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
6322 bgp_dest_unlock_node(dest
);
6323 aspath_unintern(&attr
.aspath
);
6328 /* Make new BGP info. */
6329 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6331 /* Nexthop reachability check. */
6332 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6333 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
6334 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0,
6336 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6338 if (BGP_DEBUG(nht
, NHT
)) {
6339 char buf1
[INET6_ADDRSTRLEN
];
6341 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
6344 "%s(%s): Route not in table, not advertising",
6347 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
6350 /* Delete the NHT structure if any, if we're toggling between
6351 * enabling/disabling import check. We deregister the route
6352 * from NHT to avoid overloading NHT and the process interaction
6354 bgp_unlink_nexthop(new);
6356 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6359 /* Aggregate address increment. */
6360 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6362 /* Register new BGP information. */
6363 bgp_path_info_add(dest
, new);
6365 /* route_node_get lock */
6366 bgp_dest_unlock_node(dest
);
6368 /* Process change. */
6369 bgp_process(bgp
, dest
, afi
, safi
);
6371 if (SAFI_UNICAST
== safi
6372 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6373 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6374 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6377 /* Unintern original. */
6378 aspath_unintern(&attr
.aspath
);
6381 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6384 struct bgp_dest
*dest
;
6385 struct bgp_path_info
*pi
;
6387 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6389 /* Check selected route and self inserted route. */
6390 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6391 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6392 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6395 /* Withdraw static BGP route from routing table. */
6397 if (SAFI_UNICAST
== safi
6398 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6399 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6400 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
6402 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6403 bgp_unlink_nexthop(pi
);
6404 bgp_path_info_delete(dest
, pi
);
6405 bgp_process(bgp
, dest
, afi
, safi
);
6408 /* Unlock bgp_node_lookup. */
6409 bgp_dest_unlock_node(dest
);
6413 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6415 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
6416 afi_t afi
, safi_t safi
,
6417 struct prefix_rd
*prd
)
6419 struct bgp_dest
*dest
;
6420 struct bgp_path_info
*pi
;
6422 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
6424 /* Check selected route and self inserted route. */
6425 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6426 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6427 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6430 /* Withdraw static BGP route from routing table. */
6432 #ifdef ENABLE_BGP_VNC
6433 rfapiProcessWithdraw(
6434 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
6435 1); /* Kill, since it is an administrative change */
6437 if (SAFI_MPLS_VPN
== safi
6438 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6439 vpn_leak_to_vrf_withdraw(pi
);
6441 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6442 bgp_path_info_delete(dest
, pi
);
6443 bgp_process(bgp
, dest
, afi
, safi
);
6446 /* Unlock bgp_node_lookup. */
6447 bgp_dest_unlock_node(dest
);
6450 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
6451 struct bgp_static
*bgp_static
, afi_t afi
,
6454 struct bgp_dest
*dest
;
6455 struct bgp_path_info
*new;
6456 struct attr
*attr_new
;
6457 struct attr attr
= {0};
6458 struct bgp_path_info
*pi
;
6459 #ifdef ENABLE_BGP_VNC
6460 mpls_label_t label
= 0;
6462 uint32_t num_labels
= 0;
6466 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
6468 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
6471 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6473 attr
.nexthop
= bgp_static
->igpnexthop
;
6474 attr
.med
= bgp_static
->igpmetric
;
6475 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6477 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
6478 || (safi
== SAFI_ENCAP
)) {
6479 if (afi
== AFI_IP
) {
6480 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
6481 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
6484 if (afi
== AFI_L2VPN
) {
6485 if (bgp_static
->gatewayIp
.family
== AF_INET
) {
6486 SET_IPADDR_V4(&attr
.evpn_overlay
.gw_ip
);
6487 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v4
,
6488 &bgp_static
->gatewayIp
.u
.prefix4
,
6490 } else if (bgp_static
->gatewayIp
.family
== AF_INET6
) {
6491 SET_IPADDR_V6(&attr
.evpn_overlay
.gw_ip
);
6492 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v6
,
6493 &bgp_static
->gatewayIp
.u
.prefix6
,
6496 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
6497 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
6498 struct bgp_encap_type_vxlan bet
;
6499 memset(&bet
, 0, sizeof(bet
));
6500 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
6501 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
6503 if (bgp_static
->router_mac
) {
6504 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
6507 /* Apply route-map. */
6508 if (bgp_static
->rmap
.name
) {
6509 struct attr attr_tmp
= attr
;
6510 struct bgp_path_info rmap_path
;
6511 route_map_result_t ret
;
6513 rmap_path
.peer
= bgp
->peer_self
;
6514 rmap_path
.attr
= &attr_tmp
;
6516 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6518 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6520 bgp
->peer_self
->rmap_type
= 0;
6522 if (ret
== RMAP_DENYMATCH
) {
6523 /* Free uninterned attribute. */
6524 bgp_attr_flush(&attr_tmp
);
6526 /* Unintern original. */
6527 aspath_unintern(&attr
.aspath
);
6528 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
6530 bgp_dest_unlock_node(dest
);
6534 attr_new
= bgp_attr_intern(&attr_tmp
);
6536 attr_new
= bgp_attr_intern(&attr
);
6539 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6540 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6541 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6545 if (attrhash_cmp(pi
->attr
, attr_new
)
6546 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
6547 bgp_dest_unlock_node(dest
);
6548 bgp_attr_unintern(&attr_new
);
6549 aspath_unintern(&attr
.aspath
);
6552 /* The attribute is changed. */
6553 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6555 /* Rewrite BGP route information. */
6556 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6557 bgp_path_info_restore(dest
, pi
);
6559 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6560 bgp_attr_unintern(&pi
->attr
);
6561 pi
->attr
= attr_new
;
6562 pi
->uptime
= monotime(NULL
);
6563 #ifdef ENABLE_BGP_VNC
6565 label
= decode_label(&pi
->extra
->label
[0]);
6568 /* Process change. */
6569 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6570 bgp_process(bgp
, dest
, afi
, safi
);
6572 if (SAFI_MPLS_VPN
== safi
6573 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6574 vpn_leak_to_vrf_update(bgp
, pi
,
6577 #ifdef ENABLE_BGP_VNC
6578 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
6579 pi
->attr
, afi
, safi
, pi
->type
,
6580 pi
->sub_type
, &label
);
6582 bgp_dest_unlock_node(dest
);
6583 aspath_unintern(&attr
.aspath
);
6589 /* Make new BGP info. */
6590 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6592 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6593 bgp_path_info_extra_get(new);
6595 new->extra
->label
[0] = bgp_static
->label
;
6596 new->extra
->num_labels
= num_labels
;
6598 #ifdef ENABLE_BGP_VNC
6599 label
= decode_label(&bgp_static
->label
);
6602 /* Aggregate address increment. */
6603 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6605 /* Register new BGP information. */
6606 bgp_path_info_add(dest
, new);
6607 /* route_node_get lock */
6608 bgp_dest_unlock_node(dest
);
6610 /* Process change. */
6611 bgp_process(bgp
, dest
, afi
, safi
);
6613 if (SAFI_MPLS_VPN
== safi
6614 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6615 vpn_leak_to_vrf_update(bgp
, new, &bgp_static
->prd
);
6617 #ifdef ENABLE_BGP_VNC
6618 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6619 safi
, new->type
, new->sub_type
, &label
);
6622 /* Unintern original. */
6623 aspath_unintern(&attr
.aspath
);
6626 /* Configure static BGP network. When user don't run zebra, static
6627 route should be installed as valid. */
6628 static int bgp_static_set(struct vty
*vty
, const char *negate
,
6629 const char *ip_str
, afi_t afi
, safi_t safi
,
6630 const char *rmap
, int backdoor
, uint32_t label_index
)
6632 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6635 struct bgp_static
*bgp_static
;
6636 struct bgp_dest
*dest
;
6637 uint8_t need_update
= 0;
6639 /* Convert IP prefix string to struct prefix. */
6640 ret
= str2prefix(ip_str
, &p
);
6642 vty_out(vty
, "%% Malformed prefix\n");
6643 return CMD_WARNING_CONFIG_FAILED
;
6645 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6646 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
6647 return CMD_WARNING_CONFIG_FAILED
;
6654 /* Set BGP static route configuration. */
6655 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6658 vty_out(vty
, "%% Can't find static route specified\n");
6659 return CMD_WARNING_CONFIG_FAILED
;
6662 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6664 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6665 && (label_index
!= bgp_static
->label_index
)) {
6667 "%% label-index doesn't match static route\n");
6668 bgp_dest_unlock_node(dest
);
6669 return CMD_WARNING_CONFIG_FAILED
;
6672 if ((rmap
&& bgp_static
->rmap
.name
)
6673 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6675 "%% route-map name doesn't match static route\n");
6676 bgp_dest_unlock_node(dest
);
6677 return CMD_WARNING_CONFIG_FAILED
;
6680 /* Update BGP RIB. */
6681 if (!bgp_static
->backdoor
)
6682 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6684 /* Clear configuration. */
6685 bgp_static_free(bgp_static
);
6686 bgp_dest_set_bgp_static_info(dest
, NULL
);
6687 bgp_dest_unlock_node(dest
);
6688 bgp_dest_unlock_node(dest
);
6691 /* Set BGP static route configuration. */
6692 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6693 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6695 /* Configuration change. */
6696 /* Label index cannot be changed. */
6697 if (bgp_static
->label_index
!= label_index
) {
6698 vty_out(vty
, "%% cannot change label-index\n");
6699 bgp_dest_unlock_node(dest
);
6700 return CMD_WARNING_CONFIG_FAILED
;
6703 /* Check previous routes are installed into BGP. */
6704 if (bgp_static
->valid
6705 && bgp_static
->backdoor
!= backdoor
)
6708 bgp_static
->backdoor
= backdoor
;
6711 XFREE(MTYPE_ROUTE_MAP_NAME
,
6712 bgp_static
->rmap
.name
);
6713 route_map_counter_decrement(
6714 bgp_static
->rmap
.map
);
6715 bgp_static
->rmap
.name
=
6716 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6717 bgp_static
->rmap
.map
=
6718 route_map_lookup_by_name(rmap
);
6719 route_map_counter_increment(
6720 bgp_static
->rmap
.map
);
6722 XFREE(MTYPE_ROUTE_MAP_NAME
,
6723 bgp_static
->rmap
.name
);
6724 route_map_counter_decrement(
6725 bgp_static
->rmap
.map
);
6726 bgp_static
->rmap
.map
= NULL
;
6727 bgp_static
->valid
= 0;
6729 bgp_dest_unlock_node(dest
);
6731 /* New configuration. */
6732 bgp_static
= bgp_static_new();
6733 bgp_static
->backdoor
= backdoor
;
6734 bgp_static
->valid
= 0;
6735 bgp_static
->igpmetric
= 0;
6736 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6737 bgp_static
->label_index
= label_index
;
6740 XFREE(MTYPE_ROUTE_MAP_NAME
,
6741 bgp_static
->rmap
.name
);
6742 route_map_counter_decrement(
6743 bgp_static
->rmap
.map
);
6744 bgp_static
->rmap
.name
=
6745 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6746 bgp_static
->rmap
.map
=
6747 route_map_lookup_by_name(rmap
);
6748 route_map_counter_increment(
6749 bgp_static
->rmap
.map
);
6751 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6754 bgp_static
->valid
= 1;
6756 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6758 if (!bgp_static
->backdoor
)
6759 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6765 void bgp_static_add(struct bgp
*bgp
)
6769 struct bgp_dest
*dest
;
6770 struct bgp_dest
*rm
;
6771 struct bgp_table
*table
;
6772 struct bgp_static
*bgp_static
;
6774 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6775 FOREACH_AFI_SAFI (afi
, safi
)
6776 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6777 dest
= bgp_route_next(dest
)) {
6778 if (!bgp_dest_has_bgp_path_info_data(dest
))
6781 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6782 || (safi
== SAFI_EVPN
)) {
6783 table
= bgp_dest_get_bgp_table_info(dest
);
6785 for (rm
= bgp_table_top(table
); rm
;
6786 rm
= bgp_route_next(rm
)) {
6788 bgp_dest_get_bgp_static_info(
6790 bgp_static_update_safi(
6791 bgp
, bgp_dest_get_prefix(rm
),
6792 bgp_static
, afi
, safi
);
6796 bgp
, bgp_dest_get_prefix(dest
),
6797 bgp_dest_get_bgp_static_info(dest
), afi
,
6801 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6804 /* Called from bgp_delete(). Delete all static routes from the BGP
6806 void bgp_static_delete(struct bgp
*bgp
)
6810 struct bgp_dest
*dest
;
6811 struct bgp_dest
*rm
;
6812 struct bgp_table
*table
;
6813 struct bgp_static
*bgp_static
;
6815 FOREACH_AFI_SAFI (afi
, safi
)
6816 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6817 dest
= bgp_route_next(dest
)) {
6818 if (!bgp_dest_has_bgp_path_info_data(dest
))
6821 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6822 || (safi
== SAFI_EVPN
)) {
6823 table
= bgp_dest_get_bgp_table_info(dest
);
6825 for (rm
= bgp_table_top(table
); rm
;
6826 rm
= bgp_route_next(rm
)) {
6828 bgp_dest_get_bgp_static_info(
6833 bgp_static_withdraw_safi(
6834 bgp
, bgp_dest_get_prefix(rm
),
6836 (struct prefix_rd
*)
6837 bgp_dest_get_prefix(
6839 bgp_static_free(bgp_static
);
6840 bgp_dest_set_bgp_static_info(rm
,
6842 bgp_dest_unlock_node(rm
);
6845 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6846 bgp_static_withdraw(bgp
,
6847 bgp_dest_get_prefix(dest
),
6849 bgp_static_free(bgp_static
);
6850 bgp_dest_set_bgp_static_info(dest
, NULL
);
6851 bgp_dest_unlock_node(dest
);
6856 void bgp_static_redo_import_check(struct bgp
*bgp
)
6860 struct bgp_dest
*dest
;
6861 struct bgp_dest
*rm
;
6862 struct bgp_table
*table
;
6863 struct bgp_static
*bgp_static
;
6865 /* Use this flag to force reprocessing of the route */
6866 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6867 FOREACH_AFI_SAFI (afi
, safi
) {
6868 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6869 dest
= bgp_route_next(dest
)) {
6870 if (!bgp_dest_has_bgp_path_info_data(dest
))
6873 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6874 || (safi
== SAFI_EVPN
)) {
6875 table
= bgp_dest_get_bgp_table_info(dest
);
6877 for (rm
= bgp_table_top(table
); rm
;
6878 rm
= bgp_route_next(rm
)) {
6880 bgp_dest_get_bgp_static_info(
6882 bgp_static_update_safi(
6883 bgp
, bgp_dest_get_prefix(rm
),
6884 bgp_static
, afi
, safi
);
6887 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6888 bgp_static_update(bgp
,
6889 bgp_dest_get_prefix(dest
),
6890 bgp_static
, afi
, safi
);
6894 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6897 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6900 struct bgp_table
*table
;
6901 struct bgp_dest
*dest
;
6902 struct bgp_path_info
*pi
;
6904 /* Do not install the aggregate route if BGP is in the
6905 * process of termination.
6907 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6908 || (bgp
->peer_self
== NULL
))
6911 table
= bgp
->rib
[afi
][safi
];
6912 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6913 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6914 if (pi
->peer
== bgp
->peer_self
6915 && ((pi
->type
== ZEBRA_ROUTE_BGP
6916 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6917 || (pi
->type
!= ZEBRA_ROUTE_BGP
6919 == BGP_ROUTE_REDISTRIBUTE
))) {
6920 bgp_aggregate_decrement(
6921 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6923 bgp_unlink_nexthop(pi
);
6924 bgp_path_info_delete(dest
, pi
);
6925 bgp_process(bgp
, dest
, afi
, safi
);
6932 * Purge all networks and redistributed routes from routing table.
6933 * Invoked upon the instance going down.
6935 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6940 FOREACH_AFI_SAFI (afi
, safi
)
6941 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6946 * Currently this is used to set static routes for VPN and ENCAP.
6947 * I think it can probably be factored with bgp_static_set.
6949 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6950 const char *ip_str
, const char *rd_str
,
6951 const char *label_str
, const char *rmap_str
,
6952 int evpn_type
, const char *esi
, const char *gwip
,
6953 const char *ethtag
, const char *routermac
)
6955 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6958 struct prefix_rd prd
;
6959 struct bgp_dest
*pdest
;
6960 struct bgp_dest
*dest
;
6961 struct bgp_table
*table
;
6962 struct bgp_static
*bgp_static
;
6963 mpls_label_t label
= MPLS_INVALID_LABEL
;
6964 struct prefix gw_ip
;
6966 /* validate ip prefix */
6967 ret
= str2prefix(ip_str
, &p
);
6969 vty_out(vty
, "%% Malformed prefix\n");
6970 return CMD_WARNING_CONFIG_FAILED
;
6973 if ((afi
== AFI_L2VPN
)
6974 && (bgp_build_evpn_prefix(evpn_type
,
6975 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6976 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6977 return CMD_WARNING_CONFIG_FAILED
;
6980 ret
= str2prefix_rd(rd_str
, &prd
);
6982 vty_out(vty
, "%% Malformed rd\n");
6983 return CMD_WARNING_CONFIG_FAILED
;
6987 unsigned long label_val
;
6988 label_val
= strtoul(label_str
, NULL
, 10);
6989 encode_label(label_val
, &label
);
6992 if (safi
== SAFI_EVPN
) {
6993 if (esi
&& str2esi(esi
, NULL
) == 0) {
6994 vty_out(vty
, "%% Malformed ESI\n");
6995 return CMD_WARNING_CONFIG_FAILED
;
6997 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6998 vty_out(vty
, "%% Malformed Router MAC\n");
6999 return CMD_WARNING_CONFIG_FAILED
;
7002 memset(&gw_ip
, 0, sizeof(gw_ip
));
7003 ret
= str2prefix(gwip
, &gw_ip
);
7005 vty_out(vty
, "%% Malformed GatewayIp\n");
7006 return CMD_WARNING_CONFIG_FAILED
;
7008 if ((gw_ip
.family
== AF_INET
7009 && is_evpn_prefix_ipaddr_v6(
7010 (struct prefix_evpn
*)&p
))
7011 || (gw_ip
.family
== AF_INET6
7012 && is_evpn_prefix_ipaddr_v4(
7013 (struct prefix_evpn
*)&p
))) {
7015 "%% GatewayIp family differs with IP prefix\n");
7016 return CMD_WARNING_CONFIG_FAILED
;
7020 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7021 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7022 bgp_dest_set_bgp_table_info(pdest
,
7023 bgp_table_init(bgp
, afi
, safi
));
7024 table
= bgp_dest_get_bgp_table_info(pdest
);
7026 dest
= bgp_node_get(table
, &p
);
7028 if (bgp_dest_has_bgp_path_info_data(dest
)) {
7029 vty_out(vty
, "%% Same network configuration exists\n");
7030 bgp_dest_unlock_node(dest
);
7032 /* New configuration. */
7033 bgp_static
= bgp_static_new();
7034 bgp_static
->backdoor
= 0;
7035 bgp_static
->valid
= 0;
7036 bgp_static
->igpmetric
= 0;
7037 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
7038 bgp_static
->label
= label
;
7039 bgp_static
->prd
= prd
;
7041 bgp_static
->prd_pretty
= XSTRDUP(MTYPE_BGP
, rd_str
);
7044 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
7045 route_map_counter_decrement(bgp_static
->rmap
.map
);
7046 bgp_static
->rmap
.name
=
7047 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
7048 bgp_static
->rmap
.map
=
7049 route_map_lookup_by_name(rmap_str
);
7050 route_map_counter_increment(bgp_static
->rmap
.map
);
7053 if (safi
== SAFI_EVPN
) {
7055 bgp_static
->eth_s_id
=
7058 str2esi(esi
, bgp_static
->eth_s_id
);
7061 bgp_static
->router_mac
=
7062 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
7063 (void)prefix_str2mac(routermac
,
7064 bgp_static
->router_mac
);
7067 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
7069 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
7071 bgp_static
->valid
= 1;
7072 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
7078 /* Configure static BGP network. */
7079 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
7080 const char *ip_str
, const char *rd_str
,
7081 const char *label_str
, int evpn_type
, const char *esi
,
7082 const char *gwip
, const char *ethtag
)
7084 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7087 struct prefix_rd prd
;
7088 struct bgp_dest
*pdest
;
7089 struct bgp_dest
*dest
;
7090 struct bgp_table
*table
;
7091 struct bgp_static
*bgp_static
;
7092 mpls_label_t label
= MPLS_INVALID_LABEL
;
7094 /* Convert IP prefix string to struct prefix. */
7095 ret
= str2prefix(ip_str
, &p
);
7097 vty_out(vty
, "%% Malformed prefix\n");
7098 return CMD_WARNING_CONFIG_FAILED
;
7101 if ((afi
== AFI_L2VPN
)
7102 && (bgp_build_evpn_prefix(evpn_type
,
7103 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
7104 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
7105 return CMD_WARNING_CONFIG_FAILED
;
7107 ret
= str2prefix_rd(rd_str
, &prd
);
7109 vty_out(vty
, "%% Malformed rd\n");
7110 return CMD_WARNING_CONFIG_FAILED
;
7114 unsigned long label_val
;
7115 label_val
= strtoul(label_str
, NULL
, 10);
7116 encode_label(label_val
, &label
);
7119 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7120 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7121 bgp_dest_set_bgp_table_info(pdest
,
7122 bgp_table_init(bgp
, afi
, safi
));
7124 bgp_dest_unlock_node(pdest
);
7125 table
= bgp_dest_get_bgp_table_info(pdest
);
7127 dest
= bgp_node_lookup(table
, &p
);
7130 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
7132 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
7133 bgp_static_free(bgp_static
);
7134 bgp_dest_set_bgp_static_info(dest
, NULL
);
7135 bgp_dest_unlock_node(dest
);
7136 bgp_dest_unlock_node(dest
);
7138 vty_out(vty
, "%% Can't find the route\n");
7143 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
7144 const char *rmap_name
)
7146 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7147 struct bgp_rmap
*rmap
;
7149 rmap
= &bgp
->table_map
[afi
][safi
];
7151 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7152 route_map_counter_decrement(rmap
->map
);
7153 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
7154 rmap
->map
= route_map_lookup_by_name(rmap_name
);
7155 route_map_counter_increment(rmap
->map
);
7157 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7158 route_map_counter_decrement(rmap
->map
);
7162 if (bgp_fibupd_safi(safi
))
7163 bgp_zebra_announce_table(bgp
, afi
, safi
);
7168 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
7169 const char *rmap_name
)
7171 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7172 struct bgp_rmap
*rmap
;
7174 rmap
= &bgp
->table_map
[afi
][safi
];
7175 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7176 route_map_counter_decrement(rmap
->map
);
7179 if (bgp_fibupd_safi(safi
))
7180 bgp_zebra_announce_table(bgp
, afi
, safi
);
7185 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
7188 if (bgp
->table_map
[afi
][safi
].name
) {
7189 vty_out(vty
, " table-map %s\n",
7190 bgp
->table_map
[afi
][safi
].name
);
7194 DEFUN (bgp_table_map
,
7197 "BGP table to RIB route download filter\n"
7198 "Name of the route map\n")
7201 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7202 argv
[idx_word
]->arg
);
7204 DEFUN (no_bgp_table_map
,
7205 no_bgp_table_map_cmd
,
7206 "no table-map WORD",
7208 "BGP table to RIB route download filter\n"
7209 "Name of the route map\n")
7212 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7213 argv
[idx_word
]->arg
);
7219 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
7220 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
7221 backdoor$backdoor}]",
7223 "Specify a network to announce via BGP\n"
7228 "Route-map to modify the attributes\n"
7229 "Name of the route map\n"
7230 "Label index to associate with the prefix\n"
7231 "Label index value\n"
7232 "Specify a BGP backdoor route\n")
7234 char addr_prefix_str
[BUFSIZ
];
7239 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
7241 sizeof(addr_prefix_str
));
7243 vty_out(vty
, "%% Inconsistent address and mask\n");
7244 return CMD_WARNING_CONFIG_FAILED
;
7248 return bgp_static_set(
7249 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
7250 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
7251 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7254 DEFPY(ipv6_bgp_network
,
7255 ipv6_bgp_network_cmd
,
7256 "[no] network X:X::X:X/M$prefix \
7257 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
7259 "Specify a network to announce via BGP\n"
7261 "Route-map to modify the attributes\n"
7262 "Name of the route map\n"
7263 "Label index to associate with the prefix\n"
7264 "Label index value\n")
7266 return bgp_static_set(
7267 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
7268 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7271 static struct bgp_aggregate
*bgp_aggregate_new(void)
7273 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
7276 void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
7278 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7279 route_map_counter_decrement(aggregate
->suppress_map
);
7280 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7281 route_map_counter_decrement(aggregate
->rmap
.map
);
7282 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
7286 * Helper function to avoid repeated code: prepare variables for a
7287 * `route_map_apply` call.
7289 * \returns `true` on route map match, otherwise `false`.
7291 static bool aggr_suppress_map_test(struct bgp
*bgp
,
7292 struct bgp_aggregate
*aggregate
,
7293 struct bgp_path_info
*pi
)
7295 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
7296 route_map_result_t rmr
= RMAP_DENYMATCH
;
7297 struct bgp_path_info rmap_path
= {};
7298 struct attr attr
= {};
7300 /* No route map entries created, just don't match. */
7301 if (aggregate
->suppress_map
== NULL
)
7304 /* Call route map matching and return result. */
7305 attr
.aspath
= aspath_empty(bgp
->asnotation
);
7306 rmap_path
.peer
= bgp
->peer_self
;
7307 rmap_path
.attr
= &attr
;
7309 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
7310 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
7311 bgp
->peer_self
->rmap_type
= 0;
7313 bgp_attr_flush(&attr
);
7314 aspath_unintern(&attr
.aspath
);
7316 return rmr
== RMAP_PERMITMATCH
;
7319 /** Test whether the aggregation has suppressed this path or not. */
7320 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
7321 struct bgp_path_info
*pi
)
7323 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
7326 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
7330 * Suppress this path and keep the reference.
7332 * \returns `true` if needs processing otherwise `false`.
7334 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
7335 struct bgp_path_info
*pi
)
7337 struct bgp_path_info_extra
*pie
;
7339 /* Path is already suppressed by this aggregation. */
7340 if (aggr_suppress_exists(aggregate
, pi
))
7343 pie
= bgp_path_info_extra_get(pi
);
7345 /* This is the first suppression, allocate memory and list it. */
7346 if (pie
->aggr_suppressors
== NULL
)
7347 pie
->aggr_suppressors
= list_new();
7349 listnode_add(pie
->aggr_suppressors
, aggregate
);
7351 /* Only mark for processing if suppressed. */
7352 if (listcount(pie
->aggr_suppressors
) == 1) {
7353 if (BGP_DEBUG(update
, UPDATE_OUT
))
7354 zlog_debug("aggregate-address suppressing: %pFX",
7355 bgp_dest_get_prefix(pi
->net
));
7357 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7365 * Unsuppress this path and remove the reference.
7367 * \returns `true` if needs processing otherwise `false`.
7369 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
7370 struct bgp_path_info
*pi
)
7372 /* Path wasn't suppressed. */
7373 if (!aggr_suppress_exists(aggregate
, pi
))
7376 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
7378 /* Unsuppress and free extra memory if last item. */
7379 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
7380 if (BGP_DEBUG(update
, UPDATE_OUT
))
7381 zlog_debug("aggregate-address unsuppressing: %pFX",
7382 bgp_dest_get_prefix(pi
->net
));
7384 list_delete(&pi
->extra
->aggr_suppressors
);
7385 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7392 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
7393 struct aspath
*aspath
,
7394 struct community
*comm
,
7395 struct ecommunity
*ecomm
,
7396 struct lcommunity
*lcomm
)
7398 static struct aspath
*ae
= NULL
;
7399 enum asnotation_mode asnotation
;
7401 asnotation
= bgp_get_asnotation(NULL
);
7404 ae
= aspath_empty(asnotation
);
7409 if (origin
!= pi
->attr
->origin
)
7412 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
7415 if (!community_cmp(bgp_attr_get_community(pi
->attr
), comm
))
7418 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi
->attr
), ecomm
))
7421 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi
->attr
), lcomm
))
7424 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
7430 static void bgp_aggregate_install(
7431 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
7432 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
7433 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
7434 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
7436 struct bgp_dest
*dest
;
7437 struct bgp_table
*table
;
7438 struct bgp_path_info
*pi
, *orig
, *new;
7441 table
= bgp
->rib
[afi
][safi
];
7443 dest
= bgp_node_get(table
, p
);
7445 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7446 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
7447 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7451 * If we have paths with different MEDs, then don't install
7452 * (or uninstall) the aggregate route.
7454 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
7455 goto uninstall_aggregate_route
;
7457 if (aggregate
->count
> 0) {
7459 * If the aggregate information has not changed
7460 * no need to re-install it again.
7462 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
7463 ecommunity
, lcommunity
)) {
7464 bgp_dest_unlock_node(dest
);
7467 aspath_free(aspath
);
7469 community_free(&community
);
7471 ecommunity_free(&ecommunity
);
7473 lcommunity_free(&lcommunity
);
7479 * Mark the old as unusable
7482 bgp_path_info_delete(dest
, pi
);
7484 attr
= bgp_attr_aggregate_intern(
7485 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
7486 aggregate
, atomic_aggregate
, p
);
7489 aspath_free(aspath
);
7490 community_free(&community
);
7491 ecommunity_free(&ecommunity
);
7492 lcommunity_free(&lcommunity
);
7493 bgp_dest_unlock_node(dest
);
7494 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
7495 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
7496 zlog_debug("%s: %pFX null attribute", __func__
,
7501 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
7502 bgp
->peer_self
, attr
, dest
);
7504 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7506 bgp_path_info_add(dest
, new);
7507 bgp_process(bgp
, dest
, afi
, safi
);
7509 uninstall_aggregate_route
:
7510 for (pi
= orig
; pi
; pi
= pi
->next
)
7511 if (pi
->peer
== bgp
->peer_self
7512 && pi
->type
== ZEBRA_ROUTE_BGP
7513 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7516 /* Withdraw static BGP route from routing table. */
7518 bgp_path_info_delete(dest
, pi
);
7519 bgp_process(bgp
, dest
, afi
, safi
);
7523 bgp_dest_unlock_node(dest
);
7527 * Check if the current path has different MED than other known paths.
7529 * \returns `true` if the MED matched the others else `false`.
7531 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
7532 struct bgp
*bgp
, struct bgp_path_info
*pi
)
7534 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
7536 /* This is the first route being analyzed. */
7537 if (!aggregate
->med_initialized
) {
7538 aggregate
->med_initialized
= true;
7539 aggregate
->med_mismatched
= false;
7540 aggregate
->med_matched_value
= cur_med
;
7542 /* Check if routes with different MED showed up. */
7543 if (cur_med
!= aggregate
->med_matched_value
)
7544 aggregate
->med_mismatched
= true;
7547 return !aggregate
->med_mismatched
;
7551 * Initializes and tests all routes in the aggregate address path for MED
7554 * \returns `true` if all MEDs are the same otherwise `false`.
7556 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
7557 struct bgp
*bgp
, const struct prefix
*p
,
7558 afi_t afi
, safi_t safi
)
7560 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7561 const struct prefix
*dest_p
;
7562 struct bgp_dest
*dest
, *top
;
7563 struct bgp_path_info
*pi
;
7564 bool med_matched
= true;
7566 aggregate
->med_initialized
= false;
7568 top
= bgp_node_get(table
, p
);
7569 for (dest
= bgp_node_get(table
, p
); dest
;
7570 dest
= bgp_route_next_until(dest
, top
)) {
7571 dest_p
= bgp_dest_get_prefix(dest
);
7572 if (dest_p
->prefixlen
<= p
->prefixlen
)
7575 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7576 if (BGP_PATH_HOLDDOWN(pi
))
7578 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7580 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
7581 med_matched
= false;
7588 bgp_dest_unlock_node(top
);
7594 * Toggles the route suppression status for this aggregate address
7597 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
7598 struct bgp
*bgp
, const struct prefix
*p
,
7599 afi_t afi
, safi_t safi
, bool suppress
)
7601 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7602 const struct prefix
*dest_p
;
7603 struct bgp_dest
*dest
, *top
;
7604 struct bgp_path_info
*pi
;
7605 bool toggle_suppression
;
7607 /* We've found a different MED we must revert any suppressed routes. */
7608 top
= bgp_node_get(table
, p
);
7609 for (dest
= bgp_node_get(table
, p
); dest
;
7610 dest
= bgp_route_next_until(dest
, top
)) {
7611 dest_p
= bgp_dest_get_prefix(dest
);
7612 if (dest_p
->prefixlen
<= p
->prefixlen
)
7615 toggle_suppression
= false;
7616 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7617 if (BGP_PATH_HOLDDOWN(pi
))
7619 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7622 /* We are toggling suppression back. */
7624 /* Suppress route if not suppressed already. */
7625 if (aggr_suppress_path(aggregate
, pi
))
7626 toggle_suppression
= true;
7630 /* Install route if there is no more suppression. */
7631 if (aggr_unsuppress_path(aggregate
, pi
))
7632 toggle_suppression
= true;
7635 if (toggle_suppression
)
7636 bgp_process(bgp
, dest
, afi
, safi
);
7638 bgp_dest_unlock_node(top
);
7642 * Aggregate address MED matching incremental test: this function is called
7643 * when the initial aggregation occurred and we are only testing a single
7646 * In addition to testing and setting the MED validity it also installs back
7647 * suppressed routes (if summary is configured).
7649 * Must not be called in `bgp_aggregate_route`.
7651 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7652 struct bgp
*bgp
, const struct prefix
*p
,
7653 afi_t afi
, safi_t safi
,
7654 struct bgp_path_info
*pi
)
7656 /* MED matching disabled. */
7657 if (!aggregate
->match_med
)
7660 /* Aggregation with different MED, recheck if we have got equal MEDs
7663 if (aggregate
->med_mismatched
&&
7664 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
) &&
7665 aggregate
->summary_only
)
7666 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
,
7669 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7671 /* No mismatches, just quit. */
7672 if (!aggregate
->med_mismatched
)
7675 /* Route summarization is disabled. */
7676 if (!aggregate
->summary_only
)
7679 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7682 /* Update an aggregate as routes are added/removed from the BGP table */
7683 bool bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7684 safi_t safi
, struct bgp_aggregate
*aggregate
)
7686 struct bgp_table
*table
;
7687 struct bgp_dest
*top
;
7688 struct bgp_dest
*dest
;
7690 struct aspath
*aspath
= NULL
;
7691 struct community
*community
= NULL
;
7692 struct ecommunity
*ecommunity
= NULL
;
7693 struct lcommunity
*lcommunity
= NULL
;
7694 struct bgp_path_info
*pi
;
7695 unsigned long match
= 0;
7696 uint8_t atomic_aggregate
= 0;
7698 /* If the bgp instance is being deleted or self peer is deleted
7699 * then do not create aggregate route
7701 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
7702 bgp
->peer_self
== NULL
)
7705 /* Initialize and test routes for MED difference. */
7706 if (aggregate
->match_med
)
7707 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7710 * Reset aggregate count: we might've been called from route map
7711 * update so in that case we must retest all more specific routes.
7713 * \see `bgp_route_map_process_update`.
7715 aggregate
->count
= 0;
7716 aggregate
->incomplete_origin_count
= 0;
7717 aggregate
->incomplete_origin_count
= 0;
7718 aggregate
->egp_origin_count
= 0;
7720 /* ORIGIN attribute: If at least one route among routes that are
7721 aggregated has ORIGIN with the value INCOMPLETE, then the
7722 aggregated route must have the ORIGIN attribute with the value
7723 INCOMPLETE. Otherwise, if at least one route among routes that
7724 are aggregated has ORIGIN with the value EGP, then the aggregated
7725 route must have the origin attribute with the value EGP. In all
7726 other case the value of the ORIGIN attribute of the aggregated
7727 route is INTERNAL. */
7728 origin
= BGP_ORIGIN_IGP
;
7730 table
= bgp
->rib
[afi
][safi
];
7732 top
= bgp_node_get(table
, p
);
7733 for (dest
= bgp_node_get(table
, p
); dest
;
7734 dest
= bgp_route_next_until(dest
, top
)) {
7735 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7737 if (dest_p
->prefixlen
<= p
->prefixlen
)
7740 /* If suppress fib is enabled and route not installed
7741 * in FIB, skip the route
7743 if (!bgp_check_advertise(bgp
, dest
))
7748 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7749 if (BGP_PATH_HOLDDOWN(pi
))
7753 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7754 atomic_aggregate
= 1;
7756 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7760 * summary-only aggregate route suppress
7761 * aggregated route announcements.
7764 * Don't create summaries if MED didn't match
7765 * otherwise neither the specific routes and the
7766 * aggregation will be announced.
7768 if (aggregate
->summary_only
7769 && AGGREGATE_MED_VALID(aggregate
)) {
7770 if (aggr_suppress_path(aggregate
, pi
))
7775 * Suppress more specific routes that match the route
7779 * Don't suppress routes if MED matching is enabled and
7780 * it mismatched otherwise we might end up with no
7781 * routes for this path.
7783 if (aggregate
->suppress_map_name
7784 && AGGREGATE_MED_VALID(aggregate
)
7785 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7786 if (aggr_suppress_path(aggregate
, pi
))
7793 * If at least one route among routes that are
7794 * aggregated has ORIGIN with the value INCOMPLETE,
7795 * then the aggregated route MUST have the ORIGIN
7796 * attribute with the value INCOMPLETE. Otherwise, if
7797 * at least one route among routes that are aggregated
7798 * has ORIGIN with the value EGP, then the aggregated
7799 * route MUST have the ORIGIN attribute with the value
7802 switch (pi
->attr
->origin
) {
7803 case BGP_ORIGIN_INCOMPLETE
:
7804 aggregate
->incomplete_origin_count
++;
7806 case BGP_ORIGIN_EGP
:
7807 aggregate
->egp_origin_count
++;
7815 if (!aggregate
->as_set
)
7819 * as-set aggregate route generate origin, as path,
7820 * and community aggregation.
7822 /* Compute aggregate route's as-path.
7824 bgp_compute_aggregate_aspath_hash(aggregate
,
7827 /* Compute aggregate route's community.
7829 if (bgp_attr_get_community(pi
->attr
))
7830 bgp_compute_aggregate_community_hash(
7832 bgp_attr_get_community(pi
->attr
));
7834 /* Compute aggregate route's extended community.
7836 if (bgp_attr_get_ecommunity(pi
->attr
))
7837 bgp_compute_aggregate_ecommunity_hash(
7839 bgp_attr_get_ecommunity(pi
->attr
));
7841 /* Compute aggregate route's large community.
7843 if (bgp_attr_get_lcommunity(pi
->attr
))
7844 bgp_compute_aggregate_lcommunity_hash(
7846 bgp_attr_get_lcommunity(pi
->attr
));
7849 bgp_process(bgp
, dest
, afi
, safi
);
7851 if (aggregate
->as_set
) {
7852 bgp_compute_aggregate_aspath_val(aggregate
);
7853 bgp_compute_aggregate_community_val(aggregate
);
7854 bgp_compute_aggregate_ecommunity_val(aggregate
);
7855 bgp_compute_aggregate_lcommunity_val(aggregate
);
7859 bgp_dest_unlock_node(top
);
7862 if (aggregate
->incomplete_origin_count
> 0)
7863 origin
= BGP_ORIGIN_INCOMPLETE
;
7864 else if (aggregate
->egp_origin_count
> 0)
7865 origin
= BGP_ORIGIN_EGP
;
7867 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7868 origin
= aggregate
->origin
;
7870 if (aggregate
->as_set
) {
7871 if (aggregate
->aspath
)
7872 /* Retrieve aggregate route's as-path.
7874 aspath
= aspath_dup(aggregate
->aspath
);
7876 if (aggregate
->community
)
7877 /* Retrieve aggregate route's community.
7879 community
= community_dup(aggregate
->community
);
7881 if (aggregate
->ecommunity
)
7882 /* Retrieve aggregate route's ecommunity.
7884 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7886 if (aggregate
->lcommunity
)
7887 /* Retrieve aggregate route's lcommunity.
7889 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7892 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7893 ecommunity
, lcommunity
, atomic_aggregate
,
7899 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7900 safi_t safi
, struct bgp_aggregate
*aggregate
)
7902 struct bgp_table
*table
;
7903 struct bgp_dest
*top
;
7904 struct bgp_dest
*dest
;
7905 struct bgp_path_info
*pi
;
7906 unsigned long match
;
7908 table
= bgp
->rib
[afi
][safi
];
7910 /* If routes exists below this node, generate aggregate routes. */
7911 top
= bgp_node_get(table
, p
);
7912 for (dest
= bgp_node_get(table
, p
); dest
;
7913 dest
= bgp_route_next_until(dest
, top
)) {
7914 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7916 if (dest_p
->prefixlen
<= p
->prefixlen
)
7920 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7921 if (BGP_PATH_HOLDDOWN(pi
))
7924 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7928 * This route is suppressed: attempt to unsuppress it.
7930 * `aggr_unsuppress_path` will fail if this particular
7931 * aggregate route was not the suppressor.
7933 if (pi
->extra
&& pi
->extra
->aggr_suppressors
&&
7934 listcount(pi
->extra
->aggr_suppressors
)) {
7935 if (aggr_unsuppress_path(aggregate
, pi
))
7941 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7942 aggregate
->incomplete_origin_count
--;
7943 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7944 aggregate
->egp_origin_count
--;
7946 if (aggregate
->as_set
) {
7947 /* Remove as-path from aggregate.
7949 bgp_remove_aspath_from_aggregate_hash(
7953 if (bgp_attr_get_community(pi
->attr
))
7954 /* Remove community from aggregate.
7956 bgp_remove_comm_from_aggregate_hash(
7958 bgp_attr_get_community(
7961 if (bgp_attr_get_ecommunity(pi
->attr
))
7962 /* Remove ecommunity from aggregate.
7964 bgp_remove_ecomm_from_aggregate_hash(
7966 bgp_attr_get_ecommunity(
7969 if (bgp_attr_get_lcommunity(pi
->attr
))
7970 /* Remove lcommunity from aggregate.
7972 bgp_remove_lcomm_from_aggregate_hash(
7974 bgp_attr_get_lcommunity(
7979 /* If this node was suppressed, process the change. */
7981 bgp_process(bgp
, dest
, afi
, safi
);
7983 if (aggregate
->as_set
) {
7984 aspath_free(aggregate
->aspath
);
7985 aggregate
->aspath
= NULL
;
7986 if (aggregate
->community
)
7987 community_free(&aggregate
->community
);
7988 if (aggregate
->ecommunity
)
7989 ecommunity_free(&aggregate
->ecommunity
);
7990 if (aggregate
->lcommunity
)
7991 lcommunity_free(&aggregate
->lcommunity
);
7994 bgp_dest_unlock_node(top
);
7997 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7998 const struct prefix
*aggr_p
,
7999 struct bgp_path_info
*pinew
, afi_t afi
,
8001 struct bgp_aggregate
*aggregate
)
8004 struct aspath
*aspath
= NULL
;
8005 uint8_t atomic_aggregate
= 0;
8006 struct community
*community
= NULL
;
8007 struct ecommunity
*ecommunity
= NULL
;
8008 struct lcommunity
*lcommunity
= NULL
;
8010 /* If the bgp instance is being deleted or self peer is deleted
8011 * then do not create aggregate route
8013 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
8014 || (bgp
->peer_self
== NULL
))
8017 /* ORIGIN attribute: If at least one route among routes that are
8018 * aggregated has ORIGIN with the value INCOMPLETE, then the
8019 * aggregated route must have the ORIGIN attribute with the value
8020 * INCOMPLETE. Otherwise, if at least one route among routes that
8021 * are aggregated has ORIGIN with the value EGP, then the aggregated
8022 * route must have the origin attribute with the value EGP. In all
8023 * other case the value of the ORIGIN attribute of the aggregated
8024 * route is INTERNAL.
8026 origin
= BGP_ORIGIN_IGP
;
8031 * This must be called before `summary` check to avoid
8032 * "suppressing" twice.
8034 if (aggregate
->match_med
)
8035 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
8038 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8039 aggr_suppress_path(aggregate
, pinew
);
8041 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8042 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
8043 aggr_suppress_path(aggregate
, pinew
);
8045 switch (pinew
->attr
->origin
) {
8046 case BGP_ORIGIN_INCOMPLETE
:
8047 aggregate
->incomplete_origin_count
++;
8049 case BGP_ORIGIN_EGP
:
8050 aggregate
->egp_origin_count
++;
8058 if (aggregate
->incomplete_origin_count
> 0)
8059 origin
= BGP_ORIGIN_INCOMPLETE
;
8060 else if (aggregate
->egp_origin_count
> 0)
8061 origin
= BGP_ORIGIN_EGP
;
8063 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8064 origin
= aggregate
->origin
;
8066 if (aggregate
->as_set
) {
8067 /* Compute aggregate route's as-path.
8069 bgp_compute_aggregate_aspath(aggregate
,
8070 pinew
->attr
->aspath
);
8072 /* Compute aggregate route's community.
8074 if (bgp_attr_get_community(pinew
->attr
))
8075 bgp_compute_aggregate_community(
8076 aggregate
, bgp_attr_get_community(pinew
->attr
));
8078 /* Compute aggregate route's extended community.
8080 if (bgp_attr_get_ecommunity(pinew
->attr
))
8081 bgp_compute_aggregate_ecommunity(
8083 bgp_attr_get_ecommunity(pinew
->attr
));
8085 /* Compute aggregate route's large community.
8087 if (bgp_attr_get_lcommunity(pinew
->attr
))
8088 bgp_compute_aggregate_lcommunity(
8090 bgp_attr_get_lcommunity(pinew
->attr
));
8092 /* Retrieve aggregate route's as-path.
8094 if (aggregate
->aspath
)
8095 aspath
= aspath_dup(aggregate
->aspath
);
8097 /* Retrieve aggregate route's community.
8099 if (aggregate
->community
)
8100 community
= community_dup(aggregate
->community
);
8102 /* Retrieve aggregate route's ecommunity.
8104 if (aggregate
->ecommunity
)
8105 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8107 /* Retrieve aggregate route's lcommunity.
8109 if (aggregate
->lcommunity
)
8110 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8113 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8114 aspath
, community
, ecommunity
,
8115 lcommunity
, atomic_aggregate
, aggregate
);
8118 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
8120 struct bgp_path_info
*pi
,
8121 struct bgp_aggregate
*aggregate
,
8122 const struct prefix
*aggr_p
)
8125 struct aspath
*aspath
= NULL
;
8126 uint8_t atomic_aggregate
= 0;
8127 struct community
*community
= NULL
;
8128 struct ecommunity
*ecommunity
= NULL
;
8129 struct lcommunity
*lcommunity
= NULL
;
8130 unsigned long match
= 0;
8132 /* If the bgp instance is being deleted or self peer is deleted
8133 * then do not create aggregate route
8135 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
8136 || (bgp
->peer_self
== NULL
))
8139 if (BGP_PATH_HOLDDOWN(pi
))
8142 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
8145 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8146 if (aggr_unsuppress_path(aggregate
, pi
))
8149 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8150 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
8151 if (aggr_unsuppress_path(aggregate
, pi
))
8155 * This must be called after `summary`, `suppress-map` check to avoid
8156 * "unsuppressing" twice.
8158 if (aggregate
->match_med
)
8159 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
);
8161 if (aggregate
->count
> 0)
8164 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
8165 aggregate
->incomplete_origin_count
--;
8166 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
8167 aggregate
->egp_origin_count
--;
8169 if (aggregate
->as_set
) {
8170 /* Remove as-path from aggregate.
8172 bgp_remove_aspath_from_aggregate(aggregate
,
8175 if (bgp_attr_get_community(pi
->attr
))
8176 /* Remove community from aggregate.
8178 bgp_remove_community_from_aggregate(
8179 aggregate
, bgp_attr_get_community(pi
->attr
));
8181 if (bgp_attr_get_ecommunity(pi
->attr
))
8182 /* Remove ecommunity from aggregate.
8184 bgp_remove_ecommunity_from_aggregate(
8185 aggregate
, bgp_attr_get_ecommunity(pi
->attr
));
8187 if (bgp_attr_get_lcommunity(pi
->attr
))
8188 /* Remove lcommunity from aggregate.
8190 bgp_remove_lcommunity_from_aggregate(
8191 aggregate
, bgp_attr_get_lcommunity(pi
->attr
));
8194 /* If this node was suppressed, process the change. */
8196 bgp_process(bgp
, pi
->net
, afi
, safi
);
8198 origin
= BGP_ORIGIN_IGP
;
8199 if (aggregate
->incomplete_origin_count
> 0)
8200 origin
= BGP_ORIGIN_INCOMPLETE
;
8201 else if (aggregate
->egp_origin_count
> 0)
8202 origin
= BGP_ORIGIN_EGP
;
8204 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8205 origin
= aggregate
->origin
;
8207 if (aggregate
->as_set
) {
8208 /* Retrieve aggregate route's as-path.
8210 if (aggregate
->aspath
)
8211 aspath
= aspath_dup(aggregate
->aspath
);
8213 /* Retrieve aggregate route's community.
8215 if (aggregate
->community
)
8216 community
= community_dup(aggregate
->community
);
8218 /* Retrieve aggregate route's ecommunity.
8220 if (aggregate
->ecommunity
)
8221 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8223 /* Retrieve aggregate route's lcommunity.
8225 if (aggregate
->lcommunity
)
8226 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8229 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8230 aspath
, community
, ecommunity
,
8231 lcommunity
, atomic_aggregate
, aggregate
);
8234 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
8235 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
8237 struct bgp_dest
*child
;
8238 struct bgp_dest
*dest
;
8239 struct bgp_aggregate
*aggregate
;
8240 struct bgp_table
*table
;
8242 table
= bgp
->aggregate
[afi
][safi
];
8244 /* No aggregates configured. */
8245 if (bgp_table_top_nolock(table
) == NULL
)
8248 if (p
->prefixlen
== 0)
8251 if (BGP_PATH_HOLDDOWN(pi
))
8254 /* If suppress fib is enabled and route not installed
8255 * in FIB, do not update the aggregate route
8257 if (!bgp_check_advertise(bgp
, pi
->net
))
8260 child
= bgp_node_get(table
, p
);
8262 /* Aggregate address configuration check. */
8263 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8264 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8266 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8267 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8268 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
8272 bgp_dest_unlock_node(child
);
8275 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
8276 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
8278 struct bgp_dest
*child
;
8279 struct bgp_dest
*dest
;
8280 struct bgp_aggregate
*aggregate
;
8281 struct bgp_table
*table
;
8283 table
= bgp
->aggregate
[afi
][safi
];
8285 /* No aggregates configured. */
8286 if (bgp_table_top_nolock(table
) == NULL
)
8289 if (p
->prefixlen
== 0)
8292 child
= bgp_node_get(table
, p
);
8294 /* Aggregate address configuration check. */
8295 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8296 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8298 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8299 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8300 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
8304 bgp_dest_unlock_node(child
);
8307 /* Aggregate route attribute. */
8308 #define AGGREGATE_SUMMARY_ONLY 1
8309 #define AGGREGATE_AS_SET 1
8310 #define AGGREGATE_AS_UNSET 0
8312 static const char *bgp_origin2str(uint8_t origin
)
8315 case BGP_ORIGIN_IGP
:
8317 case BGP_ORIGIN_EGP
:
8319 case BGP_ORIGIN_INCOMPLETE
:
8320 return "incomplete";
8325 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
8328 case RPKI_NOT_BEING_USED
:
8338 assert(!"We should never get here this is a dev escape");
8342 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
8343 afi_t afi
, safi_t safi
)
8345 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8348 struct bgp_dest
*dest
;
8349 struct bgp_aggregate
*aggregate
;
8351 /* Convert string to prefix structure. */
8352 ret
= str2prefix(prefix_str
, &p
);
8354 vty_out(vty
, "Malformed prefix\n");
8355 return CMD_WARNING_CONFIG_FAILED
;
8359 /* Old configuration check. */
8360 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
8363 "%% There is no aggregate-address configuration.\n");
8364 return CMD_WARNING_CONFIG_FAILED
;
8367 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8368 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
8369 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
8370 NULL
, NULL
, 0, aggregate
);
8372 /* Unlock aggregate address configuration. */
8373 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
8375 bgp_free_aggregate_info(aggregate
);
8376 bgp_dest_unlock_node(dest
);
8377 bgp_dest_unlock_node(dest
);
8382 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
8383 safi_t safi
, const char *rmap
,
8384 uint8_t summary_only
, uint8_t as_set
,
8385 uint8_t origin
, bool match_med
,
8386 const char *suppress_map
)
8388 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8391 struct bgp_dest
*dest
;
8392 struct bgp_aggregate
*aggregate
;
8393 uint8_t as_set_new
= as_set
;
8395 if (suppress_map
&& summary_only
) {
8397 "'summary-only' and 'suppress-map' can't be used at the same time\n");
8398 return CMD_WARNING_CONFIG_FAILED
;
8401 /* Convert string to prefix structure. */
8402 ret
= str2prefix(prefix_str
, &p
);
8404 vty_out(vty
, "Malformed prefix\n");
8405 return CMD_WARNING_CONFIG_FAILED
;
8409 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
8410 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
8411 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8413 return CMD_WARNING_CONFIG_FAILED
;
8416 /* Old configuration check. */
8417 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
8418 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8421 vty_out(vty
, "There is already same aggregate network.\n");
8422 /* try to remove the old entry */
8423 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
8425 vty_out(vty
, "Error deleting aggregate.\n");
8426 bgp_dest_unlock_node(dest
);
8427 return CMD_WARNING_CONFIG_FAILED
;
8431 /* Make aggregate address structure. */
8432 aggregate
= bgp_aggregate_new();
8433 aggregate
->summary_only
= summary_only
;
8434 aggregate
->match_med
= match_med
;
8436 /* Network operators MUST NOT locally generate any new
8437 * announcements containing AS_SET or AS_CONFED_SET. If they have
8438 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8439 * SHOULD withdraw those routes and re-announce routes for the
8440 * aggregate or component prefixes (i.e., the more-specific routes
8441 * subsumed by the previously aggregated route) without AS_SET
8442 * or AS_CONFED_SET in the updates.
8444 if (bgp
->reject_as_sets
) {
8445 if (as_set
== AGGREGATE_AS_SET
) {
8446 as_set_new
= AGGREGATE_AS_UNSET
;
8448 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8451 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8455 aggregate
->as_set
= as_set_new
;
8456 aggregate
->safi
= safi
;
8457 /* Override ORIGIN attribute if defined.
8458 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8459 * to IGP which is not what rfc4271 says.
8460 * This enables the same behavior, optionally.
8462 aggregate
->origin
= origin
;
8465 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
8466 route_map_counter_decrement(aggregate
->rmap
.map
);
8467 aggregate
->rmap
.name
=
8468 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
8469 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
8470 route_map_counter_increment(aggregate
->rmap
.map
);
8474 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
8475 route_map_counter_decrement(aggregate
->suppress_map
);
8477 aggregate
->suppress_map_name
=
8478 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
8479 aggregate
->suppress_map
=
8480 route_map_lookup_by_name(aggregate
->suppress_map_name
);
8481 route_map_counter_increment(aggregate
->suppress_map
);
8484 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
8486 /* Aggregate address insert into BGP routing table. */
8487 if (!bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
)) {
8488 bgp_aggregate_free(aggregate
);
8489 bgp_dest_unlock_node(dest
);
8495 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
8496 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8498 "|summary-only$summary_only"
8499 "|route-map RMAP_NAME$rmap_name"
8500 "|origin <egp|igp|incomplete>$origin_s"
8501 "|matching-MED-only$match_med"
8502 "|suppress-map RMAP_NAME$suppress_map"
8505 "Configure BGP aggregate entries\n"
8506 "Aggregate prefix\n"
8507 "Aggregate address\n"
8509 "Generate AS set path information\n"
8510 "Filter more specific routes from updates\n"
8511 "Apply route map to aggregate network\n"
8516 "Unknown heritage\n"
8517 "Only aggregate routes with matching MED\n"
8518 "Suppress the selected more specific routes\n"
8519 "Route map with the route selectors\n")
8521 const char *prefix_s
= NULL
;
8522 safi_t safi
= bgp_node_safi(vty
);
8523 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8524 int as_set
= AGGREGATE_AS_UNSET
;
8525 char prefix_buf
[PREFIX2STR_BUFFER
];
8528 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8531 vty_out(vty
, "%% Inconsistent address and mask\n");
8532 return CMD_WARNING_CONFIG_FAILED
;
8534 prefix_s
= prefix_buf
;
8536 prefix_s
= prefix_str
;
8539 if (strcmp(origin_s
, "egp") == 0)
8540 origin
= BGP_ORIGIN_EGP
;
8541 else if (strcmp(origin_s
, "igp") == 0)
8542 origin
= BGP_ORIGIN_IGP
;
8543 else if (strcmp(origin_s
, "incomplete") == 0)
8544 origin
= BGP_ORIGIN_INCOMPLETE
;
8548 as_set
= AGGREGATE_AS_SET
;
8550 /* Handle configuration removal, otherwise installation. */
8552 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8554 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8555 summary_only
!= NULL
, as_set
, origin
,
8556 match_med
!= NULL
, suppress_map
);
8559 void bgp_free_aggregate_info(struct bgp_aggregate
*aggregate
)
8561 if (aggregate
->community
)
8562 community_free(&aggregate
->community
);
8564 hash_clean_and_free(&aggregate
->community_hash
,
8565 bgp_aggr_community_remove
);
8567 if (aggregate
->ecommunity
)
8568 ecommunity_free(&aggregate
->ecommunity
);
8570 hash_clean_and_free(&aggregate
->ecommunity_hash
,
8571 bgp_aggr_ecommunity_remove
);
8573 if (aggregate
->lcommunity
)
8574 lcommunity_free(&aggregate
->lcommunity
);
8576 hash_clean_and_free(&aggregate
->lcommunity_hash
,
8577 bgp_aggr_lcommunity_remove
);
8579 if (aggregate
->aspath
)
8580 aspath_free(aggregate
->aspath
);
8582 hash_clean_and_free(&aggregate
->aspath_hash
, bgp_aggr_aspath_remove
);
8584 bgp_aggregate_free(aggregate
);
8587 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8588 "[no] aggregate-address X:X::X:X/M$prefix [{"
8590 "|summary-only$summary_only"
8591 "|route-map RMAP_NAME$rmap_name"
8592 "|origin <egp|igp|incomplete>$origin_s"
8593 "|matching-MED-only$match_med"
8594 "|suppress-map RMAP_NAME$suppress_map"
8597 "Configure BGP aggregate entries\n"
8598 "Aggregate prefix\n"
8599 "Generate AS set path information\n"
8600 "Filter more specific routes from updates\n"
8601 "Apply route map to aggregate network\n"
8606 "Unknown heritage\n"
8607 "Only aggregate routes with matching MED\n"
8608 "Suppress the selected more specific routes\n"
8609 "Route map with the route selectors\n")
8611 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8612 int as_set
= AGGREGATE_AS_UNSET
;
8615 if (strcmp(origin_s
, "egp") == 0)
8616 origin
= BGP_ORIGIN_EGP
;
8617 else if (strcmp(origin_s
, "igp") == 0)
8618 origin
= BGP_ORIGIN_IGP
;
8619 else if (strcmp(origin_s
, "incomplete") == 0)
8620 origin
= BGP_ORIGIN_INCOMPLETE
;
8624 as_set
= AGGREGATE_AS_SET
;
8626 /* Handle configuration removal, otherwise installation. */
8628 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8631 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8632 rmap_name
, summary_only
!= NULL
, as_set
,
8633 origin
, match_med
!= NULL
, suppress_map
);
8636 /* Redistribute route treatment. */
8637 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8638 const union g_addr
*nexthop
, ifindex_t ifindex
,
8639 enum nexthop_types_t nhtype
, uint8_t distance
,
8640 enum blackhole_type bhtype
, uint32_t metric
,
8641 uint8_t type
, unsigned short instance
,
8644 struct bgp_path_info
*new;
8645 struct bgp_path_info
*bpi
;
8646 struct bgp_path_info rmap_path
;
8647 struct bgp_dest
*bn
;
8649 struct attr
*new_attr
;
8651 route_map_result_t ret
;
8652 struct bgp_redist
*red
;
8654 /* Make default attribute. */
8655 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
8657 * This must not be NULL to satisfy Coverity SA
8659 assert(attr
.aspath
);
8662 case NEXTHOP_TYPE_IFINDEX
:
8663 switch (p
->family
) {
8665 attr
.nexthop
.s_addr
= INADDR_ANY
;
8666 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8669 memset(&attr
.mp_nexthop_global
, 0,
8670 sizeof(attr
.mp_nexthop_global
));
8671 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8675 case NEXTHOP_TYPE_IPV4
:
8676 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8677 attr
.nexthop
= nexthop
->ipv4
;
8678 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8680 case NEXTHOP_TYPE_IPV6
:
8681 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8682 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8683 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8685 case NEXTHOP_TYPE_BLACKHOLE
:
8686 switch (p
->family
) {
8688 attr
.nexthop
.s_addr
= INADDR_ANY
;
8689 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8692 memset(&attr
.mp_nexthop_global
, 0,
8693 sizeof(attr
.mp_nexthop_global
));
8694 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8697 attr
.bh_type
= bhtype
;
8700 attr
.nh_type
= nhtype
;
8701 attr
.nh_ifindex
= ifindex
;
8704 attr
.distance
= distance
;
8705 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8709 bgp_attr_set_aigp_metric(&attr
, metric
);
8711 afi
= family2afi(p
->family
);
8713 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8715 struct attr attr_new
;
8717 /* Copy attribute for modification. */
8720 if (red
->redist_metric_flag
) {
8721 attr_new
.med
= red
->redist_metric
;
8722 bgp_attr_set_aigp_metric(&attr_new
, red
->redist_metric
);
8725 /* Apply route-map. */
8726 if (red
->rmap
.name
) {
8727 memset(&rmap_path
, 0, sizeof(rmap_path
));
8728 rmap_path
.peer
= bgp
->peer_self
;
8729 rmap_path
.attr
= &attr_new
;
8731 SET_FLAG(bgp
->peer_self
->rmap_type
,
8732 PEER_RMAP_TYPE_REDISTRIBUTE
);
8734 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8736 bgp
->peer_self
->rmap_type
= 0;
8738 if (ret
== RMAP_DENYMATCH
) {
8739 /* Free uninterned attribute. */
8740 bgp_attr_flush(&attr_new
);
8742 /* Unintern original. */
8743 aspath_unintern(&attr
.aspath
);
8744 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8749 if (bgp_in_graceful_shutdown(bgp
))
8750 bgp_attr_add_gshut_community(&attr_new
);
8752 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8753 SAFI_UNICAST
, p
, NULL
);
8755 new_attr
= bgp_attr_intern(&attr_new
);
8757 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8758 if (bpi
->peer
== bgp
->peer_self
8759 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8763 /* Ensure the (source route) type is updated. */
8765 if (attrhash_cmp(bpi
->attr
, new_attr
)
8766 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8767 bgp_attr_unintern(&new_attr
);
8768 aspath_unintern(&attr
.aspath
);
8769 bgp_dest_unlock_node(bn
);
8772 /* The attribute is changed. */
8773 bgp_path_info_set_flag(bn
, bpi
,
8774 BGP_PATH_ATTR_CHANGED
);
8776 /* Rewrite BGP route information. */
8777 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8778 bgp_path_info_restore(bn
, bpi
);
8780 bgp_aggregate_decrement(
8781 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8782 bgp_attr_unintern(&bpi
->attr
);
8783 bpi
->attr
= new_attr
;
8784 bpi
->uptime
= monotime(NULL
);
8786 /* Process change. */
8787 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8789 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8790 bgp_dest_unlock_node(bn
);
8791 aspath_unintern(&attr
.aspath
);
8793 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8795 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8797 vpn_leak_from_vrf_update(
8798 bgp_get_default(), bgp
, bpi
);
8804 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8805 bgp
->peer_self
, new_attr
, bn
);
8806 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8808 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8809 bgp_path_info_add(bn
, new);
8810 bgp_dest_unlock_node(bn
);
8811 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8812 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8814 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8815 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8817 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8821 /* Unintern original. */
8822 aspath_unintern(&attr
.aspath
);
8825 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8826 unsigned short instance
)
8829 struct bgp_dest
*dest
;
8830 struct bgp_path_info
*pi
;
8831 struct bgp_redist
*red
;
8833 afi
= family2afi(p
->family
);
8835 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8837 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8838 SAFI_UNICAST
, p
, NULL
);
8840 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8841 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8845 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8846 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8848 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8851 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8852 bgp_path_info_delete(dest
, pi
);
8853 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8855 bgp_dest_unlock_node(dest
);
8859 /* Withdraw specified route type's route. */
8860 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8861 unsigned short instance
)
8863 struct bgp_dest
*dest
;
8864 struct bgp_path_info
*pi
;
8865 struct bgp_table
*table
;
8867 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8869 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8870 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8871 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8872 && pi
->instance
== instance
)
8876 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8877 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8879 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8882 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8883 pi
, afi
, SAFI_UNICAST
);
8884 bgp_path_info_delete(dest
, pi
);
8885 if (!CHECK_FLAG(bgp
->flags
,
8886 BGP_FLAG_DELETE_IN_PROGRESS
))
8887 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8889 bgp_path_info_reap(dest
, pi
);
8894 /* Static function to display route. */
8895 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8896 struct vty
*vty
, json_object
*json
, bool wide
)
8899 char buf
[INET6_ADDRSTRLEN
];
8901 if (p
->family
== AF_INET
) {
8903 len
= vty_out(vty
, "%pFX", p
);
8905 json_object_string_add(json
, "prefix",
8906 inet_ntop(p
->family
,
8909 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8910 json_object_string_addf(json
, "network", "%pFX", p
);
8911 json_object_int_add(json
, "version", dest
->version
);
8913 } else if (p
->family
== AF_ETHERNET
) {
8914 len
= vty_out(vty
, "%pFX", p
);
8915 } else if (p
->family
== AF_EVPN
) {
8917 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8919 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8920 } else if (p
->family
== AF_FLOWSPEC
) {
8921 route_vty_out_flowspec(vty
, p
, NULL
,
8923 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8924 NLRI_STRING_FORMAT_MIN
, json
);
8927 len
= vty_out(vty
, "%pFX", p
);
8929 json_object_string_add(json
, "prefix",
8930 inet_ntop(p
->family
,
8933 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8934 json_object_string_addf(json
, "network", "%pFX", p
);
8935 json_object_int_add(json
, "version", dest
->version
);
8940 len
= wide
? (45 - len
) : (17 - len
);
8942 vty_out(vty
, "\n%*s", 20, " ");
8944 vty_out(vty
, "%*s", len
, " ");
8948 enum bgp_display_type
{
8952 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8955 case bgp_path_selection_none
:
8956 return "Nothing to Select";
8957 case bgp_path_selection_first
:
8958 return "First path received";
8959 case bgp_path_selection_evpn_sticky_mac
:
8960 return "EVPN Sticky Mac";
8961 case bgp_path_selection_evpn_seq
:
8962 return "EVPN sequence number";
8963 case bgp_path_selection_evpn_lower_ip
:
8964 return "EVPN lower IP";
8965 case bgp_path_selection_evpn_local_path
:
8966 return "EVPN local ES path";
8967 case bgp_path_selection_evpn_non_proxy
:
8968 return "EVPN non proxy";
8969 case bgp_path_selection_weight
:
8971 case bgp_path_selection_local_pref
:
8972 return "Local Pref";
8973 case bgp_path_selection_accept_own
:
8974 return "Accept Own";
8975 case bgp_path_selection_local_route
:
8976 return "Local Route";
8977 case bgp_path_selection_aigp
:
8979 case bgp_path_selection_confed_as_path
:
8980 return "Confederation based AS Path";
8981 case bgp_path_selection_as_path
:
8983 case bgp_path_selection_origin
:
8985 case bgp_path_selection_med
:
8987 case bgp_path_selection_peer
:
8989 case bgp_path_selection_confed
:
8990 return "Confed Peer Type";
8991 case bgp_path_selection_igp_metric
:
8992 return "IGP Metric";
8993 case bgp_path_selection_older
:
8994 return "Older Path";
8995 case bgp_path_selection_router_id
:
8997 case bgp_path_selection_cluster_length
:
8998 return "Cluster length";
8999 case bgp_path_selection_stale
:
9000 return "Path Staleness";
9001 case bgp_path_selection_local_configured
:
9002 return "Locally configured route";
9003 case bgp_path_selection_neighbor_ip
:
9004 return "Neighbor IP";
9005 case bgp_path_selection_default
:
9006 return "Nothing left to compare";
9008 return "Invalid (internal error)";
9011 /* Print the short form route status for a bgp_path_info */
9012 static void route_vty_short_status_out(struct vty
*vty
,
9013 struct bgp_path_info
*path
,
9014 const struct prefix
*p
,
9015 json_object
*json_path
)
9017 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
9021 /* Route status display. */
9022 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9023 json_object_boolean_true_add(json_path
, "removed");
9025 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9026 json_object_boolean_true_add(json_path
, "stale");
9028 if (path
->extra
&& bgp_path_suppressed(path
))
9029 json_object_boolean_true_add(json_path
, "suppressed");
9031 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9032 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9033 json_object_boolean_true_add(json_path
, "valid");
9036 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9037 json_object_boolean_true_add(json_path
, "history");
9039 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9040 json_object_boolean_true_add(json_path
, "damped");
9042 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9043 json_object_boolean_true_add(json_path
, "bestpath");
9044 json_object_string_add(json_path
, "selectionReason",
9045 bgp_path_selection_reason2str(
9046 path
->net
->reason
));
9049 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9050 json_object_boolean_true_add(json_path
, "multipath");
9052 /* Internal route. */
9053 if ((path
->peer
->as
)
9054 && (path
->peer
->as
== path
->peer
->local_as
))
9055 json_object_string_add(json_path
, "pathFrom",
9058 json_object_string_add(json_path
, "pathFrom",
9064 /* RPKI validation state */
9066 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
9068 if (rpki_state
== RPKI_VALID
)
9070 else if (rpki_state
== RPKI_INVALID
)
9072 else if (rpki_state
== RPKI_NOTFOUND
)
9077 /* Route status display. */
9078 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9080 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9082 else if (bgp_path_suppressed(path
))
9084 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9085 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9091 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9093 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9095 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
9097 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9102 /* Internal route. */
9103 if (path
->peer
&& (path
->peer
->as
)
9104 && (path
->peer
->as
== path
->peer
->local_as
))
9110 static char *bgp_nexthop_hostname(struct peer
*peer
,
9111 struct bgp_nexthop_cache
*bnc
)
9114 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
9115 return peer
->hostname
;
9119 /* called from terminal list command */
9120 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9121 struct bgp_path_info
*path
, int display
, safi_t safi
,
9122 json_object
*json_paths
, bool wide
)
9125 struct attr
*attr
= path
->attr
;
9126 json_object
*json_path
= NULL
;
9127 json_object
*json_nexthops
= NULL
;
9128 json_object
*json_nexthop_global
= NULL
;
9129 json_object
*json_nexthop_ll
= NULL
;
9130 json_object
*json_ext_community
= NULL
;
9131 char vrf_id_str
[VRF_NAMSIZ
] = {0};
9133 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9134 bool nexthop_othervrf
= false;
9135 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
9136 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
9137 char *nexthop_hostname
=
9138 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9139 char esi_buf
[ESI_STR_LEN
];
9142 json_path
= json_object_new_object();
9144 /* short status lead text */
9145 route_vty_short_status_out(vty
, path
, p
, json_path
);
9148 /* print prefix and mask */
9150 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9152 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
9154 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9158 * If vrf id of nexthop is different from that of prefix,
9159 * set up printable string to append
9161 if (path
->extra
&& path
->extra
->bgp_orig
) {
9162 const char *self
= "";
9167 nexthop_othervrf
= true;
9168 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9170 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
9171 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
9172 "@%s%s", VRFID_NONE_STR
, self
);
9174 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
9175 path
->extra
->bgp_orig
->vrf_id
, self
);
9177 if (path
->extra
->bgp_orig
->inst_type
9178 != BGP_INSTANCE_TYPE_DEFAULT
)
9180 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
9182 const char *self
= "";
9187 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
9191 * For ENCAP and EVPN routes, nexthop address family is not
9192 * neccessarily the same as the prefix address family.
9193 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9194 * EVPN routes are also exchanged with a MP nexthop. Currently,
9196 * is only IPv4, the value will be present in either
9198 * attr->mp_nexthop_global_in
9200 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
9202 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9206 snprintfrr(nexthop
, sizeof(nexthop
), "%pI4",
9207 &attr
->mp_nexthop_global_in
);
9210 snprintfrr(nexthop
, sizeof(nexthop
), "%pI6",
9211 &attr
->mp_nexthop_global
);
9214 snprintf(nexthop
, sizeof(nexthop
), "?");
9219 json_nexthop_global
= json_object_new_object();
9221 json_object_string_add(json_nexthop_global
, "ip",
9224 if (path
->peer
->hostname
)
9225 json_object_string_add(json_nexthop_global
,
9227 path
->peer
->hostname
);
9229 json_object_string_add(json_nexthop_global
, "afi",
9230 (af
== AF_INET
) ? "ipv4"
9232 json_object_boolean_true_add(json_nexthop_global
,
9235 if (nexthop_hostname
)
9236 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
9237 nexthop_hostname
, vrf_id_str
);
9239 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
9241 len
= wide
? (41 - len
) : (16 - len
);
9243 vty_out(vty
, "\n%*s", 36, " ");
9245 vty_out(vty
, "%*s", len
, " ");
9247 } else if (safi
== SAFI_EVPN
) {
9249 json_nexthop_global
= json_object_new_object();
9251 json_object_string_addf(json_nexthop_global
, "ip",
9253 &attr
->mp_nexthop_global_in
);
9255 if (path
->peer
->hostname
)
9256 json_object_string_add(json_nexthop_global
,
9258 path
->peer
->hostname
);
9260 json_object_string_add(json_nexthop_global
, "afi",
9262 json_object_boolean_true_add(json_nexthop_global
,
9265 if (nexthop_hostname
)
9266 len
= vty_out(vty
, "%pI4(%s)%s",
9267 &attr
->mp_nexthop_global_in
,
9268 nexthop_hostname
, vrf_id_str
);
9270 len
= vty_out(vty
, "%pI4%s",
9271 &attr
->mp_nexthop_global_in
,
9274 len
= wide
? (41 - len
) : (16 - len
);
9276 vty_out(vty
, "\n%*s", 36, " ");
9278 vty_out(vty
, "%*s", len
, " ");
9280 } else if (safi
== SAFI_FLOWSPEC
) {
9281 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
9283 json_nexthop_global
= json_object_new_object();
9285 json_object_string_add(json_nexthop_global
,
9287 json_object_string_addf(json_nexthop_global
,
9291 if (path
->peer
->hostname
)
9292 json_object_string_add(
9293 json_nexthop_global
, "hostname",
9294 path
->peer
->hostname
);
9296 json_object_boolean_true_add(
9297 json_nexthop_global
,
9300 if (nexthop_hostname
)
9301 len
= vty_out(vty
, "%pI4(%s)%s",
9306 len
= vty_out(vty
, "%pI4%s",
9310 len
= wide
? (41 - len
) : (16 - len
);
9312 vty_out(vty
, "\n%*s", 36, " ");
9314 vty_out(vty
, "%*s", len
, " ");
9317 } else if (p
->family
== AF_INET
&& !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9319 json_nexthop_global
= json_object_new_object();
9321 json_object_string_addf(json_nexthop_global
, "ip",
9322 "%pI4", &attr
->nexthop
);
9324 if (path
->peer
->hostname
)
9325 json_object_string_add(json_nexthop_global
,
9327 path
->peer
->hostname
);
9329 json_object_string_add(json_nexthop_global
, "afi",
9331 json_object_boolean_true_add(json_nexthop_global
,
9334 if (nexthop_hostname
)
9335 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
9336 nexthop_hostname
, vrf_id_str
);
9338 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
9341 len
= wide
? (41 - len
) : (16 - len
);
9343 vty_out(vty
, "\n%*s", 36, " ");
9345 vty_out(vty
, "%*s", len
, " ");
9350 else if (p
->family
== AF_INET6
|| BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9352 json_nexthop_global
= json_object_new_object();
9353 json_object_string_addf(json_nexthop_global
, "ip",
9355 &attr
->mp_nexthop_global
);
9357 if (path
->peer
->hostname
)
9358 json_object_string_add(json_nexthop_global
,
9360 path
->peer
->hostname
);
9362 json_object_string_add(json_nexthop_global
, "afi",
9364 json_object_string_add(json_nexthop_global
, "scope",
9367 /* We display both LL & GL if both have been
9369 if ((attr
->mp_nexthop_len
9370 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9371 || (path
->peer
->conf_if
)) {
9372 json_nexthop_ll
= json_object_new_object();
9373 json_object_string_addf(
9374 json_nexthop_ll
, "ip", "%pI6",
9375 &attr
->mp_nexthop_local
);
9377 if (path
->peer
->hostname
)
9378 json_object_string_add(
9379 json_nexthop_ll
, "hostname",
9380 path
->peer
->hostname
);
9382 json_object_string_add(json_nexthop_ll
, "afi",
9384 json_object_string_add(json_nexthop_ll
, "scope",
9387 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9388 &attr
->mp_nexthop_local
)
9390 && !attr
->mp_nexthop_prefer_global
)
9391 json_object_boolean_true_add(
9392 json_nexthop_ll
, "used");
9394 json_object_boolean_true_add(
9395 json_nexthop_global
, "used");
9397 json_object_boolean_true_add(
9398 json_nexthop_global
, "used");
9400 /* Display LL if LL/Global both in table unless
9401 * prefer-global is set */
9402 if (((attr
->mp_nexthop_len
9403 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9404 && !attr
->mp_nexthop_prefer_global
)
9405 || (path
->peer
->conf_if
)) {
9406 if (path
->peer
->conf_if
) {
9407 len
= vty_out(vty
, "%s",
9408 path
->peer
->conf_if
);
9409 /* len of IPv6 addr + max len of def
9411 len
= wide
? (41 - len
) : (16 - len
);
9414 vty_out(vty
, "\n%*s", 36, " ");
9416 vty_out(vty
, "%*s", len
, " ");
9418 if (nexthop_hostname
)
9421 &attr
->mp_nexthop_local
,
9427 &attr
->mp_nexthop_local
,
9430 len
= wide
? (41 - len
) : (16 - len
);
9433 vty_out(vty
, "\n%*s", 36, " ");
9435 vty_out(vty
, "%*s", len
, " ");
9438 if (nexthop_hostname
)
9439 len
= vty_out(vty
, "%pI6(%s)%s",
9440 &attr
->mp_nexthop_global
,
9444 len
= vty_out(vty
, "%pI6%s",
9445 &attr
->mp_nexthop_global
,
9448 len
= wide
? (41 - len
) : (16 - len
);
9451 vty_out(vty
, "\n%*s", 36, " ");
9453 vty_out(vty
, "%*s", len
, " ");
9459 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9461 json_object_int_add(json_path
, "metric", attr
->med
);
9463 vty_out(vty
, "%7u", attr
->med
);
9465 vty_out(vty
, "%10u", attr
->med
);
9466 else if (!json_paths
) {
9468 vty_out(vty
, "%*s", 7, " ");
9470 vty_out(vty
, "%*s", 10, " ");
9474 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9476 json_object_int_add(json_path
, "locPrf",
9479 vty_out(vty
, "%7u", attr
->local_pref
);
9480 else if (!json_paths
)
9484 json_object_int_add(json_path
, "weight", attr
->weight
);
9486 vty_out(vty
, "%7u ", attr
->weight
);
9489 json_object_string_addf(json_path
, "peerId", "%pSU",
9495 json_object_string_add(json_path
, "path",
9498 aspath_print_vty(vty
, attr
->aspath
);
9503 json_object_string_add(json_path
, "origin",
9504 bgp_origin_long_str
[attr
->origin
]);
9506 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9509 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9510 json_object_string_add(json_path
, "esi",
9511 esi_to_str(&attr
->esi
,
9512 esi_buf
, sizeof(esi_buf
)));
9514 if (safi
== SAFI_EVPN
&&
9515 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9516 json_ext_community
= json_object_new_object();
9517 json_object_string_add(
9518 json_ext_community
, "string",
9519 bgp_attr_get_ecommunity(attr
)->str
);
9520 json_object_object_add(json_path
,
9521 "extendedCommunity",
9522 json_ext_community
);
9526 json_object_boolean_true_add(json_path
,
9527 "announceNexthopSelf");
9528 if (nexthop_othervrf
) {
9529 json_object_string_add(json_path
, "nhVrfName",
9532 json_object_int_add(json_path
, "nhVrfId",
9533 ((nexthop_vrfid
== VRF_UNKNOWN
)
9535 : (int)nexthop_vrfid
));
9540 if (json_nexthop_global
|| json_nexthop_ll
) {
9541 json_nexthops
= json_object_new_array();
9543 if (json_nexthop_global
)
9544 json_object_array_add(json_nexthops
,
9545 json_nexthop_global
);
9547 if (json_nexthop_ll
)
9548 json_object_array_add(json_nexthops
,
9551 json_object_object_add(json_path
, "nexthops",
9555 json_object_array_add(json_paths
, json_path
);
9559 if (safi
== SAFI_EVPN
) {
9560 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9561 /* XXX - add these params to the json out */
9562 vty_out(vty
, "%*s", 20, " ");
9563 vty_out(vty
, "ESI:%s",
9564 esi_to_str(&attr
->esi
, esi_buf
,
9570 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9571 vty_out(vty
, "%*s", 20, " ");
9572 vty_out(vty
, "%s\n",
9573 bgp_attr_get_ecommunity(attr
)->str
);
9577 #ifdef ENABLE_BGP_VNC
9578 /* prints an additional line, indented, with VNC info, if
9580 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9581 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9586 /* called from terminal list command */
9587 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9588 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9589 bool use_json
, json_object
*json_ar
, bool wide
)
9591 json_object
*json_status
= NULL
;
9592 json_object
*json_net
= NULL
;
9596 /* Route status display. */
9598 json_status
= json_object_new_object();
9599 json_net
= json_object_new_object();
9606 /* print prefix and mask */
9608 if (safi
== SAFI_EVPN
)
9609 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9610 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9611 json_object_string_add(
9612 json_net
, "addrPrefix",
9613 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9615 json_object_int_add(json_net
, "prefixLen",
9617 json_object_string_addf(json_net
, "network", "%pFX", p
);
9620 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9622 /* Print attribute */
9625 if (p
->family
== AF_INET
&&
9626 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9627 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9628 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9629 json_object_string_addf(
9630 json_net
, "nextHop", "%pI4",
9631 &attr
->mp_nexthop_global_in
);
9633 json_object_string_addf(
9634 json_net
, "nextHop", "%pI4",
9636 } else if (p
->family
== AF_INET6
||
9637 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9638 json_object_string_addf(
9639 json_net
, "nextHopGlobal", "%pI6",
9640 &attr
->mp_nexthop_global
);
9641 } else if (p
->family
== AF_EVPN
&&
9642 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9643 json_object_string_addf(
9644 json_net
, "nextHop", "%pI4",
9645 &attr
->mp_nexthop_global_in
);
9649 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9650 json_object_int_add(json_net
, "metric",
9653 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9654 json_object_int_add(json_net
, "locPrf",
9657 json_object_int_add(json_net
, "weight", attr
->weight
);
9661 json_object_string_add(json_net
, "path",
9665 #if CONFDATE > 20231208
9666 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9668 json_object_string_add(json_net
, "bgpOriginCode",
9669 bgp_origin_str
[attr
->origin
]);
9670 json_object_string_add(
9672 bgp_origin_long_str
[attr
->origin
]);
9674 if (p
->family
== AF_INET
&&
9675 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9676 safi
== SAFI_EVPN
||
9677 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9678 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9679 || safi
== SAFI_EVPN
)
9680 vty_out(vty
, "%-16pI4",
9681 &attr
->mp_nexthop_global_in
);
9683 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9685 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9686 } else if (p
->family
== AF_INET6
||
9687 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9688 len
= vty_out(vty
, "%pI6",
9689 &attr
->mp_nexthop_global
);
9690 len
= wide
? (41 - len
) : (16 - len
);
9692 vty_out(vty
, "\n%*s", 36, " ");
9694 vty_out(vty
, "%*s", len
, " ");
9697 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9699 vty_out(vty
, "%7u", attr
->med
);
9701 vty_out(vty
, "%10u", attr
->med
);
9707 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9708 vty_out(vty
, "%7u", attr
->local_pref
);
9712 vty_out(vty
, "%7u ", attr
->weight
);
9716 aspath_print_vty(vty
, attr
->aspath
);
9719 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9723 struct bgp_path_info
*bpi
= bgp_dest_get_bgp_path_info(dest
);
9725 #if CONFDATE > 20231208
9726 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9728 json_object_boolean_true_add(json_status
, "*");
9729 json_object_boolean_true_add(json_status
, ">");
9730 json_object_boolean_true_add(json_net
, "valid");
9731 json_object_boolean_true_add(json_net
, "best");
9733 if (bpi
&& CHECK_FLAG(bpi
->flags
, BGP_PATH_MULTIPATH
)) {
9734 json_object_boolean_true_add(json_status
, "=");
9735 json_object_boolean_true_add(json_net
, "multipath");
9737 json_object_object_add(json_net
, "appliedStatusSymbols",
9739 json_object_object_addf(json_ar
, json_net
, "%pFX", p
);
9744 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9745 struct bgp_path_info
*path
, int display
, safi_t safi
,
9748 json_object
*json_out
= NULL
;
9750 mpls_label_t label
= MPLS_INVALID_LABEL
;
9756 json_out
= json_object_new_object();
9758 /* short status lead text */
9759 route_vty_short_status_out(vty
, path
, p
, json_out
);
9761 /* print prefix and mask */
9764 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9766 vty_out(vty
, "%*s", 17, " ");
9769 /* Print attribute */
9771 if (((p
->family
== AF_INET
) &&
9772 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9773 (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) ||
9774 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9775 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9776 || safi
== SAFI_EVPN
) {
9778 json_object_string_addf(
9779 json_out
, "mpNexthopGlobalIn", "%pI4",
9780 &attr
->mp_nexthop_global_in
);
9782 vty_out(vty
, "%-16pI4",
9783 &attr
->mp_nexthop_global_in
);
9786 json_object_string_addf(json_out
, "nexthop",
9787 "%pI4", &attr
->nexthop
);
9789 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9791 } else if (((p
->family
== AF_INET6
) &&
9792 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9793 (safi
== SAFI_EVPN
&& BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) ||
9794 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9797 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9799 json_object_string_addf(
9800 json_out
, "mpNexthopGlobalIn", "%pI6",
9801 &attr
->mp_nexthop_global
);
9805 &attr
->mp_nexthop_global
,
9806 buf_a
, sizeof(buf_a
)));
9807 } else if (attr
->mp_nexthop_len
9808 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9809 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9810 &attr
->mp_nexthop_global
,
9811 &attr
->mp_nexthop_local
);
9813 json_object_string_add(json_out
,
9814 "mpNexthopGlobalLocal",
9817 vty_out(vty
, "%s", buf_a
);
9821 label
= decode_label(&path
->extra
->label
[0]);
9823 if (bgp_is_valid_label(&label
)) {
9825 json_object_int_add(json_out
, "notag", label
);
9826 json_object_array_add(json
, json_out
);
9828 vty_out(vty
, "notag/%d", label
);
9835 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9836 struct bgp_path_info
*path
, int display
,
9837 json_object
*json_paths
)
9840 json_object
*json_path
= NULL
;
9841 json_object
*json_nexthop
= NULL
;
9842 json_object
*json_overlay
= NULL
;
9848 json_path
= json_object_new_object();
9849 json_overlay
= json_object_new_object();
9850 json_nexthop
= json_object_new_object();
9853 /* short status lead text */
9854 route_vty_short_status_out(vty
, path
, p
, json_path
);
9856 /* print prefix and mask */
9858 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9860 vty_out(vty
, "%*s", 17, " ");
9862 /* Print attribute */
9864 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9869 vty_out(vty
, "%-16pI4", &attr
->mp_nexthop_global_in
);
9871 json_object_string_addf(json_nexthop
, "ip", "%pI4",
9872 &attr
->mp_nexthop_global_in
);
9874 json_object_string_add(json_nexthop
, "afi", "ipv4");
9876 json_object_object_add(json_path
, "nexthop",
9882 vty_out(vty
, "%pI6(%pI6)", &attr
->mp_nexthop_global
,
9883 &attr
->mp_nexthop_local
);
9885 json_object_string_addf(json_nexthop
, "ipv6Global",
9887 &attr
->mp_nexthop_global
);
9889 json_object_string_addf(json_nexthop
, "ipv6LinkLocal",
9891 &attr
->mp_nexthop_local
);
9893 json_object_string_add(json_nexthop
, "afi", "ipv6");
9895 json_object_object_add(json_path
, "nexthop",
9903 json_object_string_add(json_nexthop
, "error",
9904 "Unsupported address-family");
9908 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9911 vty_out(vty
, "/%pIA", &eo
->gw_ip
);
9913 json_object_string_addf(json_overlay
, "gw", "%pIA", &eo
->gw_ip
);
9915 if (bgp_attr_get_ecommunity(attr
)) {
9917 struct ecommunity_val
*routermac
= ecommunity_lookup(
9918 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9919 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9922 mac
= ecom_mac2str((char *)routermac
->val
);
9925 vty_out(vty
, "/%s", mac
);
9927 json_object_string_add(json_overlay
, "rmac",
9930 XFREE(MTYPE_TMP
, mac
);
9937 json_object_object_add(json_path
, "overlay", json_overlay
);
9939 json_object_array_add(json_paths
, json_path
);
9943 /* dampening route */
9944 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9945 struct bgp_path_info
*path
, int display
,
9946 afi_t afi
, safi_t safi
, bool use_json
,
9947 json_object
*json_paths
)
9949 struct attr
*attr
= path
->attr
;
9951 char timebuf
[BGP_UPTIME_LEN
];
9952 json_object
*json_path
= NULL
;
9955 json_path
= json_object_new_object();
9957 /* short status lead text */
9958 route_vty_short_status_out(vty
, path
, p
, json_path
);
9960 /* print prefix and mask */
9963 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9965 vty_out(vty
, "%*s", 17, " ");
9967 len
= vty_out(vty
, "%s", path
->peer
->host
);
9971 vty_out(vty
, "\n%*s", 34, " ");
9973 vty_out(vty
, "%*s", len
, " ");
9976 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9977 BGP_UPTIME_LEN
, afi
, safi
,
9981 aspath_print_vty(vty
, attr
->aspath
);
9983 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9987 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9988 safi
, use_json
, json_path
);
9991 json_object_string_add(json_path
, "asPath",
9994 json_object_string_add(json_path
, "origin",
9995 bgp_origin_str
[attr
->origin
]);
9996 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9998 json_object_array_add(json_paths
, json_path
);
10003 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
10004 struct bgp_path_info
*path
, int display
,
10005 afi_t afi
, safi_t safi
, bool use_json
,
10006 json_object
*json_paths
)
10008 struct attr
*attr
= path
->attr
;
10009 struct bgp_damp_info
*bdi
;
10010 char timebuf
[BGP_UPTIME_LEN
];
10012 json_object
*json_path
= NULL
;
10018 json_path
= json_object_new_object();
10020 bdi
= path
->extra
->damp_info
;
10022 /* short status lead text */
10023 route_vty_short_status_out(vty
, path
, p
, json_path
);
10027 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
10029 vty_out(vty
, "%*s", 17, " ");
10031 len
= vty_out(vty
, "%s", path
->peer
->host
);
10034 vty_out(vty
, "\n%*s", 33, " ");
10036 vty_out(vty
, "%*s", len
, " ");
10038 len
= vty_out(vty
, "%d", bdi
->flap
);
10043 vty_out(vty
, "%*s", len
, " ");
10045 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
10046 BGP_UPTIME_LEN
, 0, NULL
));
10048 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10049 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10050 vty_out(vty
, "%s ",
10051 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10052 BGP_UPTIME_LEN
, afi
,
10053 safi
, use_json
, NULL
));
10055 vty_out(vty
, "%*s ", 8, " ");
10058 aspath_print_vty(vty
, attr
->aspath
);
10060 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10062 vty_out(vty
, "\n");
10064 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10065 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
10067 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
10070 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10071 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10072 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10073 BGP_UPTIME_LEN
, afi
, safi
,
10074 use_json
, json_path
);
10077 json_object_string_add(json_path
, "asPath",
10078 attr
->aspath
->str
);
10080 json_object_string_add(json_path
, "origin",
10081 bgp_origin_str
[attr
->origin
]);
10083 json_object_array_add(json_paths
, json_path
);
10087 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
10088 int *first
, const char *header
,
10089 json_object
*json_adv_to
)
10091 json_object
*json_peer
= NULL
;
10094 /* 'advertised-to' is a dictionary of peers we have advertised
10096 * prefix too. The key is the peer's IP or swpX, the value is
10098 * hostname if we know it and "" if not.
10100 json_peer
= json_object_new_object();
10102 if (peer
->hostname
)
10103 json_object_string_add(json_peer
, "hostname",
10107 json_object_object_add(json_adv_to
, peer
->conf_if
,
10110 json_object_object_addf(json_adv_to
, json_peer
, "%pSU",
10114 vty_out(vty
, "%s", header
);
10119 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
10121 vty_out(vty
, " %s(%s)", peer
->hostname
,
10124 vty_out(vty
, " %s(%pSU)", peer
->hostname
,
10128 vty_out(vty
, " %s", peer
->conf_if
);
10130 vty_out(vty
, " %pSU", &peer
->su
);
10135 static void route_vty_out_tx_ids(struct vty
*vty
,
10136 struct bgp_addpath_info_data
*d
)
10140 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10141 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
10142 d
->addpath_tx_id
[i
],
10143 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
10147 static void route_vty_out_detail_es_info(struct vty
*vty
,
10148 struct bgp_path_info
*pi
,
10150 json_object
*json_path
)
10152 char esi_buf
[ESI_STR_LEN
];
10153 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
10154 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
10155 ATTR_ES_PEER_ROUTER
);
10156 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
10157 ATTR_ES_PEER_ACTIVE
);
10158 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
10159 ATTR_ES_PEER_PROXY
);
10160 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
10162 json_object
*json_es_info
= NULL
;
10164 json_object_string_add(
10167 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
10168 json_es_info
= json_object_new_object();
10170 json_object_boolean_true_add(
10171 json_es_info
, "localEs");
10173 json_object_boolean_true_add(
10174 json_es_info
, "peerActive");
10176 json_object_boolean_true_add(
10177 json_es_info
, "peerProxy");
10179 json_object_boolean_true_add(
10180 json_es_info
, "peerRouter");
10181 if (attr
->mm_sync_seqnum
)
10182 json_object_int_add(
10183 json_es_info
, "peerSeq",
10184 attr
->mm_sync_seqnum
);
10185 json_object_object_add(
10186 json_path
, "es_info",
10190 if (bgp_evpn_attr_is_sync(attr
))
10192 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10194 es_local
? "local-es":"",
10195 peer_proxy
? "proxy " : "",
10196 peer_active
? "active ":"",
10197 peer_router
? "router ":"",
10198 attr
->mm_sync_seqnum
);
10200 vty_out(vty
, " ESI %s %s\n",
10202 es_local
? "local-es":"");
10206 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
10207 const struct prefix
*p
, struct bgp_path_info
*path
,
10208 afi_t afi
, safi_t safi
,
10209 enum rpki_states rpki_curr_state
,
10210 json_object
*json_paths
)
10212 char buf
[INET6_ADDRSTRLEN
];
10214 struct attr
*attr
= path
->attr
;
10216 json_object
*json_bestpath
= NULL
;
10217 json_object
*json_cluster_list
= NULL
;
10218 json_object
*json_cluster_list_list
= NULL
;
10219 json_object
*json_ext_community
= NULL
;
10220 json_object
*json_last_update
= NULL
;
10221 json_object
*json_pmsi
= NULL
;
10222 json_object
*json_nexthop_global
= NULL
;
10223 json_object
*json_nexthop_ll
= NULL
;
10224 json_object
*json_nexthops
= NULL
;
10225 json_object
*json_path
= NULL
;
10226 json_object
*json_peer
= NULL
;
10227 json_object
*json_string
= NULL
;
10228 json_object
*json_adv_to
= NULL
;
10230 struct listnode
*node
, *nnode
;
10232 bool addpath_capable
;
10234 unsigned int first_as
;
10235 bool nexthop_self
=
10236 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
10238 char *nexthop_hostname
=
10239 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
10243 mpls_label_t label
= MPLS_INVALID_LABEL
;
10245 struct bgp_path_info
*bpi_ultimate
=
10246 bgp_get_imported_bpi_ultimate(path
);
10249 json_path
= json_object_new_object();
10250 json_peer
= json_object_new_object();
10251 json_nexthop_global
= json_object_new_object();
10254 if (safi
== SAFI_EVPN
) {
10256 vty_out(vty
, " Route %pFX", p
);
10260 if (path
->extra
&& path
->extra
->num_labels
) {
10261 bgp_evpn_label2str(path
->extra
->label
,
10262 path
->extra
->num_labels
, tag_buf
,
10265 if (safi
== SAFI_EVPN
) {
10267 if (tag_buf
[0] != '\0')
10268 vty_out(vty
, " VNI %s", tag_buf
);
10271 json_object_string_add(json_path
, "vni",
10277 if (safi
== SAFI_EVPN
10278 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
10279 char gwip_buf
[INET6_ADDRSTRLEN
];
10281 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
10285 json_object_string_add(json_path
, "gatewayIP",
10288 vty_out(vty
, " Gateway IP %s", gwip_buf
);
10291 if (safi
== SAFI_EVPN
&& !json_path
)
10292 vty_out(vty
, "\n");
10295 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
10296 struct bgp_path_info
*parent_ri
;
10297 struct bgp_dest
*dest
, *pdest
;
10299 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
10300 dest
= parent_ri
->net
;
10301 if (dest
&& dest
->pdest
) {
10302 pdest
= dest
->pdest
;
10303 if (is_pi_family_evpn(parent_ri
)) {
10304 vty_out(vty
, " Imported from ");
10305 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
10306 (struct prefix_rd
*)bgp_dest_get_prefix(
10308 vty_out(vty
, ":%pFX, VNI %s",
10309 (struct prefix_evpn
*)
10310 bgp_dest_get_prefix(dest
),
10312 if (CHECK_FLAG(attr
->es_flags
, ATTR_ES_L3_NHG
))
10313 vty_out(vty
, ", L3NHG %s",
10316 ATTR_ES_L3_NHG_ACTIVE
)
10319 vty_out(vty
, "\n");
10322 vty_out(vty
, " Imported from ");
10323 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
10324 (struct prefix_rd
*)bgp_dest_get_prefix(
10326 vty_out(vty
, ":%pFX\n",
10327 (struct prefix_evpn
*)
10328 bgp_dest_get_prefix(dest
));
10333 /* Line1 display AS-path, Aggregator */
10334 if (attr
->aspath
) {
10336 if (!attr
->aspath
->json
)
10337 aspath_str_update(attr
->aspath
, true);
10338 json_object_lock(attr
->aspath
->json
);
10339 json_object_object_add(json_path
, "aspath",
10340 attr
->aspath
->json
);
10342 if (attr
->aspath
->segments
)
10343 vty_out(vty
, " %s", attr
->aspath
->str
);
10345 vty_out(vty
, " Local");
10349 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
10351 json_object_boolean_true_add(json_path
, "removed");
10353 vty_out(vty
, ", (removed)");
10356 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10358 json_object_boolean_true_add(json_path
, "stale");
10360 vty_out(vty
, ", (stale)");
10363 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
10365 json_object_int_add(json_path
, "aggregatorAs",
10366 attr
->aggregator_as
);
10367 json_object_string_addf(json_path
, "aggregatorId",
10368 "%pI4", &attr
->aggregator_addr
);
10370 vty_out(vty
, ", (aggregated by %u %pI4)",
10371 attr
->aggregator_as
, &attr
->aggregator_addr
);
10375 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10376 PEER_FLAG_REFLECTOR_CLIENT
)) {
10378 json_object_boolean_true_add(json_path
,
10379 "rxedFromRrClient");
10381 vty_out(vty
, ", (Received from a RR-client)");
10384 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10385 PEER_FLAG_RSERVER_CLIENT
)) {
10387 json_object_boolean_true_add(json_path
,
10388 "rxedFromRsClient");
10390 vty_out(vty
, ", (Received from a RS-client)");
10393 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10395 json_object_boolean_true_add(json_path
,
10396 "dampeningHistoryEntry");
10398 vty_out(vty
, ", (history entry)");
10399 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10401 json_object_boolean_true_add(json_path
,
10402 "dampeningSuppressed");
10404 vty_out(vty
, ", (suppressed due to dampening)");
10408 vty_out(vty
, "\n");
10410 /* Line2 display Next-hop, Neighbor, Router-id */
10411 /* Display the nexthop */
10413 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
||
10414 p
->family
== AF_EVPN
) &&
10415 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
||
10416 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10417 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10418 || safi
== SAFI_EVPN
) {
10420 json_object_string_addf(
10421 json_nexthop_global
, "ip", "%pI4",
10422 &attr
->mp_nexthop_global_in
);
10424 if (path
->peer
->hostname
)
10425 json_object_string_add(
10426 json_nexthop_global
, "hostname",
10427 path
->peer
->hostname
);
10429 if (nexthop_hostname
)
10430 vty_out(vty
, " %pI4(%s)",
10431 &attr
->mp_nexthop_global_in
,
10434 vty_out(vty
, " %pI4",
10435 &attr
->mp_nexthop_global_in
);
10439 json_object_string_addf(json_nexthop_global
,
10443 if (path
->peer
->hostname
)
10444 json_object_string_add(
10445 json_nexthop_global
, "hostname",
10446 path
->peer
->hostname
);
10448 if (nexthop_hostname
)
10449 vty_out(vty
, " %pI4(%s)",
10453 vty_out(vty
, " %pI4",
10459 json_object_string_add(json_nexthop_global
, "afi",
10463 json_object_string_addf(json_nexthop_global
, "ip",
10465 &attr
->mp_nexthop_global
);
10467 if (path
->peer
->hostname
)
10468 json_object_string_add(json_nexthop_global
,
10470 path
->peer
->hostname
);
10472 json_object_string_add(json_nexthop_global
, "afi",
10474 json_object_string_add(json_nexthop_global
, "scope",
10477 if (nexthop_hostname
)
10478 vty_out(vty
, " %pI6(%s)",
10479 &attr
->mp_nexthop_global
,
10482 vty_out(vty
, " %pI6",
10483 &attr
->mp_nexthop_global
);
10487 /* Display the IGP cost or 'inaccessible' */
10488 if (!CHECK_FLAG(bpi_ultimate
->flags
, BGP_PATH_VALID
)) {
10489 bool import
= CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
);
10492 json_object_boolean_false_add(json_nexthop_global
,
10494 json_object_boolean_add(json_nexthop_global
,
10495 "importCheckEnabled", import
);
10497 vty_out(vty
, " (inaccessible%s)",
10498 import
? ", import-check enabled" : "");
10501 if (bpi_ultimate
->extra
&& bpi_ultimate
->extra
->igpmetric
) {
10503 json_object_int_add(
10504 json_nexthop_global
, "metric",
10505 bpi_ultimate
->extra
->igpmetric
);
10507 vty_out(vty
, " (metric %u)",
10508 bpi_ultimate
->extra
->igpmetric
);
10511 /* IGP cost is 0, display this only for json */
10514 json_object_int_add(json_nexthop_global
,
10519 json_object_boolean_true_add(json_nexthop_global
,
10523 /* Display peer "from" output */
10524 /* This path was originated locally */
10525 if (path
->peer
== bgp
->peer_self
) {
10527 if (safi
== SAFI_EVPN
|| (p
->family
== AF_INET
&&
10528 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10530 json_object_string_add(json_peer
, "peerId",
10533 vty_out(vty
, " from 0.0.0.0 ");
10536 json_object_string_add(json_peer
, "peerId",
10539 vty_out(vty
, " from :: ");
10543 json_object_string_addf(json_peer
, "routerId", "%pI4",
10546 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10549 /* We RXed this path from one of our peers */
10553 json_object_string_addf(json_peer
, "peerId", "%pSU",
10555 json_object_string_addf(json_peer
, "routerId", "%pI4",
10556 &path
->peer
->remote_id
);
10558 if (path
->peer
->hostname
)
10559 json_object_string_add(json_peer
, "hostname",
10560 path
->peer
->hostname
);
10562 if (path
->peer
->domainname
)
10563 json_object_string_add(json_peer
, "domainname",
10564 path
->peer
->domainname
);
10566 if (path
->peer
->conf_if
)
10567 json_object_string_add(json_peer
, "interface",
10568 path
->peer
->conf_if
);
10570 if (path
->peer
->conf_if
) {
10571 if (path
->peer
->hostname
10572 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10573 BGP_FLAG_SHOW_HOSTNAME
))
10574 vty_out(vty
, " from %s(%s)",
10575 path
->peer
->hostname
,
10576 path
->peer
->conf_if
);
10578 vty_out(vty
, " from %s",
10579 path
->peer
->conf_if
);
10581 if (path
->peer
->hostname
10582 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10583 BGP_FLAG_SHOW_HOSTNAME
))
10584 vty_out(vty
, " from %s(%s)",
10585 path
->peer
->hostname
,
10588 vty_out(vty
, " from %pSU",
10592 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10593 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10595 vty_out(vty
, " (%pI4)", &path
->peer
->remote_id
);
10600 * Note when vrfid of nexthop is different from that of prefix
10602 if (path
->extra
&& path
->extra
->bgp_orig
) {
10603 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10608 if (path
->extra
->bgp_orig
->inst_type
10609 == BGP_INSTANCE_TYPE_DEFAULT
)
10610 vn
= VRF_DEFAULT_NAME
;
10612 vn
= path
->extra
->bgp_orig
->name
;
10614 json_object_string_add(json_path
, "nhVrfName", vn
);
10616 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10617 json_object_int_add(json_path
, "nhVrfId", -1);
10619 json_object_int_add(json_path
, "nhVrfId",
10620 (int)nexthop_vrfid
);
10623 if (nexthop_vrfid
== VRF_UNKNOWN
)
10624 vty_out(vty
, " vrf ?");
10628 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10629 vty_out(vty
, " vrf %s(%u)",
10630 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10635 if (nexthop_self
) {
10637 json_object_boolean_true_add(json_path
,
10638 "announceNexthopSelf");
10640 vty_out(vty
, " announce-nh-self");
10645 vty_out(vty
, "\n");
10647 /* display the link-local nexthop */
10648 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10650 json_nexthop_ll
= json_object_new_object();
10651 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10652 &attr
->mp_nexthop_local
);
10654 if (path
->peer
->hostname
)
10655 json_object_string_add(json_nexthop_ll
,
10657 path
->peer
->hostname
);
10659 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10660 json_object_string_add(json_nexthop_ll
, "scope",
10663 json_object_boolean_true_add(json_nexthop_ll
,
10666 if (!attr
->mp_nexthop_prefer_global
)
10667 json_object_boolean_true_add(json_nexthop_ll
,
10670 json_object_boolean_true_add(
10671 json_nexthop_global
, "used");
10673 vty_out(vty
, " (%s) %s\n",
10674 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10675 buf
, INET6_ADDRSTRLEN
),
10676 attr
->mp_nexthop_prefer_global
10677 ? "(prefer-global)"
10681 /* If we do not have a link-local nexthop then we must flag the
10682 global as "used" */
10685 json_object_boolean_true_add(json_nexthop_global
,
10689 if (safi
== SAFI_EVPN
&&
10690 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10691 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10694 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10695 * Int/Ext/Local, Atomic, best */
10697 json_object_string_add(json_path
, "origin",
10698 bgp_origin_long_str
[attr
->origin
]);
10700 vty_out(vty
, " Origin %s",
10701 bgp_origin_long_str
[attr
->origin
]);
10703 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10705 json_object_int_add(json_path
, "metric", attr
->med
);
10707 vty_out(vty
, ", metric %u", attr
->med
);
10710 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10712 json_object_int_add(json_path
, "locPrf",
10715 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10718 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
10720 json_object_int_add(json_path
, "aigpMetric",
10721 bgp_attr_get_aigp_metric(attr
));
10723 vty_out(vty
, ", aigp-metric %" PRIu64
,
10724 bgp_attr_get_aigp_metric(attr
));
10727 if (attr
->weight
!= 0) {
10729 json_object_int_add(json_path
, "weight", attr
->weight
);
10731 vty_out(vty
, ", weight %u", attr
->weight
);
10734 if (attr
->tag
!= 0) {
10736 json_object_int_add(json_path
, "tag", attr
->tag
);
10738 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10741 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10743 json_object_boolean_false_add(json_path
, "valid");
10745 vty_out(vty
, ", invalid");
10746 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10748 json_object_boolean_true_add(json_path
, "valid");
10750 vty_out(vty
, ", valid");
10754 json_object_int_add(json_path
, "version", bn
->version
);
10756 if (path
->peer
!= bgp
->peer_self
) {
10757 if (path
->peer
->as
== path
->peer
->local_as
) {
10758 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10760 json_object_string_add(
10762 "confed-internal");
10764 vty_out(vty
, ", confed-internal");
10767 json_object_string_add(
10768 json_peer
, "type", "internal");
10770 vty_out(vty
, ", internal");
10773 if (bgp_confederation_peers_check(bgp
,
10776 json_object_string_add(
10778 "confed-external");
10780 vty_out(vty
, ", confed-external");
10783 json_object_string_add(
10784 json_peer
, "type", "external");
10786 vty_out(vty
, ", external");
10789 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10791 json_object_boolean_true_add(json_path
, "aggregated");
10792 json_object_boolean_true_add(json_path
, "local");
10794 vty_out(vty
, ", aggregated, local");
10796 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10798 json_object_boolean_true_add(json_path
, "sourced");
10800 vty_out(vty
, ", sourced");
10803 json_object_boolean_true_add(json_path
, "sourced");
10804 json_object_boolean_true_add(json_path
, "local");
10806 vty_out(vty
, ", sourced, local");
10810 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10812 json_object_boolean_true_add(json_path
,
10813 "atomicAggregate");
10815 vty_out(vty
, ", atomic-aggregate");
10818 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
10820 json_object_int_add(json_path
, "otc", attr
->otc
);
10822 vty_out(vty
, ", otc %u", attr
->otc
);
10825 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10826 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10827 && bgp_path_info_mpath_count(path
))) {
10829 json_object_boolean_true_add(json_path
, "multipath");
10831 vty_out(vty
, ", multipath");
10834 // Mark the bestpath(s)
10835 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10836 first_as
= aspath_get_first_as(attr
->aspath
);
10839 if (!json_bestpath
)
10840 json_bestpath
= json_object_new_object();
10841 json_object_int_add(json_bestpath
, "bestpathFromAs",
10845 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10847 vty_out(vty
, ", bestpath-from-AS Local");
10851 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10853 if (!json_bestpath
)
10854 json_bestpath
= json_object_new_object();
10855 json_object_boolean_true_add(json_bestpath
, "overall");
10856 json_object_string_add(
10857 json_bestpath
, "selectionReason",
10858 bgp_path_selection_reason2str(bn
->reason
));
10860 vty_out(vty
, ", best");
10861 vty_out(vty
, " (%s)",
10862 bgp_path_selection_reason2str(bn
->reason
));
10866 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10868 json_object_string_add(
10869 json_path
, "rpkiValidationState",
10870 bgp_rpki_validation2str(rpki_curr_state
));
10872 vty_out(vty
, ", rpki validation-state: %s",
10873 bgp_rpki_validation2str(rpki_curr_state
));
10877 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10880 vty_out(vty
, "\n");
10882 /* Line 4 display Community */
10883 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10885 if (!bgp_attr_get_community(attr
)->json
)
10886 community_str(bgp_attr_get_community(attr
),
10888 json_object_lock(bgp_attr_get_community(attr
)->json
);
10889 json_object_object_add(
10890 json_path
, "community",
10891 bgp_attr_get_community(attr
)->json
);
10893 vty_out(vty
, " Community: %s\n",
10894 bgp_attr_get_community(attr
)->str
);
10898 /* Line 5 display Extended-community */
10899 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10901 json_ext_community
= json_object_new_object();
10902 json_object_string_add(
10903 json_ext_community
, "string",
10904 bgp_attr_get_ecommunity(attr
)->str
);
10905 json_object_object_add(json_path
, "extendedCommunity",
10906 json_ext_community
);
10908 vty_out(vty
, " Extended Community: %s\n",
10909 bgp_attr_get_ecommunity(attr
)->str
);
10913 /* Line 6 display Large community */
10914 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10916 if (!bgp_attr_get_lcommunity(attr
)->json
)
10917 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10919 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10920 json_object_object_add(
10921 json_path
, "largeCommunity",
10922 bgp_attr_get_lcommunity(attr
)->json
);
10924 vty_out(vty
, " Large Community: %s\n",
10925 bgp_attr_get_lcommunity(attr
)->str
);
10929 /* Line 7 display Originator, Cluster-id */
10930 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10931 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10932 char buf
[BUFSIZ
] = {0};
10934 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10936 json_object_string_addf(json_path
,
10937 "originatorId", "%pI4",
10938 &attr
->originator_id
);
10940 vty_out(vty
, " Originator: %pI4",
10941 &attr
->originator_id
);
10944 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10945 struct cluster_list
*cluster
=
10946 bgp_attr_get_cluster(attr
);
10950 json_cluster_list
= json_object_new_object();
10951 json_cluster_list_list
=
10952 json_object_new_array();
10954 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10955 json_string
= json_object_new_string(
10958 buf
, sizeof(buf
)));
10959 json_object_array_add(
10960 json_cluster_list_list
,
10965 * struct cluster_list does not have
10966 * "str" variable like aspath and community
10967 * do. Add this someday if someone asks
10969 * json_object_string_add(json_cluster_list,
10970 * "string", cluster->str);
10972 json_object_object_add(json_cluster_list
,
10974 json_cluster_list_list
);
10975 json_object_object_add(json_path
, "clusterList",
10976 json_cluster_list
);
10978 vty_out(vty
, ", Cluster list: ");
10980 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10981 vty_out(vty
, "%pI4 ",
10982 &cluster
->list
[i
]);
10988 vty_out(vty
, "\n");
10991 if (path
->extra
&& path
->extra
->damp_info
)
10992 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
10995 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10996 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10997 mpls_lse_decode(path
->extra
->label
[0], &label
, &ttl
, &exp
,
11001 json_object_int_add(json_path
, "remoteLabel", label
);
11003 vty_out(vty
, " Remote label: %d\n", label
);
11007 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
11009 json_object_string_addf(json_path
, "remoteSid", "%pI6",
11010 &path
->extra
->sid
[0].sid
);
11012 vty_out(vty
, " Remote SID: %pI6\n",
11013 &path
->extra
->sid
[0].sid
);
11017 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
11019 json_object_int_add(json_path
, "labelIndex",
11020 attr
->label_index
);
11022 vty_out(vty
, " Label Index: %d\n",
11023 attr
->label_index
);
11026 /* Line 8 display Addpath IDs */
11027 if (path
->addpath_rx_id
11028 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
11030 json_object_int_add(json_path
, "addpathRxId",
11031 path
->addpath_rx_id
);
11033 /* Keep backwards compatibility with the old API
11034 * by putting TX All's ID in the old field
11036 json_object_int_add(
11037 json_path
, "addpathTxId",
11039 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
11041 /* ... but create a specific field for each
11044 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
11045 json_object_int_add(
11047 bgp_addpath_names(i
)->id_json_name
,
11048 path
->tx_addpath
.addpath_tx_id
[i
]);
11051 vty_out(vty
, " AddPath ID: RX %u, ",
11052 path
->addpath_rx_id
);
11054 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
11058 /* If we used addpath to TX a non-bestpath we need to display
11059 * "Advertised to" on a path-by-path basis
11061 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11064 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11066 bgp_addpath_encode_tx(peer
, afi
, safi
);
11067 has_adj
= bgp_adj_out_lookup(
11069 bgp_addpath_id_for_peer(peer
, afi
, safi
,
11070 &path
->tx_addpath
));
11072 if ((addpath_capable
&& has_adj
)
11073 || (!addpath_capable
&& has_adj
11074 && CHECK_FLAG(path
->flags
,
11075 BGP_PATH_SELECTED
))) {
11076 if (json_path
&& !json_adv_to
)
11077 json_adv_to
= json_object_new_object();
11079 route_vty_out_advertised_to(
11081 " Advertised to:", json_adv_to
);
11087 json_object_object_add(
11088 json_path
, "advertisedTo", json_adv_to
);
11092 vty_out(vty
, "\n");
11097 /* Line 9 display Uptime */
11098 tbuf
= time(NULL
) - (monotime(NULL
) - path
->uptime
);
11100 json_last_update
= json_object_new_object();
11101 json_object_int_add(json_last_update
, "epoch", tbuf
);
11102 json_object_string_add(json_last_update
, "string",
11104 json_object_object_add(json_path
, "lastUpdate",
11107 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
11109 /* Line 10 display PMSI tunnel attribute, if present */
11110 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
11111 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
11112 bgp_attr_get_pmsi_tnl_type(attr
),
11113 PMSI_TNLTYPE_STR_DEFAULT
);
11116 json_pmsi
= json_object_new_object();
11117 json_object_string_add(json_pmsi
, "tunnelType", str
);
11118 json_object_int_add(json_pmsi
, "label",
11119 label2vni(&attr
->label
));
11120 json_object_object_add(json_path
, "pmsi", json_pmsi
);
11122 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
11123 str
, label2vni(&attr
->label
));
11126 if (path
->peer
->t_gr_restart
&&
11127 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
11128 unsigned long gr_remaining
=
11129 event_timer_remain_second(path
->peer
->t_gr_restart
);
11132 json_object_int_add(json_path
,
11133 "gracefulRestartSecondsRemaining",
11137 " Time until Graceful Restart stale route deleted: %lu\n",
11141 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
11142 bgp_attr_get_community(attr
) &&
11143 community_include(bgp_attr_get_community(attr
),
11144 COMMUNITY_LLGR_STALE
)) {
11145 unsigned long llgr_remaining
= event_timer_remain_second(
11146 path
->peer
->t_llgr_stale
[afi
][safi
]);
11149 json_object_int_add(json_path
, "llgrSecondsRemaining",
11153 " Time until Long-lived stale route deleted: %lu\n",
11157 /* Output some debug about internal state of the dest flags */
11159 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
11160 json_object_boolean_true_add(json_path
, "processScheduled");
11161 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
11162 json_object_boolean_true_add(json_path
, "userCleared");
11163 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
11164 json_object_boolean_true_add(json_path
, "labelChanged");
11165 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
11166 json_object_boolean_true_add(json_path
, "registeredForLabel");
11167 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
11168 json_object_boolean_true_add(json_path
, "selectDefered");
11169 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
11170 json_object_boolean_true_add(json_path
, "fibInstalled");
11171 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
11172 json_object_boolean_true_add(json_path
, "fibPending");
11174 if (json_nexthop_global
|| json_nexthop_ll
) {
11175 json_nexthops
= json_object_new_array();
11177 if (json_nexthop_global
)
11178 json_object_array_add(json_nexthops
,
11179 json_nexthop_global
);
11181 if (json_nexthop_ll
)
11182 json_object_array_add(json_nexthops
,
11185 json_object_object_add(json_path
, "nexthops",
11189 json_object_object_add(json_path
, "peer", json_peer
);
11190 json_object_array_add(json_paths
, json_path
);
11194 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
11195 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11196 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
11198 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11199 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11201 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11202 const char *comstr
, int exact
, afi_t afi
,
11203 safi_t safi
, uint16_t show_flags
);
11205 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11206 struct bgp_table
*table
, enum bgp_show_type type
,
11207 void *output_arg
, const char *rd
, int is_last
,
11208 unsigned long *output_cum
, unsigned long *total_cum
,
11209 unsigned long *json_header_depth
, uint16_t show_flags
,
11210 enum rpki_states rpki_target_state
)
11212 struct bgp_path_info
*pi
;
11213 struct bgp_dest
*dest
;
11214 bool header
= true;
11215 bool json_detail_header
= false;
11217 unsigned long output_count
= 0;
11218 unsigned long total_count
= 0;
11220 json_object
*json_paths
= NULL
;
11222 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11223 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11224 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11225 bool detail_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
11226 bool detail_routes
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
11228 if (output_cum
&& *output_cum
!= 0)
11231 if (use_json
&& !*json_header_depth
) {
11233 *json_header_depth
= 1;
11235 vty_out(vty
, "{\n");
11236 *json_header_depth
= 2;
11239 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11240 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
11242 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
11243 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
11246 table
->version
, &bgp
->router_id
,
11247 bgp
->default_local_pref
);
11248 if ((bgp
->asnotation
== ASNOTATION_PLAIN
) ||
11249 ((bgp
->asnotation
== ASNOTATION_DOT
) &&
11250 (bgp
->as
< UINT16_MAX
)))
11251 vty_out(vty
, "%u", bgp
->as
);
11253 vty_out(vty
, "\"");
11254 vty_out(vty
, ASN_FORMAT(bgp
->asnotation
), &bgp
->as
);
11255 vty_out(vty
, "\"");
11257 vty_out(vty
, ",\n \"routes\": { ");
11259 vty_out(vty
, " \"routeDistinguishers\" : {");
11260 ++*json_header_depth
;
11264 if (use_json
&& rd
) {
11265 vty_out(vty
, " \"%s\" : { ", rd
);
11268 /* Check for 'json detail', where we need header output once per dest */
11269 if (use_json
&& detail_json
&& type
!= bgp_show_type_dampend_paths
&&
11270 type
!= bgp_show_type_damp_neighbor
&&
11271 type
!= bgp_show_type_flap_statistics
&&
11272 type
!= bgp_show_type_flap_neighbor
)
11273 json_detail_header
= true;
11275 /* Start processing of routes. */
11276 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
11277 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11278 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11279 bool json_detail_header_used
= false;
11281 pi
= bgp_dest_get_bgp_path_info(dest
);
11287 json_paths
= json_object_new_array();
11291 for (; pi
; pi
= pi
->next
) {
11292 struct community
*picomm
= NULL
;
11294 picomm
= bgp_attr_get_community(pi
->attr
);
11298 if (type
== bgp_show_type_prefix_version
) {
11300 strtoul(output_arg
, NULL
, 10);
11301 if (dest
->version
< version
)
11305 if (type
== bgp_show_type_community_alias
) {
11306 char *alias
= output_arg
;
11307 char **communities
;
11309 bool found
= false;
11312 frrstr_split(picomm
->str
, " ",
11313 &communities
, &num
);
11314 for (int i
= 0; i
< num
; i
++) {
11315 const char *com2alias
=
11316 bgp_community2alias(
11319 && strcmp(alias
, com2alias
)
11325 XFREE(MTYPE_TMP
, communities
);
11329 bgp_attr_get_lcommunity(pi
->attr
)) {
11330 frrstr_split(bgp_attr_get_lcommunity(
11333 " ", &communities
, &num
);
11334 for (int i
= 0; i
< num
; i
++) {
11335 const char *com2alias
=
11336 bgp_community2alias(
11339 && strcmp(alias
, com2alias
)
11345 XFREE(MTYPE_TMP
, communities
);
11352 if (type
== bgp_show_type_rpki
) {
11353 if (dest_p
->family
== AF_INET
11354 || dest_p
->family
== AF_INET6
)
11355 rpki_curr_state
= hook_call(
11356 bgp_rpki_prefix_status
,
11357 pi
->peer
, pi
->attr
, dest_p
);
11358 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11359 && rpki_curr_state
!= rpki_target_state
)
11363 if (type
== bgp_show_type_flap_statistics
11364 || type
== bgp_show_type_flap_neighbor
11365 || type
== bgp_show_type_dampend_paths
11366 || type
== bgp_show_type_damp_neighbor
) {
11367 if (!(pi
->extra
&& pi
->extra
->damp_info
))
11370 if (type
== bgp_show_type_regexp
) {
11371 regex_t
*regex
= output_arg
;
11373 if (bgp_regexec(regex
, pi
->attr
->aspath
)
11377 if (type
== bgp_show_type_prefix_list
) {
11378 struct prefix_list
*plist
= output_arg
;
11380 if (prefix_list_apply(plist
, dest_p
)
11384 if (type
== bgp_show_type_access_list
) {
11385 struct access_list
*alist
= output_arg
;
11387 if (access_list_apply(alist
, dest_p
) !=
11391 if (type
== bgp_show_type_filter_list
) {
11392 struct as_list
*as_list
= output_arg
;
11394 if (as_list_apply(as_list
, pi
->attr
->aspath
)
11395 != AS_FILTER_PERMIT
)
11398 if (type
== bgp_show_type_route_map
) {
11399 struct route_map
*rmap
= output_arg
;
11400 struct bgp_path_info path
;
11401 struct bgp_path_info_extra extra
;
11402 struct attr dummy_attr
= {};
11403 route_map_result_t ret
;
11405 dummy_attr
= *pi
->attr
;
11407 prep_for_rmap_apply(&path
, &extra
, dest
, pi
,
11408 pi
->peer
, &dummy_attr
);
11410 ret
= route_map_apply(rmap
, dest_p
, &path
);
11411 bgp_attr_flush(&dummy_attr
);
11412 if (ret
== RMAP_DENYMATCH
)
11415 if (type
== bgp_show_type_neighbor
11416 || type
== bgp_show_type_flap_neighbor
11417 || type
== bgp_show_type_damp_neighbor
) {
11418 union sockunion
*su
= output_arg
;
11420 if (pi
->peer
== NULL
11421 || pi
->peer
->su_remote
== NULL
11422 || !sockunion_same(pi
->peer
->su_remote
, su
))
11425 if (type
== bgp_show_type_cidr_only
) {
11426 uint32_t destination
;
11428 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11429 if (IN_CLASSC(destination
)
11430 && dest_p
->prefixlen
== 24)
11432 if (IN_CLASSB(destination
)
11433 && dest_p
->prefixlen
== 16)
11435 if (IN_CLASSA(destination
)
11436 && dest_p
->prefixlen
== 8)
11439 if (type
== bgp_show_type_prefix_longer
) {
11441 if (!prefix_match(p
, dest_p
))
11444 if (type
== bgp_show_type_community_all
) {
11448 if (type
== bgp_show_type_community
) {
11449 struct community
*com
= output_arg
;
11451 if (!picomm
|| !community_match(picomm
, com
))
11454 if (type
== bgp_show_type_community_exact
) {
11455 struct community
*com
= output_arg
;
11457 if (!picomm
|| !community_cmp(picomm
, com
))
11460 if (type
== bgp_show_type_community_list
) {
11461 struct community_list
*list
= output_arg
;
11463 if (!community_list_match(picomm
, list
))
11466 if (type
== bgp_show_type_community_list_exact
) {
11467 struct community_list
*list
= output_arg
;
11469 if (!community_list_exact_match(picomm
, list
))
11472 if (type
== bgp_show_type_lcommunity
) {
11473 struct lcommunity
*lcom
= output_arg
;
11475 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11477 bgp_attr_get_lcommunity(pi
->attr
),
11482 if (type
== bgp_show_type_lcommunity_exact
) {
11483 struct lcommunity
*lcom
= output_arg
;
11485 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11487 bgp_attr_get_lcommunity(pi
->attr
),
11491 if (type
== bgp_show_type_lcommunity_list
) {
11492 struct community_list
*list
= output_arg
;
11494 if (!lcommunity_list_match(
11495 bgp_attr_get_lcommunity(pi
->attr
),
11500 == bgp_show_type_lcommunity_list_exact
) {
11501 struct community_list
*list
= output_arg
;
11503 if (!lcommunity_list_exact_match(
11504 bgp_attr_get_lcommunity(pi
->attr
),
11508 if (type
== bgp_show_type_lcommunity_all
) {
11509 if (!bgp_attr_get_lcommunity(pi
->attr
))
11512 if (type
== bgp_show_type_dampend_paths
11513 || type
== bgp_show_type_damp_neighbor
) {
11514 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11515 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11518 if (type
== bgp_show_type_self_originated
) {
11519 if (pi
->peer
!= bgp
->peer_self
)
11523 if (!use_json
&& header
) {
11525 "BGP table version is %" PRIu64
11526 ", local router ID is %pI4, vrf id ",
11527 table
->version
, &bgp
->router_id
);
11528 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11529 vty_out(vty
, "%s", VRFID_NONE_STR
);
11531 vty_out(vty
, "%u", bgp
->vrf_id
);
11532 vty_out(vty
, "\n");
11533 vty_out(vty
, "Default local pref %u, ",
11534 bgp
->default_local_pref
);
11535 vty_out(vty
, "local AS ");
11536 vty_out(vty
, ASN_FORMAT(bgp
->asnotation
),
11538 vty_out(vty
, "\n");
11539 if (!detail_routes
) {
11540 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11541 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11542 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11543 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11545 if (type
== bgp_show_type_dampend_paths
11546 || type
== bgp_show_type_damp_neighbor
)
11547 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11548 else if (type
== bgp_show_type_flap_statistics
11549 || type
== bgp_show_type_flap_neighbor
)
11550 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11551 else if (!detail_routes
)
11552 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11553 : BGP_SHOW_HEADER
));
11557 if (rd
!= NULL
&& !display
&& !output_count
) {
11560 "Route Distinguisher: %s\n",
11563 if (type
== bgp_show_type_dampend_paths
11564 || type
== bgp_show_type_damp_neighbor
)
11565 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11566 AFI_IP
, safi
, use_json
,
11568 else if (type
== bgp_show_type_flap_statistics
11569 || type
== bgp_show_type_flap_neighbor
)
11570 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11571 AFI_IP
, safi
, use_json
,
11574 if (detail_routes
|| detail_json
) {
11575 const struct prefix_rd
*prd
= NULL
;
11578 prd
= bgp_rd_from_dest(
11579 dest
->pdest
, safi
);
11582 route_vty_out_detail_header(
11584 bgp_dest_get_prefix(
11586 prd
, table
->afi
, safi
,
11589 route_vty_out_detail(
11590 vty
, bgp
, dest
, dest_p
, pi
,
11591 family2afi(dest_p
->family
),
11592 safi
, RPKI_NOT_BEING_USED
,
11595 route_vty_out(vty
, dest_p
, pi
, display
,
11596 safi
, json_paths
, wide
);
11607 /* encode prefix */
11608 if (dest_p
->family
== AF_FLOWSPEC
) {
11609 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11612 bgp_fs_nlri_get_string(
11614 dest_p
->u
.prefix_flowspec
.ptr
,
11615 dest_p
->u
.prefix_flowspec
.prefixlen
,
11616 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11617 family2afi(dest_p
->u
11618 .prefix_flowspec
.family
));
11620 vty_out(vty
, "\"%s/%d\": ", retstr
,
11621 dest_p
->u
.prefix_flowspec
11624 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11625 dest_p
->u
.prefix_flowspec
11629 vty_out(vty
, "\"%pFX\": ", dest_p
);
11631 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11634 /* This is used for 'json detail' vty keywords.
11636 * In plain 'json' the per-prefix header is encoded
11637 * as a standalone dictionary in the first json_paths
11639 * "<prefix>": [{header}, {path-1}, {path-N}]
11640 * (which is confusing and borderline broken)
11642 * For 'json detail' this changes the value
11643 * of each prefix-key to be a dictionary where each
11644 * header item has its own key, and json_paths is
11645 * tucked under the "paths" key:
11647 * "<header-key-1>": <header-val-1>,
11648 * "<header-key-N>": <header-val-N>,
11649 * "paths": [{path-1}, {path-N}]
11652 if (json_detail_header
&& json_paths
!= NULL
) {
11653 const struct prefix_rd
*prd
;
11655 /* Start per-prefix dictionary */
11656 vty_out(vty
, "{\n");
11658 prd
= bgp_rd_from_dest(dest
, safi
);
11660 route_vty_out_detail_header(
11662 bgp_dest_get_prefix(dest
), prd
,
11663 table
->afi
, safi
, json_paths
, true);
11665 vty_out(vty
, "\"paths\": ");
11666 json_detail_header_used
= true;
11670 * We are using no_pretty here because under
11671 * extremely high settings( say lots and lots of
11672 * routes with lots and lots of ways to reach
11673 * that route via different paths ) this can
11674 * save several minutes of output when FRR
11675 * is run on older cpu's or more underperforming
11676 * routers out there
11678 vty_json_no_pretty(vty
, json_paths
);
11680 /* End per-prefix dictionary */
11681 if (json_detail_header_used
)
11682 vty_out(vty
, "} ");
11687 json_object_free(json_paths
);
11691 output_count
+= *output_cum
;
11692 *output_cum
= output_count
;
11695 total_count
+= *total_cum
;
11696 *total_cum
= total_count
;
11700 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11704 for (i
= 0; i
< *json_header_depth
; ++i
)
11705 vty_out(vty
, " } ");
11707 vty_out(vty
, "\n");
11711 /* No route is displayed */
11712 if (output_count
== 0) {
11713 if (type
== bgp_show_type_normal
)
11715 "No BGP prefixes displayed, %ld exist\n",
11719 "\nDisplayed %ld routes and %ld total paths\n",
11720 output_count
, total_count
);
11724 return CMD_SUCCESS
;
11727 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11728 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11729 enum bgp_show_type type
, void *output_arg
,
11730 uint16_t show_flags
)
11732 struct bgp_dest
*dest
, *next
;
11733 unsigned long output_cum
= 0;
11734 unsigned long total_cum
= 0;
11735 unsigned long json_header_depth
= 0;
11736 struct bgp_table
*itable
;
11738 bool use_json
= !!CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11740 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11742 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11743 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11745 next
= bgp_route_next(dest
);
11746 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11749 itable
= bgp_dest_get_bgp_table_info(dest
);
11750 if (itable
!= NULL
) {
11751 struct prefix_rd prd
;
11752 char rd
[RD_ADDRSTRLEN
];
11754 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11755 prefix_rd2str(&prd
, rd
, sizeof(rd
), bgp
->asnotation
);
11756 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11757 rd
, next
== NULL
, &output_cum
,
11758 &total_cum
, &json_header_depth
,
11759 show_flags
, RPKI_NOT_BEING_USED
);
11765 if (output_cum
== 0)
11766 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11770 "\nDisplayed %ld routes and %ld total paths\n",
11771 output_cum
, total_cum
);
11773 if (use_json
&& output_cum
== 0)
11774 vty_out(vty
, "{}\n");
11776 return CMD_SUCCESS
;
11779 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11780 enum bgp_show_type type
, void *output_arg
,
11781 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11783 struct bgp_table
*table
;
11784 unsigned long json_header_depth
= 0;
11785 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11788 bgp
= bgp_get_default();
11793 vty_out(vty
, "No BGP process is configured\n");
11795 vty_out(vty
, "{}\n");
11796 return CMD_WARNING
;
11799 /* Labeled-unicast routes live in the unicast table. */
11800 if (safi
== SAFI_LABELED_UNICAST
)
11801 safi
= SAFI_UNICAST
;
11803 table
= bgp
->rib
[afi
][safi
];
11804 /* use MPLS and ENCAP specific shows until they are merged */
11805 if (safi
== SAFI_MPLS_VPN
) {
11806 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11807 output_arg
, show_flags
);
11810 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11811 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11812 output_arg
, use_json
,
11816 if (safi
== SAFI_EVPN
)
11817 return bgp_evpn_show_all_routes(vty
, bgp
, type
, use_json
, 0);
11819 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11820 NULL
, NULL
, &json_header_depth
, show_flags
,
11821 rpki_target_state
);
11824 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11825 safi_t safi
, uint16_t show_flags
)
11827 struct listnode
*node
, *nnode
;
11830 bool route_output
= false;
11831 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11834 vty_out(vty
, "{\n");
11836 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11837 route_output
= true;
11840 vty_out(vty
, ",\n");
11844 vty_out(vty
, "\"%s\":",
11845 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11849 vty_out(vty
, "\nInstance %s:\n",
11850 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11854 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11855 show_flags
, RPKI_NOT_BEING_USED
);
11859 vty_out(vty
, "}\n");
11860 else if (!route_output
)
11861 vty_out(vty
, "%% BGP instance not found\n");
11864 /* Header of detailed BGP route information */
11865 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11866 struct bgp_dest
*dest
, const struct prefix
*p
,
11867 const struct prefix_rd
*prd
, afi_t afi
,
11868 safi_t safi
, json_object
*json
,
11869 bool incremental_print
)
11871 struct bgp_path_info
*pi
;
11873 struct listnode
*node
, *nnode
;
11874 char buf1
[RD_ADDRSTRLEN
];
11878 int accept_own
= 0;
11879 int route_filter_translated_v4
= 0;
11880 int route_filter_v4
= 0;
11881 int route_filter_translated_v6
= 0;
11882 int route_filter_v6
= 0;
11883 int llgr_stale
= 0;
11885 int accept_own_nexthop
= 0;
11888 int no_advertise
= 0;
11892 int has_valid_label
= 0;
11893 mpls_label_t label
= 0;
11894 json_object
*json_adv_to
= NULL
;
11899 mpls_lse_decode(dest
->local_label
, &label
, &ttl
, &exp
, &bos
);
11901 has_valid_label
= bgp_is_valid_label(&label
);
11903 if (safi
== SAFI_EVPN
) {
11905 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11906 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
),
11909 prd
? ":" : "", (struct prefix_evpn
*)p
);
11911 json_object_string_add(
11913 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
),
11916 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11921 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11923 (((safi
== SAFI_MPLS_VPN
||
11924 safi
== SAFI_ENCAP
) &&
11926 ? prefix_rd2str(prd
, buf1
,
11930 safi
== SAFI_MPLS_VPN
&& prd
? ":" : "", p
,
11934 if (incremental_print
) {
11935 vty_out(vty
, "\"prefix\": \"%pFX\",\n", p
);
11936 vty_out(vty
, "\"version\": \"%" PRIu64
"\",\n",
11939 json_object_string_addf(json
, "prefix", "%pFX",
11941 json_object_int_add(json
, "version",
11947 if (has_valid_label
) {
11949 if (incremental_print
)
11950 vty_out(vty
, "\"localLabel\": \"%u\",\n",
11953 json_object_int_add(json
, "localLabel", label
);
11955 vty_out(vty
, "Local label: %d\n", label
);
11959 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11960 vty_out(vty
, "not allocated\n");
11962 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11963 struct community
*picomm
= NULL
;
11965 picomm
= bgp_attr_get_community(pi
->attr
);
11968 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11970 if (bgp_path_suppressed(pi
))
11976 no_advertise
+= community_include(
11977 picomm
, COMMUNITY_NO_ADVERTISE
);
11979 community_include(picomm
, COMMUNITY_NO_EXPORT
);
11981 community_include(picomm
, COMMUNITY_LOCAL_AS
);
11983 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
11984 route_filter_translated_v4
+= community_include(
11985 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11986 route_filter_translated_v6
+= community_include(
11987 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11988 route_filter_v4
+= community_include(
11989 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
11990 route_filter_v6
+= community_include(
11991 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
11993 community_include(picomm
, COMMUNITY_LLGR_STALE
);
11994 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
11995 accept_own_nexthop
+= community_include(
11996 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11998 community_include(picomm
, COMMUNITY_BLACKHOLE
);
11999 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
12004 vty_out(vty
, "Paths: (%d available", count
);
12006 vty_out(vty
, ", best #%d", best
);
12007 if (safi
== SAFI_UNICAST
) {
12008 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
12009 vty_out(vty
, ", table %s",
12012 vty_out(vty
, ", vrf %s",
12016 vty_out(vty
, ", no best path");
12020 ", accept own local route exported and imported in different VRF");
12021 else if (route_filter_translated_v4
)
12023 ", mark translated RTs for VPNv4 route filtering");
12024 else if (route_filter_v4
)
12026 ", attach RT as-is for VPNv4 route filtering");
12027 else if (route_filter_translated_v6
)
12029 ", mark translated RTs for VPNv6 route filtering");
12030 else if (route_filter_v6
)
12032 ", attach RT as-is for VPNv6 route filtering");
12033 else if (llgr_stale
)
12035 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
12038 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
12039 else if (accept_own_nexthop
)
12041 ", accept local nexthop");
12042 else if (blackhole
)
12043 vty_out(vty
, ", inform peer to blackhole prefix");
12044 else if (no_export
)
12045 vty_out(vty
, ", not advertised to EBGP peer");
12046 else if (no_advertise
)
12047 vty_out(vty
, ", not advertised to any peer");
12049 vty_out(vty
, ", not advertised outside local AS");
12052 ", inform EBGP peer not to advertise to their EBGP peers");
12056 ", Advertisements suppressed by an aggregate.");
12057 vty_out(vty
, ")\n");
12060 /* If we are not using addpath then we can display Advertised to and
12062 * show what peers we advertised the bestpath to. If we are using
12064 * though then we must display Advertised to on a path-by-path basis. */
12065 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
12066 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
12067 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
12068 if (json
&& !json_adv_to
)
12069 json_adv_to
= json_object_new_object();
12071 route_vty_out_advertised_to(
12073 " Advertised to non peer-group peers:\n ",
12078 if (json
&& json_adv_to
) {
12079 if (incremental_print
) {
12080 vty_out(vty
, "\"advertisedTo\": ");
12081 vty_json(vty
, json_adv_to
);
12084 json_object_object_add(json
, "advertisedTo",
12087 if (!json
&& first
)
12088 vty_out(vty
, " Not advertised to any peer");
12089 vty_out(vty
, "\n");
12094 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
12095 struct bgp_dest
*bgp_node
, struct vty
*vty
,
12096 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
12097 json_object
*json
, enum bgp_path_type pathtype
,
12098 int *display
, enum rpki_states rpki_target_state
)
12100 struct bgp_path_info
*pi
;
12102 json_object
*json_header
= NULL
;
12103 json_object
*json_paths
= NULL
;
12104 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
12106 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
12107 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
12109 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
12110 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
12111 pi
->peer
, pi
->attr
, p
);
12113 if (rpki_target_state
!= RPKI_NOT_BEING_USED
12114 && rpki_curr_state
!= rpki_target_state
)
12117 if (json
&& !json_paths
) {
12118 /* Instantiate json_paths only if path is valid */
12119 json_paths
= json_object_new_array();
12121 json_header
= json_object_new_object();
12123 json_header
= json
;
12127 route_vty_out_detail_header(
12128 vty
, bgp
, bgp_node
,
12129 bgp_dest_get_prefix(bgp_node
), pfx_rd
, AFI_IP
,
12130 safi
, json_header
, false);
12135 if (pathtype
== BGP_PATH_SHOW_ALL
12136 || (pathtype
== BGP_PATH_SHOW_BESTPATH
12137 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12138 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
12139 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
12140 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
12141 route_vty_out_detail(vty
, bgp
, bgp_node
,
12142 bgp_dest_get_prefix(bgp_node
), pi
,
12143 AFI_IP
, safi
, rpki_curr_state
,
12147 if (json
&& json_paths
) {
12148 json_object_object_add(json_header
, "paths", json_paths
);
12151 json_object_object_addf(
12153 BGP_RD_AS_FORMAT(bgp
->asnotation
), pfx_rd
);
12158 * Return rd based on safi
12160 const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
12164 case SAFI_MPLS_VPN
:
12167 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
12170 case SAFI_MULTICAST
:
12171 case SAFI_LABELED_UNICAST
:
12172 case SAFI_FLOWSPEC
:
12177 assert(!"Reached end of function when we were not expecting it");
12180 /* Display specified route of BGP table. */
12181 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
12182 struct bgp_table
*rib
, const char *ip_str
,
12183 afi_t afi
, safi_t safi
,
12184 enum rpki_states rpki_target_state
,
12185 struct prefix_rd
*prd
, int prefix_check
,
12186 enum bgp_path_type pathtype
, bool use_json
)
12190 struct prefix match
;
12191 struct bgp_dest
*dest
;
12192 struct bgp_dest
*rm
;
12193 struct bgp_table
*table
;
12194 json_object
*json
= NULL
;
12195 json_object
*json_paths
= NULL
;
12197 /* Check IP address argument. */
12198 ret
= str2prefix(ip_str
, &match
);
12200 vty_out(vty
, "address is malformed\n");
12201 return CMD_WARNING
;
12204 match
.family
= afi2family(afi
);
12207 json
= json_object_new_object();
12209 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
12210 for (dest
= bgp_table_top(rib
); dest
;
12211 dest
= bgp_route_next(dest
)) {
12212 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12214 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
12216 table
= bgp_dest_get_bgp_table_info(dest
);
12220 rm
= bgp_node_match(table
, &match
);
12224 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
12226 && rm_p
->prefixlen
!= match
.prefixlen
) {
12227 bgp_dest_unlock_node(rm
);
12231 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12232 bgp
, afi
, safi
, json
, pathtype
,
12233 &display
, rpki_target_state
);
12235 bgp_dest_unlock_node(rm
);
12237 } else if (safi
== SAFI_EVPN
) {
12238 struct bgp_dest
*longest_pfx
;
12239 bool is_exact_pfxlen_match
= false;
12241 for (dest
= bgp_table_top(rib
); dest
;
12242 dest
= bgp_route_next(dest
)) {
12243 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12245 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
12247 table
= bgp_dest_get_bgp_table_info(dest
);
12251 longest_pfx
= NULL
;
12252 is_exact_pfxlen_match
= false;
12254 * Search through all the prefixes for a match. The
12255 * pfx's are enumerated in ascending order of pfxlens.
12256 * So, the last pfx match is the longest match. Set
12257 * is_exact_pfxlen_match when we get exact pfxlen match
12259 for (rm
= bgp_table_top(table
); rm
;
12260 rm
= bgp_route_next(rm
)) {
12261 const struct prefix
*rm_p
=
12262 bgp_dest_get_prefix(rm
);
12264 * Get prefixlen of the ip-prefix within type5
12267 if (evpn_type5_prefix_match(rm_p
, &match
)
12271 bgp_evpn_get_type5_prefixlen(
12273 if (type5_pfxlen
== match
.prefixlen
) {
12274 is_exact_pfxlen_match
= true;
12275 bgp_dest_unlock_node(rm
);
12284 if (prefix_check
&& !is_exact_pfxlen_match
)
12288 bgp_dest_lock_node(rm
);
12290 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12291 bgp
, afi
, safi
, json
, pathtype
,
12292 &display
, rpki_target_state
);
12294 bgp_dest_unlock_node(rm
);
12296 } else if (safi
== SAFI_FLOWSPEC
) {
12298 json_paths
= json_object_new_array();
12300 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
12301 &match
, prefix_check
,
12307 json_object_object_add(json
, "paths",
12310 json_object_free(json_paths
);
12313 dest
= bgp_node_match(rib
, &match
);
12314 if (dest
!= NULL
) {
12315 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12317 || dest_p
->prefixlen
== match
.prefixlen
) {
12318 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
12319 safi
, json
, pathtype
,
12320 &display
, rpki_target_state
);
12323 bgp_dest_unlock_node(dest
);
12328 vty_json(vty
, json
);
12331 vty_out(vty
, "%% Network not in table\n");
12332 return CMD_WARNING
;
12336 return CMD_SUCCESS
;
12339 /* Display specified route of Main RIB */
12340 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
12341 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
12342 int prefix_check
, enum bgp_path_type pathtype
,
12343 enum rpki_states rpki_target_state
, bool use_json
)
12346 bgp
= bgp_get_default();
12349 vty_out(vty
, "No BGP process is configured\n");
12351 vty_out(vty
, "{}\n");
12352 return CMD_WARNING
;
12356 /* labeled-unicast routes live in the unicast table */
12357 if (safi
== SAFI_LABELED_UNICAST
)
12358 safi
= SAFI_UNICAST
;
12360 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
12361 afi
, safi
, rpki_target_state
, prd
,
12362 prefix_check
, pathtype
, use_json
);
12365 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
12366 struct cmd_token
**argv
, bool exact
, afi_t afi
,
12367 safi_t safi
, bool uj
)
12369 struct lcommunity
*lcom
;
12374 uint16_t show_flags
= 0;
12378 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12380 b
= buffer_new(1024);
12381 for (i
= 0; i
< argc
; i
++) {
12383 buffer_putc(b
, ' ');
12385 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
12387 buffer_putstr(b
, argv
[i
]->arg
);
12391 buffer_putc(b
, '\0');
12393 str
= buffer_getstr(b
);
12396 lcom
= lcommunity_str2com(str
);
12397 XFREE(MTYPE_TMP
, str
);
12399 vty_out(vty
, "%% Large-community malformed\n");
12400 return CMD_WARNING
;
12403 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12404 (exact
? bgp_show_type_lcommunity_exact
12405 : bgp_show_type_lcommunity
),
12406 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
12408 lcommunity_free(&lcom
);
12412 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
12413 const char *lcom
, bool exact
, afi_t afi
,
12414 safi_t safi
, bool uj
)
12416 struct community_list
*list
;
12417 uint16_t show_flags
= 0;
12420 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12423 list
= community_list_lookup(bgp_clist
, lcom
, 0,
12424 LARGE_COMMUNITY_LIST_MASTER
);
12425 if (list
== NULL
) {
12426 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
12428 return CMD_WARNING
;
12431 return bgp_show(vty
, bgp
, afi
, safi
,
12432 (exact
? bgp_show_type_lcommunity_list_exact
12433 : bgp_show_type_lcommunity_list
),
12434 list
, show_flags
, RPKI_NOT_BEING_USED
);
12437 DEFUN (show_ip_bgp_large_community_list
,
12438 show_ip_bgp_large_community_list_cmd
,
12439 "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]",
12443 BGP_INSTANCE_HELP_STR
12445 BGP_SAFI_WITH_LABEL_HELP_STR
12446 "Display routes matching the large-community-list\n"
12447 "large-community-list number\n"
12448 "large-community-list name\n"
12449 "Exact match of the large-communities\n"
12452 afi_t afi
= AFI_IP6
;
12453 safi_t safi
= SAFI_UNICAST
;
12455 bool exact_match
= 0;
12456 struct bgp
*bgp
= NULL
;
12457 bool uj
= use_json(argc
, argv
);
12462 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12465 return CMD_WARNING
;
12467 argv_find(argv
, argc
, "large-community-list", &idx
);
12469 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12471 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
12474 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
12475 exact_match
, afi
, safi
, uj
);
12477 DEFUN (show_ip_bgp_large_community
,
12478 show_ip_bgp_large_community_cmd
,
12479 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
12483 BGP_INSTANCE_HELP_STR
12485 BGP_SAFI_WITH_LABEL_HELP_STR
12486 "Display routes matching the large-communities\n"
12487 "List of large-community numbers\n"
12488 "Exact match of the large-communities\n"
12491 afi_t afi
= AFI_IP6
;
12492 safi_t safi
= SAFI_UNICAST
;
12494 bool exact_match
= 0;
12495 struct bgp
*bgp
= NULL
;
12496 bool uj
= use_json(argc
, argv
);
12497 uint16_t show_flags
= 0;
12501 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12504 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12507 return CMD_WARNING
;
12509 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12510 if (argv_find(argv
, argc
, "exact-match", &idx
)) {
12514 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12515 exact_match
, afi
, safi
, uj
);
12517 return bgp_show(vty
, bgp
, afi
, safi
,
12518 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12519 RPKI_NOT_BEING_USED
);
12522 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12523 safi_t safi
, struct json_object
*json_array
);
12524 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12525 safi_t safi
, struct json_object
*json
);
12528 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12529 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12530 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12531 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12533 bool uj
= use_json(argc
, argv
);
12534 struct bgp
*bgp
= NULL
;
12535 safi_t safi
= SAFI_UNICAST
;
12536 afi_t afi
= AFI_IP6
;
12538 struct json_object
*json_all
= NULL
;
12539 struct json_object
*json_afi_safi
= NULL
;
12541 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12544 return CMD_WARNING
;
12547 json_all
= json_object_new_object();
12549 FOREACH_AFI_SAFI (afi
, safi
) {
12551 * So limit output to those afi/safi pairs that
12552 * actually have something interesting in them
12554 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12559 json_afi_safi
= json_object_new_array();
12560 json_object_object_add(
12562 get_afi_safi_str(afi
, safi
, true),
12565 json_afi_safi
= NULL
;
12568 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12572 vty_json(vty
, json_all
);
12574 return CMD_SUCCESS
;
12577 /* BGP route print out function without JSON */
12578 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12579 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12580 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12584 BGP_INSTANCE_HELP_STR
12587 "BGP RIB advertisement statistics\n"
12590 afi_t afi
= AFI_IP6
;
12591 safi_t safi
= SAFI_UNICAST
;
12592 struct bgp
*bgp
= NULL
;
12594 bool uj
= use_json(argc
, argv
);
12595 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12597 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12600 return CMD_WARNING
;
12603 json_afi_safi
= json_object_new_array();
12605 json_afi_safi
= NULL
;
12607 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12610 json
= json_object_new_object();
12611 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12613 vty_json(vty
, json
);
12618 /* BGP route print out function without JSON */
12619 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12620 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12621 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12623 statistics [json]",
12624 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12625 BGP_SAFI_WITH_LABEL_HELP_STR
12626 "BGP RIB advertisement statistics\n" JSON_STR
)
12628 afi_t afi
= AFI_IP6
;
12629 safi_t safi
= SAFI_UNICAST
;
12630 struct bgp
*bgp
= NULL
;
12632 bool uj
= use_json(argc
, argv
);
12633 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12635 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12638 return CMD_WARNING
;
12641 json_afi_safi
= json_object_new_array();
12643 json_afi_safi
= NULL
;
12645 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12648 json
= json_object_new_object();
12649 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12651 vty_json(vty
, json
);
12656 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12657 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12658 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12659 "]] [all$all] dampening parameters [json]",
12660 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12661 BGP_SAFI_WITH_LABEL_HELP_STR
12662 "Display the entries for all address families\n"
12663 "Display detailed information about dampening\n"
12664 "Display detail of configured dampening parameters\n"
12667 afi_t afi
= AFI_IP6
;
12668 safi_t safi
= SAFI_UNICAST
;
12669 struct bgp
*bgp
= NULL
;
12671 uint16_t show_flags
= 0;
12672 bool uj
= use_json(argc
, argv
);
12676 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12679 /* [<ipv4|ipv6> [all]] */
12681 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12682 if (argv_find(argv
, argc
, "ipv4", &idx
))
12683 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12685 if (argv_find(argv
, argc
, "ipv6", &idx
))
12686 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12689 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12692 return CMD_WARNING
;
12694 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12697 /* BGP route print out function */
12698 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12699 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12700 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12704 |dampening <flap-statistics|dampened-paths>\
12705 |community [AA:NN|local-AS|no-advertise|no-export\
12706 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12707 |accept-own|accept-own-nexthop|route-filter-v6\
12708 |route-filter-v4|route-filter-translated-v6\
12709 |route-filter-translated-v4] [exact-match]\
12710 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12711 |filter-list AS_PATH_FILTER_NAME\
12713 |access-list ACCESSLIST_NAME\
12714 |route-map RMAP_NAME\
12715 |rpki <invalid|valid|notfound>\
12716 |version (1-4294967295)\
12718 |A.B.C.D/M longer-prefixes\
12719 |X:X::X:X/M longer-prefixes\
12720 |"BGP_SELF_ORIG_CMD_STR
"\
12721 |detail-routes$detail_routes\
12722 ] [json$uj [detail$detail_json] | wide$wide]",
12723 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12724 BGP_SAFI_WITH_LABEL_HELP_STR
12725 "Display the entries for all address families\n"
12726 "Display only routes with non-natural netmasks\n"
12727 "Display detailed information about dampening\n"
12728 "Display flap statistics of routes\n"
12729 "Display paths suppressed due to dampening\n"
12730 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12731 "Do not send outside local AS (well-known community)\n"
12732 "Do not advertise to any peer (well-known community)\n"
12733 "Do not export to next AS (well-known community)\n"
12734 "Graceful shutdown (well-known community)\n"
12735 "Do not export to any peer (well-known community)\n"
12736 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12737 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12738 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12739 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12740 "Should accept VPN route with local nexthop (well-known community)\n"
12741 "RT VPNv6 route filtering (well-known community)\n"
12742 "RT VPNv4 route filtering (well-known community)\n"
12743 "RT translated VPNv6 route filtering (well-known community)\n"
12744 "RT translated VPNv4 route filtering (well-known community)\n"
12745 "Exact match of the communities\n"
12746 "Community-list number\n"
12747 "Community-list name\n"
12748 "Display routes matching the community-list\n"
12749 "Exact match of the communities\n"
12750 "Display routes conforming to the filter-list\n"
12751 "Regular expression access list name\n"
12752 "Display routes conforming to the prefix-list\n"
12753 "Prefix-list name\n"
12754 "Display routes conforming to the access-list\n"
12755 "Access-list name\n"
12756 "Display routes matching the route-map\n"
12757 "A route-map to match on\n"
12758 "RPKI route types\n"
12759 "A valid path as determined by rpki\n"
12760 "A invalid path as determined by rpki\n"
12761 "A path that has no rpki data\n"
12762 "Display prefixes with matching version numbers\n"
12763 "Version number and above\n"
12764 "Display prefixes with matching BGP community alias\n"
12765 "BGP community alias\n"
12767 "Display route and more specific routes\n"
12769 "Display route and more specific routes\n"
12770 BGP_SELF_ORIG_HELP_STR
12771 "Display detailed version of all routes\n"
12773 "Display detailed version of JSON output\n"
12774 "Increase table width for longer prefixes\n")
12776 afi_t afi
= AFI_IP6
;
12777 safi_t safi
= SAFI_UNICAST
;
12778 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12779 void *output_arg
= NULL
;
12780 struct bgp
*bgp
= NULL
;
12782 int exact_match
= 0;
12783 char *community
= NULL
;
12785 uint16_t show_flags
= 0;
12786 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12791 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12795 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
12798 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
12800 /* [<ipv4|ipv6> [all]] */
12802 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12804 if (argv_find(argv
, argc
, "ipv4", &idx
))
12805 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12807 if (argv_find(argv
, argc
, "ipv6", &idx
))
12808 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12812 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12814 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12817 return CMD_WARNING
;
12819 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12820 sh_type
= bgp_show_type_cidr_only
;
12822 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12823 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12824 sh_type
= bgp_show_type_dampend_paths
;
12825 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12826 sh_type
= bgp_show_type_flap_statistics
;
12829 if (argv_find(argv
, argc
, "community", &idx
)) {
12830 char *maybecomm
= NULL
;
12832 if (idx
+ 1 < argc
) {
12833 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12834 maybecomm
= argv
[idx
+ 1]->arg
;
12836 maybecomm
= argv
[idx
+ 1]->text
;
12839 if (maybecomm
&& !strmatch(maybecomm
, "json")
12840 && !strmatch(maybecomm
, "exact-match"))
12841 community
= maybecomm
;
12843 if (argv_find(argv
, argc
, "exact-match", &idx
))
12847 sh_type
= bgp_show_type_community_all
;
12850 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12851 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12852 struct community_list
*list
;
12854 if (argv_find(argv
, argc
, "exact-match", &idx
))
12857 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12858 COMMUNITY_LIST_MASTER
);
12859 if (list
== NULL
) {
12860 vty_out(vty
, "%% %s community-list not found\n",
12861 clist_number_or_name
);
12862 return CMD_WARNING
;
12866 sh_type
= bgp_show_type_community_list_exact
;
12868 sh_type
= bgp_show_type_community_list
;
12872 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12873 const char *filter
= argv
[++idx
]->arg
;
12874 struct as_list
*as_list
;
12876 as_list
= as_list_lookup(filter
);
12877 if (as_list
== NULL
) {
12878 vty_out(vty
, "%% %s AS-path access-list not found\n",
12880 return CMD_WARNING
;
12883 sh_type
= bgp_show_type_filter_list
;
12884 output_arg
= as_list
;
12887 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12888 const char *prefix_list_str
= argv
[++idx
]->arg
;
12889 struct prefix_list
*plist
;
12891 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12892 if (plist
== NULL
) {
12893 vty_out(vty
, "%% %s prefix-list not found\n",
12895 return CMD_WARNING
;
12898 sh_type
= bgp_show_type_prefix_list
;
12899 output_arg
= plist
;
12902 if (argv_find(argv
, argc
, "access-list", &idx
)) {
12903 const char *access_list_str
= argv
[++idx
]->arg
;
12904 struct access_list
*alist
;
12906 alist
= access_list_lookup(afi
, access_list_str
);
12908 vty_out(vty
, "%% %s access-list not found\n",
12910 return CMD_WARNING
;
12913 sh_type
= bgp_show_type_access_list
;
12914 output_arg
= alist
;
12917 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12918 const char *rmap_str
= argv
[++idx
]->arg
;
12919 struct route_map
*rmap
;
12921 rmap
= route_map_lookup_by_name(rmap_str
);
12923 vty_out(vty
, "%% %s route-map not found\n", rmap_str
);
12924 return CMD_WARNING
;
12927 sh_type
= bgp_show_type_route_map
;
12931 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12932 sh_type
= bgp_show_type_rpki
;
12933 if (argv_find(argv
, argc
, "valid", &idx
))
12934 rpki_target_state
= RPKI_VALID
;
12935 else if (argv_find(argv
, argc
, "invalid", &idx
))
12936 rpki_target_state
= RPKI_INVALID
;
12939 /* Display prefixes with matching version numbers */
12940 if (argv_find(argv
, argc
, "version", &idx
)) {
12941 sh_type
= bgp_show_type_prefix_version
;
12942 output_arg
= argv
[idx
+ 1]->arg
;
12945 /* Display prefixes with matching BGP community alias */
12946 if (argv_find(argv
, argc
, "alias", &idx
)) {
12947 sh_type
= bgp_show_type_community_alias
;
12948 output_arg
= argv
[idx
+ 1]->arg
;
12951 /* prefix-longer */
12952 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12953 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12954 const char *prefix_str
= argv
[idx
]->arg
;
12956 if (!str2prefix(prefix_str
, &p
)) {
12957 vty_out(vty
, "%% Malformed Prefix\n");
12958 return CMD_WARNING
;
12961 sh_type
= bgp_show_type_prefix_longer
;
12965 /* self originated only */
12966 if (argv_find(argv
, argc
, BGP_SELF_ORIG_CMD_STR
, &idx
))
12967 sh_type
= bgp_show_type_self_originated
;
12970 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12972 return bgp_show_community(vty
, bgp
, community
,
12973 exact_match
, afi
, safi
,
12976 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12977 output_arg
, show_flags
,
12978 rpki_target_state
);
12980 struct listnode
*node
;
12982 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12986 vty_out(vty
, "{\n");
12988 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12989 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12990 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12993 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12994 FOREACH_SAFI (safi
) {
12995 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
13003 vty_out(vty
, ",\n");
13004 vty_out(vty
, "\"%s\":{\n",
13005 get_afi_safi_str(afi
,
13010 "\nFor address family: %s\n",
13016 bgp_show_community(
13017 vty
, abgp
, community
,
13018 exact_match
, afi
, safi
,
13021 bgp_show(vty
, abgp
, afi
, safi
,
13022 sh_type
, output_arg
,
13024 rpki_target_state
);
13026 vty_out(vty
, "}\n");
13030 /* show <ip> bgp all: for each AFI and SAFI*/
13031 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
13032 FOREACH_AFI_SAFI (afi
, safi
) {
13033 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
13041 vty_out(vty
, ",\n");
13043 vty_out(vty
, "\"%s\":{\n",
13044 get_afi_safi_str(afi
,
13049 "\nFor address family: %s\n",
13055 bgp_show_community(
13056 vty
, abgp
, community
,
13057 exact_match
, afi
, safi
,
13060 bgp_show(vty
, abgp
, afi
, safi
,
13061 sh_type
, output_arg
,
13063 rpki_target_state
);
13065 vty_out(vty
, "}\n");
13070 vty_out(vty
, "}\n");
13072 return CMD_SUCCESS
;
13075 DEFUN (show_ip_bgp_route
,
13076 show_ip_bgp_route_cmd
,
13077 "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]",
13081 BGP_INSTANCE_HELP_STR
13083 BGP_SAFI_WITH_LABEL_HELP_STR
13084 "Network in the BGP routing table to display\n"
13086 "Network in the BGP routing table to display\n"
13088 "Display only the bestpath\n"
13089 "Display only multipaths\n"
13090 "Display only paths that match the specified rpki state\n"
13091 "A valid path as determined by rpki\n"
13092 "A invalid path as determined by rpki\n"
13093 "A path that has no rpki data\n"
13096 int prefix_check
= 0;
13098 afi_t afi
= AFI_IP6
;
13099 safi_t safi
= SAFI_UNICAST
;
13100 char *prefix
= NULL
;
13101 struct bgp
*bgp
= NULL
;
13102 enum bgp_path_type path_type
;
13103 bool uj
= use_json(argc
, argv
);
13107 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13110 return CMD_WARNING
;
13114 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13115 return CMD_WARNING
;
13118 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13119 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
13120 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
13122 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
13123 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
13126 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
13127 && afi
!= AFI_IP6
) {
13129 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13130 return CMD_WARNING
;
13132 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
13133 && afi
!= AFI_IP
) {
13135 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13136 return CMD_WARNING
;
13139 prefix
= argv
[idx
]->arg
;
13141 /* [<bestpath|multipath>] */
13142 if (argv_find(argv
, argc
, "bestpath", &idx
))
13143 path_type
= BGP_PATH_SHOW_BESTPATH
;
13144 else if (argv_find(argv
, argc
, "multipath", &idx
))
13145 path_type
= BGP_PATH_SHOW_MULTIPATH
;
13147 path_type
= BGP_PATH_SHOW_ALL
;
13149 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
13150 path_type
, RPKI_NOT_BEING_USED
, uj
);
13153 DEFUN (show_ip_bgp_regexp
,
13154 show_ip_bgp_regexp_cmd
,
13155 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
13159 BGP_INSTANCE_HELP_STR
13161 BGP_SAFI_WITH_LABEL_HELP_STR
13162 "Display routes matching the AS path regular expression\n"
13163 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13166 afi_t afi
= AFI_IP6
;
13167 safi_t safi
= SAFI_UNICAST
;
13168 struct bgp
*bgp
= NULL
;
13169 bool uj
= use_json(argc
, argv
);
13170 char *regstr
= NULL
;
13173 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13176 return CMD_WARNING
;
13178 // get index of regex
13179 if (argv_find(argv
, argc
, "REGEX", &idx
))
13180 regstr
= argv
[idx
]->arg
;
13183 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
13184 bgp_show_type_regexp
, uj
);
13187 DEFPY (show_ip_bgp_instance_all
,
13188 show_ip_bgp_instance_all_cmd
,
13189 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
13193 BGP_INSTANCE_ALL_HELP_STR
13195 BGP_SAFI_WITH_LABEL_HELP_STR
13197 "Increase table width for longer prefixes\n")
13199 afi_t afi
= AFI_IP6
;
13200 safi_t safi
= SAFI_UNICAST
;
13201 struct bgp
*bgp
= NULL
;
13203 uint16_t show_flags
= 0;
13207 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13211 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13213 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13216 return CMD_WARNING
;
13218 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
13219 return CMD_SUCCESS
;
13222 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
13223 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
13228 uint16_t show_flags
= 0;
13231 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13233 if (!config_bgp_aspath_validate(regstr
)) {
13234 vty_out(vty
, "Invalid character in REGEX %s\n",
13236 return CMD_WARNING_CONFIG_FAILED
;
13239 regex
= bgp_regcomp(regstr
);
13241 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
13242 return CMD_WARNING
;
13245 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
13246 RPKI_NOT_BEING_USED
);
13247 bgp_regex_free(regex
);
13251 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
13252 const char *comstr
, int exact
, afi_t afi
,
13253 safi_t safi
, uint16_t show_flags
)
13255 struct community
*com
;
13258 com
= community_str2com(comstr
);
13260 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
13261 return CMD_WARNING
;
13264 ret
= bgp_show(vty
, bgp
, afi
, safi
,
13265 (exact
? bgp_show_type_community_exact
13266 : bgp_show_type_community
),
13267 com
, show_flags
, RPKI_NOT_BEING_USED
);
13268 community_free(&com
);
13274 BGP_STATS_MAXBITLEN
= 0,
13276 BGP_STATS_PREFIXES
,
13278 BGP_STATS_UNAGGREGATEABLE
,
13279 BGP_STATS_MAX_AGGREGATEABLE
,
13280 BGP_STATS_AGGREGATES
,
13282 BGP_STATS_ASPATH_COUNT
,
13283 BGP_STATS_ASPATH_MAXHOPS
,
13284 BGP_STATS_ASPATH_TOTHOPS
,
13285 BGP_STATS_ASPATH_MAXSIZE
,
13286 BGP_STATS_ASPATH_TOTSIZE
,
13287 BGP_STATS_ASN_HIGHEST
,
13291 #define TABLE_STATS_IDX_VTY 0
13292 #define TABLE_STATS_IDX_JSON 1
13294 static const char *table_stats_strs
[][2] = {
13295 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
13296 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
13297 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
13298 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
13299 "unaggregateablePrefixes"},
13300 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
13301 "maximumAggregateablePrefixes"},
13302 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
13303 "bgpAggregateAdvertisements"},
13304 [BGP_STATS_SPACE
] = {"Address space advertised",
13305 "addressSpaceAdvertised"},
13306 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
13307 "advertisementsWithPaths"},
13308 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
13310 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
13312 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
13313 "averageAsPathLengthHops"},
13314 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
13315 "averageAsPathSizeBytes"},
13316 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
13317 [BGP_STATS_MAX
] = {NULL
, NULL
}
13320 struct bgp_table_stats
{
13321 struct bgp_table
*table
;
13322 unsigned long long counts
[BGP_STATS_MAX
];
13325 prefix_len_count
[MAX(EVPN_ROUTE_PREFIXLEN
, IPV6_MAX_BITLEN
) +
13328 double total_space
;
13331 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
13332 struct bgp_table_stats
*ts
, unsigned int space
)
13334 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
13335 struct bgp_path_info
*pi
;
13336 const struct prefix
*rn_p
;
13338 if (!bgp_dest_has_bgp_path_info_data(dest
))
13341 rn_p
= bgp_dest_get_prefix(dest
);
13342 ts
->counts
[BGP_STATS_PREFIXES
]++;
13343 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
13345 ts
->prefix_len_count
[rn_p
->prefixlen
]++;
13346 /* check if the prefix is included by any other announcements */
13347 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
13348 pdest
= bgp_dest_parent_nolock(pdest
);
13350 if (pdest
== NULL
|| pdest
== top
) {
13351 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
13352 /* announced address space */
13354 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
13355 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
13356 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
13359 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
13360 ts
->counts
[BGP_STATS_RIB
]++;
13362 if (CHECK_FLAG(pi
->attr
->flag
,
13363 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
13364 ts
->counts
[BGP_STATS_AGGREGATES
]++;
13366 /* as-path stats */
13367 if (pi
->attr
->aspath
) {
13368 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
13369 unsigned int size
= aspath_size(pi
->attr
->aspath
);
13370 as_t highest
= aspath_highest(pi
->attr
->aspath
);
13372 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
13374 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
13375 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
13377 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
13378 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
13380 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
13381 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
13382 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
13383 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
13388 static void bgp_table_stats_walker(struct event
*t
)
13390 struct bgp_dest
*dest
, *ndest
;
13391 struct bgp_dest
*top
;
13392 struct bgp_table_stats
*ts
= EVENT_ARG(t
);
13393 unsigned int space
= 0;
13395 if (!(top
= bgp_table_top(ts
->table
)))
13398 switch (ts
->table
->afi
) {
13400 space
= IPV4_MAX_BITLEN
;
13403 space
= IPV6_MAX_BITLEN
;
13406 space
= EVPN_ROUTE_PREFIXLEN
;
13413 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
13415 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
13416 if (ts
->table
->safi
== SAFI_MPLS_VPN
13417 || ts
->table
->safi
== SAFI_ENCAP
13418 || ts
->table
->safi
== SAFI_EVPN
) {
13419 struct bgp_table
*table
;
13421 table
= bgp_dest_get_bgp_table_info(dest
);
13425 top
= bgp_table_top(table
);
13426 for (ndest
= bgp_table_top(table
); ndest
;
13427 ndest
= bgp_route_next(ndest
))
13428 bgp_table_stats_rn(ndest
, top
, ts
, space
);
13430 bgp_table_stats_rn(dest
, top
, ts
, space
);
13435 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
13436 struct json_object
*json_array
)
13438 struct listnode
*node
, *nnode
;
13441 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
13442 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13445 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13446 safi_t safi
, struct json_object
*json_array
)
13448 struct bgp_table_stats ts
;
13450 int ret
= CMD_SUCCESS
;
13452 struct json_object
*json
= NULL
;
13453 uint32_t bitlen
= 0;
13454 struct json_object
*json_bitlen
;
13457 json
= json_object_new_object();
13459 if (!bgp
->rib
[afi
][safi
]) {
13460 char warning_msg
[50];
13462 snprintf(warning_msg
, sizeof(warning_msg
),
13463 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
13467 vty_out(vty
, "%s\n", warning_msg
);
13469 json_object_string_add(json
, "warning", warning_msg
);
13472 goto end_table_stats
;
13476 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
13477 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
13479 json_object_string_add(json
, "instance", bgp
->name_pretty
);
13481 /* labeled-unicast routes live in the unicast table */
13482 if (safi
== SAFI_LABELED_UNICAST
)
13483 safi
= SAFI_UNICAST
;
13485 memset(&ts
, 0, sizeof(ts
));
13486 ts
.table
= bgp
->rib
[afi
][safi
];
13487 event_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
13489 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
13490 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
13491 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
13495 case BGP_STATS_ASPATH_TOTHOPS
:
13496 case BGP_STATS_ASPATH_TOTSIZE
:
13499 temp_buf
, sizeof(temp_buf
), "%12.2f",
13501 ? (float)ts
.counts
[i
]
13503 [BGP_STATS_ASPATH_COUNT
]
13505 vty_out(vty
, "%-30s: %s",
13506 table_stats_strs
[i
]
13507 [TABLE_STATS_IDX_VTY
],
13510 json_object_double_add(
13512 table_stats_strs
[i
]
13513 [TABLE_STATS_IDX_JSON
],
13515 ? (double)ts
.counts
[i
]
13516 / (double)ts
.counts
13517 [BGP_STATS_ASPATH_COUNT
]
13521 case BGP_STATS_TOTPLEN
:
13524 temp_buf
, sizeof(temp_buf
), "%12.2f",
13526 ? (float)ts
.counts
[i
]
13528 [BGP_STATS_PREFIXES
]
13530 vty_out(vty
, "%-30s: %s",
13531 table_stats_strs
[i
]
13532 [TABLE_STATS_IDX_VTY
],
13535 json_object_double_add(
13537 table_stats_strs
[i
]
13538 [TABLE_STATS_IDX_JSON
],
13540 ? (double)ts
.counts
[i
]
13541 / (double)ts
.counts
13542 [BGP_STATS_PREFIXES
]
13546 case BGP_STATS_SPACE
:
13548 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13550 vty_out(vty
, "%-30s: %s\n",
13551 table_stats_strs
[i
]
13552 [TABLE_STATS_IDX_VTY
],
13555 json_object_double_add(
13557 table_stats_strs
[i
]
13558 [TABLE_STATS_IDX_JSON
],
13559 (double)ts
.total_space
);
13561 if (afi
== AFI_IP6
) {
13563 snprintf(temp_buf
, sizeof(temp_buf
),
13566 * pow(2.0, -128 + 32));
13567 vty_out(vty
, "%30s: %s\n",
13568 "/32 equivalent %s\n",
13571 json_object_double_add(
13572 json
, "/32equivalent",
13573 (double)(ts
.total_space
13578 snprintf(temp_buf
, sizeof(temp_buf
),
13581 * pow(2.0, -128 + 48));
13582 vty_out(vty
, "%30s: %s\n",
13583 "/48 equivalent %s\n",
13586 json_object_double_add(
13587 json
, "/48equivalent",
13588 (double)(ts
.total_space
13594 snprintf(temp_buf
, sizeof(temp_buf
),
13596 ts
.total_space
* 100.
13598 vty_out(vty
, "%30s: %s\n",
13599 "% announced ", temp_buf
);
13601 json_object_double_add(
13602 json
, "%announced",
13603 (double)(ts
.total_space
* 100.
13607 snprintf(temp_buf
, sizeof(temp_buf
),
13610 * pow(2.0, -32 + 8));
13611 vty_out(vty
, "%30s: %s\n",
13612 "/8 equivalent ", temp_buf
);
13614 json_object_double_add(
13615 json
, "/8equivalent",
13616 (double)(ts
.total_space
13617 * pow(2.0, -32 + 8)));
13620 snprintf(temp_buf
, sizeof(temp_buf
),
13623 * pow(2.0, -32 + 24));
13624 vty_out(vty
, "%30s: %s\n",
13625 "/24 equivalent ", temp_buf
);
13627 json_object_double_add(
13628 json
, "/24equivalent",
13629 (double)(ts
.total_space
13630 * pow(2.0, -32 + 24)));
13636 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13638 vty_out(vty
, "%-30s: %s",
13639 table_stats_strs
[i
]
13640 [TABLE_STATS_IDX_VTY
],
13643 json_object_int_add(
13645 table_stats_strs
[i
]
13646 [TABLE_STATS_IDX_JSON
],
13651 vty_out(vty
, "\n");
13656 bitlen
= IPV4_MAX_BITLEN
;
13659 bitlen
= IPV6_MAX_BITLEN
;
13662 bitlen
= EVPN_ROUTE_PREFIXLEN
;
13670 json_bitlen
= json_object_new_array();
13672 for (i
= 0; i
<= bitlen
; i
++) {
13673 struct json_object
*ind_bit
= json_object_new_object();
13675 if (!ts
.prefix_len_count
[i
])
13678 snprintf(temp_buf
, sizeof(temp_buf
), "%u", i
);
13679 json_object_int_add(ind_bit
, temp_buf
,
13680 ts
.prefix_len_count
[i
]);
13681 json_object_array_add(json_bitlen
, ind_bit
);
13683 json_object_object_add(json
, "prefixLength", json_bitlen
);
13688 json_object_array_add(json_array
, json
);
13692 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13693 safi_t safi
, struct json_object
*json_array
)
13696 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13697 return CMD_SUCCESS
;
13700 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13712 PCOUNT_BPATH_SELECTED
,
13713 PCOUNT_PFCNT
, /* the figure we display to users */
13717 static const char *const pcount_strs
[] = {
13718 [PCOUNT_ADJ_IN
] = "Adj-in",
13719 [PCOUNT_DAMPED
] = "Damped",
13720 [PCOUNT_REMOVED
] = "Removed",
13721 [PCOUNT_HISTORY
] = "History",
13722 [PCOUNT_STALE
] = "Stale",
13723 [PCOUNT_VALID
] = "Valid",
13724 [PCOUNT_ALL
] = "All RIB",
13725 [PCOUNT_COUNTED
] = "PfxCt counted",
13726 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13727 [PCOUNT_PFCNT
] = "Useable",
13728 [PCOUNT_MAX
] = NULL
,
13731 struct peer_pcounts
{
13732 unsigned int count
[PCOUNT_MAX
];
13733 const struct peer
*peer
;
13734 const struct bgp_table
*table
;
13738 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13740 const struct bgp_adj_in
*ain
;
13741 const struct bgp_path_info
*pi
;
13742 const struct peer
*peer
= pc
->peer
;
13744 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13745 if (ain
->peer
== peer
)
13746 pc
->count
[PCOUNT_ADJ_IN
]++;
13748 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13750 if (pi
->peer
!= peer
)
13753 pc
->count
[PCOUNT_ALL
]++;
13755 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13756 pc
->count
[PCOUNT_DAMPED
]++;
13757 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13758 pc
->count
[PCOUNT_HISTORY
]++;
13759 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13760 pc
->count
[PCOUNT_REMOVED
]++;
13761 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13762 pc
->count
[PCOUNT_STALE
]++;
13763 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13764 pc
->count
[PCOUNT_VALID
]++;
13765 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13766 pc
->count
[PCOUNT_PFCNT
]++;
13767 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13768 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13770 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13771 pc
->count
[PCOUNT_COUNTED
]++;
13772 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13774 EC_LIB_DEVELOPMENT
,
13775 "Attempting to count but flags say it is unusable");
13777 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13779 EC_LIB_DEVELOPMENT
,
13780 "Not counted but flags say we should");
13785 static void bgp_peer_count_walker(struct event
*t
)
13787 struct bgp_dest
*rn
, *rm
;
13788 const struct bgp_table
*table
;
13789 struct peer_pcounts
*pc
= EVENT_ARG(t
);
13791 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13792 || pc
->safi
== SAFI_EVPN
) {
13793 /* Special handling for 2-level routing tables. */
13794 for (rn
= bgp_table_top(pc
->table
); rn
;
13795 rn
= bgp_route_next(rn
)) {
13796 table
= bgp_dest_get_bgp_table_info(rn
);
13798 for (rm
= bgp_table_top(table
); rm
;
13799 rm
= bgp_route_next(rm
))
13800 bgp_peer_count_proc(rm
, pc
);
13803 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13804 bgp_peer_count_proc(rn
, pc
);
13807 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13808 safi_t safi
, bool use_json
)
13810 struct peer_pcounts pcounts
= {.peer
= peer
};
13812 json_object
*json
= NULL
;
13813 json_object
*json_loop
= NULL
;
13816 json
= json_object_new_object();
13817 json_loop
= json_object_new_object();
13820 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13821 || !peer
->bgp
->rib
[afi
][safi
]) {
13823 json_object_string_add(
13825 "No such neighbor or address family");
13826 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13827 json_object_free(json
);
13828 json_object_free(json_loop
);
13830 vty_out(vty
, "%% No such neighbor or address family\n");
13832 return CMD_WARNING
;
13835 memset(&pcounts
, 0, sizeof(pcounts
));
13836 pcounts
.peer
= peer
;
13837 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13838 pcounts
.safi
= safi
;
13840 /* in-place call via thread subsystem so as to record execution time
13841 * stats for the thread-walk (i.e. ensure this can't be blamed on
13842 * on just vty_read()).
13844 event_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13847 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13848 json_object_string_add(json
, "multiProtocol",
13849 get_afi_safi_str(afi
, safi
, true));
13850 json_object_int_add(json
, "pfxCounter",
13851 peer
->pcount
[afi
][safi
]);
13853 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13854 json_object_int_add(json_loop
, pcount_strs
[i
],
13857 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13859 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13860 json_object_string_add(json
, "pfxctDriftFor",
13862 json_object_string_add(
13863 json
, "recommended",
13864 "Please report this bug, with the above command output");
13866 vty_json(vty
, json
);
13870 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13871 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13872 peer
->hostname
, peer
->host
,
13873 get_afi_safi_str(afi
, safi
, false));
13875 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13876 get_afi_safi_str(afi
, safi
, false));
13879 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13880 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13882 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13883 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13886 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13887 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13889 "Please report this bug, with the above command output\n");
13893 return CMD_SUCCESS
;
13896 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13897 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13898 "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]",
13902 BGP_INSTANCE_HELP_STR
13905 "Detailed information on TCP and BGP neighbor connections\n"
13906 "Neighbor to display information about\n"
13907 "Neighbor to display information about\n"
13908 "Neighbor on BGP configured interface\n"
13909 "Display detailed prefix count information\n"
13912 afi_t afi
= AFI_IP6
;
13913 safi_t safi
= SAFI_UNICAST
;
13916 struct bgp
*bgp
= NULL
;
13917 bool uj
= use_json(argc
, argv
);
13922 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13925 return CMD_WARNING
;
13927 argv_find(argv
, argc
, "neighbors", &idx
);
13928 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13930 return CMD_WARNING
;
13932 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13935 #ifdef KEEP_OLD_VPN_COMMANDS
13936 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13937 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13938 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13943 "Display information about all VPNv4 NLRIs\n"
13944 "Detailed information on TCP and BGP neighbor connections\n"
13945 "Neighbor to display information about\n"
13946 "Neighbor to display information about\n"
13947 "Neighbor on BGP configured interface\n"
13948 "Display detailed prefix count information\n"
13953 bool uj
= use_json(argc
, argv
);
13955 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13957 return CMD_WARNING
;
13959 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13962 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13963 show_ip_bgp_vpn_all_route_prefix_cmd
,
13964 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13969 "Display information about all VPNv4 NLRIs\n"
13970 "Network in the BGP routing table to display\n"
13971 "Network in the BGP routing table to display\n"
13975 char *network
= NULL
;
13976 struct bgp
*bgp
= bgp_get_default();
13978 vty_out(vty
, "Can't find default instance\n");
13979 return CMD_WARNING
;
13982 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13983 network
= argv
[idx
]->arg
;
13984 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13985 network
= argv
[idx
]->arg
;
13987 vty_out(vty
, "Unable to figure out Network\n");
13988 return CMD_WARNING
;
13991 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13992 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13993 use_json(argc
, argv
));
13995 #endif /* KEEP_OLD_VPN_COMMANDS */
13997 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13998 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13999 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
14004 "Network in the BGP routing table to display\n"
14005 "Network in the BGP routing table to display\n"
14006 "Network in the BGP routing table to display\n"
14007 "Network in the BGP routing table to display\n"
14011 char *network
= NULL
;
14012 int prefix_check
= 0;
14014 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
14015 argv_find(argv
, argc
, "X:X::X:X", &idx
))
14016 network
= argv
[idx
]->arg
;
14017 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
14018 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
14019 network
= argv
[idx
]->arg
;
14022 vty_out(vty
, "Unable to figure out Network\n");
14023 return CMD_WARNING
;
14025 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
14026 prefix_check
, BGP_PATH_SHOW_ALL
,
14027 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
14030 static void show_adj_route_header(struct vty
*vty
, struct peer
*peer
,
14031 struct bgp_table
*table
, int *header1
,
14032 int *header2
, json_object
*json
,
14033 json_object
*json_scode
,
14034 json_object
*json_ocode
, bool wide
,
14037 uint64_t version
= table
? table
->version
: 0;
14041 json_object_int_add(json
, "bgpTableVersion", version
);
14042 json_object_string_addf(json
, "bgpLocalRouterId",
14043 "%pI4", &peer
->bgp
->router_id
);
14044 json_object_int_add(json
, "defaultLocPrf",
14045 peer
->bgp
->default_local_pref
);
14046 json_object_int_add(json
, "localAS",
14047 peer
->change_local_as
14048 ? peer
->change_local_as
14050 json_object_object_add(json
, "bgpStatusCodes",
14052 json_object_object_add(json
, "bgpOriginCodes",
14056 "BGP table version is %" PRIu64
14057 ", local router ID is %pI4, vrf id ",
14058 version
, &peer
->bgp
->router_id
);
14059 if (peer
->bgp
->vrf_id
== VRF_UNKNOWN
)
14060 vty_out(vty
, "%s", VRFID_NONE_STR
);
14062 vty_out(vty
, "%u", peer
->bgp
->vrf_id
);
14063 vty_out(vty
, "\n");
14064 vty_out(vty
, "Default local pref %u, ",
14065 peer
->bgp
->default_local_pref
);
14066 vty_out(vty
, "local AS %u\n",
14067 peer
->change_local_as
? peer
->change_local_as
14070 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14071 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14072 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14073 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14079 if (!json
&& !detail
)
14080 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
14081 : BGP_SHOW_HEADER
));
14087 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
14088 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
14089 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
14090 json_object
*json_scode
, json_object
*json_ocode
,
14091 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
14092 const struct prefix
*match
, unsigned long *output_count
,
14093 unsigned long *filtered_count
)
14095 struct bgp_adj_in
*ain
= NULL
;
14096 struct bgp_adj_out
*adj
= NULL
;
14097 struct bgp_dest
*dest
;
14101 struct update_subgroup
*subgrp
;
14102 struct peer_af
*paf
= NULL
;
14103 bool route_filtered
;
14104 bool detail
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14105 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14106 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14107 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14108 || (safi
== SAFI_EVPN
))
14112 json_object
*json_net
= NULL
;
14116 /* If the user supplied a prefix, look for a matching route instead
14117 * of walking the whole table.
14120 dest
= bgp_node_match(table
, match
);
14123 vty_out(vty
, "Network not in table\n");
14127 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
14129 if (rn_p
->prefixlen
!= match
->prefixlen
) {
14131 vty_out(vty
, "Network not in table\n");
14132 bgp_dest_unlock_node(dest
);
14136 if (type
== bgp_show_adj_route_received
||
14137 type
== bgp_show_adj_route_filtered
) {
14138 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14139 if (ain
->peer
== peer
) {
14144 /* bail out if if adj_out is empty, or
14145 * if the prefix isn't in this peer's
14148 if (!ain
|| ain
->peer
!= peer
) {
14150 vty_out(vty
, "Network not in table\n");
14151 bgp_dest_unlock_node(dest
);
14154 } else if (type
== bgp_show_adj_route_advertised
) {
14155 bool peer_found
= false;
14157 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
) {
14158 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14159 if (paf
->peer
== peer
&& adj
->attr
) {
14168 /* bail out if if adj_out is empty, or
14169 * if the prefix isn't in this peer's
14172 if (!paf
|| !peer_found
) {
14174 vty_out(vty
, "Network not in table\n");
14175 bgp_dest_unlock_node(dest
);
14180 ret
= bgp_output_modifier(peer
, rn_p
, &attr
, afi
, safi
,
14183 if (ret
!= RMAP_DENY
) {
14184 show_adj_route_header(vty
, peer
, table
, header1
,
14185 header2
, json
, json_scode
,
14186 json_ocode
, wide
, detail
);
14189 json_net
= json_object_new_object();
14191 bgp_show_path_info(NULL
/* prefix_rd */, dest
, vty
, bgp
,
14192 afi
, safi
, json_net
,
14193 BGP_PATH_SHOW_ALL
, &display
,
14194 RPKI_NOT_BEING_USED
);
14196 json_object_object_addf(json_ar
, json_net
,
14200 (*filtered_count
)++;
14202 bgp_attr_flush(&attr
);
14203 bgp_dest_unlock_node(dest
);
14208 subgrp
= peer_subgroup(peer
, afi
, safi
);
14210 if (type
== bgp_show_adj_route_advertised
&& subgrp
14211 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
14213 json_object_int_add(json
, "bgpTableVersion",
14215 json_object_string_addf(json
, "bgpLocalRouterId",
14216 "%pI4", &bgp
->router_id
);
14217 json_object_int_add(json
, "defaultLocPrf",
14218 bgp
->default_local_pref
);
14219 json_object_int_add(json
, "localAS",
14220 peer
->change_local_as
14221 ? peer
->change_local_as
14223 json_object_object_add(json
, "bgpStatusCodes",
14225 json_object_object_add(json
, "bgpOriginCodes",
14227 json_object_string_add(
14228 json
, "bgpOriginatingDefaultNetwork",
14229 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14232 "BGP table version is %" PRIu64
14233 ", local router ID is %pI4, vrf id ",
14234 table
->version
, &bgp
->router_id
);
14235 if (bgp
->vrf_id
== VRF_UNKNOWN
)
14236 vty_out(vty
, "%s", VRFID_NONE_STR
);
14238 vty_out(vty
, "%u", bgp
->vrf_id
);
14239 vty_out(vty
, "\n");
14240 vty_out(vty
, "Default local pref %u, ",
14241 bgp
->default_local_pref
);
14242 vty_out(vty
, "local AS %u\n",
14243 peer
->change_local_as
? peer
->change_local_as
14246 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14247 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14248 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14249 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14252 vty_out(vty
, "Originating default network %s\n\n",
14253 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14259 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
14260 if (type
== bgp_show_adj_route_received
14261 || type
== bgp_show_adj_route_filtered
) {
14262 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14263 if (ain
->peer
!= peer
)
14266 show_adj_route_header(vty
, peer
, table
, header1
,
14267 header2
, json
, json_scode
,
14268 json_ocode
, wide
, detail
);
14270 if ((safi
== SAFI_MPLS_VPN
)
14271 || (safi
== SAFI_ENCAP
)
14272 || (safi
== SAFI_EVPN
)) {
14274 json_object_string_add(
14275 json_ar
, "rd", rd_str
);
14276 else if (show_rd
&& rd_str
) {
14278 "Route Distinguisher: %s\n",
14285 route_filtered
= false;
14287 /* Filter prefix using distribute list,
14288 * filter list or prefix list
14290 const struct prefix
*rn_p
=
14291 bgp_dest_get_prefix(dest
);
14292 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
14295 route_filtered
= true;
14297 /* Filter prefix using route-map */
14298 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
14299 safi
, rmap_name
, NULL
,
14302 if (type
== bgp_show_adj_route_filtered
&&
14303 !route_filtered
&& ret
!= RMAP_DENY
) {
14304 bgp_attr_flush(&attr
);
14308 if (type
== bgp_show_adj_route_received
14309 && (route_filtered
|| ret
== RMAP_DENY
))
14310 (*filtered_count
)++;
14315 json_object_new_object();
14316 bgp_show_path_info(
14317 NULL
/* prefix_rd */, dest
, vty
,
14318 bgp
, afi
, safi
, json_net
,
14319 BGP_PATH_SHOW_ALL
, &display
,
14320 RPKI_NOT_BEING_USED
);
14322 json_object_object_addf(
14326 route_vty_out_tmp(vty
, dest
, rn_p
,
14327 &attr
, safi
, use_json
,
14329 bgp_attr_flush(&attr
);
14332 } else if (type
== bgp_show_adj_route_advertised
) {
14333 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
14334 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14335 if (paf
->peer
!= peer
|| !adj
->attr
)
14338 show_adj_route_header(
14339 vty
, peer
, table
, header1
,
14340 header2
, json
, json_scode
,
14341 json_ocode
, wide
, detail
);
14343 const struct prefix
*rn_p
=
14344 bgp_dest_get_prefix(dest
);
14347 ret
= bgp_output_modifier(
14348 peer
, rn_p
, &attr
, afi
, safi
,
14351 if (ret
!= RMAP_DENY
) {
14352 if ((safi
== SAFI_MPLS_VPN
)
14353 || (safi
== SAFI_ENCAP
)
14354 || (safi
== SAFI_EVPN
)) {
14356 json_object_string_add(
14363 "Route Distinguisher: %s\n",
14371 json_object_new_object();
14372 bgp_show_path_info(
14381 RPKI_NOT_BEING_USED
);
14383 json_object_object_addf(
14396 (*filtered_count
)++;
14399 bgp_attr_flush(&attr
);
14401 } else if (type
== bgp_show_adj_route_bestpath
) {
14402 struct bgp_path_info
*pi
;
14404 show_adj_route_header(vty
, peer
, table
, header1
,
14405 header2
, json
, json_scode
,
14406 json_ocode
, wide
, detail
);
14408 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
14410 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
14412 if (pi
->peer
!= peer
)
14415 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
14421 json_object_new_object();
14422 bgp_show_path_info(
14423 NULL
/* prefix_rd */, dest
, vty
,
14424 bgp
, afi
, safi
, json_net
,
14425 BGP_PATH_SHOW_BESTPATH
,
14426 &display
, RPKI_NOT_BEING_USED
);
14428 json_object_object_addf(
14433 vty
, dest
, rn_p
, pi
->attr
, safi
,
14434 use_json
, json_ar
, wide
);
14441 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
14442 safi_t safi
, enum bgp_show_adj_route_type type
,
14443 const char *rmap_name
, const struct prefix
*match
,
14444 uint16_t show_flags
)
14447 struct bgp_table
*table
;
14448 json_object
*json
= NULL
;
14449 json_object
*json_scode
= NULL
;
14450 json_object
*json_ocode
= NULL
;
14451 json_object
*json_ar
= NULL
;
14452 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14454 /* Init BGP headers here so they're only displayed once
14455 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14461 * Initialize variables for each RD
14462 * All prefixes under an RD is aggregated within "json_routes"
14464 char rd_str
[BUFSIZ
] = {0};
14465 json_object
*json_routes
= NULL
;
14468 /* For 2-tier tables, prefix counts need to be
14469 * maintained across multiple runs of show_adj_route()
14471 unsigned long output_count_per_rd
;
14472 unsigned long filtered_count_per_rd
;
14473 unsigned long output_count
= 0;
14474 unsigned long filtered_count
= 0;
14477 json
= json_object_new_object();
14478 json_ar
= json_object_new_object();
14479 json_scode
= json_object_new_object();
14480 json_ocode
= json_object_new_object();
14481 #if CONFDATE > 20231208
14482 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14484 json_object_string_add(json_scode
, "suppressed", "s");
14485 json_object_string_add(json_scode
, "damped", "d");
14486 json_object_string_add(json_scode
, "history", "h");
14487 json_object_string_add(json_scode
, "valid", "*");
14488 json_object_string_add(json_scode
, "best", ">");
14489 json_object_string_add(json_scode
, "multipath", "=");
14490 json_object_string_add(json_scode
, "internal", "i");
14491 json_object_string_add(json_scode
, "ribFailure", "r");
14492 json_object_string_add(json_scode
, "stale", "S");
14493 json_object_string_add(json_scode
, "removed", "R");
14495 #if CONFDATE > 20231208
14496 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14498 json_object_string_add(json_ocode
, "igp", "i");
14499 json_object_string_add(json_ocode
, "egp", "e");
14500 json_object_string_add(json_ocode
, "incomplete", "?");
14503 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14505 json_object_string_add(
14507 "No such neighbor or address family");
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
);
14514 vty_out(vty
, "%% No such neighbor or address family\n");
14516 return CMD_WARNING
;
14519 if ((type
== bgp_show_adj_route_received
14520 || type
== bgp_show_adj_route_filtered
)
14521 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
14522 PEER_FLAG_SOFT_RECONFIG
)) {
14524 json_object_string_add(
14526 "Inbound soft reconfiguration not enabled");
14527 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14528 json_object_free(json
);
14529 json_object_free(json_ar
);
14530 json_object_free(json_scode
);
14531 json_object_free(json_ocode
);
14534 "%% Inbound soft reconfiguration not enabled\n");
14536 return CMD_WARNING
;
14541 /* labeled-unicast routes live in the unicast table */
14542 if (safi
== SAFI_LABELED_UNICAST
)
14543 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
14545 table
= bgp
->rib
[afi
][safi
];
14547 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14548 || (safi
== SAFI_EVPN
)) {
14550 struct bgp_dest
*dest
;
14552 for (dest
= bgp_table_top(table
); dest
;
14553 dest
= bgp_route_next(dest
)) {
14554 table
= bgp_dest_get_bgp_table_info(dest
);
14558 output_count_per_rd
= 0;
14559 filtered_count_per_rd
= 0;
14562 json_routes
= json_object_new_object();
14564 const struct prefix_rd
*prd
;
14565 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14568 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
),
14572 vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14573 json
, json_routes
, json_scode
, json_ocode
,
14574 show_flags
, &header1
, &header2
, rd_str
, match
,
14575 &output_count_per_rd
, &filtered_count_per_rd
);
14577 /* Don't include an empty RD in the output! */
14578 if (json_routes
&& (output_count_per_rd
> 0))
14579 json_object_object_add(json_ar
, rd_str
,
14582 output_count
+= output_count_per_rd
;
14583 filtered_count
+= filtered_count_per_rd
;
14586 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14587 json
, json_ar
, json_scode
, json_ocode
,
14588 show_flags
, &header1
, &header2
, rd_str
, match
,
14589 &output_count
, &filtered_count
);
14592 if (type
== bgp_show_adj_route_advertised
)
14593 json_object_object_add(json
, "advertisedRoutes",
14596 json_object_object_add(json
, "receivedRoutes", json_ar
);
14597 json_object_int_add(json
, "totalPrefixCounter", output_count
);
14598 json_object_int_add(json
, "filteredPrefixCounter",
14602 * These fields only give up ownership to `json` when `header1`
14603 * is used (set to zero). See code in `show_adj_route` and
14604 * `show_adj_route_header`.
14606 if (header1
== 1) {
14607 json_object_free(json_scode
);
14608 json_object_free(json_ocode
);
14611 vty_json(vty
, json
);
14612 } else if (output_count
> 0) {
14613 if (!match
&& filtered_count
> 0)
14615 "\nTotal number of prefixes %ld (%ld filtered)\n",
14616 output_count
, filtered_count
);
14618 vty_out(vty
, "\nTotal number of prefixes %ld\n",
14622 return CMD_SUCCESS
;
14625 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
14626 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
14627 "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]",
14631 BGP_INSTANCE_HELP_STR
14633 BGP_SAFI_WITH_LABEL_HELP_STR
14634 "Detailed information on TCP and BGP neighbor connections\n"
14635 "Neighbor to display information about\n"
14636 "Neighbor to display information about\n"
14637 "Neighbor on BGP configured interface\n"
14638 "Display the routes selected by best path\n"
14639 "Display detailed version of routes\n"
14641 "Increase table width for longer prefixes\n")
14643 afi_t afi
= AFI_IP6
;
14644 safi_t safi
= SAFI_UNICAST
;
14645 char *rmap_name
= NULL
;
14646 char *peerstr
= NULL
;
14647 struct bgp
*bgp
= NULL
;
14649 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
14651 uint16_t show_flags
= 0;
14654 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14657 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14660 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14662 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14666 return CMD_WARNING
;
14668 argv_find(argv
, argc
, "neighbors", &idx
);
14669 peerstr
= argv
[++idx
]->arg
;
14671 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14673 return CMD_WARNING
;
14675 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, NULL
,
14679 DEFPY(show_ip_bgp_instance_neighbor_advertised_route
,
14680 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
14681 "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]",
14685 BGP_INSTANCE_HELP_STR
14687 BGP_SAFI_WITH_LABEL_HELP_STR
14688 "Display the entries for all address families\n"
14689 "Detailed information on TCP and BGP neighbor connections\n"
14690 "Neighbor to display information about\n"
14691 "Neighbor to display information about\n"
14692 "Neighbor on BGP configured interface\n"
14693 "Display the routes advertised to a BGP neighbor\n"
14694 "Display the received routes from neighbor\n"
14695 "Display the filtered routes received from neighbor\n"
14696 "Route-map to modify the attributes\n"
14697 "Name of the route map\n"
14700 "Display detailed version of routes\n"
14702 "Increase table width for longer prefixes\n")
14704 afi_t afi
= AFI_IP6
;
14705 safi_t safi
= SAFI_UNICAST
;
14706 char *peerstr
= NULL
;
14707 struct bgp
*bgp
= NULL
;
14709 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
14712 uint16_t show_flags
= 0;
14713 struct listnode
*node
;
14716 if (detail
|| prefix_str
)
14717 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14721 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14725 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
14726 if (argv_find(argv
, argc
, "ipv4", &idx
))
14727 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
14729 if (argv_find(argv
, argc
, "ipv6", &idx
))
14730 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
14734 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14736 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14739 return CMD_WARNING
;
14741 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14742 argv_find(argv
, argc
, "neighbors", &idx
);
14743 peerstr
= argv
[++idx
]->arg
;
14745 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14747 return CMD_WARNING
;
14749 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
14750 type
= bgp_show_adj_route_advertised
;
14751 else if (argv_find(argv
, argc
, "received-routes", &idx
))
14752 type
= bgp_show_adj_route_received
;
14753 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
14754 type
= bgp_show_adj_route_filtered
;
14757 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, route_map
,
14758 prefix_str
? prefix
: NULL
, show_flags
);
14760 vty_out(vty
, "{\n");
14762 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14763 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14764 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14766 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14767 FOREACH_SAFI (safi
) {
14768 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14775 vty_out(vty
, ",\n");
14776 vty_out(vty
, "\"%s\":",
14777 get_afi_safi_str(afi
, safi
,
14781 "\nFor address family: %s\n",
14782 get_afi_safi_str(afi
, safi
,
14785 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14786 route_map
, prefix
, show_flags
);
14790 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14791 FOREACH_AFI_SAFI (afi
, safi
) {
14792 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14799 vty_out(vty
, ",\n");
14800 vty_out(vty
, "\"%s\":",
14801 get_afi_safi_str(afi
, safi
,
14805 "\nFor address family: %s\n",
14806 get_afi_safi_str(afi
, safi
,
14809 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14810 route_map
, prefix
, show_flags
);
14815 vty_out(vty
, "}\n");
14817 return CMD_SUCCESS
;
14820 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14821 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14822 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14826 BGP_INSTANCE_HELP_STR
14829 BGP_AF_MODIFIER_STR
14830 "Detailed information on TCP and BGP neighbor connections\n"
14831 "Neighbor to display information about\n"
14832 "Neighbor to display information about\n"
14833 "Neighbor on BGP configured interface\n"
14834 "Display information received from a BGP neighbor\n"
14835 "Display the prefixlist filter\n"
14838 afi_t afi
= AFI_IP6
;
14839 safi_t safi
= SAFI_UNICAST
;
14840 char *peerstr
= NULL
;
14845 struct bgp
*bgp
= NULL
;
14846 bool uj
= use_json(argc
, argv
);
14851 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14854 return CMD_WARNING
;
14856 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14857 argv_find(argv
, argc
, "neighbors", &idx
);
14858 peerstr
= argv
[++idx
]->arg
;
14860 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14862 return CMD_WARNING
;
14864 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14865 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14868 vty_out(vty
, "Address Family: %s\n",
14869 get_afi_safi_str(afi
, safi
, false));
14870 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14873 vty_out(vty
, "{}\n");
14875 vty_out(vty
, "No functional output\n");
14878 return CMD_SUCCESS
;
14881 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14882 afi_t afi
, safi_t safi
,
14883 enum bgp_show_type type
, bool use_json
)
14885 uint16_t show_flags
= 0;
14888 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14890 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14892 json_object
*json_no
= NULL
;
14893 json_no
= json_object_new_object();
14894 json_object_string_add(
14895 json_no
, "warning",
14896 "No such neighbor or address family");
14897 vty_out(vty
, "%s\n",
14898 json_object_to_json_string(json_no
));
14899 json_object_free(json_no
);
14901 vty_out(vty
, "%% No such neighbor or address family\n");
14902 return CMD_WARNING
;
14905 /* labeled-unicast routes live in the unicast table */
14906 if (safi
== SAFI_LABELED_UNICAST
)
14907 safi
= SAFI_UNICAST
;
14909 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14910 RPKI_NOT_BEING_USED
);
14913 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14914 show_ip_bgp_flowspec_routes_detailed_cmd
,
14915 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14919 BGP_INSTANCE_HELP_STR
14922 "Detailed information on flowspec entries\n"
14925 afi_t afi
= AFI_IP6
;
14926 safi_t safi
= SAFI_UNICAST
;
14927 struct bgp
*bgp
= NULL
;
14929 bool uj
= use_json(argc
, argv
);
14930 uint16_t show_flags
= BGP_SHOW_OPT_ROUTES_DETAIL
;
14934 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14937 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14940 return CMD_WARNING
;
14942 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14943 show_flags
, RPKI_NOT_BEING_USED
);
14946 DEFUN (show_ip_bgp_neighbor_routes
,
14947 show_ip_bgp_neighbor_routes_cmd
,
14948 "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]",
14952 BGP_INSTANCE_HELP_STR
14954 BGP_SAFI_WITH_LABEL_HELP_STR
14955 "Detailed information on TCP and BGP neighbor connections\n"
14956 "Neighbor to display information about\n"
14957 "Neighbor to display information about\n"
14958 "Neighbor on BGP configured interface\n"
14959 "Display flap statistics of the routes learned from neighbor\n"
14960 "Display the dampened routes received from neighbor\n"
14961 "Display routes learned from neighbor\n"
14964 char *peerstr
= NULL
;
14965 struct bgp
*bgp
= NULL
;
14966 afi_t afi
= AFI_IP6
;
14967 safi_t safi
= SAFI_UNICAST
;
14969 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14971 bool uj
= use_json(argc
, argv
);
14976 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14979 return CMD_WARNING
;
14981 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14982 argv_find(argv
, argc
, "neighbors", &idx
);
14983 peerstr
= argv
[++idx
]->arg
;
14985 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14987 return CMD_WARNING
;
14989 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14990 sh_type
= bgp_show_type_flap_neighbor
;
14991 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14992 sh_type
= bgp_show_type_damp_neighbor
;
14993 else if (argv_find(argv
, argc
, "routes", &idx
))
14994 sh_type
= bgp_show_type_neighbor
;
14996 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14999 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
15001 struct bgp_distance
{
15002 /* Distance value for the IP source prefix. */
15005 /* Name of the access-list to be matched. */
15009 DEFUN (show_bgp_afi_vpn_rd_route
,
15010 show_bgp_afi_vpn_rd_route_cmd
,
15011 "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]",
15015 BGP_AF_MODIFIER_STR
15016 "Display information for a route distinguisher\n"
15017 "Route Distinguisher\n"
15018 "All Route Distinguishers\n"
15019 "Network in the BGP routing table to display\n"
15020 "Network in the BGP routing table to display\n"
15024 struct prefix_rd prd
;
15025 afi_t afi
= AFI_MAX
;
15028 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
15029 vty_out(vty
, "%% Malformed Address Family\n");
15030 return CMD_WARNING
;
15033 if (!strcmp(argv
[5]->arg
, "all"))
15034 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
15035 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
15036 RPKI_NOT_BEING_USED
,
15037 use_json(argc
, argv
));
15039 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
15041 vty_out(vty
, "%% Malformed Route Distinguisher\n");
15042 return CMD_WARNING
;
15045 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
15046 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
15047 use_json(argc
, argv
));
15050 static struct bgp_distance
*bgp_distance_new(void)
15052 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
15055 static void bgp_distance_free(struct bgp_distance
*bdistance
)
15057 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
15060 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
15061 const char *ip_str
, const char *access_list_str
)
15068 struct bgp_dest
*dest
;
15069 struct bgp_distance
*bdistance
;
15071 afi
= bgp_node_afi(vty
);
15072 safi
= bgp_node_safi(vty
);
15074 ret
= str2prefix(ip_str
, &p
);
15076 vty_out(vty
, "Malformed prefix\n");
15077 return CMD_WARNING_CONFIG_FAILED
;
15080 distance
= atoi(distance_str
);
15082 /* Get BGP distance node. */
15083 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
15084 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15086 bgp_dest_unlock_node(dest
);
15088 bdistance
= bgp_distance_new();
15089 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
15092 /* Set distance value. */
15093 bdistance
->distance
= distance
;
15095 /* Reset access-list configuration. */
15096 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
15097 if (access_list_str
)
15098 bdistance
->access_list
=
15099 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
15101 return CMD_SUCCESS
;
15104 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
15105 const char *ip_str
, const char *access_list_str
)
15112 struct bgp_dest
*dest
;
15113 struct bgp_distance
*bdistance
;
15115 afi
= bgp_node_afi(vty
);
15116 safi
= bgp_node_safi(vty
);
15118 ret
= str2prefix(ip_str
, &p
);
15120 vty_out(vty
, "Malformed prefix\n");
15121 return CMD_WARNING_CONFIG_FAILED
;
15124 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
15126 vty_out(vty
, "Can't find specified prefix\n");
15127 return CMD_WARNING_CONFIG_FAILED
;
15130 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15131 distance
= atoi(distance_str
);
15133 if (bdistance
->distance
!= distance
) {
15134 vty_out(vty
, "Distance does not match configured\n");
15135 bgp_dest_unlock_node(dest
);
15136 return CMD_WARNING_CONFIG_FAILED
;
15139 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
15140 bgp_distance_free(bdistance
);
15142 bgp_dest_set_bgp_path_info(dest
, NULL
);
15143 bgp_dest_unlock_node(dest
);
15144 bgp_dest_unlock_node(dest
);
15146 return CMD_SUCCESS
;
15149 /* Apply BGP information to distance method. */
15150 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
15151 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
15153 struct bgp_dest
*dest
;
15154 struct prefix q
= {0};
15156 struct bgp_distance
*bdistance
;
15157 struct access_list
*alist
;
15158 struct bgp_static
*bgp_static
;
15159 struct bgp_path_info
*bpi_ultimate
;
15164 peer
= pinfo
->peer
;
15166 if (pinfo
->attr
->distance
)
15167 return pinfo
->attr
->distance
;
15169 /* get peer origin to calculate appropriate distance */
15170 if (pinfo
->sub_type
== BGP_ROUTE_IMPORTED
) {
15171 bpi_ultimate
= bgp_get_imported_bpi_ultimate(pinfo
);
15172 peer
= bpi_ultimate
->peer
;
15175 /* Check source address.
15176 * Note: for aggregate route, peer can have unspec af type.
15178 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
15179 && !sockunion2hostprefix(&peer
->su
, &q
))
15182 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
15184 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15185 bgp_dest_unlock_node(dest
);
15187 if (bdistance
->access_list
) {
15188 alist
= access_list_lookup(afi
, bdistance
->access_list
);
15190 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
15191 return bdistance
->distance
;
15193 return bdistance
->distance
;
15196 /* Backdoor check. */
15197 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
15199 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15200 bgp_dest_unlock_node(dest
);
15202 if (bgp_static
->backdoor
) {
15203 if (bgp
->distance_local
[afi
][safi
])
15204 return bgp
->distance_local
[afi
][safi
];
15206 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15210 if (peer
->sort
== BGP_PEER_EBGP
) {
15211 if (bgp
->distance_ebgp
[afi
][safi
])
15212 return bgp
->distance_ebgp
[afi
][safi
];
15213 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
15214 } else if (peer
->sort
== BGP_PEER_IBGP
) {
15215 if (bgp
->distance_ibgp
[afi
][safi
])
15216 return bgp
->distance_ibgp
[afi
][safi
];
15217 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15219 if (bgp
->distance_local
[afi
][safi
])
15220 return bgp
->distance_local
[afi
][safi
];
15221 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15225 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15226 * we should tell ZEBRA update the routes for a specific
15227 * AFI/SAFI to reflect changes in RIB.
15229 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
15231 safi_t update_safi
)
15236 FOREACH_AFI_SAFI (afi
, safi
) {
15237 if (!bgp_fibupd_safi(safi
))
15240 if (afi
!= update_afi
&& safi
!= update_safi
)
15243 if (BGP_DEBUG(zebra
, ZEBRA
))
15245 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15246 __func__
, afi
, safi
);
15247 bgp_zebra_announce_table(bgp
, afi
, safi
);
15251 DEFUN (bgp_distance
,
15253 "distance bgp (1-255) (1-255) (1-255)",
15254 "Define an administrative distance\n"
15256 "Distance for routes external to the AS\n"
15257 "Distance for routes internal to the AS\n"
15258 "Distance for local routes\n")
15260 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15261 int idx_number
= 2;
15262 int idx_number_2
= 3;
15263 int idx_number_3
= 4;
15264 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
15265 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
15266 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
15270 afi
= bgp_node_afi(vty
);
15271 safi
= bgp_node_safi(vty
);
15273 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
15274 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
15275 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
15276 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
15277 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
15278 bgp
->distance_local
[afi
][safi
] = distance_local
;
15279 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15281 return CMD_SUCCESS
;
15284 DEFUN (no_bgp_distance
,
15285 no_bgp_distance_cmd
,
15286 "no distance bgp [(1-255) (1-255) (1-255)]",
15288 "Define an administrative distance\n"
15290 "Distance for routes external to the AS\n"
15291 "Distance for routes internal to the AS\n"
15292 "Distance for local routes\n")
15294 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15298 afi
= bgp_node_afi(vty
);
15299 safi
= bgp_node_safi(vty
);
15301 if (bgp
->distance_ebgp
[afi
][safi
] != 0
15302 || bgp
->distance_ibgp
[afi
][safi
] != 0
15303 || bgp
->distance_local
[afi
][safi
] != 0) {
15304 bgp
->distance_ebgp
[afi
][safi
] = 0;
15305 bgp
->distance_ibgp
[afi
][safi
] = 0;
15306 bgp
->distance_local
[afi
][safi
] = 0;
15307 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15309 return CMD_SUCCESS
;
15313 DEFUN (bgp_distance_source
,
15314 bgp_distance_source_cmd
,
15315 "distance (1-255) A.B.C.D/M",
15316 "Define an administrative distance\n"
15317 "Administrative distance\n"
15318 "IP source prefix\n")
15320 int idx_number
= 1;
15321 int idx_ipv4_prefixlen
= 2;
15322 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15323 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15324 return CMD_SUCCESS
;
15327 DEFUN (no_bgp_distance_source
,
15328 no_bgp_distance_source_cmd
,
15329 "no distance (1-255) A.B.C.D/M",
15331 "Define an administrative distance\n"
15332 "Administrative distance\n"
15333 "IP source prefix\n")
15335 int idx_number
= 2;
15336 int idx_ipv4_prefixlen
= 3;
15337 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15338 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15339 return CMD_SUCCESS
;
15342 DEFUN (bgp_distance_source_access_list
,
15343 bgp_distance_source_access_list_cmd
,
15344 "distance (1-255) A.B.C.D/M WORD",
15345 "Define an administrative distance\n"
15346 "Administrative distance\n"
15347 "IP source prefix\n"
15348 "Access list name\n")
15350 int idx_number
= 1;
15351 int idx_ipv4_prefixlen
= 2;
15353 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15354 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15355 return CMD_SUCCESS
;
15358 DEFUN (no_bgp_distance_source_access_list
,
15359 no_bgp_distance_source_access_list_cmd
,
15360 "no distance (1-255) A.B.C.D/M WORD",
15362 "Define an administrative distance\n"
15363 "Administrative distance\n"
15364 "IP source prefix\n"
15365 "Access list name\n")
15367 int idx_number
= 2;
15368 int idx_ipv4_prefixlen
= 3;
15370 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15371 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15372 return CMD_SUCCESS
;
15375 DEFUN (ipv6_bgp_distance_source
,
15376 ipv6_bgp_distance_source_cmd
,
15377 "distance (1-255) X:X::X:X/M",
15378 "Define an administrative distance\n"
15379 "Administrative distance\n"
15380 "IP source prefix\n")
15382 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
15383 return CMD_SUCCESS
;
15386 DEFUN (no_ipv6_bgp_distance_source
,
15387 no_ipv6_bgp_distance_source_cmd
,
15388 "no distance (1-255) X:X::X:X/M",
15390 "Define an administrative distance\n"
15391 "Administrative distance\n"
15392 "IP source prefix\n")
15394 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
15395 return CMD_SUCCESS
;
15398 DEFUN (ipv6_bgp_distance_source_access_list
,
15399 ipv6_bgp_distance_source_access_list_cmd
,
15400 "distance (1-255) X:X::X:X/M WORD",
15401 "Define an administrative distance\n"
15402 "Administrative distance\n"
15403 "IP source prefix\n"
15404 "Access list name\n")
15406 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
15407 return CMD_SUCCESS
;
15410 DEFUN (no_ipv6_bgp_distance_source_access_list
,
15411 no_ipv6_bgp_distance_source_access_list_cmd
,
15412 "no distance (1-255) X:X::X:X/M WORD",
15414 "Define an administrative distance\n"
15415 "Administrative distance\n"
15416 "IP source prefix\n"
15417 "Access list name\n")
15419 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
15420 return CMD_SUCCESS
;
15423 DEFUN (bgp_damp_set
,
15425 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15426 "BGP Specific commands\n"
15427 "Enable route-flap dampening\n"
15428 "Half-life time for the penalty\n"
15429 "Value to start reusing a route\n"
15430 "Value to start suppressing a route\n"
15431 "Maximum duration to suppress a stable route\n")
15433 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15434 int idx_half_life
= 2;
15436 int idx_suppress
= 4;
15437 int idx_max_suppress
= 5;
15438 int half
= DEFAULT_HALF_LIFE
* 60;
15439 int reuse
= DEFAULT_REUSE
;
15440 int suppress
= DEFAULT_SUPPRESS
;
15441 int max
= 4 * half
;
15444 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15445 reuse
= atoi(argv
[idx_reuse
]->arg
);
15446 suppress
= atoi(argv
[idx_suppress
]->arg
);
15447 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
15448 } else if (argc
== 3) {
15449 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15454 * These can't be 0 but our SA doesn't understand the
15455 * way our cli is constructed
15459 if (suppress
< reuse
) {
15461 "Suppress value cannot be less than reuse value \n");
15465 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
15466 reuse
, suppress
, max
);
15469 DEFUN (bgp_damp_unset
,
15470 bgp_damp_unset_cmd
,
15471 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15473 "BGP Specific commands\n"
15474 "Enable route-flap dampening\n"
15475 "Half-life time for the penalty\n"
15476 "Value to start reusing a route\n"
15477 "Value to start suppressing a route\n"
15478 "Maximum duration to suppress a stable route\n")
15480 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15481 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
15484 /* Display specified route of BGP table. */
15485 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
15486 const char *ip_str
, afi_t afi
, safi_t safi
,
15487 struct prefix_rd
*prd
, int prefix_check
)
15490 struct prefix match
;
15491 struct bgp_dest
*dest
;
15492 struct bgp_dest
*rm
;
15493 struct bgp_path_info
*pi
;
15494 struct bgp_path_info
*pi_temp
;
15496 struct bgp_table
*table
;
15498 /* BGP structure lookup. */
15500 bgp
= bgp_lookup_by_name(view_name
);
15502 vty_out(vty
, "%% Can't find BGP instance %s\n",
15504 return CMD_WARNING
;
15507 bgp
= bgp_get_default();
15509 vty_out(vty
, "%% No BGP process is configured\n");
15510 return CMD_WARNING
;
15514 /* Check IP address argument. */
15515 ret
= str2prefix(ip_str
, &match
);
15517 vty_out(vty
, "%% address is malformed\n");
15518 return CMD_WARNING
;
15521 match
.family
= afi2family(afi
);
15523 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
15524 || (safi
== SAFI_EVPN
)) {
15525 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
15526 dest
= bgp_route_next(dest
)) {
15527 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15529 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
15531 table
= bgp_dest_get_bgp_table_info(dest
);
15534 rm
= bgp_node_match(table
, &match
);
15538 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
15541 || rm_p
->prefixlen
== match
.prefixlen
) {
15542 pi
= bgp_dest_get_bgp_path_info(rm
);
15544 if (pi
->extra
&& pi
->extra
->damp_info
) {
15545 pi_temp
= pi
->next
;
15546 bgp_damp_info_free(
15547 pi
->extra
->damp_info
,
15555 bgp_dest_unlock_node(rm
);
15558 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
15559 if (dest
!= NULL
) {
15560 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15563 || dest_p
->prefixlen
== match
.prefixlen
) {
15564 pi
= bgp_dest_get_bgp_path_info(dest
);
15566 if (pi
->extra
&& pi
->extra
->damp_info
) {
15567 pi_temp
= pi
->next
;
15568 bgp_damp_info_free(
15569 pi
->extra
->damp_info
,
15577 bgp_dest_unlock_node(dest
);
15581 return CMD_SUCCESS
;
15584 DEFUN (clear_ip_bgp_dampening
,
15585 clear_ip_bgp_dampening_cmd
,
15586 "clear ip bgp dampening",
15590 "Clear route flap dampening information\n")
15592 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
15593 return CMD_SUCCESS
;
15596 DEFUN (clear_ip_bgp_dampening_prefix
,
15597 clear_ip_bgp_dampening_prefix_cmd
,
15598 "clear ip bgp dampening A.B.C.D/M",
15602 "Clear route flap dampening information\n"
15605 int idx_ipv4_prefixlen
= 4;
15606 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
15607 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
15610 DEFUN (clear_ip_bgp_dampening_address
,
15611 clear_ip_bgp_dampening_address_cmd
,
15612 "clear ip bgp dampening A.B.C.D",
15616 "Clear route flap dampening information\n"
15617 "Network to clear damping information\n")
15620 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
15621 SAFI_UNICAST
, NULL
, 0);
15624 DEFUN (clear_ip_bgp_dampening_address_mask
,
15625 clear_ip_bgp_dampening_address_mask_cmd
,
15626 "clear ip bgp dampening A.B.C.D A.B.C.D",
15630 "Clear route flap dampening information\n"
15631 "Network to clear damping information\n"
15635 int idx_ipv4_2
= 5;
15637 char prefix_str
[BUFSIZ
];
15639 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
15640 prefix_str
, sizeof(prefix_str
));
15642 vty_out(vty
, "%% Inconsistent address and mask\n");
15643 return CMD_WARNING
;
15646 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
15650 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
15652 struct vty
*vty
= arg
;
15653 struct peer
*peer
= bucket
->data
;
15655 vty_out(vty
, "\tPeer: %s %pSU\n", peer
->host
, &peer
->su
);
15658 DEFUN (show_bgp_listeners
,
15659 show_bgp_listeners_cmd
,
15660 "show bgp listeners",
15663 "Display Listen Sockets and who created them\n")
15665 bgp_dump_listener_info(vty
);
15667 return CMD_SUCCESS
;
15670 DEFUN (show_bgp_peerhash
,
15671 show_bgp_peerhash_cmd
,
15672 "show bgp peerhash",
15675 "Display information about the BGP peerhash\n")
15677 struct list
*instances
= bm
->bgp
;
15678 struct listnode
*node
;
15681 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
15682 vty_out(vty
, "BGP: %s\n", bgp
->name
);
15683 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
15687 return CMD_SUCCESS
;
15690 /* also used for encap safi */
15691 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
15692 afi_t afi
, safi_t safi
)
15694 struct bgp_dest
*pdest
;
15695 struct bgp_dest
*dest
;
15696 struct bgp_table
*table
;
15697 const struct prefix
*p
;
15698 struct bgp_static
*bgp_static
;
15699 mpls_label_t label
;
15701 /* Network configuration. */
15702 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15703 pdest
= bgp_route_next(pdest
)) {
15704 table
= bgp_dest_get_bgp_table_info(pdest
);
15708 for (dest
= bgp_table_top(table
); dest
;
15709 dest
= bgp_route_next(dest
)) {
15710 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15711 if (bgp_static
== NULL
)
15714 p
= bgp_dest_get_prefix(dest
);
15716 /* "network" configuration display. */
15717 label
= decode_label(&bgp_static
->label
);
15719 vty_out(vty
, " network %pFX rd %s", p
,
15720 bgp_static
->prd_pretty
);
15721 if (safi
== SAFI_MPLS_VPN
)
15722 vty_out(vty
, " label %u", label
);
15724 if (bgp_static
->rmap
.name
)
15725 vty_out(vty
, " route-map %s",
15726 bgp_static
->rmap
.name
);
15728 if (bgp_static
->backdoor
)
15729 vty_out(vty
, " backdoor");
15731 vty_out(vty
, "\n");
15736 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
15737 afi_t afi
, safi_t safi
)
15739 struct bgp_dest
*pdest
;
15740 struct bgp_dest
*dest
;
15741 struct bgp_table
*table
;
15742 const struct prefix
*p
;
15743 struct bgp_static
*bgp_static
;
15744 char buf
[PREFIX_STRLEN
* 2];
15745 char buf2
[SU_ADDRSTRLEN
];
15746 char esi_buf
[ESI_STR_LEN
];
15748 /* Network configuration. */
15749 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15750 pdest
= bgp_route_next(pdest
)) {
15751 table
= bgp_dest_get_bgp_table_info(pdest
);
15755 for (dest
= bgp_table_top(table
); dest
;
15756 dest
= bgp_route_next(dest
)) {
15757 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15758 if (bgp_static
== NULL
)
15761 char *macrouter
= NULL
;
15763 if (bgp_static
->router_mac
)
15764 macrouter
= prefix_mac2str(
15765 bgp_static
->router_mac
, NULL
, 0);
15766 if (bgp_static
->eth_s_id
)
15767 esi_to_str(bgp_static
->eth_s_id
,
15768 esi_buf
, sizeof(esi_buf
));
15769 p
= bgp_dest_get_prefix(dest
);
15771 /* "network" configuration display. */
15772 if (p
->u
.prefix_evpn
.route_type
== 5) {
15773 char local_buf
[PREFIX_STRLEN
];
15775 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15776 struct prefix_evpn
*)p
)
15780 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
15782 local_buf
, sizeof(local_buf
));
15783 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15784 p
->u
.prefix_evpn
.prefix_addr
15785 .ip_prefix_length
);
15787 prefix2str(p
, buf
, sizeof(buf
));
15790 if (bgp_static
->gatewayIp
.family
== AF_INET
15791 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15792 inet_ntop(bgp_static
->gatewayIp
.family
,
15793 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15796 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15797 buf
, bgp_static
->prd_pretty
,
15798 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15799 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15802 XFREE(MTYPE_TMP
, macrouter
);
15807 /* Configuration of static route announcement and aggregate
15809 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15812 struct bgp_dest
*dest
;
15813 const struct prefix
*p
;
15814 struct bgp_static
*bgp_static
;
15815 struct bgp_aggregate
*bgp_aggregate
;
15817 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15818 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15822 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15823 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15827 /* Network configuration. */
15828 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15829 dest
= bgp_route_next(dest
)) {
15830 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15831 if (bgp_static
== NULL
)
15834 p
= bgp_dest_get_prefix(dest
);
15836 vty_out(vty
, " network %pFX", p
);
15838 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15839 vty_out(vty
, " label-index %u",
15840 bgp_static
->label_index
);
15842 if (bgp_static
->rmap
.name
)
15843 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15845 if (bgp_static
->backdoor
)
15846 vty_out(vty
, " backdoor");
15848 vty_out(vty
, "\n");
15851 /* Aggregate-address configuration. */
15852 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15853 dest
= bgp_route_next(dest
)) {
15854 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15855 if (bgp_aggregate
== NULL
)
15858 p
= bgp_dest_get_prefix(dest
);
15860 vty_out(vty
, " aggregate-address %pFX", p
);
15862 if (bgp_aggregate
->as_set
)
15863 vty_out(vty
, " as-set");
15865 if (bgp_aggregate
->summary_only
)
15866 vty_out(vty
, " summary-only");
15868 if (bgp_aggregate
->rmap
.name
)
15869 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15871 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15872 vty_out(vty
, " origin %s",
15873 bgp_origin2str(bgp_aggregate
->origin
));
15875 if (bgp_aggregate
->match_med
)
15876 vty_out(vty
, " matching-MED-only");
15878 if (bgp_aggregate
->suppress_map_name
)
15879 vty_out(vty
, " suppress-map %s",
15880 bgp_aggregate
->suppress_map_name
);
15882 vty_out(vty
, "\n");
15886 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15889 struct bgp_dest
*dest
;
15890 struct bgp_distance
*bdistance
;
15892 /* Distance configuration. */
15893 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15894 && bgp
->distance_local
[afi
][safi
]
15895 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15896 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15897 || bgp
->distance_local
[afi
][safi
]
15898 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15899 vty_out(vty
, " distance bgp %d %d %d\n",
15900 bgp
->distance_ebgp
[afi
][safi
],
15901 bgp
->distance_ibgp
[afi
][safi
],
15902 bgp
->distance_local
[afi
][safi
]);
15905 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15906 dest
= bgp_route_next(dest
)) {
15907 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15908 if (bdistance
!= NULL
)
15909 vty_out(vty
, " distance %d %pBD %s\n",
15910 bdistance
->distance
, dest
,
15911 bdistance
->access_list
? bdistance
->access_list
15916 /* Allocate routing table structure and install commands. */
15917 void bgp_route_init(void)
15922 /* Init BGP distance table. */
15923 FOREACH_AFI_SAFI (afi
, safi
)
15924 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15926 /* IPv4 BGP commands. */
15927 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15928 install_element(BGP_NODE
, &bgp_network_cmd
);
15929 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15931 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15933 /* IPv4 unicast configuration. */
15934 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15935 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15936 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15938 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15940 /* IPv4 multicast configuration. */
15941 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15942 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15943 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15944 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15946 /* IPv4 labeled-unicast configuration. */
15947 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15948 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15950 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15951 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15952 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15953 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15954 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15955 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15956 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15957 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15959 install_element(VIEW_NODE
,
15960 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15961 install_element(VIEW_NODE
,
15962 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15963 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15964 install_element(VIEW_NODE
,
15965 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15966 #ifdef KEEP_OLD_VPN_COMMANDS
15967 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15968 #endif /* KEEP_OLD_VPN_COMMANDS */
15969 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15970 install_element(VIEW_NODE
,
15971 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15973 /* BGP dampening clear commands */
15974 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15975 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15977 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15978 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15981 install_element(ENABLE_NODE
,
15982 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15983 #ifdef KEEP_OLD_VPN_COMMANDS
15984 install_element(ENABLE_NODE
,
15985 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15986 #endif /* KEEP_OLD_VPN_COMMANDS */
15988 /* New config IPv6 BGP commands. */
15989 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15990 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15991 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15993 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15995 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15997 /* IPv6 labeled unicast address family. */
15998 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15999 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
16001 install_element(BGP_NODE
, &bgp_distance_cmd
);
16002 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
16003 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
16004 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
16005 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
16006 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
16007 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
16008 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
16009 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
16010 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
16011 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
16012 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
16013 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
16014 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
16015 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
16016 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
16017 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
16018 install_element(BGP_IPV4M_NODE
,
16019 &no_bgp_distance_source_access_list_cmd
);
16020 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
16021 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
16022 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
16023 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
16024 install_element(BGP_IPV6_NODE
,
16025 &ipv6_bgp_distance_source_access_list_cmd
);
16026 install_element(BGP_IPV6_NODE
,
16027 &no_ipv6_bgp_distance_source_access_list_cmd
);
16028 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
16029 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
16030 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
16031 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
16032 install_element(BGP_IPV6M_NODE
,
16033 &ipv6_bgp_distance_source_access_list_cmd
);
16034 install_element(BGP_IPV6M_NODE
,
16035 &no_ipv6_bgp_distance_source_access_list_cmd
);
16037 /* BGP dampening */
16038 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
16039 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
16040 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
16041 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
16042 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
16043 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
16044 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
16045 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
16046 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
16047 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
16048 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
16049 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
16050 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
16051 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
16053 /* Large Communities */
16054 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
16055 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
16057 /* show bgp ipv4 flowspec detailed */
16058 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
16060 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
16061 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
16064 void bgp_route_finish(void)
16069 FOREACH_AFI_SAFI (afi
, safi
) {
16070 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
16071 bgp_distance_table
[afi
][safi
] = NULL
;