1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* BGP routing information
3 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
4 * Copyright (C) 2016 Job Snijders <job@instituut.net>
21 #include "sockunion.h"
24 #include "workqueue.h"
29 #include "lib_errors.h"
31 #include "bgpd/bgpd.h"
32 #include "bgpd/bgp_table.h"
33 #include "bgpd/bgp_route.h"
34 #include "bgpd/bgp_attr.h"
35 #include "bgpd/bgp_debug.h"
36 #include "bgpd/bgp_errors.h"
37 #include "bgpd/bgp_aspath.h"
38 #include "bgpd/bgp_regex.h"
39 #include "bgpd/bgp_community.h"
40 #include "bgpd/bgp_community_alias.h"
41 #include "bgpd/bgp_ecommunity.h"
42 #include "bgpd/bgp_lcommunity.h"
43 #include "bgpd/bgp_clist.h"
44 #include "bgpd/bgp_packet.h"
45 #include "bgpd/bgp_filter.h"
46 #include "bgpd/bgp_fsm.h"
47 #include "bgpd/bgp_mplsvpn.h"
48 #include "bgpd/bgp_nexthop.h"
49 #include "bgpd/bgp_damp.h"
50 #include "bgpd/bgp_advertise.h"
51 #include "bgpd/bgp_zebra.h"
52 #include "bgpd/bgp_vty.h"
53 #include "bgpd/bgp_mpath.h"
54 #include "bgpd/bgp_nht.h"
55 #include "bgpd/bgp_updgrp.h"
56 #include "bgpd/bgp_label.h"
57 #include "bgpd/bgp_addpath.h"
58 #include "bgpd/bgp_mac.h"
59 #include "bgpd/bgp_network.h"
60 #include "bgpd/bgp_trace.h"
61 #include "bgpd/bgp_rpki.h"
64 #include "bgpd/rfapi/rfapi_backend.h"
65 #include "bgpd/rfapi/vnc_import_bgp.h"
66 #include "bgpd/rfapi/vnc_export_bgp.h"
68 #include "bgpd/bgp_encap_types.h"
69 #include "bgpd/bgp_encap_tlv.h"
70 #include "bgpd/bgp_evpn.h"
71 #include "bgpd/bgp_evpn_mh.h"
72 #include "bgpd/bgp_evpn_vty.h"
73 #include "bgpd/bgp_flowspec.h"
74 #include "bgpd/bgp_flowspec_util.h"
75 #include "bgpd/bgp_pbr.h"
77 #include "bgpd/bgp_route_clippy.c"
79 DEFINE_HOOK(bgp_snmp_update_stats
,
80 (struct bgp_node
*rn
, struct bgp_path_info
*pi
, bool added
),
83 DEFINE_HOOK(bgp_rpki_prefix_status
,
84 (struct peer
*peer
, struct attr
*attr
,
85 const struct prefix
*prefix
),
86 (peer
, attr
, prefix
));
88 /* Extern from bgp_dump.c */
89 extern const char *bgp_origin_str
[];
90 extern const char *bgp_origin_long_str
[];
93 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
94 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
95 static const struct message bgp_pmsi_tnltype_str
[] = {
96 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
97 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
98 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
99 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
100 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
101 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
102 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
103 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
107 #define VRFID_NONE_STR "-"
108 #define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
110 DEFINE_HOOK(bgp_process
,
111 (struct bgp
* bgp
, afi_t afi
, safi_t safi
, struct bgp_dest
*bn
,
112 struct peer
*peer
, bool withdraw
),
113 (bgp
, afi
, safi
, bn
, peer
, withdraw
));
115 /** Test if path is suppressed. */
116 static bool bgp_path_suppressed(struct bgp_path_info
*pi
)
118 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
121 return listcount(pi
->extra
->aggr_suppressors
) > 0;
124 struct bgp_dest
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
125 safi_t safi
, const struct prefix
*p
,
126 struct prefix_rd
*prd
)
128 struct bgp_dest
*dest
;
129 struct bgp_dest
*pdest
= NULL
;
133 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
134 || (safi
== SAFI_EVPN
)) {
135 pdest
= bgp_node_get(table
, (struct prefix
*)prd
);
137 if (!bgp_dest_has_bgp_path_info_data(pdest
))
138 bgp_dest_set_bgp_table_info(
139 pdest
, bgp_table_init(table
->bgp
, afi
, safi
));
141 bgp_dest_unlock_node(pdest
);
142 table
= bgp_dest_get_bgp_table_info(pdest
);
145 dest
= bgp_node_get(table
, p
);
147 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
148 || (safi
== SAFI_EVPN
))
154 struct bgp_dest
*bgp_safi_node_lookup(struct bgp_table
*table
, safi_t safi
,
155 const struct prefix
*p
,
156 struct prefix_rd
*prd
)
158 struct bgp_dest
*dest
;
159 struct bgp_dest
*pdest
= NULL
;
164 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
165 || (safi
== SAFI_EVPN
)) {
166 pdest
= bgp_node_lookup(table
, (struct prefix
*)prd
);
170 if (!bgp_dest_has_bgp_path_info_data(pdest
)) {
171 bgp_dest_unlock_node(pdest
);
175 table
= bgp_dest_get_bgp_table_info(pdest
);
178 dest
= bgp_node_lookup(table
, p
);
183 /* Allocate bgp_path_info_extra */
184 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
186 struct bgp_path_info_extra
*new;
187 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
188 sizeof(struct bgp_path_info_extra
));
189 new->label
[0] = MPLS_INVALID_LABEL
;
191 new->bgp_fs_pbr
= NULL
;
192 new->bgp_fs_iprule
= NULL
;
196 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
198 struct bgp_path_info_extra
*e
;
200 if (!extra
|| !*extra
)
205 bgp_damp_info_free(e
->damp_info
, 0, e
->damp_info
->afi
,
210 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
213 /* FIXME: since multiple e may have the same e->parent
214 * and e->parent->net is holding a refcount for each
215 * of them, we need to do some fudging here.
217 * WARNING: if bpi->net->lock drops to 0, bpi may be
218 * freed as well (because bpi->net was holding the
219 * last reference to bpi) => write after free!
223 bpi
= bgp_path_info_lock(bpi
);
224 refcount
= bgp_dest_get_lock_count(bpi
->net
) - 1;
225 bgp_dest_unlock_node((struct bgp_dest
*)bpi
->net
);
228 bgp_path_info_unlock(bpi
);
230 bgp_path_info_unlock(e
->parent
);
235 bgp_unlock(e
->bgp_orig
);
238 peer_unlock(e
->peer_orig
);
240 if (e
->aggr_suppressors
)
241 list_delete(&e
->aggr_suppressors
);
244 bgp_evpn_path_mh_info_free(e
->mh_info
);
246 if ((*extra
)->bgp_fs_iprule
)
247 list_delete(&((*extra
)->bgp_fs_iprule
));
248 if ((*extra
)->bgp_fs_pbr
)
249 list_delete(&((*extra
)->bgp_fs_pbr
));
250 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
253 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
254 * allocated if required.
256 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
259 pi
->extra
= bgp_path_info_extra_new();
263 /* Free bgp route information. */
264 void bgp_path_info_free_with_caller(const char *name
,
265 struct bgp_path_info
*path
)
267 frrtrace(2, frr_bgp
, bgp_path_info_free
, path
, name
);
268 bgp_attr_unintern(&path
->attr
);
270 bgp_unlink_nexthop(path
);
271 bgp_path_info_extra_free(&path
->extra
);
272 bgp_path_info_mpath_free(&path
->mpath
);
274 bgp_addpath_free_info_data(&path
->tx_addpath
,
275 &path
->net
->tx_addpath
);
277 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
279 XFREE(MTYPE_BGP_ROUTE
, path
);
282 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
288 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
290 assert(path
&& path
->lock
> 0);
293 if (path
->lock
== 0) {
294 bgp_path_info_free(path
);
301 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
302 static int bgp_dest_set_defer_flag(struct bgp_dest
*dest
, bool delete)
305 struct bgp_path_info
*old_pi
, *nextpi
;
306 bool set_flag
= false;
307 struct bgp
*bgp
= NULL
;
308 struct bgp_table
*table
= NULL
;
312 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
313 * then the route selection is deferred
315 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
318 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
319 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
320 table
= bgp_dest_table(dest
);
325 "Route %pBD(%s) is in workqueue and being processed, not deferred.",
326 dest
, bgp
? bgp
->name_pretty
: "(Unknown)");
332 table
= bgp_dest_table(dest
);
339 for (old_pi
= bgp_dest_get_bgp_path_info(dest
);
340 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
341 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
344 /* Route selection is deferred if there is a stale path which
345 * which indicates peer is in restart mode
347 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
348 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
351 /* If the peer is graceful restart capable and peer is
352 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
355 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
356 && BGP_PEER_RESTARTING_MODE(peer
)
358 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
366 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
369 if (set_flag
&& table
) {
370 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
371 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
372 bgp
->gr_info
[afi
][safi
].gr_deferred
++;
373 SET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
374 if (BGP_DEBUG(update
, UPDATE_OUT
))
375 zlog_debug("DEFER route %pBD(%s), dest %p",
376 dest
, bgp
->name_pretty
, dest
);
383 void bgp_path_info_add_with_caller(const char *name
, struct bgp_dest
*dest
,
384 struct bgp_path_info
*pi
)
386 frrtrace(3, frr_bgp
, bgp_path_info_add
, dest
, pi
, name
);
387 struct bgp_path_info
*top
;
389 top
= bgp_dest_get_bgp_path_info(dest
);
395 bgp_dest_set_bgp_path_info(dest
, pi
);
397 bgp_path_info_lock(pi
);
398 bgp_dest_lock_node(dest
);
399 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
400 bgp_dest_set_defer_flag(dest
, false);
401 hook_call(bgp_snmp_update_stats
, dest
, pi
, true);
404 /* Do the actual removal of info from RIB, for use by bgp_process
405 completion callback *only* */
406 void bgp_path_info_reap(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
409 pi
->next
->prev
= pi
->prev
;
411 pi
->prev
->next
= pi
->next
;
413 bgp_dest_set_bgp_path_info(dest
, pi
->next
);
415 bgp_path_info_mpath_dequeue(pi
);
416 bgp_path_info_unlock(pi
);
417 hook_call(bgp_snmp_update_stats
, dest
, pi
, false);
418 bgp_dest_unlock_node(dest
);
421 void bgp_path_info_delete(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
423 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_REMOVED
);
424 /* set of previous already took care of pcount */
425 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
428 /* undo the effects of a previous call to bgp_path_info_delete; typically
429 called when a route is deleted and then quickly re-added before the
430 deletion has been processed */
431 void bgp_path_info_restore(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
433 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_REMOVED
);
434 /* unset of previous already took care of pcount */
435 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
438 /* Adjust pcount as required */
439 static void bgp_pcount_adjust(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
441 struct bgp_table
*table
;
443 assert(dest
&& bgp_dest_table(dest
));
444 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
446 table
= bgp_dest_table(dest
);
448 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
451 if (!BGP_PATH_COUNTABLE(pi
)
452 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
454 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
456 /* slight hack, but more robust against errors. */
457 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
458 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
460 flog_err(EC_LIB_DEVELOPMENT
,
461 "Asked to decrement 0 prefix count for peer");
462 } else if (BGP_PATH_COUNTABLE(pi
)
463 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
464 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
465 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
469 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
470 struct bgp_path_info
*pi2
)
472 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
475 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
476 * This is here primarily to keep prefix-count in check.
478 void bgp_path_info_set_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
481 SET_FLAG(pi
->flags
, flag
);
483 /* early bath if we know it's not a flag that changes countability state
485 if (!CHECK_FLAG(flag
,
486 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
489 bgp_pcount_adjust(dest
, pi
);
492 void bgp_path_info_unset_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
495 UNSET_FLAG(pi
->flags
, flag
);
497 /* early bath if we know it's not a flag that changes countability state
499 if (!CHECK_FLAG(flag
,
500 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
503 bgp_pcount_adjust(dest
, pi
);
506 /* Get MED value. If MED value is missing and "bgp bestpath
507 missing-as-worst" is specified, treat it as the worst value. */
508 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
510 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
513 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
520 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
,
525 if (pi
->sub_type
== BGP_ROUTE_IMPORTED
&&
526 bgp_get_imported_bpi_ultimate(pi
))
527 peer
= bgp_get_imported_bpi_ultimate(pi
)->peer
;
531 if (pi
->addpath_rx_id
)
532 snprintf(buf
, buf_len
, "path %s (addpath rxid %d)", peer
->host
,
535 snprintf(buf
, buf_len
, "path %s", peer
->host
);
540 * Get the ultimate path info.
542 struct bgp_path_info
*bgp_get_imported_bpi_ultimate(struct bgp_path_info
*info
)
544 struct bgp_path_info
*bpi_ultimate
;
546 if (info
->sub_type
!= BGP_ROUTE_IMPORTED
)
549 for (bpi_ultimate
= info
;
550 bpi_ultimate
->extra
&& bpi_ultimate
->extra
->parent
;
551 bpi_ultimate
= bpi_ultimate
->extra
->parent
)
557 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
559 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
560 struct bgp_path_info
*exist
, int *paths_eq
,
561 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
562 char *pfx_buf
, afi_t afi
, safi_t safi
,
563 enum bgp_path_selection_reason
*reason
)
565 const struct prefix
*new_p
;
566 struct attr
*newattr
, *existattr
;
567 enum bgp_peer_sort new_sort
;
568 enum bgp_peer_sort exist_sort
;
574 uint32_t exist_weight
;
575 uint32_t newm
, existm
;
576 struct in_addr new_id
;
577 struct in_addr exist_id
;
580 int internal_as_route
;
583 int igp_metric_ret
= 0;
584 int peer_sort_ret
= -1;
585 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
586 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
588 uint32_t exist_mm_seq
;
595 bool new_origin
, exist_origin
;
596 struct bgp_path_info
*bpi_ultimate
;
597 struct peer
*peer_new
, *peer_exist
;
603 *reason
= bgp_path_selection_none
;
605 zlog_debug("%s: new is NULL", pfx_buf
);
610 bpi_ultimate
= bgp_get_imported_bpi_ultimate(new);
611 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, new_buf
,
616 *reason
= bgp_path_selection_first
;
618 zlog_debug("%s(%s): %s is the initial bestpath",
619 pfx_buf
, bgp
->name_pretty
, new_buf
);
624 bpi_ultimate
= bgp_get_imported_bpi_ultimate(exist
);
625 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate
, exist_buf
,
627 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
628 pfx_buf
, bgp
->name_pretty
, new_buf
, new->flags
,
629 exist_buf
, exist
->flags
);
633 existattr
= exist
->attr
;
635 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
636 * Capability" to a neighbor MUST perform the following upon receiving
637 * a route from that neighbor with the "LLGR_STALE" community, or upon
638 * attaching the "LLGR_STALE" community itself per Section 4.2:
640 * Treat the route as the least-preferred in route selection (see
641 * below). See the Risks of Depreferencing Routes section (Section 5.2)
642 * for a discussion of potential risks inherent in doing this.
644 if (bgp_attr_get_community(newattr
) &&
645 community_include(bgp_attr_get_community(newattr
),
646 COMMUNITY_LLGR_STALE
)) {
649 "%s: %s wins over %s due to LLGR_STALE community",
650 pfx_buf
, new_buf
, exist_buf
);
654 if (bgp_attr_get_community(existattr
) &&
655 community_include(bgp_attr_get_community(existattr
),
656 COMMUNITY_LLGR_STALE
)) {
659 "%s: %s loses to %s due to LLGR_STALE community",
660 pfx_buf
, new_buf
, exist_buf
);
664 new_p
= bgp_dest_get_prefix(new->net
);
666 /* For EVPN routes, we cannot just go by local vs remote, we have to
667 * look at the MAC mobility sequence number, if present.
669 if ((safi
== SAFI_EVPN
)
670 && (new_p
->u
.prefix_evpn
.route_type
== BGP_EVPN_MAC_IP_ROUTE
)) {
671 /* This is an error condition described in RFC 7432 Section
673 * states that in this scenario "the PE MUST alert the operator"
675 * does not state what other action to take. In order to provide
677 * consistency in this scenario we are going to prefer the path
681 if (newattr
->sticky
!= existattr
->sticky
) {
683 prefix2str(new_p
, pfx_buf
,
685 * PREFIX2STR_BUFFER
);
686 bgp_path_info_path_with_addpath_rx_str(
687 new, new_buf
, sizeof(new_buf
));
688 bgp_path_info_path_with_addpath_rx_str(
689 exist
, exist_buf
, sizeof(exist_buf
));
692 if (newattr
->sticky
&& !existattr
->sticky
) {
693 *reason
= bgp_path_selection_evpn_sticky_mac
;
696 "%s: %s wins over %s due to sticky MAC flag",
697 pfx_buf
, new_buf
, exist_buf
);
701 if (!newattr
->sticky
&& existattr
->sticky
) {
702 *reason
= bgp_path_selection_evpn_sticky_mac
;
705 "%s: %s loses to %s due to sticky MAC flag",
706 pfx_buf
, new_buf
, exist_buf
);
711 new_esi
= bgp_evpn_attr_get_esi(newattr
);
712 exist_esi
= bgp_evpn_attr_get_esi(existattr
);
713 if (bgp_evpn_is_esi_valid(new_esi
) &&
714 !memcmp(new_esi
, exist_esi
, sizeof(esi_t
))) {
720 /* If both paths have the same non-zero ES and
721 * one path is local it wins.
722 * PS: Note the local path wins even if the remote
723 * has the higher MM seq. The local path's
724 * MM seq will be fixed up to match the highest
725 * rem seq, subsequently.
728 char esi_buf
[ESI_STR_LEN
];
730 if (bgp_evpn_is_path_local(bgp
, new)) {
731 *reason
= bgp_path_selection_evpn_local_path
;
734 "%s: %s wins over %s as ES %s is same and local",
735 pfx_buf
, new_buf
, exist_buf
,
736 esi_to_str(new_esi
, esi_buf
,
740 if (bgp_evpn_is_path_local(bgp
, exist
)) {
741 *reason
= bgp_path_selection_evpn_local_path
;
744 "%s: %s loses to %s as ES %s is same and local",
745 pfx_buf
, new_buf
, exist_buf
,
746 esi_to_str(new_esi
, esi_buf
,
752 new_mm_seq
= mac_mobility_seqnum(newattr
);
753 exist_mm_seq
= mac_mobility_seqnum(existattr
);
755 if (new_mm_seq
> exist_mm_seq
) {
756 *reason
= bgp_path_selection_evpn_seq
;
759 "%s: %s wins over %s due to MM seq %u > %u",
760 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
765 if (new_mm_seq
< exist_mm_seq
) {
766 *reason
= bgp_path_selection_evpn_seq
;
769 "%s: %s loses to %s due to MM seq %u < %u",
770 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
775 /* if the sequence numbers and ESI are the same and one path
776 * is non-proxy it wins (over proxy)
778 new_proxy
= bgp_evpn_attr_is_proxy(newattr
);
779 old_proxy
= bgp_evpn_attr_is_proxy(existattr
);
780 if (same_esi
&& bgp_evpn_attr_is_local_es(newattr
) &&
781 old_proxy
!= new_proxy
) {
783 *reason
= bgp_path_selection_evpn_non_proxy
;
786 "%s: %s wins over %s, same seq/es and non-proxy",
787 pfx_buf
, new_buf
, exist_buf
);
791 *reason
= bgp_path_selection_evpn_non_proxy
;
794 "%s: %s loses to %s, same seq/es and non-proxy",
795 pfx_buf
, new_buf
, exist_buf
);
800 * if sequence numbers are the same path with the lowest IP
803 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
805 *reason
= bgp_path_selection_evpn_lower_ip
;
808 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
809 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
810 &new->attr
->nexthop
);
814 *reason
= bgp_path_selection_evpn_lower_ip
;
817 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
818 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
819 &new->attr
->nexthop
);
824 /* 1. Weight check. */
825 new_weight
= newattr
->weight
;
826 exist_weight
= existattr
->weight
;
828 if (new_weight
> exist_weight
) {
829 *reason
= bgp_path_selection_weight
;
831 zlog_debug("%s: %s wins over %s due to weight %d > %d",
832 pfx_buf
, new_buf
, exist_buf
, new_weight
,
837 if (new_weight
< exist_weight
) {
838 *reason
= bgp_path_selection_weight
;
840 zlog_debug("%s: %s loses to %s due to weight %d < %d",
841 pfx_buf
, new_buf
, exist_buf
, new_weight
,
846 /* 2. Local preference check. */
847 new_pref
= exist_pref
= bgp
->default_local_pref
;
849 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
850 new_pref
= newattr
->local_pref
;
851 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
852 exist_pref
= existattr
->local_pref
;
854 if (new_pref
> exist_pref
) {
855 *reason
= bgp_path_selection_local_pref
;
858 "%s: %s wins over %s due to localpref %d > %d",
859 pfx_buf
, new_buf
, exist_buf
, new_pref
,
864 if (new_pref
< exist_pref
) {
865 *reason
= bgp_path_selection_local_pref
;
868 "%s: %s loses to %s due to localpref %d < %d",
869 pfx_buf
, new_buf
, exist_buf
, new_pref
,
874 /* If a BGP speaker supports ACCEPT_OWN and is configured for the
875 * extensions defined in this document, the following step is inserted
876 * after the LOCAL_PREF comparison step in the BGP decision process:
877 * When comparing a pair of routes for a BGP destination, the
878 * route with the ACCEPT_OWN community attached is preferred over
879 * the route that does not have the community.
880 * This extra step MUST only be invoked during the best path selection
881 * process of VPN-IP routes.
883 if (safi
== SAFI_MPLS_VPN
&&
884 (CHECK_FLAG(new->peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
) ||
885 CHECK_FLAG(exist
->peer
->af_flags
[afi
][safi
],
886 PEER_FLAG_ACCEPT_OWN
))) {
887 bool new_accept_own
= false;
888 bool exist_accept_own
= false;
889 uint32_t accept_own
= COMMUNITY_ACCEPT_OWN
;
891 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))
892 new_accept_own
= community_include(
893 bgp_attr_get_community(newattr
), accept_own
);
894 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))
895 exist_accept_own
= community_include(
896 bgp_attr_get_community(existattr
), accept_own
);
898 if (new_accept_own
&& !exist_accept_own
) {
899 *reason
= bgp_path_selection_accept_own
;
902 "%s: %s wins over %s due to accept-own",
903 pfx_buf
, new_buf
, exist_buf
);
907 if (!new_accept_own
&& exist_accept_own
) {
908 *reason
= bgp_path_selection_accept_own
;
911 "%s: %s loses to %s due to accept-own",
912 pfx_buf
, new_buf
, exist_buf
);
917 /* Tie-breaker - AIGP (Metric TLV) attribute */
918 if (CHECK_FLAG(newattr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) &&
919 CHECK_FLAG(existattr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) &&
920 CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_AIGP
)) {
921 uint64_t new_aigp
= bgp_attr_get_aigp_metric(newattr
);
922 uint64_t exist_aigp
= bgp_attr_get_aigp_metric(existattr
);
924 if (new_aigp
< exist_aigp
) {
925 *reason
= bgp_path_selection_aigp
;
928 "%s: %s wins over %s due to AIGP %" PRIu64
930 pfx_buf
, new_buf
, exist_buf
, new_aigp
,
935 if (new_aigp
> exist_aigp
) {
936 *reason
= bgp_path_selection_aigp
;
939 "%s: %s loses to %s due to AIGP %" PRIu64
941 pfx_buf
, new_buf
, exist_buf
, new_aigp
,
947 /* 3. Local route check. We prefer:
949 * - BGP_ROUTE_AGGREGATE
950 * - BGP_ROUTE_REDISTRIBUTE
952 new_origin
= !(new->sub_type
== BGP_ROUTE_NORMAL
||
953 new->sub_type
== BGP_ROUTE_IMPORTED
);
954 exist_origin
= !(exist
->sub_type
== BGP_ROUTE_NORMAL
||
955 exist
->sub_type
== BGP_ROUTE_IMPORTED
);
957 if (new_origin
&& !exist_origin
) {
958 *reason
= bgp_path_selection_local_route
;
961 "%s: %s wins over %s due to preferred BGP_ROUTE type",
962 pfx_buf
, new_buf
, exist_buf
);
966 if (!new_origin
&& exist_origin
) {
967 *reason
= bgp_path_selection_local_route
;
970 "%s: %s loses to %s due to preferred BGP_ROUTE type",
971 pfx_buf
, new_buf
, exist_buf
);
975 /* Here if these are imported routes then get ultimate pi for
978 new = bgp_get_imported_bpi_ultimate(new);
979 exist
= bgp_get_imported_bpi_ultimate(exist
);
981 existattr
= exist
->attr
;
983 /* 4. AS path length check. */
984 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
985 int exist_hops
= aspath_count_hops(existattr
->aspath
);
986 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
988 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
991 aspath_hops
= aspath_count_hops(newattr
->aspath
);
992 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
994 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
995 *reason
= bgp_path_selection_confed_as_path
;
998 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
999 pfx_buf
, new_buf
, exist_buf
,
1001 (exist_hops
+ exist_confeds
));
1005 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
1006 *reason
= bgp_path_selection_confed_as_path
;
1009 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
1010 pfx_buf
, new_buf
, exist_buf
,
1012 (exist_hops
+ exist_confeds
));
1016 int newhops
= aspath_count_hops(newattr
->aspath
);
1018 if (newhops
< exist_hops
) {
1019 *reason
= bgp_path_selection_as_path
;
1022 "%s: %s wins over %s due to aspath hopcount %d < %d",
1023 pfx_buf
, new_buf
, exist_buf
,
1024 newhops
, exist_hops
);
1028 if (newhops
> exist_hops
) {
1029 *reason
= bgp_path_selection_as_path
;
1032 "%s: %s loses to %s due to aspath hopcount %d > %d",
1033 pfx_buf
, new_buf
, exist_buf
,
1034 newhops
, exist_hops
);
1040 /* 5. Origin check. */
1041 if (newattr
->origin
< existattr
->origin
) {
1042 *reason
= bgp_path_selection_origin
;
1044 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
1045 pfx_buf
, new_buf
, exist_buf
,
1046 bgp_origin_long_str
[newattr
->origin
],
1047 bgp_origin_long_str
[existattr
->origin
]);
1051 if (newattr
->origin
> existattr
->origin
) {
1052 *reason
= bgp_path_selection_origin
;
1054 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
1055 pfx_buf
, new_buf
, exist_buf
,
1056 bgp_origin_long_str
[newattr
->origin
],
1057 bgp_origin_long_str
[existattr
->origin
]);
1062 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
1063 && aspath_count_hops(existattr
->aspath
) == 0);
1064 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
1065 && aspath_count_confeds(existattr
->aspath
) > 0
1066 && aspath_count_hops(newattr
->aspath
) == 0
1067 && aspath_count_hops(existattr
->aspath
) == 0);
1069 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
1070 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
1071 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
1072 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
1073 || internal_as_route
) {
1074 new_med
= bgp_med_value(new->attr
, bgp
);
1075 exist_med
= bgp_med_value(exist
->attr
, bgp
);
1077 if (new_med
< exist_med
) {
1078 *reason
= bgp_path_selection_med
;
1081 "%s: %s wins over %s due to MED %d < %d",
1082 pfx_buf
, new_buf
, exist_buf
, new_med
,
1087 if (new_med
> exist_med
) {
1088 *reason
= bgp_path_selection_med
;
1091 "%s: %s loses to %s due to MED %d > %d",
1092 pfx_buf
, new_buf
, exist_buf
, new_med
,
1098 if (exist
->sub_type
== BGP_ROUTE_IMPORTED
) {
1099 bpi_ultimate
= bgp_get_imported_bpi_ultimate(exist
);
1100 peer_exist
= bpi_ultimate
->peer
;
1102 peer_exist
= exist
->peer
;
1104 if (new->sub_type
== BGP_ROUTE_IMPORTED
) {
1105 bpi_ultimate
= bgp_get_imported_bpi_ultimate(new);
1106 peer_new
= bpi_ultimate
->peer
;
1108 peer_new
= new->peer
;
1110 /* 7. Peer type check. */
1111 new_sort
= peer_new
->sort
;
1112 exist_sort
= peer_exist
->sort
;
1114 if (new_sort
== BGP_PEER_EBGP
1115 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
1116 *reason
= bgp_path_selection_peer
;
1119 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1120 pfx_buf
, new_buf
, exist_buf
);
1121 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1126 if (exist_sort
== BGP_PEER_EBGP
1127 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
1128 *reason
= bgp_path_selection_peer
;
1131 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1132 pfx_buf
, new_buf
, exist_buf
);
1133 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1138 /* 8. IGP metric check. */
1142 newm
= new->extra
->igpmetric
;
1144 existm
= exist
->extra
->igpmetric
;
1146 if (newm
< existm
) {
1147 if (debug
&& peer_sort_ret
< 0)
1149 "%s: %s wins over %s due to IGP metric %u < %u",
1150 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1154 if (newm
> existm
) {
1155 if (debug
&& peer_sort_ret
< 0)
1157 "%s: %s loses to %s due to IGP metric %u > %u",
1158 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1162 /* 9. Same IGP metric. Compare the cluster list length as
1163 representative of IGP hops metric. Rewrite the metric value
1164 pair (newm, existm) with the cluster list length. Prefer the
1165 path with smaller cluster list length. */
1166 if (newm
== existm
) {
1167 if (peer_sort_lookup(peer_new
) == BGP_PEER_IBGP
&&
1168 peer_sort_lookup(peer_exist
) == BGP_PEER_IBGP
&&
1169 (mpath_cfg
== NULL
|| mpath_cfg
->same_clusterlen
)) {
1170 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1171 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1173 if (newm
< existm
) {
1174 if (debug
&& peer_sort_ret
< 0)
1176 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
1177 pfx_buf
, new_buf
, exist_buf
,
1182 if (newm
> existm
) {
1183 if (debug
&& peer_sort_ret
< 0)
1185 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
1186 pfx_buf
, new_buf
, exist_buf
,
1193 /* 10. confed-external vs. confed-internal */
1194 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1195 if (new_sort
== BGP_PEER_CONFED
1196 && exist_sort
== BGP_PEER_IBGP
) {
1197 *reason
= bgp_path_selection_confed
;
1200 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1201 pfx_buf
, new_buf
, exist_buf
);
1202 if (!CHECK_FLAG(bgp
->flags
,
1203 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1208 if (exist_sort
== BGP_PEER_CONFED
1209 && new_sort
== BGP_PEER_IBGP
) {
1210 *reason
= bgp_path_selection_confed
;
1213 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1214 pfx_buf
, new_buf
, exist_buf
);
1215 if (!CHECK_FLAG(bgp
->flags
,
1216 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX
))
1222 /* 11. Maximum path check. */
1223 if (newm
== existm
) {
1224 /* If one path has a label but the other does not, do not treat
1225 * them as equals for multipath
1232 newl
= new->extra
->num_labels
;
1234 existl
= exist
->extra
->num_labels
;
1235 if (((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0])) !=
1237 bgp_is_valid_label(&exist
->extra
->label
[0]))) ||
1241 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1242 pfx_buf
, new_buf
, exist_buf
);
1243 } else if (CHECK_FLAG(bgp
->flags
,
1244 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
1247 * For the two paths, all comparison steps till IGP
1249 * have succeeded - including AS_PATH hop count. Since
1251 * bestpath as-path multipath-relax' knob is on, we
1253 * an exact match of AS_PATH. Thus, mark the paths are
1255 * That will trigger both these paths to get into the
1263 "%s: %s and %s are equal via multipath-relax",
1264 pfx_buf
, new_buf
, exist_buf
);
1265 } else if (peer_new
->sort
== BGP_PEER_IBGP
) {
1266 if (aspath_cmp(new->attr
->aspath
,
1267 exist
->attr
->aspath
)) {
1272 "%s: %s and %s are equal via matching aspaths",
1273 pfx_buf
, new_buf
, exist_buf
);
1275 } else if (peer_new
->as
== peer_exist
->as
) {
1280 "%s: %s and %s are equal via same remote-as",
1281 pfx_buf
, new_buf
, exist_buf
);
1285 * TODO: If unequal cost ibgp multipath is enabled we can
1286 * mark the paths as equal here instead of returning
1289 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1290 * if either step 7 or 10 (peer type checks) yielded a winner,
1291 * that result was returned immediately. Returning from step 10
1292 * ignored the return value computed in steps 8 and 9 (IGP
1293 * metric checks). In order to preserve that behavior, if
1294 * peer_sort_ret is set, return that rather than igp_metric_ret.
1296 ret
= peer_sort_ret
;
1297 if (peer_sort_ret
< 0) {
1298 ret
= igp_metric_ret
;
1302 "%s: %s wins over %s after IGP metric comparison",
1303 pfx_buf
, new_buf
, exist_buf
);
1306 "%s: %s loses to %s after IGP metric comparison",
1307 pfx_buf
, new_buf
, exist_buf
);
1309 *reason
= bgp_path_selection_igp_metric
;
1315 * At this point, the decision whether to set *paths_eq = 1 has been
1316 * completed. If we deferred returning because of bestpath peer-type
1317 * relax configuration, return now.
1319 if (peer_sort_ret
>= 0)
1320 return peer_sort_ret
;
1322 /* 12. If both paths are external, prefer the path that was received
1323 first (the oldest one). This step minimizes route-flap, since a
1324 newer path won't displace an older one, even if it was the
1325 preferred route based on the additional decision criteria below. */
1326 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1327 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1328 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1329 *reason
= bgp_path_selection_older
;
1332 "%s: %s wins over %s due to oldest external",
1333 pfx_buf
, new_buf
, exist_buf
);
1337 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1338 *reason
= bgp_path_selection_older
;
1341 "%s: %s loses to %s due to oldest external",
1342 pfx_buf
, new_buf
, exist_buf
);
1347 /* 13. Router-ID comparison. */
1348 /* If one of the paths is "stale", the corresponding peer router-id will
1349 * be 0 and would always win over the other path. If originator id is
1350 * used for the comparison, it will decide which path is better.
1352 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1353 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1355 new_id
.s_addr
= peer_new
->remote_id
.s_addr
;
1356 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1357 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1359 exist_id
.s_addr
= peer_exist
->remote_id
.s_addr
;
1361 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1362 *reason
= bgp_path_selection_router_id
;
1365 "%s: %s wins over %s due to Router-ID comparison",
1366 pfx_buf
, new_buf
, exist_buf
);
1370 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1371 *reason
= bgp_path_selection_router_id
;
1374 "%s: %s loses to %s due to Router-ID comparison",
1375 pfx_buf
, new_buf
, exist_buf
);
1379 /* 14. Cluster length comparison. */
1380 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1381 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1383 if (new_cluster
< exist_cluster
) {
1384 *reason
= bgp_path_selection_cluster_length
;
1387 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1388 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1393 if (new_cluster
> exist_cluster
) {
1394 *reason
= bgp_path_selection_cluster_length
;
1397 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1398 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1403 /* 15. Neighbor address comparison. */
1404 /* Do this only if neither path is "stale" as stale paths do not have
1405 * valid peer information (as the connection may or may not be up).
1407 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1408 *reason
= bgp_path_selection_stale
;
1411 "%s: %s wins over %s due to latter path being STALE",
1412 pfx_buf
, new_buf
, exist_buf
);
1416 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1417 *reason
= bgp_path_selection_stale
;
1420 "%s: %s loses to %s due to former path being STALE",
1421 pfx_buf
, new_buf
, exist_buf
);
1425 /* locally configured routes to advertise do not have su_remote */
1426 if (peer_new
->su_remote
== NULL
) {
1427 *reason
= bgp_path_selection_local_configured
;
1431 if (peer_exist
->su_remote
== NULL
) {
1432 *reason
= bgp_path_selection_local_configured
;
1436 ret
= sockunion_cmp(peer_new
->su_remote
, peer_exist
->su_remote
);
1439 *reason
= bgp_path_selection_neighbor_ip
;
1442 "%s: %s loses to %s due to Neighor IP comparison",
1443 pfx_buf
, new_buf
, exist_buf
);
1448 *reason
= bgp_path_selection_neighbor_ip
;
1451 "%s: %s wins over %s due to Neighor IP comparison",
1452 pfx_buf
, new_buf
, exist_buf
);
1456 *reason
= bgp_path_selection_default
;
1458 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1459 pfx_buf
, new_buf
, exist_buf
);
1465 int bgp_evpn_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
1466 struct bgp_path_info
*exist
, int *paths_eq
)
1468 enum bgp_path_selection_reason reason
;
1469 char pfx_buf
[PREFIX2STR_BUFFER
];
1471 return bgp_path_info_cmp(bgp
, new, exist
, paths_eq
, NULL
, 0, pfx_buf
,
1472 AFI_L2VPN
, SAFI_EVPN
, &reason
);
1475 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1476 * is preferred, or 0 if they are the same (usually will only occur if
1477 * multipath is enabled
1478 * This version is compatible with */
1479 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1480 struct bgp_path_info
*exist
, char *pfx_buf
,
1481 afi_t afi
, safi_t safi
,
1482 enum bgp_path_selection_reason
*reason
)
1486 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1500 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1501 const struct prefix
*p
,
1502 struct attr
*attr
, afi_t afi
,
1505 struct bgp_filter
*filter
;
1506 enum filter_type ret
= FILTER_PERMIT
;
1508 filter
= &peer
->filter
[afi
][safi
];
1510 #define FILTER_EXIST_WARN(F, f, filter) \
1511 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1512 zlog_debug("%s: Could not find configured input %s-list %s!", \
1513 peer->host, #f, F##_IN_NAME(filter));
1515 if (DISTRIBUTE_IN_NAME(filter
)) {
1516 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1518 if (access_list_apply(DISTRIBUTE_IN(filter
), p
)
1525 if (PREFIX_LIST_IN_NAME(filter
)) {
1526 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1528 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
)
1535 if (FILTER_LIST_IN_NAME(filter
)) {
1536 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1538 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1539 == AS_FILTER_DENY
) {
1546 if (frrtrace_enabled(frr_bgp
, input_filter
)) {
1547 char pfxprint
[PREFIX2STR_BUFFER
];
1549 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1550 frrtrace(5, frr_bgp
, input_filter
, peer
, pfxprint
, afi
, safi
,
1551 ret
== FILTER_PERMIT
? "permit" : "deny");
1555 #undef FILTER_EXIST_WARN
1558 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1559 const struct prefix
*p
,
1560 struct attr
*attr
, afi_t afi
,
1563 struct bgp_filter
*filter
;
1564 enum filter_type ret
= FILTER_PERMIT
;
1566 filter
= &peer
->filter
[afi
][safi
];
1568 #define FILTER_EXIST_WARN(F, f, filter) \
1569 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1570 zlog_debug("%s: Could not find configured output %s-list %s!", \
1571 peer->host, #f, F##_OUT_NAME(filter));
1573 if (DISTRIBUTE_OUT_NAME(filter
)) {
1574 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1576 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
)
1583 if (PREFIX_LIST_OUT_NAME(filter
)) {
1584 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1586 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1593 if (FILTER_LIST_OUT_NAME(filter
)) {
1594 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1596 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1597 == AS_FILTER_DENY
) {
1603 if (frrtrace_enabled(frr_bgp
, output_filter
)) {
1604 char pfxprint
[PREFIX2STR_BUFFER
];
1606 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1607 frrtrace(5, frr_bgp
, output_filter
, peer
, pfxprint
, afi
, safi
,
1608 ret
== FILTER_PERMIT
? "permit" : "deny");
1613 #undef FILTER_EXIST_WARN
1616 /* If community attribute includes no_export then return 1. */
1617 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1619 if (bgp_attr_get_community(attr
)) {
1620 /* NO_ADVERTISE check. */
1621 if (community_include(bgp_attr_get_community(attr
),
1622 COMMUNITY_NO_ADVERTISE
))
1625 /* NO_EXPORT check. */
1626 if (peer
->sort
== BGP_PEER_EBGP
&&
1627 community_include(bgp_attr_get_community(attr
),
1628 COMMUNITY_NO_EXPORT
))
1631 /* NO_EXPORT_SUBCONFED check. */
1632 if (peer
->sort
== BGP_PEER_EBGP
1633 || peer
->sort
== BGP_PEER_CONFED
)
1634 if (community_include(bgp_attr_get_community(attr
),
1635 COMMUNITY_NO_EXPORT_SUBCONFED
))
1641 /* Route reflection loop check. */
1642 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1644 struct in_addr cluster_id
;
1645 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1648 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1649 cluster_id
= peer
->bgp
->cluster_id
;
1651 cluster_id
= peer
->bgp
->router_id
;
1653 if (cluster_loop_check(cluster
, cluster_id
))
1659 static bool bgp_otc_filter(struct peer
*peer
, struct attr
*attr
)
1661 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1662 if (peer
->local_role
== ROLE_PROVIDER
||
1663 peer
->local_role
== ROLE_RS_SERVER
)
1665 if (peer
->local_role
== ROLE_PEER
&& attr
->otc
!= peer
->as
)
1669 if (peer
->local_role
== ROLE_CUSTOMER
||
1670 peer
->local_role
== ROLE_PEER
||
1671 peer
->local_role
== ROLE_RS_CLIENT
) {
1672 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1673 attr
->otc
= peer
->as
;
1678 static bool bgp_otc_egress(struct peer
*peer
, struct attr
*attr
)
1680 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
1681 if (peer
->local_role
== ROLE_CUSTOMER
||
1682 peer
->local_role
== ROLE_RS_CLIENT
||
1683 peer
->local_role
== ROLE_PEER
)
1687 if (peer
->local_role
== ROLE_PROVIDER
||
1688 peer
->local_role
== ROLE_PEER
||
1689 peer
->local_role
== ROLE_RS_SERVER
) {
1690 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
1691 attr
->otc
= peer
->bgp
->as
;
1696 static bool bgp_check_role_applicability(afi_t afi
, safi_t safi
)
1698 return ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_UNICAST
);
1701 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1702 struct attr
*attr
, afi_t afi
, safi_t safi
,
1703 const char *rmap_name
, mpls_label_t
*label
,
1704 uint32_t num_labels
, struct bgp_dest
*dest
)
1706 struct bgp_filter
*filter
;
1707 struct bgp_path_info rmap_path
= { 0 };
1708 struct bgp_path_info_extra extra
= { 0 };
1709 route_map_result_t ret
;
1710 struct route_map
*rmap
= NULL
;
1712 filter
= &peer
->filter
[afi
][safi
];
1714 /* Apply default weight value. */
1715 if (peer
->weight
[afi
][safi
])
1716 attr
->weight
= peer
->weight
[afi
][safi
];
1719 rmap
= route_map_lookup_by_name(rmap_name
);
1724 if (ROUTE_MAP_IN_NAME(filter
)) {
1725 rmap
= ROUTE_MAP_IN(filter
);
1732 /* Route map apply. */
1734 memset(&rmap_path
, 0, sizeof(rmap_path
));
1735 /* Duplicate current value to new structure for modification. */
1736 rmap_path
.peer
= peer
;
1737 rmap_path
.attr
= attr
;
1738 rmap_path
.extra
= &extra
;
1739 rmap_path
.net
= dest
;
1741 extra
.num_labels
= num_labels
;
1742 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1743 memcpy(extra
.label
, label
,
1744 num_labels
* sizeof(mpls_label_t
));
1746 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1748 /* Apply BGP route map to the attribute. */
1749 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1751 peer
->rmap_type
= 0;
1753 if (ret
== RMAP_DENYMATCH
)
1759 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1760 struct attr
*attr
, afi_t afi
, safi_t safi
,
1761 const char *rmap_name
)
1763 struct bgp_path_info rmap_path
;
1764 route_map_result_t ret
;
1765 struct route_map
*rmap
= NULL
;
1769 * So if we get to this point and have no rmap_name
1770 * we want to just show the output as it currently
1776 /* Apply default weight value. */
1777 if (peer
->weight
[afi
][safi
])
1778 attr
->weight
= peer
->weight
[afi
][safi
];
1780 rmap
= route_map_lookup_by_name(rmap_name
);
1783 * If we have a route map name and we do not find
1784 * the routemap that means we have an implicit
1790 memset(&rmap_path
, 0, sizeof(rmap_path
));
1791 /* Route map apply. */
1792 /* Duplicate current value to new structure for modification. */
1793 rmap_path
.peer
= peer
;
1794 rmap_path
.attr
= attr
;
1796 rmap_type
= peer
->rmap_type
;
1797 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1799 /* Apply BGP route map to the attribute. */
1800 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1802 peer
->rmap_type
= rmap_type
;
1804 if (ret
== RMAP_DENYMATCH
)
1806 * caller has multiple error paths with bgp_attr_flush()
1813 /* If this is an EBGP peer with remove-private-AS */
1814 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1815 struct peer
*peer
, struct attr
*attr
)
1817 if (peer
->sort
== BGP_PEER_EBGP
1818 && (peer_af_flag_check(peer
, afi
, safi
,
1819 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1820 || peer_af_flag_check(peer
, afi
, safi
,
1821 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1822 || peer_af_flag_check(peer
, afi
, safi
,
1823 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1824 || peer_af_flag_check(peer
, afi
, safi
,
1825 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1826 // Take action on the entire aspath
1827 if (peer_af_flag_check(peer
, afi
, safi
,
1828 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1829 || peer_af_flag_check(peer
, afi
, safi
,
1830 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1831 if (peer_af_flag_check(
1833 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1834 attr
->aspath
= aspath_replace_private_asns(
1835 attr
->aspath
, bgp
->as
, peer
->as
);
1838 * Even if the aspath consists of just private ASNs we
1839 * need to walk the AS-Path to maintain all instances
1840 * of the peer's ASN to break possible loops.
1843 attr
->aspath
= aspath_remove_private_asns(
1844 attr
->aspath
, peer
->as
);
1847 // 'all' was not specified so the entire aspath must be private
1849 // for us to do anything
1850 else if (aspath_private_as_check(attr
->aspath
)) {
1851 if (peer_af_flag_check(
1853 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1854 attr
->aspath
= aspath_replace_private_asns(
1855 attr
->aspath
, bgp
->as
, peer
->as
);
1858 * Walk the aspath to retain any instances of
1861 attr
->aspath
= aspath_remove_private_asns(
1862 attr
->aspath
, peer
->as
);
1867 /* If this is an EBGP peer with as-override */
1868 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1869 struct peer
*peer
, struct attr
*attr
)
1871 struct aspath
*aspath
;
1873 if (peer
->sort
== BGP_PEER_EBGP
&&
1874 peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1875 if (attr
->aspath
->refcnt
)
1876 aspath
= aspath_dup(attr
->aspath
);
1878 aspath
= attr
->aspath
;
1880 attr
->aspath
= aspath_intern(
1881 aspath_replace_specific_asn(aspath
, peer
->as
, bgp
->as
));
1883 aspath_free(aspath
);
1887 void bgp_attr_add_llgr_community(struct attr
*attr
)
1889 struct community
*old
;
1890 struct community
*new;
1891 struct community
*merge
;
1892 struct community
*llgr
;
1894 old
= bgp_attr_get_community(attr
);
1895 llgr
= community_str2com("llgr-stale");
1900 merge
= community_merge(community_dup(old
), llgr
);
1902 if (old
->refcnt
== 0)
1903 community_free(&old
);
1905 new = community_uniq_sort(merge
);
1906 community_free(&merge
);
1908 new = community_dup(llgr
);
1911 community_free(&llgr
);
1913 bgp_attr_set_community(attr
, new);
1916 void bgp_attr_add_gshut_community(struct attr
*attr
)
1918 struct community
*old
;
1919 struct community
*new;
1920 struct community
*merge
;
1921 struct community
*gshut
;
1923 old
= bgp_attr_get_community(attr
);
1924 gshut
= community_str2com("graceful-shutdown");
1929 merge
= community_merge(community_dup(old
), gshut
);
1931 if (old
->refcnt
== 0)
1932 community_free(&old
);
1934 new = community_uniq_sort(merge
);
1935 community_free(&merge
);
1937 new = community_dup(gshut
);
1940 community_free(&gshut
);
1941 bgp_attr_set_community(attr
, new);
1943 /* When we add the graceful-shutdown community we must also
1944 * lower the local-preference */
1945 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1946 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1950 /* Notify BGP Conditional advertisement scanner process. */
1951 void bgp_notify_conditional_adv_scanner(struct update_subgroup
*subgrp
)
1953 struct peer
*peer
= SUBGRP_PEER(subgrp
);
1954 afi_t afi
= SUBGRP_AFI(subgrp
);
1955 safi_t safi
= SUBGRP_SAFI(subgrp
);
1956 struct bgp_filter
*filter
= &peer
->filter
[afi
][safi
];
1958 if (!ADVERTISE_MAP_NAME(filter
))
1961 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
))
1964 peer
->advmap_table_change
= true;
1968 void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1970 if (family
== AF_INET
) {
1971 attr
->nexthop
.s_addr
= INADDR_ANY
;
1972 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1974 if (family
== AF_INET6
)
1975 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1976 if (family
== AF_EVPN
)
1977 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1980 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
1981 struct update_subgroup
*subgrp
,
1982 const struct prefix
*p
, struct attr
*attr
,
1983 struct attr
*post_attr
)
1985 struct bgp_filter
*filter
;
1988 struct peer
*onlypeer
;
1990 struct attr
*piattr
;
1991 route_map_result_t ret
;
1996 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1997 bool nh_reset
= false;
2000 if (DISABLE_BGP_ANNOUNCE
)
2003 afi
= SUBGRP_AFI(subgrp
);
2004 safi
= SUBGRP_SAFI(subgrp
);
2005 peer
= SUBGRP_PEER(subgrp
);
2007 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
2008 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
2011 filter
= &peer
->filter
[afi
][safi
];
2012 bgp
= SUBGRP_INST(subgrp
);
2013 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
2016 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX_OUT
) &&
2017 peer
->pmax_out
[afi
][safi
] != 0 &&
2018 subgrp
->pscount
>= peer
->pmax_out
[afi
][safi
]) {
2019 if (BGP_DEBUG(update
, UPDATE_OUT
) ||
2020 BGP_DEBUG(update
, UPDATE_PREFIX
)) {
2021 zlog_debug("%s reached maximum prefix to be send (%u)",
2022 peer
->host
, peer
->pmax_out
[afi
][safi
]);
2027 #ifdef ENABLE_BGP_VNC
2028 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
2029 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
2030 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
2033 * direct and direct_ext type routes originate internally even
2034 * though they can have peer pointers that reference other
2037 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
2043 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
2044 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
2045 && (pi
->type
== ZEBRA_ROUTE_BGP
)
2046 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2048 /* Applies to routes leaked vpn->vrf and vrf->vpn */
2053 /* With addpath we may be asked to TX all kinds of paths so make sure
2055 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
2056 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
2057 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
2061 /* If this is not the bestpath then check to see if there is an enabled
2063 * feature that requires us to advertise it */
2064 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2065 if (!bgp_addpath_capable(pi
, peer
, afi
, safi
))
2068 /* Aggregate-address suppress check. */
2069 if (bgp_path_suppressed(pi
) && !UNSUPPRESS_MAP_NAME(filter
))
2073 * If we are doing VRF 2 VRF leaking via the import
2074 * statement, we want to prevent the route going
2075 * off box as that the RT and RD created are localy
2076 * significant and globaly useless.
2078 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
2079 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
2082 /* If it's labeled safi, make sure the route has a valid label. */
2083 if (safi
== SAFI_LABELED_UNICAST
) {
2084 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
2085 if (!bgp_is_valid_label(&label
)) {
2086 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2087 zlog_debug("u%" PRIu64
":s%" PRIu64
2088 " %pFX is filtered - no label (%p)",
2089 subgrp
->update_group
->id
, subgrp
->id
,
2095 /* Do not send back route to sender. */
2096 if (onlypeer
&& from
== onlypeer
) {
2100 /* Do not send the default route in the BGP table if the neighbor is
2101 * configured for default-originate */
2102 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2103 PEER_FLAG_DEFAULT_ORIGINATE
)) {
2104 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
2106 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
2110 /* Transparency check. */
2111 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
2112 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
2117 /* If community is not disabled check the no-export and local. */
2118 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
2119 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2120 zlog_debug("%s: community filter check fail for %pFX",
2125 /* If the attribute has originator-id and it is same as remote
2127 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2128 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
2129 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2131 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2136 /* ORF prefix-list filter check */
2137 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
2138 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
2139 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
2140 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
2141 if (peer
->orf_plist
[afi
][safi
]) {
2142 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
2144 if (bgp_debug_update(NULL
, p
,
2145 subgrp
->update_group
, 0))
2147 "%pBP [Update:SEND] %pFX is filtered via ORF",
2153 /* Output filter check. */
2154 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
2155 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2156 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer
,
2161 /* AS path loop check. */
2162 if (peer
->as_path_loop_detection
&&
2163 aspath_loop_check(piattr
->aspath
, peer
->as
)) {
2164 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2166 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2171 /* If we're a CONFED we need to loop check the CONFED ID too */
2172 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
2173 if (aspath_loop_check_confed(piattr
->aspath
, bgp
->confed_id
)) {
2174 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2176 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2177 peer
, bgp
->confed_id
);
2182 /* Route-Reflect check. */
2183 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2188 /* IBGP reflection check. */
2189 if (reflect
&& !samepeer_safe
) {
2190 /* A route from a Client peer. */
2191 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
2192 PEER_FLAG_REFLECTOR_CLIENT
)) {
2193 /* Reflect to all the Non-Client peers and also to the
2194 Client peers other than the originator. Originator
2196 is already done. So there is noting to do. */
2197 /* no bgp client-to-client reflection check. */
2198 if (CHECK_FLAG(bgp
->flags
,
2199 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
2200 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2201 PEER_FLAG_REFLECTOR_CLIENT
))
2204 /* A route from a Non-client peer. Reflect to all other
2206 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2207 PEER_FLAG_REFLECTOR_CLIENT
))
2212 /* For modify attribute, copy it to temporary structure.
2213 * post_attr comes from BGP conditional advertisements, where
2214 * attributes are already processed by advertise-map route-map,
2215 * and this needs to be saved instead of overwriting from the
2223 /* If local-preference is not set. */
2224 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
2225 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
2226 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2227 attr
->local_pref
= bgp
->default_local_pref
;
2230 /* If originator-id is not set and the route is to be reflected,
2231 set the originator id */
2233 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
2234 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
2235 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
2238 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2240 if (peer
->sort
== BGP_PEER_EBGP
2241 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
2242 if (from
!= bgp
->peer_self
&& !transparent
2243 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2244 PEER_FLAG_MED_UNCHANGED
))
2246 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
2249 /* Since the nexthop attribute can vary per peer, it is not explicitly
2251 * in announce check, only certain flags and length (or number of
2253 * -- for IPv6/MP_REACH) are set here in order to guide the update
2255 * code in setting the nexthop(s) on a per peer basis in
2257 * Typically, the source nexthop in the attribute is preserved but in
2259 * scenarios where we know it will always be overwritten, we reset the
2260 * nexthop to "0" in an attempt to achieve better Update packing. An
2261 * example of this is when a prefix from each of 2 IBGP peers needs to
2263 * announced to an EBGP peer (and they have the same attributes barring
2267 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
2269 #define NEXTHOP_IS_V6 \
2270 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2271 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2272 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2273 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2275 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2277 * the peer (group) is configured to receive link-local nexthop
2279 * and it is available in the prefix OR we're not reflecting the route,
2280 * link-local nexthop address is valid and
2281 * the peer (group) to whom we're going to announce is on a shared
2283 * and this is either a self-originated route or the peer is EBGP.
2284 * By checking if nexthop LL address is valid we are sure that
2285 * we do not announce LL address as `::`.
2287 if (NEXTHOP_IS_V6
) {
2288 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2289 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2290 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
2291 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
2292 || (!reflect
&& !transparent
2293 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
2294 && peer
->shared_network
2295 && (from
== bgp
->peer_self
2296 || peer
->sort
== BGP_PEER_EBGP
))) {
2297 if (safi
== SAFI_MPLS_VPN
)
2298 attr
->mp_nexthop_len
=
2299 BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
;
2301 attr
->mp_nexthop_len
=
2302 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2305 /* Clear off link-local nexthop in source, whenever it is not
2307 * ensure more prefixes share the same attribute for
2310 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2311 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
2312 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
2315 if (bgp_check_role_applicability(afi
, safi
) &&
2316 bgp_otc_egress(peer
, attr
))
2319 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
2320 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
2322 if (filter
->advmap
.update_type
== UPDATE_TYPE_WITHDRAW
&&
2323 filter
->advmap
.aname
&&
2324 route_map_lookup_by_name(filter
->advmap
.aname
)) {
2325 struct bgp_path_info rmap_path
= {0};
2326 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2327 struct attr dummy_attr
= *attr
;
2329 /* Fill temp path_info */
2330 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2331 pi
, peer
, &dummy_attr
);
2333 struct route_map
*amap
=
2334 route_map_lookup_by_name(filter
->advmap
.aname
);
2336 ret
= route_map_apply(amap
, p
, &rmap_path
);
2338 bgp_attr_flush(&dummy_attr
);
2341 * The conditional advertisement mode is Withdraw and this
2342 * prefix is a conditional prefix. Don't advertise it
2344 if (ret
== RMAP_PERMITMATCH
)
2348 /* Route map & unsuppress-map apply. */
2350 (ROUTE_MAP_OUT_NAME(filter
) || bgp_path_suppressed(pi
))) {
2351 struct bgp_path_info rmap_path
= {0};
2352 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2353 struct attr dummy_attr
= {0};
2355 /* Fill temp path_info */
2356 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2359 /* don't confuse inbound and outbound setting */
2360 RESET_FLAG(attr
->rmap_change_flags
);
2363 * The route reflector is not allowed to modify the attributes
2364 * of the reflected IBGP routes unless explicitly allowed.
2366 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2367 && !CHECK_FLAG(bgp
->flags
,
2368 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
2370 rmap_path
.attr
= &dummy_attr
;
2373 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
2375 if (bgp_path_suppressed(pi
))
2376 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
2379 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
2382 bgp_attr_flush(&dummy_attr
);
2383 peer
->rmap_type
= 0;
2385 if (ret
== RMAP_DENYMATCH
) {
2386 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2388 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2389 peer
, p
, ROUTE_MAP_OUT_NAME(filter
));
2390 bgp_attr_flush(rmap_path
.attr
);
2395 /* RFC 8212 to prevent route leaks.
2396 * This specification intends to improve this situation by requiring the
2397 * explicit configuration of both BGP Import and Export Policies for any
2398 * External BGP (EBGP) session such as customers, peers, or
2399 * confederation boundaries for all enabled address families. Through
2400 * codification of the aforementioned requirement, operators will
2401 * benefit from consistent behavior across different BGP
2404 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2405 if (!bgp_outbound_policy_exists(peer
, filter
)) {
2406 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
2407 NULL
) > FIFTEENMINUTE2USEC
||
2408 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
2410 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2411 monotime(&bgp
->ebgprequirespolicywarning
);
2416 /* draft-ietf-idr-deprecate-as-set-confed-set
2417 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2418 * Eventually, This document (if approved) updates RFC 4271
2419 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2420 * and obsoletes RFC 6472.
2422 if (peer
->bgp
->reject_as_sets
)
2423 if (aspath_check_as_sets(attr
->aspath
))
2426 /* If neighbor soo is configured, then check if the route has
2427 * SoO extended community and validate against the configured
2428 * one. If they match, do not announce, to prevent routing
2431 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) &&
2432 peer
->soo
[afi
][safi
]) {
2433 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
2434 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
2436 if ((ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS
,
2437 ECOMMUNITY_SITE_ORIGIN
) ||
2438 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_AS4
,
2439 ECOMMUNITY_SITE_ORIGIN
) ||
2440 ecommunity_lookup(ecomm
, ECOMMUNITY_ENCODE_IP
,
2441 ECOMMUNITY_SITE_ORIGIN
)) &&
2442 ecommunity_include(ecomm
, ecomm_soo
)) {
2443 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2445 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2446 peer
, p
, ecommunity_str(ecomm_soo
));
2451 /* Codification of AS 0 Processing */
2452 if (aspath_check_as_zero(attr
->aspath
))
2455 if (bgp_in_graceful_shutdown(bgp
)) {
2456 if (peer
->sort
== BGP_PEER_IBGP
2457 || peer
->sort
== BGP_PEER_CONFED
) {
2458 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2459 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2461 bgp_attr_add_gshut_community(attr
);
2465 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2466 * Capability" to a neighbor MUST perform the following upon receiving
2467 * a route from that neighbor with the "LLGR_STALE" community, or upon
2468 * attaching the "LLGR_STALE" community itself per Section 4.2:
2470 * The route SHOULD NOT be advertised to any neighbor from which the
2471 * Long-lived Graceful Restart Capability has not been received.
2473 if (bgp_attr_get_community(attr
) &&
2474 community_include(bgp_attr_get_community(attr
),
2475 COMMUNITY_LLGR_STALE
) &&
2476 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_RCV
) &&
2477 !CHECK_FLAG(peer
->cap
, PEER_CAP_LLGR_ADV
))
2480 /* After route-map has been applied, we check to see if the nexthop to
2481 * be carried in the attribute (that is used for the announcement) can
2482 * be cleared off or not. We do this in all cases where we would be
2483 * setting the nexthop to "ourselves". For IPv6, we only need to
2485 * the global nexthop here; the link-local nexthop would have been
2487 * already, and if not, it is required by the update formation code.
2488 * Also see earlier comments in this function.
2491 * If route-map has performed some operation on the nexthop or the peer
2492 * configuration says to pass it unchanged, we cannot reset the nexthop
2493 * here, so only attempt to do it if these aren't true. Note that the
2494 * route-map handler itself might have cleared the nexthop, if for
2496 * it is configured as 'peer-address'.
2498 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2499 piattr
->rmap_change_flags
)
2501 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2502 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2503 /* We can reset the nexthop, if setting (or forcing) it to
2505 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2506 PEER_FLAG_NEXTHOP_SELF
)
2507 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2508 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2510 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2511 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2512 subgroup_announce_reset_nhop(
2513 (peer_cap_enhe(peer
, afi
, safi
)
2519 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2520 /* Can also reset the nexthop if announcing to EBGP, but
2522 * no peer in the subgroup is on a shared subnet.
2523 * Note: 3rd party nexthop currently implemented for
2526 if ((p
->family
== AF_INET
) &&
2527 (!bgp_subgrp_multiaccess_check_v4(
2530 subgroup_announce_reset_nhop(
2531 (peer_cap_enhe(peer
, afi
, safi
)
2538 if ((p
->family
== AF_INET6
) &&
2539 (!bgp_subgrp_multiaccess_check_v6(
2540 piattr
->mp_nexthop_global
,
2542 subgroup_announce_reset_nhop(
2543 (peer_cap_enhe(peer
, afi
, safi
)
2552 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2554 * This flag is used for leaked vpn-vrf routes
2556 int family
= p
->family
;
2558 if (peer_cap_enhe(peer
, afi
, safi
))
2561 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2563 "%s: %pFX BGP_PATH_ANNC_NH_SELF, family=%s",
2564 __func__
, p
, family2str(family
));
2565 subgroup_announce_reset_nhop(family
, attr
);
2570 /* If IPv6/MP and nexthop does not have any override and happens
2572 * be a link-local address, reset it so that we don't pass along
2574 * source's link-local IPv6 address to recipients who may not be
2576 * the same interface.
2578 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2579 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2580 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2585 /* If this is an iBGP, send Origin Validation State (OVS)
2586 * extended community (rfc8097).
2588 if (peer
->sort
== BGP_PEER_IBGP
) {
2589 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
2591 rpki_state
= hook_call(bgp_rpki_prefix_status
, peer
, attr
, p
);
2593 if (rpki_state
!= RPKI_NOT_BEING_USED
)
2594 bgp_attr_set_ecommunity(
2595 attr
, ecommunity_add_origin_validation_state(
2597 bgp_attr_get_ecommunity(attr
)));
2601 * When the next hop is set to ourselves, if all multipaths have
2602 * link-bandwidth announce the cumulative bandwidth as that makes
2603 * the most sense. However, don't modify if the link-bandwidth has
2604 * been explicitly set by user policy.
2607 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2608 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2609 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2610 bgp_attr_set_ecommunity(
2612 ecommunity_replace_linkbw(
2613 bgp
->as
, bgp_attr_get_ecommunity(attr
), cum_bw
,
2616 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
)));
2621 static void bgp_route_select_timer_expire(struct event
*thread
)
2623 struct afi_safi_info
*info
;
2628 info
= EVENT_ARG(thread
);
2633 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2634 XFREE(MTYPE_TMP
, info
);
2636 /* Best path selection */
2637 bgp_best_path_select_defer(bgp
, afi
, safi
);
2640 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2641 struct bgp_maxpaths_cfg
*mpath_cfg
,
2642 struct bgp_path_info_pair
*result
, afi_t afi
,
2645 struct bgp_path_info
*new_select
;
2646 struct bgp_path_info
*old_select
;
2647 struct bgp_path_info
*pi
;
2648 struct bgp_path_info
*pi1
;
2649 struct bgp_path_info
*pi2
;
2650 struct bgp_path_info
*nextpi
= NULL
;
2651 int paths_eq
, do_mpath
, debug
;
2652 struct list mp_list
;
2653 char pfx_buf
[PREFIX2STR_BUFFER
];
2654 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2656 bgp_mp_list_init(&mp_list
);
2658 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2660 debug
= bgp_debug_bestpath(dest
);
2663 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2665 dest
->reason
= bgp_path_selection_none
;
2666 /* bgp deterministic-med */
2668 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2670 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2671 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2673 bgp_path_info_unset_flag(dest
, pi1
,
2674 BGP_PATH_DMED_SELECTED
);
2676 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2678 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2680 if (BGP_PATH_HOLDDOWN(pi1
))
2682 if (pi1
->peer
!= bgp
->peer_self
&&
2683 !CHECK_FLAG(pi1
->peer
->sflags
,
2684 PEER_STATUS_NSF_WAIT
)) {
2685 if (!peer_established(pi1
->peer
))
2691 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2692 if (CHECK_FLAG(pi2
->flags
,
2693 BGP_PATH_DMED_CHECK
))
2695 if (BGP_PATH_HOLDDOWN(pi2
))
2697 if (pi2
->peer
!= bgp
->peer_self
2700 PEER_STATUS_NSF_WAIT
))
2701 if (pi2
->peer
->status
2705 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2707 && !aspath_cmp_left_confed(
2712 if (bgp_path_info_cmp(
2713 bgp
, pi2
, new_select
,
2714 &paths_eq
, mpath_cfg
, debug
,
2717 bgp_path_info_unset_flag(
2719 BGP_PATH_DMED_SELECTED
);
2723 bgp_path_info_set_flag(
2724 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2727 bgp_path_info_set_flag(dest
, new_select
,
2728 BGP_PATH_DMED_CHECK
);
2729 bgp_path_info_set_flag(dest
, new_select
,
2730 BGP_PATH_DMED_SELECTED
);
2733 bgp_path_info_path_with_addpath_rx_str(
2734 new_select
, path_buf
, sizeof(path_buf
));
2736 "%pBD(%s): %s is the bestpath from AS %u",
2737 dest
, bgp
->name_pretty
, path_buf
,
2738 aspath_get_first_as(
2739 new_select
->attr
->aspath
));
2744 /* Check old selected route and new selected route. */
2747 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2748 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2749 enum bgp_path_selection_reason reason
;
2751 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2754 if (BGP_PATH_HOLDDOWN(pi
)) {
2755 /* reap REMOVED routes, if needs be
2756 * selected route must stay for a while longer though
2758 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2759 && (pi
!= old_select
))
2760 bgp_path_info_reap(dest
, pi
);
2764 "%s: %pBD(%s) pi from %s in holddown",
2765 __func__
, dest
, bgp
->name_pretty
,
2771 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2772 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2773 if (!peer_established(pi
->peer
)) {
2777 "%s: %pBD(%s) non self peer %s not estab state",
2785 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2786 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2787 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2789 zlog_debug("%s: %pBD(%s) pi %s dmed", __func__
,
2790 dest
, bgp
->name_pretty
,
2795 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2797 reason
= dest
->reason
;
2798 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2799 debug
, pfx_buf
, afi
, safi
,
2801 if (new_select
== NULL
&&
2802 reason
!= bgp_path_selection_none
)
2803 dest
->reason
= reason
;
2808 /* Now that we know which path is the bestpath see if any of the other
2810 * qualify as multipaths
2814 bgp_path_info_path_with_addpath_rx_str(
2815 new_select
, path_buf
, sizeof(path_buf
));
2817 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2819 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2820 dest
, bgp
->name_pretty
, path_buf
,
2821 old_select
? old_select
->peer
->host
: "NONE");
2824 if (do_mpath
&& new_select
) {
2825 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2826 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2829 bgp_path_info_path_with_addpath_rx_str(
2830 pi
, path_buf
, sizeof(path_buf
));
2832 if (pi
== new_select
) {
2835 "%pBD(%s): %s is the bestpath, add to the multipath list",
2836 dest
, bgp
->name_pretty
,
2838 bgp_mp_list_add(&mp_list
, pi
);
2842 if (BGP_PATH_HOLDDOWN(pi
))
2845 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2846 && !CHECK_FLAG(pi
->peer
->sflags
,
2847 PEER_STATUS_NSF_WAIT
))
2848 if (!peer_established(pi
->peer
))
2851 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2854 "%pBD(%s): %s has the same nexthop as the bestpath, skip it",
2855 dest
, bgp
->name_pretty
,
2860 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2861 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2867 "%pBD(%s): %s is equivalent to the bestpath, add to the multipath list",
2868 dest
, bgp
->name_pretty
,
2870 bgp_mp_list_add(&mp_list
, pi
);
2875 bgp_path_info_mpath_update(bgp
, dest
, new_select
, old_select
, &mp_list
,
2877 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2878 bgp_mp_list_clear(&mp_list
);
2880 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2882 result
->old
= old_select
;
2883 result
->new = new_select
;
2889 * A new route/change in bestpath of an existing route. Evaluate the path
2890 * for advertisement to the subgroup.
2892 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2893 struct bgp_path_info
*selected
,
2894 struct bgp_dest
*dest
,
2895 uint32_t addpath_tx_id
)
2897 const struct prefix
*p
;
2898 struct peer
*onlypeer
;
2905 p
= bgp_dest_get_prefix(dest
);
2906 afi
= SUBGRP_AFI(subgrp
);
2907 safi
= SUBGRP_SAFI(subgrp
);
2908 bgp
= SUBGRP_INST(subgrp
);
2909 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2912 if (BGP_DEBUG(update
, UPDATE_OUT
))
2913 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2915 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2916 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2917 PEER_STATUS_ORF_WAIT_REFRESH
))
2920 memset(&attr
, 0, sizeof(attr
));
2921 /* It's initialized in bgp_announce_check() */
2923 /* Announcement to the subgroup. If the route is filtered withdraw it.
2924 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2925 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2928 advertise
= bgp_check_advertise(bgp
, dest
);
2931 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2933 /* Route is selected, if the route is already installed
2934 * in FIB, then it is advertised
2937 if (!bgp_check_withdrawal(bgp
, dest
)) {
2938 struct attr
*adv_attr
=
2939 bgp_attr_intern(&attr
);
2941 bgp_adj_out_set_subgroup(dest
, subgrp
,
2945 bgp_adj_out_unset_subgroup(
2946 dest
, subgrp
, 1, addpath_tx_id
);
2949 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2953 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2955 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2960 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2961 * This is called at the end of route processing.
2963 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2965 struct bgp_path_info
*pi
;
2967 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2968 if (BGP_PATH_HOLDDOWN(pi
))
2970 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2971 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2976 * Has the route changed from the RIB's perspective? This is invoked only
2977 * if the route selection returns the same best route as earlier - to
2978 * determine if we need to update zebra or not.
2980 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2982 struct bgp_path_info
*mpinfo
;
2984 /* If this is multipath, check all selected paths for any nexthop
2985 * change or attribute change. Some attribute changes (e.g., community)
2986 * aren't of relevance to the RIB, but we'll update zebra to ensure
2987 * we handle the case of BGP nexthop change. This is the behavior
2988 * when the best path has an attribute change anyway.
2990 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2991 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2992 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2996 * If this is multipath, check all selected paths for any nexthop change
2998 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2999 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
3000 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
3001 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
3005 /* Nothing has changed from the RIB's perspective. */
3009 struct bgp_process_queue
{
3011 STAILQ_HEAD(, bgp_dest
) pqueue
;
3012 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
3014 unsigned int queued
;
3017 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
3018 safi_t safi
, struct bgp_dest
*dest
,
3019 struct bgp_path_info
*new_select
,
3020 struct bgp_path_info
*old_select
)
3022 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3024 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
3027 if (advertise_type5_routes(bgp
, afi
) && new_select
3028 && is_route_injectable_into_evpn(new_select
)) {
3030 /* apply the route-map */
3031 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
3032 route_map_result_t ret
;
3033 struct bgp_path_info rmap_path
;
3034 struct bgp_path_info_extra rmap_path_extra
;
3035 struct attr dummy_attr
;
3037 dummy_attr
= *new_select
->attr
;
3039 /* Fill temp path_info */
3040 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
3041 new_select
, new_select
->peer
,
3044 RESET_FLAG(dummy_attr
.rmap_change_flags
);
3046 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
3049 if (ret
== RMAP_DENYMATCH
) {
3050 bgp_attr_flush(&dummy_attr
);
3051 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
3054 bgp_evpn_advertise_type5_route(
3055 bgp
, p
, &dummy_attr
, afi
, safi
);
3057 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
3060 } else if (advertise_type5_routes(bgp
, afi
) && old_select
3061 && is_route_injectable_into_evpn(old_select
))
3062 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
3066 * Utility to determine whether a particular path_info should use
3067 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3068 * in a path where we basically _know_ this is a BGP-LU route.
3070 static bool bgp_lu_need_imp_null(const struct bgp_path_info
*new_select
)
3072 /* Certain types get imp null; so do paths where the nexthop is
3075 if (new_select
->sub_type
== BGP_ROUTE_STATIC
3076 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3077 || new_select
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
3079 else if (new_select
->extra
== NULL
||
3080 !bgp_is_valid_label(&new_select
->extra
->label
[0]))
3081 /* TODO -- should be configurable? */
3088 * old_select = The old best path
3089 * new_select = the new best path
3091 * if (!old_select && new_select)
3092 * We are sending new information on.
3094 * if (old_select && new_select) {
3095 * if (new_select != old_select)
3096 * We have a new best path send a change
3098 * We've received a update with new attributes that needs
3102 * if (old_select && !new_select)
3103 * We have no eligible route that we can announce or the rn
3106 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
3107 afi_t afi
, safi_t safi
)
3109 struct bgp_path_info
*new_select
;
3110 struct bgp_path_info
*old_select
;
3111 struct bgp_path_info_pair old_and_new
;
3114 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
3116 debug
= bgp_debug_bestpath(dest
);
3119 "%s: bgp delete in progress, ignoring event, p=%pBD(%s)",
3120 __func__
, dest
, bgp
->name_pretty
);
3123 /* Is it end of initial update? (after startup) */
3125 frr_timestamp(3, bgp
->update_delay_zebra_resume_time
,
3126 sizeof(bgp
->update_delay_zebra_resume_time
));
3128 bgp
->main_zebra_update_hold
= 0;
3129 FOREACH_AFI_SAFI (afi
, safi
) {
3130 if (bgp_fibupd_safi(safi
))
3131 bgp_zebra_announce_table(bgp
, afi
, safi
);
3133 bgp
->main_peers_update_hold
= 0;
3135 bgp_start_routeadv(bgp
);
3139 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3141 debug
= bgp_debug_bestpath(dest
);
3143 zlog_debug("%s: p=%pBD(%s) afi=%s, safi=%s start", __func__
,
3144 dest
, bgp
->name_pretty
, afi2str(afi
),
3147 /* The best path calculation for the route is deferred if
3148 * BGP_NODE_SELECT_DEFER is set
3150 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3151 if (BGP_DEBUG(update
, UPDATE_OUT
))
3152 zlog_debug("SELECT_DEFER flag set for route %p(%s)",
3153 dest
, bgp
->name_pretty
);
3157 /* Best path selection. */
3158 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
3160 old_select
= old_and_new
.old
;
3161 new_select
= old_and_new
.new;
3163 /* Do we need to allocate or free labels?
3164 * Right now, since we only deal with per-prefix labels, it is not
3165 * necessary to do this upon changes to best path. Exceptions:
3166 * - label index has changed -> recalculate resulting label
3167 * - path_info sub_type changed -> switch to/from implicit-null
3168 * - no valid label (due to removed static label binding) -> get new one
3170 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
3173 || bgp_label_index_differs(new_select
, old_select
)
3174 || new_select
->sub_type
!= old_select
->sub_type
3175 || !bgp_is_valid_label(&dest
->local_label
)) {
3176 /* Enforced penultimate hop popping:
3177 * implicit-null for local routes, aggregate
3178 * and redistributed routes
3180 if (bgp_lu_need_imp_null(new_select
)) {
3183 BGP_NODE_REGISTERED_FOR_LABEL
)
3186 BGP_NODE_LABEL_REQUESTED
))
3187 bgp_unregister_for_label(dest
);
3188 dest
->local_label
= mpls_lse_encode(
3189 MPLS_LABEL_IMPLICIT_NULL
, 0, 0,
3191 bgp_set_valid_label(&dest
->local_label
);
3193 bgp_register_for_label(dest
,
3196 } else if (CHECK_FLAG(dest
->flags
,
3197 BGP_NODE_REGISTERED_FOR_LABEL
)
3198 || CHECK_FLAG(dest
->flags
,
3199 BGP_NODE_LABEL_REQUESTED
)) {
3200 bgp_unregister_for_label(dest
);
3202 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
3203 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
3204 bgp_unregister_for_label(dest
);
3209 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3210 __func__
, dest
, bgp
->name_pretty
, afi2str(afi
),
3211 safi2str(safi
), old_select
, new_select
);
3213 /* If best route remains the same and this is not due to user-initiated
3214 * clear, see exactly what needs to be done.
3216 if (old_select
&& old_select
== new_select
3217 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
3218 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3219 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
3220 if (bgp_zebra_has_route_changed(old_select
)) {
3221 #ifdef ENABLE_BGP_VNC
3222 vnc_import_bgp_add_route(bgp
, p
, old_select
);
3223 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
3225 if (bgp_fibupd_safi(safi
)
3226 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3228 if (new_select
->type
== ZEBRA_ROUTE_BGP
3229 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3230 || new_select
->sub_type
3231 == BGP_ROUTE_IMPORTED
))
3233 bgp_zebra_announce(dest
, p
, old_select
,
3238 /* If there is a change of interest to peers, reannounce the
3240 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
3241 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3242 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
3243 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3245 /* unicast routes must also be annouced to
3246 * labeled-unicast update-groups */
3247 if (safi
== SAFI_UNICAST
)
3248 group_announce_route(bgp
, afi
,
3249 SAFI_LABELED_UNICAST
, dest
,
3252 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
3253 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
3256 /* advertise/withdraw type-5 routes */
3257 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
3258 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
3259 bgp_process_evpn_route_injection(
3260 bgp
, afi
, safi
, dest
, old_select
, old_select
);
3262 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3263 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3264 bgp_zebra_clear_route_change_flags(dest
);
3265 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3269 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3271 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
3273 /* bestpath has changed; bump version */
3274 if (old_select
|| new_select
) {
3275 bgp_bump_version(dest
);
3277 if (!bgp
->t_rmap_def_originate_eval
) {
3281 update_group_refresh_default_originate_route_map
,
3282 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
3283 &bgp
->t_rmap_def_originate_eval
);
3288 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
3291 zlog_debug("%s: setting SELECTED flag", __func__
);
3292 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
3293 bgp_path_info_unset_flag(dest
, new_select
,
3294 BGP_PATH_ATTR_CHANGED
);
3295 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
3296 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
3299 #ifdef ENABLE_BGP_VNC
3300 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3301 if (old_select
!= new_select
) {
3303 vnc_import_bgp_exterior_del_route(bgp
, p
,
3305 vnc_import_bgp_del_route(bgp
, p
, old_select
);
3308 vnc_import_bgp_exterior_add_route(bgp
, p
,
3310 vnc_import_bgp_add_route(bgp
, p
, new_select
);
3316 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
3318 /* unicast routes must also be annouced to labeled-unicast update-groups
3320 if (safi
== SAFI_UNICAST
)
3321 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
3325 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
3326 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
3328 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
3329 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
3330 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
3331 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
3333 /* if this is an evpn imported type-5 prefix,
3334 * we need to withdraw the route first to clear
3335 * the nh neigh and the RMAC entry.
3338 is_route_parent_evpn(old_select
))
3339 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3341 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
3343 /* Withdraw the route from the kernel. */
3344 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
3345 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
3346 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
3347 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
3349 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
3353 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
3356 /* Clear any route change flags. */
3357 bgp_zebra_clear_route_change_flags(dest
);
3359 /* Reap old select bgp_path_info, if it has been removed */
3360 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
3361 bgp_path_info_reap(dest
, old_select
);
3363 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3367 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3368 void bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
3370 struct bgp_dest
*dest
;
3372 struct afi_safi_info
*thread_info
;
3374 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
3375 struct event
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
3377 thread_info
= EVENT_ARG(t
);
3378 XFREE(MTYPE_TMP
, thread_info
);
3379 EVENT_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
3382 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
3383 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
3384 get_afi_safi_str(afi
, safi
, false),
3385 bgp
->gr_info
[afi
][safi
].gr_deferred
);
3388 /* Process the route list */
3389 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
3390 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0 &&
3391 cnt
< BGP_MAX_BEST_ROUTE_SELECT
;
3392 dest
= bgp_route_next(dest
)) {
3393 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
3396 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3397 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3398 bgp_process_main_one(bgp
, dest
, afi
, safi
);
3401 /* If iteration stopped before the entire table was traversed then the
3402 * node needs to be unlocked.
3405 bgp_dest_unlock_node(dest
);
3409 /* Send EOR message when all routes are processed */
3410 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
3411 bgp_send_delayed_eor(bgp
);
3412 /* Send route processing complete message to RIB */
3413 bgp_zebra_update(bgp
, afi
, safi
,
3414 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
3418 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3420 thread_info
->afi
= afi
;
3421 thread_info
->safi
= safi
;
3422 thread_info
->bgp
= bgp
;
3424 /* If there are more routes to be processed, start the
3427 event_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3428 BGP_ROUTE_SELECT_DELAY
,
3429 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3432 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3434 struct bgp_process_queue
*pqnode
= data
;
3435 struct bgp
*bgp
= pqnode
->bgp
;
3436 struct bgp_table
*table
;
3437 struct bgp_dest
*dest
;
3440 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3441 bgp_process_main_one(bgp
, NULL
, 0, 0);
3442 /* should always have dedicated wq call */
3443 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3447 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3448 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3449 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3450 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3451 table
= bgp_dest_table(dest
);
3452 /* note, new DESTs may be added as part of processing */
3453 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3455 bgp_dest_unlock_node(dest
);
3456 bgp_table_unlock(table
);
3462 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3464 struct bgp_process_queue
*pqnode
= data
;
3466 bgp_unlock(pqnode
->bgp
);
3468 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3471 void bgp_process_queue_init(struct bgp
*bgp
)
3473 if (!bgp
->process_queue
) {
3476 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3477 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3480 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3481 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3482 bgp
->process_queue
->spec
.max_retries
= 0;
3483 bgp
->process_queue
->spec
.hold
= 50;
3484 /* Use a higher yield value of 50ms for main queue processing */
3485 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3488 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3490 struct bgp_process_queue
*pqnode
;
3492 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3493 sizeof(struct bgp_process_queue
));
3495 /* unlocked in bgp_processq_del */
3496 pqnode
->bgp
= bgp_lock(bgp
);
3497 STAILQ_INIT(&pqnode
->pqueue
);
3502 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3504 #define ARBITRARY_PROCESS_QLEN 10000
3505 struct work_queue
*wq
= bgp
->process_queue
;
3506 struct bgp_process_queue
*pqnode
;
3507 int pqnode_reuse
= 0;
3509 /* already scheduled for processing? */
3510 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3513 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3516 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3517 if (BGP_DEBUG(update
, UPDATE_OUT
))
3518 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3523 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
)) {
3524 if (BGP_DEBUG(update
, UPDATE_OUT
))
3526 "Soft reconfigure table in progress for route %p",
3534 /* Add route nodes to an existing work queue item until reaching the
3535 limit only if is from the same BGP view and it's not an EOIU marker
3537 if (work_queue_item_count(wq
)) {
3538 struct work_queue_item
*item
= work_queue_last_item(wq
);
3539 pqnode
= item
->data
;
3541 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3542 || pqnode
->bgp
!= bgp
3543 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3544 pqnode
= bgp_processq_alloc(bgp
);
3548 pqnode
= bgp_processq_alloc(bgp
);
3549 /* all unlocked in bgp_process_wq */
3550 bgp_table_lock(bgp_dest_table(dest
));
3552 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3553 bgp_dest_lock_node(dest
);
3555 /* can't be enqueued twice */
3556 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3557 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3561 work_queue_add(wq
, pqnode
);
3566 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3568 struct bgp_process_queue
*pqnode
;
3570 if (bgp
->process_queue
== NULL
)
3573 pqnode
= bgp_processq_alloc(bgp
);
3575 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3576 work_queue_add(bgp
->process_queue
, pqnode
);
3579 static void bgp_maximum_prefix_restart_timer(struct event
*thread
)
3583 peer
= EVENT_ARG(thread
);
3584 peer
->t_pmax_restart
= NULL
;
3586 if (bgp_debug_neighbor_events(peer
))
3588 "%s Maximum-prefix restart timer expired, restore peering",
3591 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3592 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3595 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3599 bool filtered
= false;
3600 struct bgp_dest
*dest
;
3601 struct bgp_adj_in
*ain
;
3602 struct attr attr
= {};
3603 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3605 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3606 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3607 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3611 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3615 if (bgp_input_modifier(
3616 peer
, rn_p
, &attr
, afi
, safi
,
3617 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3625 bgp_attr_flush(&attr
);
3632 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3636 iana_safi_t pkt_safi
;
3637 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3638 PEER_FLAG_MAX_PREFIX_FORCE
))
3639 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3640 + peer
->pcount
[afi
][safi
]
3641 : peer
->pcount
[afi
][safi
];
3643 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3646 if (pcount
> peer
->pmax
[afi
][safi
]) {
3647 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3648 PEER_STATUS_PREFIX_LIMIT
)
3653 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3654 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3655 peer
->pmax
[afi
][safi
]);
3656 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3658 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3659 PEER_FLAG_MAX_PREFIX_WARNING
))
3662 /* Convert AFI, SAFI to values for packet. */
3663 pkt_afi
= afi_int2iana(afi
);
3664 pkt_safi
= safi_int2iana(safi
);
3668 ndata
[0] = (pkt_afi
>> 8);
3670 ndata
[2] = pkt_safi
;
3671 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3672 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3673 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3674 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3676 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3677 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3678 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3682 /* Dynamic peers will just close their connection. */
3683 if (peer_dynamic_neighbor(peer
))
3686 /* restart timer start */
3687 if (peer
->pmax_restart
[afi
][safi
]) {
3688 peer
->v_pmax_restart
=
3689 peer
->pmax_restart
[afi
][safi
] * 60;
3691 if (bgp_debug_neighbor_events(peer
))
3693 "%pBP Maximum-prefix restart timer started for %d secs",
3694 peer
, peer
->v_pmax_restart
);
3696 BGP_TIMER_ON(peer
->t_pmax_restart
,
3697 bgp_maximum_prefix_restart_timer
,
3698 peer
->v_pmax_restart
);
3703 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3704 PEER_STATUS_PREFIX_LIMIT
);
3707 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3708 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3709 PEER_STATUS_PREFIX_THRESHOLD
)
3714 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3715 get_afi_safi_str(afi
, safi
, false), peer
, pcount
,
3716 peer
->pmax
[afi
][safi
]);
3717 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3718 PEER_STATUS_PREFIX_THRESHOLD
);
3720 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3721 PEER_STATUS_PREFIX_THRESHOLD
);
3725 /* Unconditionally remove the route from the RIB, without taking
3726 * damping into consideration (eg, because the session went down)
3728 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3729 struct peer
*peer
, afi_t afi
, safi_t safi
)
3732 struct bgp
*bgp
= NULL
;
3733 bool delete_route
= false;
3735 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3738 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3739 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3741 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3744 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3745 delete_route
= true;
3746 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3747 delete_route
= true;
3749 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3750 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3751 bgp
= pi
->peer
->bgp
;
3752 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3757 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3758 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3761 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3762 struct peer
*peer
, afi_t afi
, safi_t safi
,
3763 struct prefix_rd
*prd
)
3765 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3767 /* apply dampening, if result is suppressed, we'll be retaining
3768 * the bgp_path_info in the RIB for historical reference.
3770 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3771 && peer
->sort
== BGP_PEER_EBGP
)
3772 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3773 == BGP_DAMP_SUPPRESSED
) {
3774 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3779 #ifdef ENABLE_BGP_VNC
3780 if (safi
== SAFI_MPLS_VPN
) {
3781 struct bgp_dest
*pdest
= NULL
;
3782 struct bgp_table
*table
= NULL
;
3784 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3785 (struct prefix
*)prd
);
3786 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3787 table
= bgp_dest_get_bgp_table_info(pdest
);
3789 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3790 peer
->bgp
, prd
, table
, p
, pi
);
3792 bgp_dest_unlock_node(pdest
);
3794 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3795 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3797 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3798 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3803 /* If this is an EVPN route, process for un-import. */
3804 if (safi
== SAFI_EVPN
)
3805 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3807 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3810 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3811 struct peer
*peer
, struct attr
*attr
,
3812 struct bgp_dest
*dest
)
3814 struct bgp_path_info
*new;
3816 /* Make new BGP info. */
3817 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3819 new->instance
= instance
;
3820 new->sub_type
= sub_type
;
3823 new->uptime
= monotime(NULL
);
3828 /* Check if received nexthop is valid or not. */
3829 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3830 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3831 struct bgp_dest
*dest
)
3834 bool is_bgp_static_route
=
3835 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3839 * Only validated for unicast and multicast currently.
3840 * Also valid for EVPN where the nexthop is an IP address.
3841 * If we are a bgp static route being checked then there is
3842 * no need to check to see if the nexthop is martian as
3843 * that it should be ok.
3845 if (is_bgp_static_route
||
3846 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3849 /* If NEXT_HOP is present, validate it. */
3850 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3851 if (attr
->nexthop
.s_addr
== INADDR_ANY
||
3852 !ipv4_unicast_valid(&attr
->nexthop
) ||
3853 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3857 /* If MP_NEXTHOP is present, validate it. */
3858 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3859 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3860 * it is not an IPv6 link-local address.
3862 * If we receive an UPDATE with nexthop length set to 32 bytes
3863 * we shouldn't discard an UPDATE if it's set to (::).
3864 * The link-local (2st) is validated along the code path later.
3866 if (attr
->mp_nexthop_len
) {
3867 switch (attr
->mp_nexthop_len
) {
3868 case BGP_ATTR_NHLEN_IPV4
:
3869 case BGP_ATTR_NHLEN_VPNV4
:
3870 ret
= (attr
->mp_nexthop_global_in
.s_addr
==
3872 !ipv4_unicast_valid(
3873 &attr
->mp_nexthop_global_in
) ||
3874 bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3878 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3879 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3880 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3881 &attr
->mp_nexthop_global
)
3882 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3883 || IN6_IS_ADDR_MULTICAST(
3884 &attr
->mp_nexthop_global
)
3885 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3888 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3889 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3890 || IN6_IS_ADDR_MULTICAST(
3891 &attr
->mp_nexthop_global
)
3892 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3905 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3907 struct community
*old
;
3908 struct community
*new;
3909 struct community
*merge
;
3910 struct community
*no_export
;
3912 old
= bgp_attr_get_community(attr
);
3913 no_export
= community_str2com("no-export");
3918 merge
= community_merge(community_dup(old
), no_export
);
3921 community_free(&old
);
3923 new = community_uniq_sort(merge
);
3924 community_free(&merge
);
3926 new = community_dup(no_export
);
3929 community_free(&no_export
);
3931 bgp_attr_set_community(attr
, new);
3934 static bool bgp_accept_own(struct peer
*peer
, afi_t afi
, safi_t safi
,
3935 struct attr
*attr
, const struct prefix
*prefix
,
3938 struct listnode
*node
, *nnode
;
3940 bool accept_own_found
= false;
3942 if (safi
!= SAFI_MPLS_VPN
)
3945 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3946 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ACCEPT_OWN
))
3949 /* The route in question carries the ACCEPT_OWN community */
3950 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
3951 struct community
*comm
= bgp_attr_get_community(attr
);
3953 if (community_include(comm
, COMMUNITY_ACCEPT_OWN
))
3954 accept_own_found
= true;
3957 /* The route in question is targeted to one or more destination VRFs
3958 * on the router (as determined by inspecting the Route Target(s)).
3960 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
3961 if (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
)
3964 if (accept_own_found
&&
3966 bgp
->vpn_policy
[afi
]
3967 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
],
3968 bgp_attr_get_ecommunity(attr
))) {
3969 if (bgp_debug_update(peer
, prefix
, NULL
, 1))
3971 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3974 /* Treat this route as imported, because it's leaked
3975 * already from another VRF, and we got an updated
3976 * version from route-reflector with ACCEPT_OWN
3979 *sub_type
= BGP_ROUTE_IMPORTED
;
3988 void bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
3989 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3990 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3991 uint32_t num_labels
, int soft_reconfig
,
3992 struct bgp_route_evpn
*evpn
)
3995 int aspath_loop_count
= 0;
3996 struct bgp_dest
*dest
;
3998 struct attr new_attr
;
3999 struct attr
*attr_new
;
4000 struct bgp_path_info
*pi
;
4001 struct bgp_path_info
*new = NULL
;
4002 struct bgp_path_info_extra
*extra
;
4004 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4006 int do_loop_check
= 1;
4007 int has_valid_label
= 0;
4009 bool force_evpn_import
= false;
4010 safi_t orig_safi
= safi
;
4011 bool leak_success
= true;
4014 if (frrtrace_enabled(frr_bgp
, process_update
)) {
4015 char pfxprint
[PREFIX2STR_BUFFER
];
4017 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
4018 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
4022 #ifdef ENABLE_BGP_VNC
4023 int vnc_implicit_withdraw
= 0;
4026 const struct prefix
*bgp_nht_param_prefix
;
4028 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4029 if (orig_safi
== SAFI_LABELED_UNICAST
)
4030 safi
= SAFI_UNICAST
;
4032 memset(&new_attr
, 0, sizeof(new_attr
));
4033 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
4034 new_attr
.label
= MPLS_INVALID_LABEL
;
4037 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4038 /* TODO: Check to see if we can get rid of "is_valid_label" */
4039 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
4040 has_valid_label
= (num_labels
> 0) ? 1 : 0;
4042 has_valid_label
= bgp_is_valid_label(label
);
4044 if (has_valid_label
)
4045 assert(label
!= NULL
);
4047 /* Update overlay index of the attribute */
4048 if (afi
== AFI_L2VPN
&& evpn
)
4049 memcpy(&attr
->evpn_overlay
, evpn
,
4050 sizeof(struct bgp_route_evpn
));
4052 /* When peer's soft reconfiguration enabled. Record input packet in
4055 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4056 && peer
!= bgp
->peer_self
)
4057 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
4059 /* Update permitted loop count */
4060 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN
))
4061 allowas_in
= peer
->allowas_in
[afi
][safi
];
4063 /* Check previously received route. */
4064 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4065 if (pi
->peer
== peer
&& pi
->type
== type
4066 && pi
->sub_type
== sub_type
4067 && pi
->addpath_rx_id
== addpath_id
)
4070 /* AS path local-as loop check. */
4071 if (peer
->change_local_as
) {
4073 aspath_loop_count
= allowas_in
;
4074 else if (!CHECK_FLAG(peer
->flags
,
4075 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
4076 aspath_loop_count
= 1;
4078 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
4079 > aspath_loop_count
) {
4080 peer
->stat_pfx_aspath_loop
++;
4081 reason
= "as-path contains our own AS;";
4086 /* If the peer is configured for "allowas-in origin" and the last ASN in
4088 * as-path is our ASN then we do not need to call aspath_loop_check
4090 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
4091 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
4094 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_REFLECTOR_CLIENT
))
4095 bgp_nht_param_prefix
= NULL
;
4097 bgp_nht_param_prefix
= p
;
4099 /* AS path loop check. */
4100 if (do_loop_check
) {
4101 if (aspath_loop_check(attr
->aspath
, bgp
->as
) >
4102 peer
->allowas_in
[afi
][safi
]) {
4103 peer
->stat_pfx_aspath_loop
++;
4104 reason
= "as-path contains our own AS;";
4109 /* If we're a CONFED we need to loop check the CONFED ID too */
4110 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
) && do_loop_check
)
4111 if (aspath_loop_check_confed(attr
->aspath
, bgp
->confed_id
) >
4112 peer
->allowas_in
[afi
][safi
]) {
4113 peer
->stat_pfx_aspath_loop
++;
4114 reason
= "as-path contains our own confed AS;";
4118 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4119 * enabled, then take care of that too.
4121 bool accept_own
= false;
4123 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
4124 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
4126 bgp_accept_own(peer
, afi
, safi
, attr
, p
, &sub_type
);
4128 peer
->stat_pfx_originator_loop
++;
4129 reason
= "originator is us;";
4134 /* Route reflector cluster ID check. */
4135 if (bgp_cluster_filter(peer
, attr
)) {
4136 peer
->stat_pfx_cluster_loop
++;
4137 reason
= "reflected from the same cluster;";
4141 /* Apply incoming filter. */
4142 if (bgp_input_filter(peer
, p
, attr
, afi
, orig_safi
) == FILTER_DENY
) {
4143 peer
->stat_pfx_filter
++;
4148 /* RFC 8212 to prevent route leaks.
4149 * This specification intends to improve this situation by requiring the
4150 * explicit configuration of both BGP Import and Export Policies for any
4151 * External BGP (EBGP) session such as customers, peers, or
4152 * confederation boundaries for all enabled address families. Through
4153 * codification of the aforementioned requirement, operators will
4154 * benefit from consistent behavior across different BGP
4157 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
4158 if (!bgp_inbound_policy_exists(peer
,
4159 &peer
->filter
[afi
][safi
])) {
4160 reason
= "inbound policy missing";
4161 if (monotime_since(&bgp
->ebgprequirespolicywarning
,
4162 NULL
) > FIFTEENMINUTE2USEC
||
4163 bgp
->ebgprequirespolicywarning
.tv_sec
== 0) {
4165 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4166 monotime(&bgp
->ebgprequirespolicywarning
);
4171 /* draft-ietf-idr-deprecate-as-set-confed-set
4172 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4173 * Eventually, This document (if approved) updates RFC 4271
4174 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4175 * and obsoletes RFC 6472.
4177 if (peer
->bgp
->reject_as_sets
)
4178 if (aspath_check_as_sets(attr
->aspath
)) {
4180 "as-path contains AS_SET or AS_CONFED_SET type;";
4186 /* Apply incoming route-map.
4187 * NB: new_attr may now contain newly allocated values from route-map
4189 * commands, so we need bgp_attr_flush in the error paths, until we
4191 * the attr (which takes over the memory references) */
4192 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, orig_safi
, NULL
, label
,
4195 peer
->stat_pfx_filter
++;
4196 reason
= "route-map;";
4197 bgp_attr_flush(&new_attr
);
4201 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
4202 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
4203 /* remove from RIB previous entry */
4204 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
4207 if (peer
->sort
== BGP_PEER_EBGP
) {
4210 * A BGP speaker receiving an announcement tagged with the
4211 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4212 * NO_EXPORT community as defined in RFC1997, or a
4213 * similar community, to prevent propagation of the
4214 * prefix outside the local AS. The community to prevent
4215 * propagation SHOULD be chosen according to the operator's
4218 if (bgp_attr_get_community(&new_attr
) &&
4219 community_include(bgp_attr_get_community(&new_attr
),
4220 COMMUNITY_BLACKHOLE
))
4221 bgp_attr_add_no_export_community(&new_attr
);
4223 /* If we receive the graceful-shutdown community from an eBGP
4224 * peer we must lower local-preference */
4225 if (bgp_attr_get_community(&new_attr
) &&
4226 community_include(bgp_attr_get_community(&new_attr
),
4228 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
4229 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
4231 /* If graceful-shutdown is configured globally or
4232 * per neighbor, then add the GSHUT community to
4233 * all paths received from eBGP peers. */
4234 } else if (bgp_in_graceful_shutdown(peer
->bgp
) ||
4235 CHECK_FLAG(peer
->flags
, PEER_FLAG_GRACEFUL_SHUTDOWN
))
4236 bgp_attr_add_gshut_community(&new_attr
);
4239 /* next hop check. */
4240 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
) &&
4241 bgp_update_martian_nexthop(bgp
, afi
, safi
, type
, sub_type
,
4243 peer
->stat_pfx_nh_invalid
++;
4244 reason
= "martian or self next-hop;";
4245 bgp_attr_flush(&new_attr
);
4249 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
4250 peer
->stat_pfx_nh_invalid
++;
4251 reason
= "self mac;";
4252 bgp_attr_flush(&new_attr
);
4256 if (bgp_check_role_applicability(afi
, safi
) &&
4257 bgp_otc_filter(peer
, &new_attr
)) {
4258 reason
= "failing otc validation";
4259 bgp_attr_flush(&new_attr
);
4263 /* If neighbor soo is configured, tag all incoming routes with
4264 * this SoO tag and then filter out advertisements in
4265 * subgroup_announce_check() if it matches the configured SoO
4266 * on the other peer.
4268 if (peer
->soo
[afi
][safi
]) {
4269 struct ecommunity
*old_ecomm
=
4270 bgp_attr_get_ecommunity(&new_attr
);
4271 struct ecommunity
*ecomm_soo
= peer
->soo
[afi
][safi
];
4272 struct ecommunity
*new_ecomm
;
4275 new_ecomm
= ecommunity_merge(ecommunity_dup(old_ecomm
),
4278 if (!old_ecomm
->refcnt
)
4279 ecommunity_free(&old_ecomm
);
4281 new_ecomm
= ecommunity_dup(ecomm_soo
);
4284 bgp_attr_set_ecommunity(&new_attr
, new_ecomm
);
4287 attr_new
= bgp_attr_intern(&new_attr
);
4289 /* If the update is implicit withdraw. */
4291 pi
->uptime
= monotime(NULL
);
4292 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
4294 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4296 /* Same attribute comes in. */
4297 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4299 && (!has_valid_label
4300 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
4301 num_labels
* sizeof(mpls_label_t
))
4303 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4304 BGP_CONFIG_DAMPENING
)
4305 && peer
->sort
== BGP_PEER_EBGP
4306 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4307 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4308 bgp_debug_rdpfxpath2str(
4309 afi
, safi
, prd
, p
, label
,
4310 num_labels
, addpath_id
? 1 : 0,
4311 addpath_id
, evpn
, pfx_buf
,
4313 zlog_debug("%pBP rcvd %s", peer
,
4317 if (bgp_damp_update(pi
, dest
, afi
, safi
)
4318 != BGP_DAMP_SUPPRESSED
) {
4319 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
4321 bgp_process(bgp
, dest
, afi
, safi
);
4323 } else /* Duplicate - odd */
4325 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4326 if (!peer
->rcvd_attr_printed
) {
4328 "%pBP rcvd UPDATE w/ attr: %s",
4330 peer
->rcvd_attr_str
);
4331 peer
->rcvd_attr_printed
= 1;
4334 bgp_debug_rdpfxpath2str(
4335 afi
, safi
, prd
, p
, label
,
4336 num_labels
, addpath_id
? 1 : 0,
4337 addpath_id
, evpn
, pfx_buf
,
4340 "%pBP rcvd %s...duplicate ignored",
4344 /* graceful restart STALE flag unset. */
4345 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4346 bgp_path_info_unset_flag(
4347 dest
, pi
, BGP_PATH_STALE
);
4348 bgp_dest_set_defer_flag(dest
, false);
4349 bgp_process(bgp
, dest
, afi
, safi
);
4353 bgp_dest_unlock_node(dest
);
4354 bgp_attr_unintern(&attr_new
);
4359 /* Withdraw/Announce before we fully processed the withdraw */
4360 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4361 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4362 bgp_debug_rdpfxpath2str(
4363 afi
, safi
, prd
, p
, label
, num_labels
,
4364 addpath_id
? 1 : 0, addpath_id
, evpn
,
4365 pfx_buf
, sizeof(pfx_buf
));
4367 "%pBP rcvd %s, flapped quicker than processing",
4371 bgp_path_info_restore(dest
, pi
);
4374 * If the BGP_PATH_REMOVED flag is set, then EVPN
4375 * routes would have been unimported already when a
4376 * prior BGP withdraw processing happened. Such routes
4377 * need to be imported again, so flag accordingly.
4379 force_evpn_import
= true;
4381 /* implicit withdraw, decrement aggregate and pcount
4382 * here. only if update is accepted, they'll increment
4385 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4388 /* Received Logging. */
4389 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4390 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
4391 num_labels
, addpath_id
? 1 : 0,
4392 addpath_id
, evpn
, pfx_buf
,
4394 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4397 /* graceful restart STALE flag unset. */
4398 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
4399 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
4400 bgp_dest_set_defer_flag(dest
, false);
4403 /* The attribute is changed. */
4404 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
4406 /* Update bgp route dampening information. */
4407 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4408 && peer
->sort
== BGP_PEER_EBGP
) {
4409 /* This is implicit withdraw so we should update
4412 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
4413 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
4415 #ifdef ENABLE_BGP_VNC
4416 if (safi
== SAFI_MPLS_VPN
) {
4417 struct bgp_dest
*pdest
= NULL
;
4418 struct bgp_table
*table
= NULL
;
4420 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4421 (struct prefix
*)prd
);
4422 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4423 table
= bgp_dest_get_bgp_table_info(pdest
);
4425 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
4426 bgp
, prd
, table
, p
, pi
);
4428 bgp_dest_unlock_node(pdest
);
4430 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4431 && (safi
== SAFI_UNICAST
)) {
4432 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4434 * Implicit withdraw case.
4436 ++vnc_implicit_withdraw
;
4437 vnc_import_bgp_del_route(bgp
, p
, pi
);
4438 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
4443 /* Special handling for EVPN update of an existing route. If the
4444 * extended community attribute has changed, we need to
4446 * the route using its existing extended community. It will be
4447 * subsequently processed for import with the new extended
4450 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
4453 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
4455 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4458 cmp
= ecommunity_cmp(
4459 bgp_attr_get_ecommunity(pi
->attr
),
4460 bgp_attr_get_ecommunity(attr_new
));
4462 if (bgp_debug_update(peer
, p
, NULL
, 1))
4464 "Change in EXT-COMM, existing %s new %s",
4466 bgp_attr_get_ecommunity(
4469 bgp_attr_get_ecommunity(
4471 if (safi
== SAFI_EVPN
)
4472 bgp_evpn_unimport_route(
4473 bgp
, afi
, safi
, p
, pi
);
4474 else /* SAFI_MPLS_VPN */
4475 vpn_leak_to_vrf_withdraw(pi
);
4480 /* Update to new attribute. */
4481 bgp_attr_unintern(&pi
->attr
);
4482 pi
->attr
= attr_new
;
4484 /* Update MPLS label */
4485 if (has_valid_label
) {
4486 extra
= bgp_path_info_extra_get(pi
);
4487 if (extra
->label
!= label
) {
4488 memcpy(&extra
->label
, label
,
4489 num_labels
* sizeof(mpls_label_t
));
4490 extra
->num_labels
= num_labels
;
4492 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4493 bgp_set_valid_label(&extra
->label
[0]);
4496 /* Update SRv6 SID */
4497 if (attr
->srv6_l3vpn
) {
4498 extra
= bgp_path_info_extra_get(pi
);
4499 if (sid_diff(&extra
->sid
[0].sid
,
4500 &attr
->srv6_l3vpn
->sid
)) {
4501 sid_copy(&extra
->sid
[0].sid
,
4502 &attr
->srv6_l3vpn
->sid
);
4503 extra
->num_sids
= 1;
4505 extra
->sid
[0].loc_block_len
= 0;
4506 extra
->sid
[0].loc_node_len
= 0;
4507 extra
->sid
[0].func_len
= 0;
4508 extra
->sid
[0].arg_len
= 0;
4509 extra
->sid
[0].transposition_len
= 0;
4510 extra
->sid
[0].transposition_offset
= 0;
4512 if (attr
->srv6_l3vpn
->loc_block_len
!= 0) {
4513 extra
->sid
[0].loc_block_len
=
4514 attr
->srv6_l3vpn
->loc_block_len
;
4515 extra
->sid
[0].loc_node_len
=
4516 attr
->srv6_l3vpn
->loc_node_len
;
4517 extra
->sid
[0].func_len
=
4518 attr
->srv6_l3vpn
->func_len
;
4519 extra
->sid
[0].arg_len
=
4520 attr
->srv6_l3vpn
->arg_len
;
4521 extra
->sid
[0].transposition_len
=
4523 ->transposition_len
;
4524 extra
->sid
[0].transposition_offset
=
4526 ->transposition_offset
;
4529 } else if (attr
->srv6_vpn
) {
4530 extra
= bgp_path_info_extra_get(pi
);
4531 if (sid_diff(&extra
->sid
[0].sid
,
4532 &attr
->srv6_vpn
->sid
)) {
4533 sid_copy(&extra
->sid
[0].sid
,
4534 &attr
->srv6_vpn
->sid
);
4535 extra
->num_sids
= 1;
4539 #ifdef ENABLE_BGP_VNC
4540 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4541 && (safi
== SAFI_UNICAST
)) {
4542 if (vnc_implicit_withdraw
) {
4544 * Add back the route with its new attributes
4546 * The route is still selected, until the route
4548 * queued by bgp_process actually runs. We have
4550 * update to the VNC side immediately to avoid
4552 * configuration changes (e.g., route-map
4554 * trigger re-importation of the entire RIB.
4556 vnc_import_bgp_add_route(bgp
, p
, pi
);
4557 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4562 /* Update bgp route dampening information. */
4563 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
4564 && peer
->sort
== BGP_PEER_EBGP
) {
4565 /* Now we do normal update dampening. */
4566 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4567 if (ret
== BGP_DAMP_SUPPRESSED
) {
4568 bgp_dest_unlock_node(dest
);
4573 /* Nexthop reachability check - for unicast and
4574 * labeled-unicast.. */
4575 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4576 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4577 || (safi
== SAFI_EVPN
&&
4578 bgp_evpn_is_prefix_nht_supported(p
))) {
4579 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4580 && peer
->ttl
== BGP_DEFAULT_TTL
4581 && !CHECK_FLAG(peer
->flags
,
4582 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4583 && !CHECK_FLAG(bgp
->flags
,
4584 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4589 struct bgp
*bgp_nexthop
= bgp
;
4591 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4592 bgp_nexthop
= pi
->extra
->bgp_orig
;
4594 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4596 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4597 safi
, pi
, NULL
, connected
,
4598 bgp_nht_param_prefix
) ||
4599 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4600 bgp_path_info_set_flag(dest
, pi
,
4603 if (BGP_DEBUG(nht
, NHT
)) {
4604 zlog_debug("%s(%pI4): NH unresolved",
4606 (in_addr_t
*)&attr_new
->nexthop
);
4608 bgp_path_info_unset_flag(dest
, pi
,
4613 bgp_path_info_set_flag(dest
, pi
,
4614 BGP_PATH_ACCEPT_OWN
);
4616 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4619 #ifdef ENABLE_BGP_VNC
4620 if (safi
== SAFI_MPLS_VPN
) {
4621 struct bgp_dest
*pdest
= NULL
;
4622 struct bgp_table
*table
= NULL
;
4624 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4625 (struct prefix
*)prd
);
4626 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4627 table
= bgp_dest_get_bgp_table_info(pdest
);
4629 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4630 bgp
, prd
, table
, p
, pi
);
4632 bgp_dest_unlock_node(pdest
);
4636 /* If this is an EVPN route and some attribute has changed,
4637 * or we are explicitly told to perform a route import, process
4638 * route for import. If the extended community has changed, we
4640 * have done the un-import earlier and the import would result
4642 * route getting injected into appropriate L2 VNIs. If it is
4644 * some other attribute change, the import will result in
4646 * the attributes for the route in the VNI(s).
4648 if (safi
== SAFI_EVPN
&&
4649 (!same_attr
|| force_evpn_import
) &&
4650 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4651 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4653 /* Process change. */
4654 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4656 bgp_process(bgp
, dest
, afi
, safi
);
4657 bgp_dest_unlock_node(dest
);
4659 if (SAFI_UNICAST
== safi
4660 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4661 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4663 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4665 if ((SAFI_MPLS_VPN
== safi
)
4666 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4667 leak_success
= vpn_leak_to_vrf_update(bgp
, pi
, prd
);
4670 #ifdef ENABLE_BGP_VNC
4671 if (SAFI_MPLS_VPN
== safi
) {
4672 mpls_label_t label_decoded
= decode_label(label
);
4674 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4675 type
, sub_type
, &label_decoded
);
4677 if (SAFI_ENCAP
== safi
) {
4678 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4679 type
, sub_type
, NULL
);
4682 if ((safi
== SAFI_MPLS_VPN
) &&
4683 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4684 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4686 bgp_unlink_nexthop(pi
);
4687 bgp_path_info_delete(dest
, pi
);
4690 } // End of implicit withdraw
4692 /* Received Logging. */
4693 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4694 if (!peer
->rcvd_attr_printed
) {
4695 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4696 peer
->rcvd_attr_str
);
4697 peer
->rcvd_attr_printed
= 1;
4700 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4701 addpath_id
? 1 : 0, addpath_id
, evpn
,
4702 pfx_buf
, sizeof(pfx_buf
));
4703 zlog_debug("%pBP rcvd %s", peer
, pfx_buf
);
4706 /* Make new BGP info. */
4707 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4709 /* Update MPLS label */
4710 if (has_valid_label
) {
4711 extra
= bgp_path_info_extra_get(new);
4712 if (extra
->label
!= label
) {
4713 memcpy(&extra
->label
, label
,
4714 num_labels
* sizeof(mpls_label_t
));
4715 extra
->num_labels
= num_labels
;
4717 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4718 bgp_set_valid_label(&extra
->label
[0]);
4721 /* Update SRv6 SID */
4722 if (safi
== SAFI_MPLS_VPN
) {
4723 extra
= bgp_path_info_extra_get(new);
4724 if (attr
->srv6_l3vpn
) {
4725 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_l3vpn
->sid
);
4726 extra
->num_sids
= 1;
4728 extra
->sid
[0].loc_block_len
=
4729 attr
->srv6_l3vpn
->loc_block_len
;
4730 extra
->sid
[0].loc_node_len
=
4731 attr
->srv6_l3vpn
->loc_node_len
;
4732 extra
->sid
[0].func_len
= attr
->srv6_l3vpn
->func_len
;
4733 extra
->sid
[0].arg_len
= attr
->srv6_l3vpn
->arg_len
;
4734 extra
->sid
[0].transposition_len
=
4735 attr
->srv6_l3vpn
->transposition_len
;
4736 extra
->sid
[0].transposition_offset
=
4737 attr
->srv6_l3vpn
->transposition_offset
;
4738 } else if (attr
->srv6_vpn
) {
4739 sid_copy(&extra
->sid
[0].sid
, &attr
->srv6_vpn
->sid
);
4740 extra
->num_sids
= 1;
4744 /* Nexthop reachability check. */
4745 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4746 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4747 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4748 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4749 && peer
->ttl
== BGP_DEFAULT_TTL
4750 && !CHECK_FLAG(peer
->flags
,
4751 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4752 && !CHECK_FLAG(bgp
->flags
,
4753 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4758 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4760 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4761 connected
, bgp_nht_param_prefix
) ||
4762 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4763 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4765 if (BGP_DEBUG(nht
, NHT
))
4766 zlog_debug("%s(%pI4): NH unresolved", __func__
,
4767 &attr_new
->nexthop
);
4768 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4772 bgp_path_info_set_flag(dest
, new, BGP_PATH_ACCEPT_OWN
);
4774 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4777 /* If maximum prefix count is configured and current prefix
4780 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0)) {
4781 reason
= "maximum-prefix overflow";
4782 bgp_attr_flush(&new_attr
);
4787 new->addpath_rx_id
= addpath_id
;
4789 /* Increment prefix */
4790 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4792 /* Register new BGP information. */
4793 bgp_path_info_add(dest
, new);
4795 /* route_node_get lock */
4796 bgp_dest_unlock_node(dest
);
4798 #ifdef ENABLE_BGP_VNC
4799 if (safi
== SAFI_MPLS_VPN
) {
4800 struct bgp_dest
*pdest
= NULL
;
4801 struct bgp_table
*table
= NULL
;
4803 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4804 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4805 table
= bgp_dest_get_bgp_table_info(pdest
);
4807 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4808 bgp
, prd
, table
, p
, new);
4810 bgp_dest_unlock_node(pdest
);
4814 /* If this is an EVPN route, process for import. */
4815 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4816 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4818 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4820 /* Process change. */
4821 bgp_process(bgp
, dest
, afi
, safi
);
4823 if (SAFI_UNICAST
== safi
4824 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4825 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4826 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4828 if ((SAFI_MPLS_VPN
== safi
)
4829 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4830 leak_success
= vpn_leak_to_vrf_update(bgp
, new, prd
);
4832 #ifdef ENABLE_BGP_VNC
4833 if (SAFI_MPLS_VPN
== safi
) {
4834 mpls_label_t label_decoded
= decode_label(label
);
4836 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4837 sub_type
, &label_decoded
);
4839 if (SAFI_ENCAP
== safi
) {
4840 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4844 if ((safi
== SAFI_MPLS_VPN
) &&
4845 !CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
4846 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
) &&
4848 bgp_unlink_nexthop(new);
4849 bgp_path_info_delete(dest
, new);
4854 /* This BGP update is filtered. Log the reason then update BGP
4858 bgp_unlink_nexthop(new);
4859 bgp_path_info_delete(dest
, new);
4860 bgp_path_info_extra_free(&new->extra
);
4861 XFREE(MTYPE_BGP_ROUTE
, new);
4864 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4866 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4867 if (!peer
->rcvd_attr_printed
) {
4868 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer
,
4869 peer
->rcvd_attr_str
);
4870 peer
->rcvd_attr_printed
= 1;
4873 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4874 addpath_id
? 1 : 0, addpath_id
, evpn
,
4875 pfx_buf
, sizeof(pfx_buf
));
4876 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4877 peer
, pfx_buf
, reason
);
4881 /* If this is an EVPN route, un-import it as it is now filtered.
4883 if (safi
== SAFI_EVPN
)
4884 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4886 if (SAFI_UNICAST
== safi
4887 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4888 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4890 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4892 if ((SAFI_MPLS_VPN
== safi
)
4893 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4895 vpn_leak_to_vrf_withdraw(pi
);
4898 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4901 bgp_dest_unlock_node(dest
);
4903 #ifdef ENABLE_BGP_VNC
4905 * Filtered update is treated as an implicit withdrawal (see
4907 * a few lines above)
4909 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4910 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4918 void bgp_withdraw(struct peer
*peer
, const struct prefix
*p
,
4919 uint32_t addpath_id
, afi_t afi
, safi_t safi
, int type
,
4920 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4921 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4924 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4925 struct bgp_dest
*dest
;
4926 struct bgp_path_info
*pi
;
4928 #ifdef ENABLE_BGP_VNC
4929 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4930 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4938 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4940 /* If peer is soft reconfiguration enabled. Record input packet for
4941 * further calculation.
4943 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4944 * routes that are filtered. This tanks out Quagga RS pretty badly due
4946 * the iteration over all RS clients.
4947 * Since we need to remove the entry from adj_in anyway, do that first
4949 * if there was no entry, we don't need to do anything more.
4951 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4952 && peer
!= bgp
->peer_self
)
4953 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4954 peer
->stat_pfx_dup_withdraw
++;
4956 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4957 bgp_debug_rdpfxpath2str(
4958 afi
, safi
, prd
, p
, label
, num_labels
,
4959 addpath_id
? 1 : 0, addpath_id
, NULL
,
4960 pfx_buf
, sizeof(pfx_buf
));
4962 "%s withdrawing route %s not in adj-in",
4963 peer
->host
, pfx_buf
);
4965 bgp_dest_unlock_node(dest
);
4969 /* Lookup withdrawn route. */
4970 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4971 if (pi
->peer
== peer
&& pi
->type
== type
4972 && pi
->sub_type
== sub_type
4973 && pi
->addpath_rx_id
== addpath_id
)
4977 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4978 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4979 addpath_id
? 1 : 0, addpath_id
, NULL
,
4980 pfx_buf
, sizeof(pfx_buf
));
4981 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer
,
4985 /* Withdraw specified route from routing table. */
4986 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4987 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4988 if (SAFI_UNICAST
== safi
4989 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4990 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4991 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4993 if ((SAFI_MPLS_VPN
== safi
)
4994 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4996 vpn_leak_to_vrf_withdraw(pi
);
4998 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4999 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
5000 addpath_id
? 1 : 0, addpath_id
, NULL
,
5001 pfx_buf
, sizeof(pfx_buf
));
5002 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
5005 /* Unlock bgp_node_get() lock. */
5006 bgp_dest_unlock_node(dest
);
5011 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
5014 struct update_subgroup
*subgrp
;
5015 subgrp
= peer_subgroup(peer
, afi
, safi
);
5016 subgroup_default_originate(subgrp
, withdraw
);
5021 * bgp_stop_announce_route_timer
5023 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
5025 if (!paf
->t_announce_route
)
5028 EVENT_OFF(paf
->t_announce_route
);
5032 * bgp_announce_route_timer_expired
5034 * Callback that is invoked when the route announcement timer for a
5037 static void bgp_announce_route_timer_expired(struct event
*t
)
5039 struct peer_af
*paf
;
5045 if (!peer_established(peer
))
5048 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
5051 peer_af_announce_route(paf
, 1);
5053 /* Notify BGP conditional advertisement scanner percess */
5054 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
5058 * bgp_announce_route
5060 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
5062 * if force is true we will force an update even if the update
5063 * limiting code is attempted to kick in.
5065 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
, bool force
)
5067 struct peer_af
*paf
;
5068 struct update_subgroup
*subgrp
;
5070 paf
= peer_af_find(peer
, afi
, safi
);
5073 subgrp
= PAF_SUBGRP(paf
);
5076 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5077 * or a refresh has already been triggered.
5079 if (!subgrp
|| paf
->t_announce_route
)
5083 SET_FLAG(subgrp
->sflags
, SUBGRP_STATUS_FORCE_UPDATES
);
5086 * Start a timer to stagger/delay the announce. This serves
5087 * two purposes - announcement can potentially be combined for
5088 * multiple peers and the announcement doesn't happen in the
5091 event_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
5092 (subgrp
->peer_count
== 1)
5093 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5094 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
5095 &paf
->t_announce_route
);
5099 * Announce routes from all AF tables to a peer.
5101 * This should ONLY be called when there is a need to refresh the
5102 * routes to the peer based on a policy change for this peer alone
5103 * or a route refresh request received from the peer.
5104 * The operation will result in splitting the peer from its existing
5105 * subgroups and putting it in new subgroups.
5107 void bgp_announce_route_all(struct peer
*peer
)
5112 FOREACH_AFI_SAFI (afi
, safi
)
5113 bgp_announce_route(peer
, afi
, safi
, false);
5116 /* Flag or unflag bgp_dest to determine whether it should be treated by
5117 * bgp_soft_reconfig_table_task.
5118 * Flag if flag is true. Unflag if flag is false.
5120 static void bgp_soft_reconfig_table_flag(struct bgp_table
*table
, bool flag
)
5122 struct bgp_dest
*dest
;
5123 struct bgp_adj_in
*ain
;
5128 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5129 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5130 if (ain
->peer
!= NULL
)
5133 if (flag
&& ain
!= NULL
&& ain
->peer
!= NULL
)
5134 SET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5136 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5140 static void bgp_soft_reconfig_table_update(struct peer
*peer
,
5141 struct bgp_dest
*dest
,
5142 struct bgp_adj_in
*ain
, afi_t afi
,
5143 safi_t safi
, struct prefix_rd
*prd
)
5145 struct bgp_path_info
*pi
;
5146 uint32_t num_labels
= 0;
5147 mpls_label_t
*label_pnt
= NULL
;
5148 struct bgp_route_evpn evpn
;
5150 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5151 if (pi
->peer
== peer
)
5154 if (pi
&& pi
->extra
)
5155 num_labels
= pi
->extra
->num_labels
;
5157 label_pnt
= &pi
->extra
->label
[0];
5159 memcpy(&evpn
, bgp_attr_get_evpn_overlay(pi
->attr
),
5162 memset(&evpn
, 0, sizeof(evpn
));
5164 bgp_update(peer
, bgp_dest_get_prefix(dest
), ain
->addpath_rx_id
,
5165 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, prd
,
5166 label_pnt
, num_labels
, 1, &evpn
);
5169 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5170 struct bgp_table
*table
,
5171 struct prefix_rd
*prd
)
5173 struct bgp_dest
*dest
;
5174 struct bgp_adj_in
*ain
;
5177 table
= peer
->bgp
->rib
[afi
][safi
];
5179 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5180 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5181 if (ain
->peer
!= peer
)
5184 bgp_soft_reconfig_table_update(peer
, dest
, ain
, afi
,
5189 /* Do soft reconfig table per bgp table.
5190 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5191 * when BGP_NODE_SOFT_RECONFIG is set,
5192 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5193 * Schedule a new thread to continue the job.
5194 * Without splitting the full job into several part,
5195 * vtysh waits for the job to finish before responding to a BGP command
5197 static void bgp_soft_reconfig_table_task(struct event
*thread
)
5199 uint32_t iter
, max_iter
;
5200 struct bgp_dest
*dest
;
5201 struct bgp_adj_in
*ain
;
5203 struct bgp_table
*table
;
5204 struct prefix_rd
*prd
;
5205 struct listnode
*node
, *nnode
;
5207 table
= EVENT_ARG(thread
);
5210 max_iter
= SOFT_RECONFIG_TASK_MAX_PREFIX
;
5211 if (table
->soft_reconfig_init
) {
5212 /* first call of the function with a new srta structure.
5213 * Don't do any treatment this time on nodes
5214 * in order vtysh to respond quickly
5219 for (iter
= 0, dest
= bgp_table_top(table
); (dest
&& iter
< max_iter
);
5220 dest
= bgp_route_next(dest
)) {
5221 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
))
5224 UNSET_FLAG(dest
->flags
, BGP_NODE_SOFT_RECONFIG
);
5226 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
5227 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
,
5229 if (ain
->peer
!= peer
)
5232 bgp_soft_reconfig_table_update(
5233 peer
, dest
, ain
, table
->afi
,
5240 /* we're either starting the initial iteration,
5241 * or we're going to continue an ongoing iteration
5243 if (dest
|| table
->soft_reconfig_init
) {
5244 table
->soft_reconfig_init
= false;
5245 event_add_event(bm
->master
, bgp_soft_reconfig_table_task
, table
,
5246 0, &table
->soft_reconfig_thread
);
5249 /* we're done, clean up the background iteration context info and
5250 schedule route annoucement
5252 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
, peer
)) {
5253 listnode_delete(table
->soft_reconfig_peers
, peer
);
5254 bgp_announce_route(peer
, table
->afi
, table
->safi
, false);
5257 list_delete(&table
->soft_reconfig_peers
);
5261 /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5263 * - bgp cannot be NULL
5264 * - if table and peer are NULL, cancel all threads within the bgp instance
5265 * - if table is NULL and peer is not,
5266 * remove peer in all threads within the bgp instance
5267 * - if peer is NULL, cancel all threads matching table within the bgp instance
5269 void bgp_soft_reconfig_table_task_cancel(const struct bgp
*bgp
,
5270 const struct bgp_table
*table
,
5271 const struct peer
*peer
)
5274 struct listnode
*node
, *nnode
;
5276 struct bgp_table
*ntable
;
5281 FOREACH_AFI_SAFI (afi
, safi
) {
5282 ntable
= bgp
->rib
[afi
][safi
];
5285 if (table
&& table
!= ntable
)
5288 for (ALL_LIST_ELEMENTS(ntable
->soft_reconfig_peers
, node
, nnode
,
5290 if (peer
&& peer
!= npeer
)
5292 listnode_delete(ntable
->soft_reconfig_peers
, npeer
);
5295 if (!ntable
->soft_reconfig_peers
5296 || !list_isempty(ntable
->soft_reconfig_peers
))
5299 list_delete(&ntable
->soft_reconfig_peers
);
5300 bgp_soft_reconfig_table_flag(ntable
, false);
5301 EVENT_OFF(ntable
->soft_reconfig_thread
);
5306 * Returns false if the peer is not configured for soft reconfig in
5308 bool bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5310 struct bgp_dest
*dest
;
5311 struct bgp_table
*table
;
5312 struct listnode
*node
, *nnode
;
5314 struct peer_af
*paf
;
5316 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
))
5319 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
5320 && (safi
!= SAFI_EVPN
)) {
5321 table
= peer
->bgp
->rib
[afi
][safi
];
5325 table
->soft_reconfig_init
= true;
5327 if (!table
->soft_reconfig_peers
)
5328 table
->soft_reconfig_peers
= list_new();
5330 /* add peer to the table soft_reconfig_peers if not already
5333 for (ALL_LIST_ELEMENTS(table
->soft_reconfig_peers
, node
, nnode
,
5339 listnode_add(table
->soft_reconfig_peers
, peer
);
5341 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5342 * on table would start back at the beginning.
5344 bgp_soft_reconfig_table_flag(table
, true);
5346 if (!table
->soft_reconfig_thread
)
5347 event_add_event(bm
->master
,
5348 bgp_soft_reconfig_table_task
, table
, 0,
5349 &table
->soft_reconfig_thread
);
5350 /* Cancel bgp_announce_route_timer_expired threads.
5351 * bgp_announce_route_timer_expired threads have been scheduled
5352 * to announce routes as soon as the soft_reconfigure process
5354 * In this case, soft_reconfigure is also scheduled by using
5355 * a thread but is planned after the
5356 * bgp_announce_route_timer_expired threads. It means that,
5357 * without cancelling the threads, the route announcement task
5358 * would run before the soft reconfiguration one. That would
5359 * useless and would block vtysh during several seconds. Route
5360 * announcements are rescheduled as soon as the soft_reconfigure
5363 paf
= peer_af_find(peer
, afi
, safi
);
5365 bgp_stop_announce_route_timer(paf
);
5367 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5368 dest
= bgp_route_next(dest
)) {
5369 table
= bgp_dest_get_bgp_table_info(dest
);
5374 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5375 struct prefix_rd prd
;
5377 prd
.family
= AF_UNSPEC
;
5379 memcpy(&prd
.val
, p
->u
.val
, 8);
5381 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
5388 struct bgp_clear_node_queue
{
5389 struct bgp_dest
*dest
;
5392 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
5394 struct bgp_clear_node_queue
*cnq
= data
;
5395 struct bgp_dest
*dest
= cnq
->dest
;
5396 struct peer
*peer
= wq
->spec
.data
;
5397 struct bgp_path_info
*pi
;
5399 afi_t afi
= bgp_dest_table(dest
)->afi
;
5400 safi_t safi
= bgp_dest_table(dest
)->safi
;
5402 assert(dest
&& peer
);
5405 /* It is possible that we have multiple paths for a prefix from a peer
5406 * if that peer is using AddPath.
5408 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5409 if (pi
->peer
!= peer
)
5412 /* graceful restart STALE flag set. */
5413 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
5414 && peer
->nsf
[afi
][safi
])
5415 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5416 PEER_STATUS_ENHANCED_REFRESH
))
5417 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5418 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
5419 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
5421 /* If this is an EVPN route, process for
5423 if (safi
== SAFI_EVPN
)
5424 bgp_evpn_unimport_route(
5426 bgp_dest_get_prefix(dest
), pi
);
5427 /* Handle withdraw for VRF route-leaking and L3VPN */
5428 if (SAFI_UNICAST
== safi
5429 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
5430 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5431 vpn_leak_from_vrf_withdraw(bgp_get_default(),
5434 if (SAFI_MPLS_VPN
== safi
&&
5435 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5436 vpn_leak_to_vrf_withdraw(pi
);
5439 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5445 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
5447 struct bgp_clear_node_queue
*cnq
= data
;
5448 struct bgp_dest
*dest
= cnq
->dest
;
5449 struct bgp_table
*table
= bgp_dest_table(dest
);
5451 bgp_dest_unlock_node(dest
);
5452 bgp_table_unlock(table
);
5453 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
5456 static void bgp_clear_node_complete(struct work_queue
*wq
)
5458 struct peer
*peer
= wq
->spec
.data
;
5460 /* Tickle FSM to start moving again */
5461 BGP_EVENT_ADD(peer
, Clearing_Completed
);
5463 peer_unlock(peer
); /* bgp_clear_route */
5466 static void bgp_clear_node_queue_init(struct peer
*peer
)
5468 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5470 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
5471 #undef CLEAR_QUEUE_NAME_LEN
5473 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
5474 peer
->clear_node_queue
->spec
.hold
= 10;
5475 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
5476 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
5477 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
5478 peer
->clear_node_queue
->spec
.max_retries
= 0;
5480 /* we only 'lock' this peer reference when the queue is actually active
5482 peer
->clear_node_queue
->spec
.data
= peer
;
5485 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
5486 struct bgp_table
*table
)
5488 struct bgp_dest
*dest
;
5489 int force
= peer
->bgp
->process_queue
? 0 : 1;
5492 table
= peer
->bgp
->rib
[afi
][safi
];
5494 /* If still no table => afi/safi isn't configured at all or smth. */
5498 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5499 struct bgp_path_info
*pi
, *next
;
5500 struct bgp_adj_in
*ain
;
5501 struct bgp_adj_in
*ain_next
;
5503 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5504 * queued for every clearing peer, regardless of whether it is
5505 * relevant to the peer at hand.
5507 * Overview: There are 3 different indices which need to be
5508 * scrubbed, potentially, when a peer is removed:
5510 * 1 peer's routes visible via the RIB (ie accepted routes)
5511 * 2 peer's routes visible by the (optional) peer's adj-in index
5512 * 3 other routes visible by the peer's adj-out index
5514 * 3 there is no hurry in scrubbing, once the struct peer is
5515 * removed from bgp->peer, we could just GC such deleted peer's
5516 * adj-outs at our leisure.
5518 * 1 and 2 must be 'scrubbed' in some way, at least made
5519 * invisible via RIB index before peer session is allowed to be
5520 * brought back up. So one needs to know when such a 'search' is
5525 * - there'd be a single global queue or a single RIB walker
5526 * - rather than tracking which route_nodes still need to be
5527 * examined on a peer basis, we'd track which peers still
5530 * Given that our per-peer prefix-counts now should be reliable,
5531 * this may actually be achievable. It doesn't seem to be a huge
5532 * problem at this time,
5534 * It is possible that we have multiple paths for a prefix from
5536 * if that peer is using AddPath.
5540 ain_next
= ain
->next
;
5542 if (ain
->peer
== peer
)
5543 bgp_adj_in_remove(dest
, ain
);
5548 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5550 if (pi
->peer
!= peer
)
5554 bgp_path_info_reap(dest
, pi
);
5556 struct bgp_clear_node_queue
*cnq
;
5558 /* both unlocked in bgp_clear_node_queue_del */
5559 bgp_table_lock(bgp_dest_table(dest
));
5560 bgp_dest_lock_node(dest
);
5562 MTYPE_BGP_CLEAR_NODE_QUEUE
,
5563 sizeof(struct bgp_clear_node_queue
));
5565 work_queue_add(peer
->clear_node_queue
, cnq
);
5573 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5575 struct bgp_dest
*dest
;
5576 struct bgp_table
*table
;
5578 if (peer
->clear_node_queue
== NULL
)
5579 bgp_clear_node_queue_init(peer
);
5581 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5582 * Idle until it receives a Clearing_Completed event. This protects
5583 * against peers which flap faster than we can we clear, which could
5586 * a) race with routes from the new session being installed before
5587 * clear_route_node visits the node (to delete the route of that
5589 * b) resource exhaustion, clear_route_node likely leads to an entry
5590 * on the process_main queue. Fast-flapping could cause that queue
5594 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5595 * the unlock will happen upon work-queue completion; other wise, the
5596 * unlock happens at the end of this function.
5598 if (!peer
->clear_node_queue
->thread
)
5601 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
5602 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
5604 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5605 dest
= bgp_route_next(dest
)) {
5606 table
= bgp_dest_get_bgp_table_info(dest
);
5610 bgp_clear_route_table(peer
, afi
, safi
, table
);
5613 /* unlock if no nodes got added to the clear-node-queue. */
5614 if (!peer
->clear_node_queue
->thread
)
5618 void bgp_clear_route_all(struct peer
*peer
)
5623 FOREACH_AFI_SAFI (afi
, safi
)
5624 bgp_clear_route(peer
, afi
, safi
);
5626 #ifdef ENABLE_BGP_VNC
5627 rfapiProcessPeerDown(peer
);
5631 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
5633 struct bgp_table
*table
;
5634 struct bgp_dest
*dest
;
5635 struct bgp_adj_in
*ain
;
5636 struct bgp_adj_in
*ain_next
;
5638 table
= peer
->bgp
->rib
[afi
][safi
];
5640 /* It is possible that we have multiple paths for a prefix from a peer
5641 * if that peer is using AddPath.
5643 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5647 ain_next
= ain
->next
;
5649 if (ain
->peer
== peer
)
5650 bgp_adj_in_remove(dest
, ain
);
5657 /* If any of the routes from the peer have been marked with the NO_LLGR
5658 * community, either as sent by the peer, or as the result of a configured
5659 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5660 * operation of [RFC4271].
5662 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5664 struct bgp_dest
*dest
;
5665 struct bgp_path_info
*pi
;
5666 struct bgp_table
*table
;
5668 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5669 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5670 dest
= bgp_route_next(dest
)) {
5671 struct bgp_dest
*rm
;
5673 /* look for neighbor in tables */
5674 table
= bgp_dest_get_bgp_table_info(dest
);
5678 for (rm
= bgp_table_top(table
); rm
;
5679 rm
= bgp_route_next(rm
))
5680 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
5682 if (pi
->peer
!= peer
)
5685 peer
->af_sflags
[afi
][safi
],
5686 PEER_STATUS_LLGR_WAIT
) &&
5687 bgp_attr_get_community(pi
->attr
) &&
5689 bgp_attr_get_community(
5693 if (!CHECK_FLAG(pi
->flags
,
5698 * If this is VRF leaked route
5699 * process for withdraw.
5702 BGP_ROUTE_IMPORTED
&&
5703 peer
->bgp
->inst_type
==
5704 BGP_INSTANCE_TYPE_DEFAULT
)
5705 vpn_leak_to_vrf_withdraw(pi
);
5707 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
5712 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5713 dest
= bgp_route_next(dest
))
5714 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5716 if (pi
->peer
!= peer
)
5718 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5719 PEER_STATUS_LLGR_WAIT
) &&
5720 bgp_attr_get_community(pi
->attr
) &&
5722 bgp_attr_get_community(pi
->attr
),
5725 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
5727 if (safi
== SAFI_UNICAST
&&
5728 (peer
->bgp
->inst_type
==
5729 BGP_INSTANCE_TYPE_VRF
||
5730 peer
->bgp
->inst_type
==
5731 BGP_INSTANCE_TYPE_DEFAULT
))
5732 vpn_leak_from_vrf_withdraw(
5733 bgp_get_default(), peer
->bgp
,
5736 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
5742 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
5744 struct bgp_dest
*dest
, *ndest
;
5745 struct bgp_path_info
*pi
;
5746 struct bgp_table
*table
;
5748 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
5749 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5750 dest
= bgp_route_next(dest
)) {
5751 table
= bgp_dest_get_bgp_table_info(dest
);
5755 for (ndest
= bgp_table_top(table
); ndest
;
5756 ndest
= bgp_route_next(ndest
)) {
5757 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
5759 if (pi
->peer
!= peer
)
5763 peer
->af_sflags
[afi
][safi
],
5764 PEER_STATUS_ENHANCED_REFRESH
))
5765 && !CHECK_FLAG(pi
->flags
,
5769 BGP_PATH_UNUSEABLE
)) {
5770 if (bgp_debug_neighbor_events(
5773 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5777 bgp_dest_get_prefix(
5780 bgp_path_info_set_flag(
5788 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5789 dest
= bgp_route_next(dest
)) {
5790 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5792 if (pi
->peer
!= peer
)
5795 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5796 PEER_STATUS_ENHANCED_REFRESH
))
5797 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5798 && !CHECK_FLAG(pi
->flags
,
5799 BGP_PATH_UNUSEABLE
)) {
5800 if (bgp_debug_neighbor_events(peer
))
5802 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5805 bgp_dest_get_prefix(
5808 bgp_path_info_set_flag(dest
, pi
,
5816 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5818 if (peer
->sort
== BGP_PEER_IBGP
)
5821 if (peer
->sort
== BGP_PEER_EBGP
5822 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5823 || FILTER_LIST_OUT_NAME(filter
)
5824 || DISTRIBUTE_OUT_NAME(filter
)))
5829 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5831 if (peer
->sort
== BGP_PEER_IBGP
)
5834 if (peer
->sort
== BGP_PEER_EBGP
5835 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5836 || FILTER_LIST_IN_NAME(filter
)
5837 || DISTRIBUTE_IN_NAME(filter
)))
5842 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5845 struct bgp_dest
*dest
;
5846 struct bgp_path_info
*pi
;
5847 struct bgp_path_info
*next
;
5849 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5850 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5851 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5855 /* Unimport EVPN routes from VRFs */
5856 if (safi
== SAFI_EVPN
)
5857 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5860 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5861 && pi
->type
== ZEBRA_ROUTE_BGP
5862 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5863 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5864 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5866 if (bgp_fibupd_safi(safi
))
5867 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5870 bgp_path_info_reap(dest
, pi
);
5874 /* Delete all kernel routes. */
5875 void bgp_cleanup_routes(struct bgp
*bgp
)
5878 struct bgp_dest
*dest
;
5879 struct bgp_table
*table
;
5881 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5882 if (afi
== AFI_L2VPN
)
5884 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5887 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5889 if (afi
!= AFI_L2VPN
) {
5891 safi
= SAFI_MPLS_VPN
;
5892 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5893 dest
= bgp_route_next(dest
)) {
5894 table
= bgp_dest_get_bgp_table_info(dest
);
5895 if (table
!= NULL
) {
5896 bgp_cleanup_table(bgp
, table
, safi
);
5897 bgp_table_finish(&table
);
5898 bgp_dest_set_bgp_table_info(dest
, NULL
);
5899 bgp_dest_unlock_node(dest
);
5903 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5904 dest
= bgp_route_next(dest
)) {
5905 table
= bgp_dest_get_bgp_table_info(dest
);
5906 if (table
!= NULL
) {
5907 bgp_cleanup_table(bgp
, table
, safi
);
5908 bgp_table_finish(&table
);
5909 bgp_dest_set_bgp_table_info(dest
, NULL
);
5910 bgp_dest_unlock_node(dest
);
5915 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5916 dest
= bgp_route_next(dest
)) {
5917 table
= bgp_dest_get_bgp_table_info(dest
);
5918 if (table
!= NULL
) {
5919 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5920 bgp_table_finish(&table
);
5921 bgp_dest_set_bgp_table_info(dest
, NULL
);
5922 bgp_dest_unlock_node(dest
);
5927 void bgp_reset(void)
5930 bgp_zclient_reset();
5931 access_list_reset();
5932 prefix_list_reset();
5935 bool bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5937 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5938 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5939 PEER_CAP_ADDPATH_AF_TX_RCV
));
5942 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5944 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5945 struct bgp_nlri
*packet
)
5953 bool addpath_capable
;
5954 uint32_t addpath_id
;
5957 lim
= pnt
+ packet
->length
;
5959 safi
= packet
->safi
;
5961 addpath_capable
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5963 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5964 syntactic validity. If the field is syntactically incorrect,
5965 then the Error Subcode is set to Invalid Network Field. */
5966 for (; pnt
< lim
; pnt
+= psize
) {
5967 /* Clear prefix structure. */
5968 memset(&p
, 0, sizeof(p
));
5970 if (addpath_capable
) {
5972 /* When packet overflow occurs return immediately. */
5973 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5974 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5976 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5977 addpath_id
= ntohl(addpath_id
);
5978 pnt
+= BGP_ADDPATH_ID_LEN
;
5981 /* Fetch prefix length. */
5982 p
.prefixlen
= *pnt
++;
5983 /* afi/safi validity already verified by caller,
5984 * bgp_update_receive */
5985 p
.family
= afi2family(afi
);
5987 /* Prefix length check. */
5988 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
5991 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5992 peer
->host
, p
.prefixlen
, packet
->afi
);
5993 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
5996 /* Packet size overflow check. */
5997 psize
= PSIZE(p
.prefixlen
);
5999 /* When packet overflow occur return immediately. */
6000 if (pnt
+ psize
> lim
) {
6003 "%s [Error] Update packet error (prefix length %d overflows packet)",
6004 peer
->host
, p
.prefixlen
);
6005 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
6008 /* Defensive coding, double-check the psize fits in a struct
6009 * prefix for the v4 and v6 afi's and unicast/multicast */
6010 if (psize
> (ssize_t
)sizeof(p
.u
.val
)) {
6013 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
6014 peer
->host
, p
.prefixlen
, sizeof(p
.u
.val
));
6015 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6018 /* Fetch prefix from NLRI packet. */
6019 memcpy(p
.u
.val
, pnt
, psize
);
6021 /* Check address. */
6022 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
6023 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
6024 /* From RFC4271 Section 6.3:
6026 * If a prefix in the NLRI field is semantically
6028 * (e.g., an unexpected multicast IP address),
6030 * be logged locally, and the prefix SHOULD be
6035 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6036 peer
->host
, &p
.u
.prefix4
);
6041 /* Check address. */
6042 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
6043 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6046 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6047 peer
->host
, &p
.u
.prefix6
);
6051 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
6054 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6055 peer
->host
, &p
.u
.prefix6
);
6061 /* Normal process. */
6063 bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
6064 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
,
6067 bgp_withdraw(peer
, &p
, addpath_id
, afi
, safi
,
6068 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
,
6071 /* Do not send BGP notification twice when maximum-prefix count
6073 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
6074 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
6077 /* Packet length consistency check. */
6081 "%s [Error] Update packet error (prefix length mismatch with total length)",
6083 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
6086 return BGP_NLRI_PARSE_OK
;
6089 static struct bgp_static
*bgp_static_new(void)
6091 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
6094 static void bgp_static_free(struct bgp_static
*bgp_static
)
6096 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6097 route_map_counter_decrement(bgp_static
->rmap
.map
);
6099 if (bgp_static
->prd_pretty
)
6100 XFREE(MTYPE_BGP
, bgp_static
->prd_pretty
);
6101 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
6102 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
6105 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
6106 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
6108 struct bgp_dest
*dest
;
6109 struct bgp_path_info
*pi
;
6110 struct bgp_path_info
*new;
6111 struct bgp_path_info rmap_path
;
6113 struct attr
*attr_new
;
6114 route_map_result_t ret
;
6115 #ifdef ENABLE_BGP_VNC
6116 int vnc_implicit_withdraw
= 0;
6121 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6123 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6125 attr
.nexthop
= bgp_static
->igpnexthop
;
6126 attr
.med
= bgp_static
->igpmetric
;
6127 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6130 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
6132 if (bgp_static
->igpmetric
)
6133 bgp_attr_set_aigp_metric(&attr
, bgp_static
->igpmetric
);
6135 if (bgp_static
->atomic
)
6136 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
6138 /* Store label index, if required. */
6139 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
6140 attr
.label_index
= bgp_static
->label_index
;
6141 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
6144 /* Apply route-map. */
6145 if (bgp_static
->rmap
.name
) {
6146 struct attr attr_tmp
= attr
;
6148 memset(&rmap_path
, 0, sizeof(rmap_path
));
6149 rmap_path
.peer
= bgp
->peer_self
;
6150 rmap_path
.attr
= &attr_tmp
;
6152 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6154 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6156 bgp
->peer_self
->rmap_type
= 0;
6158 if (ret
== RMAP_DENYMATCH
) {
6159 /* Free uninterned attribute. */
6160 bgp_attr_flush(&attr_tmp
);
6162 /* Unintern original. */
6163 aspath_unintern(&attr
.aspath
);
6164 bgp_static_withdraw(bgp
, p
, afi
, safi
);
6165 bgp_dest_unlock_node(dest
);
6169 if (bgp_in_graceful_shutdown(bgp
))
6170 bgp_attr_add_gshut_community(&attr_tmp
);
6172 attr_new
= bgp_attr_intern(&attr_tmp
);
6175 if (bgp_in_graceful_shutdown(bgp
))
6176 bgp_attr_add_gshut_community(&attr
);
6178 attr_new
= bgp_attr_intern(&attr
);
6181 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6182 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6183 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6187 if (attrhash_cmp(pi
->attr
, attr_new
)
6188 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
6189 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
6190 bgp_dest_unlock_node(dest
);
6191 bgp_attr_unintern(&attr_new
);
6192 aspath_unintern(&attr
.aspath
);
6195 /* The attribute is changed. */
6196 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6198 /* Rewrite BGP route information. */
6199 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6200 bgp_path_info_restore(dest
, pi
);
6202 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6203 #ifdef ENABLE_BGP_VNC
6204 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6205 && (safi
== SAFI_UNICAST
)) {
6206 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
6208 * Implicit withdraw case.
6209 * We have to do this before pi is
6212 ++vnc_implicit_withdraw
;
6213 vnc_import_bgp_del_route(bgp
, p
, pi
);
6214 vnc_import_bgp_exterior_del_route(
6219 bgp_attr_unintern(&pi
->attr
);
6220 pi
->attr
= attr_new
;
6221 pi
->uptime
= monotime(NULL
);
6222 #ifdef ENABLE_BGP_VNC
6223 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
6224 && (safi
== SAFI_UNICAST
)) {
6225 if (vnc_implicit_withdraw
) {
6226 vnc_import_bgp_add_route(bgp
, p
, pi
);
6227 vnc_import_bgp_exterior_add_route(
6233 /* Nexthop reachability check. */
6234 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6235 && (safi
== SAFI_UNICAST
6236 || safi
== SAFI_LABELED_UNICAST
)) {
6238 struct bgp
*bgp_nexthop
= bgp
;
6240 if (pi
->extra
&& pi
->extra
->bgp_orig
)
6241 bgp_nexthop
= pi
->extra
->bgp_orig
;
6243 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
6244 afi
, safi
, pi
, NULL
,
6246 bgp_path_info_set_flag(dest
, pi
,
6249 if (BGP_DEBUG(nht
, NHT
)) {
6250 char buf1
[INET6_ADDRSTRLEN
];
6251 inet_ntop(p
->family
,
6255 "%s(%s): Route not in table, not advertising",
6258 bgp_path_info_unset_flag(
6259 dest
, pi
, BGP_PATH_VALID
);
6262 /* Delete the NHT structure if any, if we're
6264 * enabling/disabling import check. We
6265 * deregister the route
6266 * from NHT to avoid overloading NHT and the
6267 * process interaction
6269 bgp_unlink_nexthop(pi
);
6270 bgp_path_info_set_flag(dest
, pi
,
6273 /* Process change. */
6274 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6275 bgp_process(bgp
, dest
, afi
, safi
);
6277 if (SAFI_UNICAST
== safi
6278 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6280 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6281 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
6285 bgp_dest_unlock_node(dest
);
6286 aspath_unintern(&attr
.aspath
);
6291 /* Make new BGP info. */
6292 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6294 /* Nexthop reachability check. */
6295 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
6296 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
6297 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0,
6299 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6301 if (BGP_DEBUG(nht
, NHT
)) {
6302 char buf1
[INET6_ADDRSTRLEN
];
6304 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
6307 "%s(%s): Route not in table, not advertising",
6310 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
6313 /* Delete the NHT structure if any, if we're toggling between
6314 * enabling/disabling import check. We deregister the route
6315 * from NHT to avoid overloading NHT and the process interaction
6317 bgp_unlink_nexthop(new);
6319 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
6322 /* Aggregate address increment. */
6323 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6325 /* Register new BGP information. */
6326 bgp_path_info_add(dest
, new);
6328 /* route_node_get lock */
6329 bgp_dest_unlock_node(dest
);
6331 /* Process change. */
6332 bgp_process(bgp
, dest
, afi
, safi
);
6334 if (SAFI_UNICAST
== safi
6335 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6336 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6337 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6340 /* Unintern original. */
6341 aspath_unintern(&attr
.aspath
);
6344 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6347 struct bgp_dest
*dest
;
6348 struct bgp_path_info
*pi
;
6350 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
6352 /* Check selected route and self inserted route. */
6353 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6354 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6355 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6358 /* Withdraw static BGP route from routing table. */
6360 if (SAFI_UNICAST
== safi
6361 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
6362 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6363 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
6365 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6366 bgp_unlink_nexthop(pi
);
6367 bgp_path_info_delete(dest
, pi
);
6368 bgp_process(bgp
, dest
, afi
, safi
);
6371 /* Unlock bgp_node_lookup. */
6372 bgp_dest_unlock_node(dest
);
6376 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6378 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
6379 afi_t afi
, safi_t safi
,
6380 struct prefix_rd
*prd
)
6382 struct bgp_dest
*dest
;
6383 struct bgp_path_info
*pi
;
6385 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
6387 /* Check selected route and self inserted route. */
6388 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6389 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6390 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6393 /* Withdraw static BGP route from routing table. */
6395 #ifdef ENABLE_BGP_VNC
6396 rfapiProcessWithdraw(
6397 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
6398 1); /* Kill, since it is an administrative change */
6400 if (SAFI_MPLS_VPN
== safi
6401 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6402 vpn_leak_to_vrf_withdraw(pi
);
6404 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6405 bgp_path_info_delete(dest
, pi
);
6406 bgp_process(bgp
, dest
, afi
, safi
);
6409 /* Unlock bgp_node_lookup. */
6410 bgp_dest_unlock_node(dest
);
6413 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
6414 struct bgp_static
*bgp_static
, afi_t afi
,
6417 struct bgp_dest
*dest
;
6418 struct bgp_path_info
*new;
6419 struct attr
*attr_new
;
6420 struct attr attr
= {0};
6421 struct bgp_path_info
*pi
;
6422 #ifdef ENABLE_BGP_VNC
6423 mpls_label_t label
= 0;
6425 uint32_t num_labels
= 0;
6429 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
6431 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
6434 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_IGP
);
6436 attr
.nexthop
= bgp_static
->igpnexthop
;
6437 attr
.med
= bgp_static
->igpmetric
;
6438 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6440 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
6441 || (safi
== SAFI_ENCAP
)) {
6442 if (afi
== AFI_IP
) {
6443 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
6444 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
6447 if (afi
== AFI_L2VPN
) {
6448 if (bgp_static
->gatewayIp
.family
== AF_INET
) {
6449 SET_IPADDR_V4(&attr
.evpn_overlay
.gw_ip
);
6450 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v4
,
6451 &bgp_static
->gatewayIp
.u
.prefix4
,
6453 } else if (bgp_static
->gatewayIp
.family
== AF_INET6
) {
6454 SET_IPADDR_V6(&attr
.evpn_overlay
.gw_ip
);
6455 memcpy(&attr
.evpn_overlay
.gw_ip
.ipaddr_v6
,
6456 &bgp_static
->gatewayIp
.u
.prefix6
,
6459 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
6460 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
6461 struct bgp_encap_type_vxlan bet
;
6462 memset(&bet
, 0, sizeof(bet
));
6463 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
6464 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
6466 if (bgp_static
->router_mac
) {
6467 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
6470 /* Apply route-map. */
6471 if (bgp_static
->rmap
.name
) {
6472 struct attr attr_tmp
= attr
;
6473 struct bgp_path_info rmap_path
;
6474 route_map_result_t ret
;
6476 rmap_path
.peer
= bgp
->peer_self
;
6477 rmap_path
.attr
= &attr_tmp
;
6479 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
6481 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
6483 bgp
->peer_self
->rmap_type
= 0;
6485 if (ret
== RMAP_DENYMATCH
) {
6486 /* Free uninterned attribute. */
6487 bgp_attr_flush(&attr_tmp
);
6489 /* Unintern original. */
6490 aspath_unintern(&attr
.aspath
);
6491 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
6493 bgp_dest_unlock_node(dest
);
6497 attr_new
= bgp_attr_intern(&attr_tmp
);
6499 attr_new
= bgp_attr_intern(&attr
);
6502 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6503 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6504 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6508 if (attrhash_cmp(pi
->attr
, attr_new
)
6509 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
6510 bgp_dest_unlock_node(dest
);
6511 bgp_attr_unintern(&attr_new
);
6512 aspath_unintern(&attr
.aspath
);
6515 /* The attribute is changed. */
6516 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
6518 /* Rewrite BGP route information. */
6519 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
6520 bgp_path_info_restore(dest
, pi
);
6522 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
6523 bgp_attr_unintern(&pi
->attr
);
6524 pi
->attr
= attr_new
;
6525 pi
->uptime
= monotime(NULL
);
6526 #ifdef ENABLE_BGP_VNC
6528 label
= decode_label(&pi
->extra
->label
[0]);
6531 /* Process change. */
6532 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
6533 bgp_process(bgp
, dest
, afi
, safi
);
6535 if (SAFI_MPLS_VPN
== safi
6536 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6537 vpn_leak_to_vrf_update(bgp
, pi
,
6540 #ifdef ENABLE_BGP_VNC
6541 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
6542 pi
->attr
, afi
, safi
, pi
->type
,
6543 pi
->sub_type
, &label
);
6545 bgp_dest_unlock_node(dest
);
6546 aspath_unintern(&attr
.aspath
);
6552 /* Make new BGP info. */
6553 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
6555 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6556 bgp_path_info_extra_get(new);
6558 new->extra
->label
[0] = bgp_static
->label
;
6559 new->extra
->num_labels
= num_labels
;
6561 #ifdef ENABLE_BGP_VNC
6562 label
= decode_label(&bgp_static
->label
);
6565 /* Aggregate address increment. */
6566 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
6568 /* Register new BGP information. */
6569 bgp_path_info_add(dest
, new);
6570 /* route_node_get lock */
6571 bgp_dest_unlock_node(dest
);
6573 /* Process change. */
6574 bgp_process(bgp
, dest
, afi
, safi
);
6576 if (SAFI_MPLS_VPN
== safi
6577 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
6578 vpn_leak_to_vrf_update(bgp
, new, &bgp_static
->prd
);
6580 #ifdef ENABLE_BGP_VNC
6581 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
6582 safi
, new->type
, new->sub_type
, &label
);
6585 /* Unintern original. */
6586 aspath_unintern(&attr
.aspath
);
6589 /* Configure static BGP network. When user don't run zebra, static
6590 route should be installed as valid. */
6591 static int bgp_static_set(struct vty
*vty
, const char *negate
,
6592 const char *ip_str
, afi_t afi
, safi_t safi
,
6593 const char *rmap
, int backdoor
, uint32_t label_index
)
6595 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6598 struct bgp_static
*bgp_static
;
6599 struct bgp_dest
*dest
;
6600 uint8_t need_update
= 0;
6602 /* Convert IP prefix string to struct prefix. */
6603 ret
= str2prefix(ip_str
, &p
);
6605 vty_out(vty
, "%% Malformed prefix\n");
6606 return CMD_WARNING_CONFIG_FAILED
;
6608 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
6609 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
6610 return CMD_WARNING_CONFIG_FAILED
;
6617 /* Set BGP static route configuration. */
6618 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
6621 vty_out(vty
, "%% Can't find static route specified\n");
6622 return CMD_WARNING_CONFIG_FAILED
;
6625 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6627 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
6628 && (label_index
!= bgp_static
->label_index
)) {
6630 "%% label-index doesn't match static route\n");
6631 bgp_dest_unlock_node(dest
);
6632 return CMD_WARNING_CONFIG_FAILED
;
6635 if ((rmap
&& bgp_static
->rmap
.name
)
6636 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
6638 "%% route-map name doesn't match static route\n");
6639 bgp_dest_unlock_node(dest
);
6640 return CMD_WARNING_CONFIG_FAILED
;
6643 /* Update BGP RIB. */
6644 if (!bgp_static
->backdoor
)
6645 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6647 /* Clear configuration. */
6648 bgp_static_free(bgp_static
);
6649 bgp_dest_set_bgp_static_info(dest
, NULL
);
6650 bgp_dest_unlock_node(dest
);
6651 bgp_dest_unlock_node(dest
);
6654 /* Set BGP static route configuration. */
6655 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
6656 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6658 /* Configuration change. */
6659 /* Label index cannot be changed. */
6660 if (bgp_static
->label_index
!= label_index
) {
6661 vty_out(vty
, "%% cannot change label-index\n");
6662 bgp_dest_unlock_node(dest
);
6663 return CMD_WARNING_CONFIG_FAILED
;
6666 /* Check previous routes are installed into BGP. */
6667 if (bgp_static
->valid
6668 && bgp_static
->backdoor
!= backdoor
)
6671 bgp_static
->backdoor
= backdoor
;
6674 XFREE(MTYPE_ROUTE_MAP_NAME
,
6675 bgp_static
->rmap
.name
);
6676 route_map_counter_decrement(
6677 bgp_static
->rmap
.map
);
6678 bgp_static
->rmap
.name
=
6679 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6680 bgp_static
->rmap
.map
=
6681 route_map_lookup_by_name(rmap
);
6682 route_map_counter_increment(
6683 bgp_static
->rmap
.map
);
6685 XFREE(MTYPE_ROUTE_MAP_NAME
,
6686 bgp_static
->rmap
.name
);
6687 route_map_counter_decrement(
6688 bgp_static
->rmap
.map
);
6689 bgp_static
->rmap
.map
= NULL
;
6690 bgp_static
->valid
= 0;
6692 bgp_dest_unlock_node(dest
);
6694 /* New configuration. */
6695 bgp_static
= bgp_static_new();
6696 bgp_static
->backdoor
= backdoor
;
6697 bgp_static
->valid
= 0;
6698 bgp_static
->igpmetric
= 0;
6699 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6700 bgp_static
->label_index
= label_index
;
6703 XFREE(MTYPE_ROUTE_MAP_NAME
,
6704 bgp_static
->rmap
.name
);
6705 route_map_counter_decrement(
6706 bgp_static
->rmap
.map
);
6707 bgp_static
->rmap
.name
=
6708 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6709 bgp_static
->rmap
.map
=
6710 route_map_lookup_by_name(rmap
);
6711 route_map_counter_increment(
6712 bgp_static
->rmap
.map
);
6714 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6717 bgp_static
->valid
= 1;
6719 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
6721 if (!bgp_static
->backdoor
)
6722 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
6728 void bgp_static_add(struct bgp
*bgp
)
6732 struct bgp_dest
*dest
;
6733 struct bgp_dest
*rm
;
6734 struct bgp_table
*table
;
6735 struct bgp_static
*bgp_static
;
6737 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6738 FOREACH_AFI_SAFI (afi
, safi
)
6739 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6740 dest
= bgp_route_next(dest
)) {
6741 if (!bgp_dest_has_bgp_path_info_data(dest
))
6744 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6745 || (safi
== SAFI_EVPN
)) {
6746 table
= bgp_dest_get_bgp_table_info(dest
);
6748 for (rm
= bgp_table_top(table
); rm
;
6749 rm
= bgp_route_next(rm
)) {
6751 bgp_dest_get_bgp_static_info(
6753 bgp_static_update_safi(
6754 bgp
, bgp_dest_get_prefix(rm
),
6755 bgp_static
, afi
, safi
);
6759 bgp
, bgp_dest_get_prefix(dest
),
6760 bgp_dest_get_bgp_static_info(dest
), afi
,
6764 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6767 /* Called from bgp_delete(). Delete all static routes from the BGP
6769 void bgp_static_delete(struct bgp
*bgp
)
6773 struct bgp_dest
*dest
;
6774 struct bgp_dest
*rm
;
6775 struct bgp_table
*table
;
6776 struct bgp_static
*bgp_static
;
6778 FOREACH_AFI_SAFI (afi
, safi
)
6779 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6780 dest
= bgp_route_next(dest
)) {
6781 if (!bgp_dest_has_bgp_path_info_data(dest
))
6784 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6785 || (safi
== SAFI_EVPN
)) {
6786 table
= bgp_dest_get_bgp_table_info(dest
);
6788 for (rm
= bgp_table_top(table
); rm
;
6789 rm
= bgp_route_next(rm
)) {
6791 bgp_dest_get_bgp_static_info(
6796 bgp_static_withdraw_safi(
6797 bgp
, bgp_dest_get_prefix(rm
),
6799 (struct prefix_rd
*)
6800 bgp_dest_get_prefix(
6802 bgp_static_free(bgp_static
);
6803 bgp_dest_set_bgp_static_info(rm
,
6805 bgp_dest_unlock_node(rm
);
6808 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6809 bgp_static_withdraw(bgp
,
6810 bgp_dest_get_prefix(dest
),
6812 bgp_static_free(bgp_static
);
6813 bgp_dest_set_bgp_static_info(dest
, NULL
);
6814 bgp_dest_unlock_node(dest
);
6819 void bgp_static_redo_import_check(struct bgp
*bgp
)
6823 struct bgp_dest
*dest
;
6824 struct bgp_dest
*rm
;
6825 struct bgp_table
*table
;
6826 struct bgp_static
*bgp_static
;
6828 /* Use this flag to force reprocessing of the route */
6829 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6830 FOREACH_AFI_SAFI (afi
, safi
) {
6831 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6832 dest
= bgp_route_next(dest
)) {
6833 if (!bgp_dest_has_bgp_path_info_data(dest
))
6836 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6837 || (safi
== SAFI_EVPN
)) {
6838 table
= bgp_dest_get_bgp_table_info(dest
);
6840 for (rm
= bgp_table_top(table
); rm
;
6841 rm
= bgp_route_next(rm
)) {
6843 bgp_dest_get_bgp_static_info(
6845 bgp_static_update_safi(
6846 bgp
, bgp_dest_get_prefix(rm
),
6847 bgp_static
, afi
, safi
);
6850 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6851 bgp_static_update(bgp
,
6852 bgp_dest_get_prefix(dest
),
6853 bgp_static
, afi
, safi
);
6857 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6860 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6863 struct bgp_table
*table
;
6864 struct bgp_dest
*dest
;
6865 struct bgp_path_info
*pi
;
6867 /* Do not install the aggregate route if BGP is in the
6868 * process of termination.
6870 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6871 || (bgp
->peer_self
== NULL
))
6874 table
= bgp
->rib
[afi
][safi
];
6875 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6876 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6877 if (pi
->peer
== bgp
->peer_self
6878 && ((pi
->type
== ZEBRA_ROUTE_BGP
6879 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6880 || (pi
->type
!= ZEBRA_ROUTE_BGP
6882 == BGP_ROUTE_REDISTRIBUTE
))) {
6883 bgp_aggregate_decrement(
6884 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6886 bgp_unlink_nexthop(pi
);
6887 bgp_path_info_delete(dest
, pi
);
6888 bgp_process(bgp
, dest
, afi
, safi
);
6895 * Purge all networks and redistributed routes from routing table.
6896 * Invoked upon the instance going down.
6898 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6903 FOREACH_AFI_SAFI (afi
, safi
)
6904 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6909 * Currently this is used to set static routes for VPN and ENCAP.
6910 * I think it can probably be factored with bgp_static_set.
6912 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6913 const char *ip_str
, const char *rd_str
,
6914 const char *label_str
, const char *rmap_str
,
6915 int evpn_type
, const char *esi
, const char *gwip
,
6916 const char *ethtag
, const char *routermac
)
6918 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6921 struct prefix_rd prd
;
6922 struct bgp_dest
*pdest
;
6923 struct bgp_dest
*dest
;
6924 struct bgp_table
*table
;
6925 struct bgp_static
*bgp_static
;
6926 mpls_label_t label
= MPLS_INVALID_LABEL
;
6927 struct prefix gw_ip
;
6929 /* validate ip prefix */
6930 ret
= str2prefix(ip_str
, &p
);
6932 vty_out(vty
, "%% Malformed prefix\n");
6933 return CMD_WARNING_CONFIG_FAILED
;
6936 if ((afi
== AFI_L2VPN
)
6937 && (bgp_build_evpn_prefix(evpn_type
,
6938 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6939 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6940 return CMD_WARNING_CONFIG_FAILED
;
6943 ret
= str2prefix_rd(rd_str
, &prd
);
6945 vty_out(vty
, "%% Malformed rd\n");
6946 return CMD_WARNING_CONFIG_FAILED
;
6950 unsigned long label_val
;
6951 label_val
= strtoul(label_str
, NULL
, 10);
6952 encode_label(label_val
, &label
);
6955 if (safi
== SAFI_EVPN
) {
6956 if (esi
&& str2esi(esi
, NULL
) == 0) {
6957 vty_out(vty
, "%% Malformed ESI\n");
6958 return CMD_WARNING_CONFIG_FAILED
;
6960 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6961 vty_out(vty
, "%% Malformed Router MAC\n");
6962 return CMD_WARNING_CONFIG_FAILED
;
6965 memset(&gw_ip
, 0, sizeof(gw_ip
));
6966 ret
= str2prefix(gwip
, &gw_ip
);
6968 vty_out(vty
, "%% Malformed GatewayIp\n");
6969 return CMD_WARNING_CONFIG_FAILED
;
6971 if ((gw_ip
.family
== AF_INET
6972 && is_evpn_prefix_ipaddr_v6(
6973 (struct prefix_evpn
*)&p
))
6974 || (gw_ip
.family
== AF_INET6
6975 && is_evpn_prefix_ipaddr_v4(
6976 (struct prefix_evpn
*)&p
))) {
6978 "%% GatewayIp family differs with IP prefix\n");
6979 return CMD_WARNING_CONFIG_FAILED
;
6983 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6984 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6985 bgp_dest_set_bgp_table_info(pdest
,
6986 bgp_table_init(bgp
, afi
, safi
));
6987 table
= bgp_dest_get_bgp_table_info(pdest
);
6989 dest
= bgp_node_get(table
, &p
);
6991 if (bgp_dest_has_bgp_path_info_data(dest
)) {
6992 vty_out(vty
, "%% Same network configuration exists\n");
6993 bgp_dest_unlock_node(dest
);
6995 /* New configuration. */
6996 bgp_static
= bgp_static_new();
6997 bgp_static
->backdoor
= 0;
6998 bgp_static
->valid
= 0;
6999 bgp_static
->igpmetric
= 0;
7000 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
7001 bgp_static
->label
= label
;
7002 bgp_static
->prd
= prd
;
7005 bgp_static
->prd_pretty
= XSTRDUP(MTYPE_BGP
, rd_str
);
7007 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
7008 route_map_counter_decrement(bgp_static
->rmap
.map
);
7009 bgp_static
->rmap
.name
=
7010 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
7011 bgp_static
->rmap
.map
=
7012 route_map_lookup_by_name(rmap_str
);
7013 route_map_counter_increment(bgp_static
->rmap
.map
);
7016 if (safi
== SAFI_EVPN
) {
7018 bgp_static
->eth_s_id
=
7021 str2esi(esi
, bgp_static
->eth_s_id
);
7024 bgp_static
->router_mac
=
7025 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
7026 (void)prefix_str2mac(routermac
,
7027 bgp_static
->router_mac
);
7030 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
7032 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
7034 bgp_static
->valid
= 1;
7035 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
7041 /* Configure static BGP network. */
7042 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
7043 const char *ip_str
, const char *rd_str
,
7044 const char *label_str
, int evpn_type
, const char *esi
,
7045 const char *gwip
, const char *ethtag
)
7047 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7050 struct prefix_rd prd
;
7051 struct bgp_dest
*pdest
;
7052 struct bgp_dest
*dest
;
7053 struct bgp_table
*table
;
7054 struct bgp_static
*bgp_static
;
7055 mpls_label_t label
= MPLS_INVALID_LABEL
;
7057 /* Convert IP prefix string to struct prefix. */
7058 ret
= str2prefix(ip_str
, &p
);
7060 vty_out(vty
, "%% Malformed prefix\n");
7061 return CMD_WARNING_CONFIG_FAILED
;
7064 if ((afi
== AFI_L2VPN
)
7065 && (bgp_build_evpn_prefix(evpn_type
,
7066 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
7067 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
7068 return CMD_WARNING_CONFIG_FAILED
;
7070 ret
= str2prefix_rd(rd_str
, &prd
);
7072 vty_out(vty
, "%% Malformed rd\n");
7073 return CMD_WARNING_CONFIG_FAILED
;
7077 unsigned long label_val
;
7078 label_val
= strtoul(label_str
, NULL
, 10);
7079 encode_label(label_val
, &label
);
7082 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
7083 if (!bgp_dest_has_bgp_path_info_data(pdest
))
7084 bgp_dest_set_bgp_table_info(pdest
,
7085 bgp_table_init(bgp
, afi
, safi
));
7087 bgp_dest_unlock_node(pdest
);
7088 table
= bgp_dest_get_bgp_table_info(pdest
);
7090 dest
= bgp_node_lookup(table
, &p
);
7093 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
7095 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
7096 bgp_static_free(bgp_static
);
7097 bgp_dest_set_bgp_static_info(dest
, NULL
);
7098 bgp_dest_unlock_node(dest
);
7099 bgp_dest_unlock_node(dest
);
7101 vty_out(vty
, "%% Can't find the route\n");
7106 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
7107 const char *rmap_name
)
7109 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7110 struct bgp_rmap
*rmap
;
7112 rmap
= &bgp
->table_map
[afi
][safi
];
7114 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7115 route_map_counter_decrement(rmap
->map
);
7116 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
7117 rmap
->map
= route_map_lookup_by_name(rmap_name
);
7118 route_map_counter_increment(rmap
->map
);
7120 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7121 route_map_counter_decrement(rmap
->map
);
7125 if (bgp_fibupd_safi(safi
))
7126 bgp_zebra_announce_table(bgp
, afi
, safi
);
7131 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
7132 const char *rmap_name
)
7134 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7135 struct bgp_rmap
*rmap
;
7137 rmap
= &bgp
->table_map
[afi
][safi
];
7138 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
7139 route_map_counter_decrement(rmap
->map
);
7142 if (bgp_fibupd_safi(safi
))
7143 bgp_zebra_announce_table(bgp
, afi
, safi
);
7148 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
7151 if (bgp
->table_map
[afi
][safi
].name
) {
7152 vty_out(vty
, " table-map %s\n",
7153 bgp
->table_map
[afi
][safi
].name
);
7157 DEFUN (bgp_table_map
,
7160 "BGP table to RIB route download filter\n"
7161 "Name of the route map\n")
7164 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7165 argv
[idx_word
]->arg
);
7167 DEFUN (no_bgp_table_map
,
7168 no_bgp_table_map_cmd
,
7169 "no table-map WORD",
7171 "BGP table to RIB route download filter\n"
7172 "Name of the route map\n")
7175 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
7176 argv
[idx_word
]->arg
);
7182 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
7183 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
7184 backdoor$backdoor}]",
7186 "Specify a network to announce via BGP\n"
7191 "Route-map to modify the attributes\n"
7192 "Name of the route map\n"
7193 "Label index to associate with the prefix\n"
7194 "Label index value\n"
7195 "Specify a BGP backdoor route\n")
7197 char addr_prefix_str
[BUFSIZ
];
7202 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
7204 sizeof(addr_prefix_str
));
7206 vty_out(vty
, "%% Inconsistent address and mask\n");
7207 return CMD_WARNING_CONFIG_FAILED
;
7211 return bgp_static_set(
7212 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
7213 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
7214 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7217 DEFPY(ipv6_bgp_network
,
7218 ipv6_bgp_network_cmd
,
7219 "[no] network X:X::X:X/M$prefix \
7220 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
7222 "Specify a network to announce via BGP\n"
7224 "Route-map to modify the attributes\n"
7225 "Name of the route map\n"
7226 "Label index to associate with the prefix\n"
7227 "Label index value\n")
7229 return bgp_static_set(
7230 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
7231 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
7234 static struct bgp_aggregate
*bgp_aggregate_new(void)
7236 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
7239 void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
7241 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7242 route_map_counter_decrement(aggregate
->suppress_map
);
7243 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7244 route_map_counter_decrement(aggregate
->rmap
.map
);
7245 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
7249 * Helper function to avoid repeated code: prepare variables for a
7250 * `route_map_apply` call.
7252 * \returns `true` on route map match, otherwise `false`.
7254 static bool aggr_suppress_map_test(struct bgp
*bgp
,
7255 struct bgp_aggregate
*aggregate
,
7256 struct bgp_path_info
*pi
)
7258 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
7259 route_map_result_t rmr
= RMAP_DENYMATCH
;
7260 struct bgp_path_info rmap_path
= {};
7261 struct attr attr
= {};
7263 /* No route map entries created, just don't match. */
7264 if (aggregate
->suppress_map
== NULL
)
7267 /* Call route map matching and return result. */
7268 attr
.aspath
= aspath_empty(bgp
->asnotation
);
7269 rmap_path
.peer
= bgp
->peer_self
;
7270 rmap_path
.attr
= &attr
;
7272 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
7273 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
7274 bgp
->peer_self
->rmap_type
= 0;
7276 bgp_attr_flush(&attr
);
7277 aspath_unintern(&attr
.aspath
);
7279 return rmr
== RMAP_PERMITMATCH
;
7282 /** Test whether the aggregation has suppressed this path or not. */
7283 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
7284 struct bgp_path_info
*pi
)
7286 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
7289 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
7293 * Suppress this path and keep the reference.
7295 * \returns `true` if needs processing otherwise `false`.
7297 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
7298 struct bgp_path_info
*pi
)
7300 struct bgp_path_info_extra
*pie
;
7302 /* Path is already suppressed by this aggregation. */
7303 if (aggr_suppress_exists(aggregate
, pi
))
7306 pie
= bgp_path_info_extra_get(pi
);
7308 /* This is the first suppression, allocate memory and list it. */
7309 if (pie
->aggr_suppressors
== NULL
)
7310 pie
->aggr_suppressors
= list_new();
7312 listnode_add(pie
->aggr_suppressors
, aggregate
);
7314 /* Only mark for processing if suppressed. */
7315 if (listcount(pie
->aggr_suppressors
) == 1) {
7316 if (BGP_DEBUG(update
, UPDATE_OUT
))
7317 zlog_debug("aggregate-address suppressing: %pFX",
7318 bgp_dest_get_prefix(pi
->net
));
7320 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7328 * Unsuppress this path and remove the reference.
7330 * \returns `true` if needs processing otherwise `false`.
7332 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
7333 struct bgp_path_info
*pi
)
7335 /* Path wasn't suppressed. */
7336 if (!aggr_suppress_exists(aggregate
, pi
))
7339 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
7341 /* Unsuppress and free extra memory if last item. */
7342 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
7343 if (BGP_DEBUG(update
, UPDATE_OUT
))
7344 zlog_debug("aggregate-address unsuppressing: %pFX",
7345 bgp_dest_get_prefix(pi
->net
));
7347 list_delete(&pi
->extra
->aggr_suppressors
);
7348 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
7355 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
7356 struct aspath
*aspath
,
7357 struct community
*comm
,
7358 struct ecommunity
*ecomm
,
7359 struct lcommunity
*lcomm
)
7361 static struct aspath
*ae
= NULL
;
7362 enum asnotation_mode asnotation
;
7364 asnotation
= bgp_get_asnotation(NULL
);
7367 ae
= aspath_empty(asnotation
);
7372 if (origin
!= pi
->attr
->origin
)
7375 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
7378 if (!community_cmp(bgp_attr_get_community(pi
->attr
), comm
))
7381 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi
->attr
), ecomm
))
7384 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi
->attr
), lcomm
))
7387 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
7393 static void bgp_aggregate_install(
7394 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
7395 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
7396 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
7397 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
7399 struct bgp_dest
*dest
;
7400 struct bgp_table
*table
;
7401 struct bgp_path_info
*pi
, *orig
, *new;
7404 table
= bgp
->rib
[afi
][safi
];
7406 dest
= bgp_node_get(table
, p
);
7408 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7409 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
7410 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7414 * If we have paths with different MEDs, then don't install
7415 * (or uninstall) the aggregate route.
7417 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
7418 goto uninstall_aggregate_route
;
7420 if (aggregate
->count
> 0) {
7422 * If the aggregate information has not changed
7423 * no need to re-install it again.
7425 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
7426 ecommunity
, lcommunity
)) {
7427 bgp_dest_unlock_node(dest
);
7430 aspath_free(aspath
);
7432 community_free(&community
);
7434 ecommunity_free(&ecommunity
);
7436 lcommunity_free(&lcommunity
);
7442 * Mark the old as unusable
7445 bgp_path_info_delete(dest
, pi
);
7447 attr
= bgp_attr_aggregate_intern(
7448 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
7449 aggregate
, atomic_aggregate
, p
);
7452 aspath_free(aspath
);
7453 community_free(&community
);
7454 ecommunity_free(&ecommunity
);
7455 lcommunity_free(&lcommunity
);
7456 bgp_dest_unlock_node(dest
);
7457 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
7458 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
7459 zlog_debug("%s: %pFX null attribute", __func__
,
7464 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
7465 bgp
->peer_self
, attr
, dest
);
7467 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7469 bgp_path_info_add(dest
, new);
7470 bgp_process(bgp
, dest
, afi
, safi
);
7472 uninstall_aggregate_route
:
7473 for (pi
= orig
; pi
; pi
= pi
->next
)
7474 if (pi
->peer
== bgp
->peer_self
7475 && pi
->type
== ZEBRA_ROUTE_BGP
7476 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7479 /* Withdraw static BGP route from routing table. */
7481 bgp_path_info_delete(dest
, pi
);
7482 bgp_process(bgp
, dest
, afi
, safi
);
7486 bgp_dest_unlock_node(dest
);
7490 * Check if the current path has different MED than other known paths.
7492 * \returns `true` if the MED matched the others else `false`.
7494 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
7495 struct bgp
*bgp
, struct bgp_path_info
*pi
)
7497 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
7499 /* This is the first route being analyzed. */
7500 if (!aggregate
->med_initialized
) {
7501 aggregate
->med_initialized
= true;
7502 aggregate
->med_mismatched
= false;
7503 aggregate
->med_matched_value
= cur_med
;
7505 /* Check if routes with different MED showed up. */
7506 if (cur_med
!= aggregate
->med_matched_value
)
7507 aggregate
->med_mismatched
= true;
7510 return !aggregate
->med_mismatched
;
7514 * Initializes and tests all routes in the aggregate address path for MED
7517 * \returns `true` if all MEDs are the same otherwise `false`.
7519 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
7520 struct bgp
*bgp
, const struct prefix
*p
,
7521 afi_t afi
, safi_t safi
)
7523 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7524 const struct prefix
*dest_p
;
7525 struct bgp_dest
*dest
, *top
;
7526 struct bgp_path_info
*pi
;
7527 bool med_matched
= true;
7529 aggregate
->med_initialized
= false;
7531 top
= bgp_node_get(table
, p
);
7532 for (dest
= bgp_node_get(table
, p
); dest
;
7533 dest
= bgp_route_next_until(dest
, top
)) {
7534 dest_p
= bgp_dest_get_prefix(dest
);
7535 if (dest_p
->prefixlen
<= p
->prefixlen
)
7538 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7539 if (BGP_PATH_HOLDDOWN(pi
))
7541 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7543 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
7544 med_matched
= false;
7551 bgp_dest_unlock_node(top
);
7557 * Toggles the route suppression status for this aggregate address
7560 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
7561 struct bgp
*bgp
, const struct prefix
*p
,
7562 afi_t afi
, safi_t safi
, bool suppress
)
7564 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
7565 const struct prefix
*dest_p
;
7566 struct bgp_dest
*dest
, *top
;
7567 struct bgp_path_info
*pi
;
7568 bool toggle_suppression
;
7570 /* We've found a different MED we must revert any suppressed routes. */
7571 top
= bgp_node_get(table
, p
);
7572 for (dest
= bgp_node_get(table
, p
); dest
;
7573 dest
= bgp_route_next_until(dest
, top
)) {
7574 dest_p
= bgp_dest_get_prefix(dest
);
7575 if (dest_p
->prefixlen
<= p
->prefixlen
)
7578 toggle_suppression
= false;
7579 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7580 if (BGP_PATH_HOLDDOWN(pi
))
7582 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7585 /* We are toggling suppression back. */
7587 /* Suppress route if not suppressed already. */
7588 if (aggr_suppress_path(aggregate
, pi
))
7589 toggle_suppression
= true;
7593 /* Install route if there is no more suppression. */
7594 if (aggr_unsuppress_path(aggregate
, pi
))
7595 toggle_suppression
= true;
7598 if (toggle_suppression
)
7599 bgp_process(bgp
, dest
, afi
, safi
);
7601 bgp_dest_unlock_node(top
);
7605 * Aggregate address MED matching incremental test: this function is called
7606 * when the initial aggregation occurred and we are only testing a single
7609 * In addition to testing and setting the MED validity it also installs back
7610 * suppressed routes (if summary is configured).
7612 * Must not be called in `bgp_aggregate_route`.
7614 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
7615 struct bgp
*bgp
, const struct prefix
*p
,
7616 afi_t afi
, safi_t safi
,
7617 struct bgp_path_info
*pi
)
7619 /* MED matching disabled. */
7620 if (!aggregate
->match_med
)
7623 /* Aggregation with different MED, recheck if we have got equal MEDs
7626 if (aggregate
->med_mismatched
&&
7627 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
) &&
7628 aggregate
->summary_only
)
7629 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
,
7632 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
7634 /* No mismatches, just quit. */
7635 if (!aggregate
->med_mismatched
)
7638 /* Route summarization is disabled. */
7639 if (!aggregate
->summary_only
)
7642 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
7645 /* Update an aggregate as routes are added/removed from the BGP table */
7646 bool bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7647 safi_t safi
, struct bgp_aggregate
*aggregate
)
7649 struct bgp_table
*table
;
7650 struct bgp_dest
*top
;
7651 struct bgp_dest
*dest
;
7653 struct aspath
*aspath
= NULL
;
7654 struct community
*community
= NULL
;
7655 struct ecommunity
*ecommunity
= NULL
;
7656 struct lcommunity
*lcommunity
= NULL
;
7657 struct bgp_path_info
*pi
;
7658 unsigned long match
= 0;
7659 uint8_t atomic_aggregate
= 0;
7661 /* If the bgp instance is being deleted or self peer is deleted
7662 * then do not create aggregate route
7664 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
7665 bgp
->peer_self
== NULL
)
7668 /* Initialize and test routes for MED difference. */
7669 if (aggregate
->match_med
)
7670 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
7673 * Reset aggregate count: we might've been called from route map
7674 * update so in that case we must retest all more specific routes.
7676 * \see `bgp_route_map_process_update`.
7678 aggregate
->count
= 0;
7679 aggregate
->incomplete_origin_count
= 0;
7680 aggregate
->incomplete_origin_count
= 0;
7681 aggregate
->egp_origin_count
= 0;
7683 /* ORIGIN attribute: If at least one route among routes that are
7684 aggregated has ORIGIN with the value INCOMPLETE, then the
7685 aggregated route must have the ORIGIN attribute with the value
7686 INCOMPLETE. Otherwise, if at least one route among routes that
7687 are aggregated has ORIGIN with the value EGP, then the aggregated
7688 route must have the origin attribute with the value EGP. In all
7689 other case the value of the ORIGIN attribute of the aggregated
7690 route is INTERNAL. */
7691 origin
= BGP_ORIGIN_IGP
;
7693 table
= bgp
->rib
[afi
][safi
];
7695 top
= bgp_node_get(table
, p
);
7696 for (dest
= bgp_node_get(table
, p
); dest
;
7697 dest
= bgp_route_next_until(dest
, top
)) {
7698 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7700 if (dest_p
->prefixlen
<= p
->prefixlen
)
7703 /* If suppress fib is enabled and route not installed
7704 * in FIB, skip the route
7706 if (!bgp_check_advertise(bgp
, dest
))
7711 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7712 if (BGP_PATH_HOLDDOWN(pi
))
7716 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
7717 atomic_aggregate
= 1;
7719 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7723 * summary-only aggregate route suppress
7724 * aggregated route announcements.
7727 * Don't create summaries if MED didn't match
7728 * otherwise neither the specific routes and the
7729 * aggregation will be announced.
7731 if (aggregate
->summary_only
7732 && AGGREGATE_MED_VALID(aggregate
)) {
7733 if (aggr_suppress_path(aggregate
, pi
))
7738 * Suppress more specific routes that match the route
7742 * Don't suppress routes if MED matching is enabled and
7743 * it mismatched otherwise we might end up with no
7744 * routes for this path.
7746 if (aggregate
->suppress_map_name
7747 && AGGREGATE_MED_VALID(aggregate
)
7748 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7749 if (aggr_suppress_path(aggregate
, pi
))
7756 * If at least one route among routes that are
7757 * aggregated has ORIGIN with the value INCOMPLETE,
7758 * then the aggregated route MUST have the ORIGIN
7759 * attribute with the value INCOMPLETE. Otherwise, if
7760 * at least one route among routes that are aggregated
7761 * has ORIGIN with the value EGP, then the aggregated
7762 * route MUST have the ORIGIN attribute with the value
7765 switch (pi
->attr
->origin
) {
7766 case BGP_ORIGIN_INCOMPLETE
:
7767 aggregate
->incomplete_origin_count
++;
7769 case BGP_ORIGIN_EGP
:
7770 aggregate
->egp_origin_count
++;
7778 if (!aggregate
->as_set
)
7782 * as-set aggregate route generate origin, as path,
7783 * and community aggregation.
7785 /* Compute aggregate route's as-path.
7787 bgp_compute_aggregate_aspath_hash(aggregate
,
7790 /* Compute aggregate route's community.
7792 if (bgp_attr_get_community(pi
->attr
))
7793 bgp_compute_aggregate_community_hash(
7795 bgp_attr_get_community(pi
->attr
));
7797 /* Compute aggregate route's extended community.
7799 if (bgp_attr_get_ecommunity(pi
->attr
))
7800 bgp_compute_aggregate_ecommunity_hash(
7802 bgp_attr_get_ecommunity(pi
->attr
));
7804 /* Compute aggregate route's large community.
7806 if (bgp_attr_get_lcommunity(pi
->attr
))
7807 bgp_compute_aggregate_lcommunity_hash(
7809 bgp_attr_get_lcommunity(pi
->attr
));
7812 bgp_process(bgp
, dest
, afi
, safi
);
7814 if (aggregate
->as_set
) {
7815 bgp_compute_aggregate_aspath_val(aggregate
);
7816 bgp_compute_aggregate_community_val(aggregate
);
7817 bgp_compute_aggregate_ecommunity_val(aggregate
);
7818 bgp_compute_aggregate_lcommunity_val(aggregate
);
7822 bgp_dest_unlock_node(top
);
7825 if (aggregate
->incomplete_origin_count
> 0)
7826 origin
= BGP_ORIGIN_INCOMPLETE
;
7827 else if (aggregate
->egp_origin_count
> 0)
7828 origin
= BGP_ORIGIN_EGP
;
7830 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7831 origin
= aggregate
->origin
;
7833 if (aggregate
->as_set
) {
7834 if (aggregate
->aspath
)
7835 /* Retrieve aggregate route's as-path.
7837 aspath
= aspath_dup(aggregate
->aspath
);
7839 if (aggregate
->community
)
7840 /* Retrieve aggregate route's community.
7842 community
= community_dup(aggregate
->community
);
7844 if (aggregate
->ecommunity
)
7845 /* Retrieve aggregate route's ecommunity.
7847 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7849 if (aggregate
->lcommunity
)
7850 /* Retrieve aggregate route's lcommunity.
7852 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7855 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7856 ecommunity
, lcommunity
, atomic_aggregate
,
7862 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7863 safi_t safi
, struct bgp_aggregate
*aggregate
)
7865 struct bgp_table
*table
;
7866 struct bgp_dest
*top
;
7867 struct bgp_dest
*dest
;
7868 struct bgp_path_info
*pi
;
7869 unsigned long match
;
7871 table
= bgp
->rib
[afi
][safi
];
7873 /* If routes exists below this node, generate aggregate routes. */
7874 top
= bgp_node_get(table
, p
);
7875 for (dest
= bgp_node_get(table
, p
); dest
;
7876 dest
= bgp_route_next_until(dest
, top
)) {
7877 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7879 if (dest_p
->prefixlen
<= p
->prefixlen
)
7883 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7884 if (BGP_PATH_HOLDDOWN(pi
))
7887 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7891 * This route is suppressed: attempt to unsuppress it.
7893 * `aggr_unsuppress_path` will fail if this particular
7894 * aggregate route was not the suppressor.
7896 if (pi
->extra
&& pi
->extra
->aggr_suppressors
&&
7897 listcount(pi
->extra
->aggr_suppressors
)) {
7898 if (aggr_unsuppress_path(aggregate
, pi
))
7904 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7905 aggregate
->incomplete_origin_count
--;
7906 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7907 aggregate
->egp_origin_count
--;
7909 if (aggregate
->as_set
) {
7910 /* Remove as-path from aggregate.
7912 bgp_remove_aspath_from_aggregate_hash(
7916 if (bgp_attr_get_community(pi
->attr
))
7917 /* Remove community from aggregate.
7919 bgp_remove_comm_from_aggregate_hash(
7921 bgp_attr_get_community(
7924 if (bgp_attr_get_ecommunity(pi
->attr
))
7925 /* Remove ecommunity from aggregate.
7927 bgp_remove_ecomm_from_aggregate_hash(
7929 bgp_attr_get_ecommunity(
7932 if (bgp_attr_get_lcommunity(pi
->attr
))
7933 /* Remove lcommunity from aggregate.
7935 bgp_remove_lcomm_from_aggregate_hash(
7937 bgp_attr_get_lcommunity(
7942 /* If this node was suppressed, process the change. */
7944 bgp_process(bgp
, dest
, afi
, safi
);
7946 if (aggregate
->as_set
) {
7947 aspath_free(aggregate
->aspath
);
7948 aggregate
->aspath
= NULL
;
7949 if (aggregate
->community
)
7950 community_free(&aggregate
->community
);
7951 if (aggregate
->ecommunity
)
7952 ecommunity_free(&aggregate
->ecommunity
);
7953 if (aggregate
->lcommunity
)
7954 lcommunity_free(&aggregate
->lcommunity
);
7957 bgp_dest_unlock_node(top
);
7960 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7961 const struct prefix
*aggr_p
,
7962 struct bgp_path_info
*pinew
, afi_t afi
,
7964 struct bgp_aggregate
*aggregate
)
7967 struct aspath
*aspath
= NULL
;
7968 uint8_t atomic_aggregate
= 0;
7969 struct community
*community
= NULL
;
7970 struct ecommunity
*ecommunity
= NULL
;
7971 struct lcommunity
*lcommunity
= NULL
;
7973 /* If the bgp instance is being deleted or self peer is deleted
7974 * then do not create aggregate route
7976 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7977 || (bgp
->peer_self
== NULL
))
7980 /* ORIGIN attribute: If at least one route among routes that are
7981 * aggregated has ORIGIN with the value INCOMPLETE, then the
7982 * aggregated route must have the ORIGIN attribute with the value
7983 * INCOMPLETE. Otherwise, if at least one route among routes that
7984 * are aggregated has ORIGIN with the value EGP, then the aggregated
7985 * route must have the origin attribute with the value EGP. In all
7986 * other case the value of the ORIGIN attribute of the aggregated
7987 * route is INTERNAL.
7989 origin
= BGP_ORIGIN_IGP
;
7994 * This must be called before `summary` check to avoid
7995 * "suppressing" twice.
7997 if (aggregate
->match_med
)
7998 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
8001 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8002 aggr_suppress_path(aggregate
, pinew
);
8004 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8005 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
8006 aggr_suppress_path(aggregate
, pinew
);
8008 switch (pinew
->attr
->origin
) {
8009 case BGP_ORIGIN_INCOMPLETE
:
8010 aggregate
->incomplete_origin_count
++;
8012 case BGP_ORIGIN_EGP
:
8013 aggregate
->egp_origin_count
++;
8021 if (aggregate
->incomplete_origin_count
> 0)
8022 origin
= BGP_ORIGIN_INCOMPLETE
;
8023 else if (aggregate
->egp_origin_count
> 0)
8024 origin
= BGP_ORIGIN_EGP
;
8026 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8027 origin
= aggregate
->origin
;
8029 if (aggregate
->as_set
) {
8030 /* Compute aggregate route's as-path.
8032 bgp_compute_aggregate_aspath(aggregate
,
8033 pinew
->attr
->aspath
);
8035 /* Compute aggregate route's community.
8037 if (bgp_attr_get_community(pinew
->attr
))
8038 bgp_compute_aggregate_community(
8039 aggregate
, bgp_attr_get_community(pinew
->attr
));
8041 /* Compute aggregate route's extended community.
8043 if (bgp_attr_get_ecommunity(pinew
->attr
))
8044 bgp_compute_aggregate_ecommunity(
8046 bgp_attr_get_ecommunity(pinew
->attr
));
8048 /* Compute aggregate route's large community.
8050 if (bgp_attr_get_lcommunity(pinew
->attr
))
8051 bgp_compute_aggregate_lcommunity(
8053 bgp_attr_get_lcommunity(pinew
->attr
));
8055 /* Retrieve aggregate route's as-path.
8057 if (aggregate
->aspath
)
8058 aspath
= aspath_dup(aggregate
->aspath
);
8060 /* Retrieve aggregate route's community.
8062 if (aggregate
->community
)
8063 community
= community_dup(aggregate
->community
);
8065 /* Retrieve aggregate route's ecommunity.
8067 if (aggregate
->ecommunity
)
8068 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8070 /* Retrieve aggregate route's lcommunity.
8072 if (aggregate
->lcommunity
)
8073 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8076 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8077 aspath
, community
, ecommunity
,
8078 lcommunity
, atomic_aggregate
, aggregate
);
8081 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
8083 struct bgp_path_info
*pi
,
8084 struct bgp_aggregate
*aggregate
,
8085 const struct prefix
*aggr_p
)
8088 struct aspath
*aspath
= NULL
;
8089 uint8_t atomic_aggregate
= 0;
8090 struct community
*community
= NULL
;
8091 struct ecommunity
*ecommunity
= NULL
;
8092 struct lcommunity
*lcommunity
= NULL
;
8093 unsigned long match
= 0;
8095 /* If the bgp instance is being deleted or self peer is deleted
8096 * then do not create aggregate route
8098 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
8099 || (bgp
->peer_self
== NULL
))
8102 if (BGP_PATH_HOLDDOWN(pi
))
8105 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
8108 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
8109 if (aggr_unsuppress_path(aggregate
, pi
))
8112 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
8113 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
8114 if (aggr_unsuppress_path(aggregate
, pi
))
8118 * This must be called after `summary`, `suppress-map` check to avoid
8119 * "unsuppressing" twice.
8121 if (aggregate
->match_med
)
8122 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
);
8124 if (aggregate
->count
> 0)
8127 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
8128 aggregate
->incomplete_origin_count
--;
8129 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
8130 aggregate
->egp_origin_count
--;
8132 if (aggregate
->as_set
) {
8133 /* Remove as-path from aggregate.
8135 bgp_remove_aspath_from_aggregate(aggregate
,
8138 if (bgp_attr_get_community(pi
->attr
))
8139 /* Remove community from aggregate.
8141 bgp_remove_community_from_aggregate(
8142 aggregate
, bgp_attr_get_community(pi
->attr
));
8144 if (bgp_attr_get_ecommunity(pi
->attr
))
8145 /* Remove ecommunity from aggregate.
8147 bgp_remove_ecommunity_from_aggregate(
8148 aggregate
, bgp_attr_get_ecommunity(pi
->attr
));
8150 if (bgp_attr_get_lcommunity(pi
->attr
))
8151 /* Remove lcommunity from aggregate.
8153 bgp_remove_lcommunity_from_aggregate(
8154 aggregate
, bgp_attr_get_lcommunity(pi
->attr
));
8157 /* If this node was suppressed, process the change. */
8159 bgp_process(bgp
, pi
->net
, afi
, safi
);
8161 origin
= BGP_ORIGIN_IGP
;
8162 if (aggregate
->incomplete_origin_count
> 0)
8163 origin
= BGP_ORIGIN_INCOMPLETE
;
8164 else if (aggregate
->egp_origin_count
> 0)
8165 origin
= BGP_ORIGIN_EGP
;
8167 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
8168 origin
= aggregate
->origin
;
8170 if (aggregate
->as_set
) {
8171 /* Retrieve aggregate route's as-path.
8173 if (aggregate
->aspath
)
8174 aspath
= aspath_dup(aggregate
->aspath
);
8176 /* Retrieve aggregate route's community.
8178 if (aggregate
->community
)
8179 community
= community_dup(aggregate
->community
);
8181 /* Retrieve aggregate route's ecommunity.
8183 if (aggregate
->ecommunity
)
8184 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
8186 /* Retrieve aggregate route's lcommunity.
8188 if (aggregate
->lcommunity
)
8189 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
8192 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
8193 aspath
, community
, ecommunity
,
8194 lcommunity
, atomic_aggregate
, aggregate
);
8197 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
8198 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
8200 struct bgp_dest
*child
;
8201 struct bgp_dest
*dest
;
8202 struct bgp_aggregate
*aggregate
;
8203 struct bgp_table
*table
;
8205 table
= bgp
->aggregate
[afi
][safi
];
8207 /* No aggregates configured. */
8208 if (bgp_table_top_nolock(table
) == NULL
)
8211 if (p
->prefixlen
== 0)
8214 if (BGP_PATH_HOLDDOWN(pi
))
8217 /* If suppress fib is enabled and route not installed
8218 * in FIB, do not update the aggregate route
8220 if (!bgp_check_advertise(bgp
, pi
->net
))
8223 child
= bgp_node_get(table
, p
);
8225 /* Aggregate address configuration check. */
8226 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8227 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8229 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8230 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8231 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
8235 bgp_dest_unlock_node(child
);
8238 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
8239 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
8241 struct bgp_dest
*child
;
8242 struct bgp_dest
*dest
;
8243 struct bgp_aggregate
*aggregate
;
8244 struct bgp_table
*table
;
8246 table
= bgp
->aggregate
[afi
][safi
];
8248 /* No aggregates configured. */
8249 if (bgp_table_top_nolock(table
) == NULL
)
8252 if (p
->prefixlen
== 0)
8255 child
= bgp_node_get(table
, p
);
8257 /* Aggregate address configuration check. */
8258 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
8259 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
8261 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8262 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
8263 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
8267 bgp_dest_unlock_node(child
);
8270 /* Aggregate route attribute. */
8271 #define AGGREGATE_SUMMARY_ONLY 1
8272 #define AGGREGATE_AS_SET 1
8273 #define AGGREGATE_AS_UNSET 0
8275 static const char *bgp_origin2str(uint8_t origin
)
8278 case BGP_ORIGIN_IGP
:
8280 case BGP_ORIGIN_EGP
:
8282 case BGP_ORIGIN_INCOMPLETE
:
8283 return "incomplete";
8288 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
8291 case RPKI_NOT_BEING_USED
:
8301 assert(!"We should never get here this is a dev escape");
8305 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
8306 afi_t afi
, safi_t safi
)
8308 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8311 struct bgp_dest
*dest
;
8312 struct bgp_aggregate
*aggregate
;
8314 /* Convert string to prefix structure. */
8315 ret
= str2prefix(prefix_str
, &p
);
8317 vty_out(vty
, "Malformed prefix\n");
8318 return CMD_WARNING_CONFIG_FAILED
;
8322 /* Old configuration check. */
8323 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
8326 "%% There is no aggregate-address configuration.\n");
8327 return CMD_WARNING_CONFIG_FAILED
;
8330 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8331 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
8332 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
8333 NULL
, NULL
, 0, aggregate
);
8335 /* Unlock aggregate address configuration. */
8336 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
8338 if (aggregate
->community
)
8339 community_free(&aggregate
->community
);
8341 hash_clean_and_free(&aggregate
->community_hash
,
8342 bgp_aggr_community_remove
);
8344 if (aggregate
->ecommunity
)
8345 ecommunity_free(&aggregate
->ecommunity
);
8347 hash_clean_and_free(&aggregate
->ecommunity_hash
,
8348 bgp_aggr_ecommunity_remove
);
8350 if (aggregate
->lcommunity
)
8351 lcommunity_free(&aggregate
->lcommunity
);
8353 hash_clean_and_free(&aggregate
->lcommunity_hash
,
8354 bgp_aggr_lcommunity_remove
);
8356 if (aggregate
->aspath
)
8357 aspath_free(aggregate
->aspath
);
8359 hash_clean_and_free(&aggregate
->aspath_hash
, bgp_aggr_aspath_remove
);
8361 bgp_aggregate_free(aggregate
);
8362 bgp_dest_unlock_node(dest
);
8363 bgp_dest_unlock_node(dest
);
8368 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
8369 safi_t safi
, const char *rmap
,
8370 uint8_t summary_only
, uint8_t as_set
,
8371 uint8_t origin
, bool match_med
,
8372 const char *suppress_map
)
8374 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
8377 struct bgp_dest
*dest
;
8378 struct bgp_aggregate
*aggregate
;
8379 uint8_t as_set_new
= as_set
;
8381 if (suppress_map
&& summary_only
) {
8383 "'summary-only' and 'suppress-map' can't be used at the same time\n");
8384 return CMD_WARNING_CONFIG_FAILED
;
8387 /* Convert string to prefix structure. */
8388 ret
= str2prefix(prefix_str
, &p
);
8390 vty_out(vty
, "Malformed prefix\n");
8391 return CMD_WARNING_CONFIG_FAILED
;
8395 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
8396 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
8397 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8399 return CMD_WARNING_CONFIG_FAILED
;
8402 /* Old configuration check. */
8403 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
8404 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
8407 vty_out(vty
, "There is already same aggregate network.\n");
8408 /* try to remove the old entry */
8409 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
8411 vty_out(vty
, "Error deleting aggregate.\n");
8412 bgp_dest_unlock_node(dest
);
8413 return CMD_WARNING_CONFIG_FAILED
;
8417 /* Make aggregate address structure. */
8418 aggregate
= bgp_aggregate_new();
8419 aggregate
->summary_only
= summary_only
;
8420 aggregate
->match_med
= match_med
;
8422 /* Network operators MUST NOT locally generate any new
8423 * announcements containing AS_SET or AS_CONFED_SET. If they have
8424 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8425 * SHOULD withdraw those routes and re-announce routes for the
8426 * aggregate or component prefixes (i.e., the more-specific routes
8427 * subsumed by the previously aggregated route) without AS_SET
8428 * or AS_CONFED_SET in the updates.
8430 if (bgp
->reject_as_sets
) {
8431 if (as_set
== AGGREGATE_AS_SET
) {
8432 as_set_new
= AGGREGATE_AS_UNSET
;
8434 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8437 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8441 aggregate
->as_set
= as_set_new
;
8442 aggregate
->safi
= safi
;
8443 /* Override ORIGIN attribute if defined.
8444 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8445 * to IGP which is not what rfc4271 says.
8446 * This enables the same behavior, optionally.
8448 aggregate
->origin
= origin
;
8451 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
8452 route_map_counter_decrement(aggregate
->rmap
.map
);
8453 aggregate
->rmap
.name
=
8454 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
8455 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
8456 route_map_counter_increment(aggregate
->rmap
.map
);
8460 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
8461 route_map_counter_decrement(aggregate
->suppress_map
);
8463 aggregate
->suppress_map_name
=
8464 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
8465 aggregate
->suppress_map
=
8466 route_map_lookup_by_name(aggregate
->suppress_map_name
);
8467 route_map_counter_increment(aggregate
->suppress_map
);
8470 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
8472 /* Aggregate address insert into BGP routing table. */
8473 if (!bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
)) {
8474 bgp_aggregate_free(aggregate
);
8475 bgp_dest_unlock_node(dest
);
8481 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
8482 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8484 "|summary-only$summary_only"
8485 "|route-map RMAP_NAME$rmap_name"
8486 "|origin <egp|igp|incomplete>$origin_s"
8487 "|matching-MED-only$match_med"
8488 "|suppress-map RMAP_NAME$suppress_map"
8491 "Configure BGP aggregate entries\n"
8492 "Aggregate prefix\n"
8493 "Aggregate address\n"
8495 "Generate AS set path information\n"
8496 "Filter more specific routes from updates\n"
8497 "Apply route map to aggregate network\n"
8502 "Unknown heritage\n"
8503 "Only aggregate routes with matching MED\n"
8504 "Suppress the selected more specific routes\n"
8505 "Route map with the route selectors\n")
8507 const char *prefix_s
= NULL
;
8508 safi_t safi
= bgp_node_safi(vty
);
8509 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8510 int as_set
= AGGREGATE_AS_UNSET
;
8511 char prefix_buf
[PREFIX2STR_BUFFER
];
8514 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
8517 vty_out(vty
, "%% Inconsistent address and mask\n");
8518 return CMD_WARNING_CONFIG_FAILED
;
8520 prefix_s
= prefix_buf
;
8522 prefix_s
= prefix_str
;
8525 if (strcmp(origin_s
, "egp") == 0)
8526 origin
= BGP_ORIGIN_EGP
;
8527 else if (strcmp(origin_s
, "igp") == 0)
8528 origin
= BGP_ORIGIN_IGP
;
8529 else if (strcmp(origin_s
, "incomplete") == 0)
8530 origin
= BGP_ORIGIN_INCOMPLETE
;
8534 as_set
= AGGREGATE_AS_SET
;
8536 /* Handle configuration removal, otherwise installation. */
8538 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
8540 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
8541 summary_only
!= NULL
, as_set
, origin
,
8542 match_med
!= NULL
, suppress_map
);
8545 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
8546 "[no] aggregate-address X:X::X:X/M$prefix [{"
8548 "|summary-only$summary_only"
8549 "|route-map RMAP_NAME$rmap_name"
8550 "|origin <egp|igp|incomplete>$origin_s"
8551 "|matching-MED-only$match_med"
8552 "|suppress-map RMAP_NAME$suppress_map"
8555 "Configure BGP aggregate entries\n"
8556 "Aggregate prefix\n"
8557 "Generate AS set path information\n"
8558 "Filter more specific routes from updates\n"
8559 "Apply route map to aggregate network\n"
8564 "Unknown heritage\n"
8565 "Only aggregate routes with matching MED\n"
8566 "Suppress the selected more specific routes\n"
8567 "Route map with the route selectors\n")
8569 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
8570 int as_set
= AGGREGATE_AS_UNSET
;
8573 if (strcmp(origin_s
, "egp") == 0)
8574 origin
= BGP_ORIGIN_EGP
;
8575 else if (strcmp(origin_s
, "igp") == 0)
8576 origin
= BGP_ORIGIN_IGP
;
8577 else if (strcmp(origin_s
, "incomplete") == 0)
8578 origin
= BGP_ORIGIN_INCOMPLETE
;
8582 as_set
= AGGREGATE_AS_SET
;
8584 /* Handle configuration removal, otherwise installation. */
8586 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
8589 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
8590 rmap_name
, summary_only
!= NULL
, as_set
,
8591 origin
, match_med
!= NULL
, suppress_map
);
8594 /* Redistribute route treatment. */
8595 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
8596 const union g_addr
*nexthop
, ifindex_t ifindex
,
8597 enum nexthop_types_t nhtype
, uint8_t distance
,
8598 enum blackhole_type bhtype
, uint32_t metric
,
8599 uint8_t type
, unsigned short instance
,
8602 struct bgp_path_info
*new;
8603 struct bgp_path_info
*bpi
;
8604 struct bgp_path_info rmap_path
;
8605 struct bgp_dest
*bn
;
8607 struct attr
*new_attr
;
8609 route_map_result_t ret
;
8610 struct bgp_redist
*red
;
8612 /* Make default attribute. */
8613 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
8615 * This must not be NULL to satisfy Coverity SA
8617 assert(attr
.aspath
);
8620 case NEXTHOP_TYPE_IFINDEX
:
8621 switch (p
->family
) {
8623 attr
.nexthop
.s_addr
= INADDR_ANY
;
8624 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8627 memset(&attr
.mp_nexthop_global
, 0,
8628 sizeof(attr
.mp_nexthop_global
));
8629 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8633 case NEXTHOP_TYPE_IPV4
:
8634 case NEXTHOP_TYPE_IPV4_IFINDEX
:
8635 attr
.nexthop
= nexthop
->ipv4
;
8636 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8638 case NEXTHOP_TYPE_IPV6
:
8639 case NEXTHOP_TYPE_IPV6_IFINDEX
:
8640 attr
.mp_nexthop_global
= nexthop
->ipv6
;
8641 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8643 case NEXTHOP_TYPE_BLACKHOLE
:
8644 switch (p
->family
) {
8646 attr
.nexthop
.s_addr
= INADDR_ANY
;
8647 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
8650 memset(&attr
.mp_nexthop_global
, 0,
8651 sizeof(attr
.mp_nexthop_global
));
8652 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8655 attr
.bh_type
= bhtype
;
8658 attr
.nh_type
= nhtype
;
8659 attr
.nh_ifindex
= ifindex
;
8662 attr
.distance
= distance
;
8663 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8667 bgp_attr_set_aigp_metric(&attr
, metric
);
8669 afi
= family2afi(p
->family
);
8671 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8673 struct attr attr_new
;
8675 /* Copy attribute for modification. */
8678 if (red
->redist_metric_flag
) {
8679 attr_new
.med
= red
->redist_metric
;
8680 bgp_attr_set_aigp_metric(&attr_new
, red
->redist_metric
);
8683 /* Apply route-map. */
8684 if (red
->rmap
.name
) {
8685 memset(&rmap_path
, 0, sizeof(rmap_path
));
8686 rmap_path
.peer
= bgp
->peer_self
;
8687 rmap_path
.attr
= &attr_new
;
8689 SET_FLAG(bgp
->peer_self
->rmap_type
,
8690 PEER_RMAP_TYPE_REDISTRIBUTE
);
8692 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8694 bgp
->peer_self
->rmap_type
= 0;
8696 if (ret
== RMAP_DENYMATCH
) {
8697 /* Free uninterned attribute. */
8698 bgp_attr_flush(&attr_new
);
8700 /* Unintern original. */
8701 aspath_unintern(&attr
.aspath
);
8702 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8707 if (bgp_in_graceful_shutdown(bgp
))
8708 bgp_attr_add_gshut_community(&attr_new
);
8710 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8711 SAFI_UNICAST
, p
, NULL
);
8713 new_attr
= bgp_attr_intern(&attr_new
);
8715 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8716 if (bpi
->peer
== bgp
->peer_self
8717 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8721 /* Ensure the (source route) type is updated. */
8723 if (attrhash_cmp(bpi
->attr
, new_attr
)
8724 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8725 bgp_attr_unintern(&new_attr
);
8726 aspath_unintern(&attr
.aspath
);
8727 bgp_dest_unlock_node(bn
);
8730 /* The attribute is changed. */
8731 bgp_path_info_set_flag(bn
, bpi
,
8732 BGP_PATH_ATTR_CHANGED
);
8734 /* Rewrite BGP route information. */
8735 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8736 bgp_path_info_restore(bn
, bpi
);
8738 bgp_aggregate_decrement(
8739 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8740 bgp_attr_unintern(&bpi
->attr
);
8741 bpi
->attr
= new_attr
;
8742 bpi
->uptime
= monotime(NULL
);
8744 /* Process change. */
8745 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8747 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8748 bgp_dest_unlock_node(bn
);
8749 aspath_unintern(&attr
.aspath
);
8751 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8753 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8755 vpn_leak_from_vrf_update(
8756 bgp_get_default(), bgp
, bpi
);
8762 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8763 bgp
->peer_self
, new_attr
, bn
);
8764 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8766 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8767 bgp_path_info_add(bn
, new);
8768 bgp_dest_unlock_node(bn
);
8769 SET_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
);
8770 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8772 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8773 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8775 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8779 /* Unintern original. */
8780 aspath_unintern(&attr
.aspath
);
8783 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8784 unsigned short instance
)
8787 struct bgp_dest
*dest
;
8788 struct bgp_path_info
*pi
;
8789 struct bgp_redist
*red
;
8791 afi
= family2afi(p
->family
);
8793 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8795 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8796 SAFI_UNICAST
, p
, NULL
);
8798 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8799 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8803 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8804 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8806 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8809 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8810 bgp_path_info_delete(dest
, pi
);
8811 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8813 bgp_dest_unlock_node(dest
);
8817 /* Withdraw specified route type's route. */
8818 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8819 unsigned short instance
)
8821 struct bgp_dest
*dest
;
8822 struct bgp_path_info
*pi
;
8823 struct bgp_table
*table
;
8825 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8827 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8828 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8829 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8830 && pi
->instance
== instance
)
8834 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8835 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8837 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8840 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8841 pi
, afi
, SAFI_UNICAST
);
8842 bgp_path_info_delete(dest
, pi
);
8843 if (!CHECK_FLAG(bgp
->flags
,
8844 BGP_FLAG_DELETE_IN_PROGRESS
))
8845 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8847 bgp_path_info_reap(dest
, pi
);
8852 /* Static function to display route. */
8853 static void route_vty_out_route(struct bgp_dest
*dest
, const struct prefix
*p
,
8854 struct vty
*vty
, json_object
*json
, bool wide
)
8857 char buf
[INET6_ADDRSTRLEN
];
8859 if (p
->family
== AF_INET
) {
8861 len
= vty_out(vty
, "%pFX", p
);
8863 json_object_string_add(json
, "prefix",
8864 inet_ntop(p
->family
,
8867 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8868 json_object_string_addf(json
, "network", "%pFX", p
);
8869 json_object_int_add(json
, "version", dest
->version
);
8871 } else if (p
->family
== AF_ETHERNET
) {
8872 len
= vty_out(vty
, "%pFX", p
);
8873 } else if (p
->family
== AF_EVPN
) {
8875 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8877 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8878 } else if (p
->family
== AF_FLOWSPEC
) {
8879 route_vty_out_flowspec(vty
, p
, NULL
,
8881 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8882 NLRI_STRING_FORMAT_MIN
, json
);
8885 len
= vty_out(vty
, "%pFX", p
);
8887 json_object_string_add(json
, "prefix",
8888 inet_ntop(p
->family
,
8891 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8892 json_object_string_addf(json
, "network", "%pFX", p
);
8893 json_object_int_add(json
, "version", dest
->version
);
8898 len
= wide
? (45 - len
) : (17 - len
);
8900 vty_out(vty
, "\n%*s", 20, " ");
8902 vty_out(vty
, "%*s", len
, " ");
8906 enum bgp_display_type
{
8910 const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8913 case bgp_path_selection_none
:
8914 return "Nothing to Select";
8915 case bgp_path_selection_first
:
8916 return "First path received";
8917 case bgp_path_selection_evpn_sticky_mac
:
8918 return "EVPN Sticky Mac";
8919 case bgp_path_selection_evpn_seq
:
8920 return "EVPN sequence number";
8921 case bgp_path_selection_evpn_lower_ip
:
8922 return "EVPN lower IP";
8923 case bgp_path_selection_evpn_local_path
:
8924 return "EVPN local ES path";
8925 case bgp_path_selection_evpn_non_proxy
:
8926 return "EVPN non proxy";
8927 case bgp_path_selection_weight
:
8929 case bgp_path_selection_local_pref
:
8930 return "Local Pref";
8931 case bgp_path_selection_accept_own
:
8932 return "Accept Own";
8933 case bgp_path_selection_local_route
:
8934 return "Local Route";
8935 case bgp_path_selection_aigp
:
8937 case bgp_path_selection_confed_as_path
:
8938 return "Confederation based AS Path";
8939 case bgp_path_selection_as_path
:
8941 case bgp_path_selection_origin
:
8943 case bgp_path_selection_med
:
8945 case bgp_path_selection_peer
:
8947 case bgp_path_selection_confed
:
8948 return "Confed Peer Type";
8949 case bgp_path_selection_igp_metric
:
8950 return "IGP Metric";
8951 case bgp_path_selection_older
:
8952 return "Older Path";
8953 case bgp_path_selection_router_id
:
8955 case bgp_path_selection_cluster_length
:
8956 return "Cluster length";
8957 case bgp_path_selection_stale
:
8958 return "Path Staleness";
8959 case bgp_path_selection_local_configured
:
8960 return "Locally configured route";
8961 case bgp_path_selection_neighbor_ip
:
8962 return "Neighbor IP";
8963 case bgp_path_selection_default
:
8964 return "Nothing left to compare";
8966 return "Invalid (internal error)";
8969 /* Print the short form route status for a bgp_path_info */
8970 static void route_vty_short_status_out(struct vty
*vty
,
8971 struct bgp_path_info
*path
,
8972 const struct prefix
*p
,
8973 json_object
*json_path
)
8975 enum rpki_states rpki_state
= RPKI_NOT_BEING_USED
;
8979 /* Route status display. */
8980 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8981 json_object_boolean_true_add(json_path
, "removed");
8983 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8984 json_object_boolean_true_add(json_path
, "stale");
8986 if (path
->extra
&& bgp_path_suppressed(path
))
8987 json_object_boolean_true_add(json_path
, "suppressed");
8989 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8990 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8991 json_object_boolean_true_add(json_path
, "valid");
8994 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8995 json_object_boolean_true_add(json_path
, "history");
8997 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8998 json_object_boolean_true_add(json_path
, "damped");
9000 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9001 json_object_boolean_true_add(json_path
, "bestpath");
9002 json_object_string_add(json_path
, "selectionReason",
9003 bgp_path_selection_reason2str(
9004 path
->net
->reason
));
9007 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9008 json_object_boolean_true_add(json_path
, "multipath");
9010 /* Internal route. */
9011 if ((path
->peer
->as
)
9012 && (path
->peer
->as
== path
->peer
->local_as
))
9013 json_object_string_add(json_path
, "pathFrom",
9016 json_object_string_add(json_path
, "pathFrom",
9022 /* RPKI validation state */
9024 hook_call(bgp_rpki_prefix_status
, path
->peer
, path
->attr
, p
);
9026 if (rpki_state
== RPKI_VALID
)
9028 else if (rpki_state
== RPKI_INVALID
)
9030 else if (rpki_state
== RPKI_NOTFOUND
)
9035 /* Route status display. */
9036 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
9038 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
9040 else if (bgp_path_suppressed(path
))
9042 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
9043 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9049 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
9051 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
9053 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
9055 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
9060 /* Internal route. */
9061 if (path
->peer
&& (path
->peer
->as
)
9062 && (path
->peer
->as
== path
->peer
->local_as
))
9068 static char *bgp_nexthop_hostname(struct peer
*peer
,
9069 struct bgp_nexthop_cache
*bnc
)
9072 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
9073 return peer
->hostname
;
9077 /* called from terminal list command */
9078 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9079 struct bgp_path_info
*path
, int display
, safi_t safi
,
9080 json_object
*json_paths
, bool wide
)
9083 struct attr
*attr
= path
->attr
;
9084 json_object
*json_path
= NULL
;
9085 json_object
*json_nexthops
= NULL
;
9086 json_object
*json_nexthop_global
= NULL
;
9087 json_object
*json_nexthop_ll
= NULL
;
9088 json_object
*json_ext_community
= NULL
;
9089 char vrf_id_str
[VRF_NAMSIZ
] = {0};
9091 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9092 bool nexthop_othervrf
= false;
9093 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
9094 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
9095 char *nexthop_hostname
=
9096 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9097 char esi_buf
[ESI_STR_LEN
];
9100 json_path
= json_object_new_object();
9102 /* short status lead text */
9103 route_vty_short_status_out(vty
, path
, p
, json_path
);
9106 /* print prefix and mask */
9108 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9110 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
9112 route_vty_out_route(path
->net
, p
, vty
, json_path
, wide
);
9116 * If vrf id of nexthop is different from that of prefix,
9117 * set up printable string to append
9119 if (path
->extra
&& path
->extra
->bgp_orig
) {
9120 const char *self
= "";
9125 nexthop_othervrf
= true;
9126 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9128 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
9129 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
9130 "@%s%s", VRFID_NONE_STR
, self
);
9132 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
9133 path
->extra
->bgp_orig
->vrf_id
, self
);
9135 if (path
->extra
->bgp_orig
->inst_type
9136 != BGP_INSTANCE_TYPE_DEFAULT
)
9138 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
9140 const char *self
= "";
9145 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
9149 * For ENCAP and EVPN routes, nexthop address family is not
9150 * neccessarily the same as the prefix address family.
9151 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9152 * EVPN routes are also exchanged with a MP nexthop. Currently,
9154 * is only IPv4, the value will be present in either
9156 * attr->mp_nexthop_global_in
9158 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
9160 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9164 snprintfrr(nexthop
, sizeof(nexthop
), "%pI4",
9165 &attr
->mp_nexthop_global_in
);
9168 snprintfrr(nexthop
, sizeof(nexthop
), "%pI6",
9169 &attr
->mp_nexthop_global
);
9172 snprintf(nexthop
, sizeof(nexthop
), "?");
9177 json_nexthop_global
= json_object_new_object();
9179 json_object_string_add(json_nexthop_global
, "ip",
9182 if (path
->peer
->hostname
)
9183 json_object_string_add(json_nexthop_global
,
9185 path
->peer
->hostname
);
9187 json_object_string_add(json_nexthop_global
, "afi",
9188 (af
== AF_INET
) ? "ipv4"
9190 json_object_boolean_true_add(json_nexthop_global
,
9193 if (nexthop_hostname
)
9194 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
9195 nexthop_hostname
, vrf_id_str
);
9197 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
9199 len
= wide
? (41 - len
) : (16 - len
);
9201 vty_out(vty
, "\n%*s", 36, " ");
9203 vty_out(vty
, "%*s", len
, " ");
9205 } else if (safi
== SAFI_EVPN
) {
9207 json_nexthop_global
= json_object_new_object();
9209 json_object_string_addf(json_nexthop_global
, "ip",
9211 &attr
->mp_nexthop_global_in
);
9213 if (path
->peer
->hostname
)
9214 json_object_string_add(json_nexthop_global
,
9216 path
->peer
->hostname
);
9218 json_object_string_add(json_nexthop_global
, "afi",
9220 json_object_boolean_true_add(json_nexthop_global
,
9223 if (nexthop_hostname
)
9224 len
= vty_out(vty
, "%pI4(%s)%s",
9225 &attr
->mp_nexthop_global_in
,
9226 nexthop_hostname
, vrf_id_str
);
9228 len
= vty_out(vty
, "%pI4%s",
9229 &attr
->mp_nexthop_global_in
,
9232 len
= wide
? (41 - len
) : (16 - len
);
9234 vty_out(vty
, "\n%*s", 36, " ");
9236 vty_out(vty
, "%*s", len
, " ");
9238 } else if (safi
== SAFI_FLOWSPEC
) {
9239 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
9241 json_nexthop_global
= json_object_new_object();
9243 json_object_string_add(json_nexthop_global
,
9245 json_object_string_addf(json_nexthop_global
,
9249 if (path
->peer
->hostname
)
9250 json_object_string_add(
9251 json_nexthop_global
, "hostname",
9252 path
->peer
->hostname
);
9254 json_object_boolean_true_add(
9255 json_nexthop_global
,
9258 if (nexthop_hostname
)
9259 len
= vty_out(vty
, "%pI4(%s)%s",
9264 len
= vty_out(vty
, "%pI4%s",
9268 len
= wide
? (41 - len
) : (16 - len
);
9270 vty_out(vty
, "\n%*s", 36, " ");
9272 vty_out(vty
, "%*s", len
, " ");
9275 } else if (p
->family
== AF_INET
&& !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9277 json_nexthop_global
= json_object_new_object();
9279 json_object_string_addf(json_nexthop_global
, "ip",
9280 "%pI4", &attr
->nexthop
);
9282 if (path
->peer
->hostname
)
9283 json_object_string_add(json_nexthop_global
,
9285 path
->peer
->hostname
);
9287 json_object_string_add(json_nexthop_global
, "afi",
9289 json_object_boolean_true_add(json_nexthop_global
,
9292 if (nexthop_hostname
)
9293 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
9294 nexthop_hostname
, vrf_id_str
);
9296 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
9299 len
= wide
? (41 - len
) : (16 - len
);
9301 vty_out(vty
, "\n%*s", 36, " ");
9303 vty_out(vty
, "%*s", len
, " ");
9308 else if (p
->family
== AF_INET6
|| BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9310 json_nexthop_global
= json_object_new_object();
9311 json_object_string_addf(json_nexthop_global
, "ip",
9313 &attr
->mp_nexthop_global
);
9315 if (path
->peer
->hostname
)
9316 json_object_string_add(json_nexthop_global
,
9318 path
->peer
->hostname
);
9320 json_object_string_add(json_nexthop_global
, "afi",
9322 json_object_string_add(json_nexthop_global
, "scope",
9325 /* We display both LL & GL if both have been
9327 if ((attr
->mp_nexthop_len
9328 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9329 || (path
->peer
->conf_if
)) {
9330 json_nexthop_ll
= json_object_new_object();
9331 json_object_string_addf(
9332 json_nexthop_ll
, "ip", "%pI6",
9333 &attr
->mp_nexthop_local
);
9335 if (path
->peer
->hostname
)
9336 json_object_string_add(
9337 json_nexthop_ll
, "hostname",
9338 path
->peer
->hostname
);
9340 json_object_string_add(json_nexthop_ll
, "afi",
9342 json_object_string_add(json_nexthop_ll
, "scope",
9345 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
9346 &attr
->mp_nexthop_local
)
9348 && !attr
->mp_nexthop_prefer_global
)
9349 json_object_boolean_true_add(
9350 json_nexthop_ll
, "used");
9352 json_object_boolean_true_add(
9353 json_nexthop_global
, "used");
9355 json_object_boolean_true_add(
9356 json_nexthop_global
, "used");
9358 /* Display LL if LL/Global both in table unless
9359 * prefer-global is set */
9360 if (((attr
->mp_nexthop_len
9361 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
9362 && !attr
->mp_nexthop_prefer_global
)
9363 || (path
->peer
->conf_if
)) {
9364 if (path
->peer
->conf_if
) {
9365 len
= vty_out(vty
, "%s",
9366 path
->peer
->conf_if
);
9367 /* len of IPv6 addr + max len of def
9369 len
= wide
? (41 - len
) : (16 - len
);
9372 vty_out(vty
, "\n%*s", 36, " ");
9374 vty_out(vty
, "%*s", len
, " ");
9376 if (nexthop_hostname
)
9379 &attr
->mp_nexthop_local
,
9385 &attr
->mp_nexthop_local
,
9388 len
= wide
? (41 - len
) : (16 - len
);
9391 vty_out(vty
, "\n%*s", 36, " ");
9393 vty_out(vty
, "%*s", len
, " ");
9396 if (nexthop_hostname
)
9397 len
= vty_out(vty
, "%pI6(%s)%s",
9398 &attr
->mp_nexthop_global
,
9402 len
= vty_out(vty
, "%pI6%s",
9403 &attr
->mp_nexthop_global
,
9406 len
= wide
? (41 - len
) : (16 - len
);
9409 vty_out(vty
, "\n%*s", 36, " ");
9411 vty_out(vty
, "%*s", len
, " ");
9417 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9419 json_object_int_add(json_path
, "metric", attr
->med
);
9421 vty_out(vty
, "%7u", attr
->med
);
9423 vty_out(vty
, "%10u", attr
->med
);
9424 else if (!json_paths
) {
9426 vty_out(vty
, "%*s", 7, " ");
9428 vty_out(vty
, "%*s", 10, " ");
9432 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9434 json_object_int_add(json_path
, "locPrf",
9437 vty_out(vty
, "%7u", attr
->local_pref
);
9438 else if (!json_paths
)
9442 json_object_int_add(json_path
, "weight", attr
->weight
);
9444 vty_out(vty
, "%7u ", attr
->weight
);
9447 json_object_string_addf(json_path
, "peerId", "%pSU",
9453 json_object_string_add(json_path
, "path",
9456 aspath_print_vty(vty
, attr
->aspath
);
9461 json_object_string_add(json_path
, "origin",
9462 bgp_origin_long_str
[attr
->origin
]);
9464 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9467 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9468 json_object_string_add(json_path
, "esi",
9469 esi_to_str(&attr
->esi
,
9470 esi_buf
, sizeof(esi_buf
)));
9472 if (safi
== SAFI_EVPN
&&
9473 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9474 json_ext_community
= json_object_new_object();
9475 json_object_string_add(
9476 json_ext_community
, "string",
9477 bgp_attr_get_ecommunity(attr
)->str
);
9478 json_object_object_add(json_path
,
9479 "extendedCommunity",
9480 json_ext_community
);
9484 json_object_boolean_true_add(json_path
,
9485 "announceNexthopSelf");
9486 if (nexthop_othervrf
) {
9487 json_object_string_add(json_path
, "nhVrfName",
9490 json_object_int_add(json_path
, "nhVrfId",
9491 ((nexthop_vrfid
== VRF_UNKNOWN
)
9493 : (int)nexthop_vrfid
));
9498 if (json_nexthop_global
|| json_nexthop_ll
) {
9499 json_nexthops
= json_object_new_array();
9501 if (json_nexthop_global
)
9502 json_object_array_add(json_nexthops
,
9503 json_nexthop_global
);
9505 if (json_nexthop_ll
)
9506 json_object_array_add(json_nexthops
,
9509 json_object_object_add(json_path
, "nexthops",
9513 json_object_array_add(json_paths
, json_path
);
9517 if (safi
== SAFI_EVPN
) {
9518 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
9519 /* XXX - add these params to the json out */
9520 vty_out(vty
, "%*s", 20, " ");
9521 vty_out(vty
, "ESI:%s",
9522 esi_to_str(&attr
->esi
, esi_buf
,
9528 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9529 vty_out(vty
, "%*s", 20, " ");
9530 vty_out(vty
, "%s\n",
9531 bgp_attr_get_ecommunity(attr
)->str
);
9535 #ifdef ENABLE_BGP_VNC
9536 /* prints an additional line, indented, with VNC info, if
9538 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
9539 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
9544 /* called from terminal list command */
9545 void route_vty_out_tmp(struct vty
*vty
, struct bgp_dest
*dest
,
9546 const struct prefix
*p
, struct attr
*attr
, safi_t safi
,
9547 bool use_json
, json_object
*json_ar
, bool wide
)
9549 json_object
*json_status
= NULL
;
9550 json_object
*json_net
= NULL
;
9554 /* Route status display. */
9556 json_status
= json_object_new_object();
9557 json_net
= json_object_new_object();
9564 /* print prefix and mask */
9566 if (safi
== SAFI_EVPN
)
9567 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
9568 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
9569 json_object_string_add(
9570 json_net
, "addrPrefix",
9571 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
9573 json_object_int_add(json_net
, "prefixLen",
9575 json_object_string_addf(json_net
, "network", "%pFX", p
);
9578 route_vty_out_route(dest
, p
, vty
, NULL
, wide
);
9580 /* Print attribute */
9583 if (p
->family
== AF_INET
&&
9584 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9585 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9586 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9587 json_object_string_addf(
9588 json_net
, "nextHop", "%pI4",
9589 &attr
->mp_nexthop_global_in
);
9591 json_object_string_addf(
9592 json_net
, "nextHop", "%pI4",
9594 } else if (p
->family
== AF_INET6
||
9595 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9596 json_object_string_addf(
9597 json_net
, "nextHopGlobal", "%pI6",
9598 &attr
->mp_nexthop_global
);
9599 } else if (p
->family
== AF_EVPN
&&
9600 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9601 json_object_string_addf(
9602 json_net
, "nextHop", "%pI4",
9603 &attr
->mp_nexthop_global_in
);
9607 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9608 json_object_int_add(json_net
, "metric",
9611 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9612 json_object_int_add(json_net
, "locPrf",
9615 json_object_int_add(json_net
, "weight", attr
->weight
);
9619 json_object_string_add(json_net
, "path",
9623 #if CONFDATE > 20231208
9624 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9626 json_object_string_add(json_net
, "bgpOriginCode",
9627 bgp_origin_str
[attr
->origin
]);
9628 json_object_string_add(
9630 bgp_origin_long_str
[attr
->origin
]);
9632 if (p
->family
== AF_INET
&&
9633 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
||
9634 safi
== SAFI_EVPN
||
9635 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9636 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9637 || safi
== SAFI_EVPN
)
9638 vty_out(vty
, "%-16pI4",
9639 &attr
->mp_nexthop_global_in
);
9641 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9643 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9644 } else if (p
->family
== AF_INET6
||
9645 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) {
9646 len
= vty_out(vty
, "%pI6",
9647 &attr
->mp_nexthop_global
);
9648 len
= wide
? (41 - len
) : (16 - len
);
9650 vty_out(vty
, "\n%*s", 36, " ");
9652 vty_out(vty
, "%*s", len
, " ");
9655 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9657 vty_out(vty
, "%7u", attr
->med
);
9659 vty_out(vty
, "%10u", attr
->med
);
9665 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9666 vty_out(vty
, "%7u", attr
->local_pref
);
9670 vty_out(vty
, "%7u ", attr
->weight
);
9674 aspath_print_vty(vty
, attr
->aspath
);
9677 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9681 struct bgp_path_info
*bpi
= bgp_dest_get_bgp_path_info(dest
);
9683 #if CONFDATE > 20231208
9684 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9686 json_object_boolean_true_add(json_status
, "*");
9687 json_object_boolean_true_add(json_status
, ">");
9688 json_object_boolean_true_add(json_net
, "valid");
9689 json_object_boolean_true_add(json_net
, "best");
9691 if (bpi
&& CHECK_FLAG(bpi
->flags
, BGP_PATH_MULTIPATH
)) {
9692 json_object_boolean_true_add(json_status
, "=");
9693 json_object_boolean_true_add(json_net
, "multipath");
9695 json_object_object_add(json_net
, "appliedStatusSymbols",
9697 json_object_object_addf(json_ar
, json_net
, "%pFX", p
);
9702 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9703 struct bgp_path_info
*path
, int display
, safi_t safi
,
9706 json_object
*json_out
= NULL
;
9708 mpls_label_t label
= MPLS_INVALID_LABEL
;
9714 json_out
= json_object_new_object();
9716 /* short status lead text */
9717 route_vty_short_status_out(vty
, path
, p
, json_out
);
9719 /* print prefix and mask */
9722 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9724 vty_out(vty
, "%*s", 17, " ");
9727 /* Print attribute */
9729 if (((p
->family
== AF_INET
) &&
9730 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9731 (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) ||
9732 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9733 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9734 || safi
== SAFI_EVPN
) {
9736 json_object_string_addf(
9737 json_out
, "mpNexthopGlobalIn", "%pI4",
9738 &attr
->mp_nexthop_global_in
);
9740 vty_out(vty
, "%-16pI4",
9741 &attr
->mp_nexthop_global_in
);
9744 json_object_string_addf(json_out
, "nexthop",
9745 "%pI4", &attr
->nexthop
);
9747 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9749 } else if (((p
->family
== AF_INET6
) &&
9750 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
))) ||
9751 (safi
== SAFI_EVPN
&& BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
)) ||
9752 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
9755 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9757 json_object_string_addf(
9758 json_out
, "mpNexthopGlobalIn", "%pI6",
9759 &attr
->mp_nexthop_global
);
9763 &attr
->mp_nexthop_global
,
9764 buf_a
, sizeof(buf_a
)));
9765 } else if (attr
->mp_nexthop_len
9766 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9767 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9768 &attr
->mp_nexthop_global
,
9769 &attr
->mp_nexthop_local
);
9771 json_object_string_add(json_out
,
9772 "mpNexthopGlobalLocal",
9775 vty_out(vty
, "%s", buf_a
);
9779 label
= decode_label(&path
->extra
->label
[0]);
9781 if (bgp_is_valid_label(&label
)) {
9783 json_object_int_add(json_out
, "notag", label
);
9784 json_object_array_add(json
, json_out
);
9786 vty_out(vty
, "notag/%d", label
);
9793 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9794 struct bgp_path_info
*path
, int display
,
9795 json_object
*json_paths
)
9798 json_object
*json_path
= NULL
;
9799 json_object
*json_nexthop
= NULL
;
9800 json_object
*json_overlay
= NULL
;
9806 json_path
= json_object_new_object();
9807 json_overlay
= json_object_new_object();
9808 json_nexthop
= json_object_new_object();
9811 /* short status lead text */
9812 route_vty_short_status_out(vty
, path
, p
, json_path
);
9814 /* print prefix and mask */
9816 route_vty_out_route(path
->net
, p
, vty
, json_path
, false);
9818 vty_out(vty
, "%*s", 17, " ");
9820 /* Print attribute */
9822 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9827 vty_out(vty
, "%-16pI4", &attr
->mp_nexthop_global_in
);
9829 json_object_string_addf(json_nexthop
, "ip", "%pI4",
9830 &attr
->mp_nexthop_global_in
);
9832 json_object_string_add(json_nexthop
, "afi", "ipv4");
9834 json_object_object_add(json_path
, "nexthop",
9840 vty_out(vty
, "%pI6(%pI6)", &attr
->mp_nexthop_global
,
9841 &attr
->mp_nexthop_local
);
9843 json_object_string_addf(json_nexthop
, "ipv6Global",
9845 &attr
->mp_nexthop_global
);
9847 json_object_string_addf(json_nexthop
, "ipv6LinkLocal",
9849 &attr
->mp_nexthop_local
);
9851 json_object_string_add(json_nexthop
, "afi", "ipv6");
9853 json_object_object_add(json_path
, "nexthop",
9861 json_object_string_add(json_nexthop
, "error",
9862 "Unsupported address-family");
9866 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9869 vty_out(vty
, "/%pIA", &eo
->gw_ip
);
9871 json_object_string_addf(json_overlay
, "gw", "%pIA", &eo
->gw_ip
);
9873 if (bgp_attr_get_ecommunity(attr
)) {
9875 struct ecommunity_val
*routermac
= ecommunity_lookup(
9876 bgp_attr_get_ecommunity(attr
), ECOMMUNITY_ENCODE_EVPN
,
9877 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9880 mac
= ecom_mac2str((char *)routermac
->val
);
9883 vty_out(vty
, "/%s", mac
);
9885 json_object_string_add(json_overlay
, "rmac",
9888 XFREE(MTYPE_TMP
, mac
);
9895 json_object_object_add(json_path
, "overlay", json_overlay
);
9897 json_object_array_add(json_paths
, json_path
);
9901 /* dampening route */
9902 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9903 struct bgp_path_info
*path
, int display
,
9904 afi_t afi
, safi_t safi
, bool use_json
,
9905 json_object
*json_paths
)
9907 struct attr
*attr
= path
->attr
;
9909 char timebuf
[BGP_UPTIME_LEN
];
9910 json_object
*json_path
= NULL
;
9913 json_path
= json_object_new_object();
9915 /* short status lead text */
9916 route_vty_short_status_out(vty
, path
, p
, json_path
);
9918 /* print prefix and mask */
9921 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9923 vty_out(vty
, "%*s", 17, " ");
9925 len
= vty_out(vty
, "%s", path
->peer
->host
);
9929 vty_out(vty
, "\n%*s", 34, " ");
9931 vty_out(vty
, "%*s", len
, " ");
9934 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9935 BGP_UPTIME_LEN
, afi
, safi
,
9939 aspath_print_vty(vty
, attr
->aspath
);
9941 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9945 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9946 safi
, use_json
, json_path
);
9949 json_object_string_add(json_path
, "asPath",
9952 json_object_string_add(json_path
, "origin",
9953 bgp_origin_str
[attr
->origin
]);
9954 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
9956 json_object_array_add(json_paths
, json_path
);
9961 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9962 struct bgp_path_info
*path
, int display
,
9963 afi_t afi
, safi_t safi
, bool use_json
,
9964 json_object
*json_paths
)
9966 struct attr
*attr
= path
->attr
;
9967 struct bgp_damp_info
*bdi
;
9968 char timebuf
[BGP_UPTIME_LEN
];
9970 json_object
*json_path
= NULL
;
9976 json_path
= json_object_new_object();
9978 bdi
= path
->extra
->damp_info
;
9980 /* short status lead text */
9981 route_vty_short_status_out(vty
, path
, p
, json_path
);
9985 route_vty_out_route(path
->net
, p
, vty
, NULL
, false);
9987 vty_out(vty
, "%*s", 17, " ");
9989 len
= vty_out(vty
, "%s", path
->peer
->host
);
9992 vty_out(vty
, "\n%*s", 33, " ");
9994 vty_out(vty
, "%*s", len
, " ");
9996 len
= vty_out(vty
, "%d", bdi
->flap
);
10001 vty_out(vty
, "%*s", len
, " ");
10003 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
10004 BGP_UPTIME_LEN
, 0, NULL
));
10006 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10007 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10008 vty_out(vty
, "%s ",
10009 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10010 BGP_UPTIME_LEN
, afi
,
10011 safi
, use_json
, NULL
));
10013 vty_out(vty
, "%*s ", 8, " ");
10016 aspath_print_vty(vty
, attr
->aspath
);
10018 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
10020 vty_out(vty
, "\n");
10022 json_object_string_add(json_path
, "peerHost", path
->peer
->host
);
10023 json_object_int_add(json_path
, "bdiFlap", bdi
->flap
);
10025 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
10028 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
10029 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
10030 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
10031 BGP_UPTIME_LEN
, afi
, safi
,
10032 use_json
, json_path
);
10035 json_object_string_add(json_path
, "asPath",
10036 attr
->aspath
->str
);
10038 json_object_string_add(json_path
, "origin",
10039 bgp_origin_str
[attr
->origin
]);
10041 json_object_array_add(json_paths
, json_path
);
10045 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
10046 int *first
, const char *header
,
10047 json_object
*json_adv_to
)
10049 json_object
*json_peer
= NULL
;
10052 /* 'advertised-to' is a dictionary of peers we have advertised
10054 * prefix too. The key is the peer's IP or swpX, the value is
10056 * hostname if we know it and "" if not.
10058 json_peer
= json_object_new_object();
10060 if (peer
->hostname
)
10061 json_object_string_add(json_peer
, "hostname",
10065 json_object_object_add(json_adv_to
, peer
->conf_if
,
10068 json_object_object_addf(json_adv_to
, json_peer
, "%pSU",
10072 vty_out(vty
, "%s", header
);
10077 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
10079 vty_out(vty
, " %s(%s)", peer
->hostname
,
10082 vty_out(vty
, " %s(%pSU)", peer
->hostname
,
10086 vty_out(vty
, " %s", peer
->conf_if
);
10088 vty_out(vty
, " %pSU", &peer
->su
);
10093 static void route_vty_out_tx_ids(struct vty
*vty
,
10094 struct bgp_addpath_info_data
*d
)
10098 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10099 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
10100 d
->addpath_tx_id
[i
],
10101 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
10105 static void route_vty_out_detail_es_info(struct vty
*vty
,
10106 struct bgp_path_info
*pi
,
10108 json_object
*json_path
)
10110 char esi_buf
[ESI_STR_LEN
];
10111 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
10112 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
10113 ATTR_ES_PEER_ROUTER
);
10114 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
10115 ATTR_ES_PEER_ACTIVE
);
10116 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
10117 ATTR_ES_PEER_PROXY
);
10118 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
10120 json_object
*json_es_info
= NULL
;
10122 json_object_string_add(
10125 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
10126 json_es_info
= json_object_new_object();
10128 json_object_boolean_true_add(
10129 json_es_info
, "localEs");
10131 json_object_boolean_true_add(
10132 json_es_info
, "peerActive");
10134 json_object_boolean_true_add(
10135 json_es_info
, "peerProxy");
10137 json_object_boolean_true_add(
10138 json_es_info
, "peerRouter");
10139 if (attr
->mm_sync_seqnum
)
10140 json_object_int_add(
10141 json_es_info
, "peerSeq",
10142 attr
->mm_sync_seqnum
);
10143 json_object_object_add(
10144 json_path
, "es_info",
10148 if (bgp_evpn_attr_is_sync(attr
))
10150 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10152 es_local
? "local-es":"",
10153 peer_proxy
? "proxy " : "",
10154 peer_active
? "active ":"",
10155 peer_router
? "router ":"",
10156 attr
->mm_sync_seqnum
);
10158 vty_out(vty
, " ESI %s %s\n",
10160 es_local
? "local-es":"");
10164 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
10165 const struct prefix
*p
, struct bgp_path_info
*path
,
10166 afi_t afi
, safi_t safi
,
10167 enum rpki_states rpki_curr_state
,
10168 json_object
*json_paths
)
10170 char buf
[INET6_ADDRSTRLEN
];
10172 struct attr
*attr
= path
->attr
;
10174 json_object
*json_bestpath
= NULL
;
10175 json_object
*json_cluster_list
= NULL
;
10176 json_object
*json_cluster_list_list
= NULL
;
10177 json_object
*json_ext_community
= NULL
;
10178 json_object
*json_last_update
= NULL
;
10179 json_object
*json_pmsi
= NULL
;
10180 json_object
*json_nexthop_global
= NULL
;
10181 json_object
*json_nexthop_ll
= NULL
;
10182 json_object
*json_nexthops
= NULL
;
10183 json_object
*json_path
= NULL
;
10184 json_object
*json_peer
= NULL
;
10185 json_object
*json_string
= NULL
;
10186 json_object
*json_adv_to
= NULL
;
10188 struct listnode
*node
, *nnode
;
10190 bool addpath_capable
;
10192 unsigned int first_as
;
10193 bool nexthop_self
=
10194 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
10196 char *nexthop_hostname
=
10197 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
10201 mpls_label_t label
= MPLS_INVALID_LABEL
;
10203 struct bgp_path_info
*bpi_ultimate
=
10204 bgp_get_imported_bpi_ultimate(path
);
10207 json_path
= json_object_new_object();
10208 json_peer
= json_object_new_object();
10209 json_nexthop_global
= json_object_new_object();
10212 if (safi
== SAFI_EVPN
) {
10214 vty_out(vty
, " Route %pFX", p
);
10218 if (path
->extra
&& path
->extra
->num_labels
) {
10219 bgp_evpn_label2str(path
->extra
->label
,
10220 path
->extra
->num_labels
, tag_buf
,
10223 if (safi
== SAFI_EVPN
) {
10225 if (tag_buf
[0] != '\0')
10226 vty_out(vty
, " VNI %s", tag_buf
);
10229 json_object_string_add(json_path
, "vni",
10235 if (safi
== SAFI_EVPN
10236 && attr
->evpn_overlay
.type
== OVERLAY_INDEX_GATEWAY_IP
) {
10237 char gwip_buf
[INET6_ADDRSTRLEN
];
10239 ipaddr2str(&attr
->evpn_overlay
.gw_ip
, gwip_buf
,
10243 json_object_string_add(json_path
, "gatewayIP",
10246 vty_out(vty
, " Gateway IP %s", gwip_buf
);
10249 if (safi
== SAFI_EVPN
&& !json_path
)
10250 vty_out(vty
, "\n");
10253 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
10254 struct bgp_path_info
*parent_ri
;
10255 struct bgp_dest
*dest
, *pdest
;
10257 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
10258 dest
= parent_ri
->net
;
10259 if (dest
&& dest
->pdest
) {
10260 pdest
= dest
->pdest
;
10261 if (is_pi_family_evpn(parent_ri
)) {
10262 vty_out(vty
, " Imported from ");
10263 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
10264 (struct prefix_rd
*)bgp_dest_get_prefix(
10266 vty_out(vty
, ":%pFX, VNI %s",
10267 (struct prefix_evpn
*)
10268 bgp_dest_get_prefix(dest
),
10270 if (CHECK_FLAG(attr
->es_flags
, ATTR_ES_L3_NHG
))
10271 vty_out(vty
, ", L3NHG %s",
10274 ATTR_ES_L3_NHG_ACTIVE
)
10277 vty_out(vty
, "\n");
10280 vty_out(vty
, " Imported from ");
10281 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
10282 (struct prefix_rd
*)bgp_dest_get_prefix(
10284 vty_out(vty
, ":%pFX\n",
10285 (struct prefix_evpn
*)
10286 bgp_dest_get_prefix(dest
));
10291 /* Line1 display AS-path, Aggregator */
10292 if (attr
->aspath
) {
10294 if (!attr
->aspath
->json
)
10295 aspath_str_update(attr
->aspath
, true);
10296 json_object_lock(attr
->aspath
->json
);
10297 json_object_object_add(json_path
, "aspath",
10298 attr
->aspath
->json
);
10300 if (attr
->aspath
->segments
)
10301 vty_out(vty
, " %s", attr
->aspath
->str
);
10303 vty_out(vty
, " Local");
10307 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
10309 json_object_boolean_true_add(json_path
, "removed");
10311 vty_out(vty
, ", (removed)");
10314 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
10316 json_object_boolean_true_add(json_path
, "stale");
10318 vty_out(vty
, ", (stale)");
10321 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
10323 json_object_int_add(json_path
, "aggregatorAs",
10324 attr
->aggregator_as
);
10325 json_object_string_addf(json_path
, "aggregatorId",
10326 "%pI4", &attr
->aggregator_addr
);
10328 vty_out(vty
, ", (aggregated by %u %pI4)",
10329 attr
->aggregator_as
, &attr
->aggregator_addr
);
10333 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10334 PEER_FLAG_REFLECTOR_CLIENT
)) {
10336 json_object_boolean_true_add(json_path
,
10337 "rxedFromRrClient");
10339 vty_out(vty
, ", (Received from a RR-client)");
10342 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
10343 PEER_FLAG_RSERVER_CLIENT
)) {
10345 json_object_boolean_true_add(json_path
,
10346 "rxedFromRsClient");
10348 vty_out(vty
, ", (Received from a RS-client)");
10351 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10353 json_object_boolean_true_add(json_path
,
10354 "dampeningHistoryEntry");
10356 vty_out(vty
, ", (history entry)");
10357 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
10359 json_object_boolean_true_add(json_path
,
10360 "dampeningSuppressed");
10362 vty_out(vty
, ", (suppressed due to dampening)");
10366 vty_out(vty
, "\n");
10368 /* Line2 display Next-hop, Neighbor, Router-id */
10369 /* Display the nexthop */
10371 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
||
10372 p
->family
== AF_EVPN
) &&
10373 (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
||
10374 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10375 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
10376 || safi
== SAFI_EVPN
) {
10378 json_object_string_addf(
10379 json_nexthop_global
, "ip", "%pI4",
10380 &attr
->mp_nexthop_global_in
);
10382 if (path
->peer
->hostname
)
10383 json_object_string_add(
10384 json_nexthop_global
, "hostname",
10385 path
->peer
->hostname
);
10387 if (nexthop_hostname
)
10388 vty_out(vty
, " %pI4(%s)",
10389 &attr
->mp_nexthop_global_in
,
10392 vty_out(vty
, " %pI4",
10393 &attr
->mp_nexthop_global_in
);
10397 json_object_string_addf(json_nexthop_global
,
10401 if (path
->peer
->hostname
)
10402 json_object_string_add(
10403 json_nexthop_global
, "hostname",
10404 path
->peer
->hostname
);
10406 if (nexthop_hostname
)
10407 vty_out(vty
, " %pI4(%s)",
10411 vty_out(vty
, " %pI4",
10417 json_object_string_add(json_nexthop_global
, "afi",
10421 json_object_string_addf(json_nexthop_global
, "ip",
10423 &attr
->mp_nexthop_global
);
10425 if (path
->peer
->hostname
)
10426 json_object_string_add(json_nexthop_global
,
10428 path
->peer
->hostname
);
10430 json_object_string_add(json_nexthop_global
, "afi",
10432 json_object_string_add(json_nexthop_global
, "scope",
10435 if (nexthop_hostname
)
10436 vty_out(vty
, " %pI6(%s)",
10437 &attr
->mp_nexthop_global
,
10440 vty_out(vty
, " %pI6",
10441 &attr
->mp_nexthop_global
);
10445 /* Display the IGP cost or 'inaccessible' */
10446 if (!CHECK_FLAG(bpi_ultimate
->flags
, BGP_PATH_VALID
)) {
10447 bool import
= CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
);
10450 json_object_boolean_false_add(json_nexthop_global
,
10452 json_object_boolean_add(json_nexthop_global
,
10453 "importCheckEnabled", import
);
10455 vty_out(vty
, " (inaccessible%s)",
10456 import
? ", import-check enabled" : "");
10459 if (bpi_ultimate
->extra
&& bpi_ultimate
->extra
->igpmetric
) {
10461 json_object_int_add(
10462 json_nexthop_global
, "metric",
10463 bpi_ultimate
->extra
->igpmetric
);
10465 vty_out(vty
, " (metric %u)",
10466 bpi_ultimate
->extra
->igpmetric
);
10469 /* IGP cost is 0, display this only for json */
10472 json_object_int_add(json_nexthop_global
,
10477 json_object_boolean_true_add(json_nexthop_global
,
10481 /* Display peer "from" output */
10482 /* This path was originated locally */
10483 if (path
->peer
== bgp
->peer_self
) {
10485 if (safi
== SAFI_EVPN
|| (p
->family
== AF_INET
&&
10486 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr
))) {
10488 json_object_string_add(json_peer
, "peerId",
10491 vty_out(vty
, " from 0.0.0.0 ");
10494 json_object_string_add(json_peer
, "peerId",
10497 vty_out(vty
, " from :: ");
10501 json_object_string_addf(json_peer
, "routerId", "%pI4",
10504 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
10507 /* We RXed this path from one of our peers */
10511 json_object_string_addf(json_peer
, "peerId", "%pSU",
10513 json_object_string_addf(json_peer
, "routerId", "%pI4",
10514 &path
->peer
->remote_id
);
10516 if (path
->peer
->hostname
)
10517 json_object_string_add(json_peer
, "hostname",
10518 path
->peer
->hostname
);
10520 if (path
->peer
->domainname
)
10521 json_object_string_add(json_peer
, "domainname",
10522 path
->peer
->domainname
);
10524 if (path
->peer
->conf_if
)
10525 json_object_string_add(json_peer
, "interface",
10526 path
->peer
->conf_if
);
10528 if (path
->peer
->conf_if
) {
10529 if (path
->peer
->hostname
10530 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10531 BGP_FLAG_SHOW_HOSTNAME
))
10532 vty_out(vty
, " from %s(%s)",
10533 path
->peer
->hostname
,
10534 path
->peer
->conf_if
);
10536 vty_out(vty
, " from %s",
10537 path
->peer
->conf_if
);
10539 if (path
->peer
->hostname
10540 && CHECK_FLAG(path
->peer
->bgp
->flags
,
10541 BGP_FLAG_SHOW_HOSTNAME
))
10542 vty_out(vty
, " from %s(%s)",
10543 path
->peer
->hostname
,
10546 vty_out(vty
, " from %pSU",
10550 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10551 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
10553 vty_out(vty
, " (%pI4)", &path
->peer
->remote_id
);
10558 * Note when vrfid of nexthop is different from that of prefix
10560 if (path
->extra
&& path
->extra
->bgp_orig
) {
10561 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
10566 if (path
->extra
->bgp_orig
->inst_type
10567 == BGP_INSTANCE_TYPE_DEFAULT
)
10568 vn
= VRF_DEFAULT_NAME
;
10570 vn
= path
->extra
->bgp_orig
->name
;
10572 json_object_string_add(json_path
, "nhVrfName", vn
);
10574 if (nexthop_vrfid
== VRF_UNKNOWN
) {
10575 json_object_int_add(json_path
, "nhVrfId", -1);
10577 json_object_int_add(json_path
, "nhVrfId",
10578 (int)nexthop_vrfid
);
10581 if (nexthop_vrfid
== VRF_UNKNOWN
)
10582 vty_out(vty
, " vrf ?");
10586 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
10587 vty_out(vty
, " vrf %s(%u)",
10588 VRF_LOGNAME(vrf
), nexthop_vrfid
);
10593 if (nexthop_self
) {
10595 json_object_boolean_true_add(json_path
,
10596 "announceNexthopSelf");
10598 vty_out(vty
, " announce-nh-self");
10603 vty_out(vty
, "\n");
10605 /* display the link-local nexthop */
10606 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
10608 json_nexthop_ll
= json_object_new_object();
10609 json_object_string_addf(json_nexthop_ll
, "ip", "%pI6",
10610 &attr
->mp_nexthop_local
);
10612 if (path
->peer
->hostname
)
10613 json_object_string_add(json_nexthop_ll
,
10615 path
->peer
->hostname
);
10617 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10618 json_object_string_add(json_nexthop_ll
, "scope",
10621 json_object_boolean_true_add(json_nexthop_ll
,
10624 if (!attr
->mp_nexthop_prefer_global
)
10625 json_object_boolean_true_add(json_nexthop_ll
,
10628 json_object_boolean_true_add(
10629 json_nexthop_global
, "used");
10631 vty_out(vty
, " (%s) %s\n",
10632 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10633 buf
, INET6_ADDRSTRLEN
),
10634 attr
->mp_nexthop_prefer_global
10635 ? "(prefer-global)"
10639 /* If we do not have a link-local nexthop then we must flag the
10640 global as "used" */
10643 json_object_boolean_true_add(json_nexthop_global
,
10647 if (safi
== SAFI_EVPN
&&
10648 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10649 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10652 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10653 * Int/Ext/Local, Atomic, best */
10655 json_object_string_add(json_path
, "origin",
10656 bgp_origin_long_str
[attr
->origin
]);
10658 vty_out(vty
, " Origin %s",
10659 bgp_origin_long_str
[attr
->origin
]);
10661 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10663 json_object_int_add(json_path
, "metric", attr
->med
);
10665 vty_out(vty
, ", metric %u", attr
->med
);
10668 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10670 json_object_int_add(json_path
, "locPrf",
10673 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10676 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
10678 json_object_int_add(json_path
, "aigpMetric",
10679 bgp_attr_get_aigp_metric(attr
));
10681 vty_out(vty
, ", aigp-metric %" PRIu64
,
10682 bgp_attr_get_aigp_metric(attr
));
10685 if (attr
->weight
!= 0) {
10687 json_object_int_add(json_path
, "weight", attr
->weight
);
10689 vty_out(vty
, ", weight %u", attr
->weight
);
10692 if (attr
->tag
!= 0) {
10694 json_object_int_add(json_path
, "tag", attr
->tag
);
10696 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10699 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10701 json_object_boolean_false_add(json_path
, "valid");
10703 vty_out(vty
, ", invalid");
10704 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10706 json_object_boolean_true_add(json_path
, "valid");
10708 vty_out(vty
, ", valid");
10712 json_object_int_add(json_path
, "version", bn
->version
);
10714 if (path
->peer
!= bgp
->peer_self
) {
10715 if (path
->peer
->as
== path
->peer
->local_as
) {
10716 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10718 json_object_string_add(
10720 "confed-internal");
10722 vty_out(vty
, ", confed-internal");
10725 json_object_string_add(
10726 json_peer
, "type", "internal");
10728 vty_out(vty
, ", internal");
10731 if (bgp_confederation_peers_check(bgp
,
10734 json_object_string_add(
10736 "confed-external");
10738 vty_out(vty
, ", confed-external");
10741 json_object_string_add(
10742 json_peer
, "type", "external");
10744 vty_out(vty
, ", external");
10747 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10749 json_object_boolean_true_add(json_path
, "aggregated");
10750 json_object_boolean_true_add(json_path
, "local");
10752 vty_out(vty
, ", aggregated, local");
10754 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10756 json_object_boolean_true_add(json_path
, "sourced");
10758 vty_out(vty
, ", sourced");
10761 json_object_boolean_true_add(json_path
, "sourced");
10762 json_object_boolean_true_add(json_path
, "local");
10764 vty_out(vty
, ", sourced, local");
10768 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10770 json_object_boolean_true_add(json_path
,
10771 "atomicAggregate");
10773 vty_out(vty
, ", atomic-aggregate");
10776 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
10778 json_object_int_add(json_path
, "otc", attr
->otc
);
10780 vty_out(vty
, ", otc %u", attr
->otc
);
10783 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10784 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10785 && bgp_path_info_mpath_count(path
))) {
10787 json_object_boolean_true_add(json_path
, "multipath");
10789 vty_out(vty
, ", multipath");
10792 // Mark the bestpath(s)
10793 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10794 first_as
= aspath_get_first_as(attr
->aspath
);
10797 if (!json_bestpath
)
10798 json_bestpath
= json_object_new_object();
10799 json_object_int_add(json_bestpath
, "bestpathFromAs",
10803 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10805 vty_out(vty
, ", bestpath-from-AS Local");
10809 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10811 if (!json_bestpath
)
10812 json_bestpath
= json_object_new_object();
10813 json_object_boolean_true_add(json_bestpath
, "overall");
10814 json_object_string_add(
10815 json_bestpath
, "selectionReason",
10816 bgp_path_selection_reason2str(bn
->reason
));
10818 vty_out(vty
, ", best");
10819 vty_out(vty
, " (%s)",
10820 bgp_path_selection_reason2str(bn
->reason
));
10824 if (rpki_curr_state
!= RPKI_NOT_BEING_USED
) {
10826 json_object_string_add(
10827 json_path
, "rpkiValidationState",
10828 bgp_rpki_validation2str(rpki_curr_state
));
10830 vty_out(vty
, ", rpki validation-state: %s",
10831 bgp_rpki_validation2str(rpki_curr_state
));
10835 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10838 vty_out(vty
, "\n");
10840 /* Line 4 display Community */
10841 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
10843 if (!bgp_attr_get_community(attr
)->json
)
10844 community_str(bgp_attr_get_community(attr
),
10846 json_object_lock(bgp_attr_get_community(attr
)->json
);
10847 json_object_object_add(
10848 json_path
, "community",
10849 bgp_attr_get_community(attr
)->json
);
10851 vty_out(vty
, " Community: %s\n",
10852 bgp_attr_get_community(attr
)->str
);
10856 /* Line 5 display Extended-community */
10857 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10859 json_ext_community
= json_object_new_object();
10860 json_object_string_add(
10861 json_ext_community
, "string",
10862 bgp_attr_get_ecommunity(attr
)->str
);
10863 json_object_object_add(json_path
, "extendedCommunity",
10864 json_ext_community
);
10866 vty_out(vty
, " Extended Community: %s\n",
10867 bgp_attr_get_ecommunity(attr
)->str
);
10871 /* Line 6 display Large community */
10872 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10874 if (!bgp_attr_get_lcommunity(attr
)->json
)
10875 lcommunity_str(bgp_attr_get_lcommunity(attr
),
10877 json_object_lock(bgp_attr_get_lcommunity(attr
)->json
);
10878 json_object_object_add(
10879 json_path
, "largeCommunity",
10880 bgp_attr_get_lcommunity(attr
)->json
);
10882 vty_out(vty
, " Large Community: %s\n",
10883 bgp_attr_get_lcommunity(attr
)->str
);
10887 /* Line 7 display Originator, Cluster-id */
10888 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10889 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10890 char buf
[BUFSIZ
] = {0};
10892 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10894 json_object_string_addf(json_path
,
10895 "originatorId", "%pI4",
10896 &attr
->originator_id
);
10898 vty_out(vty
, " Originator: %pI4",
10899 &attr
->originator_id
);
10902 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10903 struct cluster_list
*cluster
=
10904 bgp_attr_get_cluster(attr
);
10908 json_cluster_list
= json_object_new_object();
10909 json_cluster_list_list
=
10910 json_object_new_array();
10912 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10913 json_string
= json_object_new_string(
10916 buf
, sizeof(buf
)));
10917 json_object_array_add(
10918 json_cluster_list_list
,
10923 * struct cluster_list does not have
10924 * "str" variable like aspath and community
10925 * do. Add this someday if someone asks
10927 * json_object_string_add(json_cluster_list,
10928 * "string", cluster->str);
10930 json_object_object_add(json_cluster_list
,
10932 json_cluster_list_list
);
10933 json_object_object_add(json_path
, "clusterList",
10934 json_cluster_list
);
10936 vty_out(vty
, ", Cluster list: ");
10938 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10939 vty_out(vty
, "%pI4 ",
10940 &cluster
->list
[i
]);
10946 vty_out(vty
, "\n");
10949 if (path
->extra
&& path
->extra
->damp_info
)
10950 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
10953 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10954 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10955 mpls_lse_decode(path
->extra
->label
[0], &label
, &ttl
, &exp
,
10959 json_object_int_add(json_path
, "remoteLabel", label
);
10961 vty_out(vty
, " Remote label: %d\n", label
);
10965 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10967 json_object_string_addf(json_path
, "remoteSid", "%pI6",
10968 &path
->extra
->sid
[0].sid
);
10970 vty_out(vty
, " Remote SID: %pI6\n",
10971 &path
->extra
->sid
[0].sid
);
10975 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
10977 json_object_int_add(json_path
, "labelIndex",
10978 attr
->label_index
);
10980 vty_out(vty
, " Label Index: %d\n",
10981 attr
->label_index
);
10984 /* Line 8 display Addpath IDs */
10985 if (path
->addpath_rx_id
10986 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
10988 json_object_int_add(json_path
, "addpathRxId",
10989 path
->addpath_rx_id
);
10991 /* Keep backwards compatibility with the old API
10992 * by putting TX All's ID in the old field
10994 json_object_int_add(
10995 json_path
, "addpathTxId",
10997 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
10999 /* ... but create a specific field for each
11002 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
11003 json_object_int_add(
11005 bgp_addpath_names(i
)->id_json_name
,
11006 path
->tx_addpath
.addpath_tx_id
[i
]);
11009 vty_out(vty
, " AddPath ID: RX %u, ",
11010 path
->addpath_rx_id
);
11012 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
11016 /* If we used addpath to TX a non-bestpath we need to display
11017 * "Advertised to" on a path-by-path basis
11019 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11022 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11024 bgp_addpath_encode_tx(peer
, afi
, safi
);
11025 has_adj
= bgp_adj_out_lookup(
11027 bgp_addpath_id_for_peer(peer
, afi
, safi
,
11028 &path
->tx_addpath
));
11030 if ((addpath_capable
&& has_adj
)
11031 || (!addpath_capable
&& has_adj
11032 && CHECK_FLAG(path
->flags
,
11033 BGP_PATH_SELECTED
))) {
11034 if (json_path
&& !json_adv_to
)
11035 json_adv_to
= json_object_new_object();
11037 route_vty_out_advertised_to(
11039 " Advertised to:", json_adv_to
);
11045 json_object_object_add(
11046 json_path
, "advertisedTo", json_adv_to
);
11050 vty_out(vty
, "\n");
11055 /* Line 9 display Uptime */
11056 tbuf
= time(NULL
) - (monotime(NULL
) - path
->uptime
);
11058 json_last_update
= json_object_new_object();
11059 json_object_int_add(json_last_update
, "epoch", tbuf
);
11060 json_object_string_add(json_last_update
, "string",
11062 json_object_object_add(json_path
, "lastUpdate",
11065 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
11067 /* Line 10 display PMSI tunnel attribute, if present */
11068 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
11069 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
11070 bgp_attr_get_pmsi_tnl_type(attr
),
11071 PMSI_TNLTYPE_STR_DEFAULT
);
11074 json_pmsi
= json_object_new_object();
11075 json_object_string_add(json_pmsi
, "tunnelType", str
);
11076 json_object_int_add(json_pmsi
, "label",
11077 label2vni(&attr
->label
));
11078 json_object_object_add(json_path
, "pmsi", json_pmsi
);
11080 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
11081 str
, label2vni(&attr
->label
));
11084 if (path
->peer
->t_gr_restart
&&
11085 CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
11086 unsigned long gr_remaining
=
11087 event_timer_remain_second(path
->peer
->t_gr_restart
);
11090 json_object_int_add(json_path
,
11091 "gracefulRestartSecondsRemaining",
11095 " Time until Graceful Restart stale route deleted: %lu\n",
11099 if (path
->peer
->t_llgr_stale
[afi
][safi
] &&
11100 bgp_attr_get_community(attr
) &&
11101 community_include(bgp_attr_get_community(attr
),
11102 COMMUNITY_LLGR_STALE
)) {
11103 unsigned long llgr_remaining
= event_timer_remain_second(
11104 path
->peer
->t_llgr_stale
[afi
][safi
]);
11107 json_object_int_add(json_path
, "llgrSecondsRemaining",
11111 " Time until Long-lived stale route deleted: %lu\n",
11115 /* Output some debug about internal state of the dest flags */
11117 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
11118 json_object_boolean_true_add(json_path
, "processScheduled");
11119 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
11120 json_object_boolean_true_add(json_path
, "userCleared");
11121 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
11122 json_object_boolean_true_add(json_path
, "labelChanged");
11123 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
11124 json_object_boolean_true_add(json_path
, "registeredForLabel");
11125 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
11126 json_object_boolean_true_add(json_path
, "selectDefered");
11127 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
11128 json_object_boolean_true_add(json_path
, "fibInstalled");
11129 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
11130 json_object_boolean_true_add(json_path
, "fibPending");
11132 if (json_nexthop_global
|| json_nexthop_ll
) {
11133 json_nexthops
= json_object_new_array();
11135 if (json_nexthop_global
)
11136 json_object_array_add(json_nexthops
,
11137 json_nexthop_global
);
11139 if (json_nexthop_ll
)
11140 json_object_array_add(json_nexthops
,
11143 json_object_object_add(json_path
, "nexthops",
11147 json_object_object_add(json_path
, "peer", json_peer
);
11148 json_object_array_add(json_paths
, json_path
);
11152 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
11153 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11154 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
11156 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11157 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11159 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11160 const char *comstr
, int exact
, afi_t afi
,
11161 safi_t safi
, uint16_t show_flags
);
11163 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11164 struct bgp_table
*table
, enum bgp_show_type type
,
11165 void *output_arg
, const char *rd
, int is_last
,
11166 unsigned long *output_cum
, unsigned long *total_cum
,
11167 unsigned long *json_header_depth
, uint16_t show_flags
,
11168 enum rpki_states rpki_target_state
)
11170 struct bgp_path_info
*pi
;
11171 struct bgp_dest
*dest
;
11172 bool header
= true;
11173 bool json_detail_header
= false;
11175 unsigned long output_count
= 0;
11176 unsigned long total_count
= 0;
11178 json_object
*json_paths
= NULL
;
11180 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11181 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11182 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11183 bool detail_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
11184 bool detail_routes
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
11186 if (output_cum
&& *output_cum
!= 0)
11189 if (use_json
&& !*json_header_depth
) {
11191 *json_header_depth
= 1;
11193 vty_out(vty
, "{\n");
11194 *json_header_depth
= 2;
11197 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11198 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
11200 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
11201 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
11204 table
->version
, &bgp
->router_id
,
11205 bgp
->default_local_pref
);
11206 if ((bgp
->asnotation
== ASNOTATION_PLAIN
) ||
11207 ((bgp
->asnotation
== ASNOTATION_DOT
) &&
11208 (bgp
->as
< UINT16_MAX
)))
11209 vty_out(vty
, "%u", bgp
->as
);
11211 vty_out(vty
, "\"");
11212 vty_out(vty
, ASN_FORMAT(bgp
->asnotation
), &bgp
->as
);
11213 vty_out(vty
, "\"");
11215 vty_out(vty
, ",\n \"routes\": { ");
11217 vty_out(vty
, " \"routeDistinguishers\" : {");
11218 ++*json_header_depth
;
11222 if (use_json
&& rd
) {
11223 vty_out(vty
, " \"%s\" : { ", rd
);
11226 /* Check for 'json detail', where we need header output once per dest */
11227 if (use_json
&& detail_json
&& type
!= bgp_show_type_dampend_paths
&&
11228 type
!= bgp_show_type_damp_neighbor
&&
11229 type
!= bgp_show_type_flap_statistics
&&
11230 type
!= bgp_show_type_flap_neighbor
)
11231 json_detail_header
= true;
11233 /* Start processing of routes. */
11234 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
11235 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11236 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
11237 bool json_detail_header_used
= false;
11239 pi
= bgp_dest_get_bgp_path_info(dest
);
11245 json_paths
= json_object_new_array();
11249 for (; pi
; pi
= pi
->next
) {
11250 struct community
*picomm
= NULL
;
11252 picomm
= bgp_attr_get_community(pi
->attr
);
11256 if (type
== bgp_show_type_prefix_version
) {
11258 strtoul(output_arg
, NULL
, 10);
11259 if (dest
->version
< version
)
11263 if (type
== bgp_show_type_community_alias
) {
11264 char *alias
= output_arg
;
11265 char **communities
;
11267 bool found
= false;
11270 frrstr_split(picomm
->str
, " ",
11271 &communities
, &num
);
11272 for (int i
= 0; i
< num
; i
++) {
11273 const char *com2alias
=
11274 bgp_community2alias(
11277 && strcmp(alias
, com2alias
)
11283 XFREE(MTYPE_TMP
, communities
);
11287 bgp_attr_get_lcommunity(pi
->attr
)) {
11288 frrstr_split(bgp_attr_get_lcommunity(
11291 " ", &communities
, &num
);
11292 for (int i
= 0; i
< num
; i
++) {
11293 const char *com2alias
=
11294 bgp_community2alias(
11297 && strcmp(alias
, com2alias
)
11303 XFREE(MTYPE_TMP
, communities
);
11310 if (type
== bgp_show_type_rpki
) {
11311 if (dest_p
->family
== AF_INET
11312 || dest_p
->family
== AF_INET6
)
11313 rpki_curr_state
= hook_call(
11314 bgp_rpki_prefix_status
,
11315 pi
->peer
, pi
->attr
, dest_p
);
11316 if (rpki_target_state
!= RPKI_NOT_BEING_USED
11317 && rpki_curr_state
!= rpki_target_state
)
11321 if (type
== bgp_show_type_flap_statistics
11322 || type
== bgp_show_type_flap_neighbor
11323 || type
== bgp_show_type_dampend_paths
11324 || type
== bgp_show_type_damp_neighbor
) {
11325 if (!(pi
->extra
&& pi
->extra
->damp_info
))
11328 if (type
== bgp_show_type_regexp
) {
11329 regex_t
*regex
= output_arg
;
11331 if (bgp_regexec(regex
, pi
->attr
->aspath
)
11335 if (type
== bgp_show_type_prefix_list
) {
11336 struct prefix_list
*plist
= output_arg
;
11338 if (prefix_list_apply(plist
, dest_p
)
11342 if (type
== bgp_show_type_access_list
) {
11343 struct access_list
*alist
= output_arg
;
11345 if (access_list_apply(alist
, dest_p
) !=
11349 if (type
== bgp_show_type_filter_list
) {
11350 struct as_list
*as_list
= output_arg
;
11352 if (as_list_apply(as_list
, pi
->attr
->aspath
)
11353 != AS_FILTER_PERMIT
)
11356 if (type
== bgp_show_type_route_map
) {
11357 struct route_map
*rmap
= output_arg
;
11358 struct bgp_path_info path
;
11359 struct bgp_path_info_extra extra
;
11360 struct attr dummy_attr
= {};
11361 route_map_result_t ret
;
11363 dummy_attr
= *pi
->attr
;
11365 prep_for_rmap_apply(&path
, &extra
, dest
, pi
,
11366 pi
->peer
, &dummy_attr
);
11368 ret
= route_map_apply(rmap
, dest_p
, &path
);
11369 bgp_attr_flush(&dummy_attr
);
11370 if (ret
== RMAP_DENYMATCH
)
11373 if (type
== bgp_show_type_neighbor
11374 || type
== bgp_show_type_flap_neighbor
11375 || type
== bgp_show_type_damp_neighbor
) {
11376 union sockunion
*su
= output_arg
;
11378 if (pi
->peer
== NULL
11379 || pi
->peer
->su_remote
== NULL
11380 || !sockunion_same(pi
->peer
->su_remote
, su
))
11383 if (type
== bgp_show_type_cidr_only
) {
11384 uint32_t destination
;
11386 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
11387 if (IN_CLASSC(destination
)
11388 && dest_p
->prefixlen
== 24)
11390 if (IN_CLASSB(destination
)
11391 && dest_p
->prefixlen
== 16)
11393 if (IN_CLASSA(destination
)
11394 && dest_p
->prefixlen
== 8)
11397 if (type
== bgp_show_type_prefix_longer
) {
11399 if (!prefix_match(p
, dest_p
))
11402 if (type
== bgp_show_type_community_all
) {
11406 if (type
== bgp_show_type_community
) {
11407 struct community
*com
= output_arg
;
11409 if (!picomm
|| !community_match(picomm
, com
))
11412 if (type
== bgp_show_type_community_exact
) {
11413 struct community
*com
= output_arg
;
11415 if (!picomm
|| !community_cmp(picomm
, com
))
11418 if (type
== bgp_show_type_community_list
) {
11419 struct community_list
*list
= output_arg
;
11421 if (!community_list_match(picomm
, list
))
11424 if (type
== bgp_show_type_community_list_exact
) {
11425 struct community_list
*list
= output_arg
;
11427 if (!community_list_exact_match(picomm
, list
))
11430 if (type
== bgp_show_type_lcommunity
) {
11431 struct lcommunity
*lcom
= output_arg
;
11433 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11435 bgp_attr_get_lcommunity(pi
->attr
),
11440 if (type
== bgp_show_type_lcommunity_exact
) {
11441 struct lcommunity
*lcom
= output_arg
;
11443 if (!bgp_attr_get_lcommunity(pi
->attr
) ||
11445 bgp_attr_get_lcommunity(pi
->attr
),
11449 if (type
== bgp_show_type_lcommunity_list
) {
11450 struct community_list
*list
= output_arg
;
11452 if (!lcommunity_list_match(
11453 bgp_attr_get_lcommunity(pi
->attr
),
11458 == bgp_show_type_lcommunity_list_exact
) {
11459 struct community_list
*list
= output_arg
;
11461 if (!lcommunity_list_exact_match(
11462 bgp_attr_get_lcommunity(pi
->attr
),
11466 if (type
== bgp_show_type_lcommunity_all
) {
11467 if (!bgp_attr_get_lcommunity(pi
->attr
))
11470 if (type
== bgp_show_type_dampend_paths
11471 || type
== bgp_show_type_damp_neighbor
) {
11472 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
11473 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11476 if (type
== bgp_show_type_self_originated
) {
11477 if (pi
->peer
!= bgp
->peer_self
)
11481 if (!use_json
&& header
) {
11483 "BGP table version is %" PRIu64
11484 ", local router ID is %pI4, vrf id ",
11485 table
->version
, &bgp
->router_id
);
11486 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11487 vty_out(vty
, "%s", VRFID_NONE_STR
);
11489 vty_out(vty
, "%u", bgp
->vrf_id
);
11490 vty_out(vty
, "\n");
11491 vty_out(vty
, "Default local pref %u, ",
11492 bgp
->default_local_pref
);
11493 vty_out(vty
, "local AS ");
11494 vty_out(vty
, ASN_FORMAT(bgp
->asnotation
),
11496 vty_out(vty
, "\n");
11497 if (!detail_routes
) {
11498 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11499 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11500 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11501 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
11503 if (type
== bgp_show_type_dampend_paths
11504 || type
== bgp_show_type_damp_neighbor
)
11505 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
11506 else if (type
== bgp_show_type_flap_statistics
11507 || type
== bgp_show_type_flap_neighbor
)
11508 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
11509 else if (!detail_routes
)
11510 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
11511 : BGP_SHOW_HEADER
));
11515 if (rd
!= NULL
&& !display
&& !output_count
) {
11518 "Route Distinguisher: %s\n",
11521 if (type
== bgp_show_type_dampend_paths
11522 || type
== bgp_show_type_damp_neighbor
)
11523 damp_route_vty_out(vty
, dest_p
, pi
, display
,
11524 AFI_IP
, safi
, use_json
,
11526 else if (type
== bgp_show_type_flap_statistics
11527 || type
== bgp_show_type_flap_neighbor
)
11528 flap_route_vty_out(vty
, dest_p
, pi
, display
,
11529 AFI_IP
, safi
, use_json
,
11532 if (detail_routes
|| detail_json
) {
11533 const struct prefix_rd
*prd
= NULL
;
11536 prd
= bgp_rd_from_dest(
11537 dest
->pdest
, safi
);
11540 route_vty_out_detail_header(
11542 bgp_dest_get_prefix(
11544 prd
, table
->afi
, safi
,
11547 route_vty_out_detail(
11548 vty
, bgp
, dest
, dest_p
, pi
,
11549 family2afi(dest_p
->family
),
11550 safi
, RPKI_NOT_BEING_USED
,
11553 route_vty_out(vty
, dest_p
, pi
, display
,
11554 safi
, json_paths
, wide
);
11565 /* encode prefix */
11566 if (dest_p
->family
== AF_FLOWSPEC
) {
11567 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
11570 bgp_fs_nlri_get_string(
11572 dest_p
->u
.prefix_flowspec
.ptr
,
11573 dest_p
->u
.prefix_flowspec
.prefixlen
,
11574 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
11575 family2afi(dest_p
->u
11576 .prefix_flowspec
.family
));
11578 vty_out(vty
, "\"%s/%d\": ", retstr
,
11579 dest_p
->u
.prefix_flowspec
11582 vty_out(vty
, ",\"%s/%d\": ", retstr
,
11583 dest_p
->u
.prefix_flowspec
11587 vty_out(vty
, "\"%pFX\": ", dest_p
);
11589 vty_out(vty
, ",\"%pFX\": ", dest_p
);
11592 if (json_detail_header
&& json_paths
!= NULL
) {
11593 const struct prefix_rd
*prd
;
11595 vty_out(vty
, "{\n");
11597 prd
= bgp_rd_from_dest(dest
, safi
);
11599 route_vty_out_detail_header(
11601 bgp_dest_get_prefix(dest
), prd
,
11602 table
->afi
, safi
, json_paths
, true);
11604 vty_out(vty
, "\"paths\": ");
11605 json_detail_header_used
= true;
11609 * We are using no_pretty here because under
11610 * extremely high settings( say lots and lots of
11611 * routes with lots and lots of ways to reach
11612 * that route via different paths ) this can
11613 * save several minutes of output when FRR
11614 * is run on older cpu's or more underperforming
11615 * routers out there
11617 vty_json_no_pretty(vty
, json_paths
);
11619 if (json_detail_header_used
)
11620 vty_out(vty
, "} ");
11625 json_object_free(json_paths
);
11629 output_count
+= *output_cum
;
11630 *output_cum
= output_count
;
11633 total_count
+= *total_cum
;
11634 *total_cum
= total_count
;
11638 vty_out(vty
, " }%s ", (is_last
? "" : ","));
11642 for (i
= 0; i
< *json_header_depth
; ++i
)
11643 vty_out(vty
, " } ");
11645 vty_out(vty
, "\n");
11649 /* No route is displayed */
11650 if (output_count
== 0) {
11651 if (type
== bgp_show_type_normal
)
11653 "No BGP prefixes displayed, %ld exist\n",
11657 "\nDisplayed %ld routes and %ld total paths\n",
11658 output_count
, total_count
);
11662 return CMD_SUCCESS
;
11665 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
11666 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
11667 enum bgp_show_type type
, void *output_arg
,
11668 uint16_t show_flags
)
11670 struct bgp_dest
*dest
, *next
;
11671 unsigned long output_cum
= 0;
11672 unsigned long total_cum
= 0;
11673 unsigned long json_header_depth
= 0;
11674 struct bgp_table
*itable
;
11676 bool use_json
= !!CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11678 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
11680 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
11681 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11683 next
= bgp_route_next(dest
);
11684 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
11687 itable
= bgp_dest_get_bgp_table_info(dest
);
11688 if (itable
!= NULL
) {
11689 struct prefix_rd prd
;
11690 char rd
[RD_ADDRSTRLEN
];
11692 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
11693 prefix_rd2str(&prd
, rd
, sizeof(rd
), bgp
->asnotation
);
11694 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
11695 rd
, next
== NULL
, &output_cum
,
11696 &total_cum
, &json_header_depth
,
11697 show_flags
, RPKI_NOT_BEING_USED
);
11703 if (output_cum
== 0)
11704 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
11708 "\nDisplayed %ld routes and %ld total paths\n",
11709 output_cum
, total_cum
);
11711 if (use_json
&& output_cum
== 0)
11712 vty_out(vty
, "{}\n");
11714 return CMD_SUCCESS
;
11717 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11718 enum bgp_show_type type
, void *output_arg
,
11719 uint16_t show_flags
, enum rpki_states rpki_target_state
)
11721 struct bgp_table
*table
;
11722 unsigned long json_header_depth
= 0;
11723 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11726 bgp
= bgp_get_default();
11731 vty_out(vty
, "No BGP process is configured\n");
11733 vty_out(vty
, "{}\n");
11734 return CMD_WARNING
;
11737 /* Labeled-unicast routes live in the unicast table. */
11738 if (safi
== SAFI_LABELED_UNICAST
)
11739 safi
= SAFI_UNICAST
;
11741 table
= bgp
->rib
[afi
][safi
];
11742 /* use MPLS and ENCAP specific shows until they are merged */
11743 if (safi
== SAFI_MPLS_VPN
) {
11744 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
11745 output_arg
, show_flags
);
11748 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
11749 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
11750 output_arg
, use_json
,
11754 if (safi
== SAFI_EVPN
)
11755 return bgp_evpn_show_all_routes(vty
, bgp
, type
, use_json
, 0);
11757 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
11758 NULL
, NULL
, &json_header_depth
, show_flags
,
11759 rpki_target_state
);
11762 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
11763 safi_t safi
, uint16_t show_flags
)
11765 struct listnode
*node
, *nnode
;
11768 bool route_output
= false;
11769 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11772 vty_out(vty
, "{\n");
11774 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
11775 route_output
= true;
11778 vty_out(vty
, ",\n");
11782 vty_out(vty
, "\"%s\":",
11783 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11787 vty_out(vty
, "\nInstance %s:\n",
11788 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11792 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
11793 show_flags
, RPKI_NOT_BEING_USED
);
11797 vty_out(vty
, "}\n");
11798 else if (!route_output
)
11799 vty_out(vty
, "%% BGP instance not found\n");
11802 /* Header of detailed BGP route information */
11803 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
11804 struct bgp_dest
*dest
, const struct prefix
*p
,
11805 const struct prefix_rd
*prd
, afi_t afi
,
11806 safi_t safi
, json_object
*json
,
11807 bool incremental_print
)
11809 struct bgp_path_info
*pi
;
11811 struct listnode
*node
, *nnode
;
11812 char buf1
[RD_ADDRSTRLEN
];
11816 int accept_own
= 0;
11817 int route_filter_translated_v4
= 0;
11818 int route_filter_v4
= 0;
11819 int route_filter_translated_v6
= 0;
11820 int route_filter_v6
= 0;
11821 int llgr_stale
= 0;
11823 int accept_own_nexthop
= 0;
11826 int no_advertise
= 0;
11830 int has_valid_label
= 0;
11831 mpls_label_t label
= 0;
11832 json_object
*json_adv_to
= NULL
;
11837 mpls_lse_decode(dest
->local_label
, &label
, &ttl
, &exp
, &bos
);
11839 has_valid_label
= bgp_is_valid_label(&label
);
11841 if (safi
== SAFI_EVPN
) {
11843 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11844 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
),
11847 prd
? ":" : "", (struct prefix_evpn
*)p
);
11849 json_object_string_add(
11851 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
),
11854 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11859 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11861 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11862 ? prefix_rd2str(prd
, buf1
,
11866 safi
== SAFI_MPLS_VPN
? ":" : "", p
,
11870 if (incremental_print
) {
11871 vty_out(vty
, "\"prefix\": \"%pFX\",\n", p
);
11872 vty_out(vty
, "\"version\": \"%" PRIu64
"\",\n",
11875 json_object_string_addf(json
, "prefix", "%pFX",
11877 json_object_int_add(json
, "version",
11883 if (has_valid_label
) {
11885 if (incremental_print
)
11886 vty_out(vty
, "\"localLabel\": \"%u\",\n",
11889 json_object_int_add(json
, "localLabel", label
);
11891 vty_out(vty
, "Local label: %d\n", label
);
11895 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11896 vty_out(vty
, "not allocated\n");
11898 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11899 struct community
*picomm
= NULL
;
11901 picomm
= bgp_attr_get_community(pi
->attr
);
11904 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11906 if (bgp_path_suppressed(pi
))
11912 no_advertise
+= community_include(
11913 picomm
, COMMUNITY_NO_ADVERTISE
);
11915 community_include(picomm
, COMMUNITY_NO_EXPORT
);
11917 community_include(picomm
, COMMUNITY_LOCAL_AS
);
11919 community_include(picomm
, COMMUNITY_ACCEPT_OWN
);
11920 route_filter_translated_v4
+= community_include(
11921 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11922 route_filter_translated_v6
+= community_include(
11923 picomm
, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11924 route_filter_v4
+= community_include(
11925 picomm
, COMMUNITY_ROUTE_FILTER_v4
);
11926 route_filter_v6
+= community_include(
11927 picomm
, COMMUNITY_ROUTE_FILTER_v6
);
11929 community_include(picomm
, COMMUNITY_LLGR_STALE
);
11930 no_llgr
+= community_include(picomm
, COMMUNITY_NO_LLGR
);
11931 accept_own_nexthop
+= community_include(
11932 picomm
, COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11934 community_include(picomm
, COMMUNITY_BLACKHOLE
);
11935 no_peer
+= community_include(picomm
, COMMUNITY_NO_PEER
);
11940 vty_out(vty
, "Paths: (%d available", count
);
11942 vty_out(vty
, ", best #%d", best
);
11943 if (safi
== SAFI_UNICAST
) {
11944 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11945 vty_out(vty
, ", table %s",
11948 vty_out(vty
, ", vrf %s",
11952 vty_out(vty
, ", no best path");
11956 ", accept own local route exported and imported in different VRF");
11957 else if (route_filter_translated_v4
)
11959 ", mark translated RTs for VPNv4 route filtering");
11960 else if (route_filter_v4
)
11962 ", attach RT as-is for VPNv4 route filtering");
11963 else if (route_filter_translated_v6
)
11965 ", mark translated RTs for VPNv6 route filtering");
11966 else if (route_filter_v6
)
11968 ", attach RT as-is for VPNv6 route filtering");
11969 else if (llgr_stale
)
11971 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
11974 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11975 else if (accept_own_nexthop
)
11977 ", accept local nexthop");
11978 else if (blackhole
)
11979 vty_out(vty
, ", inform peer to blackhole prefix");
11980 else if (no_export
)
11981 vty_out(vty
, ", not advertised to EBGP peer");
11982 else if (no_advertise
)
11983 vty_out(vty
, ", not advertised to any peer");
11985 vty_out(vty
, ", not advertised outside local AS");
11988 ", inform EBGP peer not to advertise to their EBGP peers");
11992 ", Advertisements suppressed by an aggregate.");
11993 vty_out(vty
, ")\n");
11996 /* If we are not using addpath then we can display Advertised to and
11998 * show what peers we advertised the bestpath to. If we are using
12000 * though then we must display Advertised to on a path-by-path basis. */
12001 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
12002 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
12003 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
12004 if (json
&& !json_adv_to
)
12005 json_adv_to
= json_object_new_object();
12007 route_vty_out_advertised_to(
12009 " Advertised to non peer-group peers:\n ",
12014 if (json
&& json_adv_to
) {
12015 if (incremental_print
) {
12016 vty_out(vty
, "\"advertisedTo\": ");
12017 vty_json(vty
, json_adv_to
);
12020 json_object_object_add(json
, "advertisedTo",
12023 if (!json
&& first
)
12024 vty_out(vty
, " Not advertised to any peer");
12025 vty_out(vty
, "\n");
12030 static void bgp_show_path_info(const struct prefix_rd
*pfx_rd
,
12031 struct bgp_dest
*bgp_node
, struct vty
*vty
,
12032 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
12033 json_object
*json
, enum bgp_path_type pathtype
,
12034 int *display
, enum rpki_states rpki_target_state
)
12036 struct bgp_path_info
*pi
;
12038 json_object
*json_header
= NULL
;
12039 json_object
*json_paths
= NULL
;
12040 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
12042 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
12043 enum rpki_states rpki_curr_state
= RPKI_NOT_BEING_USED
;
12045 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
12046 rpki_curr_state
= hook_call(bgp_rpki_prefix_status
,
12047 pi
->peer
, pi
->attr
, p
);
12049 if (rpki_target_state
!= RPKI_NOT_BEING_USED
12050 && rpki_curr_state
!= rpki_target_state
)
12053 if (json
&& !json_paths
) {
12054 /* Instantiate json_paths only if path is valid */
12055 json_paths
= json_object_new_array();
12057 json_header
= json_object_new_object();
12059 json_header
= json
;
12063 route_vty_out_detail_header(
12064 vty
, bgp
, bgp_node
,
12065 bgp_dest_get_prefix(bgp_node
), pfx_rd
, AFI_IP
,
12066 safi
, json_header
, false);
12071 if (pathtype
== BGP_PATH_SHOW_ALL
12072 || (pathtype
== BGP_PATH_SHOW_BESTPATH
12073 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12074 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
12075 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
12076 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
12077 route_vty_out_detail(vty
, bgp
, bgp_node
,
12078 bgp_dest_get_prefix(bgp_node
), pi
,
12079 AFI_IP
, safi
, rpki_curr_state
,
12083 if (json
&& json_paths
) {
12084 json_object_object_add(json_header
, "paths", json_paths
);
12087 json_object_object_addf(
12089 BGP_RD_AS_FORMAT(bgp
->asnotation
), pfx_rd
);
12094 * Return rd based on safi
12096 const struct prefix_rd
*bgp_rd_from_dest(const struct bgp_dest
*dest
,
12100 case SAFI_MPLS_VPN
:
12103 return (struct prefix_rd
*)(bgp_dest_get_prefix(dest
));
12106 case SAFI_MULTICAST
:
12107 case SAFI_LABELED_UNICAST
:
12108 case SAFI_FLOWSPEC
:
12113 assert(!"Reached end of function when we were not expecting it");
12116 /* Display specified route of BGP table. */
12117 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
12118 struct bgp_table
*rib
, const char *ip_str
,
12119 afi_t afi
, safi_t safi
,
12120 enum rpki_states rpki_target_state
,
12121 struct prefix_rd
*prd
, int prefix_check
,
12122 enum bgp_path_type pathtype
, bool use_json
)
12126 struct prefix match
;
12127 struct bgp_dest
*dest
;
12128 struct bgp_dest
*rm
;
12129 struct bgp_table
*table
;
12130 json_object
*json
= NULL
;
12131 json_object
*json_paths
= NULL
;
12133 /* Check IP address argument. */
12134 ret
= str2prefix(ip_str
, &match
);
12136 vty_out(vty
, "address is malformed\n");
12137 return CMD_WARNING
;
12140 match
.family
= afi2family(afi
);
12143 json
= json_object_new_object();
12145 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
12146 for (dest
= bgp_table_top(rib
); dest
;
12147 dest
= bgp_route_next(dest
)) {
12148 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12150 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
12152 table
= bgp_dest_get_bgp_table_info(dest
);
12156 rm
= bgp_node_match(table
, &match
);
12160 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
12162 && rm_p
->prefixlen
!= match
.prefixlen
) {
12163 bgp_dest_unlock_node(rm
);
12167 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12168 bgp
, afi
, safi
, json
, pathtype
,
12169 &display
, rpki_target_state
);
12171 bgp_dest_unlock_node(rm
);
12173 } else if (safi
== SAFI_EVPN
) {
12174 struct bgp_dest
*longest_pfx
;
12175 bool is_exact_pfxlen_match
= false;
12177 for (dest
= bgp_table_top(rib
); dest
;
12178 dest
= bgp_route_next(dest
)) {
12179 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12181 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
12183 table
= bgp_dest_get_bgp_table_info(dest
);
12187 longest_pfx
= NULL
;
12188 is_exact_pfxlen_match
= false;
12190 * Search through all the prefixes for a match. The
12191 * pfx's are enumerated in ascending order of pfxlens.
12192 * So, the last pfx match is the longest match. Set
12193 * is_exact_pfxlen_match when we get exact pfxlen match
12195 for (rm
= bgp_table_top(table
); rm
;
12196 rm
= bgp_route_next(rm
)) {
12197 const struct prefix
*rm_p
=
12198 bgp_dest_get_prefix(rm
);
12200 * Get prefixlen of the ip-prefix within type5
12203 if (evpn_type5_prefix_match(rm_p
, &match
)
12207 bgp_evpn_get_type5_prefixlen(
12209 if (type5_pfxlen
== match
.prefixlen
) {
12210 is_exact_pfxlen_match
= true;
12211 bgp_dest_unlock_node(rm
);
12220 if (prefix_check
&& !is_exact_pfxlen_match
)
12224 bgp_dest_lock_node(rm
);
12226 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
12227 bgp
, afi
, safi
, json
, pathtype
,
12228 &display
, rpki_target_state
);
12230 bgp_dest_unlock_node(rm
);
12232 } else if (safi
== SAFI_FLOWSPEC
) {
12234 json_paths
= json_object_new_array();
12236 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
12237 &match
, prefix_check
,
12243 json_object_object_add(json
, "paths",
12246 json_object_free(json_paths
);
12249 dest
= bgp_node_match(rib
, &match
);
12250 if (dest
!= NULL
) {
12251 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
12253 || dest_p
->prefixlen
== match
.prefixlen
) {
12254 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
12255 safi
, json
, pathtype
,
12256 &display
, rpki_target_state
);
12259 bgp_dest_unlock_node(dest
);
12264 vty_json(vty
, json
);
12267 vty_out(vty
, "%% Network not in table\n");
12268 return CMD_WARNING
;
12272 return CMD_SUCCESS
;
12275 /* Display specified route of Main RIB */
12276 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
12277 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
12278 int prefix_check
, enum bgp_path_type pathtype
,
12279 enum rpki_states rpki_target_state
, bool use_json
)
12282 bgp
= bgp_get_default();
12285 vty_out(vty
, "No BGP process is configured\n");
12287 vty_out(vty
, "{}\n");
12288 return CMD_WARNING
;
12292 /* labeled-unicast routes live in the unicast table */
12293 if (safi
== SAFI_LABELED_UNICAST
)
12294 safi
= SAFI_UNICAST
;
12296 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
12297 afi
, safi
, rpki_target_state
, prd
,
12298 prefix_check
, pathtype
, use_json
);
12301 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
12302 struct cmd_token
**argv
, bool exact
, afi_t afi
,
12303 safi_t safi
, bool uj
)
12305 struct lcommunity
*lcom
;
12310 uint16_t show_flags
= 0;
12314 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12316 b
= buffer_new(1024);
12317 for (i
= 0; i
< argc
; i
++) {
12319 buffer_putc(b
, ' ');
12321 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
12323 buffer_putstr(b
, argv
[i
]->arg
);
12327 buffer_putc(b
, '\0');
12329 str
= buffer_getstr(b
);
12332 lcom
= lcommunity_str2com(str
);
12333 XFREE(MTYPE_TMP
, str
);
12335 vty_out(vty
, "%% Large-community malformed\n");
12336 return CMD_WARNING
;
12339 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12340 (exact
? bgp_show_type_lcommunity_exact
12341 : bgp_show_type_lcommunity
),
12342 lcom
, show_flags
, RPKI_NOT_BEING_USED
);
12344 lcommunity_free(&lcom
);
12348 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
12349 const char *lcom
, bool exact
, afi_t afi
,
12350 safi_t safi
, bool uj
)
12352 struct community_list
*list
;
12353 uint16_t show_flags
= 0;
12356 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12359 list
= community_list_lookup(bgp_clist
, lcom
, 0,
12360 LARGE_COMMUNITY_LIST_MASTER
);
12361 if (list
== NULL
) {
12362 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
12364 return CMD_WARNING
;
12367 return bgp_show(vty
, bgp
, afi
, safi
,
12368 (exact
? bgp_show_type_lcommunity_list_exact
12369 : bgp_show_type_lcommunity_list
),
12370 list
, show_flags
, RPKI_NOT_BEING_USED
);
12373 DEFUN (show_ip_bgp_large_community_list
,
12374 show_ip_bgp_large_community_list_cmd
,
12375 "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]",
12379 BGP_INSTANCE_HELP_STR
12381 BGP_SAFI_WITH_LABEL_HELP_STR
12382 "Display routes matching the large-community-list\n"
12383 "large-community-list number\n"
12384 "large-community-list name\n"
12385 "Exact match of the large-communities\n"
12388 afi_t afi
= AFI_IP6
;
12389 safi_t safi
= SAFI_UNICAST
;
12391 bool exact_match
= 0;
12392 struct bgp
*bgp
= NULL
;
12393 bool uj
= use_json(argc
, argv
);
12398 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12401 return CMD_WARNING
;
12403 argv_find(argv
, argc
, "large-community-list", &idx
);
12405 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12407 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
12410 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
12411 exact_match
, afi
, safi
, uj
);
12413 DEFUN (show_ip_bgp_large_community
,
12414 show_ip_bgp_large_community_cmd
,
12415 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
12419 BGP_INSTANCE_HELP_STR
12421 BGP_SAFI_WITH_LABEL_HELP_STR
12422 "Display routes matching the large-communities\n"
12423 "List of large-community numbers\n"
12424 "Exact match of the large-communities\n"
12427 afi_t afi
= AFI_IP6
;
12428 safi_t safi
= SAFI_UNICAST
;
12430 bool exact_match
= 0;
12431 struct bgp
*bgp
= NULL
;
12432 bool uj
= use_json(argc
, argv
);
12433 uint16_t show_flags
= 0;
12437 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12440 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12443 return CMD_WARNING
;
12445 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
12446 if (argv_find(argv
, argc
, "exact-match", &idx
)) {
12450 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
12451 exact_match
, afi
, safi
, uj
);
12453 return bgp_show(vty
, bgp
, afi
, safi
,
12454 bgp_show_type_lcommunity_all
, NULL
, show_flags
,
12455 RPKI_NOT_BEING_USED
);
12458 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12459 safi_t safi
, struct json_object
*json_array
);
12460 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12461 safi_t safi
, struct json_object
*json
);
12464 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
12465 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12466 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12467 "Display number of prefixes for all afi/safi\n" JSON_STR
)
12469 bool uj
= use_json(argc
, argv
);
12470 struct bgp
*bgp
= NULL
;
12471 safi_t safi
= SAFI_UNICAST
;
12472 afi_t afi
= AFI_IP6
;
12474 struct json_object
*json_all
= NULL
;
12475 struct json_object
*json_afi_safi
= NULL
;
12477 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12480 return CMD_WARNING
;
12483 json_all
= json_object_new_object();
12485 FOREACH_AFI_SAFI (afi
, safi
) {
12487 * So limit output to those afi/safi pairs that
12488 * actually have something interesting in them
12490 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12495 json_afi_safi
= json_object_new_array();
12496 json_object_object_add(
12498 get_afi_safi_str(afi
, safi
, true),
12501 json_afi_safi
= NULL
;
12504 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12508 vty_json(vty
, json_all
);
12510 return CMD_SUCCESS
;
12513 /* BGP route print out function without JSON */
12514 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
12515 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
12516 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12520 BGP_INSTANCE_HELP_STR
12523 "BGP RIB advertisement statistics\n"
12526 afi_t afi
= AFI_IP6
;
12527 safi_t safi
= SAFI_UNICAST
;
12528 struct bgp
*bgp
= NULL
;
12530 bool uj
= use_json(argc
, argv
);
12531 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12533 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12536 return CMD_WARNING
;
12539 json_afi_safi
= json_object_new_array();
12541 json_afi_safi
= NULL
;
12543 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12546 json
= json_object_new_object();
12547 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12549 vty_json(vty
, json
);
12554 /* BGP route print out function without JSON */
12555 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
12556 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12557 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12559 statistics [json]",
12560 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12561 BGP_SAFI_WITH_LABEL_HELP_STR
12562 "BGP RIB advertisement statistics\n" JSON_STR
)
12564 afi_t afi
= AFI_IP6
;
12565 safi_t safi
= SAFI_UNICAST
;
12566 struct bgp
*bgp
= NULL
;
12568 bool uj
= use_json(argc
, argv
);
12569 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
12571 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12574 return CMD_WARNING
;
12577 json_afi_safi
= json_object_new_array();
12579 json_afi_safi
= NULL
;
12581 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
12584 json
= json_object_new_object();
12585 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
12587 vty_json(vty
, json
);
12592 DEFPY(show_ip_bgp_dampening_params
, show_ip_bgp_dampening_params_cmd
,
12593 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12594 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12595 "]] [all$all] dampening parameters [json]",
12596 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12597 BGP_SAFI_WITH_LABEL_HELP_STR
12598 "Display the entries for all address families\n"
12599 "Display detailed information about dampening\n"
12600 "Display detail of configured dampening parameters\n"
12603 afi_t afi
= AFI_IP6
;
12604 safi_t safi
= SAFI_UNICAST
;
12605 struct bgp
*bgp
= NULL
;
12607 uint16_t show_flags
= 0;
12608 bool uj
= use_json(argc
, argv
);
12612 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12615 /* [<ipv4|ipv6> [all]] */
12617 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12618 if (argv_find(argv
, argc
, "ipv4", &idx
))
12619 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12621 if (argv_find(argv
, argc
, "ipv6", &idx
))
12622 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12625 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12628 return CMD_WARNING
;
12630 return bgp_show_dampening_parameters(vty
, afi
, safi
, show_flags
);
12633 /* BGP route print out function */
12634 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
12635 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12636 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12640 |dampening <flap-statistics|dampened-paths>\
12641 |community [AA:NN|local-AS|no-advertise|no-export\
12642 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12643 |accept-own|accept-own-nexthop|route-filter-v6\
12644 |route-filter-v4|route-filter-translated-v6\
12645 |route-filter-translated-v4] [exact-match]\
12646 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12647 |filter-list AS_PATH_FILTER_NAME\
12649 |access-list ACCESSLIST_NAME\
12650 |route-map RMAP_NAME\
12651 |rpki <invalid|valid|notfound>\
12652 |version (1-4294967295)\
12654 |A.B.C.D/M longer-prefixes\
12655 |X:X::X:X/M longer-prefixes\
12656 |"BGP_SELF_ORIG_CMD_STR
"\
12657 |detail-routes$detail_routes\
12658 ] [json$uj [detail$detail_json] | wide$wide]",
12659 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12660 BGP_SAFI_WITH_LABEL_HELP_STR
12661 "Display the entries for all address families\n"
12662 "Display only routes with non-natural netmasks\n"
12663 "Display detailed information about dampening\n"
12664 "Display flap statistics of routes\n"
12665 "Display paths suppressed due to dampening\n"
12666 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12667 "Do not send outside local AS (well-known community)\n"
12668 "Do not advertise to any peer (well-known community)\n"
12669 "Do not export to next AS (well-known community)\n"
12670 "Graceful shutdown (well-known community)\n"
12671 "Do not export to any peer (well-known community)\n"
12672 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12673 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12674 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12675 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12676 "Should accept VPN route with local nexthop (well-known community)\n"
12677 "RT VPNv6 route filtering (well-known community)\n"
12678 "RT VPNv4 route filtering (well-known community)\n"
12679 "RT translated VPNv6 route filtering (well-known community)\n"
12680 "RT translated VPNv4 route filtering (well-known community)\n"
12681 "Exact match of the communities\n"
12682 "Community-list number\n"
12683 "Community-list name\n"
12684 "Display routes matching the community-list\n"
12685 "Exact match of the communities\n"
12686 "Display routes conforming to the filter-list\n"
12687 "Regular expression access list name\n"
12688 "Display routes conforming to the prefix-list\n"
12689 "Prefix-list name\n"
12690 "Display routes conforming to the access-list\n"
12691 "Access-list name\n"
12692 "Display routes matching the route-map\n"
12693 "A route-map to match on\n"
12694 "RPKI route types\n"
12695 "A valid path as determined by rpki\n"
12696 "A invalid path as determined by rpki\n"
12697 "A path that has no rpki data\n"
12698 "Display prefixes with matching version numbers\n"
12699 "Version number and above\n"
12700 "Display prefixes with matching BGP community alias\n"
12701 "BGP community alias\n"
12703 "Display route and more specific routes\n"
12705 "Display route and more specific routes\n"
12706 BGP_SELF_ORIG_HELP_STR
12707 "Display detailed version of all routes\n"
12709 "Display detailed version of JSON output\n"
12710 "Increase table width for longer prefixes\n")
12712 afi_t afi
= AFI_IP6
;
12713 safi_t safi
= SAFI_UNICAST
;
12714 enum bgp_show_type sh_type
= bgp_show_type_normal
;
12715 void *output_arg
= NULL
;
12716 struct bgp
*bgp
= NULL
;
12718 int exact_match
= 0;
12719 char *community
= NULL
;
12721 uint16_t show_flags
= 0;
12722 enum rpki_states rpki_target_state
= RPKI_NOT_BEING_USED
;
12727 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12731 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON_DETAIL
);
12734 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
12736 /* [<ipv4|ipv6> [all]] */
12738 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12740 if (argv_find(argv
, argc
, "ipv4", &idx
))
12741 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12743 if (argv_find(argv
, argc
, "ipv6", &idx
))
12744 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12748 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12750 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12753 return CMD_WARNING
;
12755 if (argv_find(argv
, argc
, "cidr-only", &idx
))
12756 sh_type
= bgp_show_type_cidr_only
;
12758 if (argv_find(argv
, argc
, "dampening", &idx
)) {
12759 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
12760 sh_type
= bgp_show_type_dampend_paths
;
12761 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12762 sh_type
= bgp_show_type_flap_statistics
;
12765 if (argv_find(argv
, argc
, "community", &idx
)) {
12766 char *maybecomm
= NULL
;
12768 if (idx
+ 1 < argc
) {
12769 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
12770 maybecomm
= argv
[idx
+ 1]->arg
;
12772 maybecomm
= argv
[idx
+ 1]->text
;
12775 if (maybecomm
&& !strmatch(maybecomm
, "json")
12776 && !strmatch(maybecomm
, "exact-match"))
12777 community
= maybecomm
;
12779 if (argv_find(argv
, argc
, "exact-match", &idx
))
12783 sh_type
= bgp_show_type_community_all
;
12786 if (argv_find(argv
, argc
, "community-list", &idx
)) {
12787 const char *clist_number_or_name
= argv
[++idx
]->arg
;
12788 struct community_list
*list
;
12790 if (argv_find(argv
, argc
, "exact-match", &idx
))
12793 list
= community_list_lookup(bgp_clist
, clist_number_or_name
, 0,
12794 COMMUNITY_LIST_MASTER
);
12795 if (list
== NULL
) {
12796 vty_out(vty
, "%% %s community-list not found\n",
12797 clist_number_or_name
);
12798 return CMD_WARNING
;
12802 sh_type
= bgp_show_type_community_list_exact
;
12804 sh_type
= bgp_show_type_community_list
;
12808 if (argv_find(argv
, argc
, "filter-list", &idx
)) {
12809 const char *filter
= argv
[++idx
]->arg
;
12810 struct as_list
*as_list
;
12812 as_list
= as_list_lookup(filter
);
12813 if (as_list
== NULL
) {
12814 vty_out(vty
, "%% %s AS-path access-list not found\n",
12816 return CMD_WARNING
;
12819 sh_type
= bgp_show_type_filter_list
;
12820 output_arg
= as_list
;
12823 if (argv_find(argv
, argc
, "prefix-list", &idx
)) {
12824 const char *prefix_list_str
= argv
[++idx
]->arg
;
12825 struct prefix_list
*plist
;
12827 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12828 if (plist
== NULL
) {
12829 vty_out(vty
, "%% %s prefix-list not found\n",
12831 return CMD_WARNING
;
12834 sh_type
= bgp_show_type_prefix_list
;
12835 output_arg
= plist
;
12838 if (argv_find(argv
, argc
, "access-list", &idx
)) {
12839 const char *access_list_str
= argv
[++idx
]->arg
;
12840 struct access_list
*alist
;
12842 alist
= access_list_lookup(afi
, access_list_str
);
12844 vty_out(vty
, "%% %s access-list not found\n",
12846 return CMD_WARNING
;
12849 sh_type
= bgp_show_type_access_list
;
12850 output_arg
= alist
;
12853 if (argv_find(argv
, argc
, "route-map", &idx
)) {
12854 const char *rmap_str
= argv
[++idx
]->arg
;
12855 struct route_map
*rmap
;
12857 rmap
= route_map_lookup_by_name(rmap_str
);
12859 vty_out(vty
, "%% %s route-map not found\n", rmap_str
);
12860 return CMD_WARNING
;
12863 sh_type
= bgp_show_type_route_map
;
12867 if (argv_find(argv
, argc
, "rpki", &idx
)) {
12868 sh_type
= bgp_show_type_rpki
;
12869 if (argv_find(argv
, argc
, "valid", &idx
))
12870 rpki_target_state
= RPKI_VALID
;
12871 else if (argv_find(argv
, argc
, "invalid", &idx
))
12872 rpki_target_state
= RPKI_INVALID
;
12875 /* Display prefixes with matching version numbers */
12876 if (argv_find(argv
, argc
, "version", &idx
)) {
12877 sh_type
= bgp_show_type_prefix_version
;
12878 output_arg
= argv
[idx
+ 1]->arg
;
12881 /* Display prefixes with matching BGP community alias */
12882 if (argv_find(argv
, argc
, "alias", &idx
)) {
12883 sh_type
= bgp_show_type_community_alias
;
12884 output_arg
= argv
[idx
+ 1]->arg
;
12887 /* prefix-longer */
12888 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12889 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12890 const char *prefix_str
= argv
[idx
]->arg
;
12892 if (!str2prefix(prefix_str
, &p
)) {
12893 vty_out(vty
, "%% Malformed Prefix\n");
12894 return CMD_WARNING
;
12897 sh_type
= bgp_show_type_prefix_longer
;
12901 /* self originated only */
12902 if (argv_find(argv
, argc
, BGP_SELF_ORIG_CMD_STR
, &idx
))
12903 sh_type
= bgp_show_type_self_originated
;
12906 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12908 return bgp_show_community(vty
, bgp
, community
,
12909 exact_match
, afi
, safi
,
12912 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12913 output_arg
, show_flags
,
12914 rpki_target_state
);
12916 struct listnode
*node
;
12918 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12922 vty_out(vty
, "{\n");
12924 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12925 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12926 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12929 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12930 FOREACH_SAFI (safi
) {
12931 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12939 vty_out(vty
, ",\n");
12940 vty_out(vty
, "\"%s\":{\n",
12941 get_afi_safi_str(afi
,
12946 "\nFor address family: %s\n",
12952 bgp_show_community(
12953 vty
, abgp
, community
,
12954 exact_match
, afi
, safi
,
12957 bgp_show(vty
, abgp
, afi
, safi
,
12958 sh_type
, output_arg
,
12960 rpki_target_state
);
12962 vty_out(vty
, "}\n");
12966 /* show <ip> bgp all: for each AFI and SAFI*/
12967 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
12968 FOREACH_AFI_SAFI (afi
, safi
) {
12969 if (!bgp_afi_safi_peer_exists(abgp
, afi
,
12977 vty_out(vty
, ",\n");
12979 vty_out(vty
, "\"%s\":{\n",
12980 get_afi_safi_str(afi
,
12985 "\nFor address family: %s\n",
12991 bgp_show_community(
12992 vty
, abgp
, community
,
12993 exact_match
, afi
, safi
,
12996 bgp_show(vty
, abgp
, afi
, safi
,
12997 sh_type
, output_arg
,
12999 rpki_target_state
);
13001 vty_out(vty
, "}\n");
13006 vty_out(vty
, "}\n");
13008 return CMD_SUCCESS
;
13011 DEFUN (show_ip_bgp_route
,
13012 show_ip_bgp_route_cmd
,
13013 "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]",
13017 BGP_INSTANCE_HELP_STR
13019 BGP_SAFI_WITH_LABEL_HELP_STR
13020 "Network in the BGP routing table to display\n"
13022 "Network in the BGP routing table to display\n"
13024 "Display only the bestpath\n"
13025 "Display only multipaths\n"
13026 "Display only paths that match the specified rpki state\n"
13027 "A valid path as determined by rpki\n"
13028 "A invalid path as determined by rpki\n"
13029 "A path that has no rpki data\n"
13032 int prefix_check
= 0;
13034 afi_t afi
= AFI_IP6
;
13035 safi_t safi
= SAFI_UNICAST
;
13036 char *prefix
= NULL
;
13037 struct bgp
*bgp
= NULL
;
13038 enum bgp_path_type path_type
;
13039 bool uj
= use_json(argc
, argv
);
13043 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13046 return CMD_WARNING
;
13050 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13051 return CMD_WARNING
;
13054 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13055 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
13056 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
13058 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
13059 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
13062 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
13063 && afi
!= AFI_IP6
) {
13065 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13066 return CMD_WARNING
;
13068 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
13069 && afi
!= AFI_IP
) {
13071 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13072 return CMD_WARNING
;
13075 prefix
= argv
[idx
]->arg
;
13077 /* [<bestpath|multipath>] */
13078 if (argv_find(argv
, argc
, "bestpath", &idx
))
13079 path_type
= BGP_PATH_SHOW_BESTPATH
;
13080 else if (argv_find(argv
, argc
, "multipath", &idx
))
13081 path_type
= BGP_PATH_SHOW_MULTIPATH
;
13083 path_type
= BGP_PATH_SHOW_ALL
;
13085 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
13086 path_type
, RPKI_NOT_BEING_USED
, uj
);
13089 DEFUN (show_ip_bgp_regexp
,
13090 show_ip_bgp_regexp_cmd
,
13091 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
13095 BGP_INSTANCE_HELP_STR
13097 BGP_SAFI_WITH_LABEL_HELP_STR
13098 "Display routes matching the AS path regular expression\n"
13099 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13102 afi_t afi
= AFI_IP6
;
13103 safi_t safi
= SAFI_UNICAST
;
13104 struct bgp
*bgp
= NULL
;
13105 bool uj
= use_json(argc
, argv
);
13106 char *regstr
= NULL
;
13109 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13112 return CMD_WARNING
;
13114 // get index of regex
13115 if (argv_find(argv
, argc
, "REGEX", &idx
))
13116 regstr
= argv
[idx
]->arg
;
13119 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
13120 bgp_show_type_regexp
, uj
);
13123 DEFPY (show_ip_bgp_instance_all
,
13124 show_ip_bgp_instance_all_cmd
,
13125 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
13129 BGP_INSTANCE_ALL_HELP_STR
13131 BGP_SAFI_WITH_LABEL_HELP_STR
13133 "Increase table width for longer prefixes\n")
13135 afi_t afi
= AFI_IP6
;
13136 safi_t safi
= SAFI_UNICAST
;
13137 struct bgp
*bgp
= NULL
;
13139 uint16_t show_flags
= 0;
13143 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13147 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13149 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13152 return CMD_WARNING
;
13154 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
13155 return CMD_SUCCESS
;
13158 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
13159 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
13164 uint16_t show_flags
= 0;
13167 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13169 if (!config_bgp_aspath_validate(regstr
)) {
13170 vty_out(vty
, "Invalid character in REGEX %s\n",
13172 return CMD_WARNING_CONFIG_FAILED
;
13175 regex
= bgp_regcomp(regstr
);
13177 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
13178 return CMD_WARNING
;
13181 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
,
13182 RPKI_NOT_BEING_USED
);
13183 bgp_regex_free(regex
);
13187 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
13188 const char *comstr
, int exact
, afi_t afi
,
13189 safi_t safi
, uint16_t show_flags
)
13191 struct community
*com
;
13194 com
= community_str2com(comstr
);
13196 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
13197 return CMD_WARNING
;
13200 ret
= bgp_show(vty
, bgp
, afi
, safi
,
13201 (exact
? bgp_show_type_community_exact
13202 : bgp_show_type_community
),
13203 com
, show_flags
, RPKI_NOT_BEING_USED
);
13204 community_free(&com
);
13210 BGP_STATS_MAXBITLEN
= 0,
13212 BGP_STATS_PREFIXES
,
13214 BGP_STATS_UNAGGREGATEABLE
,
13215 BGP_STATS_MAX_AGGREGATEABLE
,
13216 BGP_STATS_AGGREGATES
,
13218 BGP_STATS_ASPATH_COUNT
,
13219 BGP_STATS_ASPATH_MAXHOPS
,
13220 BGP_STATS_ASPATH_TOTHOPS
,
13221 BGP_STATS_ASPATH_MAXSIZE
,
13222 BGP_STATS_ASPATH_TOTSIZE
,
13223 BGP_STATS_ASN_HIGHEST
,
13227 #define TABLE_STATS_IDX_VTY 0
13228 #define TABLE_STATS_IDX_JSON 1
13230 static const char *table_stats_strs
[][2] = {
13231 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
13232 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
13233 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
13234 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
13235 "unaggregateablePrefixes"},
13236 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
13237 "maximumAggregateablePrefixes"},
13238 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
13239 "bgpAggregateAdvertisements"},
13240 [BGP_STATS_SPACE
] = {"Address space advertised",
13241 "addressSpaceAdvertised"},
13242 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
13243 "advertisementsWithPaths"},
13244 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
13246 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
13248 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
13249 "averageAsPathLengthHops"},
13250 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
13251 "averageAsPathSizeBytes"},
13252 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
13253 [BGP_STATS_MAX
] = {NULL
, NULL
}
13256 struct bgp_table_stats
{
13257 struct bgp_table
*table
;
13258 unsigned long long counts
[BGP_STATS_MAX
];
13261 prefix_len_count
[MAX(EVPN_ROUTE_PREFIXLEN
, IPV6_MAX_BITLEN
) +
13264 double total_space
;
13267 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
13268 struct bgp_table_stats
*ts
, unsigned int space
)
13270 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
13271 struct bgp_path_info
*pi
;
13272 const struct prefix
*rn_p
;
13274 if (!bgp_dest_has_bgp_path_info_data(dest
))
13277 rn_p
= bgp_dest_get_prefix(dest
);
13278 ts
->counts
[BGP_STATS_PREFIXES
]++;
13279 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
13281 ts
->prefix_len_count
[rn_p
->prefixlen
]++;
13282 /* check if the prefix is included by any other announcements */
13283 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
13284 pdest
= bgp_dest_parent_nolock(pdest
);
13286 if (pdest
== NULL
|| pdest
== top
) {
13287 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
13288 /* announced address space */
13290 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
13291 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
13292 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
13295 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
13296 ts
->counts
[BGP_STATS_RIB
]++;
13298 if (CHECK_FLAG(pi
->attr
->flag
,
13299 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
13300 ts
->counts
[BGP_STATS_AGGREGATES
]++;
13302 /* as-path stats */
13303 if (pi
->attr
->aspath
) {
13304 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
13305 unsigned int size
= aspath_size(pi
->attr
->aspath
);
13306 as_t highest
= aspath_highest(pi
->attr
->aspath
);
13308 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
13310 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
13311 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
13313 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
13314 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
13316 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
13317 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
13318 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
13319 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
13324 static void bgp_table_stats_walker(struct event
*t
)
13326 struct bgp_dest
*dest
, *ndest
;
13327 struct bgp_dest
*top
;
13328 struct bgp_table_stats
*ts
= EVENT_ARG(t
);
13329 unsigned int space
= 0;
13331 if (!(top
= bgp_table_top(ts
->table
)))
13334 switch (ts
->table
->afi
) {
13336 space
= IPV4_MAX_BITLEN
;
13339 space
= IPV6_MAX_BITLEN
;
13342 space
= EVPN_ROUTE_PREFIXLEN
;
13349 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
13351 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
13352 if (ts
->table
->safi
== SAFI_MPLS_VPN
13353 || ts
->table
->safi
== SAFI_ENCAP
13354 || ts
->table
->safi
== SAFI_EVPN
) {
13355 struct bgp_table
*table
;
13357 table
= bgp_dest_get_bgp_table_info(dest
);
13361 top
= bgp_table_top(table
);
13362 for (ndest
= bgp_table_top(table
); ndest
;
13363 ndest
= bgp_route_next(ndest
))
13364 bgp_table_stats_rn(ndest
, top
, ts
, space
);
13366 bgp_table_stats_rn(dest
, top
, ts
, space
);
13371 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
13372 struct json_object
*json_array
)
13374 struct listnode
*node
, *nnode
;
13377 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
13378 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13381 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13382 safi_t safi
, struct json_object
*json_array
)
13384 struct bgp_table_stats ts
;
13386 int ret
= CMD_SUCCESS
;
13388 struct json_object
*json
= NULL
;
13389 uint32_t bitlen
= 0;
13390 struct json_object
*json_bitlen
;
13393 json
= json_object_new_object();
13395 if (!bgp
->rib
[afi
][safi
]) {
13396 char warning_msg
[50];
13398 snprintf(warning_msg
, sizeof(warning_msg
),
13399 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
13403 vty_out(vty
, "%s\n", warning_msg
);
13405 json_object_string_add(json
, "warning", warning_msg
);
13408 goto end_table_stats
;
13412 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
13413 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
13415 json_object_string_add(json
, "instance", bgp
->name_pretty
);
13417 /* labeled-unicast routes live in the unicast table */
13418 if (safi
== SAFI_LABELED_UNICAST
)
13419 safi
= SAFI_UNICAST
;
13421 memset(&ts
, 0, sizeof(ts
));
13422 ts
.table
= bgp
->rib
[afi
][safi
];
13423 event_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
13425 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
13426 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
13427 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
13431 case BGP_STATS_ASPATH_TOTHOPS
:
13432 case BGP_STATS_ASPATH_TOTSIZE
:
13435 temp_buf
, sizeof(temp_buf
), "%12.2f",
13437 ? (float)ts
.counts
[i
]
13439 [BGP_STATS_ASPATH_COUNT
]
13441 vty_out(vty
, "%-30s: %s",
13442 table_stats_strs
[i
]
13443 [TABLE_STATS_IDX_VTY
],
13446 json_object_double_add(
13448 table_stats_strs
[i
]
13449 [TABLE_STATS_IDX_JSON
],
13451 ? (double)ts
.counts
[i
]
13452 / (double)ts
.counts
13453 [BGP_STATS_ASPATH_COUNT
]
13457 case BGP_STATS_TOTPLEN
:
13460 temp_buf
, sizeof(temp_buf
), "%12.2f",
13462 ? (float)ts
.counts
[i
]
13464 [BGP_STATS_PREFIXES
]
13466 vty_out(vty
, "%-30s: %s",
13467 table_stats_strs
[i
]
13468 [TABLE_STATS_IDX_VTY
],
13471 json_object_double_add(
13473 table_stats_strs
[i
]
13474 [TABLE_STATS_IDX_JSON
],
13476 ? (double)ts
.counts
[i
]
13477 / (double)ts
.counts
13478 [BGP_STATS_PREFIXES
]
13482 case BGP_STATS_SPACE
:
13484 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
13486 vty_out(vty
, "%-30s: %s\n",
13487 table_stats_strs
[i
]
13488 [TABLE_STATS_IDX_VTY
],
13491 json_object_double_add(
13493 table_stats_strs
[i
]
13494 [TABLE_STATS_IDX_JSON
],
13495 (double)ts
.total_space
);
13497 if (afi
== AFI_IP6
) {
13499 snprintf(temp_buf
, sizeof(temp_buf
),
13502 * pow(2.0, -128 + 32));
13503 vty_out(vty
, "%30s: %s\n",
13504 "/32 equivalent %s\n",
13507 json_object_double_add(
13508 json
, "/32equivalent",
13509 (double)(ts
.total_space
13514 snprintf(temp_buf
, sizeof(temp_buf
),
13517 * pow(2.0, -128 + 48));
13518 vty_out(vty
, "%30s: %s\n",
13519 "/48 equivalent %s\n",
13522 json_object_double_add(
13523 json
, "/48equivalent",
13524 (double)(ts
.total_space
13530 snprintf(temp_buf
, sizeof(temp_buf
),
13532 ts
.total_space
* 100.
13534 vty_out(vty
, "%30s: %s\n",
13535 "% announced ", temp_buf
);
13537 json_object_double_add(
13538 json
, "%announced",
13539 (double)(ts
.total_space
* 100.
13543 snprintf(temp_buf
, sizeof(temp_buf
),
13546 * pow(2.0, -32 + 8));
13547 vty_out(vty
, "%30s: %s\n",
13548 "/8 equivalent ", temp_buf
);
13550 json_object_double_add(
13551 json
, "/8equivalent",
13552 (double)(ts
.total_space
13553 * pow(2.0, -32 + 8)));
13556 snprintf(temp_buf
, sizeof(temp_buf
),
13559 * pow(2.0, -32 + 24));
13560 vty_out(vty
, "%30s: %s\n",
13561 "/24 equivalent ", temp_buf
);
13563 json_object_double_add(
13564 json
, "/24equivalent",
13565 (double)(ts
.total_space
13566 * pow(2.0, -32 + 24)));
13572 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
13574 vty_out(vty
, "%-30s: %s",
13575 table_stats_strs
[i
]
13576 [TABLE_STATS_IDX_VTY
],
13579 json_object_int_add(
13581 table_stats_strs
[i
]
13582 [TABLE_STATS_IDX_JSON
],
13587 vty_out(vty
, "\n");
13592 bitlen
= IPV4_MAX_BITLEN
;
13595 bitlen
= IPV6_MAX_BITLEN
;
13598 bitlen
= EVPN_ROUTE_PREFIXLEN
;
13606 json_bitlen
= json_object_new_array();
13608 for (i
= 0; i
<= bitlen
; i
++) {
13609 struct json_object
*ind_bit
= json_object_new_object();
13611 if (!ts
.prefix_len_count
[i
])
13614 snprintf(temp_buf
, sizeof(temp_buf
), "%u", i
);
13615 json_object_int_add(ind_bit
, temp_buf
,
13616 ts
.prefix_len_count
[i
]);
13617 json_object_array_add(json_bitlen
, ind_bit
);
13619 json_object_object_add(json
, "prefixLength", json_bitlen
);
13624 json_object_array_add(json_array
, json
);
13628 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13629 safi_t safi
, struct json_object
*json_array
)
13632 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
13633 return CMD_SUCCESS
;
13636 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
13648 PCOUNT_BPATH_SELECTED
,
13649 PCOUNT_PFCNT
, /* the figure we display to users */
13653 static const char *const pcount_strs
[] = {
13654 [PCOUNT_ADJ_IN
] = "Adj-in",
13655 [PCOUNT_DAMPED
] = "Damped",
13656 [PCOUNT_REMOVED
] = "Removed",
13657 [PCOUNT_HISTORY
] = "History",
13658 [PCOUNT_STALE
] = "Stale",
13659 [PCOUNT_VALID
] = "Valid",
13660 [PCOUNT_ALL
] = "All RIB",
13661 [PCOUNT_COUNTED
] = "PfxCt counted",
13662 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
13663 [PCOUNT_PFCNT
] = "Useable",
13664 [PCOUNT_MAX
] = NULL
,
13667 struct peer_pcounts
{
13668 unsigned int count
[PCOUNT_MAX
];
13669 const struct peer
*peer
;
13670 const struct bgp_table
*table
;
13674 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
13676 const struct bgp_adj_in
*ain
;
13677 const struct bgp_path_info
*pi
;
13678 const struct peer
*peer
= pc
->peer
;
13680 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
13681 if (ain
->peer
== peer
)
13682 pc
->count
[PCOUNT_ADJ_IN
]++;
13684 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
13686 if (pi
->peer
!= peer
)
13689 pc
->count
[PCOUNT_ALL
]++;
13691 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
13692 pc
->count
[PCOUNT_DAMPED
]++;
13693 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
13694 pc
->count
[PCOUNT_HISTORY
]++;
13695 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
13696 pc
->count
[PCOUNT_REMOVED
]++;
13697 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
13698 pc
->count
[PCOUNT_STALE
]++;
13699 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
13700 pc
->count
[PCOUNT_VALID
]++;
13701 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13702 pc
->count
[PCOUNT_PFCNT
]++;
13703 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13704 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
13706 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
13707 pc
->count
[PCOUNT_COUNTED
]++;
13708 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13710 EC_LIB_DEVELOPMENT
,
13711 "Attempting to count but flags say it is unusable");
13713 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
13715 EC_LIB_DEVELOPMENT
,
13716 "Not counted but flags say we should");
13721 static void bgp_peer_count_walker(struct event
*t
)
13723 struct bgp_dest
*rn
, *rm
;
13724 const struct bgp_table
*table
;
13725 struct peer_pcounts
*pc
= EVENT_ARG(t
);
13727 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
13728 || pc
->safi
== SAFI_EVPN
) {
13729 /* Special handling for 2-level routing tables. */
13730 for (rn
= bgp_table_top(pc
->table
); rn
;
13731 rn
= bgp_route_next(rn
)) {
13732 table
= bgp_dest_get_bgp_table_info(rn
);
13734 for (rm
= bgp_table_top(table
); rm
;
13735 rm
= bgp_route_next(rm
))
13736 bgp_peer_count_proc(rm
, pc
);
13739 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
13740 bgp_peer_count_proc(rn
, pc
);
13743 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13744 safi_t safi
, bool use_json
)
13746 struct peer_pcounts pcounts
= {.peer
= peer
};
13748 json_object
*json
= NULL
;
13749 json_object
*json_loop
= NULL
;
13752 json
= json_object_new_object();
13753 json_loop
= json_object_new_object();
13756 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
13757 || !peer
->bgp
->rib
[afi
][safi
]) {
13759 json_object_string_add(
13761 "No such neighbor or address family");
13762 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13763 json_object_free(json
);
13764 json_object_free(json_loop
);
13766 vty_out(vty
, "%% No such neighbor or address family\n");
13768 return CMD_WARNING
;
13771 memset(&pcounts
, 0, sizeof(pcounts
));
13772 pcounts
.peer
= peer
;
13773 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
13774 pcounts
.safi
= safi
;
13776 /* in-place call via thread subsystem so as to record execution time
13777 * stats for the thread-walk (i.e. ensure this can't be blamed on
13778 * on just vty_read()).
13780 event_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
13783 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
13784 json_object_string_add(json
, "multiProtocol",
13785 get_afi_safi_str(afi
, safi
, true));
13786 json_object_int_add(json
, "pfxCounter",
13787 peer
->pcount
[afi
][safi
]);
13789 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13790 json_object_int_add(json_loop
, pcount_strs
[i
],
13793 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
13795 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13796 json_object_string_add(json
, "pfxctDriftFor",
13798 json_object_string_add(
13799 json
, "recommended",
13800 "Please report this bug, with the above command output");
13802 vty_json(vty
, json
);
13806 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
13807 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
13808 peer
->hostname
, peer
->host
,
13809 get_afi_safi_str(afi
, safi
, false));
13811 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
13812 get_afi_safi_str(afi
, safi
, false));
13815 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
13816 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
13818 for (i
= 0; i
< PCOUNT_MAX
; i
++)
13819 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
13822 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
13823 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
13825 "Please report this bug, with the above command output\n");
13829 return CMD_SUCCESS
;
13832 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
13833 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
13834 "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]",
13838 BGP_INSTANCE_HELP_STR
13841 "Detailed information on TCP and BGP neighbor connections\n"
13842 "Neighbor to display information about\n"
13843 "Neighbor to display information about\n"
13844 "Neighbor on BGP configured interface\n"
13845 "Display detailed prefix count information\n"
13848 afi_t afi
= AFI_IP6
;
13849 safi_t safi
= SAFI_UNICAST
;
13852 struct bgp
*bgp
= NULL
;
13853 bool uj
= use_json(argc
, argv
);
13858 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13861 return CMD_WARNING
;
13863 argv_find(argv
, argc
, "neighbors", &idx
);
13864 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
13866 return CMD_WARNING
;
13868 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
13871 #ifdef KEEP_OLD_VPN_COMMANDS
13872 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
13873 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
13874 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13879 "Display information about all VPNv4 NLRIs\n"
13880 "Detailed information on TCP and BGP neighbor connections\n"
13881 "Neighbor to display information about\n"
13882 "Neighbor to display information about\n"
13883 "Neighbor on BGP configured interface\n"
13884 "Display detailed prefix count information\n"
13889 bool uj
= use_json(argc
, argv
);
13891 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
13893 return CMD_WARNING
;
13895 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
13898 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
13899 show_ip_bgp_vpn_all_route_prefix_cmd
,
13900 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13905 "Display information about all VPNv4 NLRIs\n"
13906 "Network in the BGP routing table to display\n"
13907 "Network in the BGP routing table to display\n"
13911 char *network
= NULL
;
13912 struct bgp
*bgp
= bgp_get_default();
13914 vty_out(vty
, "Can't find default instance\n");
13915 return CMD_WARNING
;
13918 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
13919 network
= argv
[idx
]->arg
;
13920 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
13921 network
= argv
[idx
]->arg
;
13923 vty_out(vty
, "Unable to figure out Network\n");
13924 return CMD_WARNING
;
13927 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
13928 BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
13929 use_json(argc
, argv
));
13931 #endif /* KEEP_OLD_VPN_COMMANDS */
13933 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
13934 show_bgp_l2vpn_evpn_route_prefix_cmd
,
13935 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13940 "Network in the BGP routing table to display\n"
13941 "Network in the BGP routing table to display\n"
13942 "Network in the BGP routing table to display\n"
13943 "Network in the BGP routing table to display\n"
13947 char *network
= NULL
;
13948 int prefix_check
= 0;
13950 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13951 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13952 network
= argv
[idx
]->arg
;
13953 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13954 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
13955 network
= argv
[idx
]->arg
;
13958 vty_out(vty
, "Unable to figure out Network\n");
13959 return CMD_WARNING
;
13961 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13962 prefix_check
, BGP_PATH_SHOW_ALL
,
13963 RPKI_NOT_BEING_USED
, use_json(argc
, argv
));
13966 static void show_adj_route_header(struct vty
*vty
, struct peer
*peer
,
13967 struct bgp_table
*table
, int *header1
,
13968 int *header2
, json_object
*json
,
13969 json_object
*json_scode
,
13970 json_object
*json_ocode
, bool wide
,
13973 uint64_t version
= table
? table
->version
: 0;
13977 json_object_int_add(json
, "bgpTableVersion", version
);
13978 json_object_string_addf(json
, "bgpLocalRouterId",
13979 "%pI4", &peer
->bgp
->router_id
);
13980 json_object_int_add(json
, "defaultLocPrf",
13981 peer
->bgp
->default_local_pref
);
13982 json_object_int_add(json
, "localAS",
13983 peer
->change_local_as
13984 ? peer
->change_local_as
13986 json_object_object_add(json
, "bgpStatusCodes",
13988 json_object_object_add(json
, "bgpOriginCodes",
13992 "BGP table version is %" PRIu64
13993 ", local router ID is %pI4, vrf id ",
13994 version
, &peer
->bgp
->router_id
);
13995 if (peer
->bgp
->vrf_id
== VRF_UNKNOWN
)
13996 vty_out(vty
, "%s", VRFID_NONE_STR
);
13998 vty_out(vty
, "%u", peer
->bgp
->vrf_id
);
13999 vty_out(vty
, "\n");
14000 vty_out(vty
, "Default local pref %u, ",
14001 peer
->bgp
->default_local_pref
);
14002 vty_out(vty
, "local AS %u\n",
14003 peer
->change_local_as
? peer
->change_local_as
14006 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14007 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14008 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14009 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14015 if (!json
&& !detail
)
14016 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
14017 : BGP_SHOW_HEADER
));
14023 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
14024 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
14025 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
14026 json_object
*json_scode
, json_object
*json_ocode
,
14027 uint16_t show_flags
, int *header1
, int *header2
, char *rd_str
,
14028 const struct prefix
*match
, unsigned long *output_count
,
14029 unsigned long *filtered_count
)
14031 struct bgp_adj_in
*ain
= NULL
;
14032 struct bgp_adj_out
*adj
= NULL
;
14033 struct bgp_dest
*dest
;
14037 struct update_subgroup
*subgrp
;
14038 struct peer_af
*paf
= NULL
;
14039 bool route_filtered
;
14040 bool detail
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14041 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14042 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14043 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14044 || (safi
== SAFI_EVPN
))
14048 json_object
*json_net
= NULL
;
14052 /* If the user supplied a prefix, look for a matching route instead
14053 * of walking the whole table.
14056 dest
= bgp_node_match(table
, match
);
14059 vty_out(vty
, "Network not in table\n");
14063 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
14065 if (rn_p
->prefixlen
!= match
->prefixlen
) {
14067 vty_out(vty
, "Network not in table\n");
14068 bgp_dest_unlock_node(dest
);
14072 if (type
== bgp_show_adj_route_received
||
14073 type
== bgp_show_adj_route_filtered
) {
14074 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14075 if (ain
->peer
== peer
) {
14080 /* bail out if if adj_out is empty, or
14081 * if the prefix isn't in this peer's
14084 if (!ain
|| ain
->peer
!= peer
) {
14086 vty_out(vty
, "Network not in table\n");
14087 bgp_dest_unlock_node(dest
);
14090 } else if (type
== bgp_show_adj_route_advertised
) {
14091 bool peer_found
= false;
14093 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
) {
14094 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14095 if (paf
->peer
== peer
&& adj
->attr
) {
14104 /* bail out if if adj_out is empty, or
14105 * if the prefix isn't in this peer's
14108 if (!paf
|| !peer_found
) {
14110 vty_out(vty
, "Network not in table\n");
14111 bgp_dest_unlock_node(dest
);
14116 ret
= bgp_output_modifier(peer
, rn_p
, &attr
, afi
, safi
,
14119 if (ret
!= RMAP_DENY
) {
14120 show_adj_route_header(vty
, peer
, table
, header1
,
14121 header2
, json
, json_scode
,
14122 json_ocode
, wide
, detail
);
14125 json_net
= json_object_new_object();
14127 bgp_show_path_info(NULL
/* prefix_rd */, dest
, vty
, bgp
,
14128 afi
, safi
, json_net
,
14129 BGP_PATH_SHOW_ALL
, &display
,
14130 RPKI_NOT_BEING_USED
);
14132 json_object_object_addf(json_ar
, json_net
,
14136 (*filtered_count
)++;
14138 bgp_attr_flush(&attr
);
14139 bgp_dest_unlock_node(dest
);
14144 subgrp
= peer_subgroup(peer
, afi
, safi
);
14146 if (type
== bgp_show_adj_route_advertised
&& subgrp
14147 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
14149 json_object_int_add(json
, "bgpTableVersion",
14151 json_object_string_addf(json
, "bgpLocalRouterId",
14152 "%pI4", &bgp
->router_id
);
14153 json_object_int_add(json
, "defaultLocPrf",
14154 bgp
->default_local_pref
);
14155 json_object_int_add(json
, "localAS",
14156 peer
->change_local_as
14157 ? peer
->change_local_as
14159 json_object_object_add(json
, "bgpStatusCodes",
14161 json_object_object_add(json
, "bgpOriginCodes",
14163 json_object_string_add(
14164 json
, "bgpOriginatingDefaultNetwork",
14165 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14168 "BGP table version is %" PRIu64
14169 ", local router ID is %pI4, vrf id ",
14170 table
->version
, &bgp
->router_id
);
14171 if (bgp
->vrf_id
== VRF_UNKNOWN
)
14172 vty_out(vty
, "%s", VRFID_NONE_STR
);
14174 vty_out(vty
, "%u", bgp
->vrf_id
);
14175 vty_out(vty
, "\n");
14176 vty_out(vty
, "Default local pref %u, ",
14177 bgp
->default_local_pref
);
14178 vty_out(vty
, "local AS %u\n",
14179 peer
->change_local_as
? peer
->change_local_as
14182 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
14183 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
14184 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
14185 vty_out(vty
, BGP_SHOW_RPKI_HEADER
);
14188 vty_out(vty
, "Originating default network %s\n\n",
14189 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
14195 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
14196 if (type
== bgp_show_adj_route_received
14197 || type
== bgp_show_adj_route_filtered
) {
14198 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
14199 if (ain
->peer
!= peer
)
14202 show_adj_route_header(vty
, peer
, table
, header1
,
14203 header2
, json
, json_scode
,
14204 json_ocode
, wide
, detail
);
14206 if ((safi
== SAFI_MPLS_VPN
)
14207 || (safi
== SAFI_ENCAP
)
14208 || (safi
== SAFI_EVPN
)) {
14210 json_object_string_add(
14211 json_ar
, "rd", rd_str
);
14212 else if (show_rd
&& rd_str
) {
14214 "Route Distinguisher: %s\n",
14221 route_filtered
= false;
14223 /* Filter prefix using distribute list,
14224 * filter list or prefix list
14226 const struct prefix
*rn_p
=
14227 bgp_dest_get_prefix(dest
);
14228 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
14231 route_filtered
= true;
14233 /* Filter prefix using route-map */
14234 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
14235 safi
, rmap_name
, NULL
,
14238 if (type
== bgp_show_adj_route_filtered
&&
14239 !route_filtered
&& ret
!= RMAP_DENY
) {
14240 bgp_attr_flush(&attr
);
14244 if (type
== bgp_show_adj_route_received
14245 && (route_filtered
|| ret
== RMAP_DENY
))
14246 (*filtered_count
)++;
14251 json_object_new_object();
14252 bgp_show_path_info(
14253 NULL
/* prefix_rd */, dest
, vty
,
14254 bgp
, afi
, safi
, json_net
,
14255 BGP_PATH_SHOW_ALL
, &display
,
14256 RPKI_NOT_BEING_USED
);
14258 json_object_object_addf(
14262 route_vty_out_tmp(vty
, dest
, rn_p
,
14263 &attr
, safi
, use_json
,
14265 bgp_attr_flush(&attr
);
14268 } else if (type
== bgp_show_adj_route_advertised
) {
14269 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
14270 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
14271 if (paf
->peer
!= peer
|| !adj
->attr
)
14274 show_adj_route_header(
14275 vty
, peer
, table
, header1
,
14276 header2
, json
, json_scode
,
14277 json_ocode
, wide
, detail
);
14279 const struct prefix
*rn_p
=
14280 bgp_dest_get_prefix(dest
);
14283 ret
= bgp_output_modifier(
14284 peer
, rn_p
, &attr
, afi
, safi
,
14287 if (ret
!= RMAP_DENY
) {
14288 if ((safi
== SAFI_MPLS_VPN
)
14289 || (safi
== SAFI_ENCAP
)
14290 || (safi
== SAFI_EVPN
)) {
14292 json_object_string_add(
14299 "Route Distinguisher: %s\n",
14307 json_object_new_object();
14308 bgp_show_path_info(
14317 RPKI_NOT_BEING_USED
);
14319 json_object_object_addf(
14332 (*filtered_count
)++;
14335 bgp_attr_flush(&attr
);
14337 } else if (type
== bgp_show_adj_route_bestpath
) {
14338 struct bgp_path_info
*pi
;
14340 show_adj_route_header(vty
, peer
, table
, header1
,
14341 header2
, json
, json_scode
,
14342 json_ocode
, wide
, detail
);
14344 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
14346 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
14348 if (pi
->peer
!= peer
)
14351 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
14357 json_object_new_object();
14358 bgp_show_path_info(
14359 NULL
/* prefix_rd */, dest
, vty
,
14360 bgp
, afi
, safi
, json_net
,
14361 BGP_PATH_SHOW_BESTPATH
,
14362 &display
, RPKI_NOT_BEING_USED
);
14364 json_object_object_addf(
14369 vty
, dest
, rn_p
, pi
->attr
, safi
,
14370 use_json
, json_ar
, wide
);
14377 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
14378 safi_t safi
, enum bgp_show_adj_route_type type
,
14379 const char *rmap_name
, const struct prefix
*match
,
14380 uint16_t show_flags
)
14383 struct bgp_table
*table
;
14384 json_object
*json
= NULL
;
14385 json_object
*json_scode
= NULL
;
14386 json_object
*json_ocode
= NULL
;
14387 json_object
*json_ar
= NULL
;
14388 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14390 /* Init BGP headers here so they're only displayed once
14391 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14397 * Initialize variables for each RD
14398 * All prefixes under an RD is aggregated within "json_routes"
14400 char rd_str
[BUFSIZ
] = {0};
14401 json_object
*json_routes
= NULL
;
14404 /* For 2-tier tables, prefix counts need to be
14405 * maintained across multiple runs of show_adj_route()
14407 unsigned long output_count_per_rd
;
14408 unsigned long filtered_count_per_rd
;
14409 unsigned long output_count
= 0;
14410 unsigned long filtered_count
= 0;
14413 json
= json_object_new_object();
14414 json_ar
= json_object_new_object();
14415 json_scode
= json_object_new_object();
14416 json_ocode
= json_object_new_object();
14417 #if CONFDATE > 20231208
14418 CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14420 json_object_string_add(json_scode
, "suppressed", "s");
14421 json_object_string_add(json_scode
, "damped", "d");
14422 json_object_string_add(json_scode
, "history", "h");
14423 json_object_string_add(json_scode
, "valid", "*");
14424 json_object_string_add(json_scode
, "best", ">");
14425 json_object_string_add(json_scode
, "multipath", "=");
14426 json_object_string_add(json_scode
, "internal", "i");
14427 json_object_string_add(json_scode
, "ribFailure", "r");
14428 json_object_string_add(json_scode
, "stale", "S");
14429 json_object_string_add(json_scode
, "removed", "R");
14431 #if CONFDATE > 20231208
14432 CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14434 json_object_string_add(json_ocode
, "igp", "i");
14435 json_object_string_add(json_ocode
, "egp", "e");
14436 json_object_string_add(json_ocode
, "incomplete", "?");
14439 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14441 json_object_string_add(
14443 "No such neighbor or address family");
14444 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14445 json_object_free(json
);
14446 json_object_free(json_ar
);
14447 json_object_free(json_scode
);
14448 json_object_free(json_ocode
);
14450 vty_out(vty
, "%% No such neighbor or address family\n");
14452 return CMD_WARNING
;
14455 if ((type
== bgp_show_adj_route_received
14456 || type
== bgp_show_adj_route_filtered
)
14457 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
14458 PEER_FLAG_SOFT_RECONFIG
)) {
14460 json_object_string_add(
14462 "Inbound soft reconfiguration not enabled");
14463 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
14464 json_object_free(json
);
14465 json_object_free(json_ar
);
14466 json_object_free(json_scode
);
14467 json_object_free(json_ocode
);
14470 "%% Inbound soft reconfiguration not enabled\n");
14472 return CMD_WARNING
;
14477 /* labeled-unicast routes live in the unicast table */
14478 if (safi
== SAFI_LABELED_UNICAST
)
14479 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
14481 table
= bgp
->rib
[afi
][safi
];
14483 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14484 || (safi
== SAFI_EVPN
)) {
14486 struct bgp_dest
*dest
;
14488 for (dest
= bgp_table_top(table
); dest
;
14489 dest
= bgp_route_next(dest
)) {
14490 table
= bgp_dest_get_bgp_table_info(dest
);
14494 output_count_per_rd
= 0;
14495 filtered_count_per_rd
= 0;
14498 json_routes
= json_object_new_object();
14500 const struct prefix_rd
*prd
;
14501 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14504 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
),
14508 vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14509 json
, json_routes
, json_scode
, json_ocode
,
14510 show_flags
, &header1
, &header2
, rd_str
, match
,
14511 &output_count_per_rd
, &filtered_count_per_rd
);
14513 /* Don't include an empty RD in the output! */
14514 if (json_routes
&& (output_count_per_rd
> 0))
14515 json_object_object_add(json_ar
, rd_str
,
14518 output_count
+= output_count_per_rd
;
14519 filtered_count
+= filtered_count_per_rd
;
14522 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
14523 json
, json_ar
, json_scode
, json_ocode
,
14524 show_flags
, &header1
, &header2
, rd_str
, match
,
14525 &output_count
, &filtered_count
);
14528 if (type
== bgp_show_adj_route_advertised
)
14529 json_object_object_add(json
, "advertisedRoutes",
14532 json_object_object_add(json
, "receivedRoutes", json_ar
);
14533 json_object_int_add(json
, "totalPrefixCounter", output_count
);
14534 json_object_int_add(json
, "filteredPrefixCounter",
14538 * These fields only give up ownership to `json` when `header1`
14539 * is used (set to zero). See code in `show_adj_route` and
14540 * `show_adj_route_header`.
14542 if (header1
== 1) {
14543 json_object_free(json_scode
);
14544 json_object_free(json_ocode
);
14547 vty_json(vty
, json
);
14548 } else if (output_count
> 0) {
14549 if (!match
&& filtered_count
> 0)
14551 "\nTotal number of prefixes %ld (%ld filtered)\n",
14552 output_count
, filtered_count
);
14554 vty_out(vty
, "\nTotal number of prefixes %ld\n",
14558 return CMD_SUCCESS
;
14561 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
14562 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
14563 "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]",
14567 BGP_INSTANCE_HELP_STR
14569 BGP_SAFI_WITH_LABEL_HELP_STR
14570 "Detailed information on TCP and BGP neighbor connections\n"
14571 "Neighbor to display information about\n"
14572 "Neighbor to display information about\n"
14573 "Neighbor on BGP configured interface\n"
14574 "Display the routes selected by best path\n"
14575 "Display detailed version of routes\n"
14577 "Increase table width for longer prefixes\n")
14579 afi_t afi
= AFI_IP6
;
14580 safi_t safi
= SAFI_UNICAST
;
14581 char *rmap_name
= NULL
;
14582 char *peerstr
= NULL
;
14583 struct bgp
*bgp
= NULL
;
14585 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
14587 uint16_t show_flags
= 0;
14590 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14593 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14596 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14598 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14602 return CMD_WARNING
;
14604 argv_find(argv
, argc
, "neighbors", &idx
);
14605 peerstr
= argv
[++idx
]->arg
;
14607 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14609 return CMD_WARNING
;
14611 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, NULL
,
14615 DEFPY(show_ip_bgp_instance_neighbor_advertised_route
,
14616 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
14617 "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]",
14621 BGP_INSTANCE_HELP_STR
14623 BGP_SAFI_WITH_LABEL_HELP_STR
14624 "Display the entries for all address families\n"
14625 "Detailed information on TCP and BGP neighbor connections\n"
14626 "Neighbor to display information about\n"
14627 "Neighbor to display information about\n"
14628 "Neighbor on BGP configured interface\n"
14629 "Display the routes advertised to a BGP neighbor\n"
14630 "Display the received routes from neighbor\n"
14631 "Display the filtered routes received from neighbor\n"
14632 "Route-map to modify the attributes\n"
14633 "Name of the route map\n"
14636 "Display detailed version of routes\n"
14638 "Increase table width for longer prefixes\n")
14640 afi_t afi
= AFI_IP6
;
14641 safi_t safi
= SAFI_UNICAST
;
14642 char *peerstr
= NULL
;
14643 struct bgp
*bgp
= NULL
;
14645 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
14648 uint16_t show_flags
= 0;
14649 struct listnode
*node
;
14652 if (detail
|| prefix_str
)
14653 SET_FLAG(show_flags
, BGP_SHOW_OPT_ROUTES_DETAIL
);
14657 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14661 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
14662 if (argv_find(argv
, argc
, "ipv4", &idx
))
14663 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
14665 if (argv_find(argv
, argc
, "ipv6", &idx
))
14666 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
14670 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
14672 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14675 return CMD_WARNING
;
14677 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14678 argv_find(argv
, argc
, "neighbors", &idx
);
14679 peerstr
= argv
[++idx
]->arg
;
14681 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14683 return CMD_WARNING
;
14685 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
14686 type
= bgp_show_adj_route_advertised
;
14687 else if (argv_find(argv
, argc
, "received-routes", &idx
))
14688 type
= bgp_show_adj_route_received
;
14689 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
14690 type
= bgp_show_adj_route_filtered
;
14693 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, route_map
,
14694 prefix_str
? prefix
: NULL
, show_flags
);
14696 vty_out(vty
, "{\n");
14698 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
14699 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
14700 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
14702 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14703 FOREACH_SAFI (safi
) {
14704 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14711 vty_out(vty
, ",\n");
14712 vty_out(vty
, "\"%s\":",
14713 get_afi_safi_str(afi
, safi
,
14717 "\nFor address family: %s\n",
14718 get_afi_safi_str(afi
, safi
,
14721 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14722 route_map
, prefix
, show_flags
);
14726 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, abgp
)) {
14727 FOREACH_AFI_SAFI (afi
, safi
) {
14728 if (!bgp_afi_safi_peer_exists(abgp
, afi
, safi
))
14735 vty_out(vty
, ",\n");
14736 vty_out(vty
, "\"%s\":",
14737 get_afi_safi_str(afi
, safi
,
14741 "\nFor address family: %s\n",
14742 get_afi_safi_str(afi
, safi
,
14745 peer_adj_routes(vty
, peer
, afi
, safi
, type
,
14746 route_map
, prefix
, show_flags
);
14751 vty_out(vty
, "}\n");
14753 return CMD_SUCCESS
;
14756 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
14757 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
14758 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14762 BGP_INSTANCE_HELP_STR
14765 BGP_AF_MODIFIER_STR
14766 "Detailed information on TCP and BGP neighbor connections\n"
14767 "Neighbor to display information about\n"
14768 "Neighbor to display information about\n"
14769 "Neighbor on BGP configured interface\n"
14770 "Display information received from a BGP neighbor\n"
14771 "Display the prefixlist filter\n"
14774 afi_t afi
= AFI_IP6
;
14775 safi_t safi
= SAFI_UNICAST
;
14776 char *peerstr
= NULL
;
14781 struct bgp
*bgp
= NULL
;
14782 bool uj
= use_json(argc
, argv
);
14787 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14790 return CMD_WARNING
;
14792 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14793 argv_find(argv
, argc
, "neighbors", &idx
);
14794 peerstr
= argv
[++idx
]->arg
;
14796 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14798 return CMD_WARNING
;
14800 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
14801 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
14804 vty_out(vty
, "Address Family: %s\n",
14805 get_afi_safi_str(afi
, safi
, false));
14806 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
14809 vty_out(vty
, "{}\n");
14811 vty_out(vty
, "No functional output\n");
14814 return CMD_SUCCESS
;
14817 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
14818 afi_t afi
, safi_t safi
,
14819 enum bgp_show_type type
, bool use_json
)
14821 uint16_t show_flags
= 0;
14824 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14826 if (!peer
|| !peer
->afc
[afi
][safi
]) {
14828 json_object
*json_no
= NULL
;
14829 json_no
= json_object_new_object();
14830 json_object_string_add(
14831 json_no
, "warning",
14832 "No such neighbor or address family");
14833 vty_out(vty
, "%s\n",
14834 json_object_to_json_string(json_no
));
14835 json_object_free(json_no
);
14837 vty_out(vty
, "%% No such neighbor or address family\n");
14838 return CMD_WARNING
;
14841 /* labeled-unicast routes live in the unicast table */
14842 if (safi
== SAFI_LABELED_UNICAST
)
14843 safi
= SAFI_UNICAST
;
14845 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
,
14846 RPKI_NOT_BEING_USED
);
14849 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
14850 show_ip_bgp_flowspec_routes_detailed_cmd
,
14851 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
14855 BGP_INSTANCE_HELP_STR
14858 "Detailed information on flowspec entries\n"
14861 afi_t afi
= AFI_IP6
;
14862 safi_t safi
= SAFI_UNICAST
;
14863 struct bgp
*bgp
= NULL
;
14865 bool uj
= use_json(argc
, argv
);
14866 uint16_t show_flags
= BGP_SHOW_OPT_ROUTES_DETAIL
;
14870 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
14873 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14876 return CMD_WARNING
;
14878 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
14879 show_flags
, RPKI_NOT_BEING_USED
);
14882 DEFUN (show_ip_bgp_neighbor_routes
,
14883 show_ip_bgp_neighbor_routes_cmd
,
14884 "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]",
14888 BGP_INSTANCE_HELP_STR
14890 BGP_SAFI_WITH_LABEL_HELP_STR
14891 "Detailed information on TCP and BGP neighbor connections\n"
14892 "Neighbor to display information about\n"
14893 "Neighbor to display information about\n"
14894 "Neighbor on BGP configured interface\n"
14895 "Display flap statistics of the routes learned from neighbor\n"
14896 "Display the dampened routes received from neighbor\n"
14897 "Display routes learned from neighbor\n"
14900 char *peerstr
= NULL
;
14901 struct bgp
*bgp
= NULL
;
14902 afi_t afi
= AFI_IP6
;
14903 safi_t safi
= SAFI_UNICAST
;
14905 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
14907 bool uj
= use_json(argc
, argv
);
14912 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
14915 return CMD_WARNING
;
14917 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14918 argv_find(argv
, argc
, "neighbors", &idx
);
14919 peerstr
= argv
[++idx
]->arg
;
14921 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
14923 return CMD_WARNING
;
14925 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
14926 sh_type
= bgp_show_type_flap_neighbor
;
14927 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
14928 sh_type
= bgp_show_type_damp_neighbor
;
14929 else if (argv_find(argv
, argc
, "routes", &idx
))
14930 sh_type
= bgp_show_type_neighbor
;
14932 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
14935 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
14937 struct bgp_distance
{
14938 /* Distance value for the IP source prefix. */
14941 /* Name of the access-list to be matched. */
14945 DEFUN (show_bgp_afi_vpn_rd_route
,
14946 show_bgp_afi_vpn_rd_route_cmd
,
14947 "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]",
14951 BGP_AF_MODIFIER_STR
14952 "Display information for a route distinguisher\n"
14953 "Route Distinguisher\n"
14954 "All Route Distinguishers\n"
14955 "Network in the BGP routing table to display\n"
14956 "Network in the BGP routing table to display\n"
14960 struct prefix_rd prd
;
14961 afi_t afi
= AFI_MAX
;
14964 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
14965 vty_out(vty
, "%% Malformed Address Family\n");
14966 return CMD_WARNING
;
14969 if (!strcmp(argv
[5]->arg
, "all"))
14970 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
,
14971 SAFI_MPLS_VPN
, NULL
, 0, BGP_PATH_SHOW_ALL
,
14972 RPKI_NOT_BEING_USED
,
14973 use_json(argc
, argv
));
14975 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
14977 vty_out(vty
, "%% Malformed Route Distinguisher\n");
14978 return CMD_WARNING
;
14981 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
14982 0, BGP_PATH_SHOW_ALL
, RPKI_NOT_BEING_USED
,
14983 use_json(argc
, argv
));
14986 static struct bgp_distance
*bgp_distance_new(void)
14988 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
14991 static void bgp_distance_free(struct bgp_distance
*bdistance
)
14993 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
14996 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
14997 const char *ip_str
, const char *access_list_str
)
15004 struct bgp_dest
*dest
;
15005 struct bgp_distance
*bdistance
;
15007 afi
= bgp_node_afi(vty
);
15008 safi
= bgp_node_safi(vty
);
15010 ret
= str2prefix(ip_str
, &p
);
15012 vty_out(vty
, "Malformed prefix\n");
15013 return CMD_WARNING_CONFIG_FAILED
;
15016 distance
= atoi(distance_str
);
15018 /* Get BGP distance node. */
15019 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
15020 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15022 bgp_dest_unlock_node(dest
);
15024 bdistance
= bgp_distance_new();
15025 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
15028 /* Set distance value. */
15029 bdistance
->distance
= distance
;
15031 /* Reset access-list configuration. */
15032 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
15033 if (access_list_str
)
15034 bdistance
->access_list
=
15035 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
15037 return CMD_SUCCESS
;
15040 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
15041 const char *ip_str
, const char *access_list_str
)
15048 struct bgp_dest
*dest
;
15049 struct bgp_distance
*bdistance
;
15051 afi
= bgp_node_afi(vty
);
15052 safi
= bgp_node_safi(vty
);
15054 ret
= str2prefix(ip_str
, &p
);
15056 vty_out(vty
, "Malformed prefix\n");
15057 return CMD_WARNING_CONFIG_FAILED
;
15060 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
15062 vty_out(vty
, "Can't find specified prefix\n");
15063 return CMD_WARNING_CONFIG_FAILED
;
15066 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15067 distance
= atoi(distance_str
);
15069 if (bdistance
->distance
!= distance
) {
15070 vty_out(vty
, "Distance does not match configured\n");
15071 bgp_dest_unlock_node(dest
);
15072 return CMD_WARNING_CONFIG_FAILED
;
15075 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
15076 bgp_distance_free(bdistance
);
15078 bgp_dest_set_bgp_path_info(dest
, NULL
);
15079 bgp_dest_unlock_node(dest
);
15080 bgp_dest_unlock_node(dest
);
15082 return CMD_SUCCESS
;
15085 /* Apply BGP information to distance method. */
15086 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
15087 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
15089 struct bgp_dest
*dest
;
15090 struct prefix q
= {0};
15092 struct bgp_distance
*bdistance
;
15093 struct access_list
*alist
;
15094 struct bgp_static
*bgp_static
;
15095 struct bgp_path_info
*bpi_ultimate
;
15100 peer
= pinfo
->peer
;
15102 if (pinfo
->attr
->distance
)
15103 return pinfo
->attr
->distance
;
15105 /* get peer origin to calculate appropriate distance */
15106 if (pinfo
->sub_type
== BGP_ROUTE_IMPORTED
) {
15107 bpi_ultimate
= bgp_get_imported_bpi_ultimate(pinfo
);
15108 peer
= bpi_ultimate
->peer
;
15111 /* Check source address.
15112 * Note: for aggregate route, peer can have unspec af type.
15114 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
15115 && !sockunion2hostprefix(&peer
->su
, &q
))
15118 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
15120 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15121 bgp_dest_unlock_node(dest
);
15123 if (bdistance
->access_list
) {
15124 alist
= access_list_lookup(afi
, bdistance
->access_list
);
15126 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
15127 return bdistance
->distance
;
15129 return bdistance
->distance
;
15132 /* Backdoor check. */
15133 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
15135 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15136 bgp_dest_unlock_node(dest
);
15138 if (bgp_static
->backdoor
) {
15139 if (bgp
->distance_local
[afi
][safi
])
15140 return bgp
->distance_local
[afi
][safi
];
15142 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15146 if (peer
->sort
== BGP_PEER_EBGP
) {
15147 if (bgp
->distance_ebgp
[afi
][safi
])
15148 return bgp
->distance_ebgp
[afi
][safi
];
15149 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
15150 } else if (peer
->sort
== BGP_PEER_IBGP
) {
15151 if (bgp
->distance_ibgp
[afi
][safi
])
15152 return bgp
->distance_ibgp
[afi
][safi
];
15153 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15155 if (bgp
->distance_local
[afi
][safi
])
15156 return bgp
->distance_local
[afi
][safi
];
15157 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
15161 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15162 * we should tell ZEBRA update the routes for a specific
15163 * AFI/SAFI to reflect changes in RIB.
15165 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
15167 safi_t update_safi
)
15172 FOREACH_AFI_SAFI (afi
, safi
) {
15173 if (!bgp_fibupd_safi(safi
))
15176 if (afi
!= update_afi
&& safi
!= update_safi
)
15179 if (BGP_DEBUG(zebra
, ZEBRA
))
15181 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15182 __func__
, afi
, safi
);
15183 bgp_zebra_announce_table(bgp
, afi
, safi
);
15187 DEFUN (bgp_distance
,
15189 "distance bgp (1-255) (1-255) (1-255)",
15190 "Define an administrative distance\n"
15192 "Distance for routes external to the AS\n"
15193 "Distance for routes internal to the AS\n"
15194 "Distance for local routes\n")
15196 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15197 int idx_number
= 2;
15198 int idx_number_2
= 3;
15199 int idx_number_3
= 4;
15200 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
15201 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
15202 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
15206 afi
= bgp_node_afi(vty
);
15207 safi
= bgp_node_safi(vty
);
15209 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
15210 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
15211 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
15212 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_announce_routes_distance_update(bgp
, afi
, safi
);
15217 return CMD_SUCCESS
;
15220 DEFUN (no_bgp_distance
,
15221 no_bgp_distance_cmd
,
15222 "no distance bgp [(1-255) (1-255) (1-255)]",
15224 "Define an administrative distance\n"
15226 "Distance for routes external to the AS\n"
15227 "Distance for routes internal to the AS\n"
15228 "Distance for local routes\n")
15230 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15234 afi
= bgp_node_afi(vty
);
15235 safi
= bgp_node_safi(vty
);
15237 if (bgp
->distance_ebgp
[afi
][safi
] != 0
15238 || bgp
->distance_ibgp
[afi
][safi
] != 0
15239 || bgp
->distance_local
[afi
][safi
] != 0) {
15240 bgp
->distance_ebgp
[afi
][safi
] = 0;
15241 bgp
->distance_ibgp
[afi
][safi
] = 0;
15242 bgp
->distance_local
[afi
][safi
] = 0;
15243 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
15245 return CMD_SUCCESS
;
15249 DEFUN (bgp_distance_source
,
15250 bgp_distance_source_cmd
,
15251 "distance (1-255) A.B.C.D/M",
15252 "Define an administrative distance\n"
15253 "Administrative distance\n"
15254 "IP source prefix\n")
15256 int idx_number
= 1;
15257 int idx_ipv4_prefixlen
= 2;
15258 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15259 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15260 return CMD_SUCCESS
;
15263 DEFUN (no_bgp_distance_source
,
15264 no_bgp_distance_source_cmd
,
15265 "no distance (1-255) A.B.C.D/M",
15267 "Define an administrative distance\n"
15268 "Administrative distance\n"
15269 "IP source prefix\n")
15271 int idx_number
= 2;
15272 int idx_ipv4_prefixlen
= 3;
15273 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15274 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
15275 return CMD_SUCCESS
;
15278 DEFUN (bgp_distance_source_access_list
,
15279 bgp_distance_source_access_list_cmd
,
15280 "distance (1-255) A.B.C.D/M WORD",
15281 "Define an administrative distance\n"
15282 "Administrative distance\n"
15283 "IP source prefix\n"
15284 "Access list name\n")
15286 int idx_number
= 1;
15287 int idx_ipv4_prefixlen
= 2;
15289 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
15290 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15291 return CMD_SUCCESS
;
15294 DEFUN (no_bgp_distance_source_access_list
,
15295 no_bgp_distance_source_access_list_cmd
,
15296 "no distance (1-255) A.B.C.D/M WORD",
15298 "Define an administrative distance\n"
15299 "Administrative distance\n"
15300 "IP source prefix\n"
15301 "Access list name\n")
15303 int idx_number
= 2;
15304 int idx_ipv4_prefixlen
= 3;
15306 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
15307 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
15308 return CMD_SUCCESS
;
15311 DEFUN (ipv6_bgp_distance_source
,
15312 ipv6_bgp_distance_source_cmd
,
15313 "distance (1-255) X:X::X:X/M",
15314 "Define an administrative distance\n"
15315 "Administrative distance\n"
15316 "IP source prefix\n")
15318 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
15319 return CMD_SUCCESS
;
15322 DEFUN (no_ipv6_bgp_distance_source
,
15323 no_ipv6_bgp_distance_source_cmd
,
15324 "no distance (1-255) X:X::X:X/M",
15326 "Define an administrative distance\n"
15327 "Administrative distance\n"
15328 "IP source prefix\n")
15330 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
15331 return CMD_SUCCESS
;
15334 DEFUN (ipv6_bgp_distance_source_access_list
,
15335 ipv6_bgp_distance_source_access_list_cmd
,
15336 "distance (1-255) X:X::X:X/M WORD",
15337 "Define an administrative distance\n"
15338 "Administrative distance\n"
15339 "IP source prefix\n"
15340 "Access list name\n")
15342 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
15343 return CMD_SUCCESS
;
15346 DEFUN (no_ipv6_bgp_distance_source_access_list
,
15347 no_ipv6_bgp_distance_source_access_list_cmd
,
15348 "no distance (1-255) X:X::X:X/M WORD",
15350 "Define an administrative distance\n"
15351 "Administrative distance\n"
15352 "IP source prefix\n"
15353 "Access list name\n")
15355 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
15356 return CMD_SUCCESS
;
15359 DEFUN (bgp_damp_set
,
15361 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15362 "BGP Specific commands\n"
15363 "Enable route-flap dampening\n"
15364 "Half-life time for the penalty\n"
15365 "Value to start reusing a route\n"
15366 "Value to start suppressing a route\n"
15367 "Maximum duration to suppress a stable route\n")
15369 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15370 int idx_half_life
= 2;
15372 int idx_suppress
= 4;
15373 int idx_max_suppress
= 5;
15374 int half
= DEFAULT_HALF_LIFE
* 60;
15375 int reuse
= DEFAULT_REUSE
;
15376 int suppress
= DEFAULT_SUPPRESS
;
15377 int max
= 4 * half
;
15380 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15381 reuse
= atoi(argv
[idx_reuse
]->arg
);
15382 suppress
= atoi(argv
[idx_suppress
]->arg
);
15383 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
15384 } else if (argc
== 3) {
15385 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
15390 * These can't be 0 but our SA doesn't understand the
15391 * way our cli is constructed
15395 if (suppress
< reuse
) {
15397 "Suppress value cannot be less than reuse value \n");
15401 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
15402 reuse
, suppress
, max
);
15405 DEFUN (bgp_damp_unset
,
15406 bgp_damp_unset_cmd
,
15407 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15409 "BGP Specific commands\n"
15410 "Enable route-flap dampening\n"
15411 "Half-life time for the penalty\n"
15412 "Value to start reusing a route\n"
15413 "Value to start suppressing a route\n"
15414 "Maximum duration to suppress a stable route\n")
15416 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
15417 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
15420 /* Display specified route of BGP table. */
15421 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
15422 const char *ip_str
, afi_t afi
, safi_t safi
,
15423 struct prefix_rd
*prd
, int prefix_check
)
15426 struct prefix match
;
15427 struct bgp_dest
*dest
;
15428 struct bgp_dest
*rm
;
15429 struct bgp_path_info
*pi
;
15430 struct bgp_path_info
*pi_temp
;
15432 struct bgp_table
*table
;
15434 /* BGP structure lookup. */
15436 bgp
= bgp_lookup_by_name(view_name
);
15438 vty_out(vty
, "%% Can't find BGP instance %s\n",
15440 return CMD_WARNING
;
15443 bgp
= bgp_get_default();
15445 vty_out(vty
, "%% No BGP process is configured\n");
15446 return CMD_WARNING
;
15450 /* Check IP address argument. */
15451 ret
= str2prefix(ip_str
, &match
);
15453 vty_out(vty
, "%% address is malformed\n");
15454 return CMD_WARNING
;
15457 match
.family
= afi2family(afi
);
15459 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
15460 || (safi
== SAFI_EVPN
)) {
15461 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
15462 dest
= bgp_route_next(dest
)) {
15463 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15465 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
15467 table
= bgp_dest_get_bgp_table_info(dest
);
15470 rm
= bgp_node_match(table
, &match
);
15474 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
15477 || rm_p
->prefixlen
== match
.prefixlen
) {
15478 pi
= bgp_dest_get_bgp_path_info(rm
);
15480 if (pi
->extra
&& pi
->extra
->damp_info
) {
15481 pi_temp
= pi
->next
;
15482 bgp_damp_info_free(
15483 pi
->extra
->damp_info
,
15491 bgp_dest_unlock_node(rm
);
15494 dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
);
15495 if (dest
!= NULL
) {
15496 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
15499 || dest_p
->prefixlen
== match
.prefixlen
) {
15500 pi
= bgp_dest_get_bgp_path_info(dest
);
15502 if (pi
->extra
&& pi
->extra
->damp_info
) {
15503 pi_temp
= pi
->next
;
15504 bgp_damp_info_free(
15505 pi
->extra
->damp_info
,
15513 bgp_dest_unlock_node(dest
);
15517 return CMD_SUCCESS
;
15520 DEFUN (clear_ip_bgp_dampening
,
15521 clear_ip_bgp_dampening_cmd
,
15522 "clear ip bgp dampening",
15526 "Clear route flap dampening information\n")
15528 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
15529 return CMD_SUCCESS
;
15532 DEFUN (clear_ip_bgp_dampening_prefix
,
15533 clear_ip_bgp_dampening_prefix_cmd
,
15534 "clear ip bgp dampening A.B.C.D/M",
15538 "Clear route flap dampening information\n"
15541 int idx_ipv4_prefixlen
= 4;
15542 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
15543 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
15546 DEFUN (clear_ip_bgp_dampening_address
,
15547 clear_ip_bgp_dampening_address_cmd
,
15548 "clear ip bgp dampening A.B.C.D",
15552 "Clear route flap dampening information\n"
15553 "Network to clear damping information\n")
15556 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
15557 SAFI_UNICAST
, NULL
, 0);
15560 DEFUN (clear_ip_bgp_dampening_address_mask
,
15561 clear_ip_bgp_dampening_address_mask_cmd
,
15562 "clear ip bgp dampening A.B.C.D A.B.C.D",
15566 "Clear route flap dampening information\n"
15567 "Network to clear damping information\n"
15571 int idx_ipv4_2
= 5;
15573 char prefix_str
[BUFSIZ
];
15575 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
15576 prefix_str
, sizeof(prefix_str
));
15578 vty_out(vty
, "%% Inconsistent address and mask\n");
15579 return CMD_WARNING
;
15582 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
15586 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
15588 struct vty
*vty
= arg
;
15589 struct peer
*peer
= bucket
->data
;
15591 vty_out(vty
, "\tPeer: %s %pSU\n", peer
->host
, &peer
->su
);
15594 DEFUN (show_bgp_listeners
,
15595 show_bgp_listeners_cmd
,
15596 "show bgp listeners",
15599 "Display Listen Sockets and who created them\n")
15601 bgp_dump_listener_info(vty
);
15603 return CMD_SUCCESS
;
15606 DEFUN (show_bgp_peerhash
,
15607 show_bgp_peerhash_cmd
,
15608 "show bgp peerhash",
15611 "Display information about the BGP peerhash\n")
15613 struct list
*instances
= bm
->bgp
;
15614 struct listnode
*node
;
15617 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
15618 vty_out(vty
, "BGP: %s\n", bgp
->name
);
15619 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
15623 return CMD_SUCCESS
;
15626 /* also used for encap safi */
15627 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
15628 afi_t afi
, safi_t safi
)
15630 struct bgp_dest
*pdest
;
15631 struct bgp_dest
*dest
;
15632 struct bgp_table
*table
;
15633 const struct prefix
*p
;
15634 struct bgp_static
*bgp_static
;
15635 mpls_label_t label
;
15637 /* Network configuration. */
15638 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15639 pdest
= bgp_route_next(pdest
)) {
15640 table
= bgp_dest_get_bgp_table_info(pdest
);
15644 for (dest
= bgp_table_top(table
); dest
;
15645 dest
= bgp_route_next(dest
)) {
15646 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15647 if (bgp_static
== NULL
)
15650 p
= bgp_dest_get_prefix(dest
);
15652 /* "network" configuration display. */
15653 label
= decode_label(&bgp_static
->label
);
15655 vty_out(vty
, " network %pFX rd %s", p
,
15656 bgp_static
->prd_pretty
);
15657 if (safi
== SAFI_MPLS_VPN
)
15658 vty_out(vty
, " label %u", label
);
15660 if (bgp_static
->rmap
.name
)
15661 vty_out(vty
, " route-map %s",
15662 bgp_static
->rmap
.name
);
15664 if (bgp_static
->backdoor
)
15665 vty_out(vty
, " backdoor");
15667 vty_out(vty
, "\n");
15672 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
15673 afi_t afi
, safi_t safi
)
15675 struct bgp_dest
*pdest
;
15676 struct bgp_dest
*dest
;
15677 struct bgp_table
*table
;
15678 const struct prefix
*p
;
15679 struct bgp_static
*bgp_static
;
15680 char buf
[PREFIX_STRLEN
* 2];
15681 char buf2
[SU_ADDRSTRLEN
];
15682 char esi_buf
[ESI_STR_LEN
];
15684 /* Network configuration. */
15685 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
15686 pdest
= bgp_route_next(pdest
)) {
15687 table
= bgp_dest_get_bgp_table_info(pdest
);
15691 for (dest
= bgp_table_top(table
); dest
;
15692 dest
= bgp_route_next(dest
)) {
15693 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15694 if (bgp_static
== NULL
)
15697 char *macrouter
= NULL
;
15699 if (bgp_static
->router_mac
)
15700 macrouter
= prefix_mac2str(
15701 bgp_static
->router_mac
, NULL
, 0);
15702 if (bgp_static
->eth_s_id
)
15703 esi_to_str(bgp_static
->eth_s_id
,
15704 esi_buf
, sizeof(esi_buf
));
15705 p
= bgp_dest_get_prefix(dest
);
15707 /* "network" configuration display. */
15708 if (p
->u
.prefix_evpn
.route_type
== 5) {
15709 char local_buf
[PREFIX_STRLEN
];
15711 uint8_t family
= is_evpn_prefix_ipaddr_v4((
15712 struct prefix_evpn
*)p
)
15716 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
15718 local_buf
, sizeof(local_buf
));
15719 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
15720 p
->u
.prefix_evpn
.prefix_addr
15721 .ip_prefix_length
);
15723 prefix2str(p
, buf
, sizeof(buf
));
15726 if (bgp_static
->gatewayIp
.family
== AF_INET
15727 || bgp_static
->gatewayIp
.family
== AF_INET6
)
15728 inet_ntop(bgp_static
->gatewayIp
.family
,
15729 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
15732 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15733 buf
, bgp_static
->prd_pretty
,
15734 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
15735 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
15738 XFREE(MTYPE_TMP
, macrouter
);
15743 /* Configuration of static route announcement and aggregate
15745 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15748 struct bgp_dest
*dest
;
15749 const struct prefix
*p
;
15750 struct bgp_static
*bgp_static
;
15751 struct bgp_aggregate
*bgp_aggregate
;
15753 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
15754 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
15758 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
15759 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
15763 /* Network configuration. */
15764 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
15765 dest
= bgp_route_next(dest
)) {
15766 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
15767 if (bgp_static
== NULL
)
15770 p
= bgp_dest_get_prefix(dest
);
15772 vty_out(vty
, " network %pFX", p
);
15774 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
15775 vty_out(vty
, " label-index %u",
15776 bgp_static
->label_index
);
15778 if (bgp_static
->rmap
.name
)
15779 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
15781 if (bgp_static
->backdoor
)
15782 vty_out(vty
, " backdoor");
15784 vty_out(vty
, "\n");
15787 /* Aggregate-address configuration. */
15788 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
15789 dest
= bgp_route_next(dest
)) {
15790 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
15791 if (bgp_aggregate
== NULL
)
15794 p
= bgp_dest_get_prefix(dest
);
15796 vty_out(vty
, " aggregate-address %pFX", p
);
15798 if (bgp_aggregate
->as_set
)
15799 vty_out(vty
, " as-set");
15801 if (bgp_aggregate
->summary_only
)
15802 vty_out(vty
, " summary-only");
15804 if (bgp_aggregate
->rmap
.name
)
15805 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
15807 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
15808 vty_out(vty
, " origin %s",
15809 bgp_origin2str(bgp_aggregate
->origin
));
15811 if (bgp_aggregate
->match_med
)
15812 vty_out(vty
, " matching-MED-only");
15814 if (bgp_aggregate
->suppress_map_name
)
15815 vty_out(vty
, " suppress-map %s",
15816 bgp_aggregate
->suppress_map_name
);
15818 vty_out(vty
, "\n");
15822 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
15825 struct bgp_dest
*dest
;
15826 struct bgp_distance
*bdistance
;
15828 /* Distance configuration. */
15829 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
15830 && bgp
->distance_local
[afi
][safi
]
15831 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
15832 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
15833 || bgp
->distance_local
[afi
][safi
]
15834 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
15835 vty_out(vty
, " distance bgp %d %d %d\n",
15836 bgp
->distance_ebgp
[afi
][safi
],
15837 bgp
->distance_ibgp
[afi
][safi
],
15838 bgp
->distance_local
[afi
][safi
]);
15841 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
15842 dest
= bgp_route_next(dest
)) {
15843 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
15844 if (bdistance
!= NULL
)
15845 vty_out(vty
, " distance %d %pBD %s\n",
15846 bdistance
->distance
, dest
,
15847 bdistance
->access_list
? bdistance
->access_list
15852 /* Allocate routing table structure and install commands. */
15853 void bgp_route_init(void)
15858 /* Init BGP distance table. */
15859 FOREACH_AFI_SAFI (afi
, safi
)
15860 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
15862 /* IPv4 BGP commands. */
15863 install_element(BGP_NODE
, &bgp_table_map_cmd
);
15864 install_element(BGP_NODE
, &bgp_network_cmd
);
15865 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
15867 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
15869 /* IPv4 unicast configuration. */
15870 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
15871 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
15872 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
15874 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
15876 /* IPv4 multicast configuration. */
15877 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
15878 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
15879 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
15880 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
15882 /* IPv4 labeled-unicast configuration. */
15883 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
15884 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
15886 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
15887 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
15888 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
15889 install_element(VIEW_NODE
, &show_ip_bgp_dampening_params_cmd
);
15890 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
15891 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
15892 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
15893 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
15895 install_element(VIEW_NODE
,
15896 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
15897 install_element(VIEW_NODE
,
15898 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
15899 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
15900 install_element(VIEW_NODE
,
15901 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
15902 #ifdef KEEP_OLD_VPN_COMMANDS
15903 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
15904 #endif /* KEEP_OLD_VPN_COMMANDS */
15905 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
15906 install_element(VIEW_NODE
,
15907 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
15909 /* BGP dampening clear commands */
15910 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
15911 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
15913 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
15914 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
15917 install_element(ENABLE_NODE
,
15918 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
15919 #ifdef KEEP_OLD_VPN_COMMANDS
15920 install_element(ENABLE_NODE
,
15921 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
15922 #endif /* KEEP_OLD_VPN_COMMANDS */
15924 /* New config IPv6 BGP commands. */
15925 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
15926 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
15927 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
15929 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
15931 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
15933 /* IPv6 labeled unicast address family. */
15934 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
15935 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
15937 install_element(BGP_NODE
, &bgp_distance_cmd
);
15938 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
15939 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
15940 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
15941 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
15942 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
15943 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
15944 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
15945 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
15946 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
15947 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
15948 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
15949 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
15950 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
15951 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
15952 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
15953 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
15954 install_element(BGP_IPV4M_NODE
,
15955 &no_bgp_distance_source_access_list_cmd
);
15956 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
15957 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
15958 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
15959 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15960 install_element(BGP_IPV6_NODE
,
15961 &ipv6_bgp_distance_source_access_list_cmd
);
15962 install_element(BGP_IPV6_NODE
,
15963 &no_ipv6_bgp_distance_source_access_list_cmd
);
15964 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
15965 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
15966 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
15967 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
15968 install_element(BGP_IPV6M_NODE
,
15969 &ipv6_bgp_distance_source_access_list_cmd
);
15970 install_element(BGP_IPV6M_NODE
,
15971 &no_ipv6_bgp_distance_source_access_list_cmd
);
15973 /* BGP dampening */
15974 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
15975 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
15976 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
15977 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
15978 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
15979 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
15980 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
15981 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
15982 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
15983 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
15984 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
15985 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
15986 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
15987 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
15989 /* Large Communities */
15990 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
15991 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
15993 /* show bgp ipv4 flowspec detailed */
15994 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
15996 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
15997 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
16000 void bgp_route_finish(void)
16005 FOREACH_AFI_SAFI (afi
, safi
) {
16006 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
16007 bgp_distance_table
[afi
][safi
] = NULL
;