1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* BGP routing information
3 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
4 * Copyright (C) 2016 Job Snijders <job@instituut.net>
21 #include "sockunion.h"
24 #include "workqueue.h"
29 #include "lib_errors.h"
31 #include "bgpd/bgpd.h"
32 #include "bgpd/bgp_table.h"
33 #include "bgpd/bgp_route.h"
34 #include "bgpd/bgp_attr.h"
35 #include "bgpd/bgp_debug.h"
36 #include "bgpd/bgp_errors.h"
37 #include "bgpd/bgp_aspath.h"
38 #include "bgpd/bgp_regex.h"
39 #include "bgpd/bgp_community.h"
40 #include "bgpd/bgp_community_alias.h"
41 #include "bgpd/bgp_ecommunity.h"
42 #include "bgpd/bgp_lcommunity.h"
43 #include "bgpd/bgp_clist.h"
44 #include "bgpd/bgp_packet.h"
45 #include "bgpd/bgp_filter.h"
46 #include "bgpd/bgp_fsm.h"
47 #include "bgpd/bgp_mplsvpn.h"
48 #include "bgpd/bgp_nexthop.h"
49 #include "bgpd/bgp_damp.h"
50 #include "bgpd/bgp_advertise.h"
51 #include "bgpd/bgp_zebra.h"
52 #include "bgpd/bgp_vty.h"
53 #include "bgpd/bgp_mpath.h"
54 #include "bgpd/bgp_nht.h"
55 #include "bgpd/bgp_updgrp.h"
56 #include "bgpd/bgp_label.h"
57 #include "bgpd/bgp_addpath.h"
58 #include "bgpd/bgp_mac.h"
59 #include "bgpd/bgp_network.h"
60 #include "bgpd/bgp_trace.h"
61 #include "bgpd/bgp_rpki.h"
64 #include "bgpd/rfapi/rfapi_backend.h"
65 #include "bgpd/rfapi/vnc_import_bgp.h"
66 #include "bgpd/rfapi/vnc_export_bgp.h"
68 #include "bgpd/bgp_encap_types.h"
69 #include "bgpd/bgp_encap_tlv.h"
70 #include "bgpd/bgp_evpn.h"
71 #include "bgpd/bgp_evpn_mh.h"
72 #include "bgpd/bgp_evpn_vty.h"
73 #include "bgpd/bgp_flowspec.h"
74 #include "bgpd/bgp_flowspec_util.h"
75 #include "bgpd/bgp_pbr.h"
77 #include "bgpd/bgp_route_clippy.c"
79 DEFINE_HOOK(bgp_snmp_update_stats
,
80 (struct bgp_node
*rn
, struct bgp_path_info
*pi
, bool added
),
83 DEFINE_HOOK(bgp_rpki_prefix_status
,
84 (struct peer
*peer
, struct attr
*attr
,
85 const struct prefix
*prefix
),
86 (peer
, attr
, prefix
));
88 /* Extern from bgp_dump.c */
89 extern const char *bgp_origin_str
[];
90 extern const char *bgp_origin_long_str
[];
93 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
94 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
95 static const struct message bgp_pmsi_tnltype_str
[] = {
96 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
97 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
98 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
99 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
100 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
101 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
102 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
103 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
107 #define VRFID_NONE_STR "-"
108 #define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
110 DEFINE_HOOK(bgp_process
,
111 (struct bgp
* bgp
, afi_t afi
, safi_t safi
, struct bgp_dest
*bn
,
112 struct peer
*peer
, bool withdraw
),
113 (bgp
, afi
, safi
, bn
, peer
, withdraw
));
115 /** Test if path is suppressed. */
116 static bool bgp_path_suppressed(struct bgp_path_info
*pi
)
118 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
121 return listcount(pi
->extra
->aggr_suppressors
) > 0;
124 struct bgp_dest
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
125 safi_t safi
, const struct prefix
*p
,
126 struct prefix_rd
*prd
)
128 struct bgp_dest
*dest
;
129 struct bgp_dest
*pdest
= NULL
;
133 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
134 || (safi
== SAFI_EVPN
)) {
135 pdest
= bgp_node_get(table
, (struct prefix
*)prd
);
137 if (!bgp_dest_has_bgp_path_info_data(pdest
))
138 bgp_dest_set_bgp_table_info(
139 pdest
, bgp_table_init(table
->bgp
, afi
, safi
));
141 bgp_dest_unlock_node(pdest
);
142 table
= bgp_dest_get_bgp_table_info(pdest
);
145 dest
= bgp_node_get(table
, p
);
147 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
148 || (safi
== SAFI_EVPN
))
154 struct bgp_dest
*bgp_safi_node_lookup(struct bgp_table
*table
, safi_t safi
,
155 const struct prefix
*p
,
156 struct prefix_rd
*prd
)
158 struct bgp_dest
*dest
;
159 struct bgp_dest
*pdest
= NULL
;
164 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
165 || (safi
== SAFI_EVPN
)) {
166 pdest
= bgp_node_lookup(table
, (struct prefix
*)prd
);
170 if (!bgp_dest_has_bgp_path_info_data(pdest
)) {
171 bgp_dest_unlock_node(pdest
);
175 table
= bgp_dest_get_bgp_table_info(pdest
);
178 dest
= bgp_node_lookup(table
, p
);
183 /* Allocate bgp_path_info_extra */
184 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
186 struct bgp_path_info_extra
*new;
187 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
188 sizeof(struct bgp_path_info_extra
));
189 new->label
[0] = MPLS_INVALID_LABEL
;
191 new->bgp_fs_pbr
= NULL
;
192 new->bgp_fs_iprule
= NULL
;
196 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
198 struct bgp_path_info_extra
*e
;
200 if (!extra
|| !*extra
)
205 bgp_damp_info_free(e
->damp_info
, 0, e
->damp_info
->afi
,
210 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
213 /* FIXME: since multiple e may have the same e->parent
214 * and e->parent->net is holding a refcount for each
215 * of them, we need to do some fudging here.
217 * WARNING: if bpi->net->lock drops to 0, bpi may be
218 * freed as well (because bpi->net was holding the
219 * last reference to bpi) => write after free!
223 bpi
= bgp_path_info_lock(bpi
);
224 refcount
= bgp_dest_get_lock_count(bpi
->net
) - 1;
225 bgp_dest_unlock_node((struct bgp_dest
*)bpi
->net
);
228 bgp_path_info_unlock(bpi
);
230 bgp_path_info_unlock(e
->parent
);
235 bgp_unlock(e
->bgp_orig
);
238 peer_unlock(e
->peer_orig
);
240 if (e
->aggr_suppressors
)
241 list_delete(&e
->aggr_suppressors
);
244 bgp_evpn_path_mh_info_free(e
->mh_info
);
246 if ((*extra
)->bgp_fs_iprule
)
247 list_delete(&((*extra
)->bgp_fs_iprule
));
248 if ((*extra
)->bgp_fs_pbr
)
249 list_delete(&((*extra
)->bgp_fs_pbr
));
250 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
253 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
254 * allocated if required.
256 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
259 pi
->extra
= bgp_path_info_extra_new();
263 /* Free bgp route information. */
264 void bgp_path_info_free_with_caller(const char *name
,
265 struct bgp_path_info
*path
)
267 frrtrace(2, frr_bgp
, bgp_path_info_free
, path
, name
);
268 bgp_attr_unintern(&path
->attr
);
270 bgp_unlink_nexthop(path
);
271 bgp_path_info_extra_free(&path
->extra
);
272 bgp_path_info_mpath_free(&path
->mpath
);
274 bgp_addpath_free_info_data(&path
->tx_addpath
,
275 &path
->net
->tx_addpath
);
277 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
279 XFREE(MTYPE_BGP_ROUTE
, path
);
282 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
288 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
290 assert(path
&& path
->lock
> 0);
293 if (path
->lock
== 0) {
294 bgp_path_info_free(path
);
301 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
302 static int bgp_dest_set_defer_flag(struct bgp_dest
*dest
, bool delete)
305 struct bgp_path_info
*old_pi
, *nextpi
;
306 bool set_flag
= false;
307 struct bgp
*bgp
= NULL
;
308 struct bgp_table
*table
= NULL
;
312 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
313 * then the route selection is deferred
315 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
318 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
319 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
320 table
= bgp_dest_table(dest
);
325 "Route %pBD(%s) is in workqueue and being processed, not deferred.",
326 dest
, bgp
? bgp
->name_pretty
: "(Unknown)");
332 table
= bgp_dest_table(dest
);
339 for (old_pi
= bgp_dest_get_bgp_path_info(dest
);
340 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
341 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
344 /* Route selection is deferred if there is a stale path which
345 * which indicates peer is in restart mode
347 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
348 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
351 /* If the peer is graceful restart capable and peer is
352 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
355 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
356 && BGP_PEER_RESTARTING_MODE(peer
)
358 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
366 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
369 if (set_flag
&& table
) {
370 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
371 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
372 bgp
->gr_info
[afi
][safi
].gr_deferred
++;
373 SET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
374 if (BGP_DEBUG(update
, UPDATE_OUT
))
375 zlog_debug("DEFER route %pBD(%s), dest %p",
376 dest
, bgp
->name_pretty
, dest
);
383 void bgp_path_info_add_with_caller(const char *name
, struct bgp_dest
*dest
,
384 struct bgp_path_info
*pi
)
386 frrtrace(3, frr_bgp
, bgp_path_info_add
, dest
, pi
, name
);
387 struct bgp_path_info
*top
;
389 top
= bgp_dest_get_bgp_path_info(dest
);
395 bgp_dest_set_bgp_path_info(dest
, pi
);
397 bgp_path_info_lock(pi
);
398 bgp_dest_lock_node(dest
);
399 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
400 bgp_dest_set_defer_flag(dest
, false);
401 hook_call(bgp_snmp_update_stats
, dest
, pi
, true);
404 /* Do the actual removal of info from RIB, for use by bgp_process
405 completion callback *only* */
406 void bgp_path_info_reap(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
409 pi
->next
->prev
= pi
->prev
;
411 pi
->prev
->next
= pi
->next
;
413 bgp_dest_set_bgp_path_info(dest
, pi
->next
);
415 bgp_path_info_mpath_dequeue(pi
);
416 bgp_path_info_unlock(pi
);
417 hook_call(bgp_snmp_update_stats
, dest
, pi
, false);
418 bgp_dest_unlock_node(dest
);
421 void bgp_path_info_delete(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
423 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_REMOVED
);
424 /* set of previous already took care of pcount */
425 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
428 /* undo the effects of a previous call to bgp_path_info_delete; typically
429 called when a route is deleted and then quickly re-added before the
430 deletion has been processed */
431 void bgp_path_info_restore(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
433 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_REMOVED
);
434 /* unset of previous already took care of pcount */
435 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
438 /* Adjust pcount as required */
439 static void bgp_pcount_adjust(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
441 struct bgp_table
*table
;
443 assert(dest
&& bgp_dest_table(dest
));
444 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
446 table
= bgp_dest_table(dest
);
448 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
451 if (!BGP_PATH_COUNTABLE(pi
)
452 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
454 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
456 /* slight hack, but more robust against errors. */
457 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
458 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
460 flog_err(EC_LIB_DEVELOPMENT
,
461 "Asked to decrement 0 prefix count for peer");
462 } else if (BGP_PATH_COUNTABLE(pi
)
463 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
464 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
465 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
469 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
470 struct bgp_path_info
*pi2
)
472 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
475 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
476 * This is here primarily to keep prefix-count in check.
478 void bgp_path_info_set_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
481 SET_FLAG(pi
->flags
, flag
);
483 /* early bath if we know it's not a flag that changes countability state
485 if (!CHECK_FLAG(flag
,
486 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
489 bgp_pcount_adjust(dest
, pi
);
492 void bgp_path_info_unset_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
495 UNSET_FLAG(pi
->flags
, flag
);
497 /* early bath if we know it's not a flag that changes countability state
499 if (!CHECK_FLAG(flag
,
500 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
503 bgp_pcount_adjust(dest
, pi
);
506 /* Get MED value. If MED value is missing and "bgp bestpath
507 missing-as-worst" is specified, treat it as the worst value. */
508 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
510 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
513 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
520 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
,
525 if (pi
->sub_type
== BGP_ROUTE_IMPORTED
&&
526 bgp_get_imported_bpi_ultimate(pi
))
527 peer
= bgp_get_imported_bpi_ultimate(pi
)->peer
;
531 if (pi
->addpath_rx_id
)
532 snprintf(buf
, buf_len
, "path %s (addpath rxid %d)", peer
->host
,
535 snprintf(buf
, buf_len
, "path %s", peer
->host
);
540 * Get the ultimate path info.
542 struct bgp_path_info
*bgp_get_imported_bpi_ultimate(struct bgp_path_info
*info
)
544 struct bgp_path_info
*bpi_ultimate
;
546 if (info
->sub_type
!= BGP_ROUTE_IMPORTED
)
549 for (bpi_ultimate
= info
;
550 bpi_ultimate
->extra
&& bpi_ultimate
->extra
->parent
;
551 bpi_ultimate
= bpi_ultimate
->extra
->parent
)
557 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
559 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
560 struct bgp_path_info
*exist
, int *paths_eq
,
561 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
562 char *pfx_buf
, afi_t afi
, safi_t safi
,
563 enum bgp_path_selection_reason
*reason
)
565 const struct prefix
*new_p
;
566 struct attr
*newattr
, *existattr
;
567 enum bgp_peer_sort new_sort
;
568 enum bgp_peer_sort exist_sort
;
574 uint32_t exist_weight
;
575 uint32_t newm
, existm
;
576 struct in_addr new_id
;
577 struct in_addr exist_id
;
580 int internal_as_route
;
583 int igp_metric_ret
= 0;
584 int peer_sort_ret
= -1;
585 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
586 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
588 uint32_t exist_mm_seq
;
595 bool new_origin
, exist_origin
;
596 struct bgp_path_info
*bpi_ultimate
;
597 struct peer
*peer_new
, *peer_exist
;
603 *reason
= bgp_path_selection_none
;
605 zlog_debug("%s: new is NULL", pfx_buf
);
610 bpi_ultimate
= bgp_get_imported_bpi_ultimate(new);
611 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, new_buf
,
616 *reason
= bgp_path_selection_first
;
618 zlog_debug("%s(%s): %s is the initial bestpath",
619 pfx_buf
, bgp
->name_pretty
, new_buf
);
624 bpi_ultimate
= bgp_get_imported_bpi_ultimate(exist
);
625 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, exist_buf
,
627 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
628 pfx_buf
, bgp
->name_pretty
, new_buf
, new->flags
,
629 exist_buf
, exist
->flags
);
633 existattr
= exist
->attr
;
635 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
636 * Capability" to a neighbor MUST perform the following upon receiving
637 * a route from that neighbor with the "LLGR_STALE" community, or upon
638 * attaching the "LLGR_STALE" community itself per Section 4.2:
640 * Treat the route as the least-preferred in route selection (see
641 * below). See the Risks of Depreferencing Routes section (Section 5.2)
642 * for a discussion of potential risks inherent in doing this.
644 if (bgp_attr_get_community(newattr
) &&
645 community_include(bgp_attr_get_community(newattr
),
646 COMMUNITY_LLGR_STALE
)) {
649 "%s: %s wins over %s due to LLGR_STALE community",
650 pfx_buf
, new_buf
, exist_buf
);
654 if (bgp_attr_get_community(existattr
) &&
655 community_include(bgp_attr_get_community(existattr
),
656 COMMUNITY_LLGR_STALE
)) {
659 "%s: %s loses to %s due to LLGR_STALE community",
660 pfx_buf
, new_buf
, exist_buf
);
664 new_p
= bgp_dest_get_prefix(new->net
);
666 /* For EVPN routes, we cannot just go by local vs remote, we have to
667 * look at the MAC mobility sequence number, if present.
669 if ((safi
== SAFI_EVPN
)
670 && (new_p
->u
.prefix_evpn
.route_type
== BGP_EVPN_MAC_IP_ROUTE
)) {
671 /* This is an error condition described in RFC 7432 Section
673 * states that in this scenario "the PE MUST alert the operator"
675 * does not state what other action to take. In order to provide
677 * consistency in this scenario we are going to prefer the path
681 if (newattr
->sticky
!= existattr
->sticky
) {
683 prefix2str(new_p
, pfx_buf
,
685 * PREFIX2STR_BUFFER
);
686 bgp_path_info_path_with_addpath_rx_str(
687 new, new_buf
, sizeof(new_buf
));
688 bgp_path_info_path_with_addpath_rx_str(
689 exist
, exist_buf
, sizeof(exist_buf
));
692 if (newattr
->sticky
&& !existattr
->sticky
) {
693 *reason
= bgp_path_selection_evpn_sticky_mac
;
696 "%s: %s wins over %s due to sticky MAC flag",
697 pfx_buf
, new_buf
, exist_buf
);
701 if (!newattr
->sticky
&& existattr
->sticky
) {
702 *reason
= bgp_path_selection_evpn_sticky_mac
;
705 "%s: %s loses to %s due to sticky MAC flag",
706 pfx_buf
, new_buf
, exist_buf
);
711 new_esi
= bgp_evpn_attr_get_esi(newattr
);
712 exist_esi
= bgp_evpn_attr_get_esi(existattr
);
713 if (bgp_evpn_is_esi_valid(new_esi
) &&
714 !memcmp(new_esi
, exist_esi
, sizeof(esi_t
))) {
720 /* If both paths have the same non-zero ES and
721 * one path is local it wins.
722 * PS: Note the local path wins even if the remote
723 * has the higher MM seq. The local path's
724 * MM seq will be fixed up to match the highest
725 * rem seq, subsequently.
728 char esi_buf
[ESI_STR_LEN
];
730 if (bgp_evpn_is_path_local(bgp
, new)) {
731 *reason
= bgp_path_selection_evpn_local_path
;
734 "%s: %s wins over %s as ES %s is same and local",
735 pfx_buf
, new_buf
, exist_buf
,
736 esi_to_str(new_esi
, esi_buf
,
740 if (bgp_evpn_is_path_local(bgp
, exist
)) {
741 *reason
= bgp_path_selection_evpn_local_path
;
744 "%s: %s loses to %s as ES %s is same and local",
745 pfx_buf
, new_buf
, exist_buf
,
746 esi_to_str(new_esi
, esi_buf
,
752 new_mm_seq
= mac_mobility_seqnum(newattr
);
753 exist_mm_seq
= mac_mobility_seqnum(existattr
);
755 if (new_mm_seq
> exist_mm_seq
) {
756 *reason
= bgp_path_selection_evpn_seq
;
759 "%s: %s wins over %s due to MM seq %u > %u",
760 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
765 if (new_mm_seq
< exist_mm_seq
) {
766 *reason
= bgp_path_selection_evpn_seq
;
769 "%s: %s loses to %s due to MM seq %u < %u",
770 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
775 /* if the sequence numbers and ESI are the same and one path
776 * is non-proxy it wins (over proxy)
778 new_proxy
= bgp_evpn_attr_is_proxy(newattr
);
779 old_proxy
= bgp_evpn_attr_is_proxy(existattr
);
780 if (same_esi
&& bgp_evpn_attr_is_local_es(newattr
) &&
781 old_proxy
!= new_proxy
) {
783 *reason
= bgp_path_selection_evpn_non_proxy
;
786 "%s: %s wins over %s, same seq/es and non-proxy",
787 pfx_buf
, new_buf
, exist_buf
);
791 *reason
= bgp_path_selection_evpn_non_proxy
;
794 "%s: %s loses to %s, same seq/es and non-proxy",
795 pfx_buf
, new_buf
, exist_buf
);
800 * if sequence numbers are the same path with the lowest IP
803 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
805 *reason
= bgp_path_selection_evpn_lower_ip
;
808 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
809 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
810 &new->attr
->nexthop
);
814 *reason
= bgp_path_selection_evpn_lower_ip
;
817 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
818 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
819 &new->attr
->nexthop
);
824 /* 1. Weight check. */
825 new_weight
= newattr
->weight
;
826 exist_weight
= existattr
->weight
;
828 if (new_weight
> exist_weight
) {
829 *reason
= bgp_path_selection_weight
;
831 zlog_debug("%s: %s wins over %s due to weight %d > %d",
832 pfx_buf
, new_buf
, exist_buf
, new_weight
,
837 if (new_weight
< exist_weight
) {
838 *reason
= bgp_path_selection_weight
;
840 zlog_debug("%s: %s loses to %s due to weight %d < %d",
841 pfx_buf
, new_buf
, exist_buf
, new_weight
,
846 /* 2. Local preference check. */
847 new_pref
= exist_pref
= bgp
->default_local_pref
;
849 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
850 new_pref
= newattr
->local_pref
;
851 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
852 exist_pref
= existattr
->local_pref
;
854 if (new_pref
> exist_pref
) {
855 *reason
= bgp_path_selection_local_pref
;
858 "%s: %s wins over %s due to localpref %d > %d",
859 pfx_buf
, new_buf
, exist_buf
, new_pref
,
864 if (new_pref
< exist_pref
) {
865 *reason
= bgp_path_selection_local_pref
;
868 "%s: %s loses to %s due to localpref %d < %d",
869 pfx_buf
, new_buf
, exist_buf
, new_pref
,
874 /* If a BGP speaker supports ACCEPT_OWN and is configured for the
875 * extensions defined in this document, the following step is inserted
876 * after the LOCAL_PREF comparison step in the BGP decision process:
877 * When comparing a pair of routes for a BGP destination, the
878 * route with the ACCEPT_OWN community attached is preferred over
879 * the route that does not have the community.
880 * This extra step MUST only be invoked during the best path selection
881 * process of VPN-IP routes.
883 if (safi
== SAFI_MPLS_VPN
&&
884 (CHECK_FLAG(new->peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
) ||
885 CHECK_FLAG(exist
->peer
->af_flags
[afi
][safi
],
886 PEER_FLAG_ACCEPT_OWN
))) {
887 bool new_accept_own
= false;
888 bool exist_accept_own
= false;
889 uint32_t accept_own
= COMMUNITY_ACCEPT_OWN
;
891 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))
892 new_accept_own
= community_include(
893 bgp_attr_get_community(newattr
), accept_own
);
894 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))
895 exist_accept_own
= community_include(
896 bgp_attr_get_community(existattr
), accept_own
);
898 if (new_accept_own
&& !exist_accept_own
) {
899 *reason
= bgp_path_selection_accept_own
;
902 "%s: %s wins over %s due to accept-own",
903 pfx_buf
, new_buf
, exist_buf
);
907 if (!new_accept_own
&& exist_accept_own
) {
908 *reason
= bgp_path_selection_accept_own
;
911 "%s: %s loses to %s due to accept-own",
912 pfx_buf
, new_buf
, exist_buf
);
917 /* Tie-breaker - AIGP (Metric TLV) attribute */
918 if (CHECK_FLAG(newattr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) &&
919 CHECK_FLAG(existattr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) &&
920 CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_AIGP
)) {
921 uint64_t new_aigp
= bgp_attr_get_aigp_metric(newattr
);
922 uint64_t exist_aigp
= bgp_attr_get_aigp_metric(existattr
);
924 if (new_aigp
< exist_aigp
) {
925 *reason
= bgp_path_selection_aigp
;
928 "%s: %s wins over %s due to AIGP %" PRIu64
930 pfx_buf
, new_buf
, exist_buf
, new_aigp
,
935 if (new_aigp
> exist_aigp
) {
936 *reason
= bgp_path_selection_aigp
;
939 "%s: %s loses to %s due to AIGP %" PRIu64
941 pfx_buf
, new_buf
, exist_buf
, new_aigp
,
947 /* 3. Local route check. We prefer:
949 * - BGP_ROUTE_AGGREGATE
950 * - BGP_ROUTE_REDISTRIBUTE
952 new_origin
= !(new->sub_type
== BGP_ROUTE_NORMAL
||
953 new->sub_type
== BGP_ROUTE_IMPORTED
);
954 exist_origin
= !(exist
->sub_type
== BGP_ROUTE_NORMAL
||
955 exist
->sub_type
== BGP_ROUTE_IMPORTED
);
957 if (new_origin
&& !exist_origin
) {
958 *reason
= bgp_path_selection_local_route
;
961 "%s: %s wins over %s due to preferred BGP_ROUTE type",
962 pfx_buf
, new_buf
, exist_buf
);
966 if (!new_origin
&& exist_origin
) {
967 *reason
= bgp_path_selection_local_route
;
970 "%s: %s loses to %s due to preferred BGP_ROUTE type",
971 pfx_buf
, new_buf
, exist_buf
);
975 /* Here if these are imported routes then get ultimate pi for
978 new = bgp_get_imported_bpi_ultimate(new);
979 exist
= bgp_get_imported_bpi_ultimate(exist
);
981 existattr
= exist
->attr
;
983 /* 4. AS path length check. */
984 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
985 int exist_hops
= aspath_count_hops(existattr
->aspath
);
986 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
988 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
991 aspath_hops
= aspath_count_hops(newattr
->aspath
);
992 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
994 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
995 *reason
= bgp_path_selection_confed_as_path
;
998 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
999 pfx_buf
, new_buf
, exist_buf
,
1001 (exist_hops
+ exist_confeds
));
1005 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
1006 *reason
= bgp_path_selection_confed_as_path
;
1009 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
1010 pfx_buf
, new_buf
, exist_buf
,
1012 (exist_hops
+ exist_confeds
));
1016 int newhops
= aspath_count_hops(newattr
->aspath
);
1018 if (newhops
< exist_hops
) {
1019 *reason
= bgp_path_selection_as_path
;
1022 "%s: %s wins over %s due to aspath hopcount %d < %d",
1023 pfx_buf
, new_buf
, exist_buf
,
1024 newhops
, exist_hops
);
1028 if (newhops
> exist_hops
) {
1029 *reason
= bgp_path_selection_as_path
;
1032 "%s: %s loses to %s due to aspath hopcount %d > %d",
1033 pfx_buf
, new_buf
, exist_buf
,
1034 newhops
, exist_hops
);
1040 /* 5. Origin check. */
1041 if (newattr
->origin
< existattr
->origin
) {
1042 *reason
= bgp_path_selection_origin
;
1044 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
1045 pfx_buf
, new_buf
, exist_buf
,
1046 bgp_origin_long_str
[newattr
->origin
],
1047 bgp_origin_long_str
[existattr
->origin
]);
1051 if (newattr
->origin
> existattr
->origin
) {
1052 *reason
= bgp_path_selection_origin
;
1054 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
1055 pfx_buf
, new_buf
, exist_buf
,
1056 bgp_origin_long_str
[newattr
->origin
],
1057 bgp_origin_long_str
[existattr
->origin
]);
1062 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
1063 && aspath_count_hops(existattr
->aspath
) == 0);
1064 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
1065 && aspath_count_confeds(existattr
->aspath
) > 0
1066 && aspath_count_hops(newattr
->aspath
) == 0
1067 && aspath_count_hops(existattr
->aspath
) == 0);
1069 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
1070 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
1071 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
1072 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
1073 || internal_as_route
) {
1074 new_med
= bgp_med_value(new->attr
, bgp
);
1075 exist_med
= bgp_med_value(exist
->attr
, bgp
);
1077 if (new_med
< exist_med
) {
1078 *reason
= bgp_path_selection_med
;
1081 "%s: %s wins over %s due to MED %d < %d",
1082 pfx_buf
, new_buf
, exist_buf
, new_med
,
1087 if (new_med
> exist_med
) {
1088 *reason
= bgp_path_selection_med
;
1091 "%s: %s loses to %s due to MED %d > %d",
1092 pfx_buf
, new_buf
, exist_buf
, new_med
,
1098 if (exist
->sub_type
== BGP_ROUTE_IMPORTED
) {
1099 bpi_ultimate
= bgp_get_imported_bpi_ultimate(exist
);
1100 peer_exist
= bpi_ultimate
->peer
;
1102 peer_exist
= exist
->peer
;
1104 if (new->sub_type
== BGP_ROUTE_IMPORTED
) {
1105 bpi_ultimate
= bgp_get_imported_bpi_ultimate(new);
1106 peer_new
= bpi_ultimate
->peer
;
1108 peer_new
= new->peer
;
1110 /* 7. Peer type check. */
1111 new_sort
= peer_new
->sort
;
1112 exist_sort
= peer_exist
->sort
;
1114 if (new_sort
== BGP_PEER_EBGP
1115 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
1116 *reason
= bgp_path_selection_peer
;
1119 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1120 pfx_buf
, new_buf
, exist_buf
);
1121 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1126 if (exist_sort
== BGP_PEER_EBGP
1127 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
1128 *reason
= bgp_path_selection_peer
;
1131 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1132 pfx_buf
, new_buf
, exist_buf
);
1133 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1138 /* 8. IGP metric check. */
1142 newm
= new->extra
->igpmetric
;
1144 existm
= exist
->extra
->igpmetric
;
1146 if (newm
< existm
) {
1147 if (debug
&& peer_sort_ret
< 0)
1149 "%s: %s wins over %s due to IGP metric %u < %u",
1150 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1154 if (newm
> existm
) {
1155 if (debug
&& peer_sort_ret
< 0)
1157 "%s: %s loses to %s due to IGP metric %u > %u",
1158 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1162 /* 9. Same IGP metric. Compare the cluster list length as
1163 representative of IGP hops metric. Rewrite the metric value
1164 pair (newm, existm) with the cluster list length. Prefer the
1165 path with smaller cluster list length. */
1166 if (newm
== existm
) {
1167 if (peer_sort_lookup(peer_new
) == BGP_PEER_IBGP
&&
1168 peer_sort_lookup(peer_exist
) == BGP_PEER_IBGP
&&
1169 (mpath_cfg
== NULL
|| mpath_cfg
->same_clusterlen
)) {
1170 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1171 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1173 if (newm
< existm
) {
1174 if (debug
&& peer_sort_ret
< 0)
1176 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
1177 pfx_buf
, new_buf
, exist_buf
,
1182 if (newm
> existm
) {
1183 if (debug
&& peer_sort_ret
< 0)
1185 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
1186 pfx_buf
, new_buf
, exist_buf
,
1193 /* 10. confed-external vs. confed-internal */
1194 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1195 if (new_sort
== BGP_PEER_CONFED
1196 && exist_sort
== BGP_PEER_IBGP
) {
1197 *reason
= bgp_path_selection_confed
;
1200 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1201 pfx_buf
, new_buf
, exist_buf
);
1202 if (!CHECK_FLAG(bgp
->flags
,
1203 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1208 if (exist_sort
== BGP_PEER_CONFED
1209 && new_sort
== BGP_PEER_IBGP
) {
1210 *reason
= bgp_path_selection_confed
;
1213 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1214 pfx_buf
, new_buf
, exist_buf
);
1215 if (!CHECK_FLAG(bgp
->flags
,
1216 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1222 /* 11. Maximum path check. */
1223 if (newm
== existm
) {
1224 /* If one path has a label but the other does not, do not treat
1225 * them as equals for multipath
1232 newl
= new->extra
->num_labels
;
1234 existl
= exist
->extra
->num_labels
;
1235 if (((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0])) !=
1237 bgp_is_valid_label(&exist
->extra
->label
[0]))) ||
1241 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1242 pfx_buf
, new_buf
, exist_buf
);
1243 } else if (CHECK_FLAG(bgp
->flags
,
1244 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
1247 * For the two paths, all comparison steps till IGP
1249 * have succeeded - including AS_PATH hop count. Since
1251 * bestpath as-path multipath-relax' knob is on, we
1253 * an exact match of AS_PATH. Thus, mark the paths are
1255 * That will trigger both these paths to get into the
1263 "%s: %s and %s are equal via multipath-relax",
1264 pfx_buf
, new_buf
, exist_buf
);
1265 } else if (peer_new
->sort
== BGP_PEER_IBGP
) {
1266 if (aspath_cmp(new->attr
->aspath
,
1267 exist
->attr
->aspath
)) {
1272 "%s: %s and %s are equal via matching aspaths",
1273 pfx_buf
, new_buf
, exist_buf
);
1275 } else if (peer_new
->as
== peer_exist
->as
) {
1280 "%s: %s and %s are equal via same remote-as",
1281 pfx_buf
, new_buf
, exist_buf
);
1285 * TODO: If unequal cost ibgp multipath is enabled we can
1286 * mark the paths as equal here instead of returning
1289 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1290 * if either step 7 or 10 (peer type checks) yielded a winner,
1291 * that result was returned immediately. Returning from step 10
1292 * ignored the return value computed in steps 8 and 9 (IGP
1293 * metric checks). In order to preserve that behavior, if
1294 * peer_sort_ret is set, return that rather than igp_metric_ret.
1296 ret
= peer_sort_ret
;
1297 if (peer_sort_ret
< 0) {
1298 ret
= igp_metric_ret
;
1302 "%s: %s wins over %s after IGP metric comparison",
1303 pfx_buf
, new_buf
, exist_buf
);
1306 "%s: %s loses to %s after IGP metric comparison",
1307 pfx_buf
, new_buf
, exist_buf
);
1309 *reason
= bgp_path_selection_igp_metric
;
1315 * At this point, the decision whether to set *paths_eq = 1 has been
1316 * completed. If we deferred returning because of bestpath peer-type
1317 * relax configuration, return now.
1319 if (peer_sort_ret
>= 0)
1320 return peer_sort_ret
;
1322 /* 12. If both paths are external, prefer the path that was received
1323 first (the oldest one). This step minimizes route-flap, since a
1324 newer path won't displace an older one, even if it was the
1325 preferred route based on the additional decision criteria below. */
1326 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1327 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1328 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1329 *reason
= bgp_path_selection_older
;
1332 "%s: %s wins over %s due to oldest external",
1333 pfx_buf
, new_buf
, exist_buf
);
1337 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1338 *reason
= bgp_path_selection_older
;
1341 "%s: %s loses to %s due to oldest external",
1342 pfx_buf
, new_buf
, exist_buf
);
1347 /* 13. Router-ID comparison. */
1348 /* If one of the paths is "stale", the corresponding peer router-id will
1349 * be 0 and would always win over the other path. If originator id is
1350 * used for the comparison, it will decide which path is better.
1352 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1353 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1355 new_id
.s_addr
= peer_new
->remote_id
.s_addr
;
1356 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1357 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1359 exist_id
.s_addr
= peer_exist
->remote_id
.s_addr
;
1361 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1362 *reason
= bgp_path_selection_router_id
;
1365 "%s: %s wins over %s due to Router-ID comparison",
1366 pfx_buf
, new_buf
, exist_buf
);
1370 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1371 *reason
= bgp_path_selection_router_id
;
1374 "%s: %s loses to %s due to Router-ID comparison",
1375 pfx_buf
, new_buf
, exist_buf
);
1379 /* 14. Cluster length comparison. */
1380 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1381 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1383 if (new_cluster
< exist_cluster
) {
1384 *reason
= bgp_path_selection_cluster_length
;
1387 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1388 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1393 if (new_cluster
> exist_cluster
) {
1394 *reason
= bgp_path_selection_cluster_length
;
1397 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1398 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1403 /* 15. Neighbor address comparison. */
1404 /* Do this only if neither path is "stale" as stale paths do not have
1405 * valid peer information (as the connection may or may not be up).
1407 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1408 *reason
= bgp_path_selection_stale
;
1411 "%s: %s wins over %s due to latter path being STALE",
1412 pfx_buf
, new_buf
, exist_buf
);
1416 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1417 *reason
= bgp_path_selection_stale
;
1420 "%s: %s loses to %s due to former path being STALE",
1421 pfx_buf
, new_buf
, exist_buf
);
1425 /* locally configured routes to advertise do not have su_remote */
1426 if (peer_new
->su_remote
== NULL
) {
1427 *reason
= bgp_path_selection_local_configured
;
1431 if (peer_exist
->su_remote
== NULL
) {
1432 *reason
= bgp_path_selection_local_configured
;
1436 ret
= sockunion_cmp(peer_new
->su_remote
, peer_exist
->su_remote
);
1439 *reason
= bgp_path_selection_neighbor_ip
;
1442 "%s: %s loses to %s due to Neighor IP comparison",
1443 pfx_buf
, new_buf
, exist_buf
);
1448 *reason
= bgp_path_selection_neighbor_ip
;
1451 "%s: %s wins over %s due to Neighor IP comparison",
1452 pfx_buf
, new_buf
, exist_buf
);
1456 *reason
= bgp_path_selection_default
;
1458 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1459 pfx_buf
, new_buf
, exist_buf
);
1465 int bgp_evpn_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
1466 struct bgp_path_info
*exist
, int *paths_eq
)
1468 enum bgp_path_selection_reason reason
;
1469 char pfx_buf
[PREFIX2STR_BUFFER
];
1471 return bgp_path_info_cmp(bgp
, new, exist
, paths_eq
, NULL
, 0, pfx_buf
,
1472 AFI_L2VPN
, SAFI_EVPN
, &reason
);
1475 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1476 * is preferred, or 0 if they are the same (usually will only occur if
1477 * multipath is enabled
1478 * This version is compatible with */
1479 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1480 struct bgp_path_info
*exist
, char *pfx_buf
,
1481 afi_t afi
, safi_t safi
,
1482 enum bgp_path_selection_reason
*reason
)
1486 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1500 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1501 const struct prefix
*p
,
1502 struct attr
*attr
, afi_t afi
,
1505 struct bgp_filter
*filter
;
1506 enum filter_type ret
= FILTER_PERMIT
;
1508 filter
= &peer
->filter
[afi
][safi
];
1510 #define FILTER_EXIST_WARN(F, f, filter) \
1511 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1512 zlog_debug("%s: Could not find configured input %s-list %s!", \
1513 peer->host, #f, F##_IN_NAME(filter));
1515 if (DISTRIBUTE_IN_NAME(filter
)) {
1516 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1518 if (access_list_apply(DISTRIBUTE_IN(filter
), p
)
1525 if (PREFIX_LIST_IN_NAME(filter
)) {
1526 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1528 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
)
1535 if (FILTER_LIST_IN_NAME(filter
)) {
1536 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1538 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1539 == AS_FILTER_DENY
) {
1546 if (frrtrace_enabled(frr_bgp
, input_filter
)) {
1547 char pfxprint
[PREFIX2STR_BUFFER
];
1549 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1550 frrtrace(5, frr_bgp
, input_filter
, peer
, pfxprint
, afi
, safi
,
1551 ret
== FILTER_PERMIT
? "permit" : "deny");
1555 #undef FILTER_EXIST_WARN
1558 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1559 const struct prefix
*p
,
1560 struct attr
*attr
, afi_t afi
,
1563 struct bgp_filter
*filter
;
1564 enum filter_type ret
= FILTER_PERMIT
;
1566 filter
= &peer
->filter
[afi
][safi
];
1568 #define FILTER_EXIST_WARN(F, f, filter) \
1569 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1570 zlog_debug("%s: Could not find configured output %s-list %s!", \
1571 peer->host, #f, F##_OUT_NAME(filter));
1573 if (DISTRIBUTE_OUT_NAME(filter
)) {
1574 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1576 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
)
1583 if (PREFIX_LIST_OUT_NAME(filter
)) {
1584 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1586 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1593 if (FILTER_LIST_OUT_NAME(filter
)) {
1594 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1596 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1597 == AS_FILTER_DENY
) {
1603 if (frrtrace_enabled(frr_bgp
, output_filter
)) {
1604 char pfxprint
[PREFIX2STR_BUFFER
];
1606 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1607 frrtrace(5, frr_bgp
, output_filter
, peer
, pfxprint
, afi
, safi
,
1608 ret
== FILTER_PERMIT
? "permit" : "deny");
1613 #undef FILTER_EXIST_WARN
1616 /* If community attribute includes no_export then return 1. */
1617 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1619 if (bgp_attr_get_community(attr
)) {
1620 /* NO_ADVERTISE check. */
1621 if (community_include(bgp_attr_get_community(attr
),
1622 COMMUNITY_NO_ADVERTISE
))
1625 /* NO_EXPORT check. */
1626 if (peer
->sort
== BGP_PEER_EBGP
&&
1627 community_include(bgp_attr_get_community(attr
),
1628 COMMUNITY_NO_EXPORT
))
1631 /* NO_EXPORT_SUBCONFED check. */
1632 if (peer
->sort
== BGP_PEER_EBGP
1633 || peer
->sort
== BGP_PEER_CONFED
)
1634 if (community_include(bgp_attr_get_community(attr
),
1635 COMMUNITY_NO_EXPORT_SUBCONFED
))
1641 /* Route reflection loop check. */
1642 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1644 struct in_addr cluster_id
;
1645 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1648 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1649 cluster_id
= peer
->bgp
->cluster_id
;
1651 cluster_id
= peer
->bgp
->router_id
;
1653 if (cluster_loop_check(cluster
, cluster_id
))
1659 static bool bgp_otc_filter(struct peer
*peer
, struct attr
*attr
)
1661 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1662 if (peer
->local_role
== ROLE_PROVIDER
||
1663 peer
->local_role
== ROLE_RS_SERVER
)
1665 if (peer
->local_role
== ROLE_PEER
&& attr
->otc
!= peer
->as
)
1669 if (peer
->local_role
== ROLE_CUSTOMER
||
1670 peer
->local_role
== ROLE_PEER
||
1671 peer
->local_role
== ROLE_RS_CLIENT
) {
1672 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1673 attr
->otc
= peer
->as
;
1678 static bool bgp_otc_egress(struct peer
*peer
, struct attr
*attr
)
1680 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1681 if (peer
->local_role
== ROLE_CUSTOMER
||
1682 peer
->local_role
== ROLE_RS_CLIENT
||
1683 peer
->local_role
== ROLE_PEER
)
1687 if (peer
->local_role
== ROLE_PROVIDER
||
1688 peer
->local_role
== ROLE_PEER
||
1689 peer
->local_role
== ROLE_RS_SERVER
) {
1690 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1691 attr
->otc
= peer
->bgp
->as
;
1696 static bool bgp_check_role_applicability(afi_t afi
, safi_t safi
)
1698 return ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_UNICAST
);
1701 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1702 struct attr
*attr
, afi_t afi
, safi_t safi
,
1703 const char *rmap_name
, mpls_label_t
*label
,
1704 uint32_t num_labels
, struct bgp_dest
*dest
)
1706 struct bgp_filter
*filter
;
1707 struct bgp_path_info rmap_path
= { 0 };
1708 struct bgp_path_info_extra extra
= { 0 };
1709 route_map_result_t ret
;
1710 struct route_map
*rmap
= NULL
;
1712 filter
= &peer
->filter
[afi
][safi
];
1714 /* Apply default weight value. */
1715 if (peer
->weight
[afi
][safi
])
1716 attr
->weight
= peer
->weight
[afi
][safi
];
1719 rmap
= route_map_lookup_by_name(rmap_name
);
1724 if (ROUTE_MAP_IN_NAME(filter
)) {
1725 rmap
= ROUTE_MAP_IN(filter
);
1732 /* Route map apply. */
1734 memset(&rmap_path
, 0, sizeof(rmap_path
));
1735 /* Duplicate current value to new structure for modification. */
1736 rmap_path
.peer
= peer
;
1737 rmap_path
.attr
= attr
;
1738 rmap_path
.extra
= &extra
;
1739 rmap_path
.net
= dest
;
1741 extra
.num_labels
= num_labels
;
1742 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1743 memcpy(extra
.label
, label
,
1744 num_labels
* sizeof(mpls_label_t
));
1746 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1748 /* Apply BGP route map to the attribute. */
1749 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1751 peer
->rmap_type
= 0;
1753 if (ret
== RMAP_DENYMATCH
)
1759 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1760 struct attr
*attr
, afi_t afi
, safi_t safi
,
1761 const char *rmap_name
)
1763 struct bgp_path_info rmap_path
;
1764 route_map_result_t ret
;
1765 struct route_map
*rmap
= NULL
;
1769 * So if we get to this point and have no rmap_name
1770 * we want to just show the output as it currently
1776 /* Apply default weight value. */
1777 if (peer
->weight
[afi
][safi
])
1778 attr
->weight
= peer
->weight
[afi
][safi
];
1780 rmap
= route_map_lookup_by_name(rmap_name
);
1783 * If we have a route map name and we do not find
1784 * the routemap that means we have an implicit
1790 memset(&rmap_path
, 0, sizeof(rmap_path
));
1791 /* Route map apply. */
1792 /* Duplicate current value to new structure for modification. */
1793 rmap_path
.peer
= peer
;
1794 rmap_path
.attr
= attr
;
1796 rmap_type
= peer
->rmap_type
;
1797 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1799 /* Apply BGP route map to the attribute. */
1800 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1802 peer
->rmap_type
= rmap_type
;
1804 if (ret
== RMAP_DENYMATCH
)
1806 * caller has multiple error paths with bgp_attr_flush()
1813 /* If this is an EBGP peer with remove-private-AS */
1814 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1815 struct peer
*peer
, struct attr
*attr
)
1817 if (peer
->sort
== BGP_PEER_EBGP
1818 && (peer_af_flag_check(peer
, afi
, safi
,
1819 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1820 || peer_af_flag_check(peer
, afi
, safi
,
1821 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1822 || peer_af_flag_check(peer
, afi
, safi
,
1823 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1824 || peer_af_flag_check(peer
, afi
, safi
,
1825 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1826 // Take action on the entire aspath
1827 if (peer_af_flag_check(peer
, afi
, safi
,
1828 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1829 || peer_af_flag_check(peer
, afi
, safi
,
1830 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1831 if (peer_af_flag_check(
1833 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1834 attr
->aspath
= aspath_replace_private_asns(
1835 attr
->aspath
, bgp
->as
, peer
->as
);
1838 * Even if the aspath consists of just private ASNs we
1839 * need to walk the AS-Path to maintain all instances
1840 * of the peer's ASN to break possible loops.
1843 attr
->aspath
= aspath_remove_private_asns(
1844 attr
->aspath
, peer
->as
);
1847 // 'all' was not specified so the entire aspath must be private
1849 // for us to do anything
1850 else if (aspath_private_as_check(attr
->aspath
)) {
1851 if (peer_af_flag_check(
1853 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1854 attr
->aspath
= aspath_replace_private_asns(
1855 attr
->aspath
, bgp
->as
, peer
->as
);
1858 * Walk the aspath to retain any instances of
1861 attr
->aspath
= aspath_remove_private_asns(
1862 attr
->aspath
, peer
->as
);
1867 /* If this is an EBGP peer with as-override */
1868 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1869 struct peer
*peer
, struct attr
*attr
)
1871 struct aspath
*aspath
;
1873 if (peer
->sort
== BGP_PEER_EBGP
&&
1874 peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1875 if (attr
->aspath
->refcnt
)
1876 aspath
= aspath_dup(attr
->aspath
);
1878 aspath
= attr
->aspath
;
1880 attr
->aspath
= aspath_intern(
1881 aspath_replace_specific_asn(aspath
, peer
->as
, bgp
->as
));
1883 aspath_free(aspath
);
1887 void bgp_attr_add_llgr_community(struct attr
*attr
)
1889 struct community
*old
;
1890 struct community
*new;
1891 struct community
*merge
;
1892 struct community
*llgr
;
1894 old
= bgp_attr_get_community(attr
);
1895 llgr
= community_str2com("llgr-stale");
1900 merge
= community_merge(community_dup(old
), llgr
);
1902 if (old
->refcnt
== 0)
1903 community_free(&old
);
1905 new = community_uniq_sort(merge
);
1906 community_free(&merge
);
1908 new = community_dup(llgr
);
1911 community_free(&llgr
);
1913 bgp_attr_set_community(attr
, new);
1916 void bgp_attr_add_gshut_community(struct attr
*attr
)
1918 struct community
*old
;
1919 struct community
*new;
1920 struct community
*merge
;
1921 struct community
*gshut
;
1923 old
= bgp_attr_get_community(attr
);
1924 gshut
= community_str2com("graceful-shutdown");
1929 merge
= community_merge(community_dup(old
), gshut
);
1931 if (old
->refcnt
== 0)
1932 community_free(&old
);
1934 new = community_uniq_sort(merge
);
1935 community_free(&merge
);
1937 new = community_dup(gshut
);
1940 community_free(&gshut
);
1941 bgp_attr_set_community(attr
, new);
1943 /* When we add the graceful-shutdown community we must also
1944 * lower the local-preference */
1945 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1946 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1950 /* Notify BGP Conditional advertisement scanner process. */
1951 void bgp_notify_conditional_adv_scanner(struct update_subgroup
*subgrp
)
1953 struct peer
*peer
= SUBGRP_PEER(subgrp
);
1954 afi_t afi
= SUBGRP_AFI(subgrp
);
1955 safi_t safi
= SUBGRP_SAFI(subgrp
);
1956 struct bgp_filter
*filter
= &peer
->filter
[afi
][safi
];
1958 if (!ADVERTISE_MAP_NAME(filter
))
1961 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
))
1964 peer
->advmap_table_change
= true;
1968 void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1970 if (family
== AF_INET
) {
1971 attr
->nexthop
.s_addr
= INADDR_ANY
;
1972 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1974 if (family
== AF_INET6
)
1975 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1976 if (family
== AF_EVPN
)
1977 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1980 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
1981 struct update_subgroup
*subgrp
,
1982 const struct prefix
*p
, struct attr
*attr
,
1983 struct attr
*post_attr
)
1985 struct bgp_filter
*filter
;
1988 struct peer
*onlypeer
;
1990 struct attr
*piattr
;
1991 route_map_result_t ret
;
1996 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1997 bool nh_reset
= false;
2000 if (DISABLE_BGP_ANNOUNCE
)
2003 afi
= SUBGRP_AFI(subgrp
);
2004 safi
= SUBGRP_SAFI(subgrp
);
2005 peer
= SUBGRP_PEER(subgrp
);
2007 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
2008 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
2011 filter
= &peer
->filter
[afi
][safi
];
2012 bgp
= SUBGRP_INST(subgrp
);
2013 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
2016 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX_OUT
) &&
2017 peer
->pmax_out
[afi
][safi
] != 0 &&
2018 subgrp
->pscount
>= peer
->pmax_out
[afi
][safi
]) {
2019 if (BGP_DEBUG(update
, UPDATE_OUT
) ||
2020 BGP_DEBUG(update
, UPDATE_PREFIX
)) {
2021 zlog_debug("%s reached maximum prefix to be send (%u)",
2022 peer
->host
, peer
->pmax_out
[afi
][safi
]);
2027 #ifdef ENABLE_BGP_VNC
2028 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
2029 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
2030 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
2033 * direct and direct_ext type routes originate internally even
2034 * though they can have peer pointers that reference other
2037 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
2043 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
2044 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
2045 && (pi
->type
== ZEBRA_ROUTE_BGP
)
2046 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2048 /* Applies to routes leaked vpn->vrf and vrf->vpn */
2053 /* With addpath we may be asked to TX all kinds of paths so make sure
2055 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
2056 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
2057 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
2061 /* If this is not the bestpath then check to see if there is an enabled
2063 * feature that requires us to advertise it */
2064 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2065 if (!bgp_addpath_capable(pi
, peer
, afi
, safi
))
2068 /* Aggregate-address suppress check. */
2069 if (bgp_path_suppressed(pi
) && !UNSUPPRESS_MAP_NAME(filter
))
2073 * If we are doing VRF 2 VRF leaking via the import
2074 * statement, we want to prevent the route going
2075 * off box as that the RT and RD created are localy
2076 * significant and globaly useless.
2078 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
2079 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
2082 /* If it's labeled safi, make sure the route has a valid label. */
2083 if (safi
== SAFI_LABELED_UNICAST
) {
2084 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
2085 if (!bgp_is_valid_label(&label
)) {
2086 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2087 zlog_debug("u%" PRIu64
":s%" PRIu64
2088 " %pFX is filtered - no label (%p)",
2089 subgrp
->update_group
->id
, subgrp
->id
,
2095 /* Do not send back route to sender. */
2096 if (onlypeer
&& from
== onlypeer
) {
2100 /* Do not send the default route in the BGP table if the neighbor is
2101 * configured for default-originate */
2102 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2103 PEER_FLAG_DEFAULT_ORIGINATE
)) {
2104 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
2106 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
2110 /* Transparency check. */
2111 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
2112 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
2117 /* If community is not disabled check the no-export and local. */
2118 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
2119 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2120 zlog_debug("%s: community filter check fail for %pFX",
2125 /* If the attribute has originator-id and it is same as remote
2127 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2128 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
2129 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2131 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2136 /* ORF prefix-list filter check */
2137 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
2138 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
2139 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
2140 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
2141 if (peer
->orf_plist
[afi
][safi
]) {
2142 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
2144 if (bgp_debug_update(NULL
, p
,
2145 subgrp
->update_group
, 0))
2147 "%pBP [Update:SEND] %pFX is filtered via ORF",
2153 /* Output filter check. */
2154 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
2155 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2156 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer
,
2161 /* AS path loop check. */
2162 if (peer
->as_path_loop_detection
&&
2163 aspath_loop_check(piattr
->aspath
, peer
->as
)) {
2164 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2166 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2171 /* If we're a CONFED we need to loop check the CONFED ID too */
2172 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
2173 if (aspath_loop_check_confed(piattr
->aspath
, bgp
->confed_id
)) {
2174 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2176 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2177 peer
, bgp
->confed_id
);
2182 /* Route-Reflect check. */
2183 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2188 /* IBGP reflection check. */
2189 if (reflect
&& !samepeer_safe
) {
2190 /* A route from a Client peer. */
2191 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
2192 PEER_FLAG_REFLECTOR_CLIENT
)) {
2193 /* Reflect to all the Non-Client peers and also to the
2194 Client peers other than the originator. Originator
2196 is already done. So there is noting to do. */
2197 /* no bgp client-to-client reflection check. */
2198 if (CHECK_FLAG(bgp
->flags
,
2199 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
2200 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2201 PEER_FLAG_REFLECTOR_CLIENT
))
2204 /* A route from a Non-client peer. Reflect to all other
2206 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2207 PEER_FLAG_REFLECTOR_CLIENT
))
2212 /* For modify attribute, copy it to temporary structure.
2213 * post_attr comes from BGP conditional advertisements, where
2214 * attributes are already processed by advertise-map route-map,
2215 * and this needs to be saved instead of overwriting from the
2223 /* If local-preference is not set. */
2224 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
2225 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
2226 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2227 attr
->local_pref
= bgp
->default_local_pref
;
2230 /* If originator-id is not set and the route is to be reflected,
2231 set the originator id */
2233 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
2234 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
2235 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
2238 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2240 if (peer
->sort
== BGP_PEER_EBGP
2241 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
2242 if (from
!= bgp
->peer_self
&& !transparent
2243 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2244 PEER_FLAG_MED_UNCHANGED
))
2246 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
2249 /* Since the nexthop attribute can vary per peer, it is not explicitly
2251 * in announce check, only certain flags and length (or number of
2253 * -- for IPv6/MP_REACH) are set here in order to guide the update
2255 * code in setting the nexthop(s) on a per peer basis in
2257 * Typically, the source nexthop in the attribute is preserved but in
2259 * scenarios where we know it will always be overwritten, we reset the
2260 * nexthop to "0" in an attempt to achieve better Update packing. An
2261 * example of this is when a prefix from each of 2 IBGP peers needs to
2263 * announced to an EBGP peer (and they have the same attributes barring
2267 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
2269 #define NEXTHOP_IS_V6 \
2270 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2271 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2272 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2273 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2275 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2277 * the peer (group) is configured to receive link-local nexthop
2279 * and it is available in the prefix OR we're not reflecting the route,
2280 * link-local nexthop address is valid and
2281 * the peer (group) to whom we're going to announce is on a shared
2283 * and this is either a self-originated route or the peer is EBGP.
2284 * By checking if nexthop LL address is valid we are sure that
2285 * we do not announce LL address as `::`.
2287 if (NEXTHOP_IS_V6
) {
2288 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2289 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2290 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
2291 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
2292 || (!reflect
&& !transparent
2293 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
2294 && peer
->shared_network
2295 && (from
== bgp
->peer_self
2296 || peer
->sort
== BGP_PEER_EBGP
))) {
2297 if (safi
== SAFI_MPLS_VPN
)
2298 attr
->mp_nexthop_len
=
2299 BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
;
2301 attr
->mp_nexthop_len
=
2302 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2305 /* Clear off link-local nexthop in source, whenever it is not
2307 * ensure more prefixes share the same attribute for
2310 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2311 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
2312 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
2315 if (bgp_check_role_applicability(afi
, safi
) &&
2316 bgp_otc_egress(peer
, attr
))
2319 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
2320 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
2322 if (filter
->advmap
.update_type
== UPDATE_TYPE_WITHDRAW
&&
2323 filter
->advmap
.aname
&&
2324 route_map_lookup_by_name(filter
->advmap
.aname
)) {
2325 struct bgp_path_info rmap_path
= {0};
2326 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2327 struct attr dummy_attr
= *attr
;
2329 /* Fill temp path_info */
2330 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2331 pi
, peer
, &dummy_attr
);
2333 struct route_map
*amap
=
2334 route_map_lookup_by_name(filter
->advmap
.aname
);
2336 ret
= route_map_apply(amap
, p
, &rmap_path
);
2338 bgp_attr_flush(&dummy_attr
);
2341 * The conditional advertisement mode is Withdraw and this
2342 * prefix is a conditional prefix. Don't advertise it
2344 if (ret
== RMAP_PERMITMATCH
)
2348 /* Route map & unsuppress-map apply. */
2350 (ROUTE_MAP_OUT_NAME(filter
) || bgp_path_suppressed(pi
))) {
2351 struct bgp_path_info rmap_path
= {0};
2352 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2353 struct attr dummy_attr
= {0};
2355 /* Fill temp path_info */
2356 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2359 /* don't confuse inbound and outbound setting */
2360 RESET_FLAG(attr
->rmap_change_flags
);
2363 * The route reflector is not allowed to modify the attributes
2364 * of the reflected IBGP routes unless explicitly allowed.
2366 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2367 && !CHECK_FLAG(bgp
->flags
,
2368 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
2370 rmap_path
.attr
= &dummy_attr
;
2373 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
2375 if (bgp_path_suppressed(pi
))
2376 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
2379 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
2382 bgp_attr_flush(&dummy_attr
);
2383 peer
->rmap_type
= 0;
2385 if (ret
== RMAP_DENYMATCH
) {
2386 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2388 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2390 bgp_path_suppressed(pi
)
2391 ? UNSUPPRESS_MAP_NAME(filter
)
2392 : ROUTE_MAP_OUT_NAME(filter
));
2393 bgp_attr_flush(rmap_path
.attr
);
2398 /* RFC 8212 to prevent route leaks.
2399 * This specification intends to improve this situation by requiring the
2400 * explicit configuration of both BGP Import and Export Policies for any
2401 * External BGP (EBGP) session such as customers, peers, or
2402 * confederation boundaries for all enabled address families. Through
2403 * codification of the aforementioned requirement, operators will
2404 * benefit from consistent behavior across different BGP
2407 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2408 if (!bgp_outbound_policy_exists(peer
, filter
)) {
2409 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
2410 NULL
) > FIFTEENMINUTE2USEC
||
2411 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
2413 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2414 monotime(&bgp
->ebgprequirespolicywarning
);
2419 /* draft-ietf-idr-deprecate-as-set-confed-set
2420 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2421 * Eventually, This document (if approved) updates RFC 4271
2422 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2423 * and obsoletes RFC 6472.
2425 if (peer
->bgp
->reject_as_sets
)
2426 if (aspath_check_as_sets(attr
->aspath
))
2429 /* If neighbor soo is configured, then check if the route has
2430 * SoO extended community and validate against the configured
2431 * one. If they match, do not announce, to prevent routing
2434 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) &&
2435 peer
->soo
[afi
][safi
]) {
2436 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
2437 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
2439 if ((ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS
,
2440 ECOMMUNITY_SITE_ORIGIN
) ||
2441 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS4
,
2442 ECOMMUNITY_SITE_ORIGIN
) ||
2443 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_IP
,
2444 ECOMMUNITY_SITE_ORIGIN
)) &&
2445 ecommunity_include(ecomm
, ecomm_soo
)) {
2446 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2448 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2449 peer
, p
, ecommunity_str(ecomm_soo
));
2454 /* Codification of AS 0 Processing */
2455 if (aspath_check_as_zero(attr
->aspath
))
2458 if (bgp_in_graceful_shutdown(bgp
)) {
2459 if (peer
->sort
== BGP_PEER_IBGP
2460 || peer
->sort
== BGP_PEER_CONFED
) {
2461 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2462 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2464 bgp_attr_add_gshut_community(attr
);
2468 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2469 * Capability" to a neighbor MUST perform the following upon receiving
2470 * a route from that neighbor with the "LLGR_STALE" community, or upon
2471 * attaching the "LLGR_STALE" community itself per Section 4.2:
2473 * The route SHOULD NOT be advertised to any neighbor from which the
2474 * Long-lived Graceful Restart Capability has not been received.
2476 if (bgp_attr_get_community(attr
) &&
2477 community_include(bgp_attr_get_community(attr
),
2478 COMMUNITY_LLGR_STALE
) &&
2479 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_RCV
) &&
2480 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_ADV
))
2483 /* After route-map has been applied, we check to see if the nexthop to
2484 * be carried in the attribute (that is used for the announcement) can
2485 * be cleared off or not. We do this in all cases where we would be
2486 * setting the nexthop to "ourselves". For IPv6, we only need to
2488 * the global nexthop here; the link-local nexthop would have been
2490 * already, and if not, it is required by the update formation code.
2491 * Also see earlier comments in this function.
2494 * If route-map has performed some operation on the nexthop or the peer
2495 * configuration says to pass it unchanged, we cannot reset the nexthop
2496 * here, so only attempt to do it if these aren't true. Note that the
2497 * route-map handler itself might have cleared the nexthop, if for
2499 * it is configured as 'peer-address'.
2501 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2502 piattr
->rmap_change_flags
)
2504 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2505 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2506 /* We can reset the nexthop, if setting (or forcing) it to
2508 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2509 PEER_FLAG_NEXTHOP_SELF
)
2510 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2511 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2513 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2514 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2515 subgroup_announce_reset_nhop(
2516 (peer_cap_enhe(peer
, afi
, safi
)
2522 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2523 /* Can also reset the nexthop if announcing to EBGP, but
2525 * no peer in the subgroup is on a shared subnet.
2526 * Note: 3rd party nexthop currently implemented for
2529 if ((p
->family
== AF_INET
) &&
2530 (!bgp_subgrp_multiaccess_check_v4(
2533 subgroup_announce_reset_nhop(
2534 (peer_cap_enhe(peer
, afi
, safi
)
2541 if ((p
->family
== AF_INET6
) &&
2542 (!bgp_subgrp_multiaccess_check_v6(
2543 piattr
->mp_nexthop_global
,
2545 subgroup_announce_reset_nhop(
2546 (peer_cap_enhe(peer
, afi
, safi
)
2555 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2557 * This flag is used for leaked vpn-vrf routes
2559 int family
= p
->family
;
2561 if (peer_cap_enhe(peer
, afi
, safi
))
2564 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2566 "%s: %pFX BGP_PATH_ANNC_NH_SELF, family=%s",
2567 __func__
, p
, family2str(family
));
2568 subgroup_announce_reset_nhop(family
, attr
);
2573 /* If IPv6/MP and nexthop does not have any override and happens
2575 * be a link-local address, reset it so that we don't pass along
2577 * source's link-local IPv6 address to recipients who may not be
2579 * the same interface.
2581 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2582 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2583 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2588 /* If this is an iBGP, send Origin Validation State (OVS)
2589 * extended community (rfc8097).
2591 if (peer
->sort
== BGP_PEER_IBGP
) {
2592 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
2594 rpki_state
= hook_call(bgp_rpki_prefix_status
, peer
, attr
, p
);
2596 if (rpki_state
!= RPKI_NOT_BEING_USED
)
2597 bgp_attr_set_ecommunity(
2598 attr
, ecommunity_add_origin_validation_state(
2600 bgp_attr_get_ecommunity(attr
)));
2604 * When the next hop is set to ourselves, if all multipaths have
2605 * link-bandwidth announce the cumulative bandwidth as that makes
2606 * the most sense. However, don't modify if the link-bandwidth has
2607 * been explicitly set by user policy.
2610 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2611 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2612 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2613 bgp_attr_set_ecommunity(
2615 ecommunity_replace_linkbw(
2616 bgp
->as
, bgp_attr_get_ecommunity(attr
), cum_bw
,
2619 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
)));
2624 static void bgp_route_select_timer_expire(struct event
*thread
)
2626 struct afi_safi_info
*info
;
2631 info
= EVENT_ARG(thread
);
2636 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2637 XFREE(MTYPE_TMP
, info
);
2639 /* Best path selection */
2640 bgp_best_path_select_defer(bgp
, afi
, safi
);
2643 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2644 struct bgp_maxpaths_cfg
*mpath_cfg
,
2645 struct bgp_path_info_pair
*result
, afi_t afi
,
2648 struct bgp_path_info
*new_select
;
2649 struct bgp_path_info
*old_select
;
2650 struct bgp_path_info
*pi
;
2651 struct bgp_path_info
*pi1
;
2652 struct bgp_path_info
*pi2
;
2653 struct bgp_path_info
*nextpi
= NULL
;
2654 int paths_eq
, do_mpath
, debug
;
2655 struct list mp_list
;
2656 char pfx_buf
[PREFIX2STR_BUFFER
];
2657 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2659 bgp_mp_list_init(&mp_list
);
2661 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2663 debug
= bgp_debug_bestpath(dest
);
2666 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2668 dest
->reason
= bgp_path_selection_none
;
2669 /* bgp deterministic-med */
2671 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2673 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2674 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2676 bgp_path_info_unset_flag(dest
, pi1
,
2677 BGP_PATH_DMED_SELECTED
);
2679 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2681 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2683 if (BGP_PATH_HOLDDOWN(pi1
))
2685 if (pi1
->peer
!= bgp
->peer_self
&&
2686 !CHECK_FLAG(pi1
->peer
->sflags
,
2687 PEER_STATUS_NSF_WAIT
)) {
2688 if (!peer_established(pi1
->peer
))
2694 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2695 if (CHECK_FLAG(pi2
->flags
,
2696 BGP_PATH_DMED_CHECK
))
2698 if (BGP_PATH_HOLDDOWN(pi2
))
2700 if (pi2
->peer
!= bgp
->peer_self
2703 PEER_STATUS_NSF_WAIT
))
2704 if (pi2
->peer
->status
2708 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2710 && !aspath_cmp_left_confed(
2715 if (bgp_path_info_cmp(
2716 bgp
, pi2
, new_select
,
2717 &paths_eq
, mpath_cfg
, debug
,
2720 bgp_path_info_unset_flag(
2722 BGP_PATH_DMED_SELECTED
);
2726 bgp_path_info_set_flag(
2727 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2730 bgp_path_info_set_flag(dest
, new_select
,
2731 BGP_PATH_DMED_CHECK
);
2732 bgp_path_info_set_flag(dest
, new_select
,
2733 BGP_PATH_DMED_SELECTED
);
2736 bgp_path_info_path_with_addpath_rx_str(
2737 new_select
, path_buf
, sizeof(path_buf
));
2739 "%pBD(%s): %s is the bestpath from AS %u",
2740 dest
, bgp
->name_pretty
, path_buf
,
2741 aspath_get_first_as(
2742 new_select
->attr
->aspath
));
2747 /* Check old selected route and new selected route. */
2750 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2751 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2752 enum bgp_path_selection_reason reason
;
2754 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2757 if (BGP_PATH_HOLDDOWN(pi
)) {
2758 /* reap REMOVED routes, if needs be
2759 * selected route must stay for a while longer though
2761 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2762 && (pi
!= old_select
))
2763 bgp_path_info_reap(dest
, pi
);
2767 "%s: %pBD(%s) pi from %s in holddown",
2768 __func__
, dest
, bgp
->name_pretty
,
2774 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2775 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2776 if (!peer_established(pi
->peer
)) {
2780 "%s: %pBD(%s) non self peer %s not estab state",
2788 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2789 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2790 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2792 zlog_debug("%s: %pBD(%s) pi %s dmed", __func__
,
2793 dest
, bgp
->name_pretty
,
2798 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2800 reason
= dest
->reason
;
2801 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2802 debug
, pfx_buf
, afi
, safi
,
2804 if (new_select
== NULL
&&
2805 reason
!= bgp_path_selection_none
)
2806 dest
->reason
= reason
;
2811 /* Now that we know which path is the bestpath see if any of the other
2813 * qualify as multipaths
2817 bgp_path_info_path_with_addpath_rx_str(
2818 new_select
, path_buf
, sizeof(path_buf
));
2820 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2822 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2823 dest
, bgp
->name_pretty
, path_buf
,
2824 old_select
? old_select
->peer
->host
: "NONE");
2827 if (do_mpath
&& new_select
) {
2828 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2829 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2832 bgp_path_info_path_with_addpath_rx_str(
2833 pi
, path_buf
, sizeof(path_buf
));
2835 if (pi
== new_select
) {
2838 "%pBD(%s): %s is the bestpath, add to the multipath list",
2839 dest
, bgp
->name_pretty
,
2841 bgp_mp_list_add(&mp_list
, pi
);
2845 if (BGP_PATH_HOLDDOWN(pi
))
2848 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2849 && !CHECK_FLAG(pi
->peer
->sflags
,
2850 PEER_STATUS_NSF_WAIT
))
2851 if (!peer_established(pi
->peer
))
2854 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2857 "%pBD(%s): %s has the same nexthop as the bestpath, skip it",
2858 dest
, bgp
->name_pretty
,
2863 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2864 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2870 "%pBD(%s): %s is equivalent to the bestpath, add to the multipath list",
2871 dest
, bgp
->name_pretty
,
2873 bgp_mp_list_add(&mp_list
, pi
);
2878 bgp_path_info_mpath_update(bgp
, dest
, new_select
, old_select
, &mp_list
,
2880 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2881 bgp_mp_list_clear(&mp_list
);
2883 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2885 result
->old
= old_select
;
2886 result
->new = new_select
;
2892 * A new route/change in bestpath of an existing route. Evaluate the path
2893 * for advertisement to the subgroup.
2895 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2896 struct bgp_path_info
*selected
,
2897 struct bgp_dest
*dest
,
2898 uint32_t addpath_tx_id
)
2900 const struct prefix
*p
;
2901 struct peer
*onlypeer
;
2908 p
= bgp_dest_get_prefix(dest
);
2909 afi
= SUBGRP_AFI(subgrp
);
2910 safi
= SUBGRP_SAFI(subgrp
);
2911 bgp
= SUBGRP_INST(subgrp
);
2912 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2915 if (BGP_DEBUG(update
, UPDATE_OUT
))
2916 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2918 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2919 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2920 PEER_STATUS_ORF_WAIT_REFRESH
))
2923 memset(&attr
, 0, sizeof(attr
));
2924 /* It's initialized in bgp_announce_check() */
2926 /* Announcement to the subgroup. If the route is filtered withdraw it.
2927 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2928 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2931 advertise
= bgp_check_advertise(bgp
, dest
);
2934 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2936 /* Route is selected, if the route is already installed
2937 * in FIB, then it is advertised
2940 if (!bgp_check_withdrawal(bgp
, dest
)) {
2941 struct attr
*adv_attr
=
2942 bgp_attr_intern(&attr
);
2944 bgp_adj_out_set_subgroup(dest
, subgrp
,
2948 bgp_adj_out_unset_subgroup(
2949 dest
, subgrp
, 1, addpath_tx_id
);
2952 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2956 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2958 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2963 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2964 * This is called at the end of route processing.
2966 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2968 struct bgp_path_info
*pi
;
2970 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2971 if (BGP_PATH_HOLDDOWN(pi
))
2973 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2974 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2979 * Has the route changed from the RIB's perspective? This is invoked only
2980 * if the route selection returns the same best route as earlier - to
2981 * determine if we need to update zebra or not.
2983 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2985 struct bgp_path_info
*mpinfo
;
2987 /* If this is multipath, check all selected paths for any nexthop
2988 * change or attribute change. Some attribute changes (e.g., community)
2989 * aren't of relevance to the RIB, but we'll update zebra to ensure
2990 * we handle the case of BGP nexthop change. This is the behavior
2991 * when the best path has an attribute change anyway.
2993 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2994 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2995 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2999 * If this is multipath, check all selected paths for any nexthop change
3001 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
3002 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
3003 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
3004 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
3008 /* Nothing has changed from the RIB's perspective. */
3012 struct bgp_process_queue
{
3014 STAILQ_HEAD(, bgp_dest
) pqueue
;
3015 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
3017 unsigned int queued
;
3020 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
3021 safi_t safi
, struct bgp_dest
*dest
,
3022 struct bgp_path_info
*new_select
,
3023 struct bgp_path_info
*old_select
)
3025 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3027 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
3030 if (advertise_type5_routes(bgp
, afi
) && new_select
3031 && is_route_injectable_into_evpn(new_select
)) {
3033 /* apply the route-map */
3034 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
3035 route_map_result_t ret
;
3036 struct bgp_path_info rmap_path
;
3037 struct bgp_path_info_extra rmap_path_extra
;
3038 struct attr dummy_attr
;
3040 dummy_attr
= *new_select
->attr
;
3042 /* Fill temp path_info */
3043 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
3044 new_select
, new_select
->peer
,
3047 RESET_FLAG(dummy_attr
.rmap_change_flags
);
3049 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
3052 if (ret
== RMAP_DENYMATCH
) {
3053 bgp_attr_flush(&dummy_attr
);
3054 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
3057 bgp_evpn_advertise_type5_route(
3058 bgp
, p
, &dummy_attr
, afi
, safi
);
3060 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
3063 } else if (advertise_type5_routes(bgp
, afi
) && old_select
3064 && is_route_injectable_into_evpn(old_select
))
3065 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
3069 * Utility to determine whether a particular path_info should use
3070 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3071 * in a path where we basically _know_ this is a BGP-LU route.
3073 static bool bgp_lu_need_imp_null(const struct bgp_path_info
*new_select
)
3075 /* Certain types get imp null; so do paths where the nexthop is
3078 if (new_select
->sub_type
== BGP_ROUTE_STATIC
3079 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3080 || new_select
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
3082 else if (new_select
->extra
== NULL
||
3083 !bgp_is_valid_label(&new_select
->extra
->label
[0]))
3084 /* TODO -- should be configurable? */
3091 * old_select = The old best path
3092 * new_select = the new best path
3094 * if (!old_select && new_select)
3095 * We are sending new information on.
3097 * if (old_select && new_select) {
3098 * if (new_select != old_select)
3099 * We have a new best path send a change
3101 * We've received a update with new attributes that needs
3105 * if (old_select && !new_select)
3106 * We have no eligible route that we can announce or the rn
3109 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
3110 afi_t afi
, safi_t safi
)
3112 struct bgp_path_info
*new_select
;
3113 struct bgp_path_info
*old_select
;
3114 struct bgp_path_info_pair old_and_new
;
3117 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
3119 debug
= bgp_debug_bestpath(dest
);
3122 "%s: bgp delete in progress, ignoring event, p=%pBD(%s)",
3123 __func__
, dest
, bgp
->name_pretty
);
3126 /* Is it end of initial update? (after startup) */
3128 frr_timestamp(3, bgp
->update_delay_zebra_resume_time
,
3129 sizeof(bgp
->update_delay_zebra_resume_time
));
3131 bgp
->main_zebra_update_hold
= 0;
3132 FOREACH_AFI_SAFI (afi
, safi
) {
3133 if (bgp_fibupd_safi(safi
))
3134 bgp_zebra_announce_table(bgp
, afi
, safi
);
3136 bgp
->main_peers_update_hold
= 0;
3138 bgp_start_routeadv(bgp
);
3142 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3144 debug
= bgp_debug_bestpath(dest
);
3146 zlog_debug("%s: p=%pBD(%s) afi=%s, safi=%s start", __func__
,
3147 dest
, bgp
->name_pretty
, afi2str(afi
),
3150 /* The best path calculation for the route is deferred if
3151 * BGP_NODE_SELECT_DEFER is set
3153 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3154 if (BGP_DEBUG(update
, UPDATE_OUT
))
3155 zlog_debug("SELECT_DEFER flag set for route %p(%s)",
3156 dest
, bgp
->name_pretty
);
3160 /* Best path selection. */
3161 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
3163 old_select
= old_and_new
.old
;
3164 new_select
= old_and_new
.new;
3166 /* Do we need to allocate or free labels?
3167 * Right now, since we only deal with per-prefix labels, it is not
3168 * necessary to do this upon changes to best path. Exceptions:
3169 * - label index has changed -> recalculate resulting label
3170 * - path_info sub_type changed -> switch to/from implicit-null
3171 * - no valid label (due to removed static label binding) -> get new one
3173 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
3176 || bgp_label_index_differs(new_select
, old_select
)
3177 || new_select
->sub_type
!= old_select
->sub_type
3178 || !bgp_is_valid_label(&dest
->local_label
)) {
3179 /* Enforced penultimate hop popping:
3180 * implicit-null for local routes, aggregate
3181 * and redistributed routes
3183 if (bgp_lu_need_imp_null(new_select
)) {
3186 BGP_NODE_REGISTERED_FOR_LABEL
)
3189 BGP_NODE_LABEL_REQUESTED
))
3190 bgp_unregister_for_label(dest
);
3191 dest
->local_label
= mpls_lse_encode(
3192 MPLS_LABEL_IMPLICIT_NULL
, 0, 0,
3194 bgp_set_valid_label(&dest
->local_label
);
3196 bgp_register_for_label(dest
,
3199 } else if (CHECK_FLAG(dest
->flags
,
3200 BGP_NODE_REGISTERED_FOR_LABEL
)
3201 || CHECK_FLAG(dest
->flags
,
3202 BGP_NODE_LABEL_REQUESTED
)) {
3203 bgp_unregister_for_label(dest
);
3205 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
3206 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
3207 bgp_unregister_for_label(dest
);
3212 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3213 __func__
, dest
, bgp
->name_pretty
, afi2str(afi
),
3214 safi2str(safi
), old_select
, new_select
);
3216 /* If best route remains the same and this is not due to user-initiated
3217 * clear, see exactly what needs to be done.
3219 if (old_select
&& old_select
== new_select
3220 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
3221 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3222 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
3223 if (bgp_zebra_has_route_changed(old_select
)) {
3224 #ifdef ENABLE_BGP_VNC
3225 vnc_import_bgp_add_route(bgp
, p
, old_select
);
3226 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
3228 if (bgp_fibupd_safi(safi
)
3229 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3231 if (new_select
->type
== ZEBRA_ROUTE_BGP
3232 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3233 || new_select
->sub_type
3234 == BGP_ROUTE_IMPORTED
))
3236 bgp_zebra_announce(dest
, p
, old_select
,
3241 /* If there is a change of interest to peers, reannounce the
3243 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3244 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3245 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
3246 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3248 /* unicast routes must also be annouced to
3249 * labeled-unicast update-groups */
3250 if (safi
== SAFI_UNICAST
)
3251 group_announce_route(bgp
, afi
,
3252 SAFI_LABELED_UNICAST
, dest
,
3255 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
3256 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
3259 /* advertise/withdraw type-5 routes */
3260 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3261 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
3262 bgp_process_evpn_route_injection(
3263 bgp
, afi
, safi
, dest
, old_select
, old_select
);
3265 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3266 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3267 bgp_zebra_clear_route_change_flags(dest
);
3268 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3272 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3274 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
3276 /* bestpath has changed; bump version */
3277 if (old_select
|| new_select
) {
3278 bgp_bump_version(dest
);
3280 if (!bgp
->t_rmap_def_originate_eval
) {
3284 update_group_refresh_default_originate_route_map
,
3285 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
3286 &bgp
->t_rmap_def_originate_eval
);
3291 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
3294 zlog_debug("%s: setting SELECTED flag", __func__
);
3295 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
3296 bgp_path_info_unset_flag(dest
, new_select
,
3297 BGP_PATH_ATTR_CHANGED
);
3298 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3299 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3302 #ifdef ENABLE_BGP_VNC
3303 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3304 if (old_select
!= new_select
) {
3306 vnc_import_bgp_exterior_del_route(bgp
, p
,
3308 vnc_import_bgp_del_route(bgp
, p
, old_select
);
3311 vnc_import_bgp_exterior_add_route(bgp
, p
,
3313 vnc_import_bgp_add_route(bgp
, p
, new_select
);
3319 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3321 /* unicast routes must also be annouced to labeled-unicast update-groups
3323 if (safi
== SAFI_UNICAST
)
3324 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
3328 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
3329 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3331 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
3332 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3333 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3334 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
3336 /* if this is an evpn imported type-5 prefix,
3337 * we need to withdraw the route first to clear
3338 * the nh neigh and the RMAC entry.
3341 is_route_parent_evpn(old_select
))
3342 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3344 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
3346 /* Withdraw the route from the kernel. */
3347 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
3348 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
3349 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
3350 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
3352 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3356 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
3359 /* Clear any route change flags. */
3360 bgp_zebra_clear_route_change_flags(dest
);
3362 /* Reap old select bgp_path_info, if it has been removed */
3363 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
3364 bgp_path_info_reap(dest
, old_select
);
3366 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3370 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3371 void bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
3373 struct bgp_dest
*dest
;
3375 struct afi_safi_info
*thread_info
;
3377 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
3378 struct event
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
3380 thread_info
= EVENT_ARG(t
);
3381 XFREE(MTYPE_TMP
, thread_info
);
3382 EVENT_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
3385 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
3386 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
3387 get_afi_safi_str(afi
, safi
, false),
3388 bgp
->gr_info
[afi
][safi
].gr_deferred
);
3391 /* Process the route list */
3392 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
3393 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0 &&
3394 cnt
< BGP_MAX_BEST_ROUTE_SELECT
;
3395 dest
= bgp_route_next(dest
)) {
3396 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
3399 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3400 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3401 bgp_process_main_one(bgp
, dest
, afi
, safi
);
3404 /* If iteration stopped before the entire table was traversed then the
3405 * node needs to be unlocked.
3408 bgp_dest_unlock_node(dest
);
3412 /* Send EOR message when all routes are processed */
3413 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
3414 bgp_send_delayed_eor(bgp
);
3415 /* Send route processing complete message to RIB */
3416 bgp_zebra_update(bgp
, afi
, safi
,
3417 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
3421 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3423 thread_info
->afi
= afi
;
3424 thread_info
->safi
= safi
;
3425 thread_info
->bgp
= bgp
;
3427 /* If there are more routes to be processed, start the
3430 event_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3431 BGP_ROUTE_SELECT_DELAY
,
3432 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3435 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3437 struct bgp_process_queue
*pqnode
= data
;
3438 struct bgp
*bgp
= pqnode
->bgp
;
3439 struct bgp_table
*table
;
3440 struct bgp_dest
*dest
;
3443 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3444 bgp_process_main_one(bgp
, NULL
, 0, 0);
3445 /* should always have dedicated wq call */
3446 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3450 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3451 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3452 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3453 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3454 table
= bgp_dest_table(dest
);
3455 /* note, new DESTs may be added as part of processing */
3456 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3458 bgp_dest_unlock_node(dest
);
3459 bgp_table_unlock(table
);
3465 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3467 struct bgp_process_queue
*pqnode
= data
;
3469 bgp_unlock(pqnode
->bgp
);
3471 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3474 void bgp_process_queue_init(struct bgp
*bgp
)
3476 if (!bgp
->process_queue
) {
3479 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3480 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3483 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3484 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3485 bgp
->process_queue
->spec
.max_retries
= 0;
3486 bgp
->process_queue
->spec
.hold
= 50;
3487 /* Use a higher yield value of 50ms for main queue processing */
3488 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3491 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3493 struct bgp_process_queue
*pqnode
;
3495 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3496 sizeof(struct bgp_process_queue
));
3498 /* unlocked in bgp_processq_del */
3499 pqnode
->bgp
= bgp_lock(bgp
);
3500 STAILQ_INIT(&pqnode
->pqueue
);
3505 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3507 #define ARBITRARY_PROCESS_QLEN 10000
3508 struct work_queue
*wq
= bgp
->process_queue
;
3509 struct bgp_process_queue
*pqnode
;
3510 int pqnode_reuse
= 0;
3512 /* already scheduled for processing? */
3513 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3516 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3519 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3520 if (BGP_DEBUG(update
, UPDATE_OUT
))
3521 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3526 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
)) {
3527 if (BGP_DEBUG(update
, UPDATE_OUT
))
3529 "Soft reconfigure table in progress for route %p",
3537 /* Add route nodes to an existing work queue item until reaching the
3538 limit only if is from the same BGP view and it's not an EOIU marker
3540 if (work_queue_item_count(wq
)) {
3541 struct work_queue_item
*item
= work_queue_last_item(wq
);
3542 pqnode
= item
->data
;
3544 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3545 || pqnode
->bgp
!= bgp
3546 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3547 pqnode
= bgp_processq_alloc(bgp
);
3551 pqnode
= bgp_processq_alloc(bgp
);
3552 /* all unlocked in bgp_process_wq */
3553 bgp_table_lock(bgp_dest_table(dest
));
3555 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3556 bgp_dest_lock_node(dest
);
3558 /* can't be enqueued twice */
3559 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3560 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3564 work_queue_add(wq
, pqnode
);
3569 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3571 struct bgp_process_queue
*pqnode
;
3573 if (bgp
->process_queue
== NULL
)
3576 pqnode
= bgp_processq_alloc(bgp
);
3578 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3579 work_queue_add(bgp
->process_queue
, pqnode
);
3582 static void bgp_maximum_prefix_restart_timer(struct event
*thread
)
3586 peer
= EVENT_ARG(thread
);
3587 peer
->t_pmax_restart
= NULL
;
3589 if (bgp_debug_neighbor_events(peer
))
3591 "%s Maximum-prefix restart timer expired, restore peering",
3594 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3595 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3598 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3602 bool filtered
= false;
3603 struct bgp_dest
*dest
;
3604 struct bgp_adj_in
*ain
;
3605 struct attr attr
= {};
3606 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3608 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3609 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3610 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3614 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3618 if (bgp_input_modifier(
3619 peer
, rn_p
, &attr
, afi
, safi
,
3620 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3628 bgp_attr_flush(&attr
);
3635 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3639 iana_safi_t pkt_safi
;
3640 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3641 PEER_FLAG_MAX_PREFIX_FORCE
))
3642 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3643 + peer
->pcount
[afi
][safi
]
3644 : peer
->pcount
[afi
][safi
];
3646 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3649 if (pcount
> peer
->pmax
[afi
][safi
]) {
3650 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3651 PEER_STATUS_PREFIX_LIMIT
)
3656 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3657 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3658 peer
->pmax
[afi
][safi
]);
3659 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3661 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3662 PEER_FLAG_MAX_PREFIX_WARNING
))
3665 /* Convert AFI, SAFI to values for packet. */
3666 pkt_afi
= afi_int2iana(afi
);
3667 pkt_safi
= safi_int2iana(safi
);
3671 ndata
[0] = (pkt_afi
>> 8);
3673 ndata
[2] = pkt_safi
;
3674 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3675 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3676 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3677 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3679 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3680 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3681 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3685 /* Dynamic peers will just close their connection. */
3686 if (peer_dynamic_neighbor(peer
))
3689 /* restart timer start */
3690 if (peer
->pmax_restart
[afi
][safi
]) {
3691 peer
->v_pmax_restart
=
3692 peer
->pmax_restart
[afi
][safi
] * 60;
3694 if (bgp_debug_neighbor_events(peer
))
3696 "%pBP Maximum-prefix restart timer started for %d secs",
3697 peer
, peer
->v_pmax_restart
);
3699 BGP_TIMER_ON(peer
->t_pmax_restart
,
3700 bgp_maximum_prefix_restart_timer
,
3701 peer
->v_pmax_restart
);
3706 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3707 PEER_STATUS_PREFIX_LIMIT
);
3710 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3711 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3712 PEER_STATUS_PREFIX_THRESHOLD
)
3717 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3718 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3719 peer
->pmax
[afi
][safi
]);
3720 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3721 PEER_STATUS_PREFIX_THRESHOLD
);
3723 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3724 PEER_STATUS_PREFIX_THRESHOLD
);
3728 /* Unconditionally remove the route from the RIB, without taking
3729 * damping into consideration (eg, because the session went down)
3731 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3732 struct peer
*peer
, afi_t afi
, safi_t safi
)
3735 struct bgp
*bgp
= NULL
;
3736 bool delete_route
= false;
3738 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3741 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3742 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3744 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3747 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3748 delete_route
= true;
3749 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3750 delete_route
= true;
3752 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3753 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3754 bgp
= pi
->peer
->bgp
;
3755 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3760 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3761 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3764 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3765 struct peer
*peer
, afi_t afi
, safi_t safi
,
3766 struct prefix_rd
*prd
)
3768 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3770 /* apply dampening, if result is suppressed, we'll be retaining
3771 * the bgp_path_info in the RIB for historical reference.
3773 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3774 && peer
->sort
== BGP_PEER_EBGP
)
3775 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3776 == BGP_DAMP_SUPPRESSED
) {
3777 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3782 #ifdef ENABLE_BGP_VNC
3783 if (safi
== SAFI_MPLS_VPN
) {
3784 struct bgp_dest
*pdest
= NULL
;
3785 struct bgp_table
*table
= NULL
;
3787 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3788 (struct prefix
*)prd
);
3789 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3790 table
= bgp_dest_get_bgp_table_info(pdest
);
3792 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3793 peer
->bgp
, prd
, table
, p
, pi
);
3795 bgp_dest_unlock_node(pdest
);
3797 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3798 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3800 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3801 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3806 /* If this is an EVPN route, process for un-import. */
3807 if (safi
== SAFI_EVPN
)
3808 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3810 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3813 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3814 struct peer
*peer
, struct attr
*attr
,
3815 struct bgp_dest
*dest
)
3817 struct bgp_path_info
*new;
3819 /* Make new BGP info. */
3820 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3822 new->instance
= instance
;
3823 new->sub_type
= sub_type
;
3826 new->uptime
= monotime(NULL
);
3831 /* Check if received nexthop is valid or not. */
3832 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3833 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3834 struct bgp_dest
*dest
)
3837 bool is_bgp_static_route
=
3838 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3842 * Only validated for unicast and multicast currently.
3843 * Also valid for EVPN where the nexthop is an IP address.
3844 * If we are a bgp static route being checked then there is
3845 * no need to check to see if the nexthop is martian as
3846 * that it should be ok.
3848 if (is_bgp_static_route
||
3849 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3852 /* If NEXT_HOP is present, validate it. */
3853 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3854 if (attr
->nexthop
.s_addr
== INADDR_ANY
||
3855 !ipv4_unicast_valid(&attr
->nexthop
) ||
3856 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3860 /* If MP_NEXTHOP is present, validate it. */
3861 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3862 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3863 * it is not an IPv6 link-local address.
3865 * If we receive an UPDATE with nexthop length set to 32 bytes
3866 * we shouldn't discard an UPDATE if it's set to (::).
3867 * The link-local (2st) is validated along the code path later.
3869 if (attr
->mp_nexthop_len
) {
3870 switch (attr
->mp_nexthop_len
) {
3871 case BGP_ATTR_NHLEN_IPV4
:
3872 case BGP_ATTR_NHLEN_VPNV4
:
3873 ret
= (attr
->mp_nexthop_global_in
.s_addr
==
3875 !ipv4_unicast_valid(
3876 &attr
->mp_nexthop_global_in
) ||
3877 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3881 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3882 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3883 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3884 &attr
->mp_nexthop_global
)
3885 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3886 || IN6_IS_ADDR_MULTICAST(
3887 &attr
->mp_nexthop_global
)
3888 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3891 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3892 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3893 || IN6_IS_ADDR_MULTICAST(
3894 &attr
->mp_nexthop_global
)
3895 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3908 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3910 struct community
*old
;
3911 struct community
*new;
3912 struct community
*merge
;
3913 struct community
*no_export
;
3915 old
= bgp_attr_get_community(attr
);
3916 no_export
= community_str2com("no-export");
3921 merge
= community_merge(community_dup(old
), no_export
);
3924 community_free(&old
);
3926 new = community_uniq_sort(merge
);
3927 community_free(&merge
);
3929 new = community_dup(no_export
);
3932 community_free(&no_export
);
3934 bgp_attr_set_community(attr
, new);
3937 static bool bgp_accept_own(struct peer
*peer
, afi_t afi
, safi_t safi
,
3938 struct attr
*attr
, const struct prefix
*prefix
,
3941 struct listnode
*node
, *nnode
;
3943 bool accept_own_found
= false;
3945 if (safi
!= SAFI_MPLS_VPN
)
3948 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3949 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
))
3952 /* The route in question carries the ACCEPT_OWN community */
3953 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
3954 struct community
*comm
= bgp_attr_get_community(attr
);
3956 if (community_include(comm
, COMMUNITY_ACCEPT_OWN
))
3957 accept_own_found
= true;
3960 /* The route in question is targeted to one or more destination VRFs
3961 * on the router (as determined by inspecting the Route Target(s)).
3963 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
3964 if (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
)
3967 if (accept_own_found
&&
3969 bgp
->vpn_policy
[afi
]
3970 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
],
3971 bgp_attr_get_ecommunity(attr
))) {
3972 if (bgp_debug_update(peer
, prefix
, NULL
, 1))
3974 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3977 /* Treat this route as imported, because it's leaked
3978 * already from another VRF, and we got an updated
3979 * version from route-reflector with ACCEPT_OWN
3982 *sub_type
= BGP_ROUTE_IMPORTED
;
3991 void bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
3992 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3993 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3994 uint32_t num_labels
, int soft_reconfig
,
3995 struct bgp_route_evpn
*evpn
)
3998 int aspath_loop_count
= 0;
3999 struct bgp_dest
*dest
;
4001 struct attr new_attr
;
4002 struct attr
*attr_new
;
4003 struct bgp_path_info
*pi
;
4004 struct bgp_path_info
*new = NULL
;
4005 struct bgp_path_info_extra
*extra
;
4007 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4009 int do_loop_check
= 1;
4010 int has_valid_label
= 0;
4012 bool force_evpn_import
= false;
4013 safi_t orig_safi
= safi
;
4014 bool leak_success
= true;
4017 if (frrtrace_enabled(frr_bgp
, process_update
)) {
4018 char pfxprint
[PREFIX2STR_BUFFER
];
4020 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
4021 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
4025 #ifdef ENABLE_BGP_VNC
4026 int vnc_implicit_withdraw
= 0;
4029 const struct prefix
*bgp_nht_param_prefix
;
4031 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4032 if (orig_safi
== SAFI_LABELED_UNICAST
)
4033 safi
= SAFI_UNICAST
;
4035 memset(&new_attr
, 0, sizeof(new_attr
));
4036 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
4037 new_attr
.label
= MPLS_INVALID_LABEL
;
4040 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4041 /* TODO: Check to see if we can get rid of "is_valid_label" */
4042 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
4043 has_valid_label
= (num_labels
> 0) ? 1 : 0;
4045 has_valid_label
= bgp_is_valid_label(label
);
4047 if (has_valid_label
)
4048 assert(label
!= NULL
);
4050 /* Update overlay index of the attribute */
4051 if (afi
== AFI_L2VPN
&& evpn
)
4052 memcpy(&attr
->evpn_overlay
, evpn
,
4053 sizeof(struct bgp_route_evpn
));
4055 /* When peer's soft reconfiguration enabled. Record input packet in
4058 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4059 && peer
!= bgp
->peer_self
)
4060 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
4062 /* Update permitted loop count */
4063 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN
))
4064 allowas_in
= peer
->allowas_in
[afi
][safi
];
4066 /* Check previously received route. */
4067 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4068 if (pi
->peer
== peer
&& pi
->type
== type
4069 && pi
->sub_type
== sub_type
4070 && pi
->addpath_rx_id
== addpath_id
)
4073 /* AS path local-as loop check. */
4074 if (peer
->change_local_as
) {
4076 aspath_loop_count
= allowas_in
;
4077 else if (!CHECK_FLAG(peer
->flags
,
4078 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
4079 aspath_loop_count
= 1;
4081 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
4082 > aspath_loop_count
) {
4083 peer
->stat_pfx_aspath_loop
++;
4084 reason
= "as-path contains our own AS;";
4089 /* If the peer is configured for "allowas-in origin" and the last ASN in
4091 * as-path is our ASN then we do not need to call aspath_loop_check
4093 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
4094 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
4097 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_REFLECTOR_CLIENT
))
4098 bgp_nht_param_prefix
= NULL
;
4100 bgp_nht_param_prefix
= p
;
4102 /* AS path loop check. */
4103 if (do_loop_check
) {
4104 if (aspath_loop_check(attr
->aspath
, bgp
->as
) >
4105 peer
->allowas_in
[afi
][safi
]) {
4106 peer
->stat_pfx_aspath_loop
++;
4107 reason
= "as-path contains our own AS;";
4112 /* If we're a CONFED we need to loop check the CONFED ID too */
4113 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
) && do_loop_check
)
4114 if (aspath_loop_check_confed(attr
->aspath
, bgp
->confed_id
) >
4115 peer
->allowas_in
[afi
][safi
]) {
4116 peer
->stat_pfx_aspath_loop
++;
4117 reason
= "as-path contains our own confed AS;";
4121 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4122 * enabled, then take care of that too.
4124 bool accept_own
= false;
4126 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
4127 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
4129 bgp_accept_own(peer
, afi
, safi
, attr
, p
, &sub_type
);
4131 peer
->stat_pfx_originator_loop
++;
4132 reason
= "originator is us;";
4137 /* Route reflector cluster ID check. */
4138 if (bgp_cluster_filter(peer
, attr
)) {
4139 peer
->stat_pfx_cluster_loop
++;
4140 reason
= "reflected from the same cluster;";
4144 /* Apply incoming filter. */
4145 if (bgp_input_filter(peer
, p
, attr
, afi
, orig_safi
) == FILTER_DENY
) {
4146 peer
->stat_pfx_filter
++;
4151 /* RFC 8212 to prevent route leaks.
4152 * This specification intends to improve this situation by requiring the
4153 * explicit configuration of both BGP Import and Export Policies for any
4154 * External BGP (EBGP) session such as customers, peers, or
4155 * confederation boundaries for all enabled address families. Through
4156 * codification of the aforementioned requirement, operators will
4157 * benefit from consistent behavior across different BGP
4160 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
4161 if (!bgp_inbound_policy_exists(peer
,
4162 &peer
->filter
[afi
][safi
])) {
4163 reason
= "inbound policy missing";
4164 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
4165 NULL
) > FIFTEENMINUTE2USEC
||
4166 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
4168 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4169 monotime(&bgp
->ebgprequirespolicywarning
);
4174 /* draft-ietf-idr-deprecate-as-set-confed-set
4175 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4176 * Eventually, This document (if approved) updates RFC 4271
4177 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4178 * and obsoletes RFC 6472.
4180 if (peer
->bgp
->reject_as_sets
)
4181 if (aspath_check_as_sets(attr
->aspath
)) {
4183 "as-path contains AS_SET or AS_CONFED_SET type;";
4189 /* Apply incoming route-map.
4190 * NB: new_attr may now contain newly allocated values from route-map
4192 * commands, so we need bgp_attr_flush in the error paths, until we
4194 * the attr (which takes over the memory references) */
4195 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, orig_safi
, NULL
, label
,
4198 peer
->stat_pfx_filter
++;
4199 reason
= "route-map;";
4200 bgp_attr_flush(&new_attr
);
4204 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
4205 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
4206 /* remove from RIB previous entry */
4207 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
4210 if (peer
->sort
== BGP_PEER_EBGP
) {
4213 * A BGP speaker receiving an announcement tagged with the
4214 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4215 * NO_EXPORT community as defined in RFC1997, or a
4216 * similar community, to prevent propagation of the
4217 * prefix outside the local AS. The community to prevent
4218 * propagation SHOULD be chosen according to the operator's
4221 if (bgp_attr_get_community(&new_attr
) &&
4222 community_include(bgp_attr_get_community(&new_attr
),
4223 COMMUNITY_BLACKHOLE
))
4224 bgp_attr_add_no_export_community(&new_attr
);
4226 /* If we receive the graceful-shutdown community from an eBGP
4227 * peer we must lower local-preference */
4228 if (bgp_attr_get_community(&new_attr
) &&
4229 community_include(bgp_attr_get_community(&new_attr
),
4231 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
4232 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
4234 /* If graceful-shutdown is configured globally or
4235 * per neighbor, then add the GSHUT community to
4236 * all paths received from eBGP peers. */
4237 } else if (bgp_in_graceful_shutdown(peer
->bgp
) ||
4238 CHECK_FLAG(peer
->flags
, PEER_FLAG_GRACEFUL_SHUTDOWN
))
4239 bgp_attr_add_gshut_community(&new_attr
);
4242 /* next hop check. */
4243 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
) &&
4244 bgp_update_martian_nexthop(bgp
, afi
, safi
, type
, sub_type
,
4246 peer
->stat_pfx_nh_invalid
++;
4247 reason
= "martian or self next-hop;";
4248 bgp_attr_flush(&new_attr
);
4252 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
4253 peer
->stat_pfx_nh_invalid
++;
4254 reason
= "self mac;";
4255 bgp_attr_flush(&new_attr
);
4259 if (bgp_check_role_applicability(afi
, safi
) &&
4260 bgp_otc_filter(peer
, &new_attr
)) {
4261 reason
= "failing otc validation";
4262 bgp_attr_flush(&new_attr
);
4266 /* If neighbor soo is configured, tag all incoming routes with
4267 * this SoO tag and then filter out advertisements in
4268 * subgroup_announce_check() if it matches the configured SoO
4269 * on the other peer.
4271 if (peer
->soo
[afi
][safi
]) {
4272 struct ecommunity
*old_ecomm
=
4273 bgp_attr_get_ecommunity(&new_attr
);
4274 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
4275 struct ecommunity
*new_ecomm
;
4278 new_ecomm
= ecommunity_merge(ecommunity_dup(old_ecomm
),
4281 if (!old_ecomm
->refcnt
)
4282 ecommunity_free(&old_ecomm
);
4284 new_ecomm
= ecommunity_dup(ecomm_soo
);
4287 bgp_attr_set_ecommunity(&new_attr
, new_ecomm
);
4290 attr_new
= bgp_attr_intern(&new_attr
);
4292 /* If the update is implicit withdraw. */
4294 pi
->uptime
= monotime(NULL
);
4295 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
4297 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4299 /* Same attribute comes in. */
4300 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4302 && (!has_valid_label
4303 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
4304 num_labels
* sizeof(mpls_label_t
))
4306 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4307 BGP_CONFIG_DAMPENING
)
4308 && peer
->sort
== BGP_PEER_EBGP
4309 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4310 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4311 bgp_debug_rdpfxpath2str(
4312 afi
, safi
, prd
, p
, label
,
4313 num_labels
, addpath_id
? 1 : 0,
4314 addpath_id
, evpn
, pfx_buf
,
4316 zlog_debug("%pBP rcvd %s", peer
,
4320 if (bgp_damp_update(pi
, dest
, afi
, safi
)
4321 != BGP_DAMP_SUPPRESSED
) {
4322 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
4324 bgp_process(bgp
, dest
, afi
, safi
);
4326 } else /* Duplicate - odd */
4328 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4329 if (!peer
->rcvd_attr_printed
) {
4331 "%pBP rcvd UPDATE w/ attr: %s",
4333 peer
->rcvd_attr_str
);
4334 peer
->rcvd_attr_printed
= 1;
4337 bgp_debug_rdpfxpath2str(
4338 afi
, safi
, prd
, p
, label
,
4339 num_labels
, addpath_id
? 1 : 0,
4340 addpath_id
, evpn
, pfx_buf
,
4343 "%pBP rcvd %s...duplicate ignored",
4347 /* graceful restart STALE flag unset. */
4348 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4349 bgp_path_info_unset_flag(
4350 dest
, pi
, BGP_PATH_STALE
);
4351 bgp_dest_set_defer_flag(dest
, false);
4352 bgp_process(bgp
, dest
, afi
, safi
);
4356 bgp_dest_unlock_node(dest
);
4357 bgp_attr_unintern(&attr_new
);
4362 /* Withdraw/Announce before we fully processed the withdraw */
4363 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4364 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4365 bgp_debug_rdpfxpath2str(
4366 afi
, safi
, prd
, p
, label
, num_labels
,
4367 addpath_id
? 1 : 0, addpath_id
, evpn
,
4368 pfx_buf
, sizeof(pfx_buf
));
4370 "%pBP rcvd %s, flapped quicker than processing",
4374 bgp_path_info_restore(dest
, pi
);
4377 * If the BGP_PATH_REMOVED flag is set, then EVPN
4378 * routes would have been unimported already when a
4379 * prior BGP withdraw processing happened. Such routes
4380 * need to be imported again, so flag accordingly.
4382 force_evpn_import
= true;
4384 /* implicit withdraw, decrement aggregate and pcount
4385 * here. only if update is accepted, they'll increment
4388 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4391 /* Received Logging. */
4392 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4393 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
4394 num_labels
, addpath_id
? 1 : 0,
4395 addpath_id
, evpn
, pfx_buf
,
4397 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4400 /* graceful restart STALE flag unset. */
4401 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4402 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
4403 bgp_dest_set_defer_flag(dest
, false);
4406 /* The attribute is changed. */
4407 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
4409 /* Update bgp route dampening information. */
4410 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4411 && peer
->sort
== BGP_PEER_EBGP
) {
4412 /* This is implicit withdraw so we should update
4415 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
4416 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
4418 #ifdef ENABLE_BGP_VNC
4419 if (safi
== SAFI_MPLS_VPN
) {
4420 struct bgp_dest
*pdest
= NULL
;
4421 struct bgp_table
*table
= NULL
;
4423 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4424 (struct prefix
*)prd
);
4425 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4426 table
= bgp_dest_get_bgp_table_info(pdest
);
4428 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
4429 bgp
, prd
, table
, p
, pi
);
4431 bgp_dest_unlock_node(pdest
);
4433 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4434 && (safi
== SAFI_UNICAST
)) {
4435 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4437 * Implicit withdraw case.
4439 ++vnc_implicit_withdraw
;
4440 vnc_import_bgp_del_route(bgp
, p
, pi
);
4441 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
4446 /* Special handling for EVPN update of an existing route. If the
4447 * extended community attribute has changed, we need to
4449 * the route using its existing extended community. It will be
4450 * subsequently processed for import with the new extended
4453 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
4456 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
4458 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4461 cmp
= ecommunity_cmp(
4462 bgp_attr_get_ecommunity(pi
->attr
),
4463 bgp_attr_get_ecommunity(attr_new
));
4465 if (bgp_debug_update(peer
, p
, NULL
, 1))
4467 "Change in EXT-COMM, existing %s new %s",
4469 bgp_attr_get_ecommunity(
4472 bgp_attr_get_ecommunity(
4474 if (safi
== SAFI_EVPN
)
4475 bgp_evpn_unimport_route(
4476 bgp
, afi
, safi
, p
, pi
);
4477 else /* SAFI_MPLS_VPN */
4478 vpn_leak_to_vrf_withdraw(pi
);
4483 /* Update to new attribute. */
4484 bgp_attr_unintern(&pi
->attr
);
4485 pi
->attr
= attr_new
;
4487 /* Update MPLS label */
4488 if (has_valid_label
) {
4489 extra
= bgp_path_info_extra_get(pi
);
4490 if (extra
->label
!= label
) {
4491 memcpy(&extra
->label
, label
,
4492 num_labels
* sizeof(mpls_label_t
));
4493 extra
->num_labels
= num_labels
;
4495 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4496 bgp_set_valid_label(&extra
->label
[0]);
4499 /* Update SRv6 SID */
4500 if (attr
->srv6_l3vpn
) {
4501 extra
= bgp_path_info_extra_get(pi
);
4502 if (sid_diff(&extra
->sid
[0].sid
,
4503 &attr
->srv6_l3vpn
->sid
)) {
4504 sid_copy(&extra
->sid
[0].sid
,
4505 &attr
->srv6_l3vpn
->sid
);
4506 extra
->num_sids
= 1;
4508 extra
->sid
[0].loc_block_len
= 0;
4509 extra
->sid
[0].loc_node_len
= 0;
4510 extra
->sid
[0].func_len
= 0;
4511 extra
->sid
[0].arg_len
= 0;
4512 extra
->sid
[0].transposition_len
= 0;
4513 extra
->sid
[0].transposition_offset
= 0;
4515 if (attr
->srv6_l3vpn
->loc_block_len
!= 0) {
4516 extra
->sid
[0].loc_block_len
=
4517 attr
->srv6_l3vpn
->loc_block_len
;
4518 extra
->sid
[0].loc_node_len
=
4519 attr
->srv6_l3vpn
->loc_node_len
;
4520 extra
->sid
[0].func_len
=
4521 attr
->srv6_l3vpn
->func_len
;
4522 extra
->sid
[0].arg_len
=
4523 attr
->srv6_l3vpn
->arg_len
;
4524 extra
->sid
[0].transposition_len
=
4526 ->transposition_len
;
4527 extra
->sid
[0].transposition_offset
=
4529 ->transposition_offset
;
4532 } else if (attr
->srv6_vpn
) {
4533 extra
= bgp_path_info_extra_get(pi
);
4534 if (sid_diff(&extra
->sid
[0].sid
,
4535 &attr
->srv6_vpn
->sid
)) {
4536 sid_copy(&extra
->sid
[0].sid
,
4537 &attr
->srv6_vpn
->sid
);
4538 extra
->num_sids
= 1;
4542 #ifdef ENABLE_BGP_VNC
4543 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4544 && (safi
== SAFI_UNICAST
)) {
4545 if (vnc_implicit_withdraw
) {
4547 * Add back the route with its new attributes
4549 * The route is still selected, until the route
4551 * queued by bgp_process actually runs. We have
4553 * update to the VNC side immediately to avoid
4555 * configuration changes (e.g., route-map
4557 * trigger re-importation of the entire RIB.
4559 vnc_import_bgp_add_route(bgp
, p
, pi
);
4560 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4565 /* Update bgp route dampening information. */
4566 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4567 && peer
->sort
== BGP_PEER_EBGP
) {
4568 /* Now we do normal update dampening. */
4569 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4570 if (ret
== BGP_DAMP_SUPPRESSED
) {
4571 bgp_dest_unlock_node(dest
);
4576 /* Nexthop reachability check - for unicast and
4577 * labeled-unicast.. */
4578 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4579 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4580 || (safi
== SAFI_EVPN
&&
4581 bgp_evpn_is_prefix_nht_supported(p
))) {
4582 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4583 && peer
->ttl
== BGP_DEFAULT_TTL
4584 && !CHECK_FLAG(peer
->flags
,
4585 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4586 && !CHECK_FLAG(bgp
->flags
,
4587 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4592 struct bgp
*bgp_nexthop
= bgp
;
4594 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4595 bgp_nexthop
= pi
->extra
->bgp_orig
;
4597 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4599 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4600 safi
, pi
, NULL
, connected
,
4601 bgp_nht_param_prefix
) ||
4602 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4603 bgp_path_info_set_flag(dest
, pi
,
4606 if (BGP_DEBUG(nht
, NHT
)) {
4607 zlog_debug("%s(%pI4): NH unresolved",
4609 (in_addr_t
*)&attr_new
->nexthop
);
4611 bgp_path_info_unset_flag(dest
, pi
,
4616 bgp_path_info_set_flag(dest
, pi
,
4617 BGP_PATH_ACCEPT_OWN
);
4619 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4622 #ifdef ENABLE_BGP_VNC
4623 if (safi
== SAFI_MPLS_VPN
) {
4624 struct bgp_dest
*pdest
= NULL
;
4625 struct bgp_table
*table
= NULL
;
4627 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4628 (struct prefix
*)prd
);
4629 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4630 table
= bgp_dest_get_bgp_table_info(pdest
);
4632 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4633 bgp
, prd
, table
, p
, pi
);
4635 bgp_dest_unlock_node(pdest
);
4639 /* If this is an EVPN route and some attribute has changed,
4640 * or we are explicitly told to perform a route import, process
4641 * route for import. If the extended community has changed, we
4643 * have done the un-import earlier and the import would result
4645 * route getting injected into appropriate L2 VNIs. If it is
4647 * some other attribute change, the import will result in
4649 * the attributes for the route in the VNI(s).
4651 if (safi
== SAFI_EVPN
&&
4652 (!same_attr
|| force_evpn_import
) &&
4653 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4654 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4656 /* Process change. */
4657 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4659 bgp_process(bgp
, dest
, afi
, safi
);
4660 bgp_dest_unlock_node(dest
);
4662 if (SAFI_UNICAST
== safi
4663 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4664 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4666 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4668 if ((SAFI_MPLS_VPN
== safi
)
4669 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4670 leak_success
= vpn_leak_to_vrf_update(bgp
, pi
, prd
);
4673 #ifdef ENABLE_BGP_VNC
4674 if (SAFI_MPLS_VPN
== safi
) {
4675 mpls_label_t label_decoded
= decode_label(label
);
4677 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4678 type
, sub_type
, &label_decoded
);
4680 if (SAFI_ENCAP
== safi
) {
4681 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4682 type
, sub_type
, NULL
);
4685 if ((safi
== SAFI_MPLS_VPN
) &&
4686 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4687 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4689 bgp_unlink_nexthop(pi
);
4690 bgp_path_info_delete(dest
, pi
);
4693 } // End of implicit withdraw
4695 /* Received Logging. */
4696 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4697 if (!peer
->rcvd_attr_printed
) {
4698 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4699 peer
->rcvd_attr_str
);
4700 peer
->rcvd_attr_printed
= 1;
4703 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4704 addpath_id
? 1 : 0, addpath_id
, evpn
,
4705 pfx_buf
, sizeof(pfx_buf
));
4706 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4709 /* Make new BGP info. */
4710 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4712 /* Update MPLS label */
4713 if (has_valid_label
) {
4714 extra
= bgp_path_info_extra_get(new);
4715 if (extra
->label
!= label
) {
4716 memcpy(&extra
->label
, label
,
4717 num_labels
* sizeof(mpls_label_t
));
4718 extra
->num_labels
= num_labels
;
4720 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4721 bgp_set_valid_label(&extra
->label
[0]);
4724 /* Update SRv6 SID */
4725 if (safi
== SAFI_MPLS_VPN
) {
4726 extra
= bgp_path_info_extra_get(new);
4727 if (attr
->srv6_l3vpn
) {
4728 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_l3vpn
->sid
);
4729 extra
->num_sids
= 1;
4731 extra
->sid
[0].loc_block_len
=
4732 attr
->srv6_l3vpn
->loc_block_len
;
4733 extra
->sid
[0].loc_node_len
=
4734 attr
->srv6_l3vpn
->loc_node_len
;
4735 extra
->sid
[0].func_len
= attr
->srv6_l3vpn
->func_len
;
4736 extra
->sid
[0].arg_len
= attr
->srv6_l3vpn
->arg_len
;
4737 extra
->sid
[0].transposition_len
=
4738 attr
->srv6_l3vpn
->transposition_len
;
4739 extra
->sid
[0].transposition_offset
=
4740 attr
->srv6_l3vpn
->transposition_offset
;
4741 } else if (attr
->srv6_vpn
) {
4742 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_vpn
->sid
);
4743 extra
->num_sids
= 1;
4747 /* Nexthop reachability check. */
4748 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4749 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4750 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4751 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4752 && peer
->ttl
== BGP_DEFAULT_TTL
4753 && !CHECK_FLAG(peer
->flags
,
4754 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4755 && !CHECK_FLAG(bgp
->flags
,
4756 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4761 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4763 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4764 connected
, bgp_nht_param_prefix
) ||
4765 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4766 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4768 if (BGP_DEBUG(nht
, NHT
))
4769 zlog_debug("%s(%pI4): NH unresolved", __func__
,
4770 &attr_new
->nexthop
);
4771 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4775 bgp_path_info_set_flag(dest
, new, BGP_PATH_ACCEPT_OWN
);
4777 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4780 /* If maximum prefix count is configured and current prefix
4783 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0)) {
4784 reason
= "maximum-prefix overflow";
4785 bgp_attr_flush(&new_attr
);
4790 new->addpath_rx_id
= addpath_id
;
4792 /* Increment prefix */
4793 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4795 /* Register new BGP information. */
4796 bgp_path_info_add(dest
, new);
4798 /* route_node_get lock */
4799 bgp_dest_unlock_node(dest
);
4801 #ifdef ENABLE_BGP_VNC
4802 if (safi
== SAFI_MPLS_VPN
) {
4803 struct bgp_dest
*pdest
= NULL
;
4804 struct bgp_table
*table
= NULL
;
4806 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4807 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4808 table
= bgp_dest_get_bgp_table_info(pdest
);
4810 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4811 bgp
, prd
, table
, p
, new);
4813 bgp_dest_unlock_node(pdest
);
4817 /* If this is an EVPN route, process for import. */
4818 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4819 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4821 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4823 /* Process change. */
4824 bgp_process(bgp
, dest
, afi
, safi
);
4826 if (SAFI_UNICAST
== safi
4827 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4828 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4829 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4831 if ((SAFI_MPLS_VPN
== safi
)
4832 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4833 leak_success
= vpn_leak_to_vrf_update(bgp
, new, prd
);
4835 #ifdef ENABLE_BGP_VNC
4836 if (SAFI_MPLS_VPN
== safi
) {
4837 mpls_label_t label_decoded
= decode_label(label
);
4839 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4840 sub_type
, &label_decoded
);
4842 if (SAFI_ENCAP
== safi
) {
4843 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4847 if ((safi
== SAFI_MPLS_VPN
) &&
4848 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4849 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4851 bgp_unlink_nexthop(new);
4852 bgp_path_info_delete(dest
, new);
4857 /* This BGP update is filtered. Log the reason then update BGP
4861 bgp_unlink_nexthop(new);
4862 bgp_path_info_delete(dest
, new);
4863 bgp_path_info_extra_free(&new->extra
);
4864 XFREE(MTYPE_BGP_ROUTE
, new);
4867 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4869 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4870 if (!peer
->rcvd_attr_printed
) {
4871 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4872 peer
->rcvd_attr_str
);
4873 peer
->rcvd_attr_printed
= 1;
4876 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4877 addpath_id
? 1 : 0, addpath_id
, evpn
,
4878 pfx_buf
, sizeof(pfx_buf
));
4879 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4880 peer
, pfx_buf
, reason
);
4884 /* If this is an EVPN route, un-import it as it is now filtered.
4886 if (safi
== SAFI_EVPN
)
4887 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4889 if (SAFI_UNICAST
== safi
4890 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4891 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4893 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4895 if ((SAFI_MPLS_VPN
== safi
)
4896 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4898 vpn_leak_to_vrf_withdraw(pi
);
4901 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4904 bgp_dest_unlock_node(dest
);
4906 #ifdef ENABLE_BGP_VNC
4908 * Filtered update is treated as an implicit withdrawal (see
4910 * a few lines above)
4912 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4913 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4921 void bgp_withdraw(struct peer
*peer
, const struct prefix
*p
,
4922 uint32_t addpath_id
, afi_t afi
, safi_t safi
, int type
,
4923 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4924 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4927 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4928 struct bgp_dest
*dest
;
4929 struct bgp_path_info
*pi
;
4931 #ifdef ENABLE_BGP_VNC
4932 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4933 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4941 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4943 /* If peer is soft reconfiguration enabled. Record input packet for
4944 * further calculation.
4946 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4947 * routes that are filtered. This tanks out Quagga RS pretty badly due
4949 * the iteration over all RS clients.
4950 * Since we need to remove the entry from adj_in anyway, do that first
4952 * if there was no entry, we don't need to do anything more.
4954 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4955 && peer
!= bgp
->peer_self
)
4956 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4957 peer
->stat_pfx_dup_withdraw
++;
4959 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4960 bgp_debug_rdpfxpath2str(
4961 afi
, safi
, prd
, p
, label
, num_labels
,
4962 addpath_id
? 1 : 0, addpath_id
, NULL
,
4963 pfx_buf
, sizeof(pfx_buf
));
4965 "%s withdrawing route %s not in adj-in",
4966 peer
->host
, pfx_buf
);
4968 bgp_dest_unlock_node(dest
);
4972 /* Lookup withdrawn route. */
4973 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4974 if (pi
->peer
== peer
&& pi
->type
== type
4975 && pi
->sub_type
== sub_type
4976 && pi
->addpath_rx_id
== addpath_id
)
4980 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4981 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4982 addpath_id
? 1 : 0, addpath_id
, NULL
,
4983 pfx_buf
, sizeof(pfx_buf
));
4984 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer
,
4988 /* Withdraw specified route from routing table. */
4989 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4990 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4991 if (SAFI_UNICAST
== safi
4992 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4993 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4994 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4996 if ((SAFI_MPLS_VPN
== safi
)
4997 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4999 vpn_leak_to_vrf_withdraw(pi
);
5001 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
5002 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
5003 addpath_id
? 1 : 0, addpath_id
, NULL
,
5004 pfx_buf
, sizeof(pfx_buf
));
5005 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
5008 /* Unlock bgp_node_get() lock. */
5009 bgp_dest_unlock_node(dest
);
5014 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
5017 struct update_subgroup
*subgrp
;
5018 subgrp
= peer_subgroup(peer
, afi
, safi
);
5019 subgroup_default_originate(subgrp
, withdraw
);
5024 * bgp_stop_announce_route_timer
5026 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
5028 if (!paf
->t_announce_route
)
5031 EVENT_OFF(paf
->t_announce_route
);
5035 * bgp_announce_route_timer_expired
5037 * Callback that is invoked when the route announcement timer for a
5040 static void bgp_announce_route_timer_expired(struct event
*t
)
5042 struct peer_af
*paf
;
5048 if (!peer_established(peer
))
5051 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
5054 peer_af_announce_route(paf
, 1);
5056 /* Notify BGP conditional advertisement scanner percess */
5057 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
5061 * bgp_announce_route
5063 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
5065 * if force is true we will force an update even if the update
5066 * limiting code is attempted to kick in.
5068 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
, bool force
)
5070 struct peer_af
*paf
;
5071 struct update_subgroup
*subgrp
;
5073 paf
= peer_af_find(peer
, afi
, safi
);
5076 subgrp
= PAF_SUBGRP(paf
);
5079 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5080 * or a refresh has already been triggered.
5082 if (!subgrp
|| paf
->t_announce_route
)
5086 SET_FLAG(subgrp
->sflags
, SUBGRP_STATUS_FORCE_UPDATES
);
5089 * Start a timer to stagger/delay the announce. This serves
5090 * two purposes - announcement can potentially be combined for
5091 * multiple peers and the announcement doesn't happen in the
5094 event_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
5095 (subgrp
->peer_count
== 1)
5096 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5097 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
5098 &paf
->t_announce_route
);
5102 * Announce routes from all AF tables to a peer.
5104 * This should ONLY be called when there is a need to refresh the
5105 * routes to the peer based on a policy change for this peer alone
5106 * or a route refresh request received from the peer.
5107 * The operation will result in splitting the peer from its existing
5108 * subgroups and putting it in new subgroups.
5110 void bgp_announce_route_all(struct peer
*peer
)
5115 FOREACH_AFI_SAFI (afi
, safi
)
5116 bgp_announce_route(peer
, afi
, safi
, false);
5119 /* Flag or unflag bgp_dest to determine whether it should be treated by
5120 * bgp_soft_reconfig_table_task.
5121 * Flag if flag is true. Unflag if flag is false.
5123 static void bgp_soft_reconfig_table_flag(struct bgp_table
*table
, bool flag
)
5125 struct bgp_dest
*dest
;
5126 struct bgp_adj_in
*ain
;
5131 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5132 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5133 if (ain
->peer
!= NULL
)
5136 if (flag
&& ain
!= NULL
&& ain
->peer
!= NULL
)
5137 SET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5139 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5143 static void bgp_soft_reconfig_table_update(struct peer
*peer
,
5144 struct bgp_dest
*dest
,
5145 struct bgp_adj_in
*ain
, afi_t afi
,
5146 safi_t safi
, struct prefix_rd
*prd
)
5148 struct bgp_path_info
*pi
;
5149 uint32_t num_labels
= 0;
5150 mpls_label_t
*label_pnt
= NULL
;
5151 struct bgp_route_evpn evpn
;
5153 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5154 if (pi
->peer
== peer
)
5157 if (pi
&& pi
->extra
)
5158 num_labels
= pi
->extra
->num_labels
;
5160 label_pnt
= &pi
->extra
->label
[0];
5162 memcpy(&evpn
, bgp_attr_get_evpn_overlay(pi
->attr
),
5165 memset(&evpn
, 0, sizeof(evpn
));
5167 bgp_update(peer
, bgp_dest_get_prefix(dest
), ain
->addpath_rx_id
,
5168 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, prd
,
5169 label_pnt
, num_labels
, 1, &evpn
);
5172 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5173 struct bgp_table
*table
,
5174 struct prefix_rd
*prd
)
5176 struct bgp_dest
*dest
;
5177 struct bgp_adj_in
*ain
;
5180 table
= peer
->bgp
->rib
[afi
][safi
];
5182 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5183 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5184 if (ain
->peer
!= peer
)
5187 bgp_soft_reconfig_table_update(peer
, dest
, ain
, afi
,
5192 /* Do soft reconfig table per bgp table.
5193 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5194 * when BGP_NODE_SOFT_RECONFIG is set,
5195 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5196 * Schedule a new thread to continue the job.
5197 * Without splitting the full job into several part,
5198 * vtysh waits for the job to finish before responding to a BGP command
5200 static void bgp_soft_reconfig_table_task(struct event
*thread
)
5202 uint32_t iter
, max_iter
;
5203 struct bgp_dest
*dest
;
5204 struct bgp_adj_in
*ain
;
5206 struct bgp_table
*table
;
5207 struct prefix_rd
*prd
;
5208 struct listnode
*node
, *nnode
;
5210 table
= EVENT_ARG(thread
);
5213 max_iter
= SOFT_RECONFIG_TASK_MAX_PREFIX
;
5214 if (table
->soft_reconfig_init
) {
5215 /* first call of the function with a new srta structure.
5216 * Don't do any treatment this time on nodes
5217 * in order vtysh to respond quickly
5222 for (iter
= 0, dest
= bgp_table_top(table
); (dest
&& iter
< max_iter
);
5223 dest
= bgp_route_next(dest
)) {
5224 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
))
5227 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5229 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5230 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
,
5232 if (ain
->peer
!= peer
)
5235 bgp_soft_reconfig_table_update(
5236 peer
, dest
, ain
, table
->afi
,
5243 /* we're either starting the initial iteration,
5244 * or we're going to continue an ongoing iteration
5246 if (dest
|| table
->soft_reconfig_init
) {
5247 table
->soft_reconfig_init
= false;
5248 event_add_event(bm
->master
, bgp_soft_reconfig_table_task
, table
,
5249 0, &table
->soft_reconfig_thread
);
5252 /* we're done, clean up the background iteration context info and
5253 schedule route annoucement
5255 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
, peer
)) {
5256 listnode_delete(table
->soft_reconfig_peers
, peer
);
5257 bgp_announce_route(peer
, table
->afi
, table
->safi
, false);
5260 list_delete(&table
->soft_reconfig_peers
);
5264 /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5266 * - bgp cannot be NULL
5267 * - if table and peer are NULL, cancel all threads within the bgp instance
5268 * - if table is NULL and peer is not,
5269 * remove peer in all threads within the bgp instance
5270 * - if peer is NULL, cancel all threads matching table within the bgp instance
5272 void bgp_soft_reconfig_table_task_cancel(const struct bgp
*bgp
,
5273 const struct bgp_table
*table
,
5274 const struct peer
*peer
)
5277 struct listnode
*node
, *nnode
;
5279 struct bgp_table
*ntable
;
5284 FOREACH_AFI_SAFI (afi
, safi
) {
5285 ntable
= bgp
->rib
[afi
][safi
];
5288 if (table
&& table
!= ntable
)
5291 for (ALL_LIST_ELEMENTS(ntable
->soft_reconfig_peers
, node
, nnode
,
5293 if (peer
&& peer
!= npeer
)
5295 listnode_delete(ntable
->soft_reconfig_peers
, npeer
);
5298 if (!ntable
->soft_reconfig_peers
5299 || !list_isempty(ntable
->soft_reconfig_peers
))
5302 list_delete(&ntable
->soft_reconfig_peers
);
5303 bgp_soft_reconfig_table_flag(ntable
, false);
5304 EVENT_OFF(ntable
->soft_reconfig_thread
);
5309 * Returns false if the peer is not configured for soft reconfig in
5311 bool bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5313 struct bgp_dest
*dest
;
5314 struct bgp_table
*table
;
5315 struct listnode
*node
, *nnode
;
5317 struct peer_af
*paf
;
5319 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
))
5322 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
5323 && (safi
!= SAFI_EVPN
)) {
5324 table
= peer
->bgp
->rib
[afi
][safi
];
5328 table
->soft_reconfig_init
= true;
5330 if (!table
->soft_reconfig_peers
)
5331 table
->soft_reconfig_peers
= list_new();
5333 /* add peer to the table soft_reconfig_peers if not already
5336 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
,
5342 listnode_add(table
->soft_reconfig_peers
, peer
);
5344 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5345 * on table would start back at the beginning.
5347 bgp_soft_reconfig_table_flag(table
, true);
5349 if (!table
->soft_reconfig_thread
)
5350 event_add_event(bm
->master
,
5351 bgp_soft_reconfig_table_task
, table
, 0,
5352 &table
->soft_reconfig_thread
);
5353 /* Cancel bgp_announce_route_timer_expired threads.
5354 * bgp_announce_route_timer_expired threads have been scheduled
5355 * to announce routes as soon as the soft_reconfigure process
5357 * In this case, soft_reconfigure is also scheduled by using
5358 * a thread but is planned after the
5359 * bgp_announce_route_timer_expired threads. It means that,
5360 * without cancelling the threads, the route announcement task
5361 * would run before the soft reconfiguration one. That would
5362 * useless and would block vtysh during several seconds. Route
5363 * announcements are rescheduled as soon as the soft_reconfigure
5366 paf
= peer_af_find(peer
, afi
, safi
);
5368 bgp_stop_announce_route_timer(paf
);
5370 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5371 dest
= bgp_route_next(dest
)) {
5372 table
= bgp_dest_get_bgp_table_info(dest
);
5377 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5378 struct prefix_rd prd
;
5380 prd
.family
= AF_UNSPEC
;
5382 memcpy(&prd
.val
, p
->u
.val
, 8);
5384 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
5391 struct bgp_clear_node_queue
{
5392 struct bgp_dest
*dest
;
5395 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
5397 struct bgp_clear_node_queue
*cnq
= data
;
5398 struct bgp_dest
*dest
= cnq
->dest
;
5399 struct peer
*peer
= wq
->spec
.data
;
5400 struct bgp_path_info
*pi
;
5402 afi_t afi
= bgp_dest_table(dest
)->afi
;
5403 safi_t safi
= bgp_dest_table(dest
)->safi
;
5405 assert(dest
&& peer
);
5408 /* It is possible that we have multiple paths for a prefix from a peer
5409 * if that peer is using AddPath.
5411 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5412 if (pi
->peer
!= peer
)
5415 /* graceful restart STALE flag set. */
5416 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
5417 && peer
->nsf
[afi
][safi
])
5418 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5419 PEER_STATUS_ENHANCED_REFRESH
))
5420 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5421 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
5422 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
5424 /* If this is an EVPN route, process for
5426 if (safi
== SAFI_EVPN
)
5427 bgp_evpn_unimport_route(
5429 bgp_dest_get_prefix(dest
), pi
);
5430 /* Handle withdraw for VRF route-leaking and L3VPN */
5431 if (SAFI_UNICAST
== safi
5432 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
5433 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5434 vpn_leak_from_vrf_withdraw(bgp_get_default(),
5437 if (SAFI_MPLS_VPN
== safi
&&
5438 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5439 vpn_leak_to_vrf_withdraw(pi
);
5442 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5448 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
5450 struct bgp_clear_node_queue
*cnq
= data
;
5451 struct bgp_dest
*dest
= cnq
->dest
;
5452 struct bgp_table
*table
= bgp_dest_table(dest
);
5454 bgp_dest_unlock_node(dest
);
5455 bgp_table_unlock(table
);
5456 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
5459 static void bgp_clear_node_complete(struct work_queue
*wq
)
5461 struct peer
*peer
= wq
->spec
.data
;
5463 /* Tickle FSM to start moving again */
5464 BGP_EVENT_ADD(peer
, Clearing_Completed
);
5466 peer_unlock(peer
); /* bgp_clear_route */
5469 static void bgp_clear_node_queue_init(struct peer
*peer
)
5471 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5473 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
5474 #undef CLEAR_QUEUE_NAME_LEN
5476 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
5477 peer
->clear_node_queue
->spec
.hold
= 10;
5478 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
5479 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
5480 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
5481 peer
->clear_node_queue
->spec
.max_retries
= 0;
5483 /* we only 'lock' this peer reference when the queue is actually active
5485 peer
->clear_node_queue
->spec
.data
= peer
;
5488 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5489 struct bgp_table
*table
)
5491 struct bgp_dest
*dest
;
5492 int force
= peer
->bgp
->process_queue
? 0 : 1;
5495 table
= peer
->bgp
->rib
[afi
][safi
];
5497 /* If still no table => afi/safi isn't configured at all or smth. */
5501 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5502 struct bgp_path_info
*pi
, *next
;
5503 struct bgp_adj_in
*ain
;
5504 struct bgp_adj_in
*ain_next
;
5506 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5507 * queued for every clearing peer, regardless of whether it is
5508 * relevant to the peer at hand.
5510 * Overview: There are 3 different indices which need to be
5511 * scrubbed, potentially, when a peer is removed:
5513 * 1 peer's routes visible via the RIB (ie accepted routes)
5514 * 2 peer's routes visible by the (optional) peer's adj-in index
5515 * 3 other routes visible by the peer's adj-out index
5517 * 3 there is no hurry in scrubbing, once the struct peer is
5518 * removed from bgp->peer, we could just GC such deleted peer's
5519 * adj-outs at our leisure.
5521 * 1 and 2 must be 'scrubbed' in some way, at least made
5522 * invisible via RIB index before peer session is allowed to be
5523 * brought back up. So one needs to know when such a 'search' is
5528 * - there'd be a single global queue or a single RIB walker
5529 * - rather than tracking which route_nodes still need to be
5530 * examined on a peer basis, we'd track which peers still
5533 * Given that our per-peer prefix-counts now should be reliable,
5534 * this may actually be achievable. It doesn't seem to be a huge
5535 * problem at this time,
5537 * It is possible that we have multiple paths for a prefix from
5539 * if that peer is using AddPath.
5543 ain_next
= ain
->next
;
5545 if (ain
->peer
== peer
)
5546 bgp_adj_in_remove(dest
, ain
);
5551 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5553 if (pi
->peer
!= peer
)
5557 bgp_path_info_reap(dest
, pi
);
5559 struct bgp_clear_node_queue
*cnq
;
5561 /* both unlocked in bgp_clear_node_queue_del */
5562 bgp_table_lock(bgp_dest_table(dest
));
5563 bgp_dest_lock_node(dest
);
5565 MTYPE_BGP_CLEAR_NODE_QUEUE
,
5566 sizeof(struct bgp_clear_node_queue
));
5568 work_queue_add(peer
->clear_node_queue
, cnq
);
5576 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5578 struct bgp_dest
*dest
;
5579 struct bgp_table
*table
;
5581 if (peer
->clear_node_queue
== NULL
)
5582 bgp_clear_node_queue_init(peer
);
5584 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5585 * Idle until it receives a Clearing_Completed event. This protects
5586 * against peers which flap faster than we can we clear, which could
5589 * a) race with routes from the new session being installed before
5590 * clear_route_node visits the node (to delete the route of that
5592 * b) resource exhaustion, clear_route_node likely leads to an entry
5593 * on the process_main queue. Fast-flapping could cause that queue
5597 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5598 * the unlock will happen upon work-queue completion; other wise, the
5599 * unlock happens at the end of this function.
5601 if (!peer
->clear_node_queue
->thread
)
5604 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
5605 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
5607 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5608 dest
= bgp_route_next(dest
)) {
5609 table
= bgp_dest_get_bgp_table_info(dest
);
5613 bgp_clear_route_table(peer
, afi
, safi
, table
);
5616 /* unlock if no nodes got added to the clear-node-queue. */
5617 if (!peer
->clear_node_queue
->thread
)
5621 void bgp_clear_route_all(struct peer
*peer
)
5626 FOREACH_AFI_SAFI (afi
, safi
)
5627 bgp_clear_route(peer
, afi
, safi
);
5629 #ifdef ENABLE_BGP_VNC
5630 rfapiProcessPeerDown(peer
);
5634 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5636 struct bgp_table
*table
;
5637 struct bgp_dest
*dest
;
5638 struct bgp_adj_in
*ain
;
5639 struct bgp_adj_in
*ain_next
;
5641 table
= peer
->bgp
->rib
[afi
][safi
];
5643 /* It is possible that we have multiple paths for a prefix from a peer
5644 * if that peer is using AddPath.
5646 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5650 ain_next
= ain
->next
;
5652 if (ain
->peer
== peer
)
5653 bgp_adj_in_remove(dest
, ain
);
5660 /* If any of the routes from the peer have been marked with the NO_LLGR
5661 * community, either as sent by the peer, or as the result of a configured
5662 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5663 * operation of [RFC4271].
5665 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5667 struct bgp_dest
*dest
;
5668 struct bgp_path_info
*pi
;
5669 struct bgp_table
*table
;
5671 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5672 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5673 dest
= bgp_route_next(dest
)) {
5674 struct bgp_dest
*rm
;
5676 /* look for neighbor in tables */
5677 table
= bgp_dest_get_bgp_table_info(dest
);
5681 for (rm
= bgp_table_top(table
); rm
;
5682 rm
= bgp_route_next(rm
))
5683 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
5685 if (pi
->peer
!= peer
)
5688 peer
->af_sflags
[afi
][safi
],
5689 PEER_STATUS_LLGR_WAIT
) &&
5690 bgp_attr_get_community(pi
->attr
) &&
5692 bgp_attr_get_community(
5696 if (!CHECK_FLAG(pi
->flags
,
5701 * If this is VRF leaked route
5702 * process for withdraw.
5705 BGP_ROUTE_IMPORTED
&&
5706 peer
->bgp
->inst_type
==
5707 BGP_INSTANCE_TYPE_DEFAULT
)
5708 vpn_leak_to_vrf_withdraw(pi
);
5710 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
5715 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5716 dest
= bgp_route_next(dest
))
5717 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5719 if (pi
->peer
!= peer
)
5721 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5722 PEER_STATUS_LLGR_WAIT
) &&
5723 bgp_attr_get_community(pi
->attr
) &&
5725 bgp_attr_get_community(pi
->attr
),
5728 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
5730 if (safi
== SAFI_UNICAST
&&
5731 (peer
->bgp
->inst_type
==
5732 BGP_INSTANCE_TYPE_VRF
||
5733 peer
->bgp
->inst_type
==
5734 BGP_INSTANCE_TYPE_DEFAULT
))
5735 vpn_leak_from_vrf_withdraw(
5736 bgp_get_default(), peer
->bgp
,
5739 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5745 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5747 struct bgp_dest
*dest
, *ndest
;
5748 struct bgp_path_info
*pi
;
5749 struct bgp_table
*table
;
5751 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5752 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5753 dest
= bgp_route_next(dest
)) {
5754 table
= bgp_dest_get_bgp_table_info(dest
);
5758 for (ndest
= bgp_table_top(table
); ndest
;
5759 ndest
= bgp_route_next(ndest
)) {
5760 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5762 if (pi
->peer
!= peer
)
5766 peer
->af_sflags
[afi
][safi
],
5767 PEER_STATUS_ENHANCED_REFRESH
))
5768 && !CHECK_FLAG(pi
->flags
,
5772 BGP_PATH_UNUSEABLE
)) {
5773 if (bgp_debug_neighbor_events(
5776 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5780 bgp_dest_get_prefix(
5783 bgp_path_info_set_flag(
5791 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5792 dest
= bgp_route_next(dest
)) {
5793 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5795 if (pi
->peer
!= peer
)
5798 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5799 PEER_STATUS_ENHANCED_REFRESH
))
5800 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5801 && !CHECK_FLAG(pi
->flags
,
5802 BGP_PATH_UNUSEABLE
)) {
5803 if (bgp_debug_neighbor_events(peer
))
5805 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5808 bgp_dest_get_prefix(
5811 bgp_path_info_set_flag(dest
, pi
,
5819 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5821 if (peer
->sort
== BGP_PEER_IBGP
)
5824 if (peer
->sort
== BGP_PEER_EBGP
5825 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5826 || FILTER_LIST_OUT_NAME(filter
)
5827 || DISTRIBUTE_OUT_NAME(filter
)))
5832 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5834 if (peer
->sort
== BGP_PEER_IBGP
)
5837 if (peer
->sort
== BGP_PEER_EBGP
5838 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5839 || FILTER_LIST_IN_NAME(filter
)
5840 || DISTRIBUTE_IN_NAME(filter
)))
5845 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5848 struct bgp_dest
*dest
;
5849 struct bgp_path_info
*pi
;
5850 struct bgp_path_info
*next
;
5852 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5853 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5854 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5858 /* Unimport EVPN routes from VRFs */
5859 if (safi
== SAFI_EVPN
)
5860 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5863 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5864 && pi
->type
== ZEBRA_ROUTE_BGP
5865 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5866 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5867 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5869 if (bgp_fibupd_safi(safi
))
5870 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5873 bgp_path_info_reap(dest
, pi
);
5877 /* Delete all kernel routes. */
5878 void bgp_cleanup_routes(struct bgp
*bgp
)
5881 struct bgp_dest
*dest
;
5882 struct bgp_table
*table
;
5884 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5885 if (afi
== AFI_L2VPN
)
5887 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5890 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5892 if (afi
!= AFI_L2VPN
) {
5894 safi
= SAFI_MPLS_VPN
;
5895 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5896 dest
= bgp_route_next(dest
)) {
5897 table
= bgp_dest_get_bgp_table_info(dest
);
5898 if (table
!= NULL
) {
5899 bgp_cleanup_table(bgp
, table
, safi
);
5900 bgp_table_finish(&table
);
5901 bgp_dest_set_bgp_table_info(dest
, NULL
);
5902 bgp_dest_unlock_node(dest
);
5906 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5907 dest
= bgp_route_next(dest
)) {
5908 table
= bgp_dest_get_bgp_table_info(dest
);
5909 if (table
!= NULL
) {
5910 bgp_cleanup_table(bgp
, table
, safi
);
5911 bgp_table_finish(&table
);
5912 bgp_dest_set_bgp_table_info(dest
, NULL
);
5913 bgp_dest_unlock_node(dest
);
5918 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5919 dest
= bgp_route_next(dest
)) {
5920 table
= bgp_dest_get_bgp_table_info(dest
);
5921 if (table
!= NULL
) {
5922 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5923 bgp_table_finish(&table
);
5924 bgp_dest_set_bgp_table_info(dest
, NULL
);
5925 bgp_dest_unlock_node(dest
);
5930 void bgp_reset(void)
5933 bgp_zclient_reset();
5934 access_list_reset();
5935 prefix_list_reset();
5938 bool bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5940 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5941 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5942 PEER_CAP_ADDPATH_AF_TX_RCV
));
5945 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5947 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5948 struct bgp_nlri
*packet
)
5956 bool addpath_capable
;
5957 uint32_t addpath_id
;
5960 lim
= pnt
+ packet
->length
;
5962 safi
= packet
->safi
;
5964 addpath_capable
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5966 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5967 syntactic validity. If the field is syntactically incorrect,
5968 then the Error Subcode is set to Invalid Network Field. */
5969 for (; pnt
< lim
; pnt
+= psize
) {
5970 /* Clear prefix structure. */
5971 memset(&p
, 0, sizeof(p
));
5973 if (addpath_capable
) {
5975 /* When packet overflow occurs return immediately. */
5976 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5977 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5979 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5980 addpath_id
= ntohl(addpath_id
);
5981 pnt
+= BGP_ADDPATH_ID_LEN
;
5984 /* Fetch prefix length. */
5985 p
.prefixlen
= *pnt
++;
5986 /* afi/safi validity already verified by caller,
5987 * bgp_update_receive */
5988 p
.family
= afi2family(afi
);
5990 /* Prefix length check. */
5991 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
5994 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5995 peer
->host
, p
.prefixlen
, packet
->afi
);
5996 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
5999 /* Packet size overflow check. */
6000 psize
= PSIZE(p
.prefixlen
);
6002 /* When packet overflow occur return immediately. */
6003 if (pnt
+ psize
> lim
) {
6006 "%s [Error] Update packet error (prefix length %d overflows packet)",
6007 peer
->host
, p
.prefixlen
);
6008 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
6011 /* Defensive coding, double-check the psize fits in a struct
6012 * prefix for the v4 and v6 afi's and unicast/multicast */
6013 if (psize
> (ssize_t
)sizeof(p
.u
.val
)) {
6016 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
6017 peer
->host
, p
.prefixlen
, sizeof(p
.u
.val
));
6018 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6021 /* Fetch prefix from NLRI packet. */
6022 memcpy(p
.u
.val
, pnt
, psize
);
6024 /* Check address. */
6025 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
6026 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
6027 /* From RFC4271 Section 6.3:
6029 * If a prefix in the NLRI field is semantically
6031 * (e.g., an unexpected multicast IP address),
6033 * be logged locally, and the prefix SHOULD be
6038 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6039 peer
->host
, &p
.u
.prefix4
);
6044 /* Check address. */
6045 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
6046 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6049 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6050 peer
->host
, &p
.u
.prefix6
);
6054 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
6057 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6058 peer
->host
, &p
.u
.prefix6
);
6064 /* Normal process. */
6066 bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
6067 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
,
6070 bgp_withdraw(peer
, &p
, addpath_id
, afi
, safi
,
6071 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
,
6074 /* Do not send BGP notification twice when maximum-prefix count
6076 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
6077 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
6080 /* Packet length consistency check. */
6084 "%s [Error] Update packet error (prefix length mismatch with total length)",
6086 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6089 return BGP_NLRI_PARSE_OK
;
6092 static struct bgp_static
*bgp_static_new(void)
6094 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
6097 static void bgp_static_free(struct bgp_static
*bgp_static
)
6099 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6100 route_map_counter_decrement(bgp_static
->rmap
.map
);
6102 if (bgp_static
->prd_pretty
)
6103 XFREE(MTYPE_BGP
, bgp_static
->prd_pretty
);
6104 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
6105 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
6108 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
6109 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
6111 struct bgp_dest
*dest
;
6112 struct bgp_path_info
*pi
;
6113 struct bgp_path_info
*new;
6114 struct bgp_path_info rmap_path
;
6116 struct attr
*attr_new
;
6117 route_map_result_t ret
;
6118 #ifdef ENABLE_BGP_VNC
6119 int vnc_implicit_withdraw
= 0;
6124 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6126 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6128 attr
.nexthop
= bgp_static
->igpnexthop
;
6129 attr
.med
= bgp_static
->igpmetric
;
6130 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6133 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
6135 if (bgp_static
->igpmetric
)
6136 bgp_attr_set_aigp_metric(&attr
, bgp_static
->igpmetric
);
6138 if (bgp_static
->atomic
)
6139 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
6141 /* Store label index, if required. */
6142 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
6143 attr
.label_index
= bgp_static
->label_index
;
6144 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
6147 /* Apply route-map. */
6148 if (bgp_static
->rmap
.name
) {
6149 struct attr attr_tmp
= attr
;
6151 memset(&rmap_path
, 0, sizeof(rmap_path
));
6152 rmap_path
.peer
= bgp
->peer_self
;
6153 rmap_path
.attr
= &attr_tmp
;
6155 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6157 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6159 bgp
->peer_self
->rmap_type
= 0;
6161 if (ret
== RMAP_DENYMATCH
) {
6162 /* Free uninterned attribute. */
6163 bgp_attr_flush(&attr_tmp
);
6165 /* Unintern original. */
6166 aspath_unintern(&attr
.aspath
);
6167 bgp_static_withdraw(bgp
, p
, afi
, safi
);
6168 bgp_dest_unlock_node(dest
);
6172 if (bgp_in_graceful_shutdown(bgp
))
6173 bgp_attr_add_gshut_community(&attr_tmp
);
6175 attr_new
= bgp_attr_intern(&attr_tmp
);
6178 if (bgp_in_graceful_shutdown(bgp
))
6179 bgp_attr_add_gshut_community(&attr
);
6181 attr_new
= bgp_attr_intern(&attr
);
6184 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6185 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6186 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6190 if (attrhash_cmp(pi
->attr
, attr_new
)
6191 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
6192 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
6193 bgp_dest_unlock_node(dest
);
6194 bgp_attr_unintern(&attr_new
);
6195 aspath_unintern(&attr
.aspath
);
6198 /* The attribute is changed. */
6199 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6201 /* Rewrite BGP route information. */
6202 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6203 bgp_path_info_restore(dest
, pi
);
6205 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6206 #ifdef ENABLE_BGP_VNC
6207 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6208 && (safi
== SAFI_UNICAST
)) {
6209 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
6211 * Implicit withdraw case.
6212 * We have to do this before pi is
6215 ++vnc_implicit_withdraw
;
6216 vnc_import_bgp_del_route(bgp
, p
, pi
);
6217 vnc_import_bgp_exterior_del_route(
6222 bgp_attr_unintern(&pi
->attr
);
6223 pi
->attr
= attr_new
;
6224 pi
->uptime
= monotime(NULL
);
6225 #ifdef ENABLE_BGP_VNC
6226 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6227 && (safi
== SAFI_UNICAST
)) {
6228 if (vnc_implicit_withdraw
) {
6229 vnc_import_bgp_add_route(bgp
, p
, pi
);
6230 vnc_import_bgp_exterior_add_route(
6236 /* Nexthop reachability check. */
6237 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6238 && (safi
== SAFI_UNICAST
6239 || safi
== SAFI_LABELED_UNICAST
)) {
6241 struct bgp
*bgp_nexthop
= bgp
;
6243 if (pi
->extra
&& pi
->extra
->bgp_orig
)
6244 bgp_nexthop
= pi
->extra
->bgp_orig
;
6246 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
6247 afi
, safi
, pi
, NULL
,
6249 bgp_path_info_set_flag(dest
, pi
,
6252 if (BGP_DEBUG(nht
, NHT
)) {
6253 char buf1
[INET6_ADDRSTRLEN
];
6254 inet_ntop(p
->family
,
6258 "%s(%s): Route not in table, not advertising",
6261 bgp_path_info_unset_flag(
6262 dest
, pi
, BGP_PATH_VALID
);
6265 /* Delete the NHT structure if any, if we're
6267 * enabling/disabling import check. We
6268 * deregister the route
6269 * from NHT to avoid overloading NHT and the
6270 * process interaction
6272 bgp_unlink_nexthop(pi
);
6273 bgp_path_info_set_flag(dest
, pi
,
6276 /* Process change. */
6277 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6278 bgp_process(bgp
, dest
, afi
, safi
);
6280 if (SAFI_UNICAST
== safi
6281 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6283 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6284 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
6288 bgp_dest_unlock_node(dest
);
6289 aspath_unintern(&attr
.aspath
);
6294 /* Make new BGP info. */
6295 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6297 /* Nexthop reachability check. */
6298 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6299 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
6300 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0,
6302 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6304 if (BGP_DEBUG(nht
, NHT
)) {
6305 char buf1
[INET6_ADDRSTRLEN
];
6307 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
6310 "%s(%s): Route not in table, not advertising",
6313 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
6316 /* Delete the NHT structure if any, if we're toggling between
6317 * enabling/disabling import check. We deregister the route
6318 * from NHT to avoid overloading NHT and the process interaction
6320 bgp_unlink_nexthop(new);
6322 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6325 /* Aggregate address increment. */
6326 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6328 /* Register new BGP information. */
6329 bgp_path_info_add(dest
, new);
6331 /* route_node_get lock */
6332 bgp_dest_unlock_node(dest
);
6334 /* Process change. */
6335 bgp_process(bgp
, dest
, afi
, safi
);
6337 if (SAFI_UNICAST
== safi
6338 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6339 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6340 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6343 /* Unintern original. */
6344 aspath_unintern(&attr
.aspath
);
6347 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6350 struct bgp_dest
*dest
;
6351 struct bgp_path_info
*pi
;
6353 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6355 /* Check selected route and self inserted route. */
6356 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6357 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6358 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6361 /* Withdraw static BGP route from routing table. */
6363 if (SAFI_UNICAST
== safi
6364 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6365 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6366 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
6368 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6369 bgp_unlink_nexthop(pi
);
6370 bgp_path_info_delete(dest
, pi
);
6371 bgp_process(bgp
, dest
, afi
, safi
);
6374 /* Unlock bgp_node_lookup. */
6375 bgp_dest_unlock_node(dest
);
6379 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6381 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
6382 afi_t afi
, safi_t safi
,
6383 struct prefix_rd
*prd
)
6385 struct bgp_dest
*dest
;
6386 struct bgp_path_info
*pi
;
6388 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
6390 /* Check selected route and self inserted route. */
6391 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6392 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6393 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6396 /* Withdraw static BGP route from routing table. */
6398 #ifdef ENABLE_BGP_VNC
6399 rfapiProcessWithdraw(
6400 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
6401 1); /* Kill, since it is an administrative change */
6403 if (SAFI_MPLS_VPN
== safi
6404 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6405 vpn_leak_to_vrf_withdraw(pi
);
6407 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6408 bgp_path_info_delete(dest
, pi
);
6409 bgp_process(bgp
, dest
, afi
, safi
);
6412 /* Unlock bgp_node_lookup. */
6413 bgp_dest_unlock_node(dest
);
6416 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
6417 struct bgp_static
*bgp_static
, afi_t afi
,
6420 struct bgp_dest
*dest
;
6421 struct bgp_path_info
*new;
6422 struct attr
*attr_new
;
6423 struct attr attr
= {0};
6424 struct bgp_path_info
*pi
;
6425 #ifdef ENABLE_BGP_VNC
6426 mpls_label_t label
= 0;
6428 uint32_t num_labels
= 0;
6432 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
6434 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
6437 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6439 attr
.nexthop
= bgp_static
->igpnexthop
;
6440 attr
.med
= bgp_static
->igpmetric
;
6441 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6443 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
6444 || (safi
== SAFI_ENCAP
)) {
6445 if (afi
== AFI_IP
) {
6446 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
6447 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
6450 if (afi
== AFI_L2VPN
) {
6451 if (bgp_static
->gatewayIp
.family
== AF_INET
) {
6452 SET_IPADDR_V4(&attr
.evpn_overlay
.gw_ip
);
6453 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v4
,
6454 &bgp_static
->gatewayIp
.u
.prefix4
,
6456 } else if (bgp_static
->gatewayIp
.family
== AF_INET6
) {
6457 SET_IPADDR_V6(&attr
.evpn_overlay
.gw_ip
);
6458 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v6
,
6459 &bgp_static
->gatewayIp
.u
.prefix6
,
6462 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
6463 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
6464 struct bgp_encap_type_vxlan bet
;
6465 memset(&bet
, 0, sizeof(bet
));
6466 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
6467 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
6469 if (bgp_static
->router_mac
) {
6470 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
6473 /* Apply route-map. */
6474 if (bgp_static
->rmap
.name
) {
6475 struct attr attr_tmp
= attr
;
6476 struct bgp_path_info rmap_path
;
6477 route_map_result_t ret
;
6479 rmap_path
.peer
= bgp
->peer_self
;
6480 rmap_path
.attr
= &attr_tmp
;
6482 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6484 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6486 bgp
->peer_self
->rmap_type
= 0;
6488 if (ret
== RMAP_DENYMATCH
) {
6489 /* Free uninterned attribute. */
6490 bgp_attr_flush(&attr_tmp
);
6492 /* Unintern original. */
6493 aspath_unintern(&attr
.aspath
);
6494 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
6496 bgp_dest_unlock_node(dest
);
6500 attr_new
= bgp_attr_intern(&attr_tmp
);
6502 attr_new
= bgp_attr_intern(&attr
);
6505 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6506 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6507 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6511 if (attrhash_cmp(pi
->attr
, attr_new
)
6512 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
6513 bgp_dest_unlock_node(dest
);
6514 bgp_attr_unintern(&attr_new
);
6515 aspath_unintern(&attr
.aspath
);
6518 /* The attribute is changed. */
6519 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6521 /* Rewrite BGP route information. */
6522 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6523 bgp_path_info_restore(dest
, pi
);
6525 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6526 bgp_attr_unintern(&pi
->attr
);
6527 pi
->attr
= attr_new
;
6528 pi
->uptime
= monotime(NULL
);
6529 #ifdef ENABLE_BGP_VNC
6531 label
= decode_label(&pi
->extra
->label
[0]);
6534 /* Process change. */
6535 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6536 bgp_process(bgp
, dest
, afi
, safi
);
6538 if (SAFI_MPLS_VPN
== safi
6539 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6540 vpn_leak_to_vrf_update(bgp
, pi
,
6543 #ifdef ENABLE_BGP_VNC
6544 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
6545 pi
->attr
, afi
, safi
, pi
->type
,
6546 pi
->sub_type
, &label
);
6548 bgp_dest_unlock_node(dest
);
6549 aspath_unintern(&attr
.aspath
);
6555 /* Make new BGP info. */
6556 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6558 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6559 bgp_path_info_extra_get(new);
6561 new->extra
->label
[0] = bgp_static
->label
;
6562 new->extra
->num_labels
= num_labels
;
6564 #ifdef ENABLE_BGP_VNC
6565 label
= decode_label(&bgp_static
->label
);
6568 /* Aggregate address increment. */
6569 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6571 /* Register new BGP information. */
6572 bgp_path_info_add(dest
, new);
6573 /* route_node_get lock */
6574 bgp_dest_unlock_node(dest
);
6576 /* Process change. */
6577 bgp_process(bgp
, dest
, afi
, safi
);
6579 if (SAFI_MPLS_VPN
== safi
6580 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6581 vpn_leak_to_vrf_update(bgp
, new, &bgp_static
->prd
);
6583 #ifdef ENABLE_BGP_VNC
6584 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6585 safi
, new->type
, new->sub_type
, &label
);
6588 /* Unintern original. */
6589 aspath_unintern(&attr
.aspath
);
6592 /* Configure static BGP network. When user don't run zebra, static
6593 route should be installed as valid. */
6594 static int bgp_static_set(struct vty
*vty
, const char *negate
,
6595 const char *ip_str
, afi_t afi
, safi_t safi
,
6596 const char *rmap
, int backdoor
, uint32_t label_index
)
6598 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6601 struct bgp_static
*bgp_static
;
6602 struct bgp_dest
*dest
;
6603 uint8_t need_update
= 0;
6605 /* Convert IP prefix string to struct prefix. */
6606 ret
= str2prefix(ip_str
, &p
);
6608 vty_out(vty
, "%% Malformed prefix\n");
6609 return CMD_WARNING_CONFIG_FAILED
;
6611 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6612 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
6613 return CMD_WARNING_CONFIG_FAILED
;
6620 /* Set BGP static route configuration. */
6621 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6624 vty_out(vty
, "%% Can't find static route specified\n");
6625 return CMD_WARNING_CONFIG_FAILED
;
6628 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6630 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6631 && (label_index
!= bgp_static
->label_index
)) {
6633 "%% label-index doesn't match static route\n");
6634 bgp_dest_unlock_node(dest
);
6635 return CMD_WARNING_CONFIG_FAILED
;
6638 if ((rmap
&& bgp_static
->rmap
.name
)
6639 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6641 "%% route-map name doesn't match static route\n");
6642 bgp_dest_unlock_node(dest
);
6643 return CMD_WARNING_CONFIG_FAILED
;
6646 /* Update BGP RIB. */
6647 if (!bgp_static
->backdoor
)
6648 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6650 /* Clear configuration. */
6651 bgp_static_free(bgp_static
);
6652 bgp_dest_set_bgp_static_info(dest
, NULL
);
6653 bgp_dest_unlock_node(dest
);
6654 bgp_dest_unlock_node(dest
);
6657 /* Set BGP static route configuration. */
6658 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6659 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6661 /* Configuration change. */
6662 /* Label index cannot be changed. */
6663 if (bgp_static
->label_index
!= label_index
) {
6664 vty_out(vty
, "%% cannot change label-index\n");
6665 bgp_dest_unlock_node(dest
);
6666 return CMD_WARNING_CONFIG_FAILED
;
6669 /* Check previous routes are installed into BGP. */
6670 if (bgp_static
->valid
6671 && bgp_static
->backdoor
!= backdoor
)
6674 bgp_static
->backdoor
= backdoor
;
6677 XFREE(MTYPE_ROUTE_MAP_NAME
,
6678 bgp_static
->rmap
.name
);
6679 route_map_counter_decrement(
6680 bgp_static
->rmap
.map
);
6681 bgp_static
->rmap
.name
=
6682 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6683 bgp_static
->rmap
.map
=
6684 route_map_lookup_by_name(rmap
);
6685 route_map_counter_increment(
6686 bgp_static
->rmap
.map
);
6688 XFREE(MTYPE_ROUTE_MAP_NAME
,
6689 bgp_static
->rmap
.name
);
6690 route_map_counter_decrement(
6691 bgp_static
->rmap
.map
);
6692 bgp_static
->rmap
.map
= NULL
;
6693 bgp_static
->valid
= 0;
6695 bgp_dest_unlock_node(dest
);
6697 /* New configuration. */
6698 bgp_static
= bgp_static_new();
6699 bgp_static
->backdoor
= backdoor
;
6700 bgp_static
->valid
= 0;
6701 bgp_static
->igpmetric
= 0;
6702 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6703 bgp_static
->label_index
= label_index
;
6706 XFREE(MTYPE_ROUTE_MAP_NAME
,
6707 bgp_static
->rmap
.name
);
6708 route_map_counter_decrement(
6709 bgp_static
->rmap
.map
);
6710 bgp_static
->rmap
.name
=
6711 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6712 bgp_static
->rmap
.map
=
6713 route_map_lookup_by_name(rmap
);
6714 route_map_counter_increment(
6715 bgp_static
->rmap
.map
);
6717 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6720 bgp_static
->valid
= 1;
6722 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6724 if (!bgp_static
->backdoor
)
6725 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6731 void bgp_static_add(struct bgp
*bgp
)
6735 struct bgp_dest
*dest
;
6736 struct bgp_dest
*rm
;
6737 struct bgp_table
*table
;
6738 struct bgp_static
*bgp_static
;
6740 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6741 FOREACH_AFI_SAFI (afi
, safi
)
6742 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6743 dest
= bgp_route_next(dest
)) {
6744 if (!bgp_dest_has_bgp_path_info_data(dest
))
6747 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6748 || (safi
== SAFI_EVPN
)) {
6749 table
= bgp_dest_get_bgp_table_info(dest
);
6751 for (rm
= bgp_table_top(table
); rm
;
6752 rm
= bgp_route_next(rm
)) {
6754 bgp_dest_get_bgp_static_info(
6756 bgp_static_update_safi(
6757 bgp
, bgp_dest_get_prefix(rm
),
6758 bgp_static
, afi
, safi
);
6762 bgp
, bgp_dest_get_prefix(dest
),
6763 bgp_dest_get_bgp_static_info(dest
), afi
,
6767 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6770 /* Called from bgp_delete(). Delete all static routes from the BGP
6772 void bgp_static_delete(struct bgp
*bgp
)
6776 struct bgp_dest
*dest
;
6777 struct bgp_dest
*rm
;
6778 struct bgp_table
*table
;
6779 struct bgp_static
*bgp_static
;
6781 FOREACH_AFI_SAFI (afi
, safi
)
6782 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6783 dest
= bgp_route_next(dest
)) {
6784 if (!bgp_dest_has_bgp_path_info_data(dest
))
6787 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6788 || (safi
== SAFI_EVPN
)) {
6789 table
= bgp_dest_get_bgp_table_info(dest
);
6791 for (rm
= bgp_table_top(table
); rm
;
6792 rm
= bgp_route_next(rm
)) {
6794 bgp_dest_get_bgp_static_info(
6799 bgp_static_withdraw_safi(
6800 bgp
, bgp_dest_get_prefix(rm
),
6802 (struct prefix_rd
*)
6803 bgp_dest_get_prefix(
6805 bgp_static_free(bgp_static
);
6806 bgp_dest_set_bgp_static_info(rm
,
6808 bgp_dest_unlock_node(rm
);
6811 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6812 bgp_static_withdraw(bgp
,
6813 bgp_dest_get_prefix(dest
),
6815 bgp_static_free(bgp_static
);
6816 bgp_dest_set_bgp_static_info(dest
, NULL
);
6817 bgp_dest_unlock_node(dest
);
6822 void bgp_static_redo_import_check(struct bgp
*bgp
)
6826 struct bgp_dest
*dest
;
6827 struct bgp_dest
*rm
;
6828 struct bgp_table
*table
;
6829 struct bgp_static
*bgp_static
;
6831 /* Use this flag to force reprocessing of the route */
6832 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6833 FOREACH_AFI_SAFI (afi
, safi
) {
6834 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6835 dest
= bgp_route_next(dest
)) {
6836 if (!bgp_dest_has_bgp_path_info_data(dest
))
6839 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6840 || (safi
== SAFI_EVPN
)) {
6841 table
= bgp_dest_get_bgp_table_info(dest
);
6843 for (rm
= bgp_table_top(table
); rm
;
6844 rm
= bgp_route_next(rm
)) {
6846 bgp_dest_get_bgp_static_info(
6848 bgp_static_update_safi(
6849 bgp
, bgp_dest_get_prefix(rm
),
6850 bgp_static
, afi
, safi
);
6853 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6854 bgp_static_update(bgp
,
6855 bgp_dest_get_prefix(dest
),
6856 bgp_static
, afi
, safi
);
6860 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6863 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6866 struct bgp_table
*table
;
6867 struct bgp_dest
*dest
;
6868 struct bgp_path_info
*pi
;
6870 /* Do not install the aggregate route if BGP is in the
6871 * process of termination.
6873 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6874 || (bgp
->peer_self
== NULL
))
6877 table
= bgp
->rib
[afi
][safi
];
6878 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6879 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6880 if (pi
->peer
== bgp
->peer_self
6881 && ((pi
->type
== ZEBRA_ROUTE_BGP
6882 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6883 || (pi
->type
!= ZEBRA_ROUTE_BGP
6885 == BGP_ROUTE_REDISTRIBUTE
))) {
6886 bgp_aggregate_decrement(
6887 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6889 bgp_unlink_nexthop(pi
);
6890 bgp_path_info_delete(dest
, pi
);
6891 bgp_process(bgp
, dest
, afi
, safi
);
6898 * Purge all networks and redistributed routes from routing table.
6899 * Invoked upon the instance going down.
6901 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6906 FOREACH_AFI_SAFI (afi
, safi
)
6907 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6912 * Currently this is used to set static routes for VPN and ENCAP.
6913 * I think it can probably be factored with bgp_static_set.
6915 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6916 const char *ip_str
, const char *rd_str
,
6917 const char *label_str
, const char *rmap_str
,
6918 int evpn_type
, const char *esi
, const char *gwip
,
6919 const char *ethtag
, const char *routermac
)
6921 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6924 struct prefix_rd prd
;
6925 struct bgp_dest
*pdest
;
6926 struct bgp_dest
*dest
;
6927 struct bgp_table
*table
;
6928 struct bgp_static
*bgp_static
;
6929 mpls_label_t label
= MPLS_INVALID_LABEL
;
6930 struct prefix gw_ip
;
6932 /* validate ip prefix */
6933 ret
= str2prefix(ip_str
, &p
);
6935 vty_out(vty
, "%% Malformed prefix\n");
6936 return CMD_WARNING_CONFIG_FAILED
;
6939 if ((afi
== AFI_L2VPN
)
6940 && (bgp_build_evpn_prefix(evpn_type
,
6941 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6942 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6943 return CMD_WARNING_CONFIG_FAILED
;
6946 ret
= str2prefix_rd(rd_str
, &prd
);
6948 vty_out(vty
, "%% Malformed rd\n");
6949 return CMD_WARNING_CONFIG_FAILED
;
6953 unsigned long label_val
;
6954 label_val
= strtoul(label_str
, NULL
, 10);
6955 encode_label(label_val
, &label
);
6958 if (safi
== SAFI_EVPN
) {
6959 if (esi
&& str2esi(esi
, NULL
) == 0) {
6960 vty_out(vty
, "%% Malformed ESI\n");
6961 return CMD_WARNING_CONFIG_FAILED
;
6963 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6964 vty_out(vty
, "%% Malformed Router MAC\n");
6965 return CMD_WARNING_CONFIG_FAILED
;
6968 memset(&gw_ip
, 0, sizeof(gw_ip
));
6969 ret
= str2prefix(gwip
, &gw_ip
);
6971 vty_out(vty
, "%% Malformed GatewayIp\n");
6972 return CMD_WARNING_CONFIG_FAILED
;
6974 if ((gw_ip
.family
== AF_INET
6975 && is_evpn_prefix_ipaddr_v6(
6976 (struct prefix_evpn
*)&p
))
6977 || (gw_ip
.family
== AF_INET6
6978 && is_evpn_prefix_ipaddr_v4(
6979 (struct prefix_evpn
*)&p
))) {
6981 "%% GatewayIp family differs with IP prefix\n");
6982 return CMD_WARNING_CONFIG_FAILED
;
6986 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6987 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6988 bgp_dest_set_bgp_table_info(pdest
,
6989 bgp_table_init(bgp
, afi
, safi
));
6990 table
= bgp_dest_get_bgp_table_info(pdest
);
6992 dest
= bgp_node_get(table
, &p
);
6994 if (bgp_dest_has_bgp_path_info_data(dest
)) {
6995 vty_out(vty
, "%% Same network configuration exists\n");
6996 bgp_dest_unlock_node(dest
);
6998 /* New configuration. */
6999 bgp_static
= bgp_static_new();
7000 bgp_static
->backdoor
= 0;
7001 bgp_static
->valid
= 0;
7002 bgp_static
->igpmetric
= 0;
7003 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
7004 bgp_static
->label
= label
;
7005 bgp_static
->prd
= prd
;
7008 bgp_static
->prd_pretty
= XSTRDUP(MTYPE_BGP
, rd_str
);
7010 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
7011 route_map_counter_decrement(bgp_static
->rmap
.map
);
7012 bgp_static
->rmap
.name
=
7013 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
7014 bgp_static
->rmap
.map
=
7015 route_map_lookup_by_name(rmap_str
);
7016 route_map_counter_increment(bgp_static
->rmap
.map
);
7019 if (safi
== SAFI_EVPN
) {
7021 bgp_static
->eth_s_id
=
7024 str2esi(esi
, bgp_static
->eth_s_id
);
7027 bgp_static
->router_mac
=
7028 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
7029 (void)prefix_str2mac(routermac
,
7030 bgp_static
->router_mac
);
7033 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
7035 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
7037 bgp_static
->valid
= 1;
7038 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
7044 /* Configure static BGP network. */
7045 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
7046 const char *ip_str
, const char *rd_str
,
7047 const char *label_str
, int evpn_type
, const char *esi
,
7048 const char *gwip
, const char *ethtag
)
7050 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7053 struct prefix_rd prd
;
7054 struct bgp_dest
*pdest
;
7055 struct bgp_dest
*dest
;
7056 struct bgp_table
*table
;
7057 struct bgp_static
*bgp_static
;
7058 mpls_label_t label
= MPLS_INVALID_LABEL
;
7060 /* Convert IP prefix string to struct prefix. */
7061 ret
= str2prefix(ip_str
, &p
);
7063 vty_out(vty
, "%% Malformed prefix\n");
7064 return CMD_WARNING_CONFIG_FAILED
;
7067 if ((afi
== AFI_L2VPN
)
7068 && (bgp_build_evpn_prefix(evpn_type
,
7069 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
7070 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
7071 return CMD_WARNING_CONFIG_FAILED
;
7073 ret
= str2prefix_rd(rd_str
, &prd
);
7075 vty_out(vty
, "%% Malformed rd\n");
7076 return CMD_WARNING_CONFIG_FAILED
;
7080 unsigned long label_val
;
7081 label_val
= strtoul(label_str
, NULL
, 10);
7082 encode_label(label_val
, &label
);
7085 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7086 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7087 bgp_dest_set_bgp_table_info(pdest
,
7088 bgp_table_init(bgp
, afi
, safi
));
7090 bgp_dest_unlock_node(pdest
);
7091 table
= bgp_dest_get_bgp_table_info(pdest
);
7093 dest
= bgp_node_lookup(table
, &p
);
7096 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
7098 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
7099 bgp_static_free(bgp_static
);
7100 bgp_dest_set_bgp_static_info(dest
, NULL
);
7101 bgp_dest_unlock_node(dest
);
7102 bgp_dest_unlock_node(dest
);
7104 vty_out(vty
, "%% Can't find the route\n");
7109 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
7110 const char *rmap_name
)
7112 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7113 struct bgp_rmap
*rmap
;
7115 rmap
= &bgp
->table_map
[afi
][safi
];
7117 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7118 route_map_counter_decrement(rmap
->map
);
7119 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
7120 rmap
->map
= route_map_lookup_by_name(rmap_name
);
7121 route_map_counter_increment(rmap
->map
);
7123 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7124 route_map_counter_decrement(rmap
->map
);
7128 if (bgp_fibupd_safi(safi
))
7129 bgp_zebra_announce_table(bgp
, afi
, safi
);
7134 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
7135 const char *rmap_name
)
7137 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7138 struct bgp_rmap
*rmap
;
7140 rmap
= &bgp
->table_map
[afi
][safi
];
7141 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7142 route_map_counter_decrement(rmap
->map
);
7145 if (bgp_fibupd_safi(safi
))
7146 bgp_zebra_announce_table(bgp
, afi
, safi
);
7151 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
7154 if (bgp
->table_map
[afi
][safi
].name
) {
7155 vty_out(vty
, " table-map %s\n",
7156 bgp
->table_map
[afi
][safi
].name
);
7160 DEFUN (bgp_table_map
,
7163 "BGP table to RIB route download filter\n"
7164 "Name of the route map\n")
7167 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7168 argv
[idx_word
]->arg
);
7170 DEFUN (no_bgp_table_map
,
7171 no_bgp_table_map_cmd
,
7172 "no table-map WORD",
7174 "BGP table to RIB route download filter\n"
7175 "Name of the route map\n")
7178 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7179 argv
[idx_word
]->arg
);
7185 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
7186 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
7187 backdoor$backdoor}]",
7189 "Specify a network to announce via BGP\n"
7194 "Route-map to modify the attributes\n"
7195 "Name of the route map\n"
7196 "Label index to associate with the prefix\n"
7197 "Label index value\n"
7198 "Specify a BGP backdoor route\n")
7200 char addr_prefix_str
[BUFSIZ
];
7205 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
7207 sizeof(addr_prefix_str
));
7209 vty_out(vty
, "%% Inconsistent address and mask\n");
7210 return CMD_WARNING_CONFIG_FAILED
;
7214 return bgp_static_set(
7215 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
7216 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
7217 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7220 DEFPY(ipv6_bgp_network
,
7221 ipv6_bgp_network_cmd
,
7222 "[no] network X:X::X:X/M$prefix \
7223 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
7225 "Specify a network to announce via BGP\n"
7227 "Route-map to modify the attributes\n"
7228 "Name of the route map\n"
7229 "Label index to associate with the prefix\n"
7230 "Label index value\n")
7232 return bgp_static_set(
7233 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
7234 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7237 static struct bgp_aggregate
*bgp_aggregate_new(void)
7239 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
7242 void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
7244 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7245 route_map_counter_decrement(aggregate
->suppress_map
);
7246 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7247 route_map_counter_decrement(aggregate
->rmap
.map
);
7248 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
7252 * Helper function to avoid repeated code: prepare variables for a
7253 * `route_map_apply` call.
7255 * \returns `true` on route map match, otherwise `false`.
7257 static bool aggr_suppress_map_test(struct bgp
*bgp
,
7258 struct bgp_aggregate
*aggregate
,
7259 struct bgp_path_info
*pi
)
7261 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
7262 route_map_result_t rmr
= RMAP_DENYMATCH
;
7263 struct bgp_path_info rmap_path
= {};
7264 struct attr attr
= {};
7266 /* No route map entries created, just don't match. */
7267 if (aggregate
->suppress_map
== NULL
)
7270 /* Call route map matching and return result. */
7271 attr
.aspath
= aspath_empty(bgp
->asnotation
);
7272 rmap_path
.peer
= bgp
->peer_self
;
7273 rmap_path
.attr
= &attr
;
7275 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
7276 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
7277 bgp
->peer_self
->rmap_type
= 0;
7279 bgp_attr_flush(&attr
);
7280 aspath_unintern(&attr
.aspath
);
7282 return rmr
== RMAP_PERMITMATCH
;
7285 /** Test whether the aggregation has suppressed this path or not. */
7286 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
7287 struct bgp_path_info
*pi
)
7289 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
7292 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
7296 * Suppress this path and keep the reference.
7298 * \returns `true` if needs processing otherwise `false`.
7300 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
7301 struct bgp_path_info
*pi
)
7303 struct bgp_path_info_extra
*pie
;
7305 /* Path is already suppressed by this aggregation. */
7306 if (aggr_suppress_exists(aggregate
, pi
))
7309 pie
= bgp_path_info_extra_get(pi
);
7311 /* This is the first suppression, allocate memory and list it. */
7312 if (pie
->aggr_suppressors
== NULL
)
7313 pie
->aggr_suppressors
= list_new();
7315 listnode_add(pie
->aggr_suppressors
, aggregate
);
7317 /* Only mark for processing if suppressed. */
7318 if (listcount(pie
->aggr_suppressors
) == 1) {
7319 if (BGP_DEBUG(update
, UPDATE_OUT
))
7320 zlog_debug("aggregate-address suppressing: %pFX",
7321 bgp_dest_get_prefix(pi
->net
));
7323 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7331 * Unsuppress this path and remove the reference.
7333 * \returns `true` if needs processing otherwise `false`.
7335 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
7336 struct bgp_path_info
*pi
)
7338 /* Path wasn't suppressed. */
7339 if (!aggr_suppress_exists(aggregate
, pi
))
7342 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
7344 /* Unsuppress and free extra memory if last item. */
7345 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
7346 if (BGP_DEBUG(update
, UPDATE_OUT
))
7347 zlog_debug("aggregate-address unsuppressing: %pFX",
7348 bgp_dest_get_prefix(pi
->net
));
7350 list_delete(&pi
->extra
->aggr_suppressors
);
7351 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7358 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
7359 struct aspath
*aspath
,
7360 struct community
*comm
,
7361 struct ecommunity
*ecomm
,
7362 struct lcommunity
*lcomm
)
7364 static struct aspath
*ae
= NULL
;
7365 enum asnotation_mode asnotation
;
7367 asnotation
= bgp_get_asnotation(NULL
);
7370 ae
= aspath_empty(asnotation
);
7375 if (origin
!= pi
->attr
->origin
)
7378 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
7381 if (!community_cmp(bgp_attr_get_community(pi
->attr
), comm
))
7384 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi
->attr
), ecomm
))
7387 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi
->attr
), lcomm
))
7390 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
7396 static void bgp_aggregate_install(
7397 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
7398 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
7399 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
7400 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
7402 struct bgp_dest
*dest
;
7403 struct bgp_table
*table
;
7404 struct bgp_path_info
*pi
, *orig
, *new;
7407 table
= bgp
->rib
[afi
][safi
];
7409 dest
= bgp_node_get(table
, p
);
7411 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7412 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
7413 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7417 * If we have paths with different MEDs, then don't install
7418 * (or uninstall) the aggregate route.
7420 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
7421 goto uninstall_aggregate_route
;
7423 if (aggregate
->count
> 0) {
7425 * If the aggregate information has not changed
7426 * no need to re-install it again.
7428 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
7429 ecommunity
, lcommunity
)) {
7430 bgp_dest_unlock_node(dest
);
7433 aspath_free(aspath
);
7435 community_free(&community
);
7437 ecommunity_free(&ecommunity
);
7439 lcommunity_free(&lcommunity
);
7445 * Mark the old as unusable
7448 bgp_path_info_delete(dest
, pi
);
7450 attr
= bgp_attr_aggregate_intern(
7451 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
7452 aggregate
, atomic_aggregate
, p
);
7455 aspath_free(aspath
);
7456 community_free(&community
);
7457 ecommunity_free(&ecommunity
);
7458 lcommunity_free(&lcommunity
);
7459 bgp_dest_unlock_node(dest
);
7460 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
7461 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
7462 zlog_debug("%s: %pFX null attribute", __func__
,
7467 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
7468 bgp
->peer_self
, attr
, dest
);
7470 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7472 bgp_path_info_add(dest
, new);
7473 bgp_process(bgp
, dest
, afi
, safi
);
7475 uninstall_aggregate_route
:
7476 for (pi
= orig
; pi
; pi
= pi
->next
)
7477 if (pi
->peer
== bgp
->peer_self
7478 && pi
->type
== ZEBRA_ROUTE_BGP
7479 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7482 /* Withdraw static BGP route from routing table. */
7484 bgp_path_info_delete(dest
, pi
);
7485 bgp_process(bgp
, dest
, afi
, safi
);
7489 bgp_dest_unlock_node(dest
);
7493 * Check if the current path has different MED than other known paths.
7495 * \returns `true` if the MED matched the others else `false`.
7497 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
7498 struct bgp
*bgp
, struct bgp_path_info
*pi
)
7500 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
7502 /* This is the first route being analyzed. */
7503 if (!aggregate
->med_initialized
) {
7504 aggregate
->med_initialized
= true;
7505 aggregate
->med_mismatched
= false;
7506 aggregate
->med_matched_value
= cur_med
;
7508 /* Check if routes with different MED showed up. */
7509 if (cur_med
!= aggregate
->med_matched_value
)
7510 aggregate
->med_mismatched
= true;
7513 return !aggregate
->med_mismatched
;
7517 * Initializes and tests all routes in the aggregate address path for MED
7520 * \returns `true` if all MEDs are the same otherwise `false`.
7522 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
7523 struct bgp
*bgp
, const struct prefix
*p
,
7524 afi_t afi
, safi_t safi
)
7526 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7527 const struct prefix
*dest_p
;
7528 struct bgp_dest
*dest
, *top
;
7529 struct bgp_path_info
*pi
;
7530 bool med_matched
= true;
7532 aggregate
->med_initialized
= false;
7534 top
= bgp_node_get(table
, p
);
7535 for (dest
= bgp_node_get(table
, p
); dest
;
7536 dest
= bgp_route_next_until(dest
, top
)) {
7537 dest_p
= bgp_dest_get_prefix(dest
);
7538 if (dest_p
->prefixlen
<= p
->prefixlen
)
7541 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7542 if (BGP_PATH_HOLDDOWN(pi
))
7544 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7546 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
7547 med_matched
= false;
7554 bgp_dest_unlock_node(top
);
7560 * Toggles the route suppression status for this aggregate address
7563 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
7564 struct bgp
*bgp
, const struct prefix
*p
,
7565 afi_t afi
, safi_t safi
, bool suppress
)
7567 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7568 const struct prefix
*dest_p
;
7569 struct bgp_dest
*dest
, *top
;
7570 struct bgp_path_info
*pi
;
7571 bool toggle_suppression
;
7573 /* We've found a different MED we must revert any suppressed routes. */
7574 top
= bgp_node_get(table
, p
);
7575 for (dest
= bgp_node_get(table
, p
); dest
;
7576 dest
= bgp_route_next_until(dest
, top
)) {
7577 dest_p
= bgp_dest_get_prefix(dest
);
7578 if (dest_p
->prefixlen
<= p
->prefixlen
)
7581 toggle_suppression
= false;
7582 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7583 if (BGP_PATH_HOLDDOWN(pi
))
7585 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7588 /* We are toggling suppression back. */
7590 /* Suppress route if not suppressed already. */
7591 if (aggr_suppress_path(aggregate
, pi
))
7592 toggle_suppression
= true;
7596 /* Install route if there is no more suppression. */
7597 if (aggr_unsuppress_path(aggregate
, pi
))
7598 toggle_suppression
= true;
7601 if (toggle_suppression
)
7602 bgp_process(bgp
, dest
, afi
, safi
);
7604 bgp_dest_unlock_node(top
);
7608 * Aggregate address MED matching incremental test: this function is called
7609 * when the initial aggregation occurred and we are only testing a single
7612 * In addition to testing and setting the MED validity it also installs back
7613 * suppressed routes (if summary is configured).
7615 * Must not be called in `bgp_aggregate_route`.
7617 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7618 struct bgp
*bgp
, const struct prefix
*p
,
7619 afi_t afi
, safi_t safi
,
7620 struct bgp_path_info
*pi
)
7622 /* MED matching disabled. */
7623 if (!aggregate
->match_med
)
7626 /* Aggregation with different MED, recheck if we have got equal MEDs
7629 if (aggregate
->med_mismatched
&&
7630 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
) &&
7631 aggregate
->summary_only
)
7632 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
,
7635 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7637 /* No mismatches, just quit. */
7638 if (!aggregate
->med_mismatched
)
7641 /* Route summarization is disabled. */
7642 if (!aggregate
->summary_only
)
7645 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7648 /* Update an aggregate as routes are added/removed from the BGP table */
7649 bool bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7650 safi_t safi
, struct bgp_aggregate
*aggregate
)
7652 struct bgp_table
*table
;
7653 struct bgp_dest
*top
;
7654 struct bgp_dest
*dest
;
7656 struct aspath
*aspath
= NULL
;
7657 struct community
*community
= NULL
;
7658 struct ecommunity
*ecommunity
= NULL
;
7659 struct lcommunity
*lcommunity
= NULL
;
7660 struct bgp_path_info
*pi
;
7661 unsigned long match
= 0;
7662 uint8_t atomic_aggregate
= 0;
7664 /* If the bgp instance is being deleted or self peer is deleted
7665 * then do not create aggregate route
7667 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
7668 bgp
->peer_self
== NULL
)
7671 /* Initialize and test routes for MED difference. */
7672 if (aggregate
->match_med
)
7673 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7676 * Reset aggregate count: we might've been called from route map
7677 * update so in that case we must retest all more specific routes.
7679 * \see `bgp_route_map_process_update`.
7681 aggregate
->count
= 0;
7682 aggregate
->incomplete_origin_count
= 0;
7683 aggregate
->incomplete_origin_count
= 0;
7684 aggregate
->egp_origin_count
= 0;
7686 /* ORIGIN attribute: If at least one route among routes that are
7687 aggregated has ORIGIN with the value INCOMPLETE, then the
7688 aggregated route must have the ORIGIN attribute with the value
7689 INCOMPLETE. Otherwise, if at least one route among routes that
7690 are aggregated has ORIGIN with the value EGP, then the aggregated
7691 route must have the origin attribute with the value EGP. In all
7692 other case the value of the ORIGIN attribute of the aggregated
7693 route is INTERNAL. */
7694 origin
= BGP_ORIGIN_IGP
;
7696 table
= bgp
->rib
[afi
][safi
];
7698 top
= bgp_node_get(table
, p
);
7699 for (dest
= bgp_node_get(table
, p
); dest
;
7700 dest
= bgp_route_next_until(dest
, top
)) {
7701 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7703 if (dest_p
->prefixlen
<= p
->prefixlen
)
7706 /* If suppress fib is enabled and route not installed
7707 * in FIB, skip the route
7709 if (!bgp_check_advertise(bgp
, dest
))
7714 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7715 if (BGP_PATH_HOLDDOWN(pi
))
7719 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7720 atomic_aggregate
= 1;
7722 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7726 * summary-only aggregate route suppress
7727 * aggregated route announcements.
7730 * Don't create summaries if MED didn't match
7731 * otherwise neither the specific routes and the
7732 * aggregation will be announced.
7734 if (aggregate
->summary_only
7735 && AGGREGATE_MED_VALID(aggregate
)) {
7736 if (aggr_suppress_path(aggregate
, pi
))
7741 * Suppress more specific routes that match the route
7745 * Don't suppress routes if MED matching is enabled and
7746 * it mismatched otherwise we might end up with no
7747 * routes for this path.
7749 if (aggregate
->suppress_map_name
7750 && AGGREGATE_MED_VALID(aggregate
)
7751 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7752 if (aggr_suppress_path(aggregate
, pi
))
7759 * If at least one route among routes that are
7760 * aggregated has ORIGIN with the value INCOMPLETE,
7761 * then the aggregated route MUST have the ORIGIN
7762 * attribute with the value INCOMPLETE. Otherwise, if
7763 * at least one route among routes that are aggregated
7764 * has ORIGIN with the value EGP, then the aggregated
7765 * route MUST have the ORIGIN attribute with the value
7768 switch (pi
->attr
->origin
) {
7769 case BGP_ORIGIN_INCOMPLETE
:
7770 aggregate
->incomplete_origin_count
++;
7772 case BGP_ORIGIN_EGP
:
7773 aggregate
->egp_origin_count
++;
7781 if (!aggregate
->as_set
)
7785 * as-set aggregate route generate origin, as path,
7786 * and community aggregation.
7788 /* Compute aggregate route's as-path.
7790 bgp_compute_aggregate_aspath_hash(aggregate
,
7793 /* Compute aggregate route's community.
7795 if (bgp_attr_get_community(pi
->attr
))
7796 bgp_compute_aggregate_community_hash(
7798 bgp_attr_get_community(pi
->attr
));
7800 /* Compute aggregate route's extended community.
7802 if (bgp_attr_get_ecommunity(pi
->attr
))
7803 bgp_compute_aggregate_ecommunity_hash(
7805 bgp_attr_get_ecommunity(pi
->attr
));
7807 /* Compute aggregate route's large community.
7809 if (bgp_attr_get_lcommunity(pi
->attr
))
7810 bgp_compute_aggregate_lcommunity_hash(
7812 bgp_attr_get_lcommunity(pi
->attr
));
7815 bgp_process(bgp
, dest
, afi
, safi
);
7817 if (aggregate
->as_set
) {
7818 bgp_compute_aggregate_aspath_val(aggregate
);
7819 bgp_compute_aggregate_community_val(aggregate
);
7820 bgp_compute_aggregate_ecommunity_val(aggregate
);
7821 bgp_compute_aggregate_lcommunity_val(aggregate
);
7825 bgp_dest_unlock_node(top
);
7828 if (aggregate
->incomplete_origin_count
> 0)
7829 origin
= BGP_ORIGIN_INCOMPLETE
;
7830 else if (aggregate
->egp_origin_count
> 0)
7831 origin
= BGP_ORIGIN_EGP
;
7833 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7834 origin
= aggregate
->origin
;
7836 if (aggregate
->as_set
) {
7837 if (aggregate
->aspath
)
7838 /* Retrieve aggregate route's as-path.
7840 aspath
= aspath_dup(aggregate
->aspath
);
7842 if (aggregate
->community
)
7843 /* Retrieve aggregate route's community.
7845 community
= community_dup(aggregate
->community
);
7847 if (aggregate
->ecommunity
)
7848 /* Retrieve aggregate route's ecommunity.
7850 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7852 if (aggregate
->lcommunity
)
7853 /* Retrieve aggregate route's lcommunity.
7855 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7858 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7859 ecommunity
, lcommunity
, atomic_aggregate
,
7865 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7866 safi_t safi
, struct bgp_aggregate
*aggregate
)
7868 struct bgp_table
*table
;
7869 struct bgp_dest
*top
;
7870 struct bgp_dest
*dest
;
7871 struct bgp_path_info
*pi
;
7872 unsigned long match
;
7874 table
= bgp
->rib
[afi
][safi
];
7876 /* If routes exists below this node, generate aggregate routes. */
7877 top
= bgp_node_get(table
, p
);
7878 for (dest
= bgp_node_get(table
, p
); dest
;
7879 dest
= bgp_route_next_until(dest
, top
)) {
7880 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7882 if (dest_p
->prefixlen
<= p
->prefixlen
)
7886 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7887 if (BGP_PATH_HOLDDOWN(pi
))
7890 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7894 * This route is suppressed: attempt to unsuppress it.
7896 * `aggr_unsuppress_path` will fail if this particular
7897 * aggregate route was not the suppressor.
7899 if (pi
->extra
&& pi
->extra
->aggr_suppressors
&&
7900 listcount(pi
->extra
->aggr_suppressors
)) {
7901 if (aggr_unsuppress_path(aggregate
, pi
))
7907 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7908 aggregate
->incomplete_origin_count
--;
7909 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7910 aggregate
->egp_origin_count
--;
7912 if (aggregate
->as_set
) {
7913 /* Remove as-path from aggregate.
7915 bgp_remove_aspath_from_aggregate_hash(
7919 if (bgp_attr_get_community(pi
->attr
))
7920 /* Remove community from aggregate.
7922 bgp_remove_comm_from_aggregate_hash(
7924 bgp_attr_get_community(
7927 if (bgp_attr_get_ecommunity(pi
->attr
))
7928 /* Remove ecommunity from aggregate.
7930 bgp_remove_ecomm_from_aggregate_hash(
7932 bgp_attr_get_ecommunity(
7935 if (bgp_attr_get_lcommunity(pi
->attr
))
7936 /* Remove lcommunity from aggregate.
7938 bgp_remove_lcomm_from_aggregate_hash(
7940 bgp_attr_get_lcommunity(
7945 /* If this node was suppressed, process the change. */
7947 bgp_process(bgp
, dest
, afi
, safi
);
7949 if (aggregate
->as_set
) {
7950 aspath_free(aggregate
->aspath
);
7951 aggregate
->aspath
= NULL
;
7952 if (aggregate
->community
)
7953 community_free(&aggregate
->community
);
7954 if (aggregate
->ecommunity
)
7955 ecommunity_free(&aggregate
->ecommunity
);
7956 if (aggregate
->lcommunity
)
7957 lcommunity_free(&aggregate
->lcommunity
);
7960 bgp_dest_unlock_node(top
);
7963 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7964 const struct prefix
*aggr_p
,
7965 struct bgp_path_info
*pinew
, afi_t afi
,
7967 struct bgp_aggregate
*aggregate
)
7970 struct aspath
*aspath
= NULL
;
7971 uint8_t atomic_aggregate
= 0;
7972 struct community
*community
= NULL
;
7973 struct ecommunity
*ecommunity
= NULL
;
7974 struct lcommunity
*lcommunity
= NULL
;
7976 /* If the bgp instance is being deleted or self peer is deleted
7977 * then do not create aggregate route
7979 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7980 || (bgp
->peer_self
== NULL
))
7983 /* ORIGIN attribute: If at least one route among routes that are
7984 * aggregated has ORIGIN with the value INCOMPLETE, then the
7985 * aggregated route must have the ORIGIN attribute with the value
7986 * INCOMPLETE. Otherwise, if at least one route among routes that
7987 * are aggregated has ORIGIN with the value EGP, then the aggregated
7988 * route must have the origin attribute with the value EGP. In all
7989 * other case the value of the ORIGIN attribute of the aggregated
7990 * route is INTERNAL.
7992 origin
= BGP_ORIGIN_IGP
;
7997 * This must be called before `summary` check to avoid
7998 * "suppressing" twice.
8000 if (aggregate
->match_med
)
8001 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
8004 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8005 aggr_suppress_path(aggregate
, pinew
);
8007 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8008 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
8009 aggr_suppress_path(aggregate
, pinew
);
8011 switch (pinew
->attr
->origin
) {
8012 case BGP_ORIGIN_INCOMPLETE
:
8013 aggregate
->incomplete_origin_count
++;
8015 case BGP_ORIGIN_EGP
:
8016 aggregate
->egp_origin_count
++;
8024 if (aggregate
->incomplete_origin_count
> 0)
8025 origin
= BGP_ORIGIN_INCOMPLETE
;
8026 else if (aggregate
->egp_origin_count
> 0)
8027 origin
= BGP_ORIGIN_EGP
;
8029 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8030 origin
= aggregate
->origin
;
8032 if (aggregate
->as_set
) {
8033 /* Compute aggregate route's as-path.
8035 bgp_compute_aggregate_aspath(aggregate
,
8036 pinew
->attr
->aspath
);
8038 /* Compute aggregate route's community.
8040 if (bgp_attr_get_community(pinew
->attr
))
8041 bgp_compute_aggregate_community(
8042 aggregate
, bgp_attr_get_community(pinew
->attr
));
8044 /* Compute aggregate route's extended community.
8046 if (bgp_attr_get_ecommunity(pinew
->attr
))
8047 bgp_compute_aggregate_ecommunity(
8049 bgp_attr_get_ecommunity(pinew
->attr
));
8051 /* Compute aggregate route's large community.
8053 if (bgp_attr_get_lcommunity(pinew
->attr
))
8054 bgp_compute_aggregate_lcommunity(
8056 bgp_attr_get_lcommunity(pinew
->attr
));
8058 /* Retrieve aggregate route's as-path.
8060 if (aggregate
->aspath
)
8061 aspath
= aspath_dup(aggregate
->aspath
);
8063 /* Retrieve aggregate route's community.
8065 if (aggregate
->community
)
8066 community
= community_dup(aggregate
->community
);
8068 /* Retrieve aggregate route's ecommunity.
8070 if (aggregate
->ecommunity
)
8071 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8073 /* Retrieve aggregate route's lcommunity.
8075 if (aggregate
->lcommunity
)
8076 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8079 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8080 aspath
, community
, ecommunity
,
8081 lcommunity
, atomic_aggregate
, aggregate
);
8084 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
8086 struct bgp_path_info
*pi
,
8087 struct bgp_aggregate
*aggregate
,
8088 const struct prefix
*aggr_p
)
8091 struct aspath
*aspath
= NULL
;
8092 uint8_t atomic_aggregate
= 0;
8093 struct community
*community
= NULL
;
8094 struct ecommunity
*ecommunity
= NULL
;
8095 struct lcommunity
*lcommunity
= NULL
;
8096 unsigned long match
= 0;
8098 /* If the bgp instance is being deleted or self peer is deleted
8099 * then do not create aggregate route
8101 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
8102 || (bgp
->peer_self
== NULL
))
8105 if (BGP_PATH_HOLDDOWN(pi
))
8108 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
8111 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8112 if (aggr_unsuppress_path(aggregate
, pi
))
8115 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8116 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
8117 if (aggr_unsuppress_path(aggregate
, pi
))
8121 * This must be called after `summary`, `suppress-map` check to avoid
8122 * "unsuppressing" twice.
8124 if (aggregate
->match_med
)
8125 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
);
8127 if (aggregate
->count
> 0)
8130 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
8131 aggregate
->incomplete_origin_count
--;
8132 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
8133 aggregate
->egp_origin_count
--;
8135 if (aggregate
->as_set
) {
8136 /* Remove as-path from aggregate.
8138 bgp_remove_aspath_from_aggregate(aggregate
,
8141 if (bgp_attr_get_community(pi
->attr
))
8142 /* Remove community from aggregate.
8144 bgp_remove_community_from_aggregate(
8145 aggregate
, bgp_attr_get_community(pi
->attr
));
8147 if (bgp_attr_get_ecommunity(pi
->attr
))
8148 /* Remove ecommunity from aggregate.
8150 bgp_remove_ecommunity_from_aggregate(
8151 aggregate
, bgp_attr_get_ecommunity(pi
->attr
));
8153 if (bgp_attr_get_lcommunity(pi
->attr
))
8154 /* Remove lcommunity from aggregate.
8156 bgp_remove_lcommunity_from_aggregate(
8157 aggregate
, bgp_attr_get_lcommunity(pi
->attr
));
8160 /* If this node was suppressed, process the change. */
8162 bgp_process(bgp
, pi
->net
, afi
, safi
);
8164 origin
= BGP_ORIGIN_IGP
;
8165 if (aggregate
->incomplete_origin_count
> 0)
8166 origin
= BGP_ORIGIN_INCOMPLETE
;
8167 else if (aggregate
->egp_origin_count
> 0)
8168 origin
= BGP_ORIGIN_EGP
;
8170 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8171 origin
= aggregate
->origin
;
8173 if (aggregate
->as_set
) {
8174 /* Retrieve aggregate route's as-path.
8176 if (aggregate
->aspath
)
8177 aspath
= aspath_dup(aggregate
->aspath
);
8179 /* Retrieve aggregate route's community.
8181 if (aggregate
->community
)
8182 community
= community_dup(aggregate
->community
);
8184 /* Retrieve aggregate route's ecommunity.
8186 if (aggregate
->ecommunity
)
8187 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8189 /* Retrieve aggregate route's lcommunity.
8191 if (aggregate
->lcommunity
)
8192 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8195 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8196 aspath
, community
, ecommunity
,
8197 lcommunity
, atomic_aggregate
, aggregate
);
8200 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
8201 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
8203 struct bgp_dest
*child
;
8204 struct bgp_dest
*dest
;
8205 struct bgp_aggregate
*aggregate
;
8206 struct bgp_table
*table
;
8208 table
= bgp
->aggregate
[afi
][safi
];
8210 /* No aggregates configured. */
8211 if (bgp_table_top_nolock(table
) == NULL
)
8214 if (p
->prefixlen
== 0)
8217 if (BGP_PATH_HOLDDOWN(pi
))
8220 /* If suppress fib is enabled and route not installed
8221 * in FIB, do not update the aggregate route
8223 if (!bgp_check_advertise(bgp
, pi
->net
))
8226 child
= bgp_node_get(table
, p
);
8228 /* Aggregate address configuration check. */
8229 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8230 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8232 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8233 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8234 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
8238 bgp_dest_unlock_node(child
);
8241 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
8242 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
8244 struct bgp_dest
*child
;
8245 struct bgp_dest
*dest
;
8246 struct bgp_aggregate
*aggregate
;
8247 struct bgp_table
*table
;
8249 table
= bgp
->aggregate
[afi
][safi
];
8251 /* No aggregates configured. */
8252 if (bgp_table_top_nolock(table
) == NULL
)
8255 if (p
->prefixlen
== 0)
8258 child
= bgp_node_get(table
, p
);
8260 /* Aggregate address configuration check. */
8261 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8262 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8264 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8265 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8266 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
8270 bgp_dest_unlock_node(child
);
8273 /* Aggregate route attribute. */
8274 #define AGGREGATE_SUMMARY_ONLY 1
8275 #define AGGREGATE_AS_SET 1
8276 #define AGGREGATE_AS_UNSET 0
8278 static const char *bgp_origin2str(uint8_t origin
)
8281 case BGP_ORIGIN_IGP
:
8283 case BGP_ORIGIN_EGP
:
8285 case BGP_ORIGIN_INCOMPLETE
:
8286 return "incomplete";
8291 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
8294 case RPKI_NOT_BEING_USED
:
8304 assert(!"We should never get here this is a dev escape");
8308 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
8309 afi_t afi
, safi_t safi
)
8311 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8314 struct bgp_dest
*dest
;
8315 struct bgp_aggregate
*aggregate
;
8317 /* Convert string to prefix structure. */
8318 ret
= str2prefix(prefix_str
, &p
);
8320 vty_out(vty
, "Malformed prefix\n");
8321 return CMD_WARNING_CONFIG_FAILED
;
8325 /* Old configuration check. */
8326 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
8329 "%% There is no aggregate-address configuration.\n");
8330 return CMD_WARNING_CONFIG_FAILED
;
8333 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8334 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
8335 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
8336 NULL
, NULL
, 0, aggregate
);
8338 /* Unlock aggregate address configuration. */
8339 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
8341 if (aggregate
->community
)
8342 community_free(&aggregate
->community
);
8344 hash_clean_and_free(&aggregate
->community_hash
,
8345 bgp_aggr_community_remove
);
8347 if (aggregate
->ecommunity
)
8348 ecommunity_free(&aggregate
->ecommunity
);
8350 hash_clean_and_free(&aggregate
->ecommunity_hash
,
8351 bgp_aggr_ecommunity_remove
);
8353 if (aggregate
->lcommunity
)
8354 lcommunity_free(&aggregate
->lcommunity
);
8356 hash_clean_and_free(&aggregate
->lcommunity_hash
,
8357 bgp_aggr_lcommunity_remove
);
8359 if (aggregate
->aspath
)
8360 aspath_free(aggregate
->aspath
);
8362 hash_clean_and_free(&aggregate
->aspath_hash
, bgp_aggr_aspath_remove
);
8364 bgp_aggregate_free(aggregate
);
8365 bgp_dest_unlock_node(dest
);
8366 bgp_dest_unlock_node(dest
);
8371 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
8372 safi_t safi
, const char *rmap
,
8373 uint8_t summary_only
, uint8_t as_set
,
8374 uint8_t origin
, bool match_med
,
8375 const char *suppress_map
)
8377 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8380 struct bgp_dest
*dest
;
8381 struct bgp_aggregate
*aggregate
;
8382 uint8_t as_set_new
= as_set
;
8384 if (suppress_map
&& summary_only
) {
8386 "'summary-only' and 'suppress-map' can't be used at the same time\n");
8387 return CMD_WARNING_CONFIG_FAILED
;
8390 /* Convert string to prefix structure. */
8391 ret
= str2prefix(prefix_str
, &p
);
8393 vty_out(vty
, "Malformed prefix\n");
8394 return CMD_WARNING_CONFIG_FAILED
;
8398 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
8399 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
8400 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8402 return CMD_WARNING_CONFIG_FAILED
;
8405 /* Old configuration check. */
8406 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
8407 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8410 vty_out(vty
, "There is already same aggregate network.\n");
8411 /* try to remove the old entry */
8412 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
8414 vty_out(vty
, "Error deleting aggregate.\n");
8415 bgp_dest_unlock_node(dest
);
8416 return CMD_WARNING_CONFIG_FAILED
;
8420 /* Make aggregate address structure. */
8421 aggregate
= bgp_aggregate_new();
8422 aggregate
->summary_only
= summary_only
;
8423 aggregate
->match_med
= match_med
;
8425 /* Network operators MUST NOT locally generate any new
8426 * announcements containing AS_SET or AS_CONFED_SET. If they have
8427 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8428 * SHOULD withdraw those routes and re-announce routes for the
8429 * aggregate or component prefixes (i.e., the more-specific routes
8430 * subsumed by the previously aggregated route) without AS_SET
8431 * or AS_CONFED_SET in the updates.
8433 if (bgp
->reject_as_sets
) {
8434 if (as_set
== AGGREGATE_AS_SET
) {
8435 as_set_new
= AGGREGATE_AS_UNSET
;
8437 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8440 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8444 aggregate
->as_set
= as_set_new
;
8445 aggregate
->safi
= safi
;
8446 /* Override ORIGIN attribute if defined.
8447 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8448 * to IGP which is not what rfc4271 says.
8449 * This enables the same behavior, optionally.
8451 aggregate
->origin
= origin
;
8454 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
8455 route_map_counter_decrement(aggregate
->rmap
.map
);
8456 aggregate
->rmap
.name
=
8457 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
8458 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
8459 route_map_counter_increment(aggregate
->rmap
.map
);
8463 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
8464 route_map_counter_decrement(aggregate
->suppress_map
);
8466 aggregate
->suppress_map_name
=
8467 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
8468 aggregate
->suppress_map
=
8469 route_map_lookup_by_name(aggregate
->suppress_map_name
);
8470 route_map_counter_increment(aggregate
->suppress_map
);
8473 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
8475 /* Aggregate address insert into BGP routing table. */
8476 if (!bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
)) {
8477 bgp_aggregate_free(aggregate
);
8478 bgp_dest_unlock_node(dest
);
8484 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
8485 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8487 "|summary-only$summary_only"
8488 "|route-map RMAP_NAME$rmap_name"
8489 "|origin <egp|igp|incomplete>$origin_s"
8490 "|matching-MED-only$match_med"
8491 "|suppress-map RMAP_NAME$suppress_map"
8494 "Configure BGP aggregate entries\n"
8495 "Aggregate prefix\n"
8496 "Aggregate address\n"
8498 "Generate AS set path information\n"
8499 "Filter more specific routes from updates\n"
8500 "Apply route map to aggregate network\n"
8505 "Unknown heritage\n"
8506 "Only aggregate routes with matching MED\n"
8507 "Suppress the selected more specific routes\n"
8508 "Route map with the route selectors\n")
8510 const char *prefix_s
= NULL
;
8511 safi_t safi
= bgp_node_safi(vty
);
8512 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8513 int as_set
= AGGREGATE_AS_UNSET
;
8514 char prefix_buf
[PREFIX2STR_BUFFER
];
8517 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8520 vty_out(vty
, "%% Inconsistent address and mask\n");
8521 return CMD_WARNING_CONFIG_FAILED
;
8523 prefix_s
= prefix_buf
;
8525 prefix_s
= prefix_str
;
8528 if (strcmp(origin_s
, "egp") == 0)
8529 origin
= BGP_ORIGIN_EGP
;
8530 else if (strcmp(origin_s
, "igp") == 0)
8531 origin
= BGP_ORIGIN_IGP
;
8532 else if (strcmp(origin_s
, "incomplete") == 0)
8533 origin
= BGP_ORIGIN_INCOMPLETE
;
8537 as_set
= AGGREGATE_AS_SET
;
8539 /* Handle configuration removal, otherwise installation. */
8541 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8543 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8544 summary_only
!= NULL
, as_set
, origin
,
8545 match_med
!= NULL
, suppress_map
);
8548 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8549 "[no] aggregate-address X:X::X:X/M$prefix [{"
8551 "|summary-only$summary_only"
8552 "|route-map RMAP_NAME$rmap_name"
8553 "|origin <egp|igp|incomplete>$origin_s"
8554 "|matching-MED-only$match_med"
8555 "|suppress-map RMAP_NAME$suppress_map"
8558 "Configure BGP aggregate entries\n"
8559 "Aggregate prefix\n"
8560 "Generate AS set path information\n"
8561 "Filter more specific routes from updates\n"
8562 "Apply route map to aggregate network\n"
8567 "Unknown heritage\n"
8568 "Only aggregate routes with matching MED\n"
8569 "Suppress the selected more specific routes\n"
8570 "Route map with the route selectors\n")
8572 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8573 int as_set
= AGGREGATE_AS_UNSET
;
8576 if (strcmp(origin_s
, "egp") == 0)
8577 origin
= BGP_ORIGIN_EGP
;
8578 else if (strcmp(origin_s
, "igp") == 0)
8579 origin
= BGP_ORIGIN_IGP
;
8580 else if (strcmp(origin_s
, "incomplete") == 0)
8581 origin
= BGP_ORIGIN_INCOMPLETE
;
8585 as_set
= AGGREGATE_AS_SET
;
8587 /* Handle configuration removal, otherwise installation. */
8589 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8592 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8593 rmap_name
, summary_only
!= NULL
, as_set
,
8594 origin
, match_med
!= NULL
, suppress_map
);
8597 /* Redistribute route treatment. */
8598 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8599 const union g_addr
*nexthop
, ifindex_t ifindex
,
8600 enum nexthop_types_t nhtype
, uint8_t distance
,
8601 enum blackhole_type bhtype
, uint32_t metric
,
8602 uint8_t type
, unsigned short instance
,
8605 struct bgp_path_info
*new;
8606 struct bgp_path_info
*bpi
;
8607 struct bgp_path_info rmap_path
;
8608 struct bgp_dest
*bn
;
8610 struct attr
*new_attr
;
8612 route_map_result_t ret
;
8613 struct bgp_redist
*red
;
8615 /* Make default attribute. */
8616 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
8618 * This must not be NULL to satisfy Coverity SA
8620 assert(attr
.aspath
);
8623 case NEXTHOP_TYPE_IFINDEX
:
8624 switch (p
->family
) {
8626 attr
.nexthop
.s_addr
= INADDR_ANY
;
8627 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8630 memset(&attr
.mp_nexthop_global
, 0,
8631 sizeof(attr
.mp_nexthop_global
));
8632 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8636 case NEXTHOP_TYPE_IPV4
:
8637 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8638 attr
.nexthop
= nexthop
->ipv4
;
8639 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8641 case NEXTHOP_TYPE_IPV6
:
8642 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8643 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8644 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8646 case NEXTHOP_TYPE_BLACKHOLE
:
8647 switch (p
->family
) {
8649 attr
.nexthop
.s_addr
= INADDR_ANY
;
8650 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8653 memset(&attr
.mp_nexthop_global
, 0,
8654 sizeof(attr
.mp_nexthop_global
));
8655 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8658 attr
.bh_type
= bhtype
;
8661 attr
.nh_type
= nhtype
;
8662 attr
.nh_ifindex
= ifindex
;
8665 attr
.distance
= distance
;
8666 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8670 bgp_attr_set_aigp_metric(&attr
, metric
);
8672 afi
= family2afi(p
->family
);
8674 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8676 struct attr attr_new
;
8678 /* Copy attribute for modification. */
8681 if (red
->redist_metric_flag
) {
8682 attr_new
.med
= red
->redist_metric
;
8683 bgp_attr_set_aigp_metric(&attr_new
, red
->redist_metric
);
8686 /* Apply route-map. */
8687 if (red
->rmap
.name
) {
8688 memset(&rmap_path
, 0, sizeof(rmap_path
));
8689 rmap_path
.peer
= bgp
->peer_self
;
8690 rmap_path
.attr
= &attr_new
;
8692 SET_FLAG(bgp
->peer_self
->rmap_type
,
8693 PEER_RMAP_TYPE_REDISTRIBUTE
);
8695 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8697 bgp
->peer_self
->rmap_type
= 0;
8699 if (ret
== RMAP_DENYMATCH
) {
8700 /* Free uninterned attribute. */
8701 bgp_attr_flush(&attr_new
);
8703 /* Unintern original. */
8704 aspath_unintern(&attr
.aspath
);
8705 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8710 if (bgp_in_graceful_shutdown(bgp
))
8711 bgp_attr_add_gshut_community(&attr_new
);
8713 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8714 SAFI_UNICAST
, p
, NULL
);
8716 new_attr
= bgp_attr_intern(&attr_new
);
8718 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8719 if (bpi
->peer
== bgp
->peer_self
8720 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8724 /* Ensure the (source route) type is updated. */
8726 if (attrhash_cmp(bpi
->attr
, new_attr
)
8727 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8728 bgp_attr_unintern(&new_attr
);
8729 aspath_unintern(&attr
.aspath
);
8730 bgp_dest_unlock_node(bn
);
8733 /* The attribute is changed. */
8734 bgp_path_info_set_flag(bn
, bpi
,
8735 BGP_PATH_ATTR_CHANGED
);
8737 /* Rewrite BGP route information. */
8738 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8739 bgp_path_info_restore(bn
, bpi
);
8741 bgp_aggregate_decrement(
8742 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8743 bgp_attr_unintern(&bpi
->attr
);
8744 bpi
->attr
= new_attr
;
8745 bpi
->uptime
= monotime(NULL
);
8747 /* Process change. */
8748 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8750 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8751 bgp_dest_unlock_node(bn
);
8752 aspath_unintern(&attr
.aspath
);
8754 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8756 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8758 vpn_leak_from_vrf_update(
8759 bgp_get_default(), bgp
, bpi
);
8765 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8766 bgp
->peer_self
, new_attr
, bn
);
8767 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8769 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8770 bgp_path_info_add(bn
, new);
8771 bgp_dest_unlock_node(bn
);
8772 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8773 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8775 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8776 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8778 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8782 /* Unintern original. */
8783 aspath_unintern(&attr
.aspath
);
8786 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8787 unsigned short instance
)
8790 struct bgp_dest
*dest
;
8791 struct bgp_path_info
*pi
;
8792 struct bgp_redist
*red
;
8794 afi
= family2afi(p
->family
);
8796 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8798 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8799 SAFI_UNICAST
, p
, NULL
);
8801 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8802 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8806 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8807 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8809 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8812 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8813 bgp_path_info_delete(dest
, pi
);
8814 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8816 bgp_dest_unlock_node(dest
);
8820 /* Withdraw specified route type's route. */
8821 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8822 unsigned short instance
)
8824 struct bgp_dest
*dest
;
8825 struct bgp_path_info
*pi
;
8826 struct bgp_table
*table
;
8828 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8830 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8831 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8832 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8833 && pi
->instance
== instance
)
8837 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8838 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8840 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8843 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8844 pi
, afi
, SAFI_UNICAST
);
8845 bgp_path_info_delete(dest
, pi
);
8846 if (!CHECK_FLAG(bgp
->flags
,
8847 BGP_FLAG_DELETE_IN_PROGRESS
))
8848 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8850 bgp_path_info_reap(dest
, pi
);
8855 /* Static function to display route. */
8856 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8857 struct vty
*vty
, json_object
*json
, bool wide
)
8860 char buf
[INET6_ADDRSTRLEN
];
8862 if (p
->family
== AF_INET
) {
8864 len
= vty_out(vty
, "%pFX", p
);
8866 json_object_string_add(json
, "prefix",
8867 inet_ntop(p
->family
,
8870 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8871 json_object_string_addf(json
, "network", "%pFX", p
);
8872 json_object_int_add(json
, "version", dest
->version
);
8874 } else if (p
->family
== AF_ETHERNET
) {
8875 len
= vty_out(vty
, "%pFX", p
);
8876 } else if (p
->family
== AF_EVPN
) {
8878 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8880 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8881 } else if (p
->family
== AF_FLOWSPEC
) {
8882 route_vty_out_flowspec(vty
, p
, NULL
,
8884 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8885 NLRI_STRING_FORMAT_MIN
, json
);
8888 len
= vty_out(vty
, "%pFX", p
);
8890 json_object_string_add(json
, "prefix",
8891 inet_ntop(p
->family
,
8894 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8895 json_object_string_addf(json
, "network", "%pFX", p
);
8896 json_object_int_add(json
, "version", dest
->version
);
8901 len
= wide
? (45 - len
) : (17 - len
);
8903 vty_out(vty
, "\n%*s", 20, " ");
8905 vty_out(vty
, "%*s", len
, " ");
8909 enum bgp_display_type
{
8913 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8916 case bgp_path_selection_none
:
8917 return "Nothing to Select";
8918 case bgp_path_selection_first
:
8919 return "First path received";
8920 case bgp_path_selection_evpn_sticky_mac
:
8921 return "EVPN Sticky Mac";
8922 case bgp_path_selection_evpn_seq
:
8923 return "EVPN sequence number";
8924 case bgp_path_selection_evpn_lower_ip
:
8925 return "EVPN lower IP";
8926 case bgp_path_selection_evpn_local_path
:
8927 return "EVPN local ES path";
8928 case bgp_path_selection_evpn_non_proxy
:
8929 return "EVPN non proxy";
8930 case bgp_path_selection_weight
:
8932 case bgp_path_selection_local_pref
:
8933 return "Local Pref";
8934 case bgp_path_selection_accept_own
:
8935 return "Accept Own";
8936 case bgp_path_selection_local_route
:
8937 return "Local Route";
8938 case bgp_path_selection_aigp
:
8940 case bgp_path_selection_confed_as_path
:
8941 return "Confederation based AS Path";
8942 case bgp_path_selection_as_path
:
8944 case bgp_path_selection_origin
:
8946 case bgp_path_selection_med
:
8948 case bgp_path_selection_peer
:
8950 case bgp_path_selection_confed
:
8951 return "Confed Peer Type";
8952 case bgp_path_selection_igp_metric
:
8953 return "IGP Metric";
8954 case bgp_path_selection_older
:
8955 return "Older Path";
8956 case bgp_path_selection_router_id
:
8958 case bgp_path_selection_cluster_length
:
8959 return "Cluster length";
8960 case bgp_path_selection_stale
:
8961 return "Path Staleness";
8962 case bgp_path_selection_local_configured
:
8963 return "Locally configured route";
8964 case bgp_path_selection_neighbor_ip
:
8965 return "Neighbor IP";
8966 case bgp_path_selection_default
:
8967 return "Nothing left to compare";
8969 return "Invalid (internal error)";
8972 /* Print the short form route status for a bgp_path_info */
8973 static void route_vty_short_status_out(struct vty
*vty
,
8974 struct bgp_path_info
*path
,
8975 const struct prefix
*p
,
8976 json_object
*json_path
)
8978 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
8982 /* Route status display. */
8983 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8984 json_object_boolean_true_add(json_path
, "removed");
8986 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8987 json_object_boolean_true_add(json_path
, "stale");
8989 if (path
->extra
&& bgp_path_suppressed(path
))
8990 json_object_boolean_true_add(json_path
, "suppressed");
8992 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8993 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8994 json_object_boolean_true_add(json_path
, "valid");
8997 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8998 json_object_boolean_true_add(json_path
, "history");
9000 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9001 json_object_boolean_true_add(json_path
, "damped");
9003 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9004 json_object_boolean_true_add(json_path
, "bestpath");
9005 json_object_string_add(json_path
, "selectionReason",
9006 bgp_path_selection_reason2str(
9007 path
->net
->reason
));
9010 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9011 json_object_boolean_true_add(json_path
, "multipath");
9013 /* Internal route. */
9014 if ((path
->peer
->as
)
9015 && (path
->peer
->as
== path
->peer
->local_as
))
9016 json_object_string_add(json_path
, "pathFrom",
9019 json_object_string_add(json_path
, "pathFrom",
9025 /* RPKI validation state */
9027 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
9029 if (rpki_state
== RPKI_VALID
)
9031 else if (rpki_state
== RPKI_INVALID
)
9033 else if (rpki_state
== RPKI_NOTFOUND
)
9038 /* Route status display. */
9039 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9041 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9043 else if (bgp_path_suppressed(path
))
9045 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9046 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9052 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9054 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9056 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
9058 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9063 /* Internal route. */
9064 if (path
->peer
&& (path
->peer
->as
)
9065 && (path
->peer
->as
== path
->peer
->local_as
))
9071 static char *bgp_nexthop_hostname(struct peer
*peer
,
9072 struct bgp_nexthop_cache
*bnc
)
9075 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
9076 return peer
->hostname
;
9080 /* called from terminal list command */
9081 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9082 struct bgp_path_info
*path
, int display
, safi_t safi
,
9083 json_object
*json_paths
, bool wide
)
9086 struct attr
*attr
= path
->attr
;
9087 json_object
*json_path
= NULL
;
9088 json_object
*json_nexthops
= NULL
;
9089 json_object
*json_nexthop_global
= NULL
;
9090 json_object
*json_nexthop_ll
= NULL
;
9091 json_object
*json_ext_community
= NULL
;
9092 char vrf_id_str
[VRF_NAMSIZ
] = {0};
9094 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9095 bool nexthop_othervrf
= false;
9096 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
9097 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
9098 char *nexthop_hostname
=
9099 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9100 char esi_buf
[ESI_STR_LEN
];
9103 json_path
= json_object_new_object();
9105 /* short status lead text */
9106 route_vty_short_status_out(vty
, path
, p
, json_path
);
9109 /* print prefix and mask */
9111 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9113 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
9115 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9119 * If vrf id of nexthop is different from that of prefix,
9120 * set up printable string to append
9122 if (path
->extra
&& path
->extra
->bgp_orig
) {
9123 const char *self
= "";
9128 nexthop_othervrf
= true;
9129 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9131 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
9132 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
9133 "@%s%s", VRFID_NONE_STR
, self
);
9135 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
9136 path
->extra
->bgp_orig
->vrf_id
, self
);
9138 if (path
->extra
->bgp_orig
->inst_type
9139 != BGP_INSTANCE_TYPE_DEFAULT
)
9141 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
9143 const char *self
= "";
9148 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
9152 * For ENCAP and EVPN routes, nexthop address family is not
9153 * neccessarily the same as the prefix address family.
9154 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9155 * EVPN routes are also exchanged with a MP nexthop. Currently,
9157 * is only IPv4, the value will be present in either
9159 * attr->mp_nexthop_global_in
9161 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
9163 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9167 snprintfrr(nexthop
, sizeof(nexthop
), "%pI4",
9168 &attr
->mp_nexthop_global_in
);
9171 snprintfrr(nexthop
, sizeof(nexthop
), "%pI6",
9172 &attr
->mp_nexthop_global
);
9175 snprintf(nexthop
, sizeof(nexthop
), "?");
9180 json_nexthop_global
= json_object_new_object();
9182 json_object_string_add(json_nexthop_global
, "ip",
9185 if (path
->peer
->hostname
)
9186 json_object_string_add(json_nexthop_global
,
9188 path
->peer
->hostname
);
9190 json_object_string_add(json_nexthop_global
, "afi",
9191 (af
== AF_INET
) ? "ipv4"
9193 json_object_boolean_true_add(json_nexthop_global
,
9196 if (nexthop_hostname
)
9197 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
9198 nexthop_hostname
, vrf_id_str
);
9200 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
9202 len
= wide
? (41 - len
) : (16 - len
);
9204 vty_out(vty
, "\n%*s", 36, " ");
9206 vty_out(vty
, "%*s", len
, " ");
9208 } else if (safi
== SAFI_EVPN
) {
9210 json_nexthop_global
= json_object_new_object();
9212 json_object_string_addf(json_nexthop_global
, "ip",
9214 &attr
->mp_nexthop_global_in
);
9216 if (path
->peer
->hostname
)
9217 json_object_string_add(json_nexthop_global
,
9219 path
->peer
->hostname
);
9221 json_object_string_add(json_nexthop_global
, "afi",
9223 json_object_boolean_true_add(json_nexthop_global
,
9226 if (nexthop_hostname
)
9227 len
= vty_out(vty
, "%pI4(%s)%s",
9228 &attr
->mp_nexthop_global_in
,
9229 nexthop_hostname
, vrf_id_str
);
9231 len
= vty_out(vty
, "%pI4%s",
9232 &attr
->mp_nexthop_global_in
,
9235 len
= wide
? (41 - len
) : (16 - len
);
9237 vty_out(vty
, "\n%*s", 36, " ");
9239 vty_out(vty
, "%*s", len
, " ");
9241 } else if (safi
== SAFI_FLOWSPEC
) {
9242 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
9244 json_nexthop_global
= json_object_new_object();
9246 json_object_string_add(json_nexthop_global
,
9248 json_object_string_addf(json_nexthop_global
,
9252 if (path
->peer
->hostname
)
9253 json_object_string_add(
9254 json_nexthop_global
, "hostname",
9255 path
->peer
->hostname
);
9257 json_object_boolean_true_add(
9258 json_nexthop_global
,
9261 if (nexthop_hostname
)
9262 len
= vty_out(vty
, "%pI4(%s)%s",
9267 len
= vty_out(vty
, "%pI4%s",
9271 len
= wide
? (41 - len
) : (16 - len
);
9273 vty_out(vty
, "\n%*s", 36, " ");
9275 vty_out(vty
, "%*s", len
, " ");
9278 } else if (p
->family
== AF_INET
&& !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9280 json_nexthop_global
= json_object_new_object();
9282 json_object_string_addf(json_nexthop_global
, "ip",
9283 "%pI4", &attr
->nexthop
);
9285 if (path
->peer
->hostname
)
9286 json_object_string_add(json_nexthop_global
,
9288 path
->peer
->hostname
);
9290 json_object_string_add(json_nexthop_global
, "afi",
9292 json_object_boolean_true_add(json_nexthop_global
,
9295 if (nexthop_hostname
)
9296 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
9297 nexthop_hostname
, vrf_id_str
);
9299 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
9302 len
= wide
? (41 - len
) : (16 - len
);
9304 vty_out(vty
, "\n%*s", 36, " ");
9306 vty_out(vty
, "%*s", len
, " ");
9311 else if (p
->family
== AF_INET6
|| BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9313 json_nexthop_global
= json_object_new_object();
9314 json_object_string_addf(json_nexthop_global
, "ip",
9316 &attr
->mp_nexthop_global
);
9318 if (path
->peer
->hostname
)
9319 json_object_string_add(json_nexthop_global
,
9321 path
->peer
->hostname
);
9323 json_object_string_add(json_nexthop_global
, "afi",
9325 json_object_string_add(json_nexthop_global
, "scope",
9328 /* We display both LL & GL if both have been
9330 if ((attr
->mp_nexthop_len
9331 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9332 || (path
->peer
->conf_if
)) {
9333 json_nexthop_ll
= json_object_new_object();
9334 json_object_string_addf(
9335 json_nexthop_ll
, "ip", "%pI6",
9336 &attr
->mp_nexthop_local
);
9338 if (path
->peer
->hostname
)
9339 json_object_string_add(
9340 json_nexthop_ll
, "hostname",
9341 path
->peer
->hostname
);
9343 json_object_string_add(json_nexthop_ll
, "afi",
9345 json_object_string_add(json_nexthop_ll
, "scope",
9348 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9349 &attr
->mp_nexthop_local
)
9351 && !attr
->mp_nexthop_prefer_global
)
9352 json_object_boolean_true_add(
9353 json_nexthop_ll
, "used");
9355 json_object_boolean_true_add(
9356 json_nexthop_global
, "used");
9358 json_object_boolean_true_add(
9359 json_nexthop_global
, "used");
9361 /* Display LL if LL/Global both in table unless
9362 * prefer-global is set */
9363 if (((attr
->mp_nexthop_len
9364 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9365 && !attr
->mp_nexthop_prefer_global
)
9366 || (path
->peer
->conf_if
)) {
9367 if (path
->peer
->conf_if
) {
9368 len
= vty_out(vty
, "%s",
9369 path
->peer
->conf_if
);
9370 /* len of IPv6 addr + max len of def
9372 len
= wide
? (41 - len
) : (16 - len
);
9375 vty_out(vty
, "\n%*s", 36, " ");
9377 vty_out(vty
, "%*s", len
, " ");
9379 if (nexthop_hostname
)
9382 &attr
->mp_nexthop_local
,
9388 &attr
->mp_nexthop_local
,
9391 len
= wide
? (41 - len
) : (16 - len
);
9394 vty_out(vty
, "\n%*s", 36, " ");
9396 vty_out(vty
, "%*s", len
, " ");
9399 if (nexthop_hostname
)
9400 len
= vty_out(vty
, "%pI6(%s)%s",
9401 &attr
->mp_nexthop_global
,
9405 len
= vty_out(vty
, "%pI6%s",
9406 &attr
->mp_nexthop_global
,
9409 len
= wide
? (41 - len
) : (16 - len
);
9412 vty_out(vty
, "\n%*s", 36, " ");
9414 vty_out(vty
, "%*s", len
, " ");
9420 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9422 json_object_int_add(json_path
, "metric", attr
->med
);
9424 vty_out(vty
, "%7u", attr
->med
);
9426 vty_out(vty
, "%10u", attr
->med
);
9427 else if (!json_paths
) {
9429 vty_out(vty
, "%*s", 7, " ");
9431 vty_out(vty
, "%*s", 10, " ");
9435 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9437 json_object_int_add(json_path
, "locPrf",
9440 vty_out(vty
, "%7u", attr
->local_pref
);
9441 else if (!json_paths
)
9445 json_object_int_add(json_path
, "weight", attr
->weight
);
9447 vty_out(vty
, "%7u ", attr
->weight
);
9450 json_object_string_addf(json_path
, "peerId", "%pSU",
9456 json_object_string_add(json_path
, "path",
9459 aspath_print_vty(vty
, attr
->aspath
);
9464 json_object_string_add(json_path
, "origin",
9465 bgp_origin_long_str
[attr
->origin
]);
9467 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9470 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9471 json_object_string_add(json_path
, "esi",
9472 esi_to_str(&attr
->esi
,
9473 esi_buf
, sizeof(esi_buf
)));
9475 if (safi
== SAFI_EVPN
&&
9476 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9477 json_ext_community
= json_object_new_object();
9478 json_object_string_add(
9479 json_ext_community
, "string",
9480 bgp_attr_get_ecommunity(attr
)->str
);
9481 json_object_object_add(json_path
,
9482 "extendedCommunity",
9483 json_ext_community
);
9487 json_object_boolean_true_add(json_path
,
9488 "announceNexthopSelf");
9489 if (nexthop_othervrf
) {
9490 json_object_string_add(json_path
, "nhVrfName",
9493 json_object_int_add(json_path
, "nhVrfId",
9494 ((nexthop_vrfid
== VRF_UNKNOWN
)
9496 : (int)nexthop_vrfid
));
9501 if (json_nexthop_global
|| json_nexthop_ll
) {
9502 json_nexthops
= json_object_new_array();
9504 if (json_nexthop_global
)
9505 json_object_array_add(json_nexthops
,
9506 json_nexthop_global
);
9508 if (json_nexthop_ll
)
9509 json_object_array_add(json_nexthops
,
9512 json_object_object_add(json_path
, "nexthops",
9516 json_object_array_add(json_paths
, json_path
);
9520 if (safi
== SAFI_EVPN
) {
9521 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9522 /* XXX - add these params to the json out */
9523 vty_out(vty
, "%*s", 20, " ");
9524 vty_out(vty
, "ESI:%s",
9525 esi_to_str(&attr
->esi
, esi_buf
,
9531 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9532 vty_out(vty
, "%*s", 20, " ");
9533 vty_out(vty
, "%s\n",
9534 bgp_attr_get_ecommunity(attr
)->str
);
9538 #ifdef ENABLE_BGP_VNC
9539 /* prints an additional line, indented, with VNC info, if
9541 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9542 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9547 /* called from terminal list command */
9548 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9549 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9550 bool use_json
, json_object
*json_ar
, bool wide
)
9552 json_object
*json_status
= NULL
;
9553 json_object
*json_net
= NULL
;
9557 /* Route status display. */
9559 json_status
= json_object_new_object();
9560 json_net
= json_object_new_object();
9567 /* print prefix and mask */
9569 if (safi
== SAFI_EVPN
)
9570 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9571 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9572 json_object_string_add(
9573 json_net
, "addrPrefix",
9574 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9576 json_object_int_add(json_net
, "prefixLen",
9578 json_object_string_addf(json_net
, "network", "%pFX", p
);
9581 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9583 /* Print attribute */
9586 if (p
->family
== AF_INET
&&
9587 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9588 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9589 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9590 json_object_string_addf(
9591 json_net
, "nextHop", "%pI4",
9592 &attr
->mp_nexthop_global_in
);
9594 json_object_string_addf(
9595 json_net
, "nextHop", "%pI4",
9597 } else if (p
->family
== AF_INET6
||
9598 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9599 json_object_string_addf(
9600 json_net
, "nextHopGlobal", "%pI6",
9601 &attr
->mp_nexthop_global
);
9602 } else if (p
->family
== AF_EVPN
&&
9603 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9604 json_object_string_addf(
9605 json_net
, "nextHop", "%pI4",
9606 &attr
->mp_nexthop_global_in
);
9610 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9611 json_object_int_add(json_net
, "metric",
9614 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9615 json_object_int_add(json_net
, "locPrf",
9618 json_object_int_add(json_net
, "weight", attr
->weight
);
9622 json_object_string_add(json_net
, "path",
9626 #if CONFDATE > 20231208
9627 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9629 json_object_string_add(json_net
, "bgpOriginCode",
9630 bgp_origin_str
[attr
->origin
]);
9631 json_object_string_add(
9633 bgp_origin_long_str
[attr
->origin
]);
9635 if (p
->family
== AF_INET
&&
9636 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9637 safi
== SAFI_EVPN
||
9638 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9639 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9640 || safi
== SAFI_EVPN
)
9641 vty_out(vty
, "%-16pI4",
9642 &attr
->mp_nexthop_global_in
);
9644 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9646 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9647 } else if (p
->family
== AF_INET6
||
9648 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9649 len
= vty_out(vty
, "%pI6",
9650 &attr
->mp_nexthop_global
);
9651 len
= wide
? (41 - len
) : (16 - len
);
9653 vty_out(vty
, "\n%*s", 36, " ");
9655 vty_out(vty
, "%*s", len
, " ");
9658 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9660 vty_out(vty
, "%7u", attr
->med
);
9662 vty_out(vty
, "%10u", attr
->med
);
9668 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9669 vty_out(vty
, "%7u", attr
->local_pref
);
9673 vty_out(vty
, "%7u ", attr
->weight
);
9677 aspath_print_vty(vty
, attr
->aspath
);
9680 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9684 struct bgp_path_info
*bpi
= bgp_dest_get_bgp_path_info(dest
);
9686 #if CONFDATE > 20231208
9687 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9689 json_object_boolean_true_add(json_status
, "*");
9690 json_object_boolean_true_add(json_status
, ">");
9691 json_object_boolean_true_add(json_net
, "valid");
9692 json_object_boolean_true_add(json_net
, "best");
9694 if (bpi
&& CHECK_FLAG(bpi
->flags
, BGP_PATH_MULTIPATH
)) {
9695 json_object_boolean_true_add(json_status
, "=");
9696 json_object_boolean_true_add(json_net
, "multipath");
9698 json_object_object_add(json_net
, "appliedStatusSymbols",
9700 json_object_object_addf(json_ar
, json_net
, "%pFX", p
);
9705 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9706 struct bgp_path_info
*path
, int display
, safi_t safi
,
9709 json_object
*json_out
= NULL
;
9711 mpls_label_t label
= MPLS_INVALID_LABEL
;
9717 json_out
= json_object_new_object();
9719 /* short status lead text */
9720 route_vty_short_status_out(vty
, path
, p
, json_out
);
9722 /* print prefix and mask */
9725 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9727 vty_out(vty
, "%*s", 17, " ");
9730 /* Print attribute */
9732 if (((p
->family
== AF_INET
) &&
9733 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9734 (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) ||
9735 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9736 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9737 || safi
== SAFI_EVPN
) {
9739 json_object_string_addf(
9740 json_out
, "mpNexthopGlobalIn", "%pI4",
9741 &attr
->mp_nexthop_global_in
);
9743 vty_out(vty
, "%-16pI4",
9744 &attr
->mp_nexthop_global_in
);
9747 json_object_string_addf(json_out
, "nexthop",
9748 "%pI4", &attr
->nexthop
);
9750 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9752 } else if (((p
->family
== AF_INET6
) &&
9753 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9754 (safi
== SAFI_EVPN
&& BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) ||
9755 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9758 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9760 json_object_string_addf(
9761 json_out
, "mpNexthopGlobalIn", "%pI6",
9762 &attr
->mp_nexthop_global
);
9766 &attr
->mp_nexthop_global
,
9767 buf_a
, sizeof(buf_a
)));
9768 } else if (attr
->mp_nexthop_len
9769 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9770 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9771 &attr
->mp_nexthop_global
,
9772 &attr
->mp_nexthop_local
);
9774 json_object_string_add(json_out
,
9775 "mpNexthopGlobalLocal",
9778 vty_out(vty
, "%s", buf_a
);
9782 label
= decode_label(&path
->extra
->label
[0]);
9784 if (bgp_is_valid_label(&label
)) {
9786 json_object_int_add(json_out
, "notag", label
);
9787 json_object_array_add(json
, json_out
);
9789 vty_out(vty
, "notag/%d", label
);
9796 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9797 struct bgp_path_info
*path
, int display
,
9798 json_object
*json_paths
)
9801 json_object
*json_path
= NULL
;
9802 json_object
*json_nexthop
= NULL
;
9803 json_object
*json_overlay
= NULL
;
9809 json_path
= json_object_new_object();
9810 json_overlay
= json_object_new_object();
9811 json_nexthop
= json_object_new_object();
9814 /* short status lead text */
9815 route_vty_short_status_out(vty
, path
, p
, json_path
);
9817 /* print prefix and mask */
9819 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9821 vty_out(vty
, "%*s", 17, " ");
9823 /* Print attribute */
9825 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9830 vty_out(vty
, "%-16pI4", &attr
->mp_nexthop_global_in
);
9832 json_object_string_addf(json_nexthop
, "ip", "%pI4",
9833 &attr
->mp_nexthop_global_in
);
9835 json_object_string_add(json_nexthop
, "afi", "ipv4");
9837 json_object_object_add(json_path
, "nexthop",
9843 vty_out(vty
, "%pI6(%pI6)", &attr
->mp_nexthop_global
,
9844 &attr
->mp_nexthop_local
);
9846 json_object_string_addf(json_nexthop
, "ipv6Global",
9848 &attr
->mp_nexthop_global
);
9850 json_object_string_addf(json_nexthop
, "ipv6LinkLocal",
9852 &attr
->mp_nexthop_local
);
9854 json_object_string_add(json_nexthop
, "afi", "ipv6");
9856 json_object_object_add(json_path
, "nexthop",
9864 json_object_string_add(json_nexthop
, "error",
9865 "Unsupported address-family");
9869 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9872 vty_out(vty
, "/%pIA", &eo
->gw_ip
);
9874 json_object_string_addf(json_overlay
, "gw", "%pIA", &eo
->gw_ip
);
9876 if (bgp_attr_get_ecommunity(attr
)) {
9878 struct ecommunity_val
*routermac
= ecommunity_lookup(
9879 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9880 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9883 mac
= ecom_mac2str((char *)routermac
->val
);
9886 vty_out(vty
, "/%s", mac
);
9888 json_object_string_add(json_overlay
, "rmac",
9891 XFREE(MTYPE_TMP
, mac
);
9898 json_object_object_add(json_path
, "overlay", json_overlay
);
9900 json_object_array_add(json_paths
, json_path
);
9904 /* dampening route */
9905 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9906 struct bgp_path_info
*path
, int display
,
9907 afi_t afi
, safi_t safi
, bool use_json
,
9908 json_object
*json_paths
)
9910 struct attr
*attr
= path
->attr
;
9912 char timebuf
[BGP_UPTIME_LEN
];
9913 json_object
*json_path
= NULL
;
9916 json_path
= json_object_new_object();
9918 /* short status lead text */
9919 route_vty_short_status_out(vty
, path
, p
, json_path
);
9921 /* print prefix and mask */
9924 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9926 vty_out(vty
, "%*s", 17, " ");
9928 len
= vty_out(vty
, "%s", path
->peer
->host
);
9932 vty_out(vty
, "\n%*s", 34, " ");
9934 vty_out(vty
, "%*s", len
, " ");
9937 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9938 BGP_UPTIME_LEN
, afi
, safi
,
9942 aspath_print_vty(vty
, attr
->aspath
);
9944 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9948 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9949 safi
, use_json
, json_path
);
9952 json_object_string_add(json_path
, "asPath",
9955 json_object_string_add(json_path
, "origin",
9956 bgp_origin_str
[attr
->origin
]);
9957 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9959 json_object_array_add(json_paths
, json_path
);
9964 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9965 struct bgp_path_info
*path
, int display
,
9966 afi_t afi
, safi_t safi
, bool use_json
,
9967 json_object
*json_paths
)
9969 struct attr
*attr
= path
->attr
;
9970 struct bgp_damp_info
*bdi
;
9971 char timebuf
[BGP_UPTIME_LEN
];
9973 json_object
*json_path
= NULL
;
9979 json_path
= json_object_new_object();
9981 bdi
= path
->extra
->damp_info
;
9983 /* short status lead text */
9984 route_vty_short_status_out(vty
, path
, p
, json_path
);
9988 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9990 vty_out(vty
, "%*s", 17, " ");
9992 len
= vty_out(vty
, "%s", path
->peer
->host
);
9995 vty_out(vty
, "\n%*s", 33, " ");
9997 vty_out(vty
, "%*s", len
, " ");
9999 len
= vty_out(vty
, "%d", bdi
->flap
);
10004 vty_out(vty
, "%*s", len
, " ");
10006 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
10007 BGP_UPTIME_LEN
, 0, NULL
));
10009 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10010 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10011 vty_out(vty
, "%s ",
10012 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10013 BGP_UPTIME_LEN
, afi
,
10014 safi
, use_json
, NULL
));
10016 vty_out(vty
, "%*s ", 8, " ");
10019 aspath_print_vty(vty
, attr
->aspath
);
10021 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10023 vty_out(vty
, "\n");
10025 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10026 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
10028 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
10031 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10032 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10033 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10034 BGP_UPTIME_LEN
, afi
, safi
,
10035 use_json
, json_path
);
10038 json_object_string_add(json_path
, "asPath",
10039 attr
->aspath
->str
);
10041 json_object_string_add(json_path
, "origin",
10042 bgp_origin_str
[attr
->origin
]);
10044 json_object_array_add(json_paths
, json_path
);
10048 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
10049 int *first
, const char *header
,
10050 json_object
*json_adv_to
)
10052 json_object
*json_peer
= NULL
;
10055 /* 'advertised-to' is a dictionary of peers we have advertised
10057 * prefix too. The key is the peer's IP or swpX, the value is
10059 * hostname if we know it and "" if not.
10061 json_peer
= json_object_new_object();
10063 if (peer
->hostname
)
10064 json_object_string_add(json_peer
, "hostname",
10068 json_object_object_add(json_adv_to
, peer
->conf_if
,
10071 json_object_object_addf(json_adv_to
, json_peer
, "%pSU",
10075 vty_out(vty
, "%s", header
);
10080 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
10082 vty_out(vty
, " %s(%s)", peer
->hostname
,
10085 vty_out(vty
, " %s(%pSU)", peer
->hostname
,
10089 vty_out(vty
, " %s", peer
->conf_if
);
10091 vty_out(vty
, " %pSU", &peer
->su
);
10096 static void route_vty_out_tx_ids(struct vty
*vty
,
10097 struct bgp_addpath_info_data
*d
)
10101 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10102 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
10103 d
->addpath_tx_id
[i
],
10104 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
10108 static void route_vty_out_detail_es_info(struct vty
*vty
,
10109 struct bgp_path_info
*pi
,
10111 json_object
*json_path
)
10113 char esi_buf
[ESI_STR_LEN
];
10114 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
10115 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
10116 ATTR_ES_PEER_ROUTER
);
10117 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
10118 ATTR_ES_PEER_ACTIVE
);
10119 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
10120 ATTR_ES_PEER_PROXY
);
10121 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
10123 json_object
*json_es_info
= NULL
;
10125 json_object_string_add(
10128 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
10129 json_es_info
= json_object_new_object();
10131 json_object_boolean_true_add(
10132 json_es_info
, "localEs");
10134 json_object_boolean_true_add(
10135 json_es_info
, "peerActive");
10137 json_object_boolean_true_add(
10138 json_es_info
, "peerProxy");
10140 json_object_boolean_true_add(
10141 json_es_info
, "peerRouter");
10142 if (attr
->mm_sync_seqnum
)
10143 json_object_int_add(
10144 json_es_info
, "peerSeq",
10145 attr
->mm_sync_seqnum
);
10146 json_object_object_add(
10147 json_path
, "es_info",
10151 if (bgp_evpn_attr_is_sync(attr
))
10153 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10155 es_local
? "local-es":"",
10156 peer_proxy
? "proxy " : "",
10157 peer_active
? "active ":"",
10158 peer_router
? "router ":"",
10159 attr
->mm_sync_seqnum
);
10161 vty_out(vty
, " ESI %s %s\n",
10163 es_local
? "local-es":"");
10167 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
10168 const struct prefix
*p
, struct bgp_path_info
*path
,
10169 afi_t afi
, safi_t safi
,
10170 enum rpki_states rpki_curr_state
,
10171 json_object
*json_paths
)
10173 char buf
[INET6_ADDRSTRLEN
];
10175 struct attr
*attr
= path
->attr
;
10177 json_object
*json_bestpath
= NULL
;
10178 json_object
*json_cluster_list
= NULL
;
10179 json_object
*json_cluster_list_list
= NULL
;
10180 json_object
*json_ext_community
= NULL
;
10181 json_object
*json_last_update
= NULL
;
10182 json_object
*json_pmsi
= NULL
;
10183 json_object
*json_nexthop_global
= NULL
;
10184 json_object
*json_nexthop_ll
= NULL
;
10185 json_object
*json_nexthops
= NULL
;
10186 json_object
*json_path
= NULL
;
10187 json_object
*json_peer
= NULL
;
10188 json_object
*json_string
= NULL
;
10189 json_object
*json_adv_to
= NULL
;
10191 struct listnode
*node
, *nnode
;
10193 bool addpath_capable
;
10195 unsigned int first_as
;
10196 bool nexthop_self
=
10197 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
10199 char *nexthop_hostname
=
10200 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
10204 mpls_label_t label
= MPLS_INVALID_LABEL
;
10206 struct bgp_path_info
*bpi_ultimate
=
10207 bgp_get_imported_bpi_ultimate(path
);
10210 json_path
= json_object_new_object();
10211 json_peer
= json_object_new_object();
10212 json_nexthop_global
= json_object_new_object();
10215 if (safi
== SAFI_EVPN
) {
10217 vty_out(vty
, " Route %pFX", p
);
10221 if (path
->extra
&& path
->extra
->num_labels
) {
10222 bgp_evpn_label2str(path
->extra
->label
,
10223 path
->extra
->num_labels
, tag_buf
,
10226 if (safi
== SAFI_EVPN
) {
10228 if (tag_buf
[0] != '\0')
10229 vty_out(vty
, " VNI %s", tag_buf
);
10232 json_object_string_add(json_path
, "vni",
10238 if (safi
== SAFI_EVPN
10239 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
10240 char gwip_buf
[INET6_ADDRSTRLEN
];
10242 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
10246 json_object_string_add(json_path
, "gatewayIP",
10249 vty_out(vty
, " Gateway IP %s", gwip_buf
);
10252 if (safi
== SAFI_EVPN
&& !json_path
)
10253 vty_out(vty
, "\n");
10256 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
10257 struct bgp_path_info
*parent_ri
;
10258 struct bgp_dest
*dest
, *pdest
;
10260 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
10261 dest
= parent_ri
->net
;
10262 if (dest
&& dest
->pdest
) {
10263 pdest
= dest
->pdest
;
10264 if (is_pi_family_evpn(parent_ri
)) {
10265 vty_out(vty
, " Imported from ");
10266 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
10267 (struct prefix_rd
*)bgp_dest_get_prefix(
10269 vty_out(vty
, ":%pFX, VNI %s",
10270 (struct prefix_evpn
*)
10271 bgp_dest_get_prefix(dest
),
10273 if (CHECK_FLAG(attr
->es_flags
, ATTR_ES_L3_NHG
))
10274 vty_out(vty
, ", L3NHG %s",
10277 ATTR_ES_L3_NHG_ACTIVE
)
10280 vty_out(vty
, "\n");
10283 vty_out(vty
, " Imported from ");
10284 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
10285 (struct prefix_rd
*)bgp_dest_get_prefix(
10287 vty_out(vty
, ":%pFX\n",
10288 (struct prefix_evpn
*)
10289 bgp_dest_get_prefix(dest
));
10294 /* Line1 display AS-path, Aggregator */
10295 if (attr
->aspath
) {
10297 if (!attr
->aspath
->json
)
10298 aspath_str_update(attr
->aspath
, true);
10299 json_object_lock(attr
->aspath
->json
);
10300 json_object_object_add(json_path
, "aspath",
10301 attr
->aspath
->json
);
10303 if (attr
->aspath
->segments
)
10304 vty_out(vty
, " %s", attr
->aspath
->str
);
10306 vty_out(vty
, " Local");
10310 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
10312 json_object_boolean_true_add(json_path
, "removed");
10314 vty_out(vty
, ", (removed)");
10317 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10319 json_object_boolean_true_add(json_path
, "stale");
10321 vty_out(vty
, ", (stale)");
10324 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
10326 json_object_int_add(json_path
, "aggregatorAs",
10327 attr
->aggregator_as
);
10328 json_object_string_addf(json_path
, "aggregatorId",
10329 "%pI4", &attr
->aggregator_addr
);
10331 vty_out(vty
, ", (aggregated by %u %pI4)",
10332 attr
->aggregator_as
, &attr
->aggregator_addr
);
10336 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10337 PEER_FLAG_REFLECTOR_CLIENT
)) {
10339 json_object_boolean_true_add(json_path
,
10340 "rxedFromRrClient");
10342 vty_out(vty
, ", (Received from a RR-client)");
10345 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10346 PEER_FLAG_RSERVER_CLIENT
)) {
10348 json_object_boolean_true_add(json_path
,
10349 "rxedFromRsClient");
10351 vty_out(vty
, ", (Received from a RS-client)");
10354 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10356 json_object_boolean_true_add(json_path
,
10357 "dampeningHistoryEntry");
10359 vty_out(vty
, ", (history entry)");
10360 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10362 json_object_boolean_true_add(json_path
,
10363 "dampeningSuppressed");
10365 vty_out(vty
, ", (suppressed due to dampening)");
10369 vty_out(vty
, "\n");
10371 /* Line2 display Next-hop, Neighbor, Router-id */
10372 /* Display the nexthop */
10374 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
||
10375 p
->family
== AF_EVPN
) &&
10376 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
||
10377 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10378 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10379 || safi
== SAFI_EVPN
) {
10381 json_object_string_addf(
10382 json_nexthop_global
, "ip", "%pI4",
10383 &attr
->mp_nexthop_global_in
);
10385 if (path
->peer
->hostname
)
10386 json_object_string_add(
10387 json_nexthop_global
, "hostname",
10388 path
->peer
->hostname
);
10390 if (nexthop_hostname
)
10391 vty_out(vty
, " %pI4(%s)",
10392 &attr
->mp_nexthop_global_in
,
10395 vty_out(vty
, " %pI4",
10396 &attr
->mp_nexthop_global_in
);
10400 json_object_string_addf(json_nexthop_global
,
10404 if (path
->peer
->hostname
)
10405 json_object_string_add(
10406 json_nexthop_global
, "hostname",
10407 path
->peer
->hostname
);
10409 if (nexthop_hostname
)
10410 vty_out(vty
, " %pI4(%s)",
10414 vty_out(vty
, " %pI4",
10420 json_object_string_add(json_nexthop_global
, "afi",
10424 json_object_string_addf(json_nexthop_global
, "ip",
10426 &attr
->mp_nexthop_global
);
10428 if (path
->peer
->hostname
)
10429 json_object_string_add(json_nexthop_global
,
10431 path
->peer
->hostname
);
10433 json_object_string_add(json_nexthop_global
, "afi",
10435 json_object_string_add(json_nexthop_global
, "scope",
10438 if (nexthop_hostname
)
10439 vty_out(vty
, " %pI6(%s)",
10440 &attr
->mp_nexthop_global
,
10443 vty_out(vty
, " %pI6",
10444 &attr
->mp_nexthop_global
);
10448 /* Display the IGP cost or 'inaccessible' */
10449 if (!CHECK_FLAG(bpi_ultimate
->flags
, BGP_PATH_VALID
)) {
10450 bool import
= CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
);
10453 json_object_boolean_false_add(json_nexthop_global
,
10455 json_object_boolean_add(json_nexthop_global
,
10456 "importCheckEnabled", import
);
10458 vty_out(vty
, " (inaccessible%s)",
10459 import
? ", import-check enabled" : "");
10462 if (bpi_ultimate
->extra
&& bpi_ultimate
->extra
->igpmetric
) {
10464 json_object_int_add(
10465 json_nexthop_global
, "metric",
10466 bpi_ultimate
->extra
->igpmetric
);
10468 vty_out(vty
, " (metric %u)",
10469 bpi_ultimate
->extra
->igpmetric
);
10472 /* IGP cost is 0, display this only for json */
10475 json_object_int_add(json_nexthop_global
,
10480 json_object_boolean_true_add(json_nexthop_global
,
10484 /* Display peer "from" output */
10485 /* This path was originated locally */
10486 if (path
->peer
== bgp
->peer_self
) {
10488 if (safi
== SAFI_EVPN
|| (p
->family
== AF_INET
&&
10489 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10491 json_object_string_add(json_peer
, "peerId",
10494 vty_out(vty
, " from 0.0.0.0 ");
10497 json_object_string_add(json_peer
, "peerId",
10500 vty_out(vty
, " from :: ");
10504 json_object_string_addf(json_peer
, "routerId", "%pI4",
10507 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10510 /* We RXed this path from one of our peers */
10514 json_object_string_addf(json_peer
, "peerId", "%pSU",
10516 json_object_string_addf(json_peer
, "routerId", "%pI4",
10517 &path
->peer
->remote_id
);
10519 if (path
->peer
->hostname
)
10520 json_object_string_add(json_peer
, "hostname",
10521 path
->peer
->hostname
);
10523 if (path
->peer
->domainname
)
10524 json_object_string_add(json_peer
, "domainname",
10525 path
->peer
->domainname
);
10527 if (path
->peer
->conf_if
)
10528 json_object_string_add(json_peer
, "interface",
10529 path
->peer
->conf_if
);
10531 if (path
->peer
->conf_if
) {
10532 if (path
->peer
->hostname
10533 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10534 BGP_FLAG_SHOW_HOSTNAME
))
10535 vty_out(vty
, " from %s(%s)",
10536 path
->peer
->hostname
,
10537 path
->peer
->conf_if
);
10539 vty_out(vty
, " from %s",
10540 path
->peer
->conf_if
);
10542 if (path
->peer
->hostname
10543 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10544 BGP_FLAG_SHOW_HOSTNAME
))
10545 vty_out(vty
, " from %s(%s)",
10546 path
->peer
->hostname
,
10549 vty_out(vty
, " from %pSU",
10553 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10554 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10556 vty_out(vty
, " (%pI4)", &path
->peer
->remote_id
);
10561 * Note when vrfid of nexthop is different from that of prefix
10563 if (path
->extra
&& path
->extra
->bgp_orig
) {
10564 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10569 if (path
->extra
->bgp_orig
->inst_type
10570 == BGP_INSTANCE_TYPE_DEFAULT
)
10571 vn
= VRF_DEFAULT_NAME
;
10573 vn
= path
->extra
->bgp_orig
->name
;
10575 json_object_string_add(json_path
, "nhVrfName", vn
);
10577 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10578 json_object_int_add(json_path
, "nhVrfId", -1);
10580 json_object_int_add(json_path
, "nhVrfId",
10581 (int)nexthop_vrfid
);
10584 if (nexthop_vrfid
== VRF_UNKNOWN
)
10585 vty_out(vty
, " vrf ?");
10589 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10590 vty_out(vty
, " vrf %s(%u)",
10591 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10596 if (nexthop_self
) {
10598 json_object_boolean_true_add(json_path
,
10599 "announceNexthopSelf");
10601 vty_out(vty
, " announce-nh-self");
10606 vty_out(vty
, "\n");
10608 /* display the link-local nexthop */
10609 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10611 json_nexthop_ll
= json_object_new_object();
10612 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10613 &attr
->mp_nexthop_local
);
10615 if (path
->peer
->hostname
)
10616 json_object_string_add(json_nexthop_ll
,
10618 path
->peer
->hostname
);
10620 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10621 json_object_string_add(json_nexthop_ll
, "scope",
10624 json_object_boolean_true_add(json_nexthop_ll
,
10627 if (!attr
->mp_nexthop_prefer_global
)
10628 json_object_boolean_true_add(json_nexthop_ll
,
10631 json_object_boolean_true_add(
10632 json_nexthop_global
, "used");
10634 vty_out(vty
, " (%s) %s\n",
10635 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10636 buf
, INET6_ADDRSTRLEN
),
10637 attr
->mp_nexthop_prefer_global
10638 ? "(prefer-global)"
10642 /* If we do not have a link-local nexthop then we must flag the
10643 global as "used" */
10646 json_object_boolean_true_add(json_nexthop_global
,
10650 if (safi
== SAFI_EVPN
&&
10651 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10652 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10655 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10656 * Int/Ext/Local, Atomic, best */
10658 json_object_string_add(json_path
, "origin",
10659 bgp_origin_long_str
[attr
->origin
]);
10661 vty_out(vty
, " Origin %s",
10662 bgp_origin_long_str
[attr
->origin
]);
10664 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10666 json_object_int_add(json_path
, "metric", attr
->med
);
10668 vty_out(vty
, ", metric %u", attr
->med
);
10671 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10673 json_object_int_add(json_path
, "locPrf",
10676 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10679 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
10681 json_object_int_add(json_path
, "aigpMetric",
10682 bgp_attr_get_aigp_metric(attr
));
10684 vty_out(vty
, ", aigp-metric %" PRIu64
,
10685 bgp_attr_get_aigp_metric(attr
));
10688 if (attr
->weight
!= 0) {
10690 json_object_int_add(json_path
, "weight", attr
->weight
);
10692 vty_out(vty
, ", weight %u", attr
->weight
);
10695 if (attr
->tag
!= 0) {
10697 json_object_int_add(json_path
, "tag", attr
->tag
);
10699 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10702 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10704 json_object_boolean_false_add(json_path
, "valid");
10706 vty_out(vty
, ", invalid");
10707 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10709 json_object_boolean_true_add(json_path
, "valid");
10711 vty_out(vty
, ", valid");
10715 json_object_int_add(json_path
, "version", bn
->version
);
10717 if (path
->peer
!= bgp
->peer_self
) {
10718 if (path
->peer
->as
== path
->peer
->local_as
) {
10719 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10721 json_object_string_add(
10723 "confed-internal");
10725 vty_out(vty
, ", confed-internal");
10728 json_object_string_add(
10729 json_peer
, "type", "internal");
10731 vty_out(vty
, ", internal");
10734 if (bgp_confederation_peers_check(bgp
,
10737 json_object_string_add(
10739 "confed-external");
10741 vty_out(vty
, ", confed-external");
10744 json_object_string_add(
10745 json_peer
, "type", "external");
10747 vty_out(vty
, ", external");
10750 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10752 json_object_boolean_true_add(json_path
, "aggregated");
10753 json_object_boolean_true_add(json_path
, "local");
10755 vty_out(vty
, ", aggregated, local");
10757 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10759 json_object_boolean_true_add(json_path
, "sourced");
10761 vty_out(vty
, ", sourced");
10764 json_object_boolean_true_add(json_path
, "sourced");
10765 json_object_boolean_true_add(json_path
, "local");
10767 vty_out(vty
, ", sourced, local");
10771 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10773 json_object_boolean_true_add(json_path
,
10774 "atomicAggregate");
10776 vty_out(vty
, ", atomic-aggregate");
10779 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
10781 json_object_int_add(json_path
, "otc", attr
->otc
);
10783 vty_out(vty
, ", otc %u", attr
->otc
);
10786 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10787 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10788 && bgp_path_info_mpath_count(path
))) {
10790 json_object_boolean_true_add(json_path
, "multipath");
10792 vty_out(vty
, ", multipath");
10795 // Mark the bestpath(s)
10796 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10797 first_as
= aspath_get_first_as(attr
->aspath
);
10800 if (!json_bestpath
)
10801 json_bestpath
= json_object_new_object();
10802 json_object_int_add(json_bestpath
, "bestpathFromAs",
10806 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10808 vty_out(vty
, ", bestpath-from-AS Local");
10812 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10814 if (!json_bestpath
)
10815 json_bestpath
= json_object_new_object();
10816 json_object_boolean_true_add(json_bestpath
, "overall");
10817 json_object_string_add(
10818 json_bestpath
, "selectionReason",
10819 bgp_path_selection_reason2str(bn
->reason
));
10821 vty_out(vty
, ", best");
10822 vty_out(vty
, " (%s)",
10823 bgp_path_selection_reason2str(bn
->reason
));
10827 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10829 json_object_string_add(
10830 json_path
, "rpkiValidationState",
10831 bgp_rpki_validation2str(rpki_curr_state
));
10833 vty_out(vty
, ", rpki validation-state: %s",
10834 bgp_rpki_validation2str(rpki_curr_state
));
10838 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10841 vty_out(vty
, "\n");
10843 /* Line 4 display Community */
10844 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10846 if (!bgp_attr_get_community(attr
)->json
)
10847 community_str(bgp_attr_get_community(attr
),
10849 json_object_lock(bgp_attr_get_community(attr
)->json
);
10850 json_object_object_add(
10851 json_path
, "community",
10852 bgp_attr_get_community(attr
)->json
);
10854 vty_out(vty
, " Community: %s\n",
10855 bgp_attr_get_community(attr
)->str
);
10859 /* Line 5 display Extended-community */
10860 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10862 json_ext_community
= json_object_new_object();
10863 json_object_string_add(
10864 json_ext_community
, "string",
10865 bgp_attr_get_ecommunity(attr
)->str
);
10866 json_object_object_add(json_path
, "extendedCommunity",
10867 json_ext_community
);
10869 vty_out(vty
, " Extended Community: %s\n",
10870 bgp_attr_get_ecommunity(attr
)->str
);
10874 /* Line 6 display Large community */
10875 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10877 if (!bgp_attr_get_lcommunity(attr
)->json
)
10878 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10880 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10881 json_object_object_add(
10882 json_path
, "largeCommunity",
10883 bgp_attr_get_lcommunity(attr
)->json
);
10885 vty_out(vty
, " Large Community: %s\n",
10886 bgp_attr_get_lcommunity(attr
)->str
);
10890 /* Line 7 display Originator, Cluster-id */
10891 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10892 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10893 char buf
[BUFSIZ
] = {0};
10895 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10897 json_object_string_addf(json_path
,
10898 "originatorId", "%pI4",
10899 &attr
->originator_id
);
10901 vty_out(vty
, " Originator: %pI4",
10902 &attr
->originator_id
);
10905 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10906 struct cluster_list
*cluster
=
10907 bgp_attr_get_cluster(attr
);
10911 json_cluster_list
= json_object_new_object();
10912 json_cluster_list_list
=
10913 json_object_new_array();
10915 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10916 json_string
= json_object_new_string(
10919 buf
, sizeof(buf
)));
10920 json_object_array_add(
10921 json_cluster_list_list
,
10926 * struct cluster_list does not have
10927 * "str" variable like aspath and community
10928 * do. Add this someday if someone asks
10930 * json_object_string_add(json_cluster_list,
10931 * "string", cluster->str);
10933 json_object_object_add(json_cluster_list
,
10935 json_cluster_list_list
);
10936 json_object_object_add(json_path
, "clusterList",
10937 json_cluster_list
);
10939 vty_out(vty
, ", Cluster list: ");
10941 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10942 vty_out(vty
, "%pI4 ",
10943 &cluster
->list
[i
]);
10949 vty_out(vty
, "\n");
10952 if (path
->extra
&& path
->extra
->damp_info
)
10953 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
10956 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10957 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10958 mpls_lse_decode(path
->extra
->label
[0], &label
, &ttl
, &exp
,
10962 json_object_int_add(json_path
, "remoteLabel", label
);
10964 vty_out(vty
, " Remote label: %d\n", label
);
10968 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10970 json_object_string_addf(json_path
, "remoteSid", "%pI6",
10971 &path
->extra
->sid
[0].sid
);
10973 vty_out(vty
, " Remote SID: %pI6\n",
10974 &path
->extra
->sid
[0].sid
);
10978 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
10980 json_object_int_add(json_path
, "labelIndex",
10981 attr
->label_index
);
10983 vty_out(vty
, " Label Index: %d\n",
10984 attr
->label_index
);
10987 /* Line 8 display Addpath IDs */
10988 if (path
->addpath_rx_id
10989 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
10991 json_object_int_add(json_path
, "addpathRxId",
10992 path
->addpath_rx_id
);
10994 /* Keep backwards compatibility with the old API
10995 * by putting TX All's ID in the old field
10997 json_object_int_add(
10998 json_path
, "addpathTxId",
11000 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
11002 /* ... but create a specific field for each
11005 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
11006 json_object_int_add(
11008 bgp_addpath_names(i
)->id_json_name
,
11009 path
->tx_addpath
.addpath_tx_id
[i
]);
11012 vty_out(vty
, " AddPath ID: RX %u, ",
11013 path
->addpath_rx_id
);
11015 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
11019 /* If we used addpath to TX a non-bestpath we need to display
11020 * "Advertised to" on a path-by-path basis
11022 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11025 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11027 bgp_addpath_encode_tx(peer
, afi
, safi
);
11028 has_adj
= bgp_adj_out_lookup(
11030 bgp_addpath_id_for_peer(peer
, afi
, safi
,
11031 &path
->tx_addpath
));
11033 if ((addpath_capable
&& has_adj
)
11034 || (!addpath_capable
&& has_adj
11035 && CHECK_FLAG(path
->flags
,
11036 BGP_PATH_SELECTED
))) {
11037 if (json_path
&& !json_adv_to
)
11038 json_adv_to
= json_object_new_object();
11040 route_vty_out_advertised_to(
11042 " Advertised to:", json_adv_to
);
11048 json_object_object_add(
11049 json_path
, "advertisedTo", json_adv_to
);
11053 vty_out(vty
, "\n");
11058 /* Line 9 display Uptime */
11059 tbuf
= time(NULL
) - (monotime(NULL
) - path
->uptime
);
11061 json_last_update
= json_object_new_object();
11062 json_object_int_add(json_last_update
, "epoch", tbuf
);
11063 json_object_string_add(json_last_update
, "string",
11065 json_object_object_add(json_path
, "lastUpdate",
11068 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
11070 /* Line 10 display PMSI tunnel attribute, if present */
11071 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
11072 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
11073 bgp_attr_get_pmsi_tnl_type(attr
),
11074 PMSI_TNLTYPE_STR_DEFAULT
);
11077 json_pmsi
= json_object_new_object();
11078 json_object_string_add(json_pmsi
, "tunnelType", str
);
11079 json_object_int_add(json_pmsi
, "label",
11080 label2vni(&attr
->label
));
11081 json_object_object_add(json_path
, "pmsi", json_pmsi
);
11083 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
11084 str
, label2vni(&attr
->label
));
11087 if (path
->peer
->t_gr_restart
&&
11088 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
11089 unsigned long gr_remaining
=
11090 event_timer_remain_second(path
->peer
->t_gr_restart
);
11093 json_object_int_add(json_path
,
11094 "gracefulRestartSecondsRemaining",
11098 " Time until Graceful Restart stale route deleted: %lu\n",
11102 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
11103 bgp_attr_get_community(attr
) &&
11104 community_include(bgp_attr_get_community(attr
),
11105 COMMUNITY_LLGR_STALE
)) {
11106 unsigned long llgr_remaining
= event_timer_remain_second(
11107 path
->peer
->t_llgr_stale
[afi
][safi
]);
11110 json_object_int_add(json_path
, "llgrSecondsRemaining",
11114 " Time until Long-lived stale route deleted: %lu\n",
11118 /* Output some debug about internal state of the dest flags */
11120 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
11121 json_object_boolean_true_add(json_path
, "processScheduled");
11122 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
11123 json_object_boolean_true_add(json_path
, "userCleared");
11124 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
11125 json_object_boolean_true_add(json_path
, "labelChanged");
11126 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
11127 json_object_boolean_true_add(json_path
, "registeredForLabel");
11128 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
11129 json_object_boolean_true_add(json_path
, "selectDefered");
11130 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
11131 json_object_boolean_true_add(json_path
, "fibInstalled");
11132 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
11133 json_object_boolean_true_add(json_path
, "fibPending");
11135 if (json_nexthop_global
|| json_nexthop_ll
) {
11136 json_nexthops
= json_object_new_array();
11138 if (json_nexthop_global
)
11139 json_object_array_add(json_nexthops
,
11140 json_nexthop_global
);
11142 if (json_nexthop_ll
)
11143 json_object_array_add(json_nexthops
,
11146 json_object_object_add(json_path
, "nexthops",
11150 json_object_object_add(json_path
, "peer", json_peer
);
11151 json_object_array_add(json_paths
, json_path
);
11155 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
11156 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11157 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
11159 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11160 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11162 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11163 const char *comstr
, int exact
, afi_t afi
,
11164 safi_t safi
, uint16_t show_flags
);
11166 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11167 struct bgp_table
*table
, enum bgp_show_type type
,
11168 void *output_arg
, const char *rd
, int is_last
,
11169 unsigned long *output_cum
, unsigned long *total_cum
,
11170 unsigned long *json_header_depth
, uint16_t show_flags
,
11171 enum rpki_states rpki_target_state
)
11173 struct bgp_path_info
*pi
;
11174 struct bgp_dest
*dest
;
11175 bool header
= true;
11176 bool json_detail_header
= false;
11178 unsigned long output_count
= 0;
11179 unsigned long total_count
= 0;
11181 json_object
*json_paths
= NULL
;
11183 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11184 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11185 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11186 bool detail_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
11187 bool detail_routes
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
11189 if (output_cum
&& *output_cum
!= 0)
11192 if (use_json
&& !*json_header_depth
) {
11194 *json_header_depth
= 1;
11196 vty_out(vty
, "{\n");
11197 *json_header_depth
= 2;
11200 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11201 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
11203 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
11204 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
11207 table
->version
, &bgp
->router_id
,
11208 bgp
->default_local_pref
);
11209 if ((bgp
->asnotation
== ASNOTATION_PLAIN
) ||
11210 ((bgp
->asnotation
== ASNOTATION_DOT
) &&
11211 (bgp
->as
< UINT16_MAX
)))
11212 vty_out(vty
, "%u", bgp
->as
);
11214 vty_out(vty
, "\"");
11215 vty_out(vty
, ASN_FORMAT(bgp
->asnotation
), &bgp
->as
);
11216 vty_out(vty
, "\"");
11218 vty_out(vty
, ",\n \"routes\": { ");
11220 vty_out(vty
, " \"routeDistinguishers\" : {");
11221 ++*json_header_depth
;
11225 if (use_json
&& rd
) {
11226 vty_out(vty
, " \"%s\" : { ", rd
);
11229 /* Check for 'json detail', where we need header output once per dest */
11230 if (use_json
&& detail_json
&& type
!= bgp_show_type_dampend_paths
&&
11231 type
!= bgp_show_type_damp_neighbor
&&
11232 type
!= bgp_show_type_flap_statistics
&&
11233 type
!= bgp_show_type_flap_neighbor
)
11234 json_detail_header
= true;
11236 /* Start processing of routes. */
11237 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
11238 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11239 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11240 bool json_detail_header_used
= false;
11242 pi
= bgp_dest_get_bgp_path_info(dest
);
11248 json_paths
= json_object_new_array();
11252 for (; pi
; pi
= pi
->next
) {
11253 struct community
*picomm
= NULL
;
11255 picomm
= bgp_attr_get_community(pi
->attr
);
11259 if (type
== bgp_show_type_prefix_version
) {
11261 strtoul(output_arg
, NULL
, 10);
11262 if (dest
->version
< version
)
11266 if (type
== bgp_show_type_community_alias
) {
11267 char *alias
= output_arg
;
11268 char **communities
;
11270 bool found
= false;
11273 frrstr_split(picomm
->str
, " ",
11274 &communities
, &num
);
11275 for (int i
= 0; i
< num
; i
++) {
11276 const char *com2alias
=
11277 bgp_community2alias(
11280 && strcmp(alias
, com2alias
)
11286 XFREE(MTYPE_TMP
, communities
);
11290 bgp_attr_get_lcommunity(pi
->attr
)) {
11291 frrstr_split(bgp_attr_get_lcommunity(
11294 " ", &communities
, &num
);
11295 for (int i
= 0; i
< num
; i
++) {
11296 const char *com2alias
=
11297 bgp_community2alias(
11300 && strcmp(alias
, com2alias
)
11306 XFREE(MTYPE_TMP
, communities
);
11313 if (type
== bgp_show_type_rpki
) {
11314 if (dest_p
->family
== AF_INET
11315 || dest_p
->family
== AF_INET6
)
11316 rpki_curr_state
= hook_call(
11317 bgp_rpki_prefix_status
,
11318 pi
->peer
, pi
->attr
, dest_p
);
11319 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11320 && rpki_curr_state
!= rpki_target_state
)
11324 if (type
== bgp_show_type_flap_statistics
11325 || type
== bgp_show_type_flap_neighbor
11326 || type
== bgp_show_type_dampend_paths
11327 || type
== bgp_show_type_damp_neighbor
) {
11328 if (!(pi
->extra
&& pi
->extra
->damp_info
))
11331 if (type
== bgp_show_type_regexp
) {
11332 regex_t
*regex
= output_arg
;
11334 if (bgp_regexec(regex
, pi
->attr
->aspath
)
11338 if (type
== bgp_show_type_prefix_list
) {
11339 struct prefix_list
*plist
= output_arg
;
11341 if (prefix_list_apply(plist
, dest_p
)
11345 if (type
== bgp_show_type_access_list
) {
11346 struct access_list
*alist
= output_arg
;
11348 if (access_list_apply(alist
, dest_p
) !=
11352 if (type
== bgp_show_type_filter_list
) {
11353 struct as_list
*as_list
= output_arg
;
11355 if (as_list_apply(as_list
, pi
->attr
->aspath
)
11356 != AS_FILTER_PERMIT
)
11359 if (type
== bgp_show_type_route_map
) {
11360 struct route_map
*rmap
= output_arg
;
11361 struct bgp_path_info path
;
11362 struct bgp_path_info_extra extra
;
11363 struct attr dummy_attr
= {};
11364 route_map_result_t ret
;
11366 dummy_attr
= *pi
->attr
;
11368 prep_for_rmap_apply(&path
, &extra
, dest
, pi
,
11369 pi
->peer
, &dummy_attr
);
11371 ret
= route_map_apply(rmap
, dest_p
, &path
);
11372 bgp_attr_flush(&dummy_attr
);
11373 if (ret
== RMAP_DENYMATCH
)
11376 if (type
== bgp_show_type_neighbor
11377 || type
== bgp_show_type_flap_neighbor
11378 || type
== bgp_show_type_damp_neighbor
) {
11379 union sockunion
*su
= output_arg
;
11381 if (pi
->peer
== NULL
11382 || pi
->peer
->su_remote
== NULL
11383 || !sockunion_same(pi
->peer
->su_remote
, su
))
11386 if (type
== bgp_show_type_cidr_only
) {
11387 uint32_t destination
;
11389 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11390 if (IN_CLASSC(destination
)
11391 && dest_p
->prefixlen
== 24)
11393 if (IN_CLASSB(destination
)
11394 && dest_p
->prefixlen
== 16)
11396 if (IN_CLASSA(destination
)
11397 && dest_p
->prefixlen
== 8)
11400 if (type
== bgp_show_type_prefix_longer
) {
11402 if (!prefix_match(p
, dest_p
))
11405 if (type
== bgp_show_type_community_all
) {
11409 if (type
== bgp_show_type_community
) {
11410 struct community
*com
= output_arg
;
11412 if (!picomm
|| !community_match(picomm
, com
))
11415 if (type
== bgp_show_type_community_exact
) {
11416 struct community
*com
= output_arg
;
11418 if (!picomm
|| !community_cmp(picomm
, com
))
11421 if (type
== bgp_show_type_community_list
) {
11422 struct community_list
*list
= output_arg
;
11424 if (!community_list_match(picomm
, list
))
11427 if (type
== bgp_show_type_community_list_exact
) {
11428 struct community_list
*list
= output_arg
;
11430 if (!community_list_exact_match(picomm
, list
))
11433 if (type
== bgp_show_type_lcommunity
) {
11434 struct lcommunity
*lcom
= output_arg
;
11436 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11438 bgp_attr_get_lcommunity(pi
->attr
),
11443 if (type
== bgp_show_type_lcommunity_exact
) {
11444 struct lcommunity
*lcom
= output_arg
;
11446 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11448 bgp_attr_get_lcommunity(pi
->attr
),
11452 if (type
== bgp_show_type_lcommunity_list
) {
11453 struct community_list
*list
= output_arg
;
11455 if (!lcommunity_list_match(
11456 bgp_attr_get_lcommunity(pi
->attr
),
11461 == bgp_show_type_lcommunity_list_exact
) {
11462 struct community_list
*list
= output_arg
;
11464 if (!lcommunity_list_exact_match(
11465 bgp_attr_get_lcommunity(pi
->attr
),
11469 if (type
== bgp_show_type_lcommunity_all
) {
11470 if (!bgp_attr_get_lcommunity(pi
->attr
))
11473 if (type
== bgp_show_type_dampend_paths
11474 || type
== bgp_show_type_damp_neighbor
) {
11475 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11476 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11479 if (type
== bgp_show_type_self_originated
) {
11480 if (pi
->peer
!= bgp
->peer_self
)
11484 if (!use_json
&& header
) {
11486 "BGP table version is %" PRIu64
11487 ", local router ID is %pI4, vrf id ",
11488 table
->version
, &bgp
->router_id
);
11489 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11490 vty_out(vty
, "%s", VRFID_NONE_STR
);
11492 vty_out(vty
, "%u", bgp
->vrf_id
);
11493 vty_out(vty
, "\n");
11494 vty_out(vty
, "Default local pref %u, ",
11495 bgp
->default_local_pref
);
11496 vty_out(vty
, "local AS ");
11497 vty_out(vty
, ASN_FORMAT(bgp
->asnotation
),
11499 vty_out(vty
, "\n");
11500 if (!detail_routes
) {
11501 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11502 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11503 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11504 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11506 if (type
== bgp_show_type_dampend_paths
11507 || type
== bgp_show_type_damp_neighbor
)
11508 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11509 else if (type
== bgp_show_type_flap_statistics
11510 || type
== bgp_show_type_flap_neighbor
)
11511 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11512 else if (!detail_routes
)
11513 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11514 : BGP_SHOW_HEADER
));
11518 if (rd
!= NULL
&& !display
&& !output_count
) {
11521 "Route Distinguisher: %s\n",
11524 if (type
== bgp_show_type_dampend_paths
11525 || type
== bgp_show_type_damp_neighbor
)
11526 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11527 AFI_IP
, safi
, use_json
,
11529 else if (type
== bgp_show_type_flap_statistics
11530 || type
== bgp_show_type_flap_neighbor
)
11531 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11532 AFI_IP
, safi
, use_json
,
11535 if (detail_routes
|| detail_json
) {
11536 const struct prefix_rd
*prd
= NULL
;
11539 prd
= bgp_rd_from_dest(
11540 dest
->pdest
, safi
);
11543 route_vty_out_detail_header(
11545 bgp_dest_get_prefix(
11547 prd
, table
->afi
, safi
,
11550 route_vty_out_detail(
11551 vty
, bgp
, dest
, dest_p
, pi
,
11552 family2afi(dest_p
->family
),
11553 safi
, RPKI_NOT_BEING_USED
,
11556 route_vty_out(vty
, dest_p
, pi
, display
,
11557 safi
, json_paths
, wide
);
11568 /* encode prefix */
11569 if (dest_p
->family
== AF_FLOWSPEC
) {
11570 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11573 bgp_fs_nlri_get_string(
11575 dest_p
->u
.prefix_flowspec
.ptr
,
11576 dest_p
->u
.prefix_flowspec
.prefixlen
,
11577 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11578 family2afi(dest_p
->u
11579 .prefix_flowspec
.family
));
11581 vty_out(vty
, "\"%s/%d\": ", retstr
,
11582 dest_p
->u
.prefix_flowspec
11585 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11586 dest_p
->u
.prefix_flowspec
11590 vty_out(vty
, "\"%pFX\": ", dest_p
);
11592 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11595 if (json_detail_header
&& json_paths
!= NULL
) {
11596 const struct prefix_rd
*prd
;
11598 vty_out(vty
, "{\n");
11600 prd
= bgp_rd_from_dest(dest
, safi
);
11602 route_vty_out_detail_header(
11604 bgp_dest_get_prefix(dest
), prd
,
11605 table
->afi
, safi
, json_paths
, true);
11607 vty_out(vty
, "\"paths\": ");
11608 json_detail_header_used
= true;
11612 * We are using no_pretty here because under
11613 * extremely high settings( say lots and lots of
11614 * routes with lots and lots of ways to reach
11615 * that route via different paths ) this can
11616 * save several minutes of output when FRR
11617 * is run on older cpu's or more underperforming
11618 * routers out there
11620 vty_json_no_pretty(vty
, json_paths
);
11622 if (json_detail_header_used
)
11623 vty_out(vty
, "} ");
11628 json_object_free(json_paths
);
11632 output_count
+= *output_cum
;
11633 *output_cum
= output_count
;
11636 total_count
+= *total_cum
;
11637 *total_cum
= total_count
;
11641 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11645 for (i
= 0; i
< *json_header_depth
; ++i
)
11646 vty_out(vty
, " } ");
11648 vty_out(vty
, "\n");
11652 /* No route is displayed */
11653 if (output_count
== 0) {
11654 if (type
== bgp_show_type_normal
)
11656 "No BGP prefixes displayed, %ld exist\n",
11660 "\nDisplayed %ld routes and %ld total paths\n",
11661 output_count
, total_count
);
11665 return CMD_SUCCESS
;
11668 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11669 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11670 enum bgp_show_type type
, void *output_arg
,
11671 uint16_t show_flags
)
11673 struct bgp_dest
*dest
, *next
;
11674 unsigned long output_cum
= 0;
11675 unsigned long total_cum
= 0;
11676 unsigned long json_header_depth
= 0;
11677 struct bgp_table
*itable
;
11679 bool use_json
= !!CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11681 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11683 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11684 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11686 next
= bgp_route_next(dest
);
11687 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11690 itable
= bgp_dest_get_bgp_table_info(dest
);
11691 if (itable
!= NULL
) {
11692 struct prefix_rd prd
;
11693 char rd
[RD_ADDRSTRLEN
];
11695 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11696 prefix_rd2str(&prd
, rd
, sizeof(rd
), bgp
->asnotation
);
11697 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11698 rd
, next
== NULL
, &output_cum
,
11699 &total_cum
, &json_header_depth
,
11700 show_flags
, RPKI_NOT_BEING_USED
);
11706 if (output_cum
== 0)
11707 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11711 "\nDisplayed %ld routes and %ld total paths\n",
11712 output_cum
, total_cum
);
11714 if (use_json
&& output_cum
== 0)
11715 vty_out(vty
, "{}\n");
11717 return CMD_SUCCESS
;
11720 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11721 enum bgp_show_type type
, void *output_arg
,
11722 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11724 struct bgp_table
*table
;
11725 unsigned long json_header_depth
= 0;
11726 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11729 bgp
= bgp_get_default();
11734 vty_out(vty
, "No BGP process is configured\n");
11736 vty_out(vty
, "{}\n");
11737 return CMD_WARNING
;
11740 /* Labeled-unicast routes live in the unicast table. */
11741 if (safi
== SAFI_LABELED_UNICAST
)
11742 safi
= SAFI_UNICAST
;
11744 table
= bgp
->rib
[afi
][safi
];
11745 /* use MPLS and ENCAP specific shows until they are merged */
11746 if (safi
== SAFI_MPLS_VPN
) {
11747 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11748 output_arg
, show_flags
);
11751 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11752 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11753 output_arg
, use_json
,
11757 if (safi
== SAFI_EVPN
)
11758 return bgp_evpn_show_all_routes(vty
, bgp
, type
, use_json
, 0);
11760 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11761 NULL
, NULL
, &json_header_depth
, show_flags
,
11762 rpki_target_state
);
11765 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11766 safi_t safi
, uint16_t show_flags
)
11768 struct listnode
*node
, *nnode
;
11771 bool route_output
= false;
11772 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11775 vty_out(vty
, "{\n");
11777 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11778 route_output
= true;
11781 vty_out(vty
, ",\n");
11785 vty_out(vty
, "\"%s\":",
11786 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11790 vty_out(vty
, "\nInstance %s:\n",
11791 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11795 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11796 show_flags
, RPKI_NOT_BEING_USED
);
11800 vty_out(vty
, "}\n");
11801 else if (!route_output
)
11802 vty_out(vty
, "%% BGP instance not found\n");
11805 /* Header of detailed BGP route information */
11806 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11807 struct bgp_dest
*dest
, const struct prefix
*p
,
11808 const struct prefix_rd
*prd
, afi_t afi
,
11809 safi_t safi
, json_object
*json
,
11810 bool incremental_print
)
11812 struct bgp_path_info
*pi
;
11814 struct listnode
*node
, *nnode
;
11815 char buf1
[RD_ADDRSTRLEN
];
11819 int accept_own
= 0;
11820 int route_filter_translated_v4
= 0;
11821 int route_filter_v4
= 0;
11822 int route_filter_translated_v6
= 0;
11823 int route_filter_v6
= 0;
11824 int llgr_stale
= 0;
11826 int accept_own_nexthop
= 0;
11829 int no_advertise
= 0;
11833 int has_valid_label
= 0;
11834 mpls_label_t label
= 0;
11835 json_object
*json_adv_to
= NULL
;
11840 mpls_lse_decode(dest
->local_label
, &label
, &ttl
, &exp
, &bos
);
11842 has_valid_label
= bgp_is_valid_label(&label
);
11844 if (safi
== SAFI_EVPN
) {
11846 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11847 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
),
11850 prd
? ":" : "", (struct prefix_evpn
*)p
);
11852 json_object_string_add(
11854 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
),
11857 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11862 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11864 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11865 ? prefix_rd2str(prd
, buf1
,
11869 safi
== SAFI_MPLS_VPN
? ":" : "", p
,
11873 if (incremental_print
) {
11874 vty_out(vty
, "\"prefix\": \"%pFX\",\n", p
);
11875 vty_out(vty
, "\"version\": \"%" PRIu64
"\",\n",
11878 json_object_string_addf(json
, "prefix", "%pFX",
11880 json_object_int_add(json
, "version",
11886 if (has_valid_label
) {
11888 if (incremental_print
)
11889 vty_out(vty
, "\"localLabel\": \"%u\",\n",
11892 json_object_int_add(json
, "localLabel", label
);
11894 vty_out(vty
, "Local label: %d\n", label
);
11898 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11899 vty_out(vty
, "not allocated\n");
11901 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11902 struct community
*picomm
= NULL
;
11904 picomm
= bgp_attr_get_community(pi
->attr
);
11907 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11909 if (bgp_path_suppressed(pi
))
11915 no_advertise
+= community_include(
11916 picomm
, COMMUNITY_NO_ADVERTISE
);
11918 community_include(picomm
, COMMUNITY_NO_EXPORT
);
11920 community_include(picomm
, COMMUNITY_LOCAL_AS
);
11922 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
11923 route_filter_translated_v4
+= community_include(
11924 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11925 route_filter_translated_v6
+= community_include(
11926 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11927 route_filter_v4
+= community_include(
11928 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
11929 route_filter_v6
+= community_include(
11930 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
11932 community_include(picomm
, COMMUNITY_LLGR_STALE
);
11933 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
11934 accept_own_nexthop
+= community_include(
11935 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11937 community_include(picomm
, COMMUNITY_BLACKHOLE
);
11938 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
11943 vty_out(vty
, "Paths: (%d available", count
);
11945 vty_out(vty
, ", best #%d", best
);
11946 if (safi
== SAFI_UNICAST
) {
11947 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11948 vty_out(vty
, ", table %s",
11951 vty_out(vty
, ", vrf %s",
11955 vty_out(vty
, ", no best path");
11959 ", accept own local route exported and imported in different VRF");
11960 else if (route_filter_translated_v4
)
11962 ", mark translated RTs for VPNv4 route filtering");
11963 else if (route_filter_v4
)
11965 ", attach RT as-is for VPNv4 route filtering");
11966 else if (route_filter_translated_v6
)
11968 ", mark translated RTs for VPNv6 route filtering");
11969 else if (route_filter_v6
)
11971 ", attach RT as-is for VPNv6 route filtering");
11972 else if (llgr_stale
)
11974 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
11977 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11978 else if (accept_own_nexthop
)
11980 ", accept local nexthop");
11981 else if (blackhole
)
11982 vty_out(vty
, ", inform peer to blackhole prefix");
11983 else if (no_export
)
11984 vty_out(vty
, ", not advertised to EBGP peer");
11985 else if (no_advertise
)
11986 vty_out(vty
, ", not advertised to any peer");
11988 vty_out(vty
, ", not advertised outside local AS");
11991 ", inform EBGP peer not to advertise to their EBGP peers");
11995 ", Advertisements suppressed by an aggregate.");
11996 vty_out(vty
, ")\n");
11999 /* If we are not using addpath then we can display Advertised to and
12001 * show what peers we advertised the bestpath to. If we are using
12003 * though then we must display Advertised to on a path-by-path basis. */
12004 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
12005 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
12006 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
12007 if (json
&& !json_adv_to
)
12008 json_adv_to
= json_object_new_object();
12010 route_vty_out_advertised_to(
12012 " Advertised to non peer-group peers:\n ",
12017 if (json
&& json_adv_to
) {
12018 if (incremental_print
) {
12019 vty_out(vty
, "\"advertisedTo\": ");
12020 vty_json(vty
, json_adv_to
);
12023 json_object_object_add(json
, "advertisedTo",
12026 if (!json
&& first
)
12027 vty_out(vty
, " Not advertised to any peer");
12028 vty_out(vty
, "\n");
12033 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
12034 struct bgp_dest
*bgp_node
, struct vty
*vty
,
12035 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
12036 json_object
*json
, enum bgp_path_type pathtype
,
12037 int *display
, enum rpki_states rpki_target_state
)
12039 struct bgp_path_info
*pi
;
12041 json_object
*json_header
= NULL
;
12042 json_object
*json_paths
= NULL
;
12043 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
12045 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
12046 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
12048 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
12049 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
12050 pi
->peer
, pi
->attr
, p
);
12052 if (rpki_target_state
!= RPKI_NOT_BEING_USED
12053 && rpki_curr_state
!= rpki_target_state
)
12056 if (json
&& !json_paths
) {
12057 /* Instantiate json_paths only if path is valid */
12058 json_paths
= json_object_new_array();
12060 json_header
= json_object_new_object();
12062 json_header
= json
;
12066 route_vty_out_detail_header(
12067 vty
, bgp
, bgp_node
,
12068 bgp_dest_get_prefix(bgp_node
), pfx_rd
, AFI_IP
,
12069 safi
, json_header
, false);
12074 if (pathtype
== BGP_PATH_SHOW_ALL
12075 || (pathtype
== BGP_PATH_SHOW_BESTPATH
12076 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12077 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
12078 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
12079 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
12080 route_vty_out_detail(vty
, bgp
, bgp_node
,
12081 bgp_dest_get_prefix(bgp_node
), pi
,
12082 AFI_IP
, safi
, rpki_curr_state
,
12086 if (json
&& json_paths
) {
12087 json_object_object_add(json_header
, "paths", json_paths
);
12090 json_object_object_addf(
12092 BGP_RD_AS_FORMAT(bgp
->asnotation
), pfx_rd
);
12097 * Return rd based on safi
12099 const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
12103 case SAFI_MPLS_VPN
:
12106 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
12109 case SAFI_MULTICAST
:
12110 case SAFI_LABELED_UNICAST
:
12111 case SAFI_FLOWSPEC
:
12116 assert(!"Reached end of function when we were not expecting it");
12119 /* Display specified route of BGP table. */
12120 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
12121 struct bgp_table
*rib
, const char *ip_str
,
12122 afi_t afi
, safi_t safi
,
12123 enum rpki_states rpki_target_state
,
12124 struct prefix_rd
*prd
, int prefix_check
,
12125 enum bgp_path_type pathtype
, bool use_json
)
12129 struct prefix match
;
12130 struct bgp_dest
*dest
;
12131 struct bgp_dest
*rm
;
12132 struct bgp_table
*table
;
12133 json_object
*json
= NULL
;
12134 json_object
*json_paths
= NULL
;
12136 /* Check IP address argument. */
12137 ret
= str2prefix(ip_str
, &match
);
12139 vty_out(vty
, "address is malformed\n");
12140 return CMD_WARNING
;
12143 match
.family
= afi2family(afi
);
12146 json
= json_object_new_object();
12148 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
12149 for (dest
= bgp_table_top(rib
); dest
;
12150 dest
= bgp_route_next(dest
)) {
12151 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12153 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
12155 table
= bgp_dest_get_bgp_table_info(dest
);
12159 rm
= bgp_node_match(table
, &match
);
12163 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
12165 && rm_p
->prefixlen
!= match
.prefixlen
) {
12166 bgp_dest_unlock_node(rm
);
12170 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12171 bgp
, afi
, safi
, json
, pathtype
,
12172 &display
, rpki_target_state
);
12174 bgp_dest_unlock_node(rm
);
12176 } else if (safi
== SAFI_EVPN
) {
12177 struct bgp_dest
*longest_pfx
;
12178 bool is_exact_pfxlen_match
= false;
12180 for (dest
= bgp_table_top(rib
); dest
;
12181 dest
= bgp_route_next(dest
)) {
12182 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12184 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
12186 table
= bgp_dest_get_bgp_table_info(dest
);
12190 longest_pfx
= NULL
;
12191 is_exact_pfxlen_match
= false;
12193 * Search through all the prefixes for a match. The
12194 * pfx's are enumerated in ascending order of pfxlens.
12195 * So, the last pfx match is the longest match. Set
12196 * is_exact_pfxlen_match when we get exact pfxlen match
12198 for (rm
= bgp_table_top(table
); rm
;
12199 rm
= bgp_route_next(rm
)) {
12200 const struct prefix
*rm_p
=
12201 bgp_dest_get_prefix(rm
);
12203 * Get prefixlen of the ip-prefix within type5
12206 if (evpn_type5_prefix_match(rm_p
, &match
)
12210 bgp_evpn_get_type5_prefixlen(
12212 if (type5_pfxlen
== match
.prefixlen
) {
12213 is_exact_pfxlen_match
= true;
12214 bgp_dest_unlock_node(rm
);
12223 if (prefix_check
&& !is_exact_pfxlen_match
)
12227 bgp_dest_lock_node(rm
);
12229 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12230 bgp
, afi
, safi
, json
, pathtype
,
12231 &display
, rpki_target_state
);
12233 bgp_dest_unlock_node(rm
);
12235 } else if (safi
== SAFI_FLOWSPEC
) {
12237 json_paths
= json_object_new_array();
12239 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
12240 &match
, prefix_check
,
12246 json_object_object_add(json
, "paths",
12249 json_object_free(json_paths
);
12252 dest
= bgp_node_match(rib
, &match
);
12253 if (dest
!= NULL
) {
12254 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12256 || dest_p
->prefixlen
== match
.prefixlen
) {
12257 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
12258 safi
, json
, pathtype
,
12259 &display
, rpki_target_state
);
12262 bgp_dest_unlock_node(dest
);
12267 vty_json(vty
, json
);
12270 vty_out(vty
, "%% Network not in table\n");
12271 return CMD_WARNING
;
12275 return CMD_SUCCESS
;
12278 /* Display specified route of Main RIB */
12279 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
12280 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
12281 int prefix_check
, enum bgp_path_type pathtype
,
12282 enum rpki_states rpki_target_state
, bool use_json
)
12285 bgp
= bgp_get_default();
12288 vty_out(vty
, "No BGP process is configured\n");
12290 vty_out(vty
, "{}\n");
12291 return CMD_WARNING
;
12295 /* labeled-unicast routes live in the unicast table */
12296 if (safi
== SAFI_LABELED_UNICAST
)
12297 safi
= SAFI_UNICAST
;
12299 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
12300 afi
, safi
, rpki_target_state
, prd
,
12301 prefix_check
, pathtype
, use_json
);
12304 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
12305 struct cmd_token
**argv
, bool exact
, afi_t afi
,
12306 safi_t safi
, bool uj
)
12308 struct lcommunity
*lcom
;
12313 uint16_t show_flags
= 0;
12317 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12319 b
= buffer_new(1024);
12320 for (i
= 0; i
< argc
; i
++) {
12322 buffer_putc(b
, ' ');
12324 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
12326 buffer_putstr(b
, argv
[i
]->arg
);
12330 buffer_putc(b
, '\0');
12332 str
= buffer_getstr(b
);
12335 lcom
= lcommunity_str2com(str
);
12336 XFREE(MTYPE_TMP
, str
);
12338 vty_out(vty
, "%% Large-community malformed\n");
12339 return CMD_WARNING
;
12342 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12343 (exact
? bgp_show_type_lcommunity_exact
12344 : bgp_show_type_lcommunity
),
12345 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
12347 lcommunity_free(&lcom
);
12351 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
12352 const char *lcom
, bool exact
, afi_t afi
,
12353 safi_t safi
, bool uj
)
12355 struct community_list
*list
;
12356 uint16_t show_flags
= 0;
12359 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12362 list
= community_list_lookup(bgp_clist
, lcom
, 0,
12363 LARGE_COMMUNITY_LIST_MASTER
);
12364 if (list
== NULL
) {
12365 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
12367 return CMD_WARNING
;
12370 return bgp_show(vty
, bgp
, afi
, safi
,
12371 (exact
? bgp_show_type_lcommunity_list_exact
12372 : bgp_show_type_lcommunity_list
),
12373 list
, show_flags
, RPKI_NOT_BEING_USED
);
12376 DEFUN (show_ip_bgp_large_community_list
,
12377 show_ip_bgp_large_community_list_cmd
,
12378 "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]",
12382 BGP_INSTANCE_HELP_STR
12384 BGP_SAFI_WITH_LABEL_HELP_STR
12385 "Display routes matching the large-community-list\n"
12386 "large-community-list number\n"
12387 "large-community-list name\n"
12388 "Exact match of the large-communities\n"
12391 afi_t afi
= AFI_IP6
;
12392 safi_t safi
= SAFI_UNICAST
;
12394 bool exact_match
= 0;
12395 struct bgp
*bgp
= NULL
;
12396 bool uj
= use_json(argc
, argv
);
12401 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12404 return CMD_WARNING
;
12406 argv_find(argv
, argc
, "large-community-list", &idx
);
12408 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12410 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
12413 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
12414 exact_match
, afi
, safi
, uj
);
12416 DEFUN (show_ip_bgp_large_community
,
12417 show_ip_bgp_large_community_cmd
,
12418 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
12422 BGP_INSTANCE_HELP_STR
12424 BGP_SAFI_WITH_LABEL_HELP_STR
12425 "Display routes matching the large-communities\n"
12426 "List of large-community numbers\n"
12427 "Exact match of the large-communities\n"
12430 afi_t afi
= AFI_IP6
;
12431 safi_t safi
= SAFI_UNICAST
;
12433 bool exact_match
= 0;
12434 struct bgp
*bgp
= NULL
;
12435 bool uj
= use_json(argc
, argv
);
12436 uint16_t show_flags
= 0;
12440 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12443 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12446 return CMD_WARNING
;
12448 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12449 if (argv_find(argv
, argc
, "exact-match", &idx
)) {
12453 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12454 exact_match
, afi
, safi
, uj
);
12456 return bgp_show(vty
, bgp
, afi
, safi
,
12457 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12458 RPKI_NOT_BEING_USED
);
12461 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12462 safi_t safi
, struct json_object
*json_array
);
12463 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12464 safi_t safi
, struct json_object
*json
);
12467 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12468 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12469 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12470 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12472 bool uj
= use_json(argc
, argv
);
12473 struct bgp
*bgp
= NULL
;
12474 safi_t safi
= SAFI_UNICAST
;
12475 afi_t afi
= AFI_IP6
;
12477 struct json_object
*json_all
= NULL
;
12478 struct json_object
*json_afi_safi
= NULL
;
12480 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12483 return CMD_WARNING
;
12486 json_all
= json_object_new_object();
12488 FOREACH_AFI_SAFI (afi
, safi
) {
12490 * So limit output to those afi/safi pairs that
12491 * actually have something interesting in them
12493 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12498 json_afi_safi
= json_object_new_array();
12499 json_object_object_add(
12501 get_afi_safi_str(afi
, safi
, true),
12504 json_afi_safi
= NULL
;
12507 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12511 vty_json(vty
, json_all
);
12513 return CMD_SUCCESS
;
12516 /* BGP route print out function without JSON */
12517 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12518 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12519 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12523 BGP_INSTANCE_HELP_STR
12526 "BGP RIB advertisement statistics\n"
12529 afi_t afi
= AFI_IP6
;
12530 safi_t safi
= SAFI_UNICAST
;
12531 struct bgp
*bgp
= NULL
;
12533 bool uj
= use_json(argc
, argv
);
12534 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12536 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12539 return CMD_WARNING
;
12542 json_afi_safi
= json_object_new_array();
12544 json_afi_safi
= NULL
;
12546 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12549 json
= json_object_new_object();
12550 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12552 vty_json(vty
, json
);
12557 /* BGP route print out function without JSON */
12558 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12559 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12560 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12562 statistics [json]",
12563 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12564 BGP_SAFI_WITH_LABEL_HELP_STR
12565 "BGP RIB advertisement statistics\n" JSON_STR
)
12567 afi_t afi
= AFI_IP6
;
12568 safi_t safi
= SAFI_UNICAST
;
12569 struct bgp
*bgp
= NULL
;
12571 bool uj
= use_json(argc
, argv
);
12572 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12574 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12577 return CMD_WARNING
;
12580 json_afi_safi
= json_object_new_array();
12582 json_afi_safi
= NULL
;
12584 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12587 json
= json_object_new_object();
12588 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12590 vty_json(vty
, json
);
12595 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12596 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12597 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12598 "]] [all$all] dampening parameters [json]",
12599 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12600 BGP_SAFI_WITH_LABEL_HELP_STR
12601 "Display the entries for all address families\n"
12602 "Display detailed information about dampening\n"
12603 "Display detail of configured dampening parameters\n"
12606 afi_t afi
= AFI_IP6
;
12607 safi_t safi
= SAFI_UNICAST
;
12608 struct bgp
*bgp
= NULL
;
12610 uint16_t show_flags
= 0;
12611 bool uj
= use_json(argc
, argv
);
12615 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12618 /* [<ipv4|ipv6> [all]] */
12620 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12621 if (argv_find(argv
, argc
, "ipv4", &idx
))
12622 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12624 if (argv_find(argv
, argc
, "ipv6", &idx
))
12625 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12628 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12631 return CMD_WARNING
;
12633 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12636 /* BGP route print out function */
12637 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12638 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12639 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12643 |dampening <flap-statistics|dampened-paths>\
12644 |community [AA:NN|local-AS|no-advertise|no-export\
12645 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12646 |accept-own|accept-own-nexthop|route-filter-v6\
12647 |route-filter-v4|route-filter-translated-v6\
12648 |route-filter-translated-v4] [exact-match]\
12649 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12650 |filter-list AS_PATH_FILTER_NAME\
12652 |access-list ACCESSLIST_NAME\
12653 |route-map RMAP_NAME\
12654 |rpki <invalid|valid|notfound>\
12655 |version (1-4294967295)\
12657 |A.B.C.D/M longer-prefixes\
12658 |X:X::X:X/M longer-prefixes\
12659 |"BGP_SELF_ORIG_CMD_STR
"\
12660 |detail-routes$detail_routes\
12661 ] [json$uj [detail$detail_json] | wide$wide]",
12662 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12663 BGP_SAFI_WITH_LABEL_HELP_STR
12664 "Display the entries for all address families\n"
12665 "Display only routes with non-natural netmasks\n"
12666 "Display detailed information about dampening\n"
12667 "Display flap statistics of routes\n"
12668 "Display paths suppressed due to dampening\n"
12669 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12670 "Do not send outside local AS (well-known community)\n"
12671 "Do not advertise to any peer (well-known community)\n"
12672 "Do not export to next AS (well-known community)\n"
12673 "Graceful shutdown (well-known community)\n"
12674 "Do not export to any peer (well-known community)\n"
12675 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12676 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12677 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12678 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12679 "Should accept VPN route with local nexthop (well-known community)\n"
12680 "RT VPNv6 route filtering (well-known community)\n"
12681 "RT VPNv4 route filtering (well-known community)\n"
12682 "RT translated VPNv6 route filtering (well-known community)\n"
12683 "RT translated VPNv4 route filtering (well-known community)\n"
12684 "Exact match of the communities\n"
12685 "Community-list number\n"
12686 "Community-list name\n"
12687 "Display routes matching the community-list\n"
12688 "Exact match of the communities\n"
12689 "Display routes conforming to the filter-list\n"
12690 "Regular expression access list name\n"
12691 "Display routes conforming to the prefix-list\n"
12692 "Prefix-list name\n"
12693 "Display routes conforming to the access-list\n"
12694 "Access-list name\n"
12695 "Display routes matching the route-map\n"
12696 "A route-map to match on\n"
12697 "RPKI route types\n"
12698 "A valid path as determined by rpki\n"
12699 "A invalid path as determined by rpki\n"
12700 "A path that has no rpki data\n"
12701 "Display prefixes with matching version numbers\n"
12702 "Version number and above\n"
12703 "Display prefixes with matching BGP community alias\n"
12704 "BGP community alias\n"
12706 "Display route and more specific routes\n"
12708 "Display route and more specific routes\n"
12709 BGP_SELF_ORIG_HELP_STR
12710 "Display detailed version of all routes\n"
12712 "Display detailed version of JSON output\n"
12713 "Increase table width for longer prefixes\n")
12715 afi_t afi
= AFI_IP6
;
12716 safi_t safi
= SAFI_UNICAST
;
12717 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12718 void *output_arg
= NULL
;
12719 struct bgp
*bgp
= NULL
;
12721 int exact_match
= 0;
12722 char *community
= NULL
;
12724 uint16_t show_flags
= 0;
12725 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12730 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12734 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
12737 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
12739 /* [<ipv4|ipv6> [all]] */
12741 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12743 if (argv_find(argv
, argc
, "ipv4", &idx
))
12744 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12746 if (argv_find(argv
, argc
, "ipv6", &idx
))
12747 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12751 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12753 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12756 return CMD_WARNING
;
12758 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12759 sh_type
= bgp_show_type_cidr_only
;
12761 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12762 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12763 sh_type
= bgp_show_type_dampend_paths
;
12764 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12765 sh_type
= bgp_show_type_flap_statistics
;
12768 if (argv_find(argv
, argc
, "community", &idx
)) {
12769 char *maybecomm
= NULL
;
12771 if (idx
+ 1 < argc
) {
12772 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12773 maybecomm
= argv
[idx
+ 1]->arg
;
12775 maybecomm
= argv
[idx
+ 1]->text
;
12778 if (maybecomm
&& !strmatch(maybecomm
, "json")
12779 && !strmatch(maybecomm
, "exact-match"))
12780 community
= maybecomm
;
12782 if (argv_find(argv
, argc
, "exact-match", &idx
))
12786 sh_type
= bgp_show_type_community_all
;
12789 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12790 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12791 struct community_list
*list
;
12793 if (argv_find(argv
, argc
, "exact-match", &idx
))
12796 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12797 COMMUNITY_LIST_MASTER
);
12798 if (list
== NULL
) {
12799 vty_out(vty
, "%% %s community-list not found\n",
12800 clist_number_or_name
);
12801 return CMD_WARNING
;
12805 sh_type
= bgp_show_type_community_list_exact
;
12807 sh_type
= bgp_show_type_community_list
;
12811 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12812 const char *filter
= argv
[++idx
]->arg
;
12813 struct as_list
*as_list
;
12815 as_list
= as_list_lookup(filter
);
12816 if (as_list
== NULL
) {
12817 vty_out(vty
, "%% %s AS-path access-list not found\n",
12819 return CMD_WARNING
;
12822 sh_type
= bgp_show_type_filter_list
;
12823 output_arg
= as_list
;
12826 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12827 const char *prefix_list_str
= argv
[++idx
]->arg
;
12828 struct prefix_list
*plist
;
12830 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12831 if (plist
== NULL
) {
12832 vty_out(vty
, "%% %s prefix-list not found\n",
12834 return CMD_WARNING
;
12837 sh_type
= bgp_show_type_prefix_list
;
12838 output_arg
= plist
;
12841 if (argv_find(argv
, argc
, "access-list", &idx
)) {
12842 const char *access_list_str
= argv
[++idx
]->arg
;
12843 struct access_list
*alist
;
12845 alist
= access_list_lookup(afi
, access_list_str
);
12847 vty_out(vty
, "%% %s access-list not found\n",
12849 return CMD_WARNING
;
12852 sh_type
= bgp_show_type_access_list
;
12853 output_arg
= alist
;
12856 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12857 const char *rmap_str
= argv
[++idx
]->arg
;
12858 struct route_map
*rmap
;
12860 rmap
= route_map_lookup_by_name(rmap_str
);
12862 vty_out(vty
, "%% %s route-map not found\n", rmap_str
);
12863 return CMD_WARNING
;
12866 sh_type
= bgp_show_type_route_map
;
12870 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12871 sh_type
= bgp_show_type_rpki
;
12872 if (argv_find(argv
, argc
, "valid", &idx
))
12873 rpki_target_state
= RPKI_VALID
;
12874 else if (argv_find(argv
, argc
, "invalid", &idx
))
12875 rpki_target_state
= RPKI_INVALID
;
12878 /* Display prefixes with matching version numbers */
12879 if (argv_find(argv
, argc
, "version", &idx
)) {
12880 sh_type
= bgp_show_type_prefix_version
;
12881 output_arg
= argv
[idx
+ 1]->arg
;
12884 /* Display prefixes with matching BGP community alias */
12885 if (argv_find(argv
, argc
, "alias", &idx
)) {
12886 sh_type
= bgp_show_type_community_alias
;
12887 output_arg
= argv
[idx
+ 1]->arg
;
12890 /* prefix-longer */
12891 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12892 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12893 const char *prefix_str
= argv
[idx
]->arg
;
12895 if (!str2prefix(prefix_str
, &p
)) {
12896 vty_out(vty
, "%% Malformed Prefix\n");
12897 return CMD_WARNING
;
12900 sh_type
= bgp_show_type_prefix_longer
;
12904 /* self originated only */
12905 if (argv_find(argv
, argc
, BGP_SELF_ORIG_CMD_STR
, &idx
))
12906 sh_type
= bgp_show_type_self_originated
;
12909 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12911 return bgp_show_community(vty
, bgp
, community
,
12912 exact_match
, afi
, safi
,
12915 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12916 output_arg
, show_flags
,
12917 rpki_target_state
);
12919 struct listnode
*node
;
12921 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12925 vty_out(vty
, "{\n");
12927 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12928 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12929 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12932 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12933 FOREACH_SAFI (safi
) {
12934 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12942 vty_out(vty
, ",\n");
12943 vty_out(vty
, "\"%s\":{\n",
12944 get_afi_safi_str(afi
,
12949 "\nFor address family: %s\n",
12955 bgp_show_community(
12956 vty
, abgp
, community
,
12957 exact_match
, afi
, safi
,
12960 bgp_show(vty
, abgp
, afi
, safi
,
12961 sh_type
, output_arg
,
12963 rpki_target_state
);
12965 vty_out(vty
, "}\n");
12969 /* show <ip> bgp all: for each AFI and SAFI*/
12970 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12971 FOREACH_AFI_SAFI (afi
, safi
) {
12972 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12980 vty_out(vty
, ",\n");
12982 vty_out(vty
, "\"%s\":{\n",
12983 get_afi_safi_str(afi
,
12988 "\nFor address family: %s\n",
12994 bgp_show_community(
12995 vty
, abgp
, community
,
12996 exact_match
, afi
, safi
,
12999 bgp_show(vty
, abgp
, afi
, safi
,
13000 sh_type
, output_arg
,
13002 rpki_target_state
);
13004 vty_out(vty
, "}\n");
13009 vty_out(vty
, "}\n");
13011 return CMD_SUCCESS
;
13014 DEFUN (show_ip_bgp_route
,
13015 show_ip_bgp_route_cmd
,
13016 "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]",
13020 BGP_INSTANCE_HELP_STR
13022 BGP_SAFI_WITH_LABEL_HELP_STR
13023 "Network in the BGP routing table to display\n"
13025 "Network in the BGP routing table to display\n"
13027 "Display only the bestpath\n"
13028 "Display only multipaths\n"
13029 "Display only paths that match the specified rpki state\n"
13030 "A valid path as determined by rpki\n"
13031 "A invalid path as determined by rpki\n"
13032 "A path that has no rpki data\n"
13035 int prefix_check
= 0;
13037 afi_t afi
= AFI_IP6
;
13038 safi_t safi
= SAFI_UNICAST
;
13039 char *prefix
= NULL
;
13040 struct bgp
*bgp
= NULL
;
13041 enum bgp_path_type path_type
;
13042 bool uj
= use_json(argc
, argv
);
13046 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13049 return CMD_WARNING
;
13053 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13054 return CMD_WARNING
;
13057 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13058 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
13059 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
13061 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
13062 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
13065 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
13066 && afi
!= AFI_IP6
) {
13068 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13069 return CMD_WARNING
;
13071 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
13072 && afi
!= AFI_IP
) {
13074 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13075 return CMD_WARNING
;
13078 prefix
= argv
[idx
]->arg
;
13080 /* [<bestpath|multipath>] */
13081 if (argv_find(argv
, argc
, "bestpath", &idx
))
13082 path_type
= BGP_PATH_SHOW_BESTPATH
;
13083 else if (argv_find(argv
, argc
, "multipath", &idx
))
13084 path_type
= BGP_PATH_SHOW_MULTIPATH
;
13086 path_type
= BGP_PATH_SHOW_ALL
;
13088 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
13089 path_type
, RPKI_NOT_BEING_USED
, uj
);
13092 DEFUN (show_ip_bgp_regexp
,
13093 show_ip_bgp_regexp_cmd
,
13094 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
13098 BGP_INSTANCE_HELP_STR
13100 BGP_SAFI_WITH_LABEL_HELP_STR
13101 "Display routes matching the AS path regular expression\n"
13102 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13105 afi_t afi
= AFI_IP6
;
13106 safi_t safi
= SAFI_UNICAST
;
13107 struct bgp
*bgp
= NULL
;
13108 bool uj
= use_json(argc
, argv
);
13109 char *regstr
= NULL
;
13112 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13115 return CMD_WARNING
;
13117 // get index of regex
13118 if (argv_find(argv
, argc
, "REGEX", &idx
))
13119 regstr
= argv
[idx
]->arg
;
13122 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
13123 bgp_show_type_regexp
, uj
);
13126 DEFPY (show_ip_bgp_instance_all
,
13127 show_ip_bgp_instance_all_cmd
,
13128 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
13132 BGP_INSTANCE_ALL_HELP_STR
13134 BGP_SAFI_WITH_LABEL_HELP_STR
13136 "Increase table width for longer prefixes\n")
13138 afi_t afi
= AFI_IP6
;
13139 safi_t safi
= SAFI_UNICAST
;
13140 struct bgp
*bgp
= NULL
;
13142 uint16_t show_flags
= 0;
13146 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13150 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13152 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13155 return CMD_WARNING
;
13157 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
13158 return CMD_SUCCESS
;
13161 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
13162 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
13167 uint16_t show_flags
= 0;
13170 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13172 if (!config_bgp_aspath_validate(regstr
)) {
13173 vty_out(vty
, "Invalid character in REGEX %s\n",
13175 return CMD_WARNING_CONFIG_FAILED
;
13178 regex
= bgp_regcomp(regstr
);
13180 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
13181 return CMD_WARNING
;
13184 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
13185 RPKI_NOT_BEING_USED
);
13186 bgp_regex_free(regex
);
13190 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
13191 const char *comstr
, int exact
, afi_t afi
,
13192 safi_t safi
, uint16_t show_flags
)
13194 struct community
*com
;
13197 com
= community_str2com(comstr
);
13199 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
13200 return CMD_WARNING
;
13203 ret
= bgp_show(vty
, bgp
, afi
, safi
,
13204 (exact
? bgp_show_type_community_exact
13205 : bgp_show_type_community
),
13206 com
, show_flags
, RPKI_NOT_BEING_USED
);
13207 community_free(&com
);
13213 BGP_STATS_MAXBITLEN
= 0,
13215 BGP_STATS_PREFIXES
,
13217 BGP_STATS_UNAGGREGATEABLE
,
13218 BGP_STATS_MAX_AGGREGATEABLE
,
13219 BGP_STATS_AGGREGATES
,
13221 BGP_STATS_ASPATH_COUNT
,
13222 BGP_STATS_ASPATH_MAXHOPS
,
13223 BGP_STATS_ASPATH_TOTHOPS
,
13224 BGP_STATS_ASPATH_MAXSIZE
,
13225 BGP_STATS_ASPATH_TOTSIZE
,
13226 BGP_STATS_ASN_HIGHEST
,
13230 #define TABLE_STATS_IDX_VTY 0
13231 #define TABLE_STATS_IDX_JSON 1
13233 static const char *table_stats_strs
[][2] = {
13234 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
13235 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
13236 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
13237 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
13238 "unaggregateablePrefixes"},
13239 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
13240 "maximumAggregateablePrefixes"},
13241 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
13242 "bgpAggregateAdvertisements"},
13243 [BGP_STATS_SPACE
] = {"Address space advertised",
13244 "addressSpaceAdvertised"},
13245 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
13246 "advertisementsWithPaths"},
13247 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
13249 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
13251 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
13252 "averageAsPathLengthHops"},
13253 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
13254 "averageAsPathSizeBytes"},
13255 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
13256 [BGP_STATS_MAX
] = {NULL
, NULL
}
13259 struct bgp_table_stats
{
13260 struct bgp_table
*table
;
13261 unsigned long long counts
[BGP_STATS_MAX
];
13264 prefix_len_count
[MAX(EVPN_ROUTE_PREFIXLEN
, IPV6_MAX_BITLEN
) +
13267 double total_space
;
13270 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
13271 struct bgp_table_stats
*ts
, unsigned int space
)
13273 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
13274 struct bgp_path_info
*pi
;
13275 const struct prefix
*rn_p
;
13277 if (!bgp_dest_has_bgp_path_info_data(dest
))
13280 rn_p
= bgp_dest_get_prefix(dest
);
13281 ts
->counts
[BGP_STATS_PREFIXES
]++;
13282 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
13284 ts
->prefix_len_count
[rn_p
->prefixlen
]++;
13285 /* check if the prefix is included by any other announcements */
13286 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
13287 pdest
= bgp_dest_parent_nolock(pdest
);
13289 if (pdest
== NULL
|| pdest
== top
) {
13290 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
13291 /* announced address space */
13293 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
13294 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
13295 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
13298 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
13299 ts
->counts
[BGP_STATS_RIB
]++;
13301 if (CHECK_FLAG(pi
->attr
->flag
,
13302 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
13303 ts
->counts
[BGP_STATS_AGGREGATES
]++;
13305 /* as-path stats */
13306 if (pi
->attr
->aspath
) {
13307 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
13308 unsigned int size
= aspath_size(pi
->attr
->aspath
);
13309 as_t highest
= aspath_highest(pi
->attr
->aspath
);
13311 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
13313 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
13314 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
13316 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
13317 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
13319 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
13320 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
13321 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
13322 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
13327 static void bgp_table_stats_walker(struct event
*t
)
13329 struct bgp_dest
*dest
, *ndest
;
13330 struct bgp_dest
*top
;
13331 struct bgp_table_stats
*ts
= EVENT_ARG(t
);
13332 unsigned int space
= 0;
13334 if (!(top
= bgp_table_top(ts
->table
)))
13337 switch (ts
->table
->afi
) {
13339 space
= IPV4_MAX_BITLEN
;
13342 space
= IPV6_MAX_BITLEN
;
13345 space
= EVPN_ROUTE_PREFIXLEN
;
13352 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
13354 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
13355 if (ts
->table
->safi
== SAFI_MPLS_VPN
13356 || ts
->table
->safi
== SAFI_ENCAP
13357 || ts
->table
->safi
== SAFI_EVPN
) {
13358 struct bgp_table
*table
;
13360 table
= bgp_dest_get_bgp_table_info(dest
);
13364 top
= bgp_table_top(table
);
13365 for (ndest
= bgp_table_top(table
); ndest
;
13366 ndest
= bgp_route_next(ndest
))
13367 bgp_table_stats_rn(ndest
, top
, ts
, space
);
13369 bgp_table_stats_rn(dest
, top
, ts
, space
);
13374 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
13375 struct json_object
*json_array
)
13377 struct listnode
*node
, *nnode
;
13380 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
13381 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13384 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13385 safi_t safi
, struct json_object
*json_array
)
13387 struct bgp_table_stats ts
;
13389 int ret
= CMD_SUCCESS
;
13391 struct json_object
*json
= NULL
;
13392 uint32_t bitlen
= 0;
13393 struct json_object
*json_bitlen
;
13396 json
= json_object_new_object();
13398 if (!bgp
->rib
[afi
][safi
]) {
13399 char warning_msg
[50];
13401 snprintf(warning_msg
, sizeof(warning_msg
),
13402 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
13406 vty_out(vty
, "%s\n", warning_msg
);
13408 json_object_string_add(json
, "warning", warning_msg
);
13411 goto end_table_stats
;
13415 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
13416 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
13418 json_object_string_add(json
, "instance", bgp
->name_pretty
);
13420 /* labeled-unicast routes live in the unicast table */
13421 if (safi
== SAFI_LABELED_UNICAST
)
13422 safi
= SAFI_UNICAST
;
13424 memset(&ts
, 0, sizeof(ts
));
13425 ts
.table
= bgp
->rib
[afi
][safi
];
13426 event_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
13428 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
13429 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
13430 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
13434 case BGP_STATS_ASPATH_TOTHOPS
:
13435 case BGP_STATS_ASPATH_TOTSIZE
:
13438 temp_buf
, sizeof(temp_buf
), "%12.2f",
13440 ? (float)ts
.counts
[i
]
13442 [BGP_STATS_ASPATH_COUNT
]
13444 vty_out(vty
, "%-30s: %s",
13445 table_stats_strs
[i
]
13446 [TABLE_STATS_IDX_VTY
],
13449 json_object_double_add(
13451 table_stats_strs
[i
]
13452 [TABLE_STATS_IDX_JSON
],
13454 ? (double)ts
.counts
[i
]
13455 / (double)ts
.counts
13456 [BGP_STATS_ASPATH_COUNT
]
13460 case BGP_STATS_TOTPLEN
:
13463 temp_buf
, sizeof(temp_buf
), "%12.2f",
13465 ? (float)ts
.counts
[i
]
13467 [BGP_STATS_PREFIXES
]
13469 vty_out(vty
, "%-30s: %s",
13470 table_stats_strs
[i
]
13471 [TABLE_STATS_IDX_VTY
],
13474 json_object_double_add(
13476 table_stats_strs
[i
]
13477 [TABLE_STATS_IDX_JSON
],
13479 ? (double)ts
.counts
[i
]
13480 / (double)ts
.counts
13481 [BGP_STATS_PREFIXES
]
13485 case BGP_STATS_SPACE
:
13487 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13489 vty_out(vty
, "%-30s: %s\n",
13490 table_stats_strs
[i
]
13491 [TABLE_STATS_IDX_VTY
],
13494 json_object_double_add(
13496 table_stats_strs
[i
]
13497 [TABLE_STATS_IDX_JSON
],
13498 (double)ts
.total_space
);
13500 if (afi
== AFI_IP6
) {
13502 snprintf(temp_buf
, sizeof(temp_buf
),
13505 * pow(2.0, -128 + 32));
13506 vty_out(vty
, "%30s: %s\n",
13507 "/32 equivalent %s\n",
13510 json_object_double_add(
13511 json
, "/32equivalent",
13512 (double)(ts
.total_space
13517 snprintf(temp_buf
, sizeof(temp_buf
),
13520 * pow(2.0, -128 + 48));
13521 vty_out(vty
, "%30s: %s\n",
13522 "/48 equivalent %s\n",
13525 json_object_double_add(
13526 json
, "/48equivalent",
13527 (double)(ts
.total_space
13533 snprintf(temp_buf
, sizeof(temp_buf
),
13535 ts
.total_space
* 100.
13537 vty_out(vty
, "%30s: %s\n",
13538 "% announced ", temp_buf
);
13540 json_object_double_add(
13541 json
, "%announced",
13542 (double)(ts
.total_space
* 100.
13546 snprintf(temp_buf
, sizeof(temp_buf
),
13549 * pow(2.0, -32 + 8));
13550 vty_out(vty
, "%30s: %s\n",
13551 "/8 equivalent ", temp_buf
);
13553 json_object_double_add(
13554 json
, "/8equivalent",
13555 (double)(ts
.total_space
13556 * pow(2.0, -32 + 8)));
13559 snprintf(temp_buf
, sizeof(temp_buf
),
13562 * pow(2.0, -32 + 24));
13563 vty_out(vty
, "%30s: %s\n",
13564 "/24 equivalent ", temp_buf
);
13566 json_object_double_add(
13567 json
, "/24equivalent",
13568 (double)(ts
.total_space
13569 * pow(2.0, -32 + 24)));
13575 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13577 vty_out(vty
, "%-30s: %s",
13578 table_stats_strs
[i
]
13579 [TABLE_STATS_IDX_VTY
],
13582 json_object_int_add(
13584 table_stats_strs
[i
]
13585 [TABLE_STATS_IDX_JSON
],
13590 vty_out(vty
, "\n");
13595 bitlen
= IPV4_MAX_BITLEN
;
13598 bitlen
= IPV6_MAX_BITLEN
;
13601 bitlen
= EVPN_ROUTE_PREFIXLEN
;
13609 json_bitlen
= json_object_new_array();
13611 for (i
= 0; i
<= bitlen
; i
++) {
13612 struct json_object
*ind_bit
= json_object_new_object();
13614 if (!ts
.prefix_len_count
[i
])
13617 snprintf(temp_buf
, sizeof(temp_buf
), "%u", i
);
13618 json_object_int_add(ind_bit
, temp_buf
,
13619 ts
.prefix_len_count
[i
]);
13620 json_object_array_add(json_bitlen
, ind_bit
);
13622 json_object_object_add(json
, "prefixLength", json_bitlen
);
13627 json_object_array_add(json_array
, json
);
13631 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13632 safi_t safi
, struct json_object
*json_array
)
13635 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13636 return CMD_SUCCESS
;
13639 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13651 PCOUNT_BPATH_SELECTED
,
13652 PCOUNT_PFCNT
, /* the figure we display to users */
13656 static const char *const pcount_strs
[] = {
13657 [PCOUNT_ADJ_IN
] = "Adj-in",
13658 [PCOUNT_DAMPED
] = "Damped",
13659 [PCOUNT_REMOVED
] = "Removed",
13660 [PCOUNT_HISTORY
] = "History",
13661 [PCOUNT_STALE
] = "Stale",
13662 [PCOUNT_VALID
] = "Valid",
13663 [PCOUNT_ALL
] = "All RIB",
13664 [PCOUNT_COUNTED
] = "PfxCt counted",
13665 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13666 [PCOUNT_PFCNT
] = "Useable",
13667 [PCOUNT_MAX
] = NULL
,
13670 struct peer_pcounts
{
13671 unsigned int count
[PCOUNT_MAX
];
13672 const struct peer
*peer
;
13673 const struct bgp_table
*table
;
13677 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13679 const struct bgp_adj_in
*ain
;
13680 const struct bgp_path_info
*pi
;
13681 const struct peer
*peer
= pc
->peer
;
13683 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13684 if (ain
->peer
== peer
)
13685 pc
->count
[PCOUNT_ADJ_IN
]++;
13687 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13689 if (pi
->peer
!= peer
)
13692 pc
->count
[PCOUNT_ALL
]++;
13694 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13695 pc
->count
[PCOUNT_DAMPED
]++;
13696 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13697 pc
->count
[PCOUNT_HISTORY
]++;
13698 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13699 pc
->count
[PCOUNT_REMOVED
]++;
13700 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13701 pc
->count
[PCOUNT_STALE
]++;
13702 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13703 pc
->count
[PCOUNT_VALID
]++;
13704 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13705 pc
->count
[PCOUNT_PFCNT
]++;
13706 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13707 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13709 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13710 pc
->count
[PCOUNT_COUNTED
]++;
13711 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13713 EC_LIB_DEVELOPMENT
,
13714 "Attempting to count but flags say it is unusable");
13716 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13718 EC_LIB_DEVELOPMENT
,
13719 "Not counted but flags say we should");
13724 static void bgp_peer_count_walker(struct event
*t
)
13726 struct bgp_dest
*rn
, *rm
;
13727 const struct bgp_table
*table
;
13728 struct peer_pcounts
*pc
= EVENT_ARG(t
);
13730 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13731 || pc
->safi
== SAFI_EVPN
) {
13732 /* Special handling for 2-level routing tables. */
13733 for (rn
= bgp_table_top(pc
->table
); rn
;
13734 rn
= bgp_route_next(rn
)) {
13735 table
= bgp_dest_get_bgp_table_info(rn
);
13737 for (rm
= bgp_table_top(table
); rm
;
13738 rm
= bgp_route_next(rm
))
13739 bgp_peer_count_proc(rm
, pc
);
13742 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13743 bgp_peer_count_proc(rn
, pc
);
13746 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13747 safi_t safi
, bool use_json
)
13749 struct peer_pcounts pcounts
= {.peer
= peer
};
13751 json_object
*json
= NULL
;
13752 json_object
*json_loop
= NULL
;
13755 json
= json_object_new_object();
13756 json_loop
= json_object_new_object();
13759 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13760 || !peer
->bgp
->rib
[afi
][safi
]) {
13762 json_object_string_add(
13764 "No such neighbor or address family");
13765 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13766 json_object_free(json
);
13767 json_object_free(json_loop
);
13769 vty_out(vty
, "%% No such neighbor or address family\n");
13771 return CMD_WARNING
;
13774 memset(&pcounts
, 0, sizeof(pcounts
));
13775 pcounts
.peer
= peer
;
13776 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13777 pcounts
.safi
= safi
;
13779 /* in-place call via thread subsystem so as to record execution time
13780 * stats for the thread-walk (i.e. ensure this can't be blamed on
13781 * on just vty_read()).
13783 event_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13786 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13787 json_object_string_add(json
, "multiProtocol",
13788 get_afi_safi_str(afi
, safi
, true));
13789 json_object_int_add(json
, "pfxCounter",
13790 peer
->pcount
[afi
][safi
]);
13792 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13793 json_object_int_add(json_loop
, pcount_strs
[i
],
13796 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13798 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13799 json_object_string_add(json
, "pfxctDriftFor",
13801 json_object_string_add(
13802 json
, "recommended",
13803 "Please report this bug, with the above command output");
13805 vty_json(vty
, json
);
13809 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13810 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13811 peer
->hostname
, peer
->host
,
13812 get_afi_safi_str(afi
, safi
, false));
13814 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13815 get_afi_safi_str(afi
, safi
, false));
13818 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13819 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13821 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13822 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13825 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13826 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13828 "Please report this bug, with the above command output\n");
13832 return CMD_SUCCESS
;
13835 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13836 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13837 "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]",
13841 BGP_INSTANCE_HELP_STR
13844 "Detailed information on TCP and BGP neighbor connections\n"
13845 "Neighbor to display information about\n"
13846 "Neighbor to display information about\n"
13847 "Neighbor on BGP configured interface\n"
13848 "Display detailed prefix count information\n"
13851 afi_t afi
= AFI_IP6
;
13852 safi_t safi
= SAFI_UNICAST
;
13855 struct bgp
*bgp
= NULL
;
13856 bool uj
= use_json(argc
, argv
);
13861 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13864 return CMD_WARNING
;
13866 argv_find(argv
, argc
, "neighbors", &idx
);
13867 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13869 return CMD_WARNING
;
13871 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13874 #ifdef KEEP_OLD_VPN_COMMANDS
13875 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13876 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13877 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13882 "Display information about all VPNv4 NLRIs\n"
13883 "Detailed information on TCP and BGP neighbor connections\n"
13884 "Neighbor to display information about\n"
13885 "Neighbor to display information about\n"
13886 "Neighbor on BGP configured interface\n"
13887 "Display detailed prefix count information\n"
13892 bool uj
= use_json(argc
, argv
);
13894 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13896 return CMD_WARNING
;
13898 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13901 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13902 show_ip_bgp_vpn_all_route_prefix_cmd
,
13903 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13908 "Display information about all VPNv4 NLRIs\n"
13909 "Network in the BGP routing table to display\n"
13910 "Network in the BGP routing table to display\n"
13914 char *network
= NULL
;
13915 struct bgp
*bgp
= bgp_get_default();
13917 vty_out(vty
, "Can't find default instance\n");
13918 return CMD_WARNING
;
13921 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13922 network
= argv
[idx
]->arg
;
13923 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13924 network
= argv
[idx
]->arg
;
13926 vty_out(vty
, "Unable to figure out Network\n");
13927 return CMD_WARNING
;
13930 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13931 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13932 use_json(argc
, argv
));
13934 #endif /* KEEP_OLD_VPN_COMMANDS */
13936 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13937 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13938 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13943 "Network in the BGP routing table to display\n"
13944 "Network in the BGP routing table to display\n"
13945 "Network in the BGP routing table to display\n"
13946 "Network in the BGP routing table to display\n"
13950 char *network
= NULL
;
13951 int prefix_check
= 0;
13953 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13954 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13955 network
= argv
[idx
]->arg
;
13956 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13957 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
13958 network
= argv
[idx
]->arg
;
13961 vty_out(vty
, "Unable to figure out Network\n");
13962 return CMD_WARNING
;
13964 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13965 prefix_check
, BGP_PATH_SHOW_ALL
,
13966 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
13969 static void show_adj_route_header(struct vty
*vty
, struct peer
*peer
,
13970 struct bgp_table
*table
, int *header1
,
13971 int *header2
, json_object
*json
,
13972 json_object
*json_scode
,
13973 json_object
*json_ocode
, bool wide
,
13976 uint64_t version
= table
? table
->version
: 0;
13980 json_object_int_add(json
, "bgpTableVersion", version
);
13981 json_object_string_addf(json
, "bgpLocalRouterId",
13982 "%pI4", &peer
->bgp
->router_id
);
13983 json_object_int_add(json
, "defaultLocPrf",
13984 peer
->bgp
->default_local_pref
);
13985 json_object_int_add(json
, "localAS",
13986 peer
->change_local_as
13987 ? peer
->change_local_as
13989 json_object_object_add(json
, "bgpStatusCodes",
13991 json_object_object_add(json
, "bgpOriginCodes",
13995 "BGP table version is %" PRIu64
13996 ", local router ID is %pI4, vrf id ",
13997 version
, &peer
->bgp
->router_id
);
13998 if (peer
->bgp
->vrf_id
== VRF_UNKNOWN
)
13999 vty_out(vty
, "%s", VRFID_NONE_STR
);
14001 vty_out(vty
, "%u", peer
->bgp
->vrf_id
);
14002 vty_out(vty
, "\n");
14003 vty_out(vty
, "Default local pref %u, ",
14004 peer
->bgp
->default_local_pref
);
14005 vty_out(vty
, "local AS %u\n",
14006 peer
->change_local_as
? peer
->change_local_as
14009 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14010 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14011 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14012 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14018 if (!json
&& !detail
)
14019 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
14020 : BGP_SHOW_HEADER
));
14026 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
14027 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
14028 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
14029 json_object
*json_scode
, json_object
*json_ocode
,
14030 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
14031 const struct prefix
*match
, unsigned long *output_count
,
14032 unsigned long *filtered_count
)
14034 struct bgp_adj_in
*ain
= NULL
;
14035 struct bgp_adj_out
*adj
= NULL
;
14036 struct bgp_dest
*dest
;
14040 struct update_subgroup
*subgrp
;
14041 struct peer_af
*paf
= NULL
;
14042 bool route_filtered
;
14043 bool detail
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14044 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14045 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14046 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14047 || (safi
== SAFI_EVPN
))
14051 json_object
*json_net
= NULL
;
14055 /* If the user supplied a prefix, look for a matching route instead
14056 * of walking the whole table.
14059 dest
= bgp_node_match(table
, match
);
14062 vty_out(vty
, "Network not in table\n");
14066 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
14068 if (rn_p
->prefixlen
!= match
->prefixlen
) {
14070 vty_out(vty
, "Network not in table\n");
14071 bgp_dest_unlock_node(dest
);
14075 if (type
== bgp_show_adj_route_received
||
14076 type
== bgp_show_adj_route_filtered
) {
14077 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14078 if (ain
->peer
== peer
) {
14083 /* bail out if if adj_out is empty, or
14084 * if the prefix isn't in this peer's
14087 if (!ain
|| ain
->peer
!= peer
) {
14089 vty_out(vty
, "Network not in table\n");
14090 bgp_dest_unlock_node(dest
);
14093 } else if (type
== bgp_show_adj_route_advertised
) {
14094 bool peer_found
= false;
14096 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
) {
14097 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14098 if (paf
->peer
== peer
&& adj
->attr
) {
14107 /* bail out if if adj_out is empty, or
14108 * if the prefix isn't in this peer's
14111 if (!paf
|| !peer_found
) {
14113 vty_out(vty
, "Network not in table\n");
14114 bgp_dest_unlock_node(dest
);
14119 ret
= bgp_output_modifier(peer
, rn_p
, &attr
, afi
, safi
,
14122 if (ret
!= RMAP_DENY
) {
14123 show_adj_route_header(vty
, peer
, table
, header1
,
14124 header2
, json
, json_scode
,
14125 json_ocode
, wide
, detail
);
14128 json_net
= json_object_new_object();
14130 bgp_show_path_info(NULL
/* prefix_rd */, dest
, vty
, bgp
,
14131 afi
, safi
, json_net
,
14132 BGP_PATH_SHOW_ALL
, &display
,
14133 RPKI_NOT_BEING_USED
);
14135 json_object_object_addf(json_ar
, json_net
,
14139 (*filtered_count
)++;
14141 bgp_attr_flush(&attr
);
14142 bgp_dest_unlock_node(dest
);
14147 subgrp
= peer_subgroup(peer
, afi
, safi
);
14149 if (type
== bgp_show_adj_route_advertised
&& subgrp
14150 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
14152 json_object_int_add(json
, "bgpTableVersion",
14154 json_object_string_addf(json
, "bgpLocalRouterId",
14155 "%pI4", &bgp
->router_id
);
14156 json_object_int_add(json
, "defaultLocPrf",
14157 bgp
->default_local_pref
);
14158 json_object_int_add(json
, "localAS",
14159 peer
->change_local_as
14160 ? peer
->change_local_as
14162 json_object_object_add(json
, "bgpStatusCodes",
14164 json_object_object_add(json
, "bgpOriginCodes",
14166 json_object_string_add(
14167 json
, "bgpOriginatingDefaultNetwork",
14168 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14171 "BGP table version is %" PRIu64
14172 ", local router ID is %pI4, vrf id ",
14173 table
->version
, &bgp
->router_id
);
14174 if (bgp
->vrf_id
== VRF_UNKNOWN
)
14175 vty_out(vty
, "%s", VRFID_NONE_STR
);
14177 vty_out(vty
, "%u", bgp
->vrf_id
);
14178 vty_out(vty
, "\n");
14179 vty_out(vty
, "Default local pref %u, ",
14180 bgp
->default_local_pref
);
14181 vty_out(vty
, "local AS %u\n",
14182 peer
->change_local_as
? peer
->change_local_as
14185 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14186 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14187 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14188 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14191 vty_out(vty
, "Originating default network %s\n\n",
14192 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14198 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
14199 if (type
== bgp_show_adj_route_received
14200 || type
== bgp_show_adj_route_filtered
) {
14201 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14202 if (ain
->peer
!= peer
)
14205 show_adj_route_header(vty
, peer
, table
, header1
,
14206 header2
, json
, json_scode
,
14207 json_ocode
, wide
, detail
);
14209 if ((safi
== SAFI_MPLS_VPN
)
14210 || (safi
== SAFI_ENCAP
)
14211 || (safi
== SAFI_EVPN
)) {
14213 json_object_string_add(
14214 json_ar
, "rd", rd_str
);
14215 else if (show_rd
&& rd_str
) {
14217 "Route Distinguisher: %s\n",
14224 route_filtered
= false;
14226 /* Filter prefix using distribute list,
14227 * filter list or prefix list
14229 const struct prefix
*rn_p
=
14230 bgp_dest_get_prefix(dest
);
14231 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
14234 route_filtered
= true;
14236 /* Filter prefix using route-map */
14237 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
14238 safi
, rmap_name
, NULL
,
14241 if (type
== bgp_show_adj_route_filtered
&&
14242 !route_filtered
&& ret
!= RMAP_DENY
) {
14243 bgp_attr_flush(&attr
);
14247 if (type
== bgp_show_adj_route_received
14248 && (route_filtered
|| ret
== RMAP_DENY
))
14249 (*filtered_count
)++;
14254 json_object_new_object();
14255 bgp_show_path_info(
14256 NULL
/* prefix_rd */, dest
, vty
,
14257 bgp
, afi
, safi
, json_net
,
14258 BGP_PATH_SHOW_ALL
, &display
,
14259 RPKI_NOT_BEING_USED
);
14261 json_object_object_addf(
14265 route_vty_out_tmp(vty
, dest
, rn_p
,
14266 &attr
, safi
, use_json
,
14268 bgp_attr_flush(&attr
);
14271 } else if (type
== bgp_show_adj_route_advertised
) {
14272 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
14273 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14274 if (paf
->peer
!= peer
|| !adj
->attr
)
14277 show_adj_route_header(
14278 vty
, peer
, table
, header1
,
14279 header2
, json
, json_scode
,
14280 json_ocode
, wide
, detail
);
14282 const struct prefix
*rn_p
=
14283 bgp_dest_get_prefix(dest
);
14286 ret
= bgp_output_modifier(
14287 peer
, rn_p
, &attr
, afi
, safi
,
14290 if (ret
!= RMAP_DENY
) {
14291 if ((safi
== SAFI_MPLS_VPN
)
14292 || (safi
== SAFI_ENCAP
)
14293 || (safi
== SAFI_EVPN
)) {
14295 json_object_string_add(
14302 "Route Distinguisher: %s\n",
14310 json_object_new_object();
14311 bgp_show_path_info(
14320 RPKI_NOT_BEING_USED
);
14322 json_object_object_addf(
14335 (*filtered_count
)++;
14338 bgp_attr_flush(&attr
);
14340 } else if (type
== bgp_show_adj_route_bestpath
) {
14341 struct bgp_path_info
*pi
;
14343 show_adj_route_header(vty
, peer
, table
, header1
,
14344 header2
, json
, json_scode
,
14345 json_ocode
, wide
, detail
);
14347 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
14349 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
14351 if (pi
->peer
!= peer
)
14354 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
14360 json_object_new_object();
14361 bgp_show_path_info(
14362 NULL
/* prefix_rd */, dest
, vty
,
14363 bgp
, afi
, safi
, json_net
,
14364 BGP_PATH_SHOW_BESTPATH
,
14365 &display
, RPKI_NOT_BEING_USED
);
14367 json_object_object_addf(
14372 vty
, dest
, rn_p
, pi
->attr
, safi
,
14373 use_json
, json_ar
, wide
);
14380 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
14381 safi_t safi
, enum bgp_show_adj_route_type type
,
14382 const char *rmap_name
, const struct prefix
*match
,
14383 uint16_t show_flags
)
14386 struct bgp_table
*table
;
14387 json_object
*json
= NULL
;
14388 json_object
*json_scode
= NULL
;
14389 json_object
*json_ocode
= NULL
;
14390 json_object
*json_ar
= NULL
;
14391 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14393 /* Init BGP headers here so they're only displayed once
14394 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14400 * Initialize variables for each RD
14401 * All prefixes under an RD is aggregated within "json_routes"
14403 char rd_str
[BUFSIZ
] = {0};
14404 json_object
*json_routes
= NULL
;
14407 /* For 2-tier tables, prefix counts need to be
14408 * maintained across multiple runs of show_adj_route()
14410 unsigned long output_count_per_rd
;
14411 unsigned long filtered_count_per_rd
;
14412 unsigned long output_count
= 0;
14413 unsigned long filtered_count
= 0;
14416 json
= json_object_new_object();
14417 json_ar
= json_object_new_object();
14418 json_scode
= json_object_new_object();
14419 json_ocode
= json_object_new_object();
14420 #if CONFDATE > 20231208
14421 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14423 json_object_string_add(json_scode
, "suppressed", "s");
14424 json_object_string_add(json_scode
, "damped", "d");
14425 json_object_string_add(json_scode
, "history", "h");
14426 json_object_string_add(json_scode
, "valid", "*");
14427 json_object_string_add(json_scode
, "best", ">");
14428 json_object_string_add(json_scode
, "multipath", "=");
14429 json_object_string_add(json_scode
, "internal", "i");
14430 json_object_string_add(json_scode
, "ribFailure", "r");
14431 json_object_string_add(json_scode
, "stale", "S");
14432 json_object_string_add(json_scode
, "removed", "R");
14434 #if CONFDATE > 20231208
14435 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14437 json_object_string_add(json_ocode
, "igp", "i");
14438 json_object_string_add(json_ocode
, "egp", "e");
14439 json_object_string_add(json_ocode
, "incomplete", "?");
14442 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14444 json_object_string_add(
14446 "No such neighbor or address family");
14447 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14448 json_object_free(json
);
14449 json_object_free(json_ar
);
14450 json_object_free(json_scode
);
14451 json_object_free(json_ocode
);
14453 vty_out(vty
, "%% No such neighbor or address family\n");
14455 return CMD_WARNING
;
14458 if ((type
== bgp_show_adj_route_received
14459 || type
== bgp_show_adj_route_filtered
)
14460 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
14461 PEER_FLAG_SOFT_RECONFIG
)) {
14463 json_object_string_add(
14465 "Inbound soft reconfiguration not enabled");
14466 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14467 json_object_free(json
);
14468 json_object_free(json_ar
);
14469 json_object_free(json_scode
);
14470 json_object_free(json_ocode
);
14473 "%% Inbound soft reconfiguration not enabled\n");
14475 return CMD_WARNING
;
14480 /* labeled-unicast routes live in the unicast table */
14481 if (safi
== SAFI_LABELED_UNICAST
)
14482 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
14484 table
= bgp
->rib
[afi
][safi
];
14486 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14487 || (safi
== SAFI_EVPN
)) {
14489 struct bgp_dest
*dest
;
14491 for (dest
= bgp_table_top(table
); dest
;
14492 dest
= bgp_route_next(dest
)) {
14493 table
= bgp_dest_get_bgp_table_info(dest
);
14497 output_count_per_rd
= 0;
14498 filtered_count_per_rd
= 0;
14501 json_routes
= json_object_new_object();
14503 const struct prefix_rd
*prd
;
14504 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14507 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
),
14511 vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14512 json
, json_routes
, json_scode
, json_ocode
,
14513 show_flags
, &header1
, &header2
, rd_str
, match
,
14514 &output_count_per_rd
, &filtered_count_per_rd
);
14516 /* Don't include an empty RD in the output! */
14517 if (json_routes
&& (output_count_per_rd
> 0))
14518 json_object_object_add(json_ar
, rd_str
,
14521 output_count
+= output_count_per_rd
;
14522 filtered_count
+= filtered_count_per_rd
;
14525 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14526 json
, json_ar
, json_scode
, json_ocode
,
14527 show_flags
, &header1
, &header2
, rd_str
, match
,
14528 &output_count
, &filtered_count
);
14531 if (type
== bgp_show_adj_route_advertised
)
14532 json_object_object_add(json
, "advertisedRoutes",
14535 json_object_object_add(json
, "receivedRoutes", json_ar
);
14536 json_object_int_add(json
, "totalPrefixCounter", output_count
);
14537 json_object_int_add(json
, "filteredPrefixCounter",
14541 * These fields only give up ownership to `json` when `header1`
14542 * is used (set to zero). See code in `show_adj_route` and
14543 * `show_adj_route_header`.
14545 if (header1
== 1) {
14546 json_object_free(json_scode
);
14547 json_object_free(json_ocode
);
14550 vty_json(vty
, json
);
14551 } else if (output_count
> 0) {
14552 if (!match
&& filtered_count
> 0)
14554 "\nTotal number of prefixes %ld (%ld filtered)\n",
14555 output_count
, filtered_count
);
14557 vty_out(vty
, "\nTotal number of prefixes %ld\n",
14561 return CMD_SUCCESS
;
14564 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
14565 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
14566 "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]",
14570 BGP_INSTANCE_HELP_STR
14572 BGP_SAFI_WITH_LABEL_HELP_STR
14573 "Detailed information on TCP and BGP neighbor connections\n"
14574 "Neighbor to display information about\n"
14575 "Neighbor to display information about\n"
14576 "Neighbor on BGP configured interface\n"
14577 "Display the routes selected by best path\n"
14578 "Display detailed version of routes\n"
14580 "Increase table width for longer prefixes\n")
14582 afi_t afi
= AFI_IP6
;
14583 safi_t safi
= SAFI_UNICAST
;
14584 char *rmap_name
= NULL
;
14585 char *peerstr
= NULL
;
14586 struct bgp
*bgp
= NULL
;
14588 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
14590 uint16_t show_flags
= 0;
14593 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14596 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14599 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14601 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14605 return CMD_WARNING
;
14607 argv_find(argv
, argc
, "neighbors", &idx
);
14608 peerstr
= argv
[++idx
]->arg
;
14610 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14612 return CMD_WARNING
;
14614 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, NULL
,
14618 DEFPY(show_ip_bgp_instance_neighbor_advertised_route
,
14619 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
14620 "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]",
14624 BGP_INSTANCE_HELP_STR
14626 BGP_SAFI_WITH_LABEL_HELP_STR
14627 "Display the entries for all address families\n"
14628 "Detailed information on TCP and BGP neighbor connections\n"
14629 "Neighbor to display information about\n"
14630 "Neighbor to display information about\n"
14631 "Neighbor on BGP configured interface\n"
14632 "Display the routes advertised to a BGP neighbor\n"
14633 "Display the received routes from neighbor\n"
14634 "Display the filtered routes received from neighbor\n"
14635 "Route-map to modify the attributes\n"
14636 "Name of the route map\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 *peerstr
= NULL
;
14646 struct bgp
*bgp
= NULL
;
14648 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
14651 uint16_t show_flags
= 0;
14652 struct listnode
*node
;
14655 if (detail
|| prefix_str
)
14656 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14660 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14664 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
14665 if (argv_find(argv
, argc
, "ipv4", &idx
))
14666 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
14668 if (argv_find(argv
, argc
, "ipv6", &idx
))
14669 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
14673 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14675 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14678 return CMD_WARNING
;
14680 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14681 argv_find(argv
, argc
, "neighbors", &idx
);
14682 peerstr
= argv
[++idx
]->arg
;
14684 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14686 return CMD_WARNING
;
14688 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
14689 type
= bgp_show_adj_route_advertised
;
14690 else if (argv_find(argv
, argc
, "received-routes", &idx
))
14691 type
= bgp_show_adj_route_received
;
14692 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
14693 type
= bgp_show_adj_route_filtered
;
14696 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, route_map
,
14697 prefix_str
? prefix
: NULL
, show_flags
);
14699 vty_out(vty
, "{\n");
14701 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14702 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14703 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14705 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14706 FOREACH_SAFI (safi
) {
14707 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14714 vty_out(vty
, ",\n");
14715 vty_out(vty
, "\"%s\":",
14716 get_afi_safi_str(afi
, safi
,
14720 "\nFor address family: %s\n",
14721 get_afi_safi_str(afi
, safi
,
14724 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14725 route_map
, prefix
, show_flags
);
14729 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14730 FOREACH_AFI_SAFI (afi
, safi
) {
14731 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14738 vty_out(vty
, ",\n");
14739 vty_out(vty
, "\"%s\":",
14740 get_afi_safi_str(afi
, safi
,
14744 "\nFor address family: %s\n",
14745 get_afi_safi_str(afi
, safi
,
14748 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14749 route_map
, prefix
, show_flags
);
14754 vty_out(vty
, "}\n");
14756 return CMD_SUCCESS
;
14759 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14760 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14761 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14765 BGP_INSTANCE_HELP_STR
14768 BGP_AF_MODIFIER_STR
14769 "Detailed information on TCP and BGP neighbor connections\n"
14770 "Neighbor to display information about\n"
14771 "Neighbor to display information about\n"
14772 "Neighbor on BGP configured interface\n"
14773 "Display information received from a BGP neighbor\n"
14774 "Display the prefixlist filter\n"
14777 afi_t afi
= AFI_IP6
;
14778 safi_t safi
= SAFI_UNICAST
;
14779 char *peerstr
= NULL
;
14784 struct bgp
*bgp
= NULL
;
14785 bool uj
= use_json(argc
, argv
);
14790 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14793 return CMD_WARNING
;
14795 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14796 argv_find(argv
, argc
, "neighbors", &idx
);
14797 peerstr
= argv
[++idx
]->arg
;
14799 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14801 return CMD_WARNING
;
14803 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14804 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14807 vty_out(vty
, "Address Family: %s\n",
14808 get_afi_safi_str(afi
, safi
, false));
14809 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14812 vty_out(vty
, "{}\n");
14814 vty_out(vty
, "No functional output\n");
14817 return CMD_SUCCESS
;
14820 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14821 afi_t afi
, safi_t safi
,
14822 enum bgp_show_type type
, bool use_json
)
14824 uint16_t show_flags
= 0;
14827 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14829 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14831 json_object
*json_no
= NULL
;
14832 json_no
= json_object_new_object();
14833 json_object_string_add(
14834 json_no
, "warning",
14835 "No such neighbor or address family");
14836 vty_out(vty
, "%s\n",
14837 json_object_to_json_string(json_no
));
14838 json_object_free(json_no
);
14840 vty_out(vty
, "%% No such neighbor or address family\n");
14841 return CMD_WARNING
;
14844 /* labeled-unicast routes live in the unicast table */
14845 if (safi
== SAFI_LABELED_UNICAST
)
14846 safi
= SAFI_UNICAST
;
14848 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14849 RPKI_NOT_BEING_USED
);
14852 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14853 show_ip_bgp_flowspec_routes_detailed_cmd
,
14854 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14858 BGP_INSTANCE_HELP_STR
14861 "Detailed information on flowspec entries\n"
14864 afi_t afi
= AFI_IP6
;
14865 safi_t safi
= SAFI_UNICAST
;
14866 struct bgp
*bgp
= NULL
;
14868 bool uj
= use_json(argc
, argv
);
14869 uint16_t show_flags
= BGP_SHOW_OPT_ROUTES_DETAIL
;
14873 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14876 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14879 return CMD_WARNING
;
14881 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14882 show_flags
, RPKI_NOT_BEING_USED
);
14885 DEFUN (show_ip_bgp_neighbor_routes
,
14886 show_ip_bgp_neighbor_routes_cmd
,
14887 "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]",
14891 BGP_INSTANCE_HELP_STR
14893 BGP_SAFI_WITH_LABEL_HELP_STR
14894 "Detailed information on TCP and BGP neighbor connections\n"
14895 "Neighbor to display information about\n"
14896 "Neighbor to display information about\n"
14897 "Neighbor on BGP configured interface\n"
14898 "Display flap statistics of the routes learned from neighbor\n"
14899 "Display the dampened routes received from neighbor\n"
14900 "Display routes learned from neighbor\n"
14903 char *peerstr
= NULL
;
14904 struct bgp
*bgp
= NULL
;
14905 afi_t afi
= AFI_IP6
;
14906 safi_t safi
= SAFI_UNICAST
;
14908 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14910 bool uj
= use_json(argc
, argv
);
14915 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14918 return CMD_WARNING
;
14920 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14921 argv_find(argv
, argc
, "neighbors", &idx
);
14922 peerstr
= argv
[++idx
]->arg
;
14924 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14926 return CMD_WARNING
;
14928 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14929 sh_type
= bgp_show_type_flap_neighbor
;
14930 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14931 sh_type
= bgp_show_type_damp_neighbor
;
14932 else if (argv_find(argv
, argc
, "routes", &idx
))
14933 sh_type
= bgp_show_type_neighbor
;
14935 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14938 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14940 struct bgp_distance
{
14941 /* Distance value for the IP source prefix. */
14944 /* Name of the access-list to be matched. */
14948 DEFUN (show_bgp_afi_vpn_rd_route
,
14949 show_bgp_afi_vpn_rd_route_cmd
,
14950 "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]",
14954 BGP_AF_MODIFIER_STR
14955 "Display information for a route distinguisher\n"
14956 "Route Distinguisher\n"
14957 "All Route Distinguishers\n"
14958 "Network in the BGP routing table to display\n"
14959 "Network in the BGP routing table to display\n"
14963 struct prefix_rd prd
;
14964 afi_t afi
= AFI_MAX
;
14967 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
14968 vty_out(vty
, "%% Malformed Address Family\n");
14969 return CMD_WARNING
;
14972 if (!strcmp(argv
[5]->arg
, "all"))
14973 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
14974 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
14975 RPKI_NOT_BEING_USED
,
14976 use_json(argc
, argv
));
14978 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
14980 vty_out(vty
, "%% Malformed Route Distinguisher\n");
14981 return CMD_WARNING
;
14984 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
14985 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14986 use_json(argc
, argv
));
14989 static struct bgp_distance
*bgp_distance_new(void)
14991 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
14994 static void bgp_distance_free(struct bgp_distance
*bdistance
)
14996 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
14999 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
15000 const char *ip_str
, const char *access_list_str
)
15007 struct bgp_dest
*dest
;
15008 struct bgp_distance
*bdistance
;
15010 afi
= bgp_node_afi(vty
);
15011 safi
= bgp_node_safi(vty
);
15013 ret
= str2prefix(ip_str
, &p
);
15015 vty_out(vty
, "Malformed prefix\n");
15016 return CMD_WARNING_CONFIG_FAILED
;
15019 distance
= atoi(distance_str
);
15021 /* Get BGP distance node. */
15022 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
15023 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15025 bgp_dest_unlock_node(dest
);
15027 bdistance
= bgp_distance_new();
15028 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
15031 /* Set distance value. */
15032 bdistance
->distance
= distance
;
15034 /* Reset access-list configuration. */
15035 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
15036 if (access_list_str
)
15037 bdistance
->access_list
=
15038 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
15040 return CMD_SUCCESS
;
15043 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
15044 const char *ip_str
, const char *access_list_str
)
15051 struct bgp_dest
*dest
;
15052 struct bgp_distance
*bdistance
;
15054 afi
= bgp_node_afi(vty
);
15055 safi
= bgp_node_safi(vty
);
15057 ret
= str2prefix(ip_str
, &p
);
15059 vty_out(vty
, "Malformed prefix\n");
15060 return CMD_WARNING_CONFIG_FAILED
;
15063 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
15065 vty_out(vty
, "Can't find specified prefix\n");
15066 return CMD_WARNING_CONFIG_FAILED
;
15069 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15070 distance
= atoi(distance_str
);
15072 if (bdistance
->distance
!= distance
) {
15073 vty_out(vty
, "Distance does not match configured\n");
15074 bgp_dest_unlock_node(dest
);
15075 return CMD_WARNING_CONFIG_FAILED
;
15078 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
15079 bgp_distance_free(bdistance
);
15081 bgp_dest_set_bgp_path_info(dest
, NULL
);
15082 bgp_dest_unlock_node(dest
);
15083 bgp_dest_unlock_node(dest
);
15085 return CMD_SUCCESS
;
15088 /* Apply BGP information to distance method. */
15089 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
15090 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
15092 struct bgp_dest
*dest
;
15093 struct prefix q
= {0};
15095 struct bgp_distance
*bdistance
;
15096 struct access_list
*alist
;
15097 struct bgp_static
*bgp_static
;
15098 struct bgp_path_info
*bpi_ultimate
;
15103 peer
= pinfo
->peer
;
15105 if (pinfo
->attr
->distance
)
15106 return pinfo
->attr
->distance
;
15108 /* get peer origin to calculate appropriate distance */
15109 if (pinfo
->sub_type
== BGP_ROUTE_IMPORTED
) {
15110 bpi_ultimate
= bgp_get_imported_bpi_ultimate(pinfo
);
15111 peer
= bpi_ultimate
->peer
;
15114 /* Check source address.
15115 * Note: for aggregate route, peer can have unspec af type.
15117 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
15118 && !sockunion2hostprefix(&peer
->su
, &q
))
15121 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
15123 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15124 bgp_dest_unlock_node(dest
);
15126 if (bdistance
->access_list
) {
15127 alist
= access_list_lookup(afi
, bdistance
->access_list
);
15129 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
15130 return bdistance
->distance
;
15132 return bdistance
->distance
;
15135 /* Backdoor check. */
15136 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
15138 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15139 bgp_dest_unlock_node(dest
);
15141 if (bgp_static
->backdoor
) {
15142 if (bgp
->distance_local
[afi
][safi
])
15143 return bgp
->distance_local
[afi
][safi
];
15145 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15149 if (peer
->sort
== BGP_PEER_EBGP
) {
15150 if (bgp
->distance_ebgp
[afi
][safi
])
15151 return bgp
->distance_ebgp
[afi
][safi
];
15152 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
15153 } else if (peer
->sort
== BGP_PEER_IBGP
) {
15154 if (bgp
->distance_ibgp
[afi
][safi
])
15155 return bgp
->distance_ibgp
[afi
][safi
];
15156 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15158 if (bgp
->distance_local
[afi
][safi
])
15159 return bgp
->distance_local
[afi
][safi
];
15160 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15164 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15165 * we should tell ZEBRA update the routes for a specific
15166 * AFI/SAFI to reflect changes in RIB.
15168 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
15170 safi_t update_safi
)
15175 FOREACH_AFI_SAFI (afi
, safi
) {
15176 if (!bgp_fibupd_safi(safi
))
15179 if (afi
!= update_afi
&& safi
!= update_safi
)
15182 if (BGP_DEBUG(zebra
, ZEBRA
))
15184 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15185 __func__
, afi
, safi
);
15186 bgp_zebra_announce_table(bgp
, afi
, safi
);
15190 DEFUN (bgp_distance
,
15192 "distance bgp (1-255) (1-255) (1-255)",
15193 "Define an administrative distance\n"
15195 "Distance for routes external to the AS\n"
15196 "Distance for routes internal to the AS\n"
15197 "Distance for local routes\n")
15199 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15200 int idx_number
= 2;
15201 int idx_number_2
= 3;
15202 int idx_number_3
= 4;
15203 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
15204 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
15205 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
15209 afi
= bgp_node_afi(vty
);
15210 safi
= bgp_node_safi(vty
);
15212 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
15213 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
15214 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
15215 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
15216 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
15217 bgp
->distance_local
[afi
][safi
] = distance_local
;
15218 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15220 return CMD_SUCCESS
;
15223 DEFUN (no_bgp_distance
,
15224 no_bgp_distance_cmd
,
15225 "no distance bgp [(1-255) (1-255) (1-255)]",
15227 "Define an administrative distance\n"
15229 "Distance for routes external to the AS\n"
15230 "Distance for routes internal to the AS\n"
15231 "Distance for local routes\n")
15233 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15237 afi
= bgp_node_afi(vty
);
15238 safi
= bgp_node_safi(vty
);
15240 if (bgp
->distance_ebgp
[afi
][safi
] != 0
15241 || bgp
->distance_ibgp
[afi
][safi
] != 0
15242 || bgp
->distance_local
[afi
][safi
] != 0) {
15243 bgp
->distance_ebgp
[afi
][safi
] = 0;
15244 bgp
->distance_ibgp
[afi
][safi
] = 0;
15245 bgp
->distance_local
[afi
][safi
] = 0;
15246 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15248 return CMD_SUCCESS
;
15252 DEFUN (bgp_distance_source
,
15253 bgp_distance_source_cmd
,
15254 "distance (1-255) A.B.C.D/M",
15255 "Define an administrative distance\n"
15256 "Administrative distance\n"
15257 "IP source prefix\n")
15259 int idx_number
= 1;
15260 int idx_ipv4_prefixlen
= 2;
15261 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15262 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15263 return CMD_SUCCESS
;
15266 DEFUN (no_bgp_distance_source
,
15267 no_bgp_distance_source_cmd
,
15268 "no distance (1-255) A.B.C.D/M",
15270 "Define an administrative distance\n"
15271 "Administrative distance\n"
15272 "IP source prefix\n")
15274 int idx_number
= 2;
15275 int idx_ipv4_prefixlen
= 3;
15276 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15277 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15278 return CMD_SUCCESS
;
15281 DEFUN (bgp_distance_source_access_list
,
15282 bgp_distance_source_access_list_cmd
,
15283 "distance (1-255) A.B.C.D/M WORD",
15284 "Define an administrative distance\n"
15285 "Administrative distance\n"
15286 "IP source prefix\n"
15287 "Access list name\n")
15289 int idx_number
= 1;
15290 int idx_ipv4_prefixlen
= 2;
15292 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15293 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15294 return CMD_SUCCESS
;
15297 DEFUN (no_bgp_distance_source_access_list
,
15298 no_bgp_distance_source_access_list_cmd
,
15299 "no distance (1-255) A.B.C.D/M WORD",
15301 "Define an administrative distance\n"
15302 "Administrative distance\n"
15303 "IP source prefix\n"
15304 "Access list name\n")
15306 int idx_number
= 2;
15307 int idx_ipv4_prefixlen
= 3;
15309 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15310 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15311 return CMD_SUCCESS
;
15314 DEFUN (ipv6_bgp_distance_source
,
15315 ipv6_bgp_distance_source_cmd
,
15316 "distance (1-255) X:X::X:X/M",
15317 "Define an administrative distance\n"
15318 "Administrative distance\n"
15319 "IP source prefix\n")
15321 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
15322 return CMD_SUCCESS
;
15325 DEFUN (no_ipv6_bgp_distance_source
,
15326 no_ipv6_bgp_distance_source_cmd
,
15327 "no distance (1-255) X:X::X:X/M",
15329 "Define an administrative distance\n"
15330 "Administrative distance\n"
15331 "IP source prefix\n")
15333 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
15334 return CMD_SUCCESS
;
15337 DEFUN (ipv6_bgp_distance_source_access_list
,
15338 ipv6_bgp_distance_source_access_list_cmd
,
15339 "distance (1-255) X:X::X:X/M WORD",
15340 "Define an administrative distance\n"
15341 "Administrative distance\n"
15342 "IP source prefix\n"
15343 "Access list name\n")
15345 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
15346 return CMD_SUCCESS
;
15349 DEFUN (no_ipv6_bgp_distance_source_access_list
,
15350 no_ipv6_bgp_distance_source_access_list_cmd
,
15351 "no distance (1-255) X:X::X:X/M WORD",
15353 "Define an administrative distance\n"
15354 "Administrative distance\n"
15355 "IP source prefix\n"
15356 "Access list name\n")
15358 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
15359 return CMD_SUCCESS
;
15362 DEFUN (bgp_damp_set
,
15364 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15365 "BGP Specific commands\n"
15366 "Enable route-flap dampening\n"
15367 "Half-life time for the penalty\n"
15368 "Value to start reusing a route\n"
15369 "Value to start suppressing a route\n"
15370 "Maximum duration to suppress a stable route\n")
15372 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15373 int idx_half_life
= 2;
15375 int idx_suppress
= 4;
15376 int idx_max_suppress
= 5;
15377 int half
= DEFAULT_HALF_LIFE
* 60;
15378 int reuse
= DEFAULT_REUSE
;
15379 int suppress
= DEFAULT_SUPPRESS
;
15380 int max
= 4 * half
;
15383 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15384 reuse
= atoi(argv
[idx_reuse
]->arg
);
15385 suppress
= atoi(argv
[idx_suppress
]->arg
);
15386 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
15387 } else if (argc
== 3) {
15388 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15393 * These can't be 0 but our SA doesn't understand the
15394 * way our cli is constructed
15398 if (suppress
< reuse
) {
15400 "Suppress value cannot be less than reuse value \n");
15404 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
15405 reuse
, suppress
, max
);
15408 DEFUN (bgp_damp_unset
,
15409 bgp_damp_unset_cmd
,
15410 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15412 "BGP Specific commands\n"
15413 "Enable route-flap dampening\n"
15414 "Half-life time for the penalty\n"
15415 "Value to start reusing a route\n"
15416 "Value to start suppressing a route\n"
15417 "Maximum duration to suppress a stable route\n")
15419 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15420 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
15423 /* Display specified route of BGP table. */
15424 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
15425 const char *ip_str
, afi_t afi
, safi_t safi
,
15426 struct prefix_rd
*prd
, int prefix_check
)
15429 struct prefix match
;
15430 struct bgp_dest
*dest
;
15431 struct bgp_dest
*rm
;
15432 struct bgp_path_info
*pi
;
15433 struct bgp_path_info
*pi_temp
;
15435 struct bgp_table
*table
;
15437 /* BGP structure lookup. */
15439 bgp
= bgp_lookup_by_name(view_name
);
15441 vty_out(vty
, "%% Can't find BGP instance %s\n",
15443 return CMD_WARNING
;
15446 bgp
= bgp_get_default();
15448 vty_out(vty
, "%% No BGP process is configured\n");
15449 return CMD_WARNING
;
15453 /* Check IP address argument. */
15454 ret
= str2prefix(ip_str
, &match
);
15456 vty_out(vty
, "%% address is malformed\n");
15457 return CMD_WARNING
;
15460 match
.family
= afi2family(afi
);
15462 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
15463 || (safi
== SAFI_EVPN
)) {
15464 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
15465 dest
= bgp_route_next(dest
)) {
15466 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15468 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
15470 table
= bgp_dest_get_bgp_table_info(dest
);
15473 rm
= bgp_node_match(table
, &match
);
15477 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
15480 || rm_p
->prefixlen
== match
.prefixlen
) {
15481 pi
= bgp_dest_get_bgp_path_info(rm
);
15483 if (pi
->extra
&& pi
->extra
->damp_info
) {
15484 pi_temp
= pi
->next
;
15485 bgp_damp_info_free(
15486 pi
->extra
->damp_info
,
15494 bgp_dest_unlock_node(rm
);
15497 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
15498 if (dest
!= NULL
) {
15499 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15502 || dest_p
->prefixlen
== match
.prefixlen
) {
15503 pi
= bgp_dest_get_bgp_path_info(dest
);
15505 if (pi
->extra
&& pi
->extra
->damp_info
) {
15506 pi_temp
= pi
->next
;
15507 bgp_damp_info_free(
15508 pi
->extra
->damp_info
,
15516 bgp_dest_unlock_node(dest
);
15520 return CMD_SUCCESS
;
15523 DEFUN (clear_ip_bgp_dampening
,
15524 clear_ip_bgp_dampening_cmd
,
15525 "clear ip bgp dampening",
15529 "Clear route flap dampening information\n")
15531 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
15532 return CMD_SUCCESS
;
15535 DEFUN (clear_ip_bgp_dampening_prefix
,
15536 clear_ip_bgp_dampening_prefix_cmd
,
15537 "clear ip bgp dampening A.B.C.D/M",
15541 "Clear route flap dampening information\n"
15544 int idx_ipv4_prefixlen
= 4;
15545 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
15546 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
15549 DEFUN (clear_ip_bgp_dampening_address
,
15550 clear_ip_bgp_dampening_address_cmd
,
15551 "clear ip bgp dampening A.B.C.D",
15555 "Clear route flap dampening information\n"
15556 "Network to clear damping information\n")
15559 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
15560 SAFI_UNICAST
, NULL
, 0);
15563 DEFUN (clear_ip_bgp_dampening_address_mask
,
15564 clear_ip_bgp_dampening_address_mask_cmd
,
15565 "clear ip bgp dampening A.B.C.D A.B.C.D",
15569 "Clear route flap dampening information\n"
15570 "Network to clear damping information\n"
15574 int idx_ipv4_2
= 5;
15576 char prefix_str
[BUFSIZ
];
15578 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
15579 prefix_str
, sizeof(prefix_str
));
15581 vty_out(vty
, "%% Inconsistent address and mask\n");
15582 return CMD_WARNING
;
15585 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
15589 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
15591 struct vty
*vty
= arg
;
15592 struct peer
*peer
= bucket
->data
;
15594 vty_out(vty
, "\tPeer: %s %pSU\n", peer
->host
, &peer
->su
);
15597 DEFUN (show_bgp_listeners
,
15598 show_bgp_listeners_cmd
,
15599 "show bgp listeners",
15602 "Display Listen Sockets and who created them\n")
15604 bgp_dump_listener_info(vty
);
15606 return CMD_SUCCESS
;
15609 DEFUN (show_bgp_peerhash
,
15610 show_bgp_peerhash_cmd
,
15611 "show bgp peerhash",
15614 "Display information about the BGP peerhash\n")
15616 struct list
*instances
= bm
->bgp
;
15617 struct listnode
*node
;
15620 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
15621 vty_out(vty
, "BGP: %s\n", bgp
->name
);
15622 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
15626 return CMD_SUCCESS
;
15629 /* also used for encap safi */
15630 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
15631 afi_t afi
, safi_t safi
)
15633 struct bgp_dest
*pdest
;
15634 struct bgp_dest
*dest
;
15635 struct bgp_table
*table
;
15636 const struct prefix
*p
;
15637 struct bgp_static
*bgp_static
;
15638 mpls_label_t label
;
15640 /* Network configuration. */
15641 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15642 pdest
= bgp_route_next(pdest
)) {
15643 table
= bgp_dest_get_bgp_table_info(pdest
);
15647 for (dest
= bgp_table_top(table
); dest
;
15648 dest
= bgp_route_next(dest
)) {
15649 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15650 if (bgp_static
== NULL
)
15653 p
= bgp_dest_get_prefix(dest
);
15655 /* "network" configuration display. */
15656 label
= decode_label(&bgp_static
->label
);
15658 vty_out(vty
, " network %pFX rd %s", p
,
15659 bgp_static
->prd_pretty
);
15660 if (safi
== SAFI_MPLS_VPN
)
15661 vty_out(vty
, " label %u", label
);
15663 if (bgp_static
->rmap
.name
)
15664 vty_out(vty
, " route-map %s",
15665 bgp_static
->rmap
.name
);
15667 if (bgp_static
->backdoor
)
15668 vty_out(vty
, " backdoor");
15670 vty_out(vty
, "\n");
15675 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
15676 afi_t afi
, safi_t safi
)
15678 struct bgp_dest
*pdest
;
15679 struct bgp_dest
*dest
;
15680 struct bgp_table
*table
;
15681 const struct prefix
*p
;
15682 struct bgp_static
*bgp_static
;
15683 char buf
[PREFIX_STRLEN
* 2];
15684 char buf2
[SU_ADDRSTRLEN
];
15685 char esi_buf
[ESI_STR_LEN
];
15687 /* Network configuration. */
15688 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15689 pdest
= bgp_route_next(pdest
)) {
15690 table
= bgp_dest_get_bgp_table_info(pdest
);
15694 for (dest
= bgp_table_top(table
); dest
;
15695 dest
= bgp_route_next(dest
)) {
15696 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15697 if (bgp_static
== NULL
)
15700 char *macrouter
= NULL
;
15702 if (bgp_static
->router_mac
)
15703 macrouter
= prefix_mac2str(
15704 bgp_static
->router_mac
, NULL
, 0);
15705 if (bgp_static
->eth_s_id
)
15706 esi_to_str(bgp_static
->eth_s_id
,
15707 esi_buf
, sizeof(esi_buf
));
15708 p
= bgp_dest_get_prefix(dest
);
15710 /* "network" configuration display. */
15711 if (p
->u
.prefix_evpn
.route_type
== 5) {
15712 char local_buf
[PREFIX_STRLEN
];
15714 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15715 struct prefix_evpn
*)p
)
15719 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
15721 local_buf
, sizeof(local_buf
));
15722 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15723 p
->u
.prefix_evpn
.prefix_addr
15724 .ip_prefix_length
);
15726 prefix2str(p
, buf
, sizeof(buf
));
15729 if (bgp_static
->gatewayIp
.family
== AF_INET
15730 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15731 inet_ntop(bgp_static
->gatewayIp
.family
,
15732 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15735 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15736 buf
, bgp_static
->prd_pretty
,
15737 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15738 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15741 XFREE(MTYPE_TMP
, macrouter
);
15746 /* Configuration of static route announcement and aggregate
15748 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15751 struct bgp_dest
*dest
;
15752 const struct prefix
*p
;
15753 struct bgp_static
*bgp_static
;
15754 struct bgp_aggregate
*bgp_aggregate
;
15756 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15757 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15761 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15762 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15766 /* Network configuration. */
15767 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15768 dest
= bgp_route_next(dest
)) {
15769 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15770 if (bgp_static
== NULL
)
15773 p
= bgp_dest_get_prefix(dest
);
15775 vty_out(vty
, " network %pFX", p
);
15777 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15778 vty_out(vty
, " label-index %u",
15779 bgp_static
->label_index
);
15781 if (bgp_static
->rmap
.name
)
15782 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15784 if (bgp_static
->backdoor
)
15785 vty_out(vty
, " backdoor");
15787 vty_out(vty
, "\n");
15790 /* Aggregate-address configuration. */
15791 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15792 dest
= bgp_route_next(dest
)) {
15793 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15794 if (bgp_aggregate
== NULL
)
15797 p
= bgp_dest_get_prefix(dest
);
15799 vty_out(vty
, " aggregate-address %pFX", p
);
15801 if (bgp_aggregate
->as_set
)
15802 vty_out(vty
, " as-set");
15804 if (bgp_aggregate
->summary_only
)
15805 vty_out(vty
, " summary-only");
15807 if (bgp_aggregate
->rmap
.name
)
15808 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15810 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15811 vty_out(vty
, " origin %s",
15812 bgp_origin2str(bgp_aggregate
->origin
));
15814 if (bgp_aggregate
->match_med
)
15815 vty_out(vty
, " matching-MED-only");
15817 if (bgp_aggregate
->suppress_map_name
)
15818 vty_out(vty
, " suppress-map %s",
15819 bgp_aggregate
->suppress_map_name
);
15821 vty_out(vty
, "\n");
15825 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15828 struct bgp_dest
*dest
;
15829 struct bgp_distance
*bdistance
;
15831 /* Distance configuration. */
15832 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15833 && bgp
->distance_local
[afi
][safi
]
15834 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15835 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15836 || bgp
->distance_local
[afi
][safi
]
15837 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15838 vty_out(vty
, " distance bgp %d %d %d\n",
15839 bgp
->distance_ebgp
[afi
][safi
],
15840 bgp
->distance_ibgp
[afi
][safi
],
15841 bgp
->distance_local
[afi
][safi
]);
15844 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15845 dest
= bgp_route_next(dest
)) {
15846 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15847 if (bdistance
!= NULL
)
15848 vty_out(vty
, " distance %d %pBD %s\n",
15849 bdistance
->distance
, dest
,
15850 bdistance
->access_list
? bdistance
->access_list
15855 /* Allocate routing table structure and install commands. */
15856 void bgp_route_init(void)
15861 /* Init BGP distance table. */
15862 FOREACH_AFI_SAFI (afi
, safi
)
15863 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15865 /* IPv4 BGP commands. */
15866 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15867 install_element(BGP_NODE
, &bgp_network_cmd
);
15868 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15870 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15872 /* IPv4 unicast configuration. */
15873 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15874 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15875 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15877 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15879 /* IPv4 multicast configuration. */
15880 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15881 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15882 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15883 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15885 /* IPv4 labeled-unicast configuration. */
15886 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15887 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15889 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15890 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15891 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15892 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15893 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15894 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15895 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15896 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15898 install_element(VIEW_NODE
,
15899 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15900 install_element(VIEW_NODE
,
15901 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15902 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15903 install_element(VIEW_NODE
,
15904 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15905 #ifdef KEEP_OLD_VPN_COMMANDS
15906 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15907 #endif /* KEEP_OLD_VPN_COMMANDS */
15908 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15909 install_element(VIEW_NODE
,
15910 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15912 /* BGP dampening clear commands */
15913 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15914 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15916 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15917 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15920 install_element(ENABLE_NODE
,
15921 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15922 #ifdef KEEP_OLD_VPN_COMMANDS
15923 install_element(ENABLE_NODE
,
15924 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15925 #endif /* KEEP_OLD_VPN_COMMANDS */
15927 /* New config IPv6 BGP commands. */
15928 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15929 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15930 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15932 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15934 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15936 /* IPv6 labeled unicast address family. */
15937 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15938 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15940 install_element(BGP_NODE
, &bgp_distance_cmd
);
15941 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15942 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15943 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
15944 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
15945 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
15946 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15947 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15948 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15949 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
15950 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
15951 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
15952 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15953 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15954 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
15955 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
15956 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
15957 install_element(BGP_IPV4M_NODE
,
15958 &no_bgp_distance_source_access_list_cmd
);
15959 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
15960 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
15961 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
15962 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15963 install_element(BGP_IPV6_NODE
,
15964 &ipv6_bgp_distance_source_access_list_cmd
);
15965 install_element(BGP_IPV6_NODE
,
15966 &no_ipv6_bgp_distance_source_access_list_cmd
);
15967 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
15968 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
15969 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
15970 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15971 install_element(BGP_IPV6M_NODE
,
15972 &ipv6_bgp_distance_source_access_list_cmd
);
15973 install_element(BGP_IPV6M_NODE
,
15974 &no_ipv6_bgp_distance_source_access_list_cmd
);
15976 /* BGP dampening */
15977 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
15978 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
15979 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
15980 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
15981 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
15982 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
15983 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
15984 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
15985 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
15986 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
15987 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
15988 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
15989 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
15990 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
15992 /* Large Communities */
15993 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
15994 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
15996 /* show bgp ipv4 flowspec detailed */
15997 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
15999 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
16000 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
16003 void bgp_route_finish(void)
16008 FOREACH_AFI_SAFI (afi
, safi
) {
16009 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
16010 bgp_distance_table
[afi
][safi
] = NULL
;